最小的一个窗口
#include "windows.h"
HINSTANCE g_hInstance;
LRESULT CALLBACK MainWndProc(_In_ HWND hWnd,_In_ UINT uMsg,_In_ WPARAM wParam,_In_ LPARAM lParam)
{
//每一个发给这个窗体的消息,通过不同的uMsg消息来做不同的动作,wParam和lParam保存的是这个消息的具体参数
switch(uMsg)
{
case WM_CREATE:
//这里可以添加创建时的界面选项,不要做耗时操作。
break;
case WM_CLOSE:
break;
case WM_COMMAND:
break;
case WM_LBUTTONDOWN:
MessageBox(0,"单击后的效果","Title",MB_OK);
break;
case WM_DESTROY:
PostQuitMessage(0);//按关闭按钮后,向GetMessage发送一个关闭的消息,然他退出循环,结束进程
break;
default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
g_hInstance = hInstance;
WNDCLASS MyWcs= {};
MyWcs.lpszClassName = "LpszClassName";
MyWcs.lpfnWndProc = MainWndProc;////这里定义消息处理函数 很重要
MyWcs.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH+2);
MyWcs.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&MyWcs);//注册为窗口类
HWND hWnd = CreateWindow(
"LpszClassName", // 这个名字要和上面定义的lpszClassName名字一致
"Sample_Tile", // title-bar string
WS_OVERLAPPEDWINDOW, // top-level window
CW_USEDEFAULT, // default horizontal position
CW_USEDEFAULT, // default vertical position
290, // default width
500, // default height
(HWND) NULL, // no owner window
(HMENU) NULL, // use class menu
hInstance, // handle to application instance
(LPVOID) NULL); // no window-creation data
ShowWindow(hWnd,SW_SHOW);//展示窗口,不不展示的话你看不到图案,程序会在后台运行
MSG msg = {};
while (GetMessage(&msg,NULL,NULL,NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
以上就是一个最基本窗体了,最重要的是以下几步
1.定义窗口类:定义了这个类的回调函数,也就是说使用这个类创建的窗体的消息由这里设置的函数处理。这个类控制着这个窗口的样式,比如颜色,背景,风格等等,这个窗口类可以多次使用。
2.创建窗口:现在你就可以使用上面定义好的类,来创建一个窗口,可以控制窗口出现的位置,大小和一些其他选项
3.创建循环接收消息:因为Windows是消息机制,循环接收发给控件的消息,我们就可以处理这些消息,这些消息比如鼠标点击了窗体,键盘按下了某个键,或者点击了那个按钮,这些都是不同的消息类型
下面是使用win32控制计算机的模拟按键
这里只贴核心代码,其他都一样
LRESULT CALLBACK OnWndCommand(_In_ HWND hwnd,_In_ UINT uMsg, _In_ WPARAM wParam,_In_ LPARAM lParam)
{
switch (HIWORD(wParam))// wParam高2位保存的是通知码,低2位保存的是控件ID
{
case BN_CLICKED:
{
switch (LOWORD(wParam))
{
case 0x1000:
case 0x1001:
case 0x1002:
{
HWND hCalc = FindWindowA(NULL,"计算器");
if(!hCalc)
{
WinExec("calc.exe",SW_SHOW);
hCalc = FindWindowA(NULL,"计算器");
}
SendMessage(hCalc,WM_COMMAND,wParam-0xF7D,0);
return true;
}
}
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
消息循环中这样写
case WM_COMMAND:
return OnWndCommand(hWnd, uMsg, wParam, lParam);
按钮事件是WM_COMMAND来处理https://docs.microsoft.com/en-us/windows/win32/menurc/wm-command
wParam高2位保存的是通知码,低2位保存的是控件ID
每个按钮能处理详细信息,注意看Notification(通知码类型)https://docs.microsoft.com/en-us/windows/win32/controls/individual-control-info
根据wParam的高两位看是否是控件信息,再看wParam的低两位,代表是谁发出的这个消息。
接着我们就可以处理他了
处理的时候我FindWindowA
查看有没有计算器处于打开状态,没有就开一个
最重要的一步是模拟给他发消息,就像自己给自己发一样
SendMessage(hCalc,WM_COMMAND,83,0);
SendMessage MSDN https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage
上面这句理解为 我给hCalc 这个程序的控件ID为83的控件发送了一个WM_COMMAND消息
最后依次找到找到他们的控件ID,就能完全模拟计算器发包了