Windows编程系列:图形编程基础2

通过函数BeginPaint画图

1、创建一个Windows桌面应用程序

 

2、找到WM_PAINT消息的处理函数,添加代码如下:

1 case WM_PAINT:
2     {
3         PAINTSTRUCT ps;
4         HDC hdc = BeginPaint(hWnd, &ps);
5         TextOut(hdc, 10, 20, L"HelloWorld", 10);  //绘制文本 
6         Ellipse(hdc, 50, 50, 200, 200);           //绘制椭圆
7         EndPaint(hWnd, &ps);
8     }
9     break;

 

这里主要用到了TextOutEllipse函数来进行文本绘制和椭圆绘制。

TextOut函数声明如下:

1 BOOL TextOutW(
2   [in] HDC     hdc,
3   [in] int     x,
4   [in] int     y,
5   [in] LPCWSTR lpString,
6   [in] int     c
7 );

参数说明:

[in] hdc

设备上下文的句柄。

[in] x

系统用于对齐字符串的引用点的 x 坐标(以逻辑坐标表示)。

[in] y

系统用于对齐字符串的引用点的 y 坐标(以逻辑坐标表示)。

[in] lpString

指向要绘制的字符串的指针。 字符串不需要以零结尾,因为 cchString 指定字符串的长度。

[in] c

lpString 指向字符串的长度(以字符为单位)。

 

返回值:

成功,返回非0,失败,返回0

 

Ellipse函数声明如下:

1 BOOL Ellipse(
2   [in] HDC hdc,
3   [in] int left,
4   [in] int top,
5   [in] int right,
6   [in] int bottom
7 );

参数说明:

[in] hdc

设备上下文的句柄。

[in] left

边界矩形左上角的 x 坐标(以逻辑坐标表示)。

[in] top

边界矩形左上角的 y 坐标(以逻辑坐标表示)。

[in] right

边界矩形右下角的 x 坐标(以逻辑坐标表示)。

[in] bottom

边界矩形右下角的 y 坐标(以逻辑坐标表示)。

 

返回值:

成功,返回非0,失败,返回0

 

3、运行效果

 

 

验证BeginPaint只用于无效区域的绘图

1、创建一个Windows桌面应用程序

2、在WM_LBUTTON消息处理函数中,产生一个从(100,100)到(200,200)的无效区域范围,添加代码如下:

 case WM_LBUTTONDOWN:
 {
     RECT rect{ 100,100,200,200 };
     InvalidateRect(hWnd, &rect, FALSE);
     bDown = TRUE;
 }
     break;

3、在WM_PAINT的消息处理函数中,从(0,0)到(400,400)进行画线,

 1     case WM_PAINT:
 2         {
 3             PAINTSTRUCT ps;
 4             HDC hdc = BeginPaint(hWnd, &ps);
 5             if (bDown)
 6             {
 7                 MoveToEx(hdc, 0, 0, NULL);  //移动到(0,0)位置
 8                 LineTo(hdc, 400, 400);      //绘制从(0,0)到(400,400)的线
 9             }
10             EndPaint(hWnd, &ps);
11         }
12         break;

4、由于无效区域只在(100,100)到(200,200),所以当鼠标按下时只有这个区域会进行绘制,运行效果如下

 5、如果此时改变窗口大小,会使整个客户区无效,就能绘制出完整的线,效果如下

 

 

 

以定时间隔进行绘制

可以通过使用 SetTimer 函数创建计时器,按定时间隔绘制。 通过使用计时器定期向窗口过程发送 WM_TIMER 消息,应用程序可以在其他应用程序继续运行时在工作区中执行简单的动画。

1、创建一个Windows桌面应用工程

2、定义一些全局变量

1 RECT rcCurrent = { 0,0,20,20 };
2 POINT aptStar[6] = { 10,1,1,19,19,6,1,6,19,19,10,1 };
3 int X = 2, Y = -1, idTimer = -1;
4 BOOL fVisible = FALSE;
5 HDC hdc;

3、消息处理函数如下

在WM_CREATE中计算起始点、初始化DC和创建定时器

在WM_SIZE中处理窗口大小变化时的逻辑

在WM_TIMER中处理定时器逻辑

在WM_PAINT中处理绘制绘制逻辑

  8 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  9 {
 10     PAINTSTRUCT ps;
 11     RECT rc;
 12 
 13     switch (message)
 14     {
 15     case WM_CREATE:
 16         //计算起始点
 17         GetClientRect(hWnd, &rc);
 18         OffsetRect(&rcCurrent, rc.right / 2, rc.bottom / 2);
 19 
 20         //初始化DC
 21         hdc = GetDC(hWnd);
 22         SetViewportOrgEx(hdc, rcCurrent.left, rcCurrent.top, NULL);  //哪个设备点映射到窗口原点 (0,0)
 23 
 24         SetROP2(hdc, R2_NOT);
 25 
 26         //开启定时器
 27         SetTimer(hWnd, idTimer = 1, 10, NULL);
 28         return 0L;
 29     case WM_COMMAND:
 30         {
 31             int wmId = LOWORD(wParam);
 32             // 分析菜单选择:
 33             switch (wmId)
 34             {
 35             case IDM_ABOUT:
 36                 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
 37                 break;
 38             case IDM_EXIT:
 39                 DestroyWindow(hWnd);
 40                 break;
 41             default:
 42                 return DefWindowProc(hWnd, message, wParam, lParam);
 43             }
 44         }
 45         break;
 46     case WM_PAINT:
 47         {
 48             BeginPaint(hWnd, &ps);
 49             if (!fVisible)
 50                 fVisible = Polyline(hdc, aptStar, 6);
 51             EndPaint(hWnd, &ps);
 52         }
 53         break;
 54     case WM_DESTROY:
 55         if (hdc)
 56             ReleaseDC(hWnd, hdc);
 57         KillTimer(hWnd, 1);
 58         PostQuitMessage(0);
 59         return 0L;
 60     case WM_SIZE:
 61         switch (wParam)
 62         {
 63         case SIZE_MINIMIZED:
 64             //最小化的时候停止定时器
 65             KillTimer(hWnd, 1);
 66             idTimer = -1;
 67             break;
 68         case SIZE_RESTORED:
 69             //如果绘制的星不在客户区,就重新移动到客户区
 70             if (rcCurrent.right > (int)LOWORD(lParam))
 71             {
 72                 rcCurrent.left = (rcCurrent.right = (int)LOWORD(lParam)) - 20;
 73             }
 74 
 75             if (rcCurrent.bottom > (int)HIWORD(lParam))
 76             {
 77                 rcCurrent.top = (rcCurrent.bottom = (int)HIWORD(lParam)) - 20;
 78             }
 79             break;
 80         case SIZE_MAXIMIZED:
 81             if (idTimer == -1)
 82                 SetTimer(hWnd, idTimer, 10, NULL);
 83             break;
 84         default:
 85             break;
 86         }
 87         return 0L;
 88     case WM_TIMER:
 89         //如果绘制的星是可见的,就隐藏它
 90         if (fVisible)
 91             Polyline(hdc, aptStar, 6);
 92 
 93         GetClientRect(hWnd, &rc);
 94 
 95         if (rcCurrent.left + X < rc.left ||
 96             rcCurrent.right + X > rc.right)
 97             X = -X;
 98         if (rcCurrent.top + Y < rc.top ||
 99             rcCurrent.bottom + Y > rc.bottom)
100             Y = -Y;
101 
102         //在新的位置显示绘制的星
103         OffsetRect(&rcCurrent, X, Y);
104         SetViewportOrgEx(hdc, rcCurrent.left, rcCurrent.top, NULL);
105         fVisible = Polyline(hdc, aptStar, 6);
106         return 0L;
107     case WM_ERASEBKGND:
108         fVisible = FALSE;
109         return DefWindowProc(hWnd, message, wParam, lParam);   
110     }
111     return DefWindowProc(hWnd, message, wParam, lParam);
112 }

4、运行效果如下

 

更改文本颜色 

1、创建一个Windows桌面应用程序

2、在WM_PAINT消息的处理函数中添加如下代码

1  case WM_PAINT:
2      {
3          PAINTSTRUCT ps;
4          HDC hdc = BeginPaint(hWnd, &ps);
5          SetTextColor(hdc, RGB(0, 128, 128));
6          TextOut(hdc, 300, 300, L"HelloWorld", 10);
7          EndPaint(hWnd, &ps);
8      }
9      break;

3、运行效果

 

示例代码

 

 

参考资料:

https://learn.microsoft.com/zh-cn/windows/win32/gdi/drawing-at-timed-intervals

posted @ 2024-04-08 10:45  zhaotianff  阅读(9)  评论(0编辑  收藏  举报