第4章 第一個窗口程序

1 了解窗口

2 窗口程序原理

事件驅(qū)動模式


image.png

窗口程序的運行過程


窗口程序的運行過程

DispatchMessage會在內(nèi)部調(diào)用消息處理的回調(diào)函數(shù)
窗口程序的運行過程

應(yīng)用程序之間也可互相發(fā)送消息
PostMessage 將一個消息放到其他程序的消息隊列中
SendMessage 越過消息隊列直接調(diào)用目標程序的窗口過程

RegisterClassEx 用來注冊窗口過程 即用來注冊處理窗口消息的回調(diào)函數(shù)

2 分析窗口程序

2.1 模塊與句柄

exe dll裝入內(nèi)存后稱為模塊,每個模塊都有一個唯一標識的句柄,在win32中,模塊句柄在數(shù)值上等于內(nèi)存中裝入的起始地址,用來標識各種資源
使用GetModuleHandle來獲取模塊句柄
例子


獲取user32.dll的句柄

當(dāng)參數(shù)為NULL,會獲取調(diào)用者本模塊的句柄


image.png

在win32中實例句柄就是模塊句柄
hInstance hModule
在C語言編程中 hInstance通過WinMain由系統(tǒng)傳入
在win32匯編中,hInstance需要自己獲取

windows中幾乎所有的東西都是用句柄標識的,如文件句柄、窗口句柄、線程句柄、模塊句柄等

2.2 創(chuàng)建窗口

窗口類中定義窗口的屬性


窗口類的定義

初始化


窗口類的初始化
hIcon 窗口圖標句柄 預(yù)定義 可通過LoadIcon指定
hCursor 光標句柄 預(yù)定義(IDC_ARROW...) 可通過LoadCursor指定
lpszMenuName 菜單字符串
hInstance 指定窗口類屬于哪個模塊 GetModuleHandle
cbSize 指定結(jié)構(gòu)的長度
style 窗口風(fēng)格 CS_HREDRAW CS_VREDRAW CS_DBLCLKS
hbrBackground  刷子句柄 指定窗口客戶區(qū)的背景色  如BLACK_BRUSH、WHITE_BRUSH 使用 GetStockObject來獲取刷子句柄 也可以指定顏色值 如 COLOR_BACKGROUND,COLOR_HIGHLIGHT,COLOR_MENU,COLOR_WINDOW等,需要加1
lpszClassName 指定類的名稱
cbWndExtra cbClsExtra 預(yù)留的空間 用來存放自定義數(shù)據(jù)
lpfnWndProc 回調(diào)函數(shù)

使用CreateWindowEx來建立窗口

HWND CreateWindowEx(
    DWORD dwExStyle,    // extended window style WS_EX_* 可參考MSDN
    LPCTSTR lpClassName,    // pointer to registered class name
    LPCTSTR lpWindowName,   // pointer to window name
    DWORD dwStyle,  // window style 可參考MSDN WS_*
    int x,  // horizontal position of window
    int y,  // vertical position of window
    int nWidth, // window width
    int nHeight,    // window height
    HWND hWndParent,    // handle to parent or owner window 上級窗口,上級窗口銷毀時,下級窗口也會被銷毀
    HMENU hMenu,    // handle to menu, or child-window identifier 菜單句柄 可替換窗口類中的菜單 當(dāng)dwStyle為WS_CHILD時,表示子窗口的ID
    HINSTANCE hInstance,    // handle to application instance 模塊句柄
    LPVOID lpParam  // pointer to window-creation data 傳給窗口的參數(shù)  這個參數(shù)在WM_CREATE消息中可以被獲取
   );
style的預(yù)定義值
style的預(yù)定義組合
ExStyle的預(yù)定義值

常見的窗口樣式


image.png

ShowWindow用來顯示窗口

BOOL ShowWindow(
    HWND hWnd,  // handle of window
    int nCmdShow    // show state of window
   );
窗口的顯示方式

UpdateWindow繪制客戶區(qū) 向窗口發(fā)送了一條WM_PAINT消息

BOOL UpdateWindow(
    HWND hWnd   // handle of window  
   );

CreateWindowEx也可以創(chuàng)建子窗口 如Button Edit
創(chuàng)建一個button


創(chuàng)建一個button

注意 hMenu在這里表示子窗口的ID

2.3 消息循環(huán)

消息循環(huán)的一般形式

image.png

消息格式


image.png
image.png

lpMsg為指向MSG結(jié)構(gòu)體的指針,接收返回消息
若獲取的消息WM_QUIT eax中的返回值為0

TranslateMessage進行一些鍵盤消息的轉(zhuǎn)換,將鍵盤消息的掃描碼轉(zhuǎn)換成ASC碼在消息隊列中插入WM_CHAR WM_SYSCHAR消息 遇到非鍵盤消息不處理

DispathMessage將消息發(fā)送到窗口處理過程,窗口過程返回后DispathMessage才返回

其它形式的消息循環(huán)

PeekMessage

BOOL PeekMessage(
    LPMSG lpMsg,    // pointer to structure for message
    HWND hWnd,  // handle to window
    UINT wMsgFilterMin, // first message
    UINT wMsgFilterMax, // last message
    UINT wRemoveMsg     // removal flags PM_NOREMOVE 取一條消息后在消息隊列中刪除該消息 PM_REMOVE 取一條消息不刪除
   );   
 

無論應(yīng)用程序消息隊列是否有消息,PeekMessage函數(shù)都立即返回,程序得以繼續(xù)執(zhí)行后面的語句(無消息則執(zhí)行其它指令,有消息時一般要將消息派發(fā)出去,再執(zhí)行其它指令)。
GetMessage函數(shù)只有在消息隊列中有消息時返回,隊列中無消息就會一直等,直至下一個消息出現(xiàn)時才返回。在等的這段時間,應(yīng)用程序不能執(zhí)行任何指令。

2.4 窗口過程

窗口過程的一般結(jié)構(gòu)


image.png

注意 proc后面的uses偽操作在子程序進入和退出時自動插上push和pop寄存器指令,來保護這些寄存器的值

uMsg的windows標準窗口預(yù)定義的值的范圍為0-03ffh
用戶自定義的消息可以從04ooh開始 一般為WM_USER+1,WM_USER+2,...

wParam和lParam為消息附帶的參數(shù),不同消息不一樣

當(dāng)窗口決定關(guān)閉時,需要程序調(diào)用DestoryWindow來摧毀窗口,并用PostQuitMessage向消息循環(huán)發(fā)送WM_QUIT消息來退出消息循環(huán)。

DefWindowProc來處理用戶不管的消息,采取默認方式來處理窗口消息


DefWindowProc對一些消息的默認處理方式

附錄 B實驗

3 窗口間的通信

3.1 窗口間消息的互發(fā)

不同的應(yīng)用程序之間可以使用SendMessage和PostMessage互相發(fā)送消息

LRESULT SendMessage(

    HWND hWnd,  // handle of destination window
    UINT Msg,   // message to send
    WPARAM wParam,  // first message parameter
    LPARAM lParam   // second message parameter
   );
BOOL PostMessage(

    HWND hWnd,  // handle of destination window
    UINT Msg,   // message to post 
    WPARAM wParam,  // first message parameter
    LPARAM lParam   // second message parameter
   );

對于不同的msg, wParam和lParam的含義是不同的
wsprintf win32 api中用來格式化字符串輸出的函數(shù)
windows在處理SendMessage時 傳遞字符串時使用了共享內(nèi)容
注意 在用戶自定義的消息中,不要在消息參數(shù)中傳遞指針 會引發(fā)非法訪問內(nèi)存

3.2 在窗口間傳遞數(shù)據(jù)

WM_COPYDATA消息用于在不同應(yīng)用間傳遞數(shù)據(jù)

WM_COPYDATA  
wParam = (WPARAM) (HWND) hwnd;            // handle of sending window 
lParam = (LPARAM) (PCOPYDATASTRUCT) pcds; // pointer to structure with data 

數(shù)據(jù)包含在COPYDATASTRUCT結(jié)構(gòu)體中

typedef struct tagCOPYDATASTRUCT {  // cds  
    DWORD dwData; //Specifies up to 32 bits of data to be passed to the receiving application
    DWORD cbData; //Specifies the size, in bytes, of the data pointed to by the lpData member.
    PVOID lpData; //Points to data to be passed to the receiving application. This member can be NULL. 
} COPYDATASTRUCT; 

3.3 SendMessage和PostMessage的區(qū)別

SendMessage相當(dāng)于直接調(diào)用其他窗口的窗口過程來處理某個消息,并等待窗口過程處理完成后返回
PostMessage則將某個消息放入目標窗口的消息隊列中并直接返回,不能用于任何參數(shù)中用到指針的消息

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容