创建窗口:
#include <Windows.h>
// 窗口处理函数(自定义处理消息)
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msgID, wParam, lParam);
}
return 0;
}
// 入口函数
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// 注册窗口类
WNDCLASS wc = { 0 };
wc.cbClsExtra = 0; // 申请额外类存储空间
wc.cbWndExtra = 0; // 申请额外窗口存储空间
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 背景色
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 加载箭头光标
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 加载默认图标
wc.hInstance = hInstance; // 实例句柄
wc.lpfnWndProc = WndProc; // 窗口处理函数
wc.lpszClassName = L"Main"; // 窗口类名
wc.lpszMenuName = NULL; // 菜单资源名称
wc.style = CS_HREDRAW | CS_VREDRAW; // 类样式
if (!RegisterClass(&wc)) // 注册窗口类
{
MessageBox(NULL, L"窗口注册失败!", L"错误", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// 创建窗口
HWND hWnd = CreateWindow(L"Main", L"window", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hInstance, NULL);
if (hWnd == NULL) // 创建窗口失败检查
{
MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// 显示窗口
ShowWindow(hWnd, nCmdShow);
// 刷新窗口
UpdateWindow(hWnd);
// 消息循环
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0)) // 获取消息
{
TranslateMessage(&msg); // 翻译消息
DispatchMessage(&msg); // 分发消息
}
return (int)msg.wParam; // 返回退出码
}
上面是一个windows程序界面启动时的最简单的代码,包含了对于窗口的初始化设置以及窗口的创建、显示、刷新以及消息的处理
注册窗口类
- 注册窗口类:包含了各种参数的数据结构
- 每一个窗口都具有窗口类,基于窗口类创建窗口
- 每一个窗口类都有窗口名称,使用前必须注册到系统 (必须存入内存)
窗口类的结构体:
窗口创建
**creatwindows /creatwindowsEX
创建子窗口
- 创建时需要设置父窗口句柄
- 创建风格要增加WS_CHILD|WS_VISIBLE
宽字节字符串:
我们先来看看数据的编码
数据编码从最初的
asc 128bit ————> ascii 256bit ————>DBCS 单双字节混合编码
————> Unicode(万国码) 双字节编码
所有我们这里的宽字节字符串 w_char其实也就是双字节类型的
我们来使用一下直接打印出单字节的数据试试:
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
void C_char()
{
const char* pszText = "hello char";
printf("%s\n", pszText);
}
void W_char()
{
const wchar_t* pszText = L"hello w_char";
int len = wcslen(pszText);
wprintf(L"%s\n%d\n", pszText, len);
}
int main()
{
W_char();
C_char();
getchar();
return 0;
}
假如不知道是不是使用wchar_t or char 那就直接使用Tchar tchar会去检测是否有Unicode编码,假如有就在会转化为wchar,没有就直接转化为char
同时在打印的过程中也可以直接使用__TEXT() 它会根据是否是wchar 来是否添加 L 在打印的字符串之前
消息(message)
Windows下面的消息的组成是:
窗口句柄
消息ID
消息的两个参数
消息的产生时间
消息产生时的鼠标位置
这里是windows下对应的数据结构对应的结构体
首先我们来看看为什么,我们会需要最后实现一个消息循环的情况
我们先来看看我们GetMessage得到的数据其实也就是上面对应的六个参数的数据,然后我们通过TranslateMessage函数对于得到的消息进行翻译(这里我们先不讨论翻译的事情)
为什么我们在自己写了一个窗口处理函数之后,我们就不再需要对于进程进行kill?
这至少说一个问题,DispatchMessage函数是直接去到我们的自定义的WndProc也就是窗口处理函数的
这里其实实现的就是函数的回调
DispatchMessage函数其实是首先获取GetMessage得到的消息句柄,从而获取到Main函数对应的内存空间去回调WndProc函数,实现一个窗口的处理过程
这里也说明了一个问题:为什么我们的WndProc也就是我们的窗口处理函数为什么要设置四个参数了,分别就是对应的handle,message ID ,wParam , lParam .
同时这里,我们介绍一下在WndProc中的DefwindowsProc函数:假如我们的msgID不符合我们的case的条件,就直接返回给这个DefWindowsProc函数,这个函数会使用默认的操作对于符合其msgID的操作
浅谈消息
GetMessage:
这个是GetMessage函数对应的参数和,参数的意义
其中的第一个也就是我们之前定义的msg 数据结构变量的参数 ,其中包含了六个数据 ,第二个 hWnd 是对应窗口的句柄,它可以细节到一个类中的某一个窗口,设置为NULL,则会获取类中的全部窗口句柄,后面两个参数则设置的是获取消息的最大小ID,设置为0 则无限制
这里我们解释一下,为什么在我们的消息处理函数的位置要添加了函数之后才能进行正常的退出过程
PostQuitMessage(0);
break;
其实GetMessage函数是在当获取的消息为WM_QUIT的时候才会将返回值设置为0,才能通过我们的while的消息循环,所有由此我们可以知道的是PostQuitMessage函数其实是在我们的GetMessage获取的类中添加了一个WM_QUIT的退出参数实现了退出
TranslateMessage函数
将可见的按键字符转为字符消息,假如不是按键消息,不做处理
标签:窗口,函数,day02,char,消息,wc,NULL
From: https://www.cnblogs.com/ovo-fisherman/p/18145799