[译]屏幕截图,带有源代码的窗口大小调整实用程序
By robot-v1.0
本文链接 https://www.kyfws.com/applications/screen-capture-window-resizing-utility-with-source-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 9 分钟阅读 - 4100 个词 阅读量 0[译]屏幕截图,带有源代码的窗口大小调整实用程序
原文地址:https://www.codeproject.com/Articles/5686/Screen-capture-window-resizing-utility-with-source
原文作者:peterboulton
译文由本站 robot-v1.0 翻译
前言
This utility uses Lim Bio Liong’s excellent Spy++ style Window Finder code to build a screen capture utility (featuring text capture as well as bitmaps) and window resizer/mover. It also demonstrates stay on top and expanding/contracting (i.e. more detail / less detail) dialog boxes.
该实用程序使用Lim Bio Liong出色的Spy ++风格的"窗口查找器"代码来构建屏幕捕获实用程序(具有文本捕获和位图功能)和窗口缩放器/移动器.它还演示了停留在顶部和展开/收缩(即,更多细节/更少细节)对话框.
- 下载源文件-22.1 Kb(Download source files - 22.1 Kb)
- 下载可执行文件(需要(Download executable (needs)mfc71.dll(mfc71.dll)和(and)msvcr71.dll(msvcr71.dll))-11.9 Kb() - 11.9 Kb)
新增-25(New - 25)日(th)2005年6月(June 2005)
- 添加了"居中"按钮,可将找到的窗口居中放置在桌面上. (用于录制应用程序演示等.)(Added a ‘Center’ button, which centers the found window on the desktop. (Useful for recording application demos etc..))
- 现在,它会记住其在桌面上的最后位置,并在下次重新开始.(Now remembers its last position on the desktop and starts there next time.)
- 先前的变更(Previous changes)
介绍(Introduction)
Lim Bio Liong的出色CodeProject文章((Lim Bio Liong’s excellent CodeProject article () MS Spy ++样式的窗口查找器(MS Spy++ style Window Finder) )进行了与为此工具选择要使用的窗口有关的所有艰苦工作.我对此不承担任何责任.() does all the hard work relating to picking a window to work with for this utility. I claim no credit whatever for this.)
但是,Lim Bio Liong的示例项目从SDI应用程序启动了"窗口查找器"对话框,主要是为了帮助演示窗口查找器代码而提供的.(However, Lim Bio Liong’s sample project launches the window finder dialog from an SDI application and is provided principally to assist in demonstrating the window finder code.)
作为开发人员,我想要一个简单,免费的工具,该工具可以执行以下所有操作:(As a developer, I wanted a simple, free tool that would do all of the following:)
- 从对话框控件或消息框中"擦除"文本,以便可以将文本作为文本粘贴到电子邮件或其他内容中. (我在没有准确记下错误内容的情况下解雇错误框的频率是多少?)(‘Scrape’ the text off a dialog box control or message box, so that it can be pasted as text into an email or whatever. (How often have I dismissed the error box without accurately noting down its contents?))
- 从我的应用程序中捕获控件或窗口的图像,以用于文档记录等.(Capture images of controls or windows from my application for documentation purposes etc..)
- 将我的应用程序或Web浏览器窗口调整为特定尺寸,以测试我的应用程序的备用屏幕分辨率或一致的文档.(Resize my application or web browser windows to a specific size for testing alternate screen resolutions or consistent documentation of my application.) 这就是本文介绍的工具所要做的.作为一个全职的开发人员,我希望从现在开始可以大量使用它!(That’s what the tool presented in this article sets out to do. As a full time developer I expect to make a lot of use of it from now on!)
在此过程中,源代码还演示了"保持领先"功能,并且对话框会展开和收缩以显示更多或更少的细节.(Along the way, the source code also demonstrates ‘stay on top’ functionality, and the dialog box expands and contracts to show more or less detail.)
建筑(Architecture)
我要做的第一件事是将原始的SDI应用程序+对话框转换为对话框应用程序,因为SDI位不适合我的设计.(The first thing I wanted to do was to turn the original SDI app + dialog box into a dialog box application, as the SDI bit was inappropriate to my design.)
作为MFC开发人员,最简单的方法是:(As an MFC developer, the easiest way was:)
- 创建一个MFC对话框应用程序.(Create an MFC dialog box application.)
- 删除应用程序向导创建的对话框(Remove the app wizard created dialog box)*cpp(cpp)*和(and)*H(h)*项目中的文件.(files from the project.)
- 删除对对话框的引用(Remove the reference to the dialog box)*H(h)*应用程序中的文件(file in the application)*cpp(cpp)*文件.(file.)
- 从应用程序的中删除标准对话框启动代码(Remove the standard dialog box launch code from the application’s)
InitInstance()
并将其替换为启动Win32对话框所需的代码,即:(and replace it with the code needed to launch the Win32 dialog, i.e.:)
InitialiseResources();
long lRet = (long)DialogBox
(
(HINSTANCE)m_hInstance, // handle to application instance
(LPCTSTR)MAKEINTRESOURCE
(IDD_DIALOG_SEARCH_WINDOW), // identifies dialog box template
(HWND)NULL, // handle to owner window
(DLGPROC)SearchWindowDialogProc // pointer to dialog box procedure
);
还有必要将一些全局声明移出SDI应用程序文件并移至(It was also necessary to move some of the global declarations out of the SDI app file and into the)*windowfinder.cpp(windowfinder.cpp)*文件.结果是应用程序的(file. The result is that the application’s) InitApp()
初始化对话框所需的资源,然后启动对话框.(initializes the resources required for the dialog and then launches the dialog.)
从对话框和消息框中刮取文本(Scraping Text from Dialog and Message Boxes)
中的代码(The code in) DisplayInfoOnFoundWindow()
在(in)*windowfinder.cpp(windowfinder.cpp)*接收到所选窗口的句柄.使用此句柄,很容易获得窗口的文本:(receives a handle to the selected window. With this handle, it is simple to get the window’s text:)
char winTxt[5000];
memset(winTxt, 0, 5000);
SendMessage(hwndFoundWindow, WM_GETTEXT, 5000, (LPARAM)winTxt);
(MSDN文档指出,此方法最好用于((The MSDN documentation states that this method is preferable to) GetWindowText()
从应用程序外部的窗口获取文本时.)(when getting text from a window outside your application.))
然而(However) ,某些控件不会以这种方式产生其内容.因此,例如,要从列表框控件获取文本,我们使用以下代码:(, some controls do not yield their contents in this way. So, for example, to get the text from a listbox control, we use the following:)
if(strcmp(szClassName, "ListBox") == 0)
{
CListBox lb; // Instantiate a MFC listbox object
lb.Attach(hwndFoundWindow);
// Attach the listbox's HWND to our MFC object
nItems=lb.GetCount();
for(count=0; count < nItems; count++)
{
lb.GetText(count, strItem);
strItem+="\r\n";
strcat(winTxt, strItem);
}
lb.Detach(); // Must remember to detach,
// otherwise when lb goes out of scope
// it will destroy the listbox prematurely!
}
(最好使用类似的方法从更复杂的控件(例如树控件)中捕获文本,但到目前为止,这种方法使我难以理解.((It would be nice to capture the text from more complex controls, such as tree controls, using a similar approach but to date such an approach eludes me. Even) myTreeCtrl.GetItemText(myTreeCtrl.GetRootItem()
由于某种原因返回一个空字符串.)(returns an empty string, for some reason.))
将窗口捕获到Windows剪贴板(Capturing the Window to the Windows Clipboard)
这是在处理(This is processed in) SearchWindowDialogProc()
-(搜寻(- (search)windowfinder.cpp(windowfinder.cpp)为"(for “) if(wID == IDC_CAPTURE_BUTTON)
“).(").)
全局已设置为目标窗口的句柄之前(A global is already set to the handle of the target window before) SearchWindowDialogProc()
被调用,所以我们已经有一个要捕获的窗口句柄.(is called, so we already have a handle to the window to capture.)
万一它与捕获目标重叠,我们需要暂时隐藏我们的应用程序,然后将屏幕区域捕获到兼容的位图,然后将其插入剪贴板,最后恢复我们的应用程序窗口.(We need to temporarily hide our application in case it overlaps the capture target, then we capture the screen area to a compatible bitmap and insert it into the clipboard, finally restoring our application’s window.)
这里最大的挑战是,我最初认为您应该使用要捕获的窗口的设备上下文来创建兼容的位图-但这导致捕获了"错误"的区域.使用”(The biggest challenge here was that I initially thought you should use the device context of the window you want to capture to create the compatible bitmap - however this led to the ‘wrong’ area being captured. Using “) hdc=GetDC(HWND_DESKTOP)
“可以正确捕获内容.(” gets things capturing correctly.)
移动和调整目标窗口的大小(Moving and Resizing the Target Window)
中的代码(The code in) DisplayInfoOnFoundWindow()
在(in)*windowfinder.cpp(windowfinder.cpp)*接收到所选窗口的句柄.使用此句柄,很容易调整目标窗口的大小((receives a handle to the selected window. With this handle, it is simple to resize the target window (where) h
和(and) w
是目标窗口的所需高度和宽度):(are the desired height and width of the target window):)
WINDOWPLACEMENT wp;
GetWindowPlacement(g_hwndFoundWindow, &wp);
// Adjust width and height to required
wp.rcNormalPosition.right=wp.rcNormalPosition.left+w;
wp.rcNormalPosition.bottom=wp.rcNormalPosition.top+h;
// Set window placement
SetWindowPlacement(g_hwndFoundWindow, &wp);
同样,将窗口移到屏幕位置很容易通过(Similarly, moving the window to a screen location is easily accomplished via the) Get/SetWindowPlacement()
Win32函数.(Win32 functions.)
留在上面(Stay on Top)
使对话框停留在所有其他窗口的顶部很容易,但是没有以足够清晰的方式记录下来,以便我的头脑在MS文档中理解:(Making the dialog stay on top of all other windows is easy, but not documented in a sufficiently clear enough way for my simple mind to understand in the MS docs:)
设置顶部属性:(To set the stay on top property:)
SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
删除它:(To remove it:)
SetWindowPos( hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW );
对话框上的更多/更少细节(More / Less Detail on Dialog)
通过使用对话框上可见(或隐藏)控件的位置作为标记来调整对话框的大小,可以使对话框显示更多或更少的细节.(We can make the dialog show more or less detail by resizing it using the position of a visible (or hidden) control on the dialog as a marker.)
以下代码块处理对话框的扩展/收缩:(The following code block handles expanding / contracting the dialog:)
WINDOWPLACEMENT dlgwp;
GetWindowPlacement(hwndDlg, &dlgwp);
CRect rect;
UINT nBtnState=IsDlgButtonChecked(hwndDlg, IDC_EXPANDVIEW_CHECK);
if(nBtnState == BST_CHECKED) // Expanded view
{
// Get window placement of bottom groupbox,
// which is the marker for the expanded view
GetWindowRect(GetDlgItem(hwndDlg, IDC_DETAILS_STATIC), &rect);
dlgwp.rcNormalPosition.bottom=rect.bottom+8;
SetWindowPlacement(hwndDlg, &dlgwp);
}
else // Shrunk view
{
// Get window placement of window text static, which
// is the marker for the expanded view
GetWindowRect(GetDlgItem(hwndDlg, IDC_WINTXT_STATIC), &rect);
dlgwp.rcNormalPosition.bottom=rect.top+2;
SetWindowPlacement(hwndDlg, &dlgwp);
}
的(The) IDC_DETAILS_STATIC
ID是指扩展的应用程序窗口底部标记为"详细信息:“的静态组框.(ID refers to the static groupbox labeled “Details:” at the bottom of the expanded application window.)
的(The) IDC_WINTXT_STATIC
ID是指对话框上标有"窗口文本"的静态分组框.(ID refers to the static groupbox labeled “Window Text” on the dialog.)
如您所见,我们使用以下命令获取对话框的初始尺寸和标记静态值(As you can see, we get the initial dimensions of the dialog and marker statics using) GetWindowPlacement()
和(and) GetWindowRect()
并调整(and adjust the) WINDOWPLACEMENT
的(’s) rcNormalPosition
成员.最后我们使用调整后的(members. Finally we use the adjusted) WINDOWPLACEMENT
设置对话框的新大小的结构.(structure to set the new size of the dialog.)
结论(Conclusion)
希望我们在这里拥有的软件/网站开发人员可以使用一个相当有用的小工具.在此过程中,我学到了更多有关Win32的知识(但考虑到选择,我会坚持使用MFC!).我希望您发现该工具有用,即使源代码是Lim Bio Liong的原始作品和我的又快又脏的(但是,它们似乎起作用!)黑客的混合物.(Hopefully what we have here is a reasonably useful little tool for software / web site developers. Along the way, I learned a little more about Win32 (but think I will stick with MFC given the choice!). I hope you find the tool useful, even if the source code is a mixture of Lim Bio Liong’s original work and my quick and dirty (but hell, they seem to work!) hacks.)
最后,如果您确实觉得该工具有用,那么请您抽出宝贵时间单击指向该链接的链接,我们将不胜感激.(Finally, if you do find the tool useful, I’d really appreciate it if you could kindly take the time to click on the link to) http://www.powerprogrammer.co.uk/(http://www.powerprogrammer.co.uk/) 在工具对话框的右上方.哦,还有,给这篇文章一个不错的评价,以便使其他人也能从中受益也有好处!谢谢!(at the top right of the tool’s dialog. Oh, and also, how about giving this article a nice rating so that others can be alerted to the benefits too! Thanks!)
历史(History)
- 2004年1月5日更新了源代码和exe(Updated source and exe on 5 January 2004)
- 2005年6月25日更新了源代码和exe(Updated source and exe on 25 June 2005)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
VC7.0 VC7.1 VC6 WinXP Win2003 Win2K Visual-Studio MFC VS.NET2003 Dev 新闻 翻译