注:转载自小甲鱼-鱼c论坛 ,归纳一下方便自己学习//SetScrollRange

函数

BeginPaint

函数功能:

BeginPaint 函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。

API 函数原型:

1
2
3
4
HDC BeginPaint(
_In_ HWND hwnd,
_Out_ LPPAINTSTRUCT lpPaint
);

参数解析:

参数 含义
hwnd 需要重新绘制的窗口句柄
lpPaint 指向 PAINTSTRUCT 结构的指针,用于存放绘画相关的信息

返回值:

  1. 如果函数成功,返回值是指定窗口的“显示设备描述表”句柄;

  2. 如果函数失败,返回值是 NULL,表明没有得到显示设备的内容。

备注:

  1. BeginPaint 函数自动设置显示设备内容的剪切区域,而排除任何更新区域外的区域。该更新区域可以通过 InvalidateRect 或 InvalidateRgn 函数设置,也可以是系统在改变大小、移动、创建、滚动后设置的,或者其他的影响客户区的操作来设置的。

  2. 如果更新区域被标记为可擦除的,BeginPaint 发送一个 WM_ERASEBKGND 消息给窗口。

  3. 一个应用程序除了响应 WM_PAINT 消息外,不应该调用 BeginPaint。

  4. 每次调用 BeginPaint 都应该有相应的 EndPaint 函数。

  5. 如果被绘画的客户区中有一个 caret(caret:插入符。是窗口客户区中的一个闪烁的线,块,或位图。插入符通常表示文本或图形将被插入的地方。即一闪一闪的光标),BeginPaint 自动隐藏该符号,而保证它不被擦除。

  6. 如果窗口类有一个背景刷,BeginPaint 使用这个刷子来擦除更新区域的背景。

CreateWindow

函数功能:

CreateWindow 函数创建一个重叠式窗口、弹出式窗口或子窗口。它指定窗口类,窗口标题,窗口风格,以及窗口的初始位置及大小(可选的)。函数也指该窗口的父窗口或所属窗口(如果存在的话),及窗口的菜单。

若要使用除 CreateWindow 函数支持的风格外的扩展风格,则使用 CreateWindowEx 函数代替 CreateWindow 函数。

API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_说明该参数是可选参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
HWND WINAPI CreateWindow(
_In_opt_ LPCTSTR lpClassName, // 窗口类名称
_In_opt_ LPCTSTR lpWindowName, // 窗口标题
_In_ DWORD dwStyle, // 窗口风格,或称窗口格式
_In_ int x, // 初始 x 坐标
_In_ int y, // 初始 y 坐标
_In_ int nWidth, // 初始 x 方向尺寸
_In_ int nHeight, // 初始 y 方向尺寸
_In_opt_ HWND hWndParent, // 父窗口句柄
_In_opt_ HMENU hMenu, // 窗口菜单句柄
_In_opt_ HINSTANCE hInstance, // 程序实例句柄
_In_opt_ LPVOID lpParam // 创建参数
);

参数解析:

参数 含义
lpClassName 1. 窗口类名称,可以是一个指向 NULL 结束的字符串或一个整型数值 2. 如果是字符串,它指定了窗口的类名。这个类名可以是任何用函数 RegisterClass 注册的类名,或是任何预定义的控制类名 3. 如是一个整型量,它是由此前调用 theGlobalAddAtom 函数产生的全局量。这个小于 0xC000 的 16 位数必须是 lpClassName 参数字的低 16 位,该参数的高位必须是 0
lpWindowName 1. 窗口标题,一个指向 NULL 结束的字符串指针 2. 如果窗口风格指定了标题条,由 lpWindowName 指向的窗口标题将显示在标题条上 3. 当使用 Createwindow 函数来创建控制例如按钮,选择框和静态控制时,可使用 lpWindowName 来指定控制文本
dwStyle 指定创建窗口的风格(详见下方↓)
x 1. 指定窗口的初始水平位置(x 坐标) 2. 对一个层叠或弹出式窗口,x 参数是屏幕坐标系的窗口的左上角的初始 x 坐标 3. 对于子窗口,x 是子窗口左上角相对父窗口客户区左上角的初始 x 坐标 4. 如果该参数被设为 CW_USEDEFAULT 则系统为窗口选择缺省的左上角坐标并忽略 y 参数,CW_USEDEFAULT 只对层叠窗口有效,如果为弹出式窗口或子窗口设定,则 x 和 y 参数被设为零。
y 1. 指定窗口的初始垂直位置(y 坐标) 2. 对一个层叠或弹出式窗口,y 参数是屏幕坐标系的窗口的左上角的初始 y 坐标 3. 对于子窗口,y 是子窗口左上角相对父窗口客户区左上角的初始 y 坐标 4. 对于列表框,y 是列表框客户区左上角相对父窗口客户区左上角的初始 y 坐标 5. 如果层叠窗口是使用 WS_VISIBLE 风格位创建的并且 x 参数被设为 CW_USEDEFAULT,则系统将忽略 y 参数
nWidth 1. 以设备单元指明窗口的宽度 2. 对于层叠窗口,nWidth 的值或是屏幕坐标的窗口宽度或是 CW_USEDEFAULT 3. 若 nWidth 是 CW_USEDEFAULT,则系统为窗口选择一个默认的高度和宽度(默认宽度为从初始 x 坐标开始到屏幕的右边界,缺省高度为从初始 y 坐标开始到目标区域的顶部。),CW_USEDEFAULT 只对层叠窗口有效,如果为弹出式窗口和子窗口设定 CW_USEDEFAULT 标志则 nWidth 和 nHeight 被设为零
nHeight 1. 以设备单元指明窗口的高度 2. 对于层叠窗口,nHeight 是屏幕坐标的窗口宽度 3. 若 nWidth 被设为 CW_USEDEFAULT,则系统忽略 nHeight 参数,自动为 nWidth 和 nHeight 设置默认参数
hWndParent 1. 指向被创建窗口的父窗口或所有者窗口的句柄 2. 若要创建一个子窗口或一个从属窗口,需提供一个有效的窗口句柄 3. 创建一个单纯的消息窗口,可以提供 HWND_MESSAGE 或提供一个己存在的消息窗口的句柄
hMenu 1. 指向窗口菜单句柄,或依据窗口风格指明一个子窗口标识 2. 对于层叠或弹出式窗口,hMenu 指定窗口使用的菜单:如果使用了菜单类,则 hMenu 可以为 NULL 3. 对于子窗口,hMenu 指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的
hInstance 与窗口相关联的模块实例的句柄
lpParam 1. 指向一个值的指针,该值传递给窗口 WM_CREATE 消息。该值通过在 IParam 参数中的 CREATESTRUCT 结构传递 2. 如果应用程序调用 CreateWindow 创建一个 MDI 客户窗口,则 lpParam 必须指向一个 CLIENTCREATESTRUCT 结构

dwStyle 窗口风格解析

窗口风格 含义
WS_BORDER 创建一个带边框的窗口
WS_CAPTION 创建一个有标题框的窗口(包含了 WS_BODER 风格)
WS_CHILD 创建一个子窗口,这个风格的窗口不能拥有菜单也不能与 WS_POPUP 风格合用
WS_CHILDWINDOW 与 WS_CHILD 相同
WS_CLIPCHILDREN 当在父窗口内绘图时,排除子窗口区域,在创建父窗口时使用这个风格
WS_CLIPSIBLINGS 1. 排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到 WM_PAINT 消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口 2. 如果未指定该风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口
WS_DISABLED 1. 创建一个初始状态为禁止的子窗口,一个禁止状态的窗口不能接受来自用户的输入信息 2. 在窗口创建之后,可以调用 EnableWindow 函数来启用该窗口
WS_DLGFRAME 创建一个带对话框边框风格的窗口,这种风格的窗口不能带标题条
WS_GROUP 1. 指定一组“控制窗口”的第一个“控制窗口” 2. 这个“控制窗口”组由第一个“控制窗口”和随后定义的“控制窗口”组成,自第二个“控制窗口”开始每个“控制窗口”具有 WS_GROUP 风格 3. 每个组的第一个“控制窗口”带有 WS_TABSTOP 风格,从而使用户可以在组间移动 4. 用户随后可以使用光标在组内的控制间改变键盘焦点
WS_HSCROLL 创建一个有水平滚动条的窗口
WS_ICONIC 创建一个初始状态为最小化状态的窗口,与 WS_MINIMIZE 风格相同
WS_MAXIMIZE 创建一个初始状态为最大化状态的窗口
WS_MAXIMIZEBOX 创建一个具有最大化按钮的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格
WS_MINIMIZE 创建一个初始状态为最小化状态的窗口,与 WS_ICONIC 风格相同
WS_MINIMIZEBOX 创建一个具有最小化按钮的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格
WS_OVERLAPPED 产生一个层叠的窗口,一个层叠的窗口有一个标题条和一个边框,与 WS_TILED 风格相同
WS_OVERLAPPEDWINDOW 相当于(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),与 WS_TILEDWINDOW 风格相同
WS_POPUP 创建一个弹出式窗口,该风格不能与 WS_CHILD 风格同时使用。
WS_POPUPWINDOW 相当于(WS_POPUP | WS_BORDER | WS_SYSMENU),但 WS_CAPTION 和 WS_POPUPWINDOW 必须同时设定才能使窗口某单可见
WS_SIZEBOX 创建一个可调边框的窗口,与 WS_THICKFRAME 风格相同
WS_SYSMENU 创建一个在标题条上带有窗口菜单的窗口,必须同时设定 WS_CAPTION 风格
WS_TABSTOP 1. 创建一个“控制窗口”,在用户按下 Tab 键时可以获得键盘焦点。 2. 按下 Tab 键后使键盘焦点转移到下一具有 WS_TABSTOP 风格的“控制窗口”
WS_THICKFRAME 创建一个具有可调边框的窗口,与 WS_SIZEBOX 风格相同
WS_TILED 产生一个层叠的窗口,一个层叠的窗口有一个标题和一个边框,与 WS_OVERLAPPED 风格相同
WS_TILEDWINDOW 相当于(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),与 WS_OVERLAPPEDWINDOW 风格相同
WS_VISIBLE 创建一个初始状态为可见的窗口
WS_VSCROLL 创建一个有垂直滚动条的窗口

返回值:

  1. 如果函数成功,返回值为新窗口的句柄;

  2. 如果函数失败,返回值为 NULL。

DefWindowProc

函数功能:

DefWindowProc 函数调用默认的窗口过程来处理我们不感兴趣的任何消息,该函数是为了确保每个消息都被处理。

DefWindowProc 函数传入和窗口过程同样的参数。

API 函数原型:

1
2
3
4
5
6
LRESULT WINAPI DefWindowProc(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);

参数解析:

参数 含义
hWnd 指定接收消息的窗口句柄
Msg 1. 消息的标识符,由于数值不便于记忆,所以 Windows 将消息对应的数值定义为 WM_XXX 宏的形式 2. 应用程序消息只能使用低 16 位,高 16 位被系统保留 3. 传送门:Windows 常用消息及含义
wParam 指定消息的附加消息,确切的含义取决于消息成员的值
lParam 指定消息的附加消息,确切的含义取决于消息成员的值

返回值:

返回值就是消息处理结果,它取决于发送的消息。

DestroyWindow

函数功能:

  1. DestroyWindow 用于销毁一个指定的窗口,该函数通过发送 WM_DESTROY 消息和 WM_NCDESTROY 消息使窗口无效并移除其键盘焦点。

  2. DestroyWindow 函数还销毁窗口的菜单,清空线程的消息队列,销毁与窗口过程相关的定时器,解除窗口对剪贴板的拥有权,打断剪贴板器的查看链。

  3. 如果指定的窗口拥有子窗口或拥有其它窗口,该函数将自动先销毁其子窗口或所拥有的窗口,然后再销毁自身。

API 函数原型:

1
2
3
BOOL WINAPI DestroyWindow(
_In_ HWND hWnd
);

参数解析:

参数 含义
hWnd 指定将被销毁的窗口句柄

返回值:

  1. 如果函数成功执行,返回值为非 0;

  2. 如果函数执行失败,返回值为 0。

备注:

  1. 一个线程不能使用本函数销毁别的线程创建的窗口。

  2. 如果这个窗口是一个不具有 WS_EX_NOPARENTNOTIFY 样式的子窗口,则销毁窗口时将发 WM_PARENTNOTIFY 消息给其父窗口。

DispatchMessage

函数功能:

DispatchMessage 函数分派一个消息给窗口过程(回调函数),通常该消息从 GetMessage 函数获得。Windows 的控制权在该函数交给了应用程序。

API 函数原型:

1
2
3
LRESULT WINAPI DispatchMessage(
_In_ const MSG *lpmsg
);

参数解析:

参数 含义
lpmsg 指向含有消息的 MSG结构 的指针

返回值:

  1. 返回值是窗口过程返回的值;

  2. 尽管返回值的含义依赖于被分派的消息,但返回值通常被忽略。

备注:

  1. MSG 结构必须包含有效的消息值。

  2. 如果参数 lpmsg 指向一个 WM_TIMER 消息,并且 WM_TIMER 消息的参数 lParam 不为 NULL,则调用 lParam 指向的函数,而不是调用窗口程序。

DrawText

函数原型:

DrawText 函数在指定的矩形里写入格式化的正文,根据指定的方法对正文格式化(扩展的制表符,字符对齐、折行等)。

需要指定更多的格式选项,可以使用 DrawTextEx 函数。

API 函数原型:

1
2
3
4
5
6
7
int DrawText(
_In_ HDC hDC,
_Inout_ LPCTSTR lpchText,
_In_ int nCount,
_Inout_ LPRECT lpRect,
_In_ UINT uFormat
);

参数解析:

参数 含义
hDC 指定“显示设备描述表”句柄
lpchText 1. 指向将被写入的字符串的指针,如果参数 nCount 是 -1,则字符串必须是以 \0 结束的 2. 如果 uFormat 包含 DT_MODIFYSTRING,则函数可为此字符串增加 4 个字符,存放字符串的缓冲区必须足够大,能容纳附加的字符
nCount 1. 指向字符串中的字符数 2. 如果 nCount 为 -1,则 lpchText 指向的字符串被认为是以 \0 结束的,DrawText 会自动计算字符数
lpRect 指向 RECT 结构的指针,其中包含文本将被置于其中的矩形的信息(按逻辑坐标)
uFormat 1. 指定格式化文本的方法 2. 此参数可以通过指定下列标志或标志的组合

uFormat 参数各种标志解析

标志 含义
DT_BOTTOM 对齐文字到矩形的底部,当且仅当设置了 DT_SINGLELINE 标志才有效
DT_CALCRECT 1. 这个参数决定矩形的宽度和高度 2. 如果输出文本有多行,DrawText 函数使用 lpRect 定义的矩形的宽度,并扩展矩形的底部以容纳输出文本的最后一行 3. 如果输出文本只有一行,则 DrawText 函数改变矩形的右边界,以容纳下正文行的最后一个字符 4. 出现上述任何一种情况,DrawText 函数将返回格式化文本的高度,而不是绘制文本
DT_CENTER 文本水平居中显示
DT_EDITCONTROL 将拥有多行编辑控件的正文显示特性(尤其是平均字符宽度的计算方法,并且不会显示不可见的最后一行)
DT_END_ELLIPSIS 1. 对于显示的文本,如果结束的字符串的范围不在矩形内,它会被截断并以省略号标识 2. 如果一个字母不是在字符串的末尾但却超出了矩形范围,它会被换行但没有追加省略号标识 3. 除非指定了 DT_MODIFYSTRING 标志,否则字符串不会被修改
DT_EXPANDTABS 1. 扩展制表符,每个制表符的缺省字符数是 8 2. DT_WORD_ELLIPSIS, DT_PATH_ELLIPSIS 和 DT_END_ELLIPSIS 不能和此参数一起使用
DT_EXTERNALLEADING 在行的高度里包含字体的外部标头(通常外部标头不被包含在正文行的高度里)
DT_HIDEPREFIX 1. 忽略正文中的前缀字符(&),并且前缀字符后面的字母不会出现下划线,其它前缀字符的调用方式不受影响 2. 例如:输入字符串为“F&is&&hC”,正常显示为“Fis&hC”,使用 DT_HIDEPREFIX 显示为“Fis&hC”
DT_INTERNAL 用系统字体来计算正文尺寸
DT_LEFT 正文左对齐
DT_MODIFYSTRING 1. 允许系统修改给定的字符串来匹配显示的正文 2. 此标志必须和 DT_END_ELLIPSIS 或 DT_PATH_ELLIPSIS 同时使用
DT_NOCLIP 无裁剪绘制,使用 DT_NOCLIP 可以提高 DrawText 的效率
DT_NOFULLWIDTHCHARBREAK 1. 在宽字符的字符串中防止行断开,因此折行规则相当于单字符的字符串 2. 例如,我们可以用在韩国版的 Windows 中,为图标标签提供更好的可读性 3. 除非指定 DT_WORDBREAK,否则此值没有作用
DT_NOPREFIX 1. 关闭前缀字符的处理(通常 DrawText 解释 & 为给其后的字符加下划线,解释 && 为显示单个 &) 2. 例如:输入字符串为“F&is&&hC”,正常显示为“Fis&hC”,使用 DT_NOPREFIX 显示为“F&is&&hC”
DT_PATH_ELLIPSIS 1. 对于过长的正文,自动替换字符串中间的字符为省略号(…),以确保结果能在合适的矩形内显示 2. 如果该字符串包含反斜杠(\)字符,DT_PATH_ELLIPSIS 尽可能的保留最后一个反斜杠之后的字符 3. 除非指定了 DT_MODIFYSTRING 标志否则字符串不会被修改
DT_PREFIXONLY 1. 仅仅在(&)前缀字符的位置下绘制一个下划线,但不绘制字符串中的任何其他字符 2. 例如:输入字符串为“F&is&&hC”,正常显示为“Fis&hC”,使用 DT_PREFIXONLY 显示为“_”
DT_RIGHT 正文右对齐
DT_RTLREADING 当设备环境的字体是希伯来文或阿拉伯文字体时,为双向正文安排从右到左的阅读顺序
DT_SINGLELINE 显示正文的同一行,回车和换行符都不能换行
DT_TABSTOP 1. 设置制表符,参数 uFormat 的 8~15 位(低位字中的高位字节)指定每个制表符的字符数,每个制表符的缺省字符数是 8 2. DT_CALCRECT, DT_EXTERNALLEADING, DT_INTERNAL, DT_NOCLIP 和 DT_NOPREFIX 不能和此参数一起使用
DT_TOP 正文顶端对齐
DT_VCENTER 使正文在矩形中垂直居中,当且仅当设置了 DT_SINGLELINE 标志才有效
DT_WORDBREAK 1. 当一行中的字符将会延伸到由 lpRect 指定的矩形的边框时,此行自动地在单词之间断开 2. 一个回车一换行也能使之换行 3. 如果没有指定,输出会在一行上
DT_WORD_ELLIPSIS 截短不符合矩形的正文,并增加省略号(与 DT_END_ELLIPSIS 类似)

返回值:

  1. 如果函数调用成功,返回值是正文的高度(逻辑单位);

  2. 如果指定了 DT_VCENTER 或 DT_BOTTOM,返回值是 lpRect -> top 到绘制的正文的底部的偏移值;

  3. 如果 函数调用失败,返回值是 0。

备注:

  1. 函数 DrawText 用设备环境中的字体选择、正文颜色和背景颜色来写正文。

  2. DrawText 裁剪正文,使之不会出现在指定矩形的外面,除非指定了 DT_NOCLIP。

  3. 除非使用 DT_SINGLELINE 格式化,否则其余的格式都认为正文有多行。

  4. 如果选择的字体对指定的矩形而言太大,DrawText 并不会试图去换成一种小字体。

  5. 设备环境的正文对齐方式必须包括 TA_LEFT, TA_TOP 和 TA_NOUPDATECP 标志。

EndPaint

函数原型:

EndPaint 函数标记指定窗口的绘画过程结束。

这个函数在每次调用 BeginPaint 函数之后被调用(释放设备描述表),但仅仅在绘画完成以后。

API 函数原型:

1
2
3
4
BOOL EndPaint(
_In_ HWND hWnd,
_In_ const PAINTSTRUCT *lpPaint
);

参数解析:

参数 含义
hWnd 已经被重新绘制的窗口句柄
lpPaint 指向 PAINTSTRUCT 结构的指针,用于存放绘画相关的信息(该指针在调用 BeginPaint 时被赋值)

返回值:

该函数返回值始终是非 0。

GetClientRect

函数原型:

GetClientRect 函数用于获取窗口客户区的坐标,客户区坐标指定客户区的左上角和右下角。

由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0)

API 函数原型:

1
2
3
4
BOOL WINAPI GetClientRect(
_In_ HWND hWnd,
_Out_ LPRECT lpRect
);

参数解析:

参数 含义
hWnd 需要获取客户区坐标的窗口句柄
lpRect 1. 指向 RECT 结构的指针,该结构有四个成员,分别为 left、top、right 和 bottom 2. GetClientRect 将这四个成员设定为窗口显示区域的尺寸,left 和 top 字段通常设定为 0,right 和 bottom 字段设定为显示区域的宽度和高度(像素点数)

返回值:

  1. 如果函数成功,返回值是非 0;

  2. 如果函数失败,返回值是 0。

GetMessage

函数功能:

GetMessage 函数的作用是从当前线程的消息队列里获取一个消息并填入 MSG 结构 中。

该函数只能获取调用线程的消息,不能获得其他线程的消息。成功获取消息后,线程将从消息队列中删除该消息。

使用 GetMessage 函数,如果消息队列为空,函数会一直等待直到有消息到来才有返回值。如果希望函数立刻返回(无论是否获取消息),请使用 PeekMessage 函数。

API 函数原型:

1
2
3
4
5
6
BOOL WINAPI GetMessage(
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax
);

参数解析:

参数 含义
lpMsg 指向 MSG 结构的指针,用于存放获取到的消息
hWnd 1. 需要获取消息的窗口的句柄,该窗口必须属于当前线程 2. 当其值是 NULL 时,将获取所有的当前线程的窗口消息和线程消息 3. 当其值是 -1 时,只获取当前线程消息
wMsgFilterMin 指定被可以被获取的消息值的最小整数(消息其实就是一个被定义的整数)
wMsgFilterMax 指定被可以被获取的消息值的最小整数

返回值:

  1. 如果函数取得 WM_QUIT 之外的其他消息,返回值是非 0;

  2. 如果函数取得 WM_QUIT 消息,返回值是 0;

  3. 如果出现了错误,返回值是 -1。

备注:

  1. 应用程序通常根据 GetMessage 函数的返回值决定是否结束消息循环并退出程序;

  2. 如果 hWnd 参数不为零,则 GetMessage 函数只获取属于 hWnd 窗口的消息,以及被 IsChild 函数确定为 hWnd 的子窗口的消息;

  3. wMsgFilterMin 和 wMsgFilterMax 参数限定消息获取的范围,如果二者都为 0,则消息获取的范围为所有消息;

  4. 注意,即便你通过 wMsgFilterMin 和 wMsgFilterMax 参数限定消息获取的范围,但 WM_QUIT 不受此范围影响(无法阻止此消息被 PeekMessage 函数获取);

  5. 调用此函数的过程中,如果接收到非排队消息 —— 也就是由该线程调用 SendMessage, SendMessageCallback, SendMessageTimeout, 或 SendNotifyMessage 发送给所属窗口的消息 —— 系统先暂时挂起等待,然后再获取过滤器匹配的第一个队列消息。如果不指定过滤器,那么按照以下顺序获取消息:

  • Sent messages
  • Posted messages
  • Input (hardware) messages and system internal events
  • Sent messages (again)
  • WM_PAINT messages
  • WM_TIMER messages
  1. PeekMessage 函数通常不会从消息队列中删除 WM_PAINT 消息,WM_PAINT 会持续保留在消息队列中直到它们被处理,除非一个 WM_PAINT 消息指定的区域为 NULL。

小甲鱼注释:大家应该还记得有三个消息 WM_QUIT, WM_PAINT, WM_TIMER 会被特殊处理,它们总是放在队列的最后面,直到没有其它消息的时候才被处理,连续的 WM_PAINT 消息将被合并成一个以提高绘图效率。

  1. 如果一个顶层窗口停止响应的消息超过几秒钟,系统认为窗口没有响应,并使用一个备用窗口替代,该窗口具有相同的 Z 序列、位置、尺寸和视觉属性。这使得用户可以移动、调整大小,甚至关闭该应用程序。然而,这些仅仅是动作,现有的程序事实上仍然没有响应(为了提高用户体验而制作的假象)。当一个程序被调试时,系统并不会为其生成备用窗口。

GetTextAlign

函数功能:

GetTextAlign 函数获得指定的设备环境下的文本对齐方式的设置。

API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。

1
2
3
UINT GetTextAlign(
_In_ HDC hdc
);

参数解析:

参数 含义
hdc 指定设备环境句柄

返回值:

  1. 如果函数调用失败,返回值是 GDI_ERROR;

  2. 如果函数调用成功,返回值是文字对齐标志的状态。

该返回值是下列值的组合:

含义
TA_BASELINE 基准点在正文的基线上
TA_BOTTOM 基准点在限定矩形的底边上(限定矩形的含义请看下边备注)
TA_TOP 基准点在限定矩形的顶边上
TA_CENTER 基准点在限定矩形的中心水平对齐位置
TA_LEFT 基准点在限定矩形的左边上
TA_RIGHT 基准点在限定矩形的右边上
TA_RTLREADING 1. 适用于中东 Windows 版本:正文从右到左的阅读顺序排列,与缺省的从左到右正好相反 2. 只有当被选择的字体是 Hebrew 或 Arabic 时,此值才有用
TA_NOUPDATECP 每次输出调用后当前状态不改变
TA_UPDATECP 每次输出调用后当前状态改变

若当前字体有一条缺省的垂直基线(如Kanji),下列值用于取代 TA_BASELINE 和 TA_CENTER:

含义
VTA_BASELINE 基准点在正文的基线上
VTA_CENTER 基准点与限定矩形的中心垂直对齐

备注:

  1. 默认值是 TA_LEFT, TA_TOP 和 TA_NOUPDATECP

  2. 限定矩形是指能将正文字符串的所有字符单元限定于其中的矩形

  3. 限定矩形的尺寸可通过调用 GetTextExtentPoint32 来获得

  4. 文字对齐标志决定 TextOut 和 ExtTextOut 如何将正文字符串与基准点对齐

  5. 文字对齐标志不必是单个的标志位,可以等于0

  6. 标志必须按相关的组来检查,如下:

  • TA_LEFT, TA_RIGHT, and TA_CENTER
  • TA_BOTTOM, TA_TOP, and TA_BASELINE
  • TA_NOUPDATECP and TA_UPDATECP

如果当前字体有缺省的垂直基线,相关的标志如下所示:

  • TA_LEFT, TA_RIGHT, and VTA_BASELINE
  • TA_BOTTOM, TA_TOP, and VTA_CENTER
  • TA_NOUPDATECP and TA_UPDATECP
  1. 要验证一个特定的标志在返回值中被设置,应用程序必须执行以下步骤:
    (例子:如何设置文本对齐模式
  • 对该标志及其相关标志实施位OR操作;
  • 对结果和返回值实施位AND操作;
  • 检查结果值和标志是否相等。

GetTextMetrics

函数功能:

GetTextMetrics 函数将当前字体的信息填充到指定缓冲区(TEXTMETRIC 结构

API 函数原型:

1
2
3
4
BOOL GetTextMetrics(
_In_ HDC hdc,
_Out_ LPTEXTMETRIC lptm
);

参数解析:

参数 含义
hdc 设备环境句柄
lptm 指向 TEXTMETRIC 结构的指针,该结构用于获得字体信息

返回值:

  1. 如果函数调用成功,返回值是非 0;

  2. 如果函数调用失败,返回值是 0。

备注:

  1. 要确定一种字体是否为 TrueType 字体,可以通过调用 GetTextMetrics 函数,然后检查 TEXTMETRIC.tmPitchAndFamily 的值是否为 TMPF_TRUETYPE

  2. 注意,调用 GetDC 函数返回的是一个未初始化的 DC,它具有“系统”(一个位图字体)作为默认字体。因此你需要先选择一种字体到 DC

lstrcat

函数功能:

lstrcat 函数的功能是将一个字符串拼接在另一个字符串后边。

注意:实际编程中不要再使用该函数,请使用 StringCchCat 代替。

API 函数原型:

1
2
3
4
LPTSTR WINAPI lstrcat(
_Inout_ LPTSTR lpString1,
_In_ LPTSTR lpString2
);

参数解析:

参数 含义
lpString1 一个以’\0’为结尾的字符串,该字符串空间必须大到足以容纳本身及另一个字符串
lpString2 一个以’\0’为结尾的字符串,该字符串将拼接到 lpString1 指向的字符串后边

返回值:

  1. 如果函数调用成功,返回指向拼接好的字符串指针;

  2. 如果函数调用失败,返回值为 NULL,并且 lpString1 可能会变成非 ‘\0’ 结束的字符串。

安全建议:

  1. 不正确的使用 lstrcat 函数,可能会损害应用程序的安全性

  2. lstrcat 函数使用结构化异常处理(SEH)来捕捉访问冲突和其他错误。当该函数捕获 SEH 错误,如果没有以’\0’结尾的字符串,则返回 NULL,且不把错误通知调用者。因此,把空间不足作为错误的条件是不安全的

  3. lpString1 必须足够大,以增加 lpString2 和结束’\0’,否则可能发生缓冲区溢出

  4. 在最坏的情况下,缓冲区溢出可能允许攻击者可执行代码注入到你的进程,尤其是当 lpString1 是一个基于堆栈的缓冲区

lstrcpy

函数功能:

lstrcpy 函数的功能是复制一个字符串到缓冲区。

注意:实际编程中不要再使用该函数,请使用 StringCchCopy 代替。

API 函数原型:

1
2
3
4
LPTSTR WINAPI lstrcpy(
_Out_ LPTSTR lpString1,
_In_ LPTSTR lpString2
);

参数解析:

参数 含义
lpString1 1. 缓冲区,用于接收来自 lpString2 参数指向的字符串 2. 该缓冲区必须足够容纳字符串和’\0’
lpString2 待拷贝的字符串

返回值:

  1. 如果函数调用成功,返回指向缓冲区的指针;

  2. 如果函数调用失败,返回值是 NULL,并且 lpString1 可能会变成非 ‘\0’ 结束的字符串。

安全建议:

  1. 不正确的使用 lstcpy 函数,可能会损害应用程序的安全性

  2. lstrcpy 函数使用结构化异常处理(SEH)来捕捉访问冲突和其他错误。当该函数捕获 SEH 错误,如果没有以’\0’结尾的字符串,则返回 NULL,且不把错误通知调用者。因此,把空间不足作为错误的条件是不安全的

  3. lpString1 必须足够大,以增加 lpString2 和结束’\0’,否则可能发生缓冲区溢出

  4. 在最坏的情况下,缓冲区溢出可能允许攻击者可执行代码注入到你的进程,尤其是当 lpString1 是一个基于堆栈的缓冲区

lstrlen

函数功能:

lstrlen 函数用于计算指定字符串的长度(不包含’\0)

注意:实际编程中不要再使用该函数,请使用 StringCchLength 或 StringCbLength 代替。

API 函数原型:

1
2
3
int WINAPI lstrlen(
_In_ LPCTSTR lpString
);

参数解析:

参数 含义
lpString 指向以’\0’为终止符的字符串

返回值:

  1. 该函数返回指定字符串的字符数;

  2. 如果是空字符串,则返回 0。

MessageBox

函数功能:

MessageBox 函数用于显示一个模态对话框,其中包含一个系统图标、 一组按钮和一个简短的特定于应用程序消息,如状态或错误的信息。

消息框中返回一个整数值,该值指示用户单击了哪个按钮。

API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。

1
2
3
4
5
6
int WINAPI MessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType
);

参数解析:

参数 含义
hWnd 1. 该消息框的父窗口句柄 2. 如果此参数为NULL,则该消息框没有拥有父窗口
lpText 消息框的内容
lpCaption 消息框的标题
uType 1. 指定一个决定对话框的内容和行为的位标志集 2. 此参数可以通过指定下列标志或标志的组合,来显示消息框中的按钮以及图标

uType参数定义解析

按钮 含义
MB_OK 默认值,有一个“确认”按钮在里面
MB_YESNO 有“是”和“否”两个按钮在里面
MB_ABORTRETRYIGNORE 有“中止”,“重试”和“跳过”三个按钮在里面
MB_YESNOCANCEL 有“是”,“否”和“取消”三个按钮在里面
MB_RETRYCANCEL 有“重试”和“取消”两个按钮在里面
MB_OKCANCEL 有“确定”和“取消”两个按钮在里面
图标 含义
MB_ICONEXCLAMATION 一个惊叹号出现在消息框:IC534153.png
MB_ICONWARNING 一个惊叹号出现在消息框(同上)
MB_ICONINFORMATION 一个圆圈中小写字母i组成的图标出现在消息框:IC534154.png
MB_ICONASTERISK 一个圆圈中小写字母i组成的图标出现在消息框(同上)
MB_ICONQUESTION 一个问题标记图标出现在消息框:IC534152.png
MB_ICONSTOP 一个停止消息图标出现在消息框:IC534151.png
MB_ICONERROR 一个停止消息图标出现在消息框(同上)
MB_ICONHAND 一个停止消息图标出现在消息框(同上)
默认按钮 含义
MB_DEFBUTTON1 指定第一个按钮为默认按钮
MB_DEFBUTTON2 指定第二个按钮为默认按钮
MB_DEFBUTTON3 指定第三个按钮为默认按钮
MB_DEFBUTTON4 指定第四个按钮为默认按钮
消息框形态 含义
MB_APPLMODAL 1. 在 hWnd 参数标识的窗口中继续工作以前,用户一定响应消息框 2. 但是,用户可以移动到其他线程的窗口且在这些窗口中工作 3. 根据应用程序中窗口的层次机构,用户则以移动到线程内的其他窗口 4. 所有母消息框的子窗口自动地失效,但是弹出窗口不是这样 5. 如果既没有指定 MB_SYSTEMMODAL 也没有指定 MB_TASKMODAL,则 MB_APPLMODAL 为默认的
MB_SYSTEMMODAL 1. 除了消息框有 WB_EX_TOPMOST 类型,否则 MB_APPLMODAL 和 MB_SYSTEMMODAL 一样 2. 用系统模态消息框来改变各种各样的用户,主要的损坏错误需要立即注意(例如,内存溢出) 3. 如果不是那些与 hWnd 联系的窗口,此标志对用户对窗口的相互联系没有影响
MB_TASKMODAL 1. 如果参数 hWnd 为 NULL 的话,那么除了所有属于当前线程高层次的窗口失效外,MB_TASKMODAL 和 MB_APPLMODAL 一样 2. 当调用应用程序或库没有一个可以得到的窗口句柄时,可以使用此标志,但仍需要阻止输入到调用线程的其他窗口,而不是搁置其他线程
其他标志 含义
MB_DEFAULT_DESKTOP_ONLY 1. 接收输入的当前桌面一定是一个默认桌面,否则函数调用失败 2. 默认桌面是一个在用户已经记录且以后应用程序在此上面运行的桌面
MB_HELP 1. 把一个 Help 按钮增加到消息框 2. 选择 Help 按钮或按 F1 产生一个 Help 事件
MB_RIGHT 文本为右对齐
MB_RTLREADING 用在 Hebrew 和 Arabic 系统中从右到左的顺序显示消息和大写文本
MB_SETFOREGROUND 1. 消息框变为前景窗口 2. 在内部系统为消息个调用 SetForegroundWindow 函数
MB_TOPMOST 消息框用 WS_EX_TOPMOST 窗口类型来创建 MB_SERVICE_NOTIFICATION
参数 含义
hWnd 1. 该消息框的父窗口句柄 2. 如果此参数为NULL,则该消息框没有拥有父窗口
lpText 消息框的内容
lpCaption 消息框的标题
uType 1. 指定一个决定对话框的内容和行为的位标志集 2. 此参数可以通过指定下列标志或标志的组合,来显示消息框中的按钮以及图标

返回值:

返回值 含义
IDOK 用户按下了“确认”按钮
IDCANCEL 用户按下了“取消”按钮
IDABORT 用户按下了“中止”按钮
IDRETRY 用户按下了“重试”按钮
IDIGNORE 用户按下了“忽略”按钮
IDYES 用户按下了“是”按钮
IDNO 用户按下了“否”按钮

PostQuitMessage

函数原型:

PostQuitMessage 函数向系统表明有个线程提出终止(退出)请求。

这个函数通常用来响应 WM_DESTROY 消息。

API 函数原型:

1
2
3
VOID WINAPI PostQuitMessage(
_In_ int nExitCode
);

参数解析:

参数 含义
nExitCode 指定应用程序的退出代码,此值被用作 WM_QUIT 消息的 wParam 参数

返回值:

该函数没有返回值。

备注:

  1. PostQuitMessage 函数的功能是发送一个 WM_QUIT 消息给线程的消息队列并立即返回。

  2. 当线程从消息队列里取得 WM_QUIT 消息时,应当退出消息循环并将返回系统,返回给系统的退出值必须是消息 WM_QUIT 的 wParam 参数(所以 WinMain 函数的返回值是 msg.wParam)。

SetScrollRange

函数功能:

SetScrollRange 函数设置所指定滚动条范围的最小值和最大值。

注意:SetScrollRange 函数提供了向后的兼容性。但新的应用程序应该提倡使用 SetScrollInfo 函数代替。

API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。

1
2
3
4
5
6
7
BOOL SetScrollRange(
_In_ HWND hWnd,
_In_ int nBar,
_In_ int nMinPos,
_In_ int nMaxPos,
_In_ BOOL bRedraw
);

参数解析:

参数 含义
hWnd 1. 滚动条控件的句柄或带有标准滚动条窗体的句柄 2. 由 nBar 参数的值确定
nBar 指定将要设置哪类滚动条的参数: 1. SB_CTL:设置滚动条控件的范围,要求参数 hwnd 必须是滚动条控件的句柄 2. SB_HORZ:设置窗体的标准水平滚动条的范围 3. SB_VERT:设置窗体的标准垂直滚动条的范围
nMinPos 指定滚动位置的最小值
nMaxPos 指定滚动位置的最大值
bRedraw 指定滚动条是否被重画以反映变化(如果这个参数为 TRUE,滚动条将被重画;如果为 FALSE 则不被重画)

返回值:

  1. 如果函数调用成功,返回值为非 0;

  2. 如果函数调用失败,返回值为 0。

备注:

  1. 将 SetScrollRange 函数中的 nMinPos 和 nMaxPos 参数设置为一样的值,可以达到隐藏滚动条的目的。但在处理滚动条消息时,应用程序不应该调用 SetScrollRange 函数来隐藏滚动条。新的应用程序应该调用 ShowScrollBar 函数来隐藏滚动条。

  2. 如果调用 SetScrollPos 函数之后马上调用 SetScrollRange 函数,则 SetScrollPos 函数中的 bRedraw 参数一定要设置为零值(FALSE),以防止滚动条被画两次。

  3. 标准滚动条的缺省范围是 0 到 100。滚动条控件的缺省值为 NULL(参数 nMinPos 和 nMaxPos 的值均为零)。两个范围值之间的不同之处在于由参数 nMinPos 和 nMaxPos 指定,不过不能超过 MAXLONG 定义的大小。

  4. 因为说明滚动条位置的消息 WM_HSCROLL 和 WM_VSCROLL 是 16 位数据,所以那些只依赖于说明位置数据消息的应用程序在 SetScrollRange 函数的参数 nMaxPos 中有一个实际最大值 65,535。但是,因为 SetScrolllnfo,SetScrollPos, SetScrollRange,GetScrolllnfo,GetScrollPos 和 GetScrollRange 函数都支持 32 位的滚动条位置数据,所以有一个解决 16 位 WM_HSCROLL 和 WM_VSCROLL 消息阻碍的途径,请参见函数 GetScrolllnfo 的有关技术说明。

  5. 如果参数 nBar 设置为 SB_CTL 并且参数 hWnd 所标识的不是一个标准的滚动条控件。系统将发送一个 SBM_SETRANGE 消息到窗体用以设置滚动条消息。这将允许 SetScrollRange 函数操作一个定制的伪滚动条控件。如果窗体没有处理 SBM_SETRANGE 消息,SetScrollRange 函数将调用失败。

SetTextAlign

函数功能:

SetTextAlign 函数为指定设备环境设置文本的对齐标志。

API 函数原型:

1
2
3
4
UINT SetTextAlign(
_In_ HDC hdc,
_In_ UINT fMode
);

参数解析:

参数 含义
hdc 指定设备环境句柄
fMode 1. 文本对齐标志 2. 在横向对齐和纵向对齐标志中只能选择一个 3. 两个标志只能选择一个来改变当前的位置

使用下面的列表中的掩码指定文本对齐方式:

含义
TA_BASELINE 基准点在正文的基线上
TA_BOTTOM 基准点在限定矩形的底边上(限定矩形的含义请看下边备注)
TA_TOP 基准点在限定矩形的顶边上
TA_CENTER 基准点在限定矩形的中心水平对齐位置
TA_LEFT 基准点在限定矩形的左边上
TA_RIGHT 基准点在限定矩形的右边上
TA_NOUPDATECP 1. 适用于中东 Windows 版本:正文从右到左的阅读顺序排列,与缺省的从左到右正好相反 2. 只有当被选择的字体是 Hebrew 或 Arabic 时,此值才有用
TA_RTLREADING 每次输出调用后当前状态不改变
TA_UPDATECP 每次输出调用后当前状态改变

若当前字体有一条缺省的垂直基线(如Kanji),下列值用于取代 TA_BASELINE 和 TA_CENTER:

含义
VTA_BASELINE 基准点在正文的基线上
VTA_CENTER 基准点与限定矩形的中心垂直对齐

默认值是 TA_LEFT, TA_TOP 和 TA_NOUPDATECP。

返回值:

  1. 如果函数调用失败,返回值是 GDI_ERROR;

  2. 如果函数调用成功,返回值是文字对齐方式的前一个设置。

备注:

  1. 限定矩形是指能将正文字符串的所有字符单元限定于其中的矩形

  2. TextOut 和 ExtTextOut 函数用文字对齐标志来将一个正文字符串定位于显示器或者其他设备

  3. 该标志指定了基准点与限定正文的矩形的位置关系,基准点可以是当前位置,也可是传给正文输出函数的一个点

  4. 设置左对齐文本的做好方法可以是如下:

1
SetTextAlign (hdc, GetTextAlign(hdc) & (~TA_CENTER))

1
SetTextAlign (hdc,TA_LEFT | <other flags>)

你当然可以使用 SetTextAlign (hdc, TA_LEFT) 来达到这个目的,但是这个方法会丢失所有的垂直基线或者从右到左的设置。

  1. 调用 SetTextAlign 函数时,如果使用 TA_UPDATECP 标志,Windows 会忽略 TextOut 的 xStart 和 yStart 参数,而使用由 MoveToEx、LineTo 或更改目前位置的另一个函数设定的位置。

ShowWindow

函数功能:

ShowWindow 函数用于设置窗口的显示状态。

应用程序第一次调用 ShowWindow 时,应该使用 WinMain 函数的 nCmdshow 参数作为它的 nCmdShow 参数。在随后调用 ShowWindow 函数时,必须使用下列显示方式中的一个给定值,而不是由 WinMain 函数的 nCmdSHow 参数指定的值。

API 函数原型:

1
2
3
4
BOOL WINAPI ShowWindow(
_In_ HWND hWnd,
_In_ int nCmdShow
);

参数解析:

参数 含义
hWnd 窗口句柄
nCmdShow 控制窗口如何显示,如果发送应用程序的程序提供了 STARTUPINFO 结构,则应用程序第一次调用 ShowWindow 时该参数被忽略。否则,在第一次调用 ShowWindow 函数时,该值应为在函数 WinMain 中 nCmdShow 参数。

在随后的调用中,nCmdShow 参数可以为下列值之一:

显示方式 含义
SW_FORCEMINIMIZE 1. 最小化窗口,即使拥有窗口的线程被挂起也会最小化 2. 在从其他线程最小化窗口时才使用这个参数
SW_HIDE 隐藏窗口并激活其他窗口
SW_MAXIMIZE 最大化指定的窗口
SW_MINIMIZE 最小化指定的窗口并且激活在 Z 序中的下一个顶层窗口
SW_RESTORE 1. 激活并显示窗口 2. 如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置 3. 在恢复最小化窗口时,应用程序应该指定这个标志。
SW_SHOW 在窗口原来的位置以原来的尺寸激活并显示窗口
SW_SHOWDEFAULT 依据在 STARTUPINFO 结构中指定的 SW_FLAG 标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给 CreateProcess 函数的。
SW_SHOWMAXIMIZED 激活窗口并将其最大化
SW_SHOWMINIMIZED 激活窗口并将其最小化
SW_SHOWMINNOACTIVE 1. 窗口最小化 2. 在窗口激活的情况下,这个值跟 SW_SHOWMINIMIZED 很相似
SW_SHOWNA 1. 以窗口原来的位置以原来的尺寸显示窗口 2. 在窗口激活的情况下,这个值跟 SW_SHOW 很相似
SW_SHOWNOACTIVATE 1. 以窗口最近一次的位置和尺寸显示窗口 2. 在窗口激活的情况下,这个值跟 SW_SHOWNORMAL 很相似
SW_SHOWNORMAL 1. 激活并显示一个窗口 2. 如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小 3. 应用程序在第一次显示窗口的时候应该指定此标志

返回值:

  1. 如果窗口之前可见,则返回值为非 0;

  2. 如果窗口之前被隐藏,则返回值为 0。

StringCchCat

函数功能:

StringCchCat 函数的功能是将一个字符串拼接到另一个字符串。StringCchCat 函数要求提供目标缓冲区的长度,以确保写入数据不会超出缓冲区的末尾。

微软推荐使用该函数替代以下函数:

  • strcat, wcscat, _tcsat
  • lstrcat
  • StrCat
  • StrCatBuff

API 函数原型:

1
2
3
4
5
HRESULT StringCchCat(
_Inout_ LPTSTR pszDest,
_In_ size_t cchDest,
_In_ LPCTSTR pszSrc
);

参数解析:

参数 含义
pszDest 1. 目标缓冲区,同时包含第一个字符串 2. 该缓冲区必须大于或等于 pszDest + pszSrc + 1(两个字符串的字符总和+’\0’)
cchDest 1. 目标缓冲区的大小(字符个数) 2. 该值必须大于或等于 pszDest + pszSrc + 1(两个字符串的字符总和+’\0’) 3. 这个数不能超过 STRSAFE_MAX_CCH
pszSrc 第二个字符串

返回值:

这个函数返回一个 HRESULT,而不是拼接好的字符串指针。我们强烈建议您使用 SUCCEEDEDFAILED 宏来测试这个函数的返回值。

返回值可以是以下任意一个值:

返回代码 描述
S_OK 字符串正常拼接
STRSAFE_E_INVALID_PARAMETER 1. cchDest 参数的值为 0 2. cchDest 参数的值大于 STRSAFE_MAX_CCH 3. 目标缓冲区空间已满
STRSAFE_E_INSUFFICIENT_BUFFER 1. 因缓冲区空间不足导致失败 2. 结果被截断,当仍然包含’\0’结尾 3. 如果截断操作可以被接受,则不一定被看作是失败

备注:

使用 StringCchCat 函数需要添加头文件:strsafe.h

StringCchCopy

函数功能:

StringCchCopy 函数的功能是复制一个字符串到缓冲区。StringCchCopy 函数要求提供目标缓冲区的长度,以确保写入数据不会超出缓冲区的末尾。

微软推荐使用该函数替代以下函数:

  • strcpy, wcscpy, _tcscpy
  • lstrcpy
  • StrCpy

API 函数原型:

1
2
3
4
5
HRESULT StringCchCopy(
_Out_ LPTSTR pszDest,
_In_ size_t cchDest,
_In_ LPCTSTR pszSrc
);

参数解析:

参数 含义
pszDest 缓冲区,用于接收拷贝过来的字符串
cchDest 1. 目标缓冲区的大小(字符个数) 2. 该值必须大于或等于 pszSrc + 1(待拷贝字符串的字符+’\0’) 3. 这个数不能超过 STRSAFE_MAX_CCH
pszSrc 待拷贝的字符串

返回值:

这个函数返回一个 HRESULT,而不是指向缓冲区的指针。我们强烈建议您使用 SUCCEEDED 和 FAILED 宏来测试这个函数的返回值。

返回值可以是以下任意一个值:

返回代码 描述
S_OK 字符串正常拷贝
STRSAFE_E_INVALID_PARAMETER 1. cchDest 参数的值为 0 2. cchDest 参数的值大于 STRSAFE_MAX_CCH
STRSAFE_E_INSUFFICIENT_BUFFER 1. 因缓冲区空间不足导致失败 2. 结果被截断,当仍然包含’\0’结尾 3. 如果截断操作可以被接受,则不一定被看作是失败

StringCchLength

函数功能:

StringCchLength 函数用于确定字符串是否超过了规定的长度,以字符为计算单位。

微软推荐使用该函数替代以下函数:

  • strlen, wcslen, _tcslen

API 函数原型:

1
2
3
4
5
HRESULT StringCchLength(
_In_ LPCTSTR psz,
_In_ size_t cchMax,
_Out_ size_t *pcch
);

参数解析:

参数 含义
psz 指向待检查的字符串
cchMax 1. psz 参数里最大允许的字符数量,包括’\0’ 2. 这个数不能超过 STRSAFE_MAX_CCH
pcch 1. psz 参数指向字符串的字符个数,不包括’\0’ 2. 这个值只有在 psz 指针不为 NULL,且函数成功时有效

返回值:

这个函数返回一个 HRESULT,而不是指定字符串的字符个数。我们强烈建议您使用 SUCCEEDEDFAILED 宏来测试这个函数的返回值。

返回值可以是以下任意一个值:

返回代码 描述
S_OK psz 指向的字符串不为空,且字符串的长度(包括’\0’)小于等于 cchMax
STRSAFE_E_INVALID_PARAMETER 1. psz 指向空字符串 2. cchMax 的值大于STRSAFE_MAX_CCH 3. psz 指向的字符串的字符个数超过 cchMax

备注:

  1. 对比 StringCchLength 所替代的函数,StringCchLength 是可以使你的代码正确处理缓存区的一个附加功能。因为小的缓冲处理会牵连很多安全问题,例如缓存区溢出

  2. 使用 StringCchLength 函数需要添加头文件:strsafe.h

StringCchPrintf

函数功能:

StringCchPrintf 函数用于把数据格式化写入到指定的缓冲区里,该函数要求提供目标缓冲区的大小,确保不会发生越界访问。

微软推荐使用该函数替代以下函数:

  • sprintf, swprintf, _stprintf
  • wsprintf
  • wnsprintf
  • _snprintf, _snwprintf, _sntprintf

API 函数原型:

1
2
3
4
5
6
HRESULT StringCchPrintf(
_Out_ LPTSTR pszDest,
_In_ size_t cchDest,
_In_ LPCTSTR pszFormat,
_In_ ...
);

参数解析:

参数 含义
pszDest 指定格式化数据将要写入的缓冲区
cchDest 1. 缓冲区大小 2. 应该设置足够大,以容纳字符串和结束标记(’\n’) 3. 最大允许的字符数是 STRSAFE_MAX_CCH
pszFormat 1. 格式化字符串 2. 与 pirntf 的格式化字符串一致
可变参数,参数的个数取决 pszFormat 参数

返回值:

这个函数返回一个 HRESULT,而不是像 sprintf 一样返回存储在其目标缓冲区的字节数。我们强烈建议您使用 SUCCEEDEDFAILED 宏来测试这个函数的返回值。

返回值可以是以下任意一个值:

返回代码 描述
S_OK 表示有足够的空间将拷贝到 pszDest,没有发生截断
STRSAFE_E_INVALID_PARAMETER cchDest 的值为 0 或大于 STRSAFE_MAX_CCH
STRSAFE_E_INSUFFICIENT_BUFFER 1. 由于缓冲区空间不足而导致的复制失败 2. 结果被截断,当仍然包含’\0’结尾 3. 如果截断操作可以被接受,则不一定被看作是失败

备注:

使用 StringCchPrintf 函数需要添加头文件:strsafe.h

代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
#include "strsafe.h"

......

TCHAR pszDest[30];
size_t cchDest = 30;

LPCTSTR pszFormat = TEXT("从你家到鱼C工作室需要 %f 公里!");

HRESULT hr = StringCchPrintf(pszDest, cchDest, pszFormat, 123.45);

......

TextOut

函数功能:

TextOut 函数使用当前选择的字体、背景颜色和文本颜色,将一个字符串绘制于窗口的指定位置。

API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。

1
2
3
4
5
6
7
BOOL TextOut(
_In_ HDC hdc,
_In_ int nXStart,
_In_ int nYStart,
_In_ LPCTSTR lpString,
_In_ int cchString
);

参数解析:

参数 含义
hdc 设备环境句柄
nXStart 指定用于字符串对齐的基准点的逻辑 x 坐标(有关基准点请看下边备注)
nYStart 指定用于字符串对齐的基准点的逻辑 y 坐标
lpString 1. 指向将被绘制字符串的指针 2. 该字符串不必以’\0’结束,因为 cchString 参数指定了该字符串的长度
cchString lpString 字符串的长度(有多少个字符)

返回值:

  1. 如果函数调用成功,返回值为非 0;

  2. 如果函数调用失败,返回值为 0。

备注:

字符串对齐的基准点取决于当前的文本对齐模式。应用程序可以通过调用 GetTextAlign 获得当前的文本对齐模式,通过调用 SetTextAlign 修改该模式。

TranslateMessage

函数功能:

TranslateMessage 函数将虚拟键消息转换为字符消息,字符消息被寄送到当前线程的消息队列里。

当下一次线程调用函数 GetMessage 或 PeekMessage 时被读出。

API 函数原型:

1
2
3
BOOL WINAPI TranslateMessage(
_In_ const MSG *lpMsg
);

参数解析:

参数 含义
lpMsg 指向含有消息的 MSG 结构的指针

返回值:

  1. 如果消息被转换(字符消息被寄送到当前线程的消息队列里)则返回非零值;

  2. 如果消息是 WM_KEYDOWN,WM_KEYUP WM_SYSKEYDOWN 或 WM_SYSKEYUP,返回非零值,不考虑转换;

  3. 如果消息没被转换(字符消息没被寄送到调用线程的消息队列里)则返回值是零。

UpdateWindow

函数功能:

UpdateWindow 函数绕过应用程序的消息队列,直接发送 WM_PAINT 消息给指定窗口的窗口过程。

如果窗口更新的区域不为空,UpdateWindow 函数通过发送一个 WM_PAINT 消息来更新指定窗口的客户区。如果更新区域为空,则不发送消息。

API 函数原型:

1
2
3
BOOL UpdateWindow(
_In_ HWND hWnd
);

参数解析:

参数 含义
hWnd 指定要更新的窗口的句柄.

返回值:

  1. 如果函数调用成功,返回值为非 0;

  2. 如果函数调用不成功,返回值为 0。

wsprintf

函数功能

  • wsprintf 函数将格式化字符串写入到指定的缓冲区里
  • 输出缓冲区里的的值取决于格式说明符(即”%”)
  • 如果写入的是文字,此函数给写入的文字的末尾追加一个’\0’
  • 函数的返回值是写入的长度,但不包括最后的’\0’

注意:实际编程中不要再使用该函数,请使用 StringCchPrintf 或 StringCbPrint 代替。

API 函数原型:

1
2
3
4
5
int __cdecl wsprintf(
_Out_ LPTSTR lpOut,
_In_ LPCTSTR lpFmt,
_In_ ...
);

参数解析:

参数 含义
lpOut 1. 指定格式化数据将要写入的缓冲区 2. 缓冲区限定最大为 1024 字节
lpFmt 1. 格式化字符串 2. 与 printf 的格式化字符串基本一致,但不支持浮点数
可变参数,参数的个数取决 lpFmt 参数

返回值:

  1. 如果函数调用成功,返回值与计划写入缓冲区的字符个数相等(不包含最后的’\0’);

  2. 如果函数调用失败,返回值小于计划写入缓冲区的字符个数,可通过调用 GetLastError 获取详细的错误信息。

结构

MSG 结构

MSG 消息结构

在 Windows 程序中,消息是由 MSG 结构体来表示的。

结构原型:

1
2
3
4
5
6
7
8
typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG, *LPMSG;

成员解析:

成员 含义
hwnd 指定接收消息的窗口句柄 如果是线程消息,该值是 NULL
message 1. 消息的标识符,由于数值不便于记忆,所以 Windows 将消息对应的数值定义为 WM_XXX 宏的形式 2. 应用程序消息只能使用低 16 位,高 16 位被系统保留 3. 传送门:Windows 常用消息及含义
wParam 指定消息的附加消息,确切的含义取决于消息成员的值
lParam 指定消息的附加消息,确切的含义取决于消息成员的值
time 该消息被投放到消息队列的时间
pt 当消息被投放到消息队列的时,鼠标位于屏幕中的位置

PAINTSTRUCT 结构

PAINTSTRUCT 结构包含一些窗口过程用来对客户区进行绘制的信息。

结构原型:

1
2
3
4
5
6
7
8
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;

成员解析:

成员 含义
hdc 用于绘制的设备环境句柄
fErase 1. 表示背景是否必须擦除,如果为非零值则擦除背景,否则不擦除背景 2. 如果创建窗口类的时候没有设置背景画刷,则负责擦除背景
rcPaint 一个 RECT 结构,指定左上角和右下角的坐标确定一个要绘制的矩形范围
fRestore 系统保留
fIncUpdate 系统保留
rgbReserved 系统保留

RECT 结构

RECT 结构定义了一个矩形的左上角和右下角的坐标。

结构原型:

1
2
3
4
5
6
typedef struct _RECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT;

成员解析:

成员 含义
left 指定矩形左上角的 x 坐标
top 指定矩形左上角的 y 坐标
right 指定矩形右下角的 x 坐标
bottom 指定矩形右下角的 y 坐标

TEXTMETRIC 结构

TEXTMETRIC 结构记录当前设备环境中有关字体的各种信息。

TEXTMETRIC 结构成员的值的单位取决于设备环境中当前选定的映射模式,默认的映射模式是 MM_TEXT,所以它们的值是以像素为单位的。

结构原型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef struct tagTEXTMETRIC {
LONG tmHeight;
LONG tmAscent;
LONG tmDescent;
LONG tmInternalLeading;
LONG tmExternalLeading;
LONG tmAveCharWidth;
LONG tmMaxCharWidth;
LONG tmWeight;
LONG tmOverhang;
LONG tmDigitizedAspectX;
LONG tmDigitizedAspectY;
TCHAR tmFirstChar;
TCHAR tmLastChar;
TCHAR tmDefaultChar;
TCHAR tmBreakChar;
BYTE tmItalic;
BYTE tmUnderlined;
BYTE tmStruckOut;
BYTE tmPitchAndFamily;
BYTE tmCharSet;
} TEXTMETRIC, *PTEXTMETRIC;

成员解析:

成员 含义
tmHeight 字符高度(tmAscent + tmDescent)
tmAscent 字符上部高度(基线以上)
tmDescent 字符下部高度(基线以下)
tmInternalLeading 内部间距(包含在 tmHeight 中),该间距通常被用于显示重音符号
tmExternalLeading 外部间距,这个值是字体设计者建议在两行文字间留出的空间大小
tmAveCharWidth 1. 字体中小写字符的平均宽度(一般定义为字母 x 的宽度) 2. 字体中大写字符的平均宽度一般是该值的 1.5 倍计算 3. 此值不包括字体所需要的加粗和倾斜字符
tmMaxCharWidth 字体中最宽字符的宽度
tmWeight 字体的粗细轻重程度
tmOverhang 加入某些拼接字体上的附加高度
tmDigitizedAspectX 字体设计所针对的设备水平方向
tmDigitizedAspectY 字体设计所针对的设备垂直方向
tmFirstChar 为字体定义的第一个字符
tmLastChar 为字体定义的最后一个字符
tmDefaultChar 字体中所没有字符的替代字符
tmBreakChar 定义文本对齐截断操作所显示的字符
tmItalic 如果该值非零,则为斜体字体
tmUnderlined 如果该值非零,则为带下横线字体
tmStruckOut 如果该值非零,则为带删除线字体(字符中间画一条线)
tmPitchAndFamily 1. 如果低位为 0,表示等宽字体,小写和大写字母平均宽度一样 2. 如果低位为 1,表示变宽字体,大写字母是小写平均宽度的 3/2 倍
tmCharSet 字体的字符集

WNDCLASS 结构

​ Windows 的窗口总是基于窗口类来创建的,窗口类同时确定了处理窗口消息的窗口过程(回调函数)。

​ 在创建应用程序窗口之前,必须调用 RegisterClass 函数来注册窗口类。该函数只需要一个参数,即指向 WNDCLASS 窗口类的指针。因为 WNDCLASS 类包含了窗口所拥有的基本属性。

结构原型:

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct tagWNDCLASSW {
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCWSTR lpszMenuName;
LPCWSTR lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;

成员解析:

成员 含义
style 指定窗口类型,各种“类风格”(详见下方↓)可以使用按位或操作符组合起来
lpfnWndProc 指定窗口过程(必须是回调函数)
cbClsExtra 预留的额外空间,一般为 0
cbWndExtra 预留的额外空间,一般为 0
hInstance 应用程序的实例句柄
hIcon 为所有基于该窗口类的窗口设定一个图标
hCursor 为所有基于该窗口类的窗口设定一个鼠标指针
hbrBackground 指定窗口背景色
lpszMenuName 指定窗口菜单
lpszClassName 指定窗口类名

style 类风格解析

类风格 含义
CS_VREDRAW 移动或者调整窗口的高度(垂直方向)时,重绘整个窗口
CS_HREDRAW 移动或者调整窗口的宽度(水平方向)时,重绘整个窗口
CS_DBLCLKS 当用户光标在窗口内双击时,允许发送双击消息给窗口过程
CS_OWNDC 给予每个窗口实例分配一个唯一的 DC(注意,尽管这样是很方便,但它必须慎重使用,因为每个 DC 大约要占 800 个字节的内存)
CS_CLASSDC 该窗口类的所有窗口实例都共享一个窗口类 DC
CS_PARENTDC 1. 将子窗口的裁剪区域设置到父窗口的 DC 中去,这样子窗口便可以在父窗口上绘制自身。(注意,这是子窗口从系统缓存中获取 DC,而不是使用父窗口的 DC。) 2. 指定该风格可以提高系统性能
CS_NOCLOSE 禁止系统菜单的关闭选项
CS_SAVEBITS 1. 以位图形式保存被该窗口遮挡的屏幕部分,当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息 2. 该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失 3. 设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存
CS_BYTEALIGNCLIENT 在字节边界上(在 x 方向上)定位窗口的用户区域的位置
CS_BYTEALIGNWINDOW 在字节边界上(在 x 方向上)定位窗口的位置
CS_GLOBALCLASS 1. 当调用 CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的 hInstance 参数和注册窗口类时传递给 RegisterClass 的 hInstance 参数不同 2. 如果不指定该风格,则这两个 hInstance 必须相同

GET_X_LPARAM 和 GET_Y_LPARAM 宏

原文链接(GET_X_LPARAM)-> 传送门

原文链接(GET_Y_LPARAM)-> 传送门

宏功能:

通过 lParam 参数获得相关消息触发的坐标 (x , y)

宏定义:

1
2
3
4
5
6
7
int GET_X_LPARAM(
LPARAM lParam
);
……
int GET_Y_LPARAM(
LPARAM lParam
);

参数解析:

参数 含义
lParam 将要被转换的 lParam 参数

返回值:

  1. GET_X_LPARAM(lParam) 返回坐标的 x 值;

  2. GET_Y_LPARAM(lParam) 返回坐标的 y 值。

重要备注:

  1. 使用该宏需要包含头文件:windowsx.h。

  2. 不要再使用 LOWORD 和 HIWORD 去获取鼠标的坐标了,因为在多显示器的情况下会得到错误的坐标。

SUCCEEDED 和 FAILED 宏

原文链接(SUCCEEDED)-> 传送门

原文链接(FAILED)-> 传送门

宏功能:

SUCCEEDED 宏表示测试成功,FAILED 宏表示测试失败。

宏原型:

1
2
3
4
5
6
7
BOOL SUCCEEDED(
HRESULT hr
);
……
BOOL FAILED(
HRESULT hr
);

参数解析:

参数 含义
hr 1. 状态码 2. 该值可以是 HRESULT 或 SCODE 类型 3. 非负数表示成功 4. 负数表示失败

返回值:

  1. 如果 hr 的值大于等于 0,则结果为 TRUE;

  2. 如果 hr 的值小于 0,则结果为 FALSE。