1.控件
系统已经定义窗口类型,相应窗口的处理函数等都已经由系统定义完成。例如编辑框、按钮等。
2.控件创建
不需要注册,直接使用CreateWindow/Ex创建该类窗口。
控件创建时,每个控件都具有一个ID。
3.控件消息
程序和控件之间的交互都是用过消息完成的。
控件的窗口消息:
我们想获取控件的消息或设置控件的状态,程序可以通过SendMessage向控件发送消息(调用控件的处理函数)。
控件的通知消息:
控件有相应的事件发生后,会向所有的父窗口(的窗口处理函数)发生通知消息(WM_COMMAND),父窗口根据通知消息的ID做相应处理。
4.静态框
(1)相关信息
静态框常用语显示文字和图标等,窗口类名称“STATIC“
文字静态框 - 显示文字
图标静态框 - 显示图标,设置SS_ICON/SS_BITMAP
(2)使用
a.创建
CreateWindow/CreateWindowEx
风格:图标静态框使用SS_ICON/SS_BITMAP风格
如果创建图标静态框,那么窗口的名称要设置成图标ID,例如:CreateWindowEx(0, "STATIC", "#101", ... );
b.窗口消息
SendMessage发送到控件即可。
c.通知消息
需要在创建时增加SS_NOTIFY风格。通知消息通过WM_COMMAND消息传递。
wPARAM:LOWORD - 菜单项、加速键、控件ID
HIWORD - 对于菜单项,为0
对于加速键,为1
对于控件,是Notify-Code
lPARAM:对于菜单项、加速键为NULL
对于控件,为控件窗口句柄
相关代码:

#include "stdafx.h" HINSTANCE g_hInstance = 0; //接收当前程序实例句柄 void OnCreate(HWND hWnd) { //静态框添加SS_NOTIFY风格才会发出WM_COMMAND消息 //占用菜单参数作为控件ID CreateWindowEx(0, "STATIC", "hello txt", WS_CHILD | WS_VISIBLE | SS_NOTIFY, 100, 100, 200, 30, hWnd, (HMENU)1001, g_hInstance, NULL); CreateWindowEx(0, "STATIC", "#129", WS_CHILD | WS_VISIBLE | SS_ICON | SS_NOTIFY, 350, 100, 0, 0, hWnd, (HMENU)1002, g_hInstance, NULL); } void OnCommand(HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case 1001: if (STN_CLICKED == HIWORD(wParam)) { MessageBox(hWnd, "点击文字静态框", "Info", MB_OK); } break; case 1002: if (STN_DBLCLK == HIWORD(wParam)) { MessageBox(hWnd, "双击图标静态框", "Info", MB_OK); } break; case ID_REDCROSS: { HICON hRedCross = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON1)); HWND hStatic = GetDlgItem(hWnd, 1001); SendMessage(hStatic, STM_SETICON, (WPARAM)hRedCross, 0); } break; case ID_BLUECROSS: { HICON hBlueCross = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON2)); HWND hStatic = GetDlgItem(hWnd, 1002); SendMessage(hStatic, STM_SETICON, (WPARAM)hBlueCross, 0); } break; } } //窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_COMMAND: OnCommand(hWnd, wParam); break; case WM_CREATE: OnCreate(hWnd); //在WM_CREATE消息中创建子窗口 break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } //注册窗口类 BOOL Register(LPSTR lpClassName, WNDPROC wndProc) { WNDCLASSEX wce = { 0 }; wce.cbSize = sizeof(wce); wce.cbClsExtra = 200; wce.cbClsExtra = 200; wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wce.hCursor = NULL; wce.hIcon = NULL; wce.hIconSm = NULL; wce.hInstance = g_hInstance; wce.lpfnWndProc = wndProc; wce.lpszClassName = lpClassName; wce.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); wce.style = CS_HREDRAW | CS_VREDRAW; ATOM nAtom = RegisterClassEx(&wce); if (0 == nAtom) { return FALSE; } return TRUE; } //创建主窗口 HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName) { HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL); return hWnd; } //显示窗口 void Display(HWND hWnd) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); } //消息循环 void Message() { MSG nMsg = { 0 }; while (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; Register("Main", WndProc); HWND hWnd = CreateMainWindow("Main", "window"); Display(hWnd); Message(); return 0; }
运行结果:
5.按钮
(1)相关信息
根据按钮的方格,分为4类:
下压式按钮:BS_PUSHBUTTON / BS_DEFPUSHBUTTON
分组框:BS_GROUPBOX
复选框:BS_CHECKEDBOX / BS_AUTOCHECKEDBOX
BS_3STATE / BS_AUTO3STATE
单选框:BS_RADIOBUTTON / BS_AUTORADIOBUTTON
(2)下压式按钮
创建按钮
窗口消息
通知消息,通知码BN_CLICKED
(3)分组框
用于界面上的控件分组显示,提高界面友好性
(4)复选框
a.风格和创建
BS_CHECKBOX - 点击选择时,需要自己维护选择状态
BS_AUTOCHECKBOX - 点击选择时,系统自动维护选择状态
b.窗口消息
获取和设置选择状态:
BM_SETCHECK:wPARAM - 具体状态
lPARAM - 没用,必须为0
BM_GETCHECK:wPARAM/lPARAM - 都没有用,必须为0
复选框当前状态通过SendMessage函数的返回值获取
c.通知消息
BN_CLICKED - 按钮被点击
(5)单选框
a.风格和创建
BS_RADIOBUTTON - 自己维护状态
BS_AUTORADIOBUTTON - 系统自动维护状态
b.窗口消息
获取和设置选择状态
BM_SETCHECK
BM_GETCHECK
每组单选框中只能同时有一个被选择
c.通知消息
BN_CLICKED
d.其他
单选框分组,可以使用WS_GROUP风格分组。从当前具有WS_GROUP风格的单选框,
到下一个单选框之前,为一组单选框。
相关代码:

#include "stdafx.h" HINSTANCE g_hInstance = 0; //接收当前程序实例句柄 void OnCreate(HWND hWnd) { CreateWindowEx(0, "BUTTON", "OK", WS_CHILD|WS_VISIBLE |BS_PUSHBUTTON, 50, 50, 100, 40, hWnd, (HMENU)1001, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "GroupBox", WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 30, 30, 300, 450, hWnd, (HMENU)1002, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "CheckBox", WS_VISIBLE|WS_CHILD|BS_CHECKBOX, 50, 100, 200, 30, hWnd, (HMENU)1003, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "AutoCheckBox", WS_VISIBLE|WS_CHILD|BS_AUTOCHECKBOX, 50, 140, 200, 30, hWnd, (HMENU)1004, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "3State", WS_VISIBLE|WS_CHILD|BS_3STATE, 50, 180, 200, 30, hWnd, (HMENU)1005, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "Auto3State", WS_VISIBLE|WS_CHILD|BS_AUTO3STATE, 50, 220, 200, 30, hWnd, (HMENU)1006, g_hInstance, NULL); //从当前具有WS_GROUP风格的单选框开始到下一个具有该风格的单选框之前为一组 CreateWindowEx(0, "BUTTON", "A 奔波儿霸", WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON|WS_GROUP, 50, 260, 200, 20, hWnd, (HMENU)1007, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "B 霸波尔奔", WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, 50, 300, 200, 20, hWnd, (HMENU)1008, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "C 喜洋洋", WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON|WS_GROUP, 50, 340, 200, 20, hWnd, (HMENU)1009, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "D 灰太狼", WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, 50, 380, 200, 20, hWnd, (HMENU)1010, g_hInstance, NULL); CreateWindowEx(0, "BUTTON", "多态按钮", WS_VISIBLE|WS_CHILD|BS_AUTOCHECKBOX|BS_PUSHLIKE, 50, 420, 200, 20, hWnd, (HMENU)1011, g_hInstance, NULL); } void OnCommand(HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case 1005: if (BN_CLICKED == HIWORD(wParam)) { HWND h3State = GetDlgItem(hWnd, 1005); LRESULT nRet = SendMessage(h3State, BM_GETCHECK, 0, 0); if (BST_CHECKED == nRet) { SendMessage(h3State, BM_SETCHECK, BST_INDETERMINATE, 0); } else if (BST_INDETERMINATE == nRet) { SendMessage(h3State, BM_SETCHECK, BST_UNCHECKED, 0); } else { SendMessage(h3State, BM_SETCHECK, BST_CHECKED, 0); } } break; case 1003: if (BN_CLICKED == HIWORD(wParam)) { HWND hCheck = GetDlgItem(hWnd, 1003); LRESULT nRet = SendMessage(hCheck, BM_GETCHECK, 0, 0); if (BST_CHECKED == nRet) { SendMessage(hCheck, BM_SETCHECK, BST_UNCHECKED, 0); } else { SendMessage(hCheck, BM_SETCHECK, BST_CHECKED, 0); } } break; case 1001: if (BN_CLICKED == HIWORD(wParam)) { MessageBox(hWnd, "点击OK", "Info", MB_OK); } break; } } //窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_COMMAND: OnCommand(hWnd, wParam); break; case WM_CREATE: OnCreate(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } //注册窗口类 BOOL Register(LPSTR lpClassName, WNDPROC wndProc) { WNDCLASSEX wce = { 0 }; wce.cbSize = sizeof(wce); wce.cbClsExtra = 200; wce.cbClsExtra = 200; wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wce.hCursor = NULL; wce.hIcon = NULL; wce.hIconSm = NULL; wce.hInstance = g_hInstance; wce.lpfnWndProc = wndProc; wce.lpszClassName = lpClassName; wce.lpszMenuName = NULL; wce.style = CS_HREDRAW | CS_VREDRAW; ATOM nAtom = RegisterClassEx(&wce); if (0 == nAtom) { return FALSE; } return TRUE; } //创建主窗口 HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName) { HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hInstance, NULL); return hWnd; } //显示窗口 void Display(HWND hWnd) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); } //消息循环 void Message() { MSG nMsg = { 0 }; while (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; Register("Main", WndProc); HWND hWnd = CreateMainWindow("Main", "window"); Display(hWnd); Message(); return 0; }
运行结果: