如何在没有 NativeMethods 的情况下找到给定 hWnd 的窗口的位置/位置?
我目前正在使用 WatiN,发现它是一个很棒的网络浏览自动化工具。然而,截至上一个版本,它的屏幕捕获功能似乎缺乏。我提出了一个可行的解决方案,用于从屏幕捕获屏幕截图(独立生成类似于 this StackOverflow 问题)以及一些 Charles Petzold 的代码。不幸的是,缺少一个组件:实际窗口在哪里?
WatiN 方便地向您提供浏览器的 hWnd
,因此我们可以(通过这个简化的示例)设置从屏幕复制图像,如下所示:
// browser is either an WatiN.Core.IE or a WatiN.Core.FireFox...
IntPtr hWnd = browser.hWnd;
string filename = "my_file.bmp";
using (Graphics browser = Graphics.FromHwnd(browser.hWnd) )
using (Bitmap screenshot = new Bitmap((int)browser.VisibleClipBounds.Width,
(int)browser.VisibleClipBounds.Height,
browser))
using (Graphics screenGraphics = Graphics.FromImage(screenshot))
{
int hWndX = 0; // Upper left of graphics? Nope,
int hWndY = 0; // this is upper left of the entire desktop!
screenGraphics.CopyFromScreen(hWndX, hWndY, 0, 0,
new Size((int)browser.VisibileClipBounds.Width,
(int)browser.VisibileClipBounds.Height));
screenshot.Save(filename, ImageFormat.Bmp);
}
成功!我们得到了屏幕截图,但存在一个问题:hWndX
和 hWndY
始终指向屏幕的左上角,而不是我们要从中复制的窗口的位置。
然后我研究了 Control.FromHandle
,但这似乎只适用于您创建的表单;如果将 hWnd
传递给该方法,该方法将返回一个空指针。
然后,进一步的阅读导致我改变了我的搜索标准......当大多数人真正想要窗口的“位置”时,我一直在搜索“窗口的位置”。这导致另一个SO问题 谈到了这一点,但他们的答案是使用本机方法。
那么,是否有一种原生 C# 方法可以仅在给定 hWnd 的情况下查找窗口的位置(最好仅使用 .NET 2.0 时代的库)?
I'm currently working with WatiN, and finding it to be a great web browsing automation tool. However, as of the last release, it's screen capturing functionality seems to be lacking. I've come up with a workable solution for capturing screenshots from the screen (independently generating code similar to this StackOverflow question) in addition to some code by Charles Petzold. Unfortunately, there is a missing component: Where is the actual window?
WatiN conveniently provides the browser's hWnd
to you, so we can (with this simplified example) get set to copy an image from the screen, like so:
// browser is either an WatiN.Core.IE or a WatiN.Core.FireFox...
IntPtr hWnd = browser.hWnd;
string filename = "my_file.bmp";
using (Graphics browser = Graphics.FromHwnd(browser.hWnd) )
using (Bitmap screenshot = new Bitmap((int)browser.VisibleClipBounds.Width,
(int)browser.VisibleClipBounds.Height,
browser))
using (Graphics screenGraphics = Graphics.FromImage(screenshot))
{
int hWndX = 0; // Upper left of graphics? Nope,
int hWndY = 0; // this is upper left of the entire desktop!
screenGraphics.CopyFromScreen(hWndX, hWndY, 0, 0,
new Size((int)browser.VisibileClipBounds.Width,
(int)browser.VisibileClipBounds.Height));
screenshot.Save(filename, ImageFormat.Bmp);
}
Success! We get screenshots, but there's that problem: hWndX
and hWndY
always point to the upper left most corner of the screen, not the location of the window we want to copy from.
I then looked into Control.FromHandle
, however this seems to only work with forms you created; this method returns a null pointer if you pass the hWnd
into it.
Then, further reading lead me to switch my search criteria...I had been searching for 'location of window' when most people really want the 'position' of the window. This lead to another SO question that talked about this, but their answer was to use native methods.
So, Is there a native C# way of finding the position of a window, only given the hWnd (preferably with only .NET 2.0 era libraries)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我刚刚在一个项目中经历过这个,但无法找到任何托管 C# 方式。
要添加到 Reed 的答案,P/Invoke 代码为:
将其调用为:
I just went through this on a project and was unable to find any managed C# way.
To add to Reed's answer the P/Invoke code is:
Call it as:
否 - 如果您没有创建表单,则必须 P/Invoke GetWindowRect< /a>.我不相信有一个可管理的等价物。
No - if you didn't create the form, you have to P/Invoke GetWindowRect. I don't believe there is a managed equivalent.
答案正如其他人所说,可能是“不,如果没有本机方法,您无法从 hwnd 中截取随机窗口的屏幕截图。”。在展示之前,有几点需要注意:
警告:
对于任何想要使用此代码的人,请注意,VisibleClipBounds 给出的大小仅在窗口内,并且< em>不包括边框或标题栏。这是可绘制区域。如果你有这个,你也许可以在没有 p/invoke 的情况下做到这一点。
(如果您可以计算浏览器窗口的边框,则可以使用 VisibleClipBounds。如果需要,您可以使用
SystemInformation
对象来获取重要信息,例如Border3DSize
,或者您可以尝试通过创建虚拟表单并导出边框和标题栏高度,但这一切听起来就像是虫子的黑魔法。)这相当于窗口的 Ctrl+Printscreen。这也无法实现 WatiN 屏幕截图功能的功能,例如滚动浏览器并拍摄整个页面的图像。这适合我的项目,但可能不适合你的项目。
增强功能:
如果您使用 .NET 3 和高地,则可以将其更改为扩展方法,并且可以非常轻松地添加图像类型的选项(我默认为
本例中为 ImageFormat.Bmp
)。代码:
The answer is as others have stated, probably "No, you cannot take a screenshot of a random window from an hwnd without native methods.". Couple of caveats before I show it:
Forewarning:
For anyone who wants to use this code, note that the size given from the VisibleClipBounds is only inside the window, and does not include the border or title bar. It's the drawable area. If you had that, you might be able to do this without p/invoke.
(If you could calculate the border of the browser window, you could use the VisibleClipBounds. If you wanted, you could use the
SystemInformation
object to get important info likeBorder3DSize
, or you could try to calculate it by creating a dummy form and deriving the border and title bar height from that, but that all sounds like the black magic that bugs are made of.)This is equivalent to Ctrl+Printscreen of the window. This also does not do the niceties that the WatiN screenshot capability does, such as scroll the browser and take an image of the whole page. This is suitable for my project, but may not be for yours.
Enhancements:
This could be changed to be an extension method if you're in .NET 3 and up-land, and an option for the image type could be added pretty easily (I default to
ImageFormat.Bmp
for this example).Code: