windows消息

消息机制

主要的三个动态链接库 内核(KERNEL32.DLL)用户(User32.DLL) 窗口管理(GDI32.DLL)。windows程序运行时通过一个“动态链接”进程与windows接口,每个EXE包含它所需要的各个动态链接库以及库中函数的reference引用地址。当exe被装入内存后,程序中函数调用都被解析成DLL函数入口的指针,同时这些调用函数也被装入内存。

链接生成exe时会链接编程环境提供的特殊“导入库”,其包含所有windows函数调用要碰到的动态链接库的名字及引用信息。链接程序利用这些信息构建exe文件中的表格,当装入程序时windows通过这些表格解析windows函数调用。

#include<windwos.h>

int 
WINAPI  // 即 __stdcall
WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        PSTR szCmdLine, // 命令行参数
        int iCmdShow) { // 程序的最初显示
    return 0;
}

windows.h 囊括了其他几个重要头文件

WINDEF.H    基本数据类型定义
WINNT.H     支持 Unicode 的类型定义,包含了CTYPE.H
	typedef char CHAR;
	typedef wchar_t WCHAR;
	
	字符串指针类型
	typedef CHAR *PCHAR, *LPCH, *PCH;
	typedef CONST CHAR *LPCCH, *PCCH;
	
	宽字符串指针类型
    typedef WCHAR *PWCHAR, *LPWCH, *PWCH;
    typedef CONST WCHAR *LPCWCH, *PCWCH;
    
WINBASE.H   内核函数
WINUSER.H   用户界面函数
WINGDI.H    图形设备接口函数

Unicode

在win中使用 wchar_t 表示宽字符,在 WCHAR.H 中 typedef unsigned short wchar_t;

定义一个单个宽字符的变量

wchar_t c = 'A'; // 变量 c 为 0x0041,Intel使用小端存储,故在内存中为 0x41 0x00
wchar_t *p = L"Hello!"; // L紧接着字符串表示这是一个宽字符串,末端有一个两字节的'\0'表示结束
sizeof(p); // 14
p[1]; // 'e' 0x0065

字符串 "hello!" 在内存中

0x0048 0x0065 0x006c 0x006c 0x006f 0x0021
48 00 65 00 6c 00 6c 00 6f 00 21 00       在内存中的真正存储

使用strlen时会将第二个字节当作字符结束符号,所以对于宽字符应该使用特殊函数,定义在STRING.H和WCHAR.H下的 wcslen

size_t __cdecl strlen(const char*);
size_t __cdecl wcslen(const wchar_t*);

wcslen(p); // 6 返回字符个数

当在Unicode和非Unicode环境下时将不同的函数、类型定义为通用函数、类型

// _UNICODE
#define _tcslen wcslen
typedef wchar_t TCHAR;
#define __T(x) L##x // 相当模糊的语法使字母L与宏参数拼接在一起

// not _UNICODE
#define _tcslen strlen
typedef char TCHAR;
#define __T(x) x

// 更通用的宏
#define _T(x) __T(x)
#define _TEXT(x) __T(x)

_TEXT("Hello!") // 如果定义 _UNICODE 则解释为宽字符,否则解释为普通字符

TCHAR

以 w 开头表示宽字符,T 开头表示通用字符

#ifdef UNICODE
typedef WCHAR TCHAR, *PTCHAR;
typedef LPWSTR LPTCH, PTCH, PTSTR, LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef char TCHAR, *PTCHAR;
typedef LPSTR LPTCH, PTCH, PTSTR, LPTSTR;
typedef LPCSTR LPCTSTR;
#endif

#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif

// 更通用的c字符串函数
lstrlen, lstrcpy, lstrcpyn, lstrcat, lstrcmp, lstrcmpi

win32中字符串输入输出函数都需要使用格式兼容版本,sprintf -> vsprintf 等。

窗口与消息-窗口的创建

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	PSTR szCmdLine,
	int iCmdShow)
{
	static TCHAR szAppName[] = TEXT("HelloWin");
	WNDCLASS wndclass;
	HWND hwnd;
	MSG msg;

    // 创建窗口类
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//GetStockObject 获取图形对象
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;

    // 注册窗口类
	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("regest windwos class failed!"), szAppName, MB_ICONERROR);
		return 0;
	}

    // 创建窗口
	hwnd = CreateWindow(szAppName,  // 窗口类名称
		TEXT("The Hello Program"),  // 标题
		WS_OVERLAPPEDWINDOW,        // 风格,窗口格式。此处使用的是常见的通过位运算符合的类型
		CW_USEDEFAULT,              // 初始x坐标,相对屏幕左上角
		CW_USEDEFAULT,              // 初始y坐标,使用的是默认值
		CW_USEDEFAULT,              // 初始x方向尺寸,窗口初始宽度
		CW_USEDEFAULT,              // 初始y方向尺寸
		NULL,                       // 父窗口句柄,子窗口总是在父窗口前
		NULL,                       // 窗口菜单句柄
		hInstance,                  // 程序实例句柄
		NULL);                      // 创建参数

        
        
	// 显示窗口,第二个参数决定窗口在屏幕中的初始显示形式 
    // 正常   SW_SHOWNORMAL
    // 最小化 SW_SHOWMAXIMIZED
    // 最大化 SW_SHOWMINNOACTIVE
	ShowWindow(hwnd, iCmdShow);
	// 指示窗口对自身进行重绘,向窗口过程发送一条 WM_PAINT 消息
    UpdateWindow(hwnd);
    
    
	// win为每个程序维护了一个消息队列,输入事件发生后win会将这些事件转化为“消息”
    // 从消息队列中检索,当message字段不为 WM_QUIT 时返回非0值,否则返回0
	while (GetMessage(&msg, 
                      NULL, 
                      0, 
                      0))
	{
        // 翻译一些键盘消息
		TranslateMessage(&msg);
        // 将消息发送给窗口过程
		DispatchMessage(&msg);
	}

	return msg.wParam;//参数通常为 0
}

/************************* 窗口过程 *************************/

// win prock :处理消息的函数。这4个参数与Message结构体的前4个参数一一对应
LRESULT CALLBACK WndProc(HWND hwnd, // 接受消息的窗口的句柄
	UINT message,    // 标识消息的数字,WINUSER.H中定义各种以WM开头的标识符
	WPARAM wParam,
	LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch (message)
	{
     // 调用 CreateWindow 函数创建窗口时生成此消息
	case WM_CREATE:
		MessageBox(hwnd, TEXT("创建成功"), TEXT("title"), MB_DEFBUTTON1);
		return 0;

     /*
     当窗口的客户区的部分或全部“无效”且需要“更新”时,应用得到此通知,意味着窗口需要重绘。
     何时客户区无效?
     首次创建时整个客户区都是无效的,因为此时应用尚未在该窗口上绘制任何东西。第一条WM_PAINT 消息通常在UpdateWindow时出现。
     调整窗口大小时客户区也会变得无效,此后窗口过程接收到一条 WM_PAINT 消息。
     最小化最大化、拖动窗口发生遮盖时都会引起无效。
     */
	case WM_PAINT://DefWindowProc 中的默认处理就是简单调用 BeginPaint EndPaint

         // 表明窗口绘画开始,第二个参数是指向PAINTSTRUCT结构的指针
         // 返回一个设备环境句柄,指物理输出设备机器驱动。使用它只能在客户区内绘制
		hdc = BeginPaint(hwnd, &ps);
            
         // 获取窗口客户区的尺寸,设置rect结构体中的 left top right bottom,left top总为0,right bottom为像素个数
		GetClientRect(hwnd, &rect);
         // 显示一个文本字符串
		DrawText(hdc, 
                 TEXT("Hello, win32!"), 
                 -1,  // 表示文本字符串以0结尾
                 &rect, 
                 DT_SINGLELINE | DT_CENTER | DT_VCENTER);//规定格式
		
         // 结束窗口绘画,释放 hdc
         EndPaint(hwnd, &ps);
		return 0;
    // 窗口大小发生变化,低位字宽度、高位字高度        
     case WM_SIZE:
         cxClient = LOWORD(lParam);
         cyClient = HIWORD(lParam);

	case WM_DESTROY:
         // 将“退出”消息 WM_QUIT 插入消息队列
		PostQuitMessage(0);
		return 0;

	default:
		break;
	}
           // 执行默认消息处理,不进行处理的消息都必须传给此函数。必须要有,否则结束程序等功能无法进行
	return DefWindowProc(hwnd, message, wParam, lParam);
}

大写标识符前缀

前缀 常量
CS 类窗口风格
CW 创建窗口选项
DT 文本绘制选项
IDI 图标的ID号
IDC 光标的ID号
MB 消息框选项
SND 声音选项
WM 窗口消息
WS 窗口风格
结构 含义
MSG 消息结构
WNDCLASS 窗口类结构
PAINTSTRUCT 绘制结构
RECT 矩形结构

句柄

标识符 含义
HINSTANCE 实例句柄——程序本身
HWND 窗口句柄
HDC 设备句柄本身

匈牙利命名法

前缀:

前缀 数据类型
c char / WCHAR / TCHAR
by BYTE
cb 字节数
n short
i int
x,y int x坐标 y坐标
cx, cy int x或y的长度,c表示count
B f BOOL / flag
w WORD (usigned int)
l LONG
dw DWORD
fn 函数
s 字符串
sz 以零结束的字符串
h 句柄
hbr 画刷的句柄 handle to a brush
p lp 指针

常见结构体

窗口类

typedef struct tagWNDCLASSW {
    UINT        style; // 可选 CS_VREDRAW | CS_DBLCLKS | CS_NOCLOSE
    WNDPROC     lpfnWndProc; // 窗口函数
    // 用于在类结构和窗口结构中预留一些额外的空间
    int         cbClsExtra;
    int         cbWndExtra;
    // 应用程序的实例句柄
    HINSTANCE   hInstance;
    HICON       hIcon;//配合 LoadIcon(程序实例句柄, 图标标识);
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;//填充背景色
    LPCWSTR     lpszMenuName;//菜单栏
    LPCWSTR     lpszClassName; // 窗口类名称
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;

typedef WNDCLASSW WNDCLASS;

消息类

typedef struct tagMSG {
    HWND        hwnd;     // 消息指向的窗口
    UINT        message;  // 消息标识符
    WPARAM      wParam;   // 消息参数,取决于具体消息
    LPARAM      lParam;   // 另一个消息参数,取决于具体消息
    DWORD       time;     // 进入消息队列的事件
    POINT       pt;       // 消息进入消息队列时鼠标指针的位置
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

typedef struct tagPOINT
{
    LONG  x;
    LONG  y;
} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;
posted @ 2022-07-28 16:03  某某人8265  阅读(50)  评论(0编辑  收藏  举报