Win 32 编程
程序分类
控制台应用程序(DOS 程序)
本质上是一个DOS
程序,本身没有窗口,通过Windows DOS
窗口执行
窗口程序
拥有自己的窗口,可以与用户交互
库程序
存放代码数据的程序,执行文件可以从中取出代码执行和获取数据
- 静态库程序:扩展名
lib
,在编译链接程序时,将代码放入到执行文件中,无法执行 ( 没有入口函数 ) - 动态库程序:扩展名
dll
,执行文件时从中获取代码,不能独立运行,需要依附其他程序运行 ( 有入口函数 )
编译工具
编译器cl.exe
:将源代码编译成目标代码.obj
链接器link.exe
:将目标代码、库链接生成最终文件
资源编译器rc.exe
:( .rc ) 将资源编译,最终通过链接器存入最终文件 ( 一种脚本语言 )
库函数
kernel32.dll
:提供了核心的API
,例如进程、线程、内存管理等
user32.dll
:提供了窗口、消息等API
gdi32.dll
:绘图相关的API
头文件
windows.h
:所有Windows
头文件的集合
windef.h
:Windows
数据类型 ( typdef
对基本数据类型取别名实现的 )
winbase.h
:kernel32
的API
wingdi.h
:gdi32
的API
winuser.h
:user32
的API
winnt.h
:Unicode
字符集支持
一般写一个
Windows.h
即可
编译过程
1 |
|
宽字节字符
wchar_t
每个字符占两个字节,其本质上是unsigned short
类型,定义时,需要增加 “L” ,通知编译器按照双字节编译字符串,采用Unicode
编码,同时对宽字节字符串操作时需要使用相关支持宽字节的函数。wprintf
对Unicode
字符打印支持并不完善,在Windows
下使用WriteConsole
进行输出。
窗口类
概念
-
窗口类包含了窗口的各种参数信息的数据结构
-
每个窗口都具有窗口类,基于窗口类创建窗口
-
每个窗口类都具有一个名称,使用前必须注册到系统
分类
系统窗口类:系统已经定义好的窗口类,所有应用程序都可以直接使用
应用程序全局窗口类:由用户自己定义,当前应用程序所有模块都可以直接使用
应用程序局部窗口类:由用户自己定义,当前应用程序中本模块可以使用
资源类
菜单
分类
窗口的顶层菜单
弹出式菜单
系统菜单
HMENU
类型( 菜单句柄 )表示菜单,ID
表示菜单项。
1 |
|
加载菜单资源
1>注册窗口类时设置菜单
2>创建窗口传参设置菜单
3>在主窗口WM_CREATE消息中利用SetMenu
函数设置菜单
图标
一个图标文件中可以有多个不同大小的图标
加载
1 |
|
光标
光标的大小默认是32X32
像素,每个光标有HotSpot
,是当前鼠标的热点
加载资源
1 |
|
必须放在消息处理函数中定义
1
2
3
HCURSOR SetCursor(
HCURSOR hCursor // handle to cursor
);
WM_SETCURSOR
消息参数
wPARAM
当前使用的光标句柄
lPARAM
:LOWORD
当前区域的代码( Hit-Test code )
HTCLIENT
( 客户区域 ) 、HTCAPTION
( 标题栏区域 )…
HIWORD
:当前鼠标消息ID
设置资源
在注册窗口时,设置光标( 不方便随时改光标 )
使用SetCursor
设置光标( 可以随时改光标 )
字符串
方便实现中英文两版程序
添加字符串资源
添加字符串表,在表中增加字符串
字符串资源的使用
1 |
|
加速键
例如快捷键,可以添加对应的ID
来对应的快捷操作
加载加速键表
1 |
|
翻译加速键
1 |
|
在WM_COMMAND
中相应消息,消息参数:
wPARAM
: HIWORD
为 1 表示加速键,为 0 表示菜单。LOWORD
为命令ID
。
lParam
:为0
消息
消息组成
窗口句柄、消息ID、消息的两个参数( 两个附带信息 ):消息产生的时间、消息产生时的鼠标位置
消息作用
当系统通知窗口工作室,就采用消息的方式派发给窗口
相关消息
消息名 | 产生时间 | 附带消息 | 一般用法 |
---|---|---|---|
WM_DESTORY | 窗口被销毁时的消息 | wParam 为 0 , lPARAM 为 0 |
常用于在窗口被销毁之前,做对应的善后处理,例如资源、内存等。 |
WM_SYSCOMMAND | 当点击窗口的最大化、最小化、关闭等 | wParam 为具体点击位置,例如关闭SC_CLOSE等 , lPARAM 为鼠标光标的位置。LOWORD(lPARAM);//水平位置HIWORD(lPARAM);//垂直位置 |
常用在窗口关闭时,提示用户处理 |
WM_CREATE | 窗口创建成功但是还未显示时 | wParam 为 0 , lPARAM 为 CREATESTRUCT 类型的指针。通过这个指针可以获取CreatWindowEX 中全部的12个参数的信息 |
常用于初始化窗口的函数、资源等,包括创建子窗口的等 |
WM_SIZE | 窗口的大小法神变化后,窗口刚产生时 | wParam 为窗口变化的原因 , lPARAM 为窗口变化后的大小。LOWORD(lPARAM);//变化后的宽度HIWORD(lPARAM);//变化后的高度 |
常用于窗口大小变化后,调整窗口内各个部分的布局 |
WM_QUIT | 程序员发送 | wParam 为PostQuitMessage 传递的参数 , lPARAM 为 0 |
用于结束消息循环,当GetMessage 收到这个消息后,返回FALSE ,结束while 处理,退出消息循环 |
WM_PAINT | 当窗口需要绘制的时候 | wParam 为 0 , lPARAM 为 0 |
用于绘图 |
… | … | … | … |
消息的阻塞
GetMessage
:从系统获取消息,将消息从系统中移除,阻塞函数。当系统无消息时,会等候下—条消息。
PeekMessage
:以查看的方式从系统获取消息,可以不将消息从系统移除,非阻塞函数。当系统无消息时,返回FALSE
,继续执行后续代码。
1 |
|
消息循环:
1 |
|
发送消息
SendMessage
:发送消息(直接发送到自己定义的消息处理函数),会等候消息处理的结果。消息未处理完会造成阻塞。
PostMessage
:投递消息(发送到系统队列),消息发出后立刻返回,不等候消息执行结果。
1 |
|
系统消息:ID 范围0 - 0x03FF
由系统定义好的消息,可以在程序中直接使用。
用户自定义消息:ID 范围0x0400 - 0x7FFF(31743)
由用户自己定义,满足用户自己的需求。由用户自己发出消息,并响应处理。
自定义消息宏:WM_USER
消息队列
概念
- 消息队列是用于存放消息的队列。
- 消息在队列中先入先出。
- 所有窗口程序都具有消息队列。
- 程序可以从队列中获取消息。
分类
系统消息队列:由系统维护的消息队列。存放系统产生的消息,例如鼠标、键盘等。
程序消息队列:属于每一个应用程序(线程)的消息队列。由应用程序(线程)维护。
根据消息和消息队列之间使用关系,将消息分成两类:
-
队列消息 – 消息的发送和获取,都是通过消息队列完成。
队列消息-消息发送后,首先放入系统消息队列,之后分发道程序消息队列,然后通过消息循环,从队列当中获取。
GetMessage
:从消息队列中获取消息PostMessage
:将消息投递到消息队列常见队列消息:
WM_PAINT
、键盘、鼠标、定时器。 -
非队列消息 – 消息的发送和获取,是直接调用消息的窗口处理完成。
非队列消息–消息发送时,首先查找消息接收窗口的窗口处理函数,直接调用处理函数,完成消息。
SendMessage
:直接将消息发送给窗口的处理函数,并等候处理结果。常见消息:WM_CREATE
、WM_SIZE
等。
键盘消息
WM_KEYDOWN
:按键被按下时产生
WM_KEYUP
:按键被放开时产生
WM_SYSKEYDOWN
:系统键按下时产生比如ALT、F10等
WM_SYSKEYUP
:系统键放开时产生
附带信息:
WPARAM
:按键建Virtual Key
LPARAM
:按键的参数,例如按下次数
鼠标消息
基本鼠标消息:
WM_LBUTTONDOWN
:鼠标左键按下
WM_LBUTTONUP
:鼠标左键抬起
WM_RBUTTONDOWN
:鼠标右键按下
WM_RBUTTONUP
:鼠标右键抬起
WM_MOUSEMOVE
:鼠标移动消息
双击消息:
WM_LBUTTONDBLCLK
:鼠标左键双击
WM_RBUTTONDBLCLK
:鼠标右键双击
滚轮消息:
WM_MOUSEWHEEL
:鼠标滚轮消息
一般滚轮的位移量为
120
的倍数 ( 正负均可 )
附带信息∶
wPARAM
:其他按键的状态,例如Ctrl/Shift等
lPARAM
:鼠标的位置,窗口客户区坐标系。
LOWORD
:X 坐标位置
HIWORD
:Y 坐标位置
一般情况鼠标按下/抬起成对出现。在鼠标移动过程中,会根据移动速度产生一列的WM_MOUSEMOVE消息。同时使用双击消息处理时需要在注册窗口类的时候添加CS_CBLCLKS
风格。
定时器消息
定时器一般用于周期性执行的操作
产生时间
在程序中创建定时器,当到达时间间隔时,GetMessage
会向程序发送一个WM_TIMER
消息。定时器的精度是毫秒,但是准确度很低。例如设置时间间隔为1000ms,但是会在非1000毫秒到达消息。
误差在毫秒级
1 |
|
定时器的创建
1 |
|
销毁定时器
附带信息
wPARAM
:定时器ID,用于区分时间到后是哪个定时器触发的
lPARAM
:定时器处理函数的指针
绘图
绘图设备DC ( Device Context ) ,也称之为绘图上下文或绘图描述表
HDC - DC句柄,表示绘图设备
GDI - Windows graphics device interface ( Win32提供的绘图API )
颜色
计算机使用红、绿、蓝,R - 0 ~ 255
、G - 0 ~ 255
、B - 0 ~ 255
每一个点颜色是 3 个字节 24 位保存0 - 2^24 - 1
,可以保存任意的颜色
16位:5,5,6 ( RGB )
32位:8,8,8,8 绘图或透明度 ( RGB+透明度 )
颜色的使用
COLORREF
:实际DWORD ( unsigned long )
例如:COLORREF nColor = 0;
赋值使用RGB宏
例如: nColor = RGB(0,0,255);
获取RGB值
GetRValue/GetGValue/GetBValue
例如:BYTE nRed = GetRValue( nColor );
返回对应颜色的配比是多少
基本图形绘制
SetPixel
设置指定点的颜色 ( 画一个点 )
1 |
|
线的使用(直线、弧线)
MoveToEx
:指到窗口到目标点(从(0,0)
到指定的点),设置当前点
LineTo
:从窗口当前点到指定点绘制一条直线
当前点:上一次绘图时的最后一点,初始为(0,0)
点。
封闭图形:能够用画刷填充的图形Rectangle
( 绘画直角矩形 ) / Ellipse
( 圆形 )
GDI 绘图对象
画笔
画笔的作用
线的颜色、线型、线粗。
HPEN
:画笔句柄
画笔的创建
1 |
|
PS_SOILD
:实心线,可以支持多个像素宽其他线型只能是一个像素宽。
虚线画笔像素宽只能是 1,实心画笔可以是任意像素宽
将画笔应用到DC中
1 |
|
注意保存原来 DC 当中的画笔 ( 返回值 ),DC 使用完我们创建的画笔需要将其还回原来的画笔( 黑色 )
将原来的画笔,使用SelectObject
函数 ( 类似于交换 ),放入到设备DC中,就会将我们创建的画笔取出
释放画笔 ( 我们自己创建的画笔 )
1 |
|
只能删除不被 DC 使用的画笔,所以在释放前,必须将画笔从DC中取出。
画刷
画刷-封闭图形的填充的颜色、图案
HBRUSH - 画刷句柄
CreateSolidBrush
:创建实心画刷 ( 填充单一颜色 )
CreateHatchBrush
:创建纹理画刷 ( 填充纹理线 )
之后同画笔一样,需要进行交换(SelectObject)
和对创建的画刷句柄进行消除。
初始画刷为白颜色,同时用直线围起来的图形即使封闭也不是封闭图形
可以使用
GetStockObject
函数获取系统维护的画刷、画笔等。调用的系统画刷不需要销毁,也无法使用DeleteObject
进行销毁掉。如果不使用画刷填充,需要使用
NULL_BRUSH
参数,获取不填充的画刷。GetStockObject
返回的画刷不需要DeleteObject
。
位图
光栅图形 – 记录图像中每一点的颜色等信息。
矢量图形 – 记录图像算法、绘图指令等。
HBITMAP - 位图句柄
位图的使用
- 在资源中添加位图资源
- 从资源中加载位图
LoadBitmap
- 创建一个与当前DC相匹配的DC ( 内存 DC )
1 |
|
- 将位图放入匹配的DC中SelectObject
- 成像( 1:1 )
1 |
|
缩放成像
1
2
3
4
5
6
7
8
9
10
11
12
13
BOOL StretchBlt(
HDC hdcDest,// handle to destination DC
int nXOriginDest,// x-coord of destination upper-left corner
int nYOriginDest,// y-coord of destination upper-left corner
int nWidthDest,// width of destination rectangle
int nHeightDest,// height of destination rectangle
HDC hdcSrc,// handle to source DC
int nXOriginSrc,// x-coord of source upper-left corner
int nYOriginSrc,// y-coord of source upper-left corner
int nWidthSrc,//源DC宽
int nHeightSrc,//源DC高
DWORD dwRop// raster operation code
)
-
取出位图
( SelectObject )
-
释放位图
( DelectObject )
-
释放匹配的 DC
(DeleteObject)
文字的绘制
TextOut
:将文字绘制在指定坐标位置 ( 只能绘制单行 )
DrawText
:可以绘制矩形框的字符串
1 |
|
文字颜色和背景
文字颜色::SetTextColor
文字背景色:SetBkColor
只适用于不透明模式下
文字背景模式:SetBkMode
(OPAQUE 不透明模式 / TRANSPARENT 透明模式)
字体
Windows
常用的字体为TrueType
格式的字体文件
创建字体
1 |
|
对话框
对话框的分类
模式对话框–当对话框显示时,会禁止其他窗口和用户交互操作。
无模式对话框–在对话框显示后,其他窗口仍然可以和用户交互操作。
对话框基本使用
- 对话框窗口处理函数
- 注册窗口类(不使用)
- 创建对话框
- 对话框的关闭
对话框窗口处理函数
并非真正的对话框窗口处理函数
1 |
|
返回TRUE
:缺省处理函数不需要处理。
返回FALSE
:交给缺省处理函数处理。
不需要调用缺省对话框窗口处理函数。
创建对话框
1 |
|
DialogBox
是一个阻塞函数,只有当对话框关闭后,才会返回,继续执行后续代码。
返回值是通过EndDialog
设置。
1 |
|
非阻塞函数,创建成功返回窗口句柄,需要使用ShowWindow
函数显示对话框
关闭时使用DestroyWindow
销毁窗口,不能使用EndDialog
关闭对话框。
对话框的关闭
1 |
|
关闭模式对话框,只能使用EndDialog
,不能使用DestroyWindow
等函数。nResult
是DialogBox
函数退出时的返回值。
关闭非模式对话框,关闭时使用DestroyWindow
销毁窗口,不能使用EndDialog
关闭对话框。
对话框的消息
WM_INITDIALOG
:对话框创建之后显示之前,通知对话框窗口处理函数,可以完成自己的初始化相关的操作。
静态库
特点
运行不存在,静态库源码被链接到调用程序中,目标程序的归档。
C
在Windows
下直接编译不连接不需要对函数进行声明即可调用,但是C++
需要对函数进行申明
C 静态库的使用
库路径设置:可以使用pragma
关键字设置#pragma comment( lib,"../lib/clib.lib”)
C++ 静态库的创建
- 创建一个静态库项目。
- 添加库程序,源文件使用CPP文件。
C++静态库的使用
库路径设置:可以使用pragma
关键字设置#pragma comment( lib,"../lib/cpplib.lib”)
C++
在处理函数时会对函数进行换名,因此在C++
中调用C
静态库会找不到,而无法使用可以在调用的
C
静态库的函数声明前加一个extern "C"
动态库
特点
- 运行时独立存在
- 源码不会链接到执行程序
- 使用时加载(使用动态库必须使动态库执行)
与静态库的比较︰
由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小。
静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义(或地址)未变化,其他使用DLL
的程序不需重新链接。
创建动态库项目
添加库程序
库程序导出–提供给使用者库中的函数等信息。
- 声明导出︰使用
_declspec(dllexport)
导出函数,用该方法导出的函数名字会被替换 ( C++ )
注意:动态库编译链接后,也会有
lib
文件,是作为动态库函数映射使用,与静态库不完全相同。
- 模块定义文件.def
例如
LIBRARY DLLFunc //库
EXPORTS //库导出表
DLL_Mul @1 //导出的函数
dll
文件中将函数导出后会将定义的函数的地址放在文件头,之后放定义函数的源码
动态库的使用
隐式链接(操作系统负责使动态库执行)
- 头文件和函数原型
可以在函数原型的声明前,增加_declspec(dllimport))
- 导入动态库的LIB文件
- 在程序中使用函数
- 隐式链接的情况,dll文件可以存放的路径︰
- 与执行文件中同一个目录下
- 当前工作目录
- Windows 目录
- Windows / System32 目录
- Windows / System
- 环境变量
PATH
指定目录
程序通过定位到
lib
文件之后取其中的编号,而对引用的函数进行加载
1
2
_declspec(dllimport) XXX //定义的函数申明 ( C++ )
#pragma comment (lib,"lib文件路径")
显示链接(程序员自己负责使动态库执行)
-
定义函数指针类型typedef
-
加载动态库
1
2
3HMODULE LoadLibrary(
LPCTSTR IpFileName //动态库文件名或全路径
);//返回DLL的实例句柄 (HINSTANCE) -
获取函数地址 ( 绝对 / 真实地址 )
1
2
3
4FARPROC GetProcAddress(
HMODULE hModule,//DLL句柄
LPCSTR lpProcName //函数名称
);//成功返回函数地址 -
使用函数
-
卸载动态库
1 |
|
如果出现加载的函数的地址为 0 的情况,可以在
dll
项目的文件中加入一个文件头,包含以下内容:
1
2
3
4
5
6
7
8
#pragma once
#ifdef __DLLEXPORT
#define __DLL_EXP _declspec(dllexport)
#else
#define __DLL_EXP _declspec(dllimport)
#endif
extern "C" __DLL_EXP 定义的函数添加完后再次生成
dll
文件即可
动态库封装类
在类名称前增加_declspec(dllexport)
定义,例如∶
1 |
|
通常使用预编译开关切换类的导入导出定义,例如∶
1 |
|
线程
Windows
线程是可以执行的代码的实例。系统是以线程为单位调度程序。一序当中可以有多个线程,实现多任务的处理。
Windows 线程的特点︰
- 线程都具有1个ID
- 每个线程都具有自己的内存栈
- 同一进程中的线程使用同一个地址空间。
线程的调度:
将CPU的执行时间划分成时间片,依次根据时间片执行不同的线程。
线程轮询:
线程A->线程B->线程A…
创建一个线程
1 |
|
处理函数
线程处理函数:
1 |
|
挂起线程:
1 |
|
恢复线程:
1 |
|
结束指定线程:
1 |
|
类似于"杀人",输入对应线程的句柄就可以结束对应线程
结束函数所在的线程:
1 |
|
类似于"自杀",哪个线程调用,哪个线程就结束
获取线程的ID:
1 |
|
获取当前线程的句柄:
1 |
|
等候单个句柄有信号:
1 |
|
可等候的句柄,需要包括有信号和无信号两个状态,可以是一个线程句柄。如果程序无信号(最大等候时间内),该函数会阻塞,等候有信号时停止阻塞
同时等候多个句柄有信号:
1 |
|
bWaitAll
等候方式:
TRUE
:表示所有句柄都有信号,才结束等候
FASLE
:表示句柄中只要有一个有信号,就结束等候。当线程执行中时,该线程无信号,当线程结束时才产生信号。
线程同步
原子锁
相关问题
多个线程对同一个数据进行原子操作,会产生结果丢失。比如执行++
运算时。
错误代码分析
当线程A执行a value++
时,如果线程切换时间正好是在线程A将值保存到a value
之前,线程B继续执行g_value++
,那么当线程A再次被切换回来之后,会将原来线程A保存的值保存到g_value上
,线程B进行的加法操作被覆盖。
一般被
CPU
切换出该线程时,程序会将当前运行状态进行压栈保存( 每个进程都有独立的栈空间 )以上图为例,当线程一再执行完语句一后,被
CPU
切换到线程二,线程一的数据进行压栈保存,线程二完整的执行完了对应的全部代码,此时切换回到线程一,栈中的数据弹出,执行语句三,而导致线程一的语句一的数据未被保存,而导致丢失了数据。
使用原子锁函数
InterlockedIncrement(long*)
对++
操作符进行加锁
对传入的数据进行加一运算,当运行时间超过了等待时间,仍然会被操作系统切换到其他线程,当该线程无法进行加锁时会造成阻塞,只能等待切换线程。
InterlockedDecrement
对--
操作符进行加锁
InterlockedCompareExchange
对比较进行加锁
InterlockedExchange
对交换进行加锁
原子锁的实现
直接对数据所在的内存操作,并且在任何一个瞬间只能有一个线程访问。
互斥锁
效率不如原子锁,但是原子锁能实现的互斥锁均能实现
相关的问题
多线程下代码或资源的共享使用。
互斥的使用
1 |
|
在任何时间点上,只能有一个线程拥有互斥,具有独占性和排他性,当任何一个线程不拥有互斥时其拥有信号,但是当拥有互斥时其变为无信号。
WaitForSingleObject / WaitForMultipleObjects
互斥的等候遵循谁先等候谁先获取。
释放互斥
1 |
|
关闭互斥句柄
1 |
|
事件
相关问题
解决程序之间的通知的问题。
事件的使用
创建事件
1 |
|
时间也具备有信号和无信号两个状态
等候事件
1 |
|
触发事件(将事件设置成有信号状态)
1 |
|
关闭事件
1 |
|
注意:小心事件的死锁。
信号量
相关的问题
类似于事件,解决通知的相关问题。但提供一个计数器,可以设置次数。
信号量的使用
1 |
|
等候信号量
WaitForSingleObject / WaitForMultipleObjects
每等候通过一次,信号量的信号减1,直到为 0 阻塞
给信号量指定计数值
1 |
|
关闭句柄
1 |
|
相关函数
1 |
|
句柄一个拿来找到内存的东西,但不是指针,句柄类型定义以
H
开头
1 |
|
MessageBox
是一个阻塞函数,当提示框弹出时便阻塞了,当点击了按钮后终止阻塞
uType
按钮参数:
按钮参数 含义 MB_OK 默认值。有一个确认按钮在里面。 MB_YESNO 有是和否在里面。 MB_ABORTRETRYIGNORE 有Abort(放弃),Retry(重试)和Ignore(跳过) MB_YESNOCANCEL 消息框含有三个按钮:Yes,No和Cancel MB_RETRYCANCEL 有Retry(重试)和Cancel(取消) MB_OKCANCEL 消息框含有两个按钮:OK和Cancel 图标:
参数 含义 MB_ICONEXCLAMATION 一个惊叹号出现在消息框 MB_ICONWARNING 一个惊叹号出现在消息框 MB_ICONINFORMATION 一个圆圈中小写字母 i 组成的图标出现在消息框 MB_ICONASTERISK 一个圆圈中小写字母 i 组成的图标出现在消息框 MB_ICONQUESTION 一个问题标记图标出现在消息框 MB_ICONSTOP 一个停止消息图标出现在消息框 MB_ICONERROR 一个停止消息图标出现在消息框 MB_ICONHAND 一个停止消息图标出现在消息框
1 |
|
注册窗口类的结构体
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct _WNDCLASS{
UINT style; //窗口类风格
WNDPROC IpfnWndroc; //窗口处理函数
int cbClsExtra; //窗口类的附加数据buff的大小(开缓冲区大小[字节])
int cbWndExtra; //窗口的附加数据buff的大小(开缓冲区大小[字节])
HINSTANCE hInstance; //当前模块的实例句柄
HICON hIcon; //窗口图标句柄
HCURSOR hCursor; //鼠标的句柄
HBRUSH hbrBackground; //绘制窗口背景的画刷句柄
LPCTSTR IpszMenuName; //窗口菜单的资源ID字符串
LPCTSR IpszClassName; //窗口类名称
}WNDCLASS,*PWNDCLASS;
style
风格:
1
2
3
4CS_HREDRAW - 当窗口水平变化时,窗口重新绘制
CS_VREDRAW - 当窗口垂直变化时,窗口重新绘制
CS_DCLCLKS - 允许窗口接收鼠标双击
CS_NOCLOSE - 窗口没有关闭按钮
1 |
|
窗口创建
1 |
|
消息处理函数,通过用户自定义来对产生的消息进行处理
1 |
|
IpMsg
:当获取到消息后,将消息的参数存放到MSG
结构中
hWnd
:获取hWnd
所指定窗口的消息
wMsgFilterMax
和wMsgFilterMin
:只能获取到由它们指定的消息范围内的消息,如果都为0
,表示没有范围。返回值:
抓到
WM_QUIT
返回零值,否则返回非零值。
PostQuitMessage(0)
可以发送一个WM_QUIT
消息,使其返回在程序(线程)消息队列查找消息,如果队列有消息,检查消息是否满足指定条件(HWND,ID范围),不满足条件就不会取出消息,否则从队列取出消息返回。
如果程序(线程)消息队列没有消息,向系统消息队列获取属于本程序的消息。如果系统队列的当前消息属于本程序,系统会将消息转发到程序消息队列中。
如果系统消息队列也没有消息,检查当前进程的所有窗口的需要重新绘制的区域,如果发现有需要绘制的区域,产生WM_PAINT
消息,取得消息返回处理。
如果没有重新绘制区域,检查定时器如果有到时的定时器,产生WM_TIMER
,返回处理执行。
GetMessage
会继续等候下一条消息。PeekMessage
会返回FALSE
,交出程序的控制权。
注意:GetMessage
如果获取到是WM_QUIT
,函数会返回FALSE
。
如果没有到时的定时器,整理程序的资源、内存等等。
1 |
|
翻译消息( 对于可见字符 ),将键盘消息翻译成字符消息。
检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行。
TranslateMessage
在转换WM_KEYDOWN
消息时,对于可见字符可以产生WM_CHAR
,不可见字符无此消息。附带信息∶
WPARAM
:输入的字符的ASCII
字符编码值
LPARAM
:按键的相关参数
1 |
|
将消息派发到该消息所属的窗口处理函数上
1 |
|
申明窗口无效区域:需要重新绘制的区域