學習win32 API 編程,我們應該善於利用微軟給我們提供的一些協助工具輔助,例如大家都知道的MSDN、SPY++等等。
今天在講述之前呢,先給大家介紹一個很有用的工具——Control Spy——它的用途和SPY++有點兒類似,它能查看對應控制項所屬的風格、能響應的訊息以及響應的通知碼。
有了它,加上msdn,你基本上就能很快掌握這些控制項的用法了——都是基於訊息驅動來完成響應的工作
(點擊下載Control Spy小工具)
OK,先來講一下這個小工具的用法(包含個人的學習心得):
(1)在左邊子視窗中,選擇你想學習的控制項,這裡我就選擇Button
(2)在中間子視窗中你就能預覽這個控制項的樣式
(3)我們知道,這些控制項其實本質上都是視窗,因此他們都可以用CreateWindow或者CreateWindowEx函數來建立
下面,我詳細講一下建立的過程(為了協助說明,我將以CreateWindow函數為例,並貼出該函數的原型聲明)
HWND CreateWindow( LPCTSTR lpClassName, // registered class name LPCTSTR lpWindowName, // window name DWORD dwStyle, // window style 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, // menu handle or child identifier HINSTANCE hInstance, // handle to application instance LPVOID lpParam // window-creation data);
我只列出需要注意的幾個特別參數的設法
1>視窗類別的名稱lpClassName——微軟幫預設了對應控制項所關聯的視窗類別名稱——因此,你只需要將它設為TEXT("控制項的英文名稱")
例如,我這裡選擇按鈕Button,你就可以寫為TEXT("button");如果選擇組合框ComboBox,就寫為TEXT("combobox")
註:名稱不區分大小寫,因此你在建立主視窗的時候,就不能將主視窗的視窗類別名稱設為這些控制項的名稱,免得覆蓋了微軟預設的控制項視窗類別名稱
2>視窗的風格dwStyle——這時剛剛提到的小工具就起作用了,你可以在它的子視窗Style中,尋找對應的類型:
不過類型WS_CHILD是必須添加的,如果你想讓改控制項一建立就可見,那麼就應該還加上WS_VISIBLE
3>父視窗hWndParent,由於這些控制項都是子視窗,所以父視窗一定不可為空,這個之情況而定
4>菜單控制代碼hMenu,這個需要設定為控制項的ID號(ID一般就是用宏定義的一些常量,例如:IDB_BUTTON 按鈕ID號)
為了類型的匹配,你需要強制轉換一下類型:(HMENU)IDB_BUTTON
5>執行個體控制代碼hInstance,如果你是在主視窗的WM_CREATE訊息中建立控制項,那麼可以這樣設定:((LPCREATESTRUCT)lParam)->hInstance
(4)瞭解控制項能響應的訊息:
(5)你還可以操作,這個控制項來看看它所響應的訊息以及對應的通知碼
訊息:
通知碼:
好了,這個小工具的大致使用方法就介紹到這裡,如果你還是不怎麼清楚它的用法,可以參見資源下載中提供的英文版協助文檔
光說不練是假把式,還是用程式碼來證明一切
昨天講了按鈕的建立以及使用方法,今天兒就講一下組合框的使用方法。
還是先來看看實現的效果:
可以看見,我還是使用WinXP以來微軟提供的新控制項,畢竟要美觀些
***************************************************進入代碼階段******************************************************
先在標頭檔做一些相應的聲明
//WINDOW_XP_STYLE.H#include<windows.h>//組合框的ID#define IDCB_COMBOBOX_1100#define IDCB_COMBOBOX_2101#define IDCB_COMBOBOX_3103//組合框的個數#define NUMS3//一些字串數組,用於顯示TCHAR* tchSmall[]= {TEXT("小美女"), TEXT("小帥哥"), TEXT("小可愛")};TCHAR* tchBig[]= {TEXT("大美女"), TEXT("大帥哥"), TEXT("小頑皮")};TCHAR* tchNone[]= {TEXT("漂亮"), TEXT("帥氣"), TEXT("可愛")};//使用WinXP以來提供的心控制項#pragma comment(linker,"\"/manifestdependency:type='win32' "\"name='Microsoft.Windows.Common-Controls' "\"version='6.0.0.0' processorArchitecture='*' "\"publicKeyToken='6595b64144ccf1df' language='*'\"")
因為大部分技術都是在前面博文中講述過的,這裡我就僅僅將完整代碼貼出來,內含一定的注釋,只要各位有一定的基礎,應該是能看懂的^_^
//ComboBox.c#include"Window_Xp_Style.h"LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){staticTCHARszAppName[] = TEXT("ComboBox View");//注意這裡不能寫為ComboBox 因為這樣會覆蓋微軟預設的控制項視窗類別名稱HWNDhwnd;MSGmsg;WNDCLASSwndclass;intcxScreen, cyScreen;wndclass.style= CS_HREDRAW | CS_VREDRAW;wndclass.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= szAppName;if(!RegisterClass(&wndclass)){MessageBox(NULL, TEXT("This program requires Windows NT!"),szAppName, MB_ICONERROR);return 0;}cxScreen = GetSystemMetrics(SM_CXSCREEN);cyScreen = GetSystemMetrics(SM_CYSCREEN);hwnd = CreateWindow(szAppName,TEXT("ComboBox Demo"),WS_OVERLAPPEDWINDOW,cxScreen * 7 / 20,cyScreen / 4,cxScreen * 3 / 10,cyScreen / 2,NULL,NULL,hInstance,NULL);ShowWindow(hwnd, iCmdShow);UpdateWindow(hwnd);while(GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){static HWNDhComboBox[NUMS];//組合框視窗控制代碼數組(有3個)intiCombID[] = {IDCB_COMBOBOX_1, IDCB_COMBOBOX_2, IDCB_COMBOBOX_3};//組合框ID數組HFONThFont;//字型控制代碼LOGFONTlf;inti, xPos, yDiv;//迴圈變數、組合框x座標、y座標上的間距switch(message){case WM_CREATE://建立組合框for(i=0; i<NUMS; i++){hComboBox[i] = CreateWindow(TEXT("combobox"), TEXT(""),WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_HASSTRINGS | CBS_SIMPLE,0, 0, 0, 0, hwnd, (HMENU)iCombID[i],((LPCREATESTRUCT)lParam)->hInstance, NULL);}//添加子項for(i=0; i<NUMS; i++)SendMessage(hComboBox[0], CB_ADDSTRING, 0, (LPARAM)tchSmall[i]);for(i=0; i<NUMS; i++)SendMessage(hComboBox[1], CB_ADDSTRING, 0, (LPARAM)tchBig[i]);for(i=0; i<NUMS; i++)SendMessage(hComboBox[2], CB_ADDSTRING, 0, (LPARAM)tchNone[i]);//設定初始狀態選中的子項for(i=0; i<NUMS; i++)SendMessage(hComboBox[i], CB_SETCURSEL, (WPARAM)0, 0);//建立字型ZeroMemory(&lf, sizeof(LOGFONT));lf.lfHeight= -10;hFont = CreateFontIndirect(&lf);//修改當前的字型for(i=0; i<NUMS; i++)SendMessage(hComboBox[i], WM_SETFONT, (WPARAM)hFont, 0); return 0;case WM_SIZE://隨著視窗大小的改變而移動組合框xPos = (LOWORD(lParam) - 100) / 2;yDiv = HIWORD(lParam) / (NUMS + 2);for(i=0; i<NUMS; i++)MoveWindow(hComboBox[i], xPos, yDiv * (i + 1), 100, 20, TRUE);return 0;//回應群組合框子項選擇的訊息case WM_COMMAND://判斷控制項的IDswitch(LOWORD(wParam)){case IDCB_COMBOBOX_1://判斷當前控制項對應的通知碼if(HIWORD(wParam) == CBN_SELENDOK)//選擇了組合框的子項{LRESULT index;index = SendMessage(hComboBox[0], CB_GETCURSEL, 0, 0);if(CB_ERR != index)MessageBox(hwnd, tchSmall[(int)index], TEXT("提示"), MB_OK);}break;case IDCB_COMBOBOX_2://判斷當前控制項對應的通知碼if(HIWORD(wParam) == CBN_SELENDOK){LRESULT index;index = SendMessage(hComboBox[1], CB_GETCURSEL, 0, 0);if(CB_ERR != index)MessageBox(hwnd, tchBig[(int)index], TEXT("提示"), MB_OK);}break;case IDCB_COMBOBOX_3://判斷當前控制項對應的通知碼if(HIWORD(wParam) == CBN_SELENDOK){LRESULT index;index = SendMessage(hComboBox[2], CB_GETCURSEL, 0, 0);if(CB_ERR != index)MessageBox(hwnd, tchNone[(int)index], TEXT("提示"), MB_OK);}break;}return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);}