在 C# 中捕获应用程序窗口的最佳方法是什么?
我开发了一个简单的 Windows 窗体应用程序来捕获视频聊天应用程序的窗口(入站,又名远程,出站,又名本地)。 我为此使用非托管 Windows API 代码。这是捕获代码:
// Set Local Window
localHandle = FindWindow(null, "local");
// Backup parent window for local
prevLocalHandle = GetParent(localHandle);
SetParent(localHandle, this.pBoxLocal.Handle);
SetWindowLong(localHandle, GWL_STYLE, WS_VISIBLE + (WS_MAXIMIZE | WS_BORDER | WS_DISABLED));
MoveWindow(localHandle, 0, -TOP_BAR_HEIGHT, this.pBoxLocal.Width, this.pBoxLocal.Height + LOWER_BAR_HEIGHT, true);
// Set Remote Window
remoteHandle = FindWindow(null, "remote");
// Backup parent window for remote
prevRemoteHandle = GetParent(remoteHandle);
SetParent(remoteHandle, this.pBoxRemote.Handle);
SetWindowLong(remoteHandle, GWL_STYLE, WS_VISIBLE + (WS_MAXIMIZE | WS_BORDER | WS_DISABLED));
MoveWindow(remoteHandle, 0, -TOP_BAR_HEIGHT, this.pBoxRemote.Width, this.pBoxRemote.Height + LOWER_BAR_HEIGHT, true);
这是返回代码:
// Return Windows
SetParent(localHandle, prevLocalHandle);
SetWindowLong(localHandle, GWL_STYLE, (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
MoveWindow(localHandle, 0, 0, NORMAL_WIDTH, NORMAL_HEIGHT, true);
SetParent(remoteHandle, prevRemoteHandle);
SetWindowLong(remoteHandle, GWL_STYLE, (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
MoveWindow(remoteHandle, 0, 0, NORMAL_WIDTH, NORMAL_HEIGHT, true);
目标是从这里开始:
对此:
然后再回来! :)
目前我的处理方式存在两个问题:
首先,当我将窗口返回到视频聊天应用程序时,屏幕的左上角有时会留下一个黑色矩形。当我刷新该区域时,它就会消失。
第二也是最重要的一点是,有时当我捕获应用程序的窗口时,我也会捕获它的工具栏(尽管我提供的测量值只是关于窗口视频区域的测量值)。
有更好的方法吗?即使它只是更好的功能!请记住:我想获取视频聊天应用程序的窗口并随后返回它们。
预先感谢您的任何提示!
I've developed a simple windows forms application to capture the windows of a video chat application (inbound, aka Remote, and outbound, aka Local).
I use unmanaged Windows API code for this. Here is the Capture code:
// Set Local Window
localHandle = FindWindow(null, "local");
// Backup parent window for local
prevLocalHandle = GetParent(localHandle);
SetParent(localHandle, this.pBoxLocal.Handle);
SetWindowLong(localHandle, GWL_STYLE, WS_VISIBLE + (WS_MAXIMIZE | WS_BORDER | WS_DISABLED));
MoveWindow(localHandle, 0, -TOP_BAR_HEIGHT, this.pBoxLocal.Width, this.pBoxLocal.Height + LOWER_BAR_HEIGHT, true);
// Set Remote Window
remoteHandle = FindWindow(null, "remote");
// Backup parent window for remote
prevRemoteHandle = GetParent(remoteHandle);
SetParent(remoteHandle, this.pBoxRemote.Handle);
SetWindowLong(remoteHandle, GWL_STYLE, WS_VISIBLE + (WS_MAXIMIZE | WS_BORDER | WS_DISABLED));
MoveWindow(remoteHandle, 0, -TOP_BAR_HEIGHT, this.pBoxRemote.Width, this.pBoxRemote.Height + LOWER_BAR_HEIGHT, true);
Here is the Return code:
// Return Windows
SetParent(localHandle, prevLocalHandle);
SetWindowLong(localHandle, GWL_STYLE, (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
MoveWindow(localHandle, 0, 0, NORMAL_WIDTH, NORMAL_HEIGHT, true);
SetParent(remoteHandle, prevRemoteHandle);
SetWindowLong(remoteHandle, GWL_STYLE, (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
MoveWindow(remoteHandle, 0, 0, NORMAL_WIDTH, NORMAL_HEIGHT, true);
The goal is to go from this:
To this:
And then back again! :)
There are currently two issues with my way of doing things:
first of all, when I return the windows to the video chat application, ocasionally a black rectangle is left on my top-left corner of the screen. It disappears when I refresh the area.
second and most important of all, there are times that when I capture the window of the application, I also capture its toolbars (although the measurements I supply are just the ones regarding the video area of the window).
Is there a better way of doing this? Even if its just better functions! Remember: I want to obtain the windows of the video chat application and return them afterwards.
Thanks in advance for any tips!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,你所说的第一个问题很容易解决。返回窗口时,只需调用 Refresh() 即可。但是,如果您的意思是主桌面上有一个黑色矩形而不是窗口,那么您可以使用 http://msdn.microsoft.com/en-us/library/bb776346(VS.85).aspx 这将允许您强制刷新整个桌面。
至于您遇到的第二个问题,因为您已经弄乱了 Window Long 方法,为什么不直接删除所有边框,我相信可能发生的情况是边框可能有一个“ThickFrame”,您在返回方法中指定但不捕获方法,这可能就是您获得工具栏和边框的原因。您可以通过调用 GetWindowLong 存储该值并查看其中的内容来检查这一点,这样您就可以准确地知道要删除的内容。
虽然我不确定这个应用程序的用途是什么。我相信你正在做的事情可能是唯一的方法,因为你正在操纵外部屏幕。
Ok well the first issue you stated is an easy one to fix. You can just call Refresh() when you return the windows. However if you meant there is a black rectangle on your main desktop not a window then you can use http://msdn.microsoft.com/en-us/library/bb776346(VS.85).aspx which will allow you to force the whole desktop to refresh.
As for the second issue you are having since you are already messing with the Window Long method why not just remove all borders, I believe what might be happening is the border may have a "ThickFrame" which you specify in your return methods but not capture methods so that may be why you are getting toolbars and borders. You can check this by calling GetWindowLong storing that value and seeing what is there, this way you can know exactly what to remove.
Although I am not sure as to what the use of this application is. I believe what you are doing may be the only way to do it, since you are manipulating external screens.