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结构;