1.標准控件
可以在win32窗口程序中添加資源腳本來給程序添加標准控件;
具體操作為:新建資源腳本 ->在.rc文件中添加控件 ->給控件綁定事件;
常用的標准控件:
Static ->組框,用來將窗口分成多個塊
Group Box
Button
Check Box
Radio Button
Edit
ComboBox
ListBox
2.通用控件
標准控件是一些常用的控件,因此每當程序編譯時,會將這些控件加到exe程序中;
因此標准控件總是可用的;
還有一些不常用的控件,因為不常用,每次編譯時加到程序中會浪費空間;
這些控件就是通用控件;
微軟為了節省程序空間,將不常用的通用控件放在Comctrl32.dll中;
如果要使用通用控件,首先要引入該動態鏈接庫:
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
常用的通用控件:
Animation
ComboBoxEx
Date_and_Time_Picker
Drag_List_Box
Flat_Scroll_Bar
Header
HotKey
ImageList
IPAddress
List_View
Month_Calendar
Pager
Progress_Bar
Property_Sheets
Rebar
Status Bars
SysLink
Tab
Toolbar
ToolTip
Trackbar
TreeView
Up_and_Down
特別說明:
通用控件在使用前,需要通過INITCOMMONCONTROLSEX進行初始化
只要在您的程序中的任意地方引用了該函數就、會使得WINDOWS的程序加載器PE Loader加載該庫
INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&icex);
也就是告訴PE Loader到底要dll中的哪些通用控件;
這段代碼一般放winmain剛開始的地方;
在msdn中搜索INITCOMMONCONTROLSEX結構,可以看到哪個參數對應的是哪個控件,例如:ICC_WIN95_CLASSES表示包含大多數常用通用控件;
3.ListView的使用
ListView是一種通用控件;用來顯示多條信息;
往listView中添加數據:
#include <windows.h> #include "resource.h" #include <commctrl.h> #pragma comment(lib,"comctl32.lib") //給進程窗口添加內容;就是給ListView控件添加列,本來是要遍歷進程的,為了簡單填假數據 void EnumProcess(HWND hListProcess){ LV_ITEM vitem; //初始化 memset(&vitem,0,sizeof(LV_ITEM)); vitem.mask = LVIF_TEXT; vitem.pszText = "csrss.exe"; //值 vitem.iItem = 0; //行 vitem.iSubItem = 0; //列 //ListView_InsertItem(hListProcess, &vitem); //一個宏和SendMessage作用一樣 SendMessage(hListProcess, LVM_INSERTITEM,0,(DWORD)&vitem); //如果用SendMessage,給第一列賦值用LVM_INSERTITEM,其它列用LVM_SETITEM,用ListView同理 vitem.pszText = TEXT("448"); vitem.iItem = 0; vitem.iSubItem = 1; ListView_SetItem(hListProcess, &vitem); vitem.pszText = TEXT("56590000"); vitem.iItem = 0; vitem.iSubItem = 2; ListView_SetItem(hListProcess, &vitem); vitem.pszText = TEXT("000F0000"); vitem.iItem = 0; vitem.iSubItem = 3; ListView_SetItem(hListProcess, &vitem); vitem.pszText = TEXT("winlogon.exe"); vitem.iItem = 1; vitem.iSubItem = 0; //ListView_InsertItem(hListProcess, &vitem); SendMessage(hListProcess, LVM_INSERTITEM,0,(DWORD)&vitem); vitem.pszText = TEXT("456"); vitem.iSubItem = 1; ListView_SetItem(hListProcess, &vitem); vitem.pszText = TEXT("10000000"); vitem.iSubItem = 2; ListView_SetItem(hListProcess, &vitem); vitem.pszText = TEXT("000045800"); vitem.iSubItem = 3; ListView_SetItem(hListProcess, &vitem); } //初始化進程窗口,就是給ListView控件添加列 void initProcessView(HWND hDlg){ LV_COLUMN lv; HWND hListProcess; //初始化,局部變量堆棧中分配,不知道是什么數據所以先清零 memset(&lv,0,sizeof(LV_COLUMN)); //獲取IDC_LIST_PROCESS句柄 hListProcess = GetDlgItem(hDlg,IDC_LIST_PROCESS); //設置整行選中,窗口是windows來管理的無法直接操作,程序能做的只能發送一個消息來讓windows直到該怎么做 SendMessage(hListProcess,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT); //第一列 lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; lv.pszText = TEXT("進程"); //列標題 lv.cx = 150; //列寬 lv.iSubItem = 0; //ListView_InsertColumn(hListProcess, 0, &lv); SendMessage(hListProcess,LVM_INSERTCOLUMN,0,(DWORD)&lv); //第二列 lv.pszText = TEXT("PID"); lv.cx = 90; lv.iSubItem = 1; //ListView_InsertColumn(hListProcess, 1, &lv); SendMessage(hListProcess,LVM_INSERTCOLUMN,1,(DWORD)&lv); //第三列 lv.pszText = TEXT("鏡像基址"); lv.cx = 100; lv.iSubItem = 2; ListView_InsertColumn(hListProcess, 2, &lv); //第四列 lv.pszText = TEXT("鏡像大小"); lv.cx = 100; lv.iSubItem = 3; ListView_InsertColumn(hListProcess, 3, &lv); EnumProcess(hListProcess); } //回調函數 BOOL CALLBACK DialogProc( HWND hwndDlg, // handle to dialog box UINT uMsg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { switch(uMsg) { case WM_INITDIALOG : initProcessView(hwndDlg); //初始化列表 return TRUE; case WM_COMMAND : switch (LOWORD (wParam)) { case IDC_BUTTON_SHOW: return TRUE; case IDC_BUTTON_ABOUT: return TRUE; case IDC_BUTTON_OUT: EndDialog(hwndDlg, 0); return TRUE; } break ; } return FALSE ; } //程序入口 int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrevHinstance, LPSTR lpCmdLine, int nCmdShow ){ INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&icex); //創建對話框窗口 DialogBox( hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, DialogProc ); return 0; }
結果:

3.WM_NOTIFY消息
該消息類型與WM_COMMAND類型相似,都是由子窗口向父窗口發送的消息。
WM_NOTIFY可以包含比WM_COMMAND更豐富的信息
Windows通用組件中有很多消息,都是通過WM_NOTIFY來描述的.
例如:
當點擊按鈕時,按鈕自身的回調函數會將消息轉為WM_COMMAND消息給主窗口的回調函數;
如果是想處理ListView的列的點擊事件,則是通過WM_NOTIFY;
WM_NOTIFY消息參數如下:
wParam:控件ID
lParam:指向一個結構,並且這個結構是可以拓展的,因此比WM_COMMAND能傳遞更多消息
typedef struct tagNMHDR { HWND hwndFrom; //發送通知消息的控件窗口句柄; ->哪個子窗口發的消息 UINT idFrom; //發送通知消息的控件ID值; ->子窗口的哪個控件發過來的 UINT code; //通知碼,如LVM_SELCHANGED; -> 做了那些事:點左鍵、點右鍵、值改變等等 } NMHDR;
這個結構體能滿足一般的要求,但能描述的信息還是有限的
解決方案:對每種不同用途的通知消息都定義另一種結構來表示
typedef struct tagNMLVCACHEHINT { NMHDR hdr; int iFrom; int iTo; } NMLVCACHEHINT, *PNMLVCACHEHINT; typedef struct tagLVDISPINFO { NMHDR hdr; LVITEM item; } NMLVDISPINFO, FAR *LPNMLVDISPINFO; typedef struct _NMLVFINDITEM { NMHDR hdr; int iStart; LVFINDINFO lvfi; } NMLVFINDITEM, *PNMLVFINDITEM;
它們的第一個成員都是NMHDR結構;
相當於c++中的繼承,拓展了NMHDR結構;