按钮
1.Windows窗口由特点可分为两大类
一类表明窗口和其他窗口的关系:
WS_OVERLAPED 重叠窗口
WS_POPPUP 弹出窗口
WS_CHILD 子窗口
另一类表明窗口自身外观特征:
WS_BORDER 边框
WS_CAPTION 标题
2.窗口控件:
窗口类名 控件名称
WC_BUTTON 按钮
WC_STATIC 静态文本
WC_COMBOBOX 复合框
WC_EDIT 编辑框
WC_LISTBOX 列表框
WC_SCROLLBAR 滚动条
3.通用控件:
WC_LISTVIEW 列表框控件
WC_TREEVIEW 树控件
WC_TABCONTROL tab控件
4.子控件通知父窗口一些事件,例如子控件被点击,需要通过以下两类消息
标准控件的消息:WM_COMMAND
通用控件的消息:WM_NOTIFY
#include <Windows.h>
#include <CommCtrl.h>
//回调函数
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
static HINSTANCE hInstance = GetModuleHandleW(NULL);//获取当前程序的实例句柄
switch (uMsg)
{
case WM_CREATE:
CreateWindowW(WC_BUTTON, L"按钮1", WS_CHILD | WS_VISIBLE, 10, 10, 120, 40, hwnd, (HMENU)0X100, hInstance, 0);
CreateWindowW(WC_BUTTON, L"按钮2", WS_CHILD | WS_VISIBLE, 10, 100, 120, 40, hwnd, (HMENU)0X101, hInstance, 0);
CreateWindowW(WC_EDIT, L"文本框", WS_CHILD | WS_BORDER | WS_VISIBLE, 10, 200, 320, 80, hwnd, (HMENU)0X102, hInstance, 0);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
PostQuitMessage(0); //该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息
break;
case WM_COMMAND:
//按钮是标准控件,所以用WM_COMMAND接受消息
{
WORD ConTrlId = LOWORD(wParam);//wParam占两个字节,LOWORD()返回低字节数据
if (ConTrlId == 0X100)
{
MessageBoxW(hwnd, L"按钮1被点击了!", L"提示", MB_OK);
}
else if (ConTrlId == 0X101)
{
MessageBoxW(hwnd, L"按钮2被点击了!", L"提示", MB_OK);
}
break;
}
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
//1.注册窗口类
WNDCLASSW myWndClass{ 0 };
myWndClass.lpfnWndProc = WindowProc;
myWndClass.lpszClassName = L"Allure_Love";
//2.创建窗口类
RegisterClassW(&myWndClass);
//3.创建窗口
HWND hwnd = CreateWindowW(
myWndClass.lpszClassName,
L"Allure_Love",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
hInstance,
0
);
//4.显示窗口
ShowWindow(hwnd, SW_SHOWNORMAL);
//5.获取消息
MSG msg{ 0 };
while (GetMessageW(&msg, 0, 0, 0))
{
DispatchMessageW(&msg);
}
return 0;
}
该代码来自51hook
捕获子窗口按钮消息
我们写了一个switch-case语句来输出捕获到的消息
发现除了这三个按钮所在区域,其他区域单击鼠标左键均能捕获到消息
这是因为按钮是一种特殊的窗体,并不需要提供单独的窗口回调函数
当按钮有事件产生时,会给父窗口消息处理程序发送一个WM_COMMAND消息
具体如下图所示:
就是说,按钮产生的消息,最后都会传到父窗口的消息处理函数中,而消息的类型最后都会转换为WM_COMMAND类型
所以在switch-case语句中还需要加入一个case语句:通过WM_COMMAND类型的消息来捕获按钮的消息
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case 1001:
MessageBox(hwnd,"Hello Button 1","Demo",MB_OK);
return 0;
case 1002:
MessageBox(hwnd,"Hello Button 2","Demo",MB_OK);
return 0;
case 1003:
MessageBox(hwnd,"Hello Button 3","Demo",MB_OK);
return 0;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
理论内容参考滴水逆向