加载中...
在Windows桌面打个叉
第1节:在Windows桌面打个叉
第2节:在窗口上跟踪输出鼠标坐标—Win32版
第3节:你好!wxWidgets
第4节:深入分析基于框架窗口的应用
第5节:玩转主菜单
课文封面

结合 Code::Blocks 提供的 Win32 project 向导,快速创建一个对话框,学习启动定时器,如何获取应用之外的系统资源,如何强制在电脑桌面上画一个叉叉。轻松有趣之间,了解 Windows GUI 的基础知识。

0. 视频

1. 使用的 Windows API 函数

GetSystemMetrics

原型:

int GetSystemMetrics(int nIndex);

参考: GetSystemMetrics

说明: 查询(检索)指定的 Windows (下同)系统的配置或度量。

在本例中,我们使用的 入参 nIndex 有两个:

  • SM_CXFULLSCREEN : 取主桌面的屏幕宽度;
  • SM_CYFULLSCREEN :取主桌面的屏幕高度。

注意:

  1. 如果有多个显示器,仅取主桌面;
  2. 经实测,宽度或高度不会包含任务栏。即:如任务栏布置为横向(常见:底部),则取桌面高度时,不含任务栏高度,如果任务栏布置为竖向,则取桌面宽度时,不含任务的宽度。

本课使用:

DesktopWidth = ::GetSystemMetrics(SM_CXFULLSCREEN); DesktopHeight = ::GetSystemMetrics(SM_CYFULLSCREEN);

SetTimer

原型:

UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc );

参考: SetTimer

说明: 设置一个定时器。

入参:

  1. hwnd:指定 定时器要绑定的窗口的句柄;该窗口可接收定时消息,也可指定为 nullptr,则定时器改为调用 lpTimerFunc: 指定的回调函数。
  2. nIDEvewnt:指定定时器事件编号;
  3. uElapse:指定定时间隔时长,单位为毫秒;
  4. 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

说明: 创建指定风格、宽度、颜色的笔资源。

参数:

  1. iStyle :支持: PS_SOLID(实线)、PS_DASH(虚线)、PS_DOT(点线)等风格;
  2. cWidth :宽度,单位为 象素;
  3. 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 程序,还需要有一些外部资源文件。完整项目文件下载:

DesktopX.zip