学习视频连接
【SDK开发】《Windows程序设计》_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1us411A7UE?p=9&spm_id_from=pageDriver
一、前面章节的难点 1.1 关闭确认1、流程
如果我的程序需要在关闭前让用户判断是否确定要关闭窗口,我应该响应哪个消息呢?
如下图所示
2、错误的写法
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("大家好,这是我的第一个窗口程序!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_DESTROY:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
PostQuitMessage(0);
}
else {
return 0;
}
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
存在的问题,选择的时候点了否,窗口没有重新打开,并且后台有进程
3、正确的写法
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("大家好,这是我的第一个窗口程序!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
1.2 程序未响应
如果一个case结束不了,这个程序就未响应了
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("大家好,这是我的第一个窗口程序!"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
while (1) {}
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
点一下屏幕中间,程序就卡住了
二、文本输出 2.1 三大核心部件我们所调用的大部分 api 都是封装在三大子系统中的
kernel:内核相关 内存管理、文件输入输出、任务管理
user:用户相关 窗口管理、用户界面、GUI
2.2 设备环境1、定义
设备环境句柄是应用程序使用 GDI 函数的通行证
2、获取设备环境句柄
方法一:响应 WM_PAINT 消息时候使用
hdc = BeginPaint(hwnd, &ps); // 使用 GDI 函数
EndPaint(hwnd, &ps);
方法二:
hdc = GetDC(hwnd); // 使用 GDI 函数
ReleaseDC(hwnd, hdc);
3、前面有使用设备环境句柄绘制文本的代码
2.3 TextOut1、结构体
BOOL TextOut( _In_ HDC hdc, _In_ int nXStart, _In_ int nYStart, _In_ LPCTSTR lpString, _In_ int cchString );
2、参数解析:
| 参数 | 含义 |
| hdc | 设备环境句柄 |
| nXStart | 指定用于字符串对齐的基准点的逻辑 x 坐标(有关基准点请看下边备注) |
| nYStart | 指定用于字符串对齐的基准点的逻辑 y 坐标 |
| lpString | 1. 指向将被绘制字符串的指针 2. 该字符串不必以' '结束,因为 cchString 参数指定了该字符串的长度 |
| cchString | lpString 字符串的长度(有多少个字符) |
3、返回值:
(1) 如果函数调用成功,返回值为非 0
(2) 如果函数调用失败,返回值为 0
4、代码:
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 400, 300, TEXT("I love China"), 12);
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
如果字符少于 12,则显示不全;如果字符多余12,则多的部分显示乱码
三、安全的使用字符串 3.1 字符串处理函数 3.2 简单使用循环打印内容LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TCHAR szBuffer[128] = TEXT("I love China!");
int i;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0; i < 10; i++) {
TextOut(hdc, 0, i * 20, szBuffer, 13);
}
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
3.3 合并字符串
1、代码
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TCHAR szBuffer[128];
int i;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0; i < 10; i++) {
wsprintf(szBuffer, TEXT("%d: %s"), i + 1, TEXT("I love China!"));
TextOut(hdc, 0, i * 20, szBuffer, 16);
}
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
2、出现的问题:
第 10 行少了感叹号
修改方案1
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TCHAR szBuffer[128];
int i;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0; i < 10; i++) {
wsprintf(szBuffer, TEXT("%3d: %s"), i + 1, TEXT("I love China!"));
TextOut(hdc, 0, i * 20, szBuffer, 18);
}
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
修改方案2
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TCHAR szBuffer[128];
int i;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0; i < 10; i++) {
wsprintf(szBuffer, TEXT("%d: %s"), i + 1, TEXT("I love China!"));
TextOut(hdc, 0, i * 20, szBuffer, lstrlen(szBuffer));
}
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
3.4 缓冲区溢出
1、缓冲区大小为 12
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TCHAR szBuffer[10];
int i;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0; i < 10; i++) {
wsprintf(szBuffer, TEXT("%d: %s"), i + 1, TEXT("I love China!"));
TextOut(hdc, 0, i * 20, szBuffer, lstrlen(szBuffer));
}
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
2、没有设置结束点
lstrlen 判断结束点是找到最近的一个 ' '
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
TCHAR szBuffer[] = {'A', 'B', 'c', 'D'};
int i, j;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
for (i = 0; i < 10; i++) {
// wsprintf(szBuffer, TEXT("%d: %s"), i + 1, TEXT("I love China!"));
j = lstrlen(szBuffer);
TextOut(hdc, 0, i * 20, szBuffer, j);
}
EndPaint(hwnd, &ps);
return 0;
case WM_LBUTTONUP:
MessageBox(hwnd, TEXT("我被按了一下"), TEXT("我是标题"), MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(hwnd, TEXT("是否真的关闭?"), TEXT("请确认"), MB_YESNO) == IDYES) {
DestroyWindow(hwnd);
}
else {
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
3.5 安全的字符串处理函数
题目:要求打印10行字符串到窗口上,然后要求每行显示出行号



