0. 视频
1. 使用的 Windows API 函数
GetSystemMetrics
原型:
int GetSystemMetrics(int nIndex);
参考: GetSystemMetrics
说明: 查询(检索)指定的 Windows (下同)系统的配置或度量。
在本例中,我们使用的 入参 nIndex 有两个:
- SM_CXFULLSCREEN : 取主桌面的屏幕宽度;
- SM_CYFULLSCREEN :取主桌面的屏幕高度。
注意:
- 如果有多个显示器,仅取主桌面;
- 经实测,宽度或高度不会包含任务栏。即:如任务栏布置为横向(常见:底部),则取桌面高度时,不含任务栏高度,如果任务栏布置为竖向,则取桌面宽度时,不含任务的宽度。
本课使用:
DesktopWidth = ::GetSystemMetrics(SM_CXFULLSCREEN); DesktopHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);
SetTimer
原型:
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
);
参考: SetTimer
说明: 设置一个定时器。
入参:
- hwnd:指定 定时器要绑定的窗口的句柄;该窗口可接收定时消息,也可指定为 nullptr,则定时器改为调用 lpTimerFunc: 指定的回调函数。
- nIDEvewnt:指定定时器事件编号;
- uElapse:指定定时间隔时长,单位为毫秒;
- lpTimerFunc :定时到点时,调用的函数;
本课使用:
::SetTimer(hwndDlg, ID_TIMER, 80 /*毫秒*/, OnTimer);
KillTimer
原型:
BOOL KillTimer(
HWND hWnd,
UINT_PTR uIDEvent
);
参考: killtimer
说明: 通过指定窗口句柄和定时器事件编号,结束之前设置的定时器。
本课使用:
::KillTimer(hwndDlg, ID_TIMER);
GetDC
原型:
HDC GetDC(HWND hWnd);
参考: GetDC
说明: 获取入参 hWnd 指定的窗口绘图用的设备上下文(Device Context);如 hWnd 为 nullptr,则返回整个屏幕的设备上下文。
注意: 使用完后,需调用 ReleaseDC() 归还。
本课使用:
auto hDC = ::GetDC(nullptr); // 得到主桌面的 DC (“画板”)
ReleaseDC
原型:
int ReleaseDC(
HWND hWnd,
HDC hDC
);
参考: ReleaseDC
说明: 释放DC,通常该 DC 由 GetDC() 方法从指定窗口获得。
本课使用:
::ReleaseDC(nullptr, hDC); // 归还DC
CreatePen
原型:
HPEN CreatePen(
int iStyle, // 画线风格
int cWidth, // 画线宽度
COLORREF color // 画线条颜色
);
参考: CreatePen
说明: 创建指定风格、宽度、颜色的笔资源。
参数:
- iStyle :支持: PS_SOLID(实线)、PS_DASH(虚线)、PS_DOT(点线)等风格;
- cWidth :宽度,单位为 象素;
- colro : 颜色,可使用宏 RGB(r, g, b) 组合 red、green、blue 三颜色的分量来创建不同颜色。
注意:
笔使用结束后,需及时调用 DeleteObject() 以释放所占用的资源。
本课使用:
//创建实线、宽10,红色的笔:
auto pen = ::CreatePen(PS_SOLID, 10, RGB(0xff, 0, 0));
DeleteObject
原型:
BOOL DeleteObject(
HGDIOBJ ho
);
参考: DeleteObject
说明: 释放给定的GDI资源,比如本课所创建的 HPEN。
本课使用:
::DeleteObject(pen); // 删除笔资源
MoveToEx
原型:
BOOL MoveToEx(
HDC hdc,
int x,
int y,
LPPOINT lppt
);
参考: MoveToEx
说明: 在 设备 hdc 上,将当前绘图位置移动入参 x, y 所指定的位置;如果 lppt 不为空(指到某一 POINT结构体上),则将返回在 本次 MoveToEx() 开始时的当前绘制位置。注意,MoveToEx 仅移动位置,并不在 hdc 上留下痕迹。
特别说明: Windows API 中,尾部带 Ex 的函数,是对早先版本的不带“Ex”的函数的扩展,比如,MoveToEx 是对 MoveTo 函数的扩展,后者不提供第4个入参。
本课使用:
::MoveToEx(hDC, 0, 0, nullptr); // 移动到 DC 的左上角
//...
::MoveToEx(hDC, DesktopWidth, 0, nullptr); // 移动到右上角
LineTo
原型:
BOOL LineTo(
HDC hdc,
int x,
int y
);
参考: LineTo
说明: 在 hdc 上,使用当前选中的画笔(HPEN),从当前绘图位置,画一条直线到 x, y 位置。
本课使用:
::LineTo(hDC, DesktopWidth, DesktopHeight); // 从左上角画线到右下角
// ...
::LineTo(hDC, 0, DesktopHeight); // 从右上角画线到左下角
2. 完整代码
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
HINSTANCE hInst;
int DesktopWidth, DesktopHeight; // 桌面宽度、高度
unsigned int ID_TIMER = 999; // 定时器ID
void CALLBACK OnTimer(HWND hWnd, UINT iMsg, UINT_PTR iTimerID, DWORD dwTime)
{
auto hDC = ::GetDC(nullptr); // 得到主桌面的 DC (“画板”)
if (hDC != nullptr)
{
auto pen = ::CreatePen(PS_SOLID, 10, RGB(0xff, 0, 0)); // 创建宽度10,红色的笔
// 把 pen (笔) 放到 画板 (DC,设备上下文)上:
::SelectObject(hDC, pen);
::MoveToEx(hDC, 0, 0, nullptr); // 移动到 DC 的左上角
::LineTo(hDC, DesktopWidth, DesktopHeight); // 从左上角画线到右下角
::MoveToEx(hDC, DesktopWidth, 0, nullptr); // 移动到右上角
::LineTo(hDC, 0, DesktopHeight); // 从右上角画线到左下角
::DeleteObject(pen); // 删除笔资源
::ReleaseDC(nullptr, hDC); // 归还DC
}
}
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG: // 初始化对话框
{
DesktopWidth = ::GetSystemMetrics(SM_CXFULLSCREEN);
DesktopHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);
::SetTimer(hwndDlg, ID_TIMER, 80 /*毫秒*/, OnTimer);
}
return TRUE;
case WM_CLOSE:
{
::KillTimer(hwndDlg, ID_TIMER);
EndDialog(hwndDlg, 0);
}
return TRUE;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
}
}
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst=hInstance;
InitCommonControls();
return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}
注意,本课无需 wxWidgets 库;但以上仅为 main.cpp 源文件的内容,要完整编译出 Win32 GUI 程序,还需要有一些外部资源文件。完整项目文件下载: