win32基础界面开发

项目创建

在VS2022中选择空项目,点击下一步,输入相关信息后点击创建

用鼠标右键点击右边解决方案下的项目名字,打开属性页,将配置改为所有配置平台改为所有平台

接着找到配置属性中的链接器中的系统,将子系统控制台 (/SUBSYSTEM:CONSOLE)改成窗口 (/SUBSYSTEM:WINDOWS),点击确定。

新建一个main.c源文件:

#ifndef UNICODE
#define UNICODE
#endif

启用UNICODE调用unicode版本的函数

引入头文件:

#include <windows.h>

win32 gui 应用的入口函数:

int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE _,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd
) {
return 0;
}

其中的_In_或者_In_opt_或者_Out_都是微软自己拓展的东西,给预处理器和人看的,经过预处理器处理后不会留下了,_In_表示是输入参数,_Out_是输出参数,_In_opt_ 表示是可选的输入参数。

参考链接: winMain函数(winbase.h)

注册 Window 类

想要显示一个window,首先需要注册Window类。

注册窗口类的第一步是使用窗口类信息填充WNDCLASSEXW结构。并该将结构传递给 RegisterClassExW函数。

const wchar_t MainClassName[] = L"Goodbye";
WNDCLASSEXW mainWndClass;
// 不初始化的话,可能会导致RegisterClassExW调用失败
memset(&mainWndClass, 0, sizeof(WNDCLASSEXW));
mainWndClass.hInstance = instance;
// 窗口消息处理函数
mainWndClass.lpfnWndProc = MainWndProc;
mainWndClass.cbSize = sizeof(WNDCLASSEXW);
mainWndClass.lpszClassName = MainClassName;
mainWndClass.style = CS_HREDRAW|CS_VREDRAW;
// 没有这一行代码的话,改变窗口大小会变成黑色
mainWndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
if (0 == RegisterClassExW(&mainWndClass)) {
ErrorExit(L"RegisterClassExW");
}

每一个window都有自己的lpszClassName(类名),每个window的类名都不一样。

cbSize设置为 sizeof(WNDCLASSEXW)。 在调用 GetClassInfoExW 函数之前,请务必设置此成员。

style设置为CS_HREDRAW|CS_VREDRAW表示窗口水平和垂直方向大小发生变化时重绘窗口。

hbrBackground设置为(HBRUSH)COLOR_WINDOWFRAME是为了给窗口重绘时指定一个背景色,不然窗口大小改变时,会变成黑色。

消息处理

当消息到达的时候,系统会调用WNDCLASSEXWlpfnWndProc指针所指向的函数来处理消息,这个函数的定义如下:

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

这是最基础的消息处理,可以选择感兴趣的消息增加对应的case。

错误处理

ErrorExit汇报出错的函数以及系统错误代码,其实现是从检索Last-Error代码复制过来的。

#include <strsafe.h>
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}

注册窗口

RegisterClassExW函数向系统注册我们的window成功时,我们才能去创建出这个窗口。RegisterClassExW注册成功时返回一个HWND句柄,失败时返回0。

创建窗口及消息分发

hwnd = CreateWindowExW(
WS_EX_LTRREADING,
MainClassName,
L"再见咯",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
instance,
NULL
);
if (NULL == hwnd) {
ErrorExit(L"CreateWindowExW");
}
ShowWindow(hwnd, showCmd);
while (GetMessageW(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}

通过CreateWindowExW创建我们的窗口,参数的具体意思看官方的文档,这里就不介绍了。在创建成功后通过调用ShowWindow来显示我们的窗口,之后要建立一个while循环来读取系统消息队列里的消息,并通过TranslateMessage来将虚拟密钥消息转换为字符消息,字符消息将发布到调用线程的消息队列,下次线程调用 GetMessageWPeekMessageW 函数时要读取。然后是用DispatchMessageW将消息调度到窗口过程。

最后

至此,一个简单的基本窗口程序就算是成功建立了。全部代码如下:

// main.c
#ifndef UNICODE
#define UNICODE
#endif
#include<windows.h>
#include<strsafe.h>
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
int WINAPI WinMain(
_In_ HINSTANCE instance,
_In_opt_ HINSTANCE _,
_In_ LPSTR cmdLine,
_In_ int showCmd
) {
const wchar_t MainClassName[] = L"Goodbye";
WNDCLASSEXW mainWndClass;
MSG msg;
HWND hwnd;
memset(&mainWndClass, 0, sizeof(WNDCLASSEXW));
mainWndClass.hInstance = instance;
mainWndClass.lpfnWndProc = MainWndProc;
mainWndClass.cbSize = sizeof(WNDCLASSEXW);
mainWndClass.lpszClassName = MainClassName;
mainWndClass.style = CS_HREDRAW|CS_VREDRAW;
// 没有这一行代码的话,改变窗口大小会变成黑色
mainWndClass.hbrBackground = (HBRUSH)COLOR_WINDOWFRAME;
if (0 == RegisterClassExW(&mainWndClass)) {
ErrorExit(L"RegisterClassExW");
}
hwnd = CreateWindowExW(
WS_EX_LTRREADING,
MainClassName,
L"再见咯",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
instance,
NULL
);
if (NULL == hwnd) {
ErrorExit(L"CreateWindowExW");
}
ShowWindow(hwnd, showCmd);
while (GetMessageW(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

本文作者:梅花Q

本文链接:https://www.cnblogs.com/ReginaQ/p/17437933.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   梅花Q  阅读(270)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 故梦(Cover 橙翼) 双笙(陈元汐)
故梦(Cover 橙翼) - 双笙(陈元汐)
00:00 / 00:00
An audio error has occurred.

作词 : 腾云驾雾琉璃仙

作曲 : 千年破晓

编曲 : 千年破晓

原唱:橙翼

翻唱:双笙

旧忆就像一扇窗

推开了就再难合上

谁踩过枯枝轻响

萤火绘着画屏香

为谁拢一袖芬芳

红叶的信笺情意绵长

他说就这样去流浪

到美丽的地方

谁的歌声轻轻、轻轻唱

谁的泪水静静淌

那些年华都付作过往

他们偎依着彼此说好要面对风浪

又是一地枯黄

枫叶红了满面秋霜

这场故梦里

人生如戏唱

还有谁登场

昏黄烛火轻摇晃

大红盖头下谁彷徨

流泪的花和荣喜堂

静静放在一旁

回忆像默片播放

刻下一寸一寸旧时光

他说就这样去流浪

到美丽的地方

谁的歌声轻轻、轻轻唱

谁的泪水静静淌

愿化一双鸟儿去飞翔

任身后哭嚎嘶喊着也追不上

又一年七月晚风凉

斜阳渐矮只影长

这场故梦里

孤桨声远荡

去他乡 遗忘