用spy++ 查看訊息

來源:互聯網
上載者:User

VC內建的工具SPY++ 一直不會用,在網上找了一個篇文章,感覺比較好,拿來共用 呵呵
用spy++查看訊息,通過發送訊息控製程序2007-01-11 21:42

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 );

至此,基本操作實現。其實我覺得,只要做的好,完全可以自己做一個介面來,取

代它的介面。


轉自:http://hi.baidu.com/chenfalei/blog/item/725c9a230237f640ac34de1e.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.