1.字符编码
宽字节字符
wchar_t每个字符占2个字节
charmei每个字符占1个字节
wchar_t实际是unsigned short类型,定义时,需要增加“L”,通知编译器按照双字节编译字符串,采用UNICODE(UTF16)编码
例如:
wchat_t * p = L"hello world";
wprintf(L"%s\n",p);
TCHAR
#ifdef UNICODE
typedef wchar_t TCHAR;
#define_TEXT(quote) L##quote
#else
typedef char TCHAR;
#define _TEXT(quote) quote
#endif
打印UNICODE字符
wprintf对UNICODE字符打印支持不完善
在Windows下使用WriteConsole API打印UNICODE字符GetstdHandle
在使用宽字节字符时,提前将属性–语言–符合模式改为否,否则会报错
void Print()
{
wchar_t* p = L"是案的课件撒回家的卡号表示肯定就好看";
wprintf(L"%s", p);
HANDLE hOUT = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出句柄
WriteConsole(hOUT,p,wcslen(p),NULL,NULL);//标准输出句柄、输出缓冲区、输出长度、返回实际输出长度、扩展参数
}
int main()
{
Print();
return 0;
}
wprintf由于对UNICODE字符打印支持不完善,所以输出都是?乱码。
WriteConsole既可以打印UNICODE编码也可以打印DBCS编码。
2.注册窗口类
1.窗口类概念
· 窗口类包含了窗口的各种参数信息的数据结构
· 每个窗口都具有窗口类,基于窗口类创建窗口
· 每个窗口类都具有一个名称,使用前必须注册到系统
2.窗口类分类
· 系统窗口类
系统已经定义好的窗口类,所有应用程序都可以直接使用
· 应用程序全局窗口类
由用户自己定义,当前应用程序所有模块都可以使用
· 应用程序局部窗口类
由用户自己定义,当前应用程序中本模块可以使用。
系统窗口类:不需要程序员注册,直接使用窗口类即可。系统已经注册好了,例如:按钮(BUTTON)、编辑框(EDIT)
int CALLBACK wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
HWND hwnd = CreateWindow(L"Button", L"确认", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, NULL, NULL, hInstance, NULL);//实现系统窗口Button的创建
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG nmsg = { 0 };
while (GetMessage(&nmsg, NULL, 0, 0))
{
TranslateMessage(&nmsg);
DispatchMessageW(&nmsg);
}
return 0;
}
全局已经局部窗口类
RegisterClass(CONST WNDCLASS * IpWndClass);//注册成功后,返回一个数字标识,否则返回0
RegisterClass将所有所有赋值定义好的窗口类写入计算机内核中保存(写入操作系统)
注册窗口类的结构体
typedef struct_WNDCLASS
{
UINT style;//窗口类的风格
WNDPROC IpfnWndProc;//窗口处理函数
int cbClsExtra;//窗口类的附件数据BUFF的大小
int cbWndExtra;//窗口的附件数据BUFF的大小
HINSTANCE hInstance;//当前模块的实例句柄
HICON hIcon;//窗口图标句柄
HCURSOR hCursor;//鼠标句柄
HBRUSH hbrBackground;//绘制窗口背景的画刷句柄
LPCTSTR IpszMenuName;//窗口菜单的资源ID字符串
LPCTSTR IpszClassName;//窗口类的名称
}WNDCLASS,*PWNDCLASS;
- style窗口风格:
应用程序全局窗口类的注册,需要在窗口类的风格中增加CS_GLOBALCLASS,例如:
WNDCLASS wc = {0};
wc.style = ...|CS_GLOBALCLASS;
应用程序局部窗口类,不添加CS_GLOBALCLASS风格,因为局部窗口类拥有全局窗口类所有风格
CS_HREDRAW - 当窗口水平变化时,窗口重新绘制
CS_VREDRAW - 当窗口垂直变化时,窗口重新绘制
CS_DBLCLKS - 允许窗口接收鼠标双镜
CS_NOCLOSE - 窗口没有关闭按钮
3.创建窗口
创建窗口的API: CreateWindow/CreateWindowEX
HWND CreateWindow(
DWORD dwExstyle,//窗口的扩展风格
LPCTSTR IpClassName,//已经注册的窗口类的名称
LPCTSTR IpWindowName,//窗口标题栏的名字
DWORD dwStyle,//窗口的基本风格
int x,//窗口左上角水平坐标的位姿
int y,//窗口左上角垂直坐标的位姿
int nWidth,//窗口的宽度
int nHeight,//窗口的高度
HWND hWndParant,//窗口的父窗口句柄
HMENU hMenu,//窗口菜单句柄
HINSTANCE hInstance,//应用程序实例句柄
LPVOID IpParam //窗口创建时附加参数
);//返回值为窗口句柄
4.消息的概念和作用
- 系统根据传入的窗口名称,在应用程序局部窗口类中查找,如果找到执行2,如果未找到执行3;
- 比较局部窗口类与创建窗口时传入的HINSTANCE变量,如果发现相等,创建和注册的窗口类在同一模块,创建窗口返回,如果不相等,继续执行3(若两者相等说明两者注册和创建在同一进程)
- 在应用程序全局窗口类,如果找到,执行4,如果未找到执行5
- 使用找的窗口类的信息,创建窗口返回
- 在系统窗口类中查找,如果找到创建窗口返回,否则创建窗口失败。
if(找到窗口类)
{
申请一大块内存,将窗口的数据信息存入这块内存。
return 这块内存的句柄;
}
else{return NULL;}
5.子窗口创建过程
-
创建时要设置父窗口句柄
-
创建风格要增加WS_CHILD|WS_VISIBLE
wc.lpfnWndProc = DefWindowProc;//默认处理函数
HWND child1 = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"1", WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, hwnd, NULL, hInstance, NULL);
HWND child2 = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"2", WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 200, 200, 200, hwnd, NULL, hInstance, NULL);
套用父窗口的类,修改处理函数后直接创建
#include <windows.h>
//窗口处理函数
LRESULT CALLBACK test(HWND hwnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
switch (msgID)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd,msgID,wParam,lParam);
}
int CALLBACK wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
//注册窗口类
WNDCLASS wc = { 0 };
wc.cbClsExtra = 0;//申请缓冲区
wc.cbWndExtra = 0;//申请缓冲区
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//窗口背景色
wc.hCursor = NULL;//默认光标
wc.hIcon = NULL;//默认图标
wc.hInstance = hInstance;//实例句柄
wc.lpfnWndProc = test;//窗口处理函数
wc.lpszClassName = (LPCWSTR)L"main";//窗口类名称
wc.lpszMenuName = NULL;//不要菜单
wc.style = CS_HREDRAW | CS_VREDRAW;//窗口水平或竖直方向有变化就重绘窗口
RegisterClass(&wc);//将以上所有赋值写入操作系统
//在内存中创建窗口
HWND hwnd = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"hello world", WS_OVERLAPPEDWINDOW, 100,100, 500, 500, NULL, NULL, hInstance, NULL);
wc.lpfnWndProc = DefWindowProc;//默认处理函数
HWND child1 = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"1", WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, hwnd, NULL, hInstance, NULL);
HWND child2 = CreateWindow((LPCWSTR)L"main", (LPCWSTR)L"2", WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW, 0, 200, 200, 200, hwnd, NULL, hInstance, NULL);
//显示窗口
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
//消息循环
MSG nMSG = { 0 };
while (GetMessage(&nMSG,NULL,0,0))
{
TranslateMessage(&nMSG);
DispatchMessage(&nMSG);//派发消息,将消息交给窗口处理函数处理
}
return 0;
}