![]() |
【转帖】用spy++查看消息,通过发送消息控制程序
用spy++查看消息,通过发送消息控制程序
Windows程序都是基于消息机制的,每个程序中都会有各种各样的消息, 如果想通过消息来控制程序的运行,我们只用关心程序中的命令消息 (WM_COMMAND)就行了,其他关于程序界面等等的消息,可以不管。要查看程 序运行的消息,使用Visual Studio中自带的工具spy++。 打开spy++,选择 spy|Windows,然后就会显示出当前的所有窗口,一 些主窗口中的字窗口也会显示出来,比如说工具栏窗口,编辑窗口等等。在 其中找到目标窗口。 以下是我运行spy++时显示的部分spy++窗口,其中有FineReader窗口 001702A6 - tooltips_class32 000C01FE - "M" MSCTFIME Ul 001C02A0 - "Default IME" IME 002401DO - tooltips_class32 003B009A - "Microsoft Spy++ - [Windows 2]" Afx:100000:0:10011:0:2600515 00300244 - "M" MSCTFIME Ul 002E032E - FineReaderTipWindowClass 004F02B4 - tooltips_class32 00410254 - "Untitled batch - ABBYY FineReader 7.0 Professional Edition" FineReader7MainWindowClass 003E0370 - "DDE Server Window" OleDdeWndClass 005002DC - ComboLBox 000D02B6 - ComboLBox 00270320 - ComboLBox 00AB0366 - ComboLBox 00A000A4 - 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 a menu] wlD:4O2O3 <00041> 00410254 S...................WM_GETTEXT cchTextMax:512 lpszText:0012E200 <00042> 00410254 R...................WM_GETTEXT cchCopied:72 lpszText:0012E200 f'U'l (注:以上是使用print screen抓图,然后使用FineReader识别的结果) 双击这个WM_COMMAND消息,可以看见关于这个消息的详细信息,如下 Window Handle 001F00AA //FineReader窗口句柄 Nesting Level 2 Message 0111 (Sent) //WM_COMMAND消息ID,这个消息是发送出的消息 WM_COMMAND wParam 00009D0B //WM_COMMAND消息的两个参数 lParam 00000000 在spy++中监听到的另外一个WM_COMMAND消息 <00089> 00410254 S...................WM_GETTEXT cchTextMax:512 lpszText:0012E1E0 <00090> 00410254 R...................WM_GETTEXT cchCopied:71 lpszText:0012E1E0 (V") <00092> 00410254 S...................WM_NOTIFY idCtrl:177 pnmh:0012F988 (注:以上是使用print screen抓图,然后使用FineReader识别的结果) 双击这个WM_COMMAND消息,可以看见关于这个消息的详细信息,如下 Window Handle 001F00AA //FineReader窗口句柄 Nesting Level 2 Message 0111 (Return) //WM_COMMAND消息ID,这个消息是的消息 WM_COMMAND wParam 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 Professional Edition\\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 Professional Edition"); } 第三步,向目标窗口发送消息。 可以使FineReader开始运行时,自动打开最后一次运行的一个Batch,所以我们只用 发送消息, 让FineReader开始识别就可以了。通过spy++可以查看到FineReader识别的WM_COMMAND 信息如下 Message 0111 (Sent) WM_COMMAND wParam 00009D0B lParam 00000000 按以下方式向FineReader发送这个消息,使用SendMessage,等待消息返回后,再进 行下一步操作 ::SendMessage(pWnd->GetSafeHwnd(), 0x0111, 0x9D0B, 0 ); FineReader识别完成之后,可以选择把结果保存为文件,或者发送到剪贴板,我选 择的是让其 把识别结果发送到剪贴板。同样使用spy++监听消息及其参数,然后发送对应的消息, 如下: Message 0111 (Sent) WM_COMMAND wParam 00009DA1 lParam 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 ); 至此,基本操作实现。其实我觉得,只要做的好,完全可以自己做一个界面来,取 代它的界面。 |
回复: 【转帖】用spy++查看消息,通过发送消息控制程序
如何使用spy ++ (How to use Spy ++)
一个网友在我的一篇随笔后问道,如何使用spy ++ 查找要用到的窗体类名以及相关信息 现把相关作法整理如下 如果你装了vs.net,在vs.net的工具里面就可以看到spy ++ 打开spy ++,会以树状图显示当前系统所有的窗体信息,然后找到你需要用到的窗体,当然,这里的窗口并不一定都是窗口,子窗体的一般都是指父窗体中的控件而已 其实这里的信息就已经一目了然了 比如说这里显示的是“窗口000A04A0’本地连接’#32770(对话框)” 其中”000A04A0”是这个窗体的句柄 “本地连接”是这个窗体的标题 最后一个”#32770(对话框)”就代表这个窗体的类名了 这里表示这个窗体是一个对话框 像下面的”窗口 00080416’取消’Button”中最后的”Button”也是类名一样 当然你也可以通过双击或者右键查看这个窗体具体的属性 |
所有的时间均为北京时间。 现在的时间是 05:33 AM. |