從當初說要學C++,學了兩天放了倆月,真是無奈+悲劇。元旦放假,天氣太冷,原計劃再次騎行密雲也無法成行了,隻好在家繼續貓着,正好再look下C++。
以前一直走的是彎路,如果要想學工作之外的東西,從底層文法開始一點點的走實在是費時費力的事情。無法連貫的看、寫,效率極其低下。所有的語言文法結構等都差别不是很大,我感覺差距最大的在編譯器上,不過這不是我們關心的了。所有掌握了最最基本的C++後,果斷放棄文法。通過寫程式,碰到的東西在回來學習思考,效率提高很多,而且不再枯燥無味。
好了,轉入正題。
昨天用C++完成了一個初步的窗體和資源檔案的建立與調用。用就了C#和Java,習慣了拖拽。對于這種較原始的方式感覺無比的不爽。但對于程式的執行方式,Windows的消息機制的了解是很有好處的。
昨天的知識複習:
一、Windows類
Windows類有兩種:WNDCLASS和WNDCLASSEX後者是前者的擴充版,是以主要用的是WNDCLASSEX。
WNDCLASSEX結構
typedef struct _WNDCLASSEX
{
UINT cbSize; // 結構大小
UINT style; // 視窗的資訊标志
WNDPROC lpfnWndProc; // 事件函數
int cbClsExtra; // 緊跟在視窗類結構後的附加位元組數。
int cbWndExtra; // 緊跟在視窗類結構後的附加位元組數。
HANDLE hInstance; // 子產品的事例句柄
HICON hIcon; // 圖示的句柄
HCURSOR hCursor; // 光标的句柄
HBRUSH hbrBackground; // 背景畫刷的句柄
LPCTSTR lpszMenuName; // 指向菜單的指針
LPCTSTR lpszClassName; // 指向類名稱的指針
HICON hIconSm; // 和視窗類關聯的小圖示
} 執行個體
1 WNDCLASSEX winclass;
2
3 winclass.cbSize = sizeof (WNDCLASSEX);
4 winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
5 winclass.lpfnWndProc = WindowProc;
6 winclass.cbClsExtra = 0 ;
7 winclass.cbWndExtra = 0 ;
8 winclass.hInstance = hInstance;
9 winclass.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_SKELETON));
10 winclass.hCursor = LoadCursor(hInstance,MAKEINTRESOURCE(IDC_XING));
11 winclass.hbrBackground = (HBRUSH)GetStockBrush(WHITE_BRUSH);
12 winclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
13 winclass.lpszClassName = WINDOW_CLASS_NAME;
14 winclass.hIconSm = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_SKELETON)); 接下來為類的注冊:RegisterClassEx(&winclass)
建立視窗:
代碼
// 生成窗體
if ( ! (hWnd = CreateWindowEx(NULL,
WINDOW_CLASS_NAME, // 類名
" Window " , // 标題
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // 風格
200 , 200 , // 坐标
400 , 400 , // 大小
NULL,
NULL,
hInstance,
NULL)))
{
return 0 ;
}
二:事件機制
Windows的事件機制為當Windows運作任務時會産生事件和消息,所有的消息都進入一個隊列,你視窗的消息會進入一個專門的隊列中。你要做的就是從這些隊列中取出消息并處理。Windows把最常用的消息做了處理,是以你可以隻對你幹興趣的消息進行處理。
代碼
1 LRESULT CALLBACK WindowProc(HWND hWnd,
2 UINT msg,
3 WPARAM wparam,
4 LPARAM lparam)
5 {
6 PAINTSTRUCT ps;
7 HDC hdc;
8
9 switch (msg)
10 {
11 case WM_CREATE:
12 return 0 ;
13 break ;
14 case WM_PAINT:
15 hdc = BeginPaint(hWnd, & ps);
16
17 EndPaint(hWnd, & ps);
18 break ;
19 case WM_DESTROY:
20 PostQuitMessage( 0 );
21 return 0 ;
22 break ;
23 case WM_KEYUP:
24 if (wparam == VK_F5)
25 {
26 // 播放音樂
27 PlaySound(MAKEINTRESOURCE(IDR_WARP),hInstanceCpp,SND_RESOURCE | SND_SYNC);
28 }
29 break ;
30 case WM_CLOSE:
31 MessageBox(hWnd, " 關閉 " , " 消息 " ,MB_OK | MB_ICONINFORMATION);
32 break ;
33 case WM_COMMAND:
34 switch (LOWORD(wparam))
35 {
36 case MEN_NEW:
37 MessageBox(hWnd, " 建立 " , " 消息 " ,MB_OK | MB_ICONINFORMATION);
38 break ;
39 case MEN_OPEN:
40 MessageBox(hWnd, " Open " , " 消息 " ,MB_OK | MB_ICONINFORMATION);
41 break ;
42 }
43 break ;
44 default : break ;
45 }
46
47 return (DefWindowProc(hWnd,msg,wparam,lparam));
48 } 三:主事件循環
主事件循環的工作就是從消息隊列中取消息經過初步處理後發生至消息處理函數。
代碼
1 // 主事件循環
2 while ( true )
3 {
4 if (PeekMessage( & msg,NULL, 0 , 0 ,PM_REMOVE))
5 {
6 if (msg.message == WM_QUIT)
7 break ;
8
9 TranslateMessage( & msg);
10
11 DispatchMessage( & msg);
12
13 }
14 } 這裡的一個無限循環看似是一個錯誤的用法,會無限制的消耗資源,但其實這是對的。
取出消息隊列有兩種方式GetMessage()和PeekMeessage(),他們的差別在于前者取出後會删除消息隊列中的消息而後者可以設定參數表明是否删除。
繼續上面所說的無限循環問題,因為對應代碼可知隻有在有消息并取出時才會真正的執行循環,并不會消耗太多資源。另外很多時候消息隊列是空閑的,如果隻是等待确實不是個好主意可以在消息隊列空閑時處理額外的事情,你要做的隻是在上面加一個else。
四:資源的使用
隻是看了些簡單的時候,原理基本相同,打包成資源檔案或存到硬碟,隻要能取得句柄就ok。
好了,就到這裡,邊寫邊學對我來說應該是最适合的學習方法,學無止境。以前感覺用C#已經很牛了,可以做很多東西,但對于真正的系統級的東西了解太少了。C#的重點在于快速開發和減少程式員的工作。這方面它是成功的。但對于我來說則更傾向于大型遊戲開發,這是我的一個夢想。
漸行漸近漸迷茫,
玉兔蹬春新年鬧。
欲說尋夢今不悔,
同輩盡皆而立望。
轉載于:https://www.cnblogs.com/mnight/archive/2011/01/02/1924032.html