《VC++深入详解》学习笔记 第一章 Windows程序内部运行机制
生活随笔
收集整理的這篇文章主要介紹了
《VC++深入详解》学习笔记 第一章 Windows程序内部运行机制
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
(金光鱗閃影若茫)
窗口四步走:
設計窗口類
注冊窗口類
創建窗口
顯示更新窗口
最后創建消息循環和響應函數
設計窗口類:
typedef struct {UINT style;//窗口類型 WNDPROC lpfnWndProc;//窗口處理函數int cbClsExtra;//窗口擴展int cbWndExtra;//窗口實例擴展HINSTANCE hInstance;//實例句柄HICON hIcon;//窗口的最小化圖標HCURSOR hCursor;//窗口鼠標光標HBRUSH hbrBackground;//窗口背景色LPCTSTR lpszMenuName;//窗口菜單LPCTSTR lpszClassName;// 窗口類名 } WNDCLASS, *LPWNDCLASS說明:
舉例:
WNDCLASS wndclass;char lpszClassName[]="窗口"; //窗口類名char lpszTitle[]="測試窗口"; //窗口標題名//窗口類定義,窗口類定義了窗口的形式與功能,窗口類定義通過給窗口類數據結構WNDCLASS賦值完成//該數據結構中包含窗口類的各種屬性wndclass.style =0; // 窗口類型為缺省類型CS_ Class Stylewndclass.lpfnWndProc=WndProc; //定義窗口處理函數wndclass.cbClsExtra=0; //窗口類無擴展wndclass.cbWndExtra=0; //窗口實例無擴展wndclass.hInstance=hInstance; //當前實例句柄wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); //窗口的最小化圖標為缺省圖標wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); // 窗口采用箭頭光標wndclass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景為白色wndclass.lpszMenuName=NULL; //窗口無菜單wndclass.lpszClassName=lpszClassName; //窗口類名為“窗口”注冊窗口類:
//以下是窗口類的注冊-----------Windows系統本身提供部分預定義的窗口類,程序員也可以自定義窗口類,窗口類必須先注冊后使用。 if(!RegisterClass(&wndclass)) //如果注冊失敗 發出警告 {MessageBeep(0); return FALSE;}說明:注冊內容為窗口類對象指針(服務消息處理)
?創建窗口:
//創建窗口創建一個窗口的實例由函數CreateWindow()實現 CreateWindow(lpszClassName, //窗口類名,創建窗口時一定要基于我們已經注冊過的窗口類名,即"窗口"。lpszTitle, //窗口標題名WS_OVERLAPPEDWINDOW, //窗口的風格 WS_ Windows StyleCW_USEDEFAULT, //窗口左上角坐標值為缺省值 CW_ Create Wndow CW_USEDEFAULT, CW_USEDEFAULT, //窗口的高和寬為缺省值 CW_USEDEFAULT, NULL, //此窗口無父窗口NULL, //此窗口無子菜單hInstance, //創建此窗口的應用程序的當前句柄NULL //不使用該值 );說明:創建方式應為 HWND hwnd = CreateWindow(...);
hwnd值為NULL(創建失敗)或者窗口句柄(創建成功)
顯示更新窗口:
顯示窗口:
//顯示窗口
ShowWindow(hwnd,nCmdShow);
窗口句柄以及指定顯示狀態
更新窗口:
//繪制用戶區,在顯示后必須需要
UpdateWindow(hwnd);
循環及響應:
?消息循環:
BOOL GetMessage(LPMSG lpMsg,//指向 MSG 結構的指針,用于存放獲取到的消息HWND hWnd,//當其值是 NULL 時,將獲取所有的當前線程的窗口消息和線程消;當其值是 -1 時,只獲取當前線程消息UINT wMsgFilterMin,//指定被可以被獲取的消息值的最小整數(消息其實就是一個被定義的整數)UINT wMsgFilterMax,//指定被可以被獲取的消息值的最大整數 );說明:Min和Max都設置為0時接收所有消息;返回值都為非零值(除了WM_QUIT)錯誤返回值為-1;
消息循環一條線程一個,是保證windows消息響應模式就基礎,而非一個窗口一個;
舉例:
//消息循環 while(GetMessage(&Msg,NULL,0,0)) {TranslateMessage(&Msg);//對"消息對"的轉化,如對鍵盤的WM_KEYDOWN和WM_KEYUP消息對轉化為WM_CHAR消息,并且將轉換后的新消息投遞到我們的消息隊列中去,//這個轉化操作不會影響原來的消息,只會產生一個新的消息。DispatchMessage(&Msg);//DispatchMessage()函數是將我們取出的消息傳到窗口的回調函數去處理;可以理解為該函數將取出的消息路由給操作系統,然后操作系統去調用我們的窗口回調函數對這個消息進行處理。 }
窗口過程函數:
LRESULT CALLBACK WindowProc ( HWND hwnd, // 消息句柄 UINT uMsg, // 消息代碼 WPARAM wParam, // first message parameter LPARAM lParam // second message parameter );說明:
函數名隨意但要對應設計時的名稱,一個窗口對應一個過程函數
過程函數配合switch/case處理窗口中其他控件消息
舉例:
long CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) {switch(message){case WM_DESTROY:PostQuitMessage(0);default: //缺省時采用系統消息缺省處理函數return DefWindowProc(hwnd,message,wParam,lParam);}return (0); }?說明:其中message 通過translatemessage()將事件轉化而來
?
?
綜合:
long CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);//聲明 //WinMain函數是所有Windows應用程序的入口,類似c語言中的main函數其功能是完成//一系列的定義和初始化,并產生消息循環。函數說明: int WINAPI WinMain(HINSTANCE hInstance, // handle to current instanceHINSTANCE hPrevInstance, // handle to previous instanceLPSTR lpCmdLine, // command lineint nCmdShow // show state ) {//初始化,初始化包括窗口類的定義、注冊、創建窗口實例和顯示窗口四部分 HWND hwnd;MSG Msg;WNDCLASS wndclass;char lpszClassName[]="窗口"; //窗口類名char lpszTitle[]="測試窗口"; //窗口標題名//窗口類定義,窗口類定義了窗口的形式與功能,窗口類定義通過給窗口類數據結構WNDCLASS賦值完成//該數據結構中包含窗口類的各種屬性wndclass.style =0; // 窗口類型為缺省類型CS_ Class Stylewndclass.lpfnWndProc=WndProc; //定義窗口處理函數wndclass.cbClsExtra=0; //窗口類無擴展wndclass.cbWndExtra=0; //窗口實例無擴展wndclass.hInstance=hInstance; //當前實例句柄wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); //窗口的最小化圖標為缺省圖標wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); // 窗口采用箭頭光標wndclass.hbrBackground=(HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景為白色wndclass.lpszMenuName=NULL; //窗口無菜單wndclass.lpszClassName=lpszClassName; //窗口類名為“窗口”//以下是窗口類的注冊-----------Windows系統本身提供部分預定義的窗口類,程序員也可以自定義窗口類,窗口類必須先注冊后使用。if(!RegisterClass(&wndclass)) //如果注冊失敗 發出警告{MessageBeep(0); return FALSE;}//創建窗口創建一個窗口的實例由函數CreateWindow()實現hwnd=CreateWindow( lpszClassName, //窗口類名,創建窗口時一定要基于我們已經注冊過的窗口類名,即"窗口"。lpszTitle, //窗口標題名WS_OVERLAPPEDWINDOW, //窗口的風格 WS_ Windows StyleCW_USEDEFAULT, //窗口左上角坐標值為缺省值 CW_ Create Wndow CW_USEDEFAULT,CW_USEDEFAULT, //窗口的高和寬為缺省值 CW_USEDEFAULT,NULL, //此窗口無父窗口NULL, //此窗口無子菜單hInstance, //創建此窗口的應用程序的當前句柄NULL //不使用該值 );//顯示窗口 ShowWindow(hwnd,nCmdShow);//繪制用戶區 UpdateWindow(hwnd);//消息循環while(GetMessage(&Msg,NULL,0,0)) //GetMessage()函數是從調用線程的消息隊列中取出一條消息;對于每一個應用程序窗口線程,操作系統都會為其建立一個消息隊列,當我們的窗口有消息時(即所有與這個窗口線程相關的消息),操縱系統會把這個消息放到該線程的消息隊列當中,我們的窗口程序就通過這個GetMessage()函數從自己的消息隊列中取出一條一條具體的消息并進行響應操作。 {TranslateMessage(&Msg);//對"消息對"的轉化,如對鍵盤的WM_KEYDOWN和WM_KEYUP消息對轉化為WM_CHAR消息,并且將轉換后的新消息投遞到我們的消息隊列中去,
這個轉化操作不會影響原來的消息,只會產生一個新的消息。DispatchMessage(&Msg);//DispatchMessage()函數是將我們取出的消息傳到窗口的回調函數去處理;可以理解為該函數將取出的消息路由給操作系統,然后操作系統去調用我們的窗口回調函數對這個消息進行處理。 }return Msg.wParam; //消息循環結束 即程序結束時 將信息返回系統 } //窗口函數,窗口函數定義了應用程序對接收到的不同消息的響應,其中包含了應用程序對各種可能接受到的消息的處理過程,時消息處理分支控制語句的集合 long CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) {switch(message){case WM_DESTROY:PostQuitMessage(0);default: //缺省時采用系統消息缺省處理函數return DefWindowProc(hwnd,message,wParam,lParam);}return (0); } 注:窗口回調函數的函數指針定義typedef LRESULT CALLBACK (* WNDPROC)(HWND, UINT, WPARAM, LPARAM); WNDPROC OldWndProc; LRESULT CALLBACK NewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){switch (Msg){......}return CallWindowProc(OldWndProc,g_Wnd,Msg,wParam,lParam); } OldWndProc = (WNDPROC)GetWindowLong(g_Wnd,GWL_WNDPROC); SetWindowLong(hwnd, GWL_WNDPROC,(LPARAM)(WNDPROC)NewWndProc); 通過調用SetWindowLong函數可以修改該窗體類的回調函數。
?
轉載于:https://www.cnblogs.com/sepmaple/p/9321732.html
總結
以上是生活随笔為你收集整理的《VC++深入详解》学习笔记 第一章 Windows程序内部运行机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis使用场景一,查询出的数据保存到
- 下一篇: GIL,同步与异步