首先,Win32是Windows操作系统上的应用程序编程接口(API)之一,它提供了许多函数和工具,用于开发Windows桌面应用程序。在Win32编程中,可以创建一个窗口实例,以实现图形用户界面(GUI)。
#include <windows.h>
/* 函数声明 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
/* 应用程序主函数 */
INT APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szCmdLine, _In_ INT nCmdShow)
{
/* 1.设计一个窗口类
UINT style; // 类风格
WNDPROC lpfnWndProc; // 窗口的处理过程
HINSTANCE hInstance; // 窗口类所在模块的实例句柄
HICON hIcon; // 窗口类的图标
HCURSOR hCursor; // 窗口类的光标
HBRUSH hbrBackground; // 窗口类的背景画刷
LPCWSTR lpszMenuName; // 窗口类的菜单资源名
LPCWSTR lpszClassName; // 窗口类的名称
*/
WNDCLASSEX wcex = { };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = hInstance;
wcex.lpfnWndProc = WndProc;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszClassName = L"New-HackerHK";
wcex.hbrBackground = (HBRUSH)COLOR_WINDOW;
/* 2.注册窗口类 */
if (!RegisterClassEx(&wcex)){
MessageBox(NULL, L"注册窗口类失败!", L"错误", MB_YESNO | MB_ICONERROR);
TerminateProcess(GetCurrentProcess(), 0);
}
// 获取屏幕的宽度和高度
int SCREEN_W = GetSystemMetrics(SM_CXSCREEN);
int SCREEN_H = GetSystemMetrics(SM_CYSCREEN);
// 计算窗口的左上角坐标,使其位于屏幕中心
int WINFROM_W = SCREEN_W - (SCREEN_W / 6);
int WINFROM_H = SCREEN_H - (SCREEN_H / 6);
int WINFROM_X = (SCREEN_W - WINFROM_W) / 2;
int WINFROM_Y = (SCREEN_H - WINFROM_H) / 2;
TCHAR szOutBuff[256];
wsprintf(szOutBuff, L"WINFROM_X:%d,WINFROM_Y:%d,WINFROM_W:%d,WINFROM_H:%d\n", WINFROM_X, WINFROM_Y, WINFROM_W, WINFROM_H);
OutputDebugString((LPCWSTR)szOutBuff);
/* 3.创建窗口
dwExStyle :窗口扩展风格
lpClassName :我们注册的窗口类的名称
lpWindowName:窗口的名称(说白了就是窗口的标题)
dwStyle :窗口创建的风格(跟dwExStyle不同哦)
X :窗口左上角的点位于屏幕的横坐标
Y :窗口左上角的点位于屏幕的纵坐标
nWidth :窗口的宽度
nHeight :窗口的高度
hWndParent :窗口所有者的句柄
hMenu :菜单句柄
hInstance :所在模块的实例句柄
lpParam :在WM_CREATE中进行传递的参数
返回值 :创建成功返回创建的窗口句柄,失败返回NULL
*/
/* 5.应用程序消息循环 */
MSG msg = { 0 };
//在创建窗口时,将窗口样式(dwStyle) 参数设置为 WS_OVERLAPPEDWINDOW 是多种窗口类型的组合 (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)。
HWND hWnd = CreateWindowEx(NULL, L"New-HackerHK", L"Hello,New-HackerHK", WS_OVERLAPPEDWINDOW, WINFROM_X, WINFROM_Y, WINFROM_W, WINFROM_H, NULL, NULL, hInstance, NULL);
if (hWnd == NULL){
MessageBox(NULL, L"在创建窗口时失败!", L"错误", MB_YESNO | MB_ICONERROR);
TerminateProcess(GetCurrentProcess(), 0);
}
else {
/* 4.更新显示窗口
hWnd :显示的窗口句柄
nCmdShow:窗口显示的方式(全屏,最大化窗口,最小化窗口,······)
返回值 :成功返回非0,失败返回0
*/
ShowWindow(hWnd, nCmdShow);
/*
hWnd:更新的窗口
返回值:成功返回非0,失败返回0
*/
UpdateWindow(hWnd);
/* GetMessage 发生错误会返回-1
lpMsg :接收从消息队列中获取的消息
hWnd :接收消息的窗口句柄
wMsgFilterMin:指定被检测的最小消息值
wMsgFilterMax:指定被检测的最大消息值
返回值 :获取错误返回-1,消息为WM_QUIT返回0,其他为非0
*/
while (msg.message != WM_QUIT)
{
//应用程序以此获取对消息队列操作权利,并获取属于自己的消息
//if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
/*
_Out_ LPMSG lpMsg, 消息
_In_opt_ HWND hWnd, 捕获窗口 填NULL代表捕获所有的窗口
_In_ UINT wMsgFilterMin, //最小和最大的过滤的消息 一般填入0
_In_ UINT wMsgFilterMax) //填0代表捕获所有消息
*/
if (GetMessage(&msg, NULL, 0, 0))
{
/*
消息解析()
lpMsg :接收的消息
返回值 :成功返回非0,失败返回0
*/
TranslateMessage(&msg);
/*
* 消息派发(通过USER模块发送到窗口函数)
lpMsg :分发的消息
返回值 :窗口处理过程的返回值
*/
DispatchMessage(&msg);
}
else
{
TCHAR szBuffer[256];
wsprintf(szBuffer, L"Error:%d\0", GetLastError());
OutputDebugString(szBuffer);
}
}
//发送退出消息
PostQuitMessage(0);
}
return (int)msg.wParam;
}
/* 应用程序消息处理回调函数
hWnd :窗口处理过程的窗口句柄
message:消息ID
wParam :附加消息
lParam :附加消息
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
{
//所有xxxWindow为结尾的方法 ,都不会进入到消息队列中,而是直接执行
DestroyWindow(hWnd); //DestroyWindow 发送另一个消息 WM_DESTROY
break;
}
case WM_DESTROY:
{
//发送退出消息
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
包含必要的头文件:你需要包含一些必要的头文件,如windows.h,以便使用Win32 API函数和数据类型。
注册窗口类:使用RegisterClassEx函数注册一个窗口类,该类描述了窗口的外观和行为。你需要提供一个窗口过程函数来处理窗口消息。
创建窗口实例:使用CreateWindowEx函数创建一个窗口实例,并指定该窗口所属的窗口类、窗口标题、初始位置和大小等信息。
处理窗口消息:在窗口过程函数中处理窗口消息,例如响应用户输入、绘制图形等。常见的消息处理包括WM_CREATE(窗口创建时触发)、WM_PAINT(绘制窗口内容时触发)和WM_CLOSE(关闭窗口时触发)。
进入消息循环:在主函数中使用GetMessage或PeekMessage函数来获取并分发窗口消息,直到接收到退出消息为止。