VS编译器工具 2010-09-27 16:22:34 阅读29 评论0 字号:大中小 订阅
Windows程序都是基于消息机制的,每个程序中都会有各种各样的消息,如果想通过消息来控制程序的运行,我们只用关心程序中的命令消息(WM_COMMAND)就行了,其他关于程序界面等等的消息,可以不管。要查看程序运行的消息,使用Visual Studio中自带的工具spy++。
打开spy++,选择 spy|Windows,然后就会显示出当前的所有窗口,一些主窗口中的字窗口也会显示出来,比如说工具栏窗口,编辑窗口等等。在其中找到目标窗口。
以下是我运行spy++时显示的部分spy++窗口,其中有FineReader窗口001702A6 - tooltips_class32000C01FE - "M" MSCTFIME Ul001C02A0 - "Default IME" IME002401DO - tooltips_class32003B009A - "Microsoft Spy++ - [Windows 2]" Afx:100000:0:10011:0:260051500300244 - "M" MSCTFIME Ul002E032E - FineReaderTipWindowClass004F02B4 - tooltips_class3200410254 - "Untitled batch - ABBYY FineReader 7.0 Professional Edition"FineReader7MainWindowClass003E0370 - "DDE Server Window" OleDdeWndClass005002DC - ComboLBox000D02B6 - ComboLBox00270320 - ComboLBox00AB0366 - ComboLBox00A000A4 - tooltips_class32(注:以上是使用print screen抓图,然后使用FineReader识别的结果)
选择FineReader窗口,点击右键,弹出菜单中选择“Messages”,即可开始监听该窗口的消息。你要是实际操作一下就会发现,消息非常多,根本无法从中找到自己想看的消息。为了选出我们想看的消息,我们需要对消息进行过滤。选择Messages|Options,弹出菜单中选择Messages Tab页,可以看见很多消息过滤选项。我想监听WM_COMMAND消息,所以我Clear All之后,只选择General消息。
以上设置好之后,开始监听消息,然后到FineReader窗口中点击Read快捷按钮(安该按钮之后,FineReader开始识别当前选择的图片),然后回到spy++,监听到的消息仍然不少,但是可以找到我们要查看的消息。如果你只按了一个按钮或者一个菜单,在监听到的消息中间,你应该可以找到两个WM_COMMAND消息,一个发送出去的消息,一个返回的消息,相信信息见下文。
以下是我在spy++中监听到的消息,其中有一个WM_COMMAND消息<00039> 00410254 R...................WM_NOTIFY<00040> 00410254 S...................WM_COMMAND v/NotifyCode:0 (sent from amenu] wlD:4O2O3<00041> 00410254 S...................WM_GETTEXT cchTextMax:512lpszText:0012E200<00042> 00410254 R...................WM_GETTEXT cchCopied:72lpszText:0012E200 f'U'l(注:以上是使用print screen抓图,然后使用FineReader识别的结果)
双击这个WM_COMMAND消息,可以看见关于这个消息的详细信息,如下Window Handle 001F00AA //FineReader窗口句柄Nesting Level 2Message 0111 (Sent) //WM_COMMAND消息ID,这个消息是发送出的消息WM_COMMANDwParam 00009D0B //WM_COMMAND消息的两个参数lParam 00000000
在spy++中监听到的另外一个WM_COMMAND消息<00089> 00410254 S...................WM_GETTEXT cchTextMax:512lpszText:0012E1E0<00090> 00410254 R...................WM_GETTEXT cchCopied:71lpszText:0012E1E0 (V")<00092> 00410254 S...................WM_NOTIFY idCtrl:177 pnmh:0012F988(注:以上是使用print screen抓图,然后使用FineReader识别的结果)
双击这个WM_COMMAND消息,可以看见关于这个消息的详细信息,如下Window Handle 001F00AA //FineReader窗口句柄Nesting Level 2Message 0111 (Return) //WM_COMMAND消息ID,这个消息是的消息WM_COMMANDwParam 00009D0B //WM_COMMAND消息的两个参数lParam 00000000
既然可以查看到程序中消息的ID及消息的参数,那么我们可以自己编写程序,向被控制的程序发送对应的消息,从而控制程序的运行。
第一步,在自己的程序中打开目标程序,使用一下API,具体请查看MSDN。HINSTANCE ShellExecute(HWND hwnd,LPCTSTR lpOperation,LPCTSTR lpFile,LPCTSTR lpParameters,LPCTSTR lpDirectory,INT nShowCmd);
在我的程序中,目标程序为FineReader,打开程序的代码如下:HINSTANCE hRet = 0;hRet = ShellExecute(m_hWnd,NULL,"D://Program Files//ABBYY FineReader 7.0 ProfessionalEdition//FineReader.exe",NULL,NULL,SW_HIDE);if( (int)hRet <= 32 ){MessageBox("打开FineReader失败!");}
第二步,找到目标窗口,获得目标窗口的句柄CWnd* pWnd = NULL;
//可能程序启动较慢,需要尝试多次才能找到目标窗口while(pWnd == NULL){Sleep(1000);pWnd = FindWindow(NULL, "Batch - ABBYY FineReader 7.0 ProfessionalEdition");}
第三步,向目标窗口发送消息。可以使FineReader开始运行时,自动打开最后一次运行的一个Batch,所以我们只用发送消息,让FineReader开始识别就可以了。通过spy++可以查看到FineReader识别的WM_COMMAND信息如下Message 0111 (Sent)WM_COMMANDwParam 00009D0BlParam 00000000按以下方式向FineReader发送这个消息,使用SendMessage,等待消息返回后,再进行下一步操作::SendMessage(pWnd->GetSafeHwnd(), 0x0111, 0x9D0B, 0 );FineReader识别完成之后,可以选择把结果保存为文件,或者发送到剪贴板,我选择的是让其把识别结果发送到剪贴板。同样使用spy++监听消息及其参数,然后发送对应的消息,如下:Message 0111 (Sent)WM_COMMANDwParam 00009DA1lParam 00000000::SendMessage(pWnd->GetSafeHwnd(), 0x0111, 0x9DA1, 0 );
进行这些操作之后,FineReader识别之后,就可以直接从剪贴板得到识别结果了,相关代码如下if (!IsClipboardFormatAvailable(CF_TEXT))return;if (!OpenClipboard())return;
HGLOBAL hglb = GetClipboardData(CF_TEXT);if (hglb != NULL){LPTSTR lptstr = (char*)GlobalLock(hglb);if (lptstr != NULL){MessageBox(lptstr, "识别结果");GlobalUnlock(hglb);}}EmptyClipboard();CloseClipboard();
第四步,操作完毕之后,关闭目标程序,同样通过发送消息完成。最先我以为直接发送WM_QUIT消息就可以了,后来发现不行,用spy++监听后发现,应该发送WM_CLOSE消息。::SendMessage(pWnd->GetSafeHwnd(), WM_CLOSE, 0, 0 );至此,基本操作实现。其实我觉得,只要做的好,完全可以自己做一个界面来,取代它的界面。
