Win32 绘图基础 -- 绘制直线、边框、贝塞尔曲线、填充、裁剪

分类: Win32 SDK 3990人阅读 评论(2) 收藏 举报

目录(?)[+]

注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达能力较差,写的不好。因非翻译、非转载,只好选原创,但多数乃摘抄,实为惭愧。但若能帮助一二访客,幸甚!

1.GDI

GDI 的一个主要目的就是支持与设备无关的图形。GDI提供了一种特殊的机制来彻底隔离应用程序和不同输出设备的特性,这样就可以支持与设备无关的图形。


2.设备环境

如果希望在图形输出设备上绘图,必须首先获取设备环境(即DC)的句柄。当Windows把这个句柄交给你的程序,Windows同时也就给予了你使用这个设备的权限。接着,在GDI函数中将这个句柄作为一个参数,告诉Windows在哪个设备上进行绘图。

设备环境中包含许多GDI函数如何工作的属性。


获取设备环境句柄:

1)在处理WM_PAINT消息时使用BeginPaint函数和EndPaint函数:

  1. HDC hdc;   
  2. hdc = BeginPaint(hwnd, &ps);  
  3. // ...  
  4. EndPaint(hwnd, &ps);  

2)在处理非WM_PAINT消息时由Windows程序获取:
  1. HDC hdc;  
  2. hdc = GetDC(hwnd);  
  3. //....  
  4. ReleaseDC(hwnd, hdc);  

3)获得用于整个窗口的,而不仅仅是窗口客户区的设备环境句柄:

  1. hdc = GetWindowDC(hwnd);  
  2. // ...  
  3. ReleaseDC(hwnd, hdc);  

4)更通用的获取设备环境句柄的函数:
  1. hdc = CreateDC(pszDriver, pszDevice, pszOutput, pData);  
  2. // ...  
  3. DeleteDC(hdc);  
获取当前整个屏幕的设备环境句柄:
  1. hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);  

5)处理位图时,有时可能会用到一个”内存设备环境“:
  1. hdcMem = CreateCompatibleDC(hdc);  
  2. // ..  
  3. DeleteDC(hdcMem);  

可以把一个位图选入内存设备环境,并且调用GDI函数绘制这个位图

6)图元文件是以二进制形式编码的GDI函数调用的集合。它可以通过获取一个图元文件的设备环境来创建:

  1. hdcMeta = CreateMetaFile(pszFilename);  
  2. // ...  
  3. hmf = CloseMetaFile(hdcMeta);  

3.设备的尺寸

”分辨率“:每度量单位(通常是英寸)中含有的像素数。

常用函数:

GetSystemMetrics、GetDeviceCaps.


4.色彩ABC

获取视频适配器板卡上的内存的组织形式:

1)色彩平面的数目:

  1. iPlanes= GetDeviceCaps(hdc, PLANES);  

2)每个像素的颜色位数:

  1. iBitsPixel = GetDeviceCaps(hdc, BITSPIXEL);  


5.点和线的绘制

1)点

  1. SetPixel(hdc, x, y, crColor);  
  2. crColor = GetPixel(hdc, x, y);  

2)直线
  1. MoveToEx(hdc, xBeg, yBeg, NULL);  
  2. LineTo(hdc, xEnd, yEnd);  

数组的点连成线:

  1. Polyline(hdc, apt, 5);  

用Polyline实现绘制正玄曲线:

  1. /*------------------------------------------------------------------- 
  2.     SINEWAVE.cpp -- sine wave Using polyline 
  3. --------------------------------------------------------------------*/  
  4.   
  5. #include <windows.h>  
  6. #include <math.h>  
  7.   
  8. #define NUM     1000  
  9. #define TWOPI   (2*3.14159)  
  10.   
  11. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  12.   
  13. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
  14. {  
  15.     static TCHAR    szAppName[] = TEXT("SineWave");  
  16.     HWND            hwnd;  
  17.     MSG             msg;  
  18.     WNDCLASS        wndclass;  
  19.   
  20.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
  21.     wndclass.lpfnWndProc    = WndProc;  
  22.     wndclass.cbClsExtra     = 0;  
  23.     wndclass.cbWndExtra     = 0;  
  24.     wndclass.hInstance      = hInstance;  
  25.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  26.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  27.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  28.     wndclass.lpszMenuName   = NULL;  
  29.     wndclass.lpszClassName  = szAppName;  
  30.   
  31.     if (!RegisterClass(&wndclass))  
  32.     {  
  33.         MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);  
  34.         return 0;  
  35.     }  
  36.   
  37.     hwnd = CreateWindow(szAppName, TEXT("Sine Wave Using Polyline"),  
  38.                         WS_OVERLAPPEDWINDOW,  
  39.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  40.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  41.                         NULL, NULL, hInstance, NULL);  
  42.   
  43.     ShowWindow(hwnd, iCmdShow);  
  44.     UpdateWindow(hwnd);  
  45.   
  46.     while (GetMessage(&msg, NULL, 0, 0))  
  47.     {  
  48.         TranslateMessage(&msg);  
  49.         DispatchMessage(&msg);  
  50.     }  
  51.   
  52.     return msg.wParam;  
  53. }  
  54.   
  55.   
  56. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  57. {  
  58.     static int      cxClient, cyClient;  
  59.     HDC             hdc;  
  60.     int             i;  
  61.     PAINTSTRUCT     ps;  
  62.     POINT           apt[NUM];  
  63.   
  64.     switch (message)  
  65.     {  
  66.     case WM_SIZE:  
  67.         cxClient = LOWORD(lParam);  
  68.         cyClient = HIWORD(lParam);  
  69.         return 0;  
  70.   
  71.     case WM_PAINT:  
  72.         hdc = BeginPaint(hwnd, &ps);  
  73.   
  74.         MoveToEx(hdc, 0, cyClient/2, NULL);  
  75.         LineTo(hdc, cxClient, cyClient/2);  
  76.   
  77.         for (i = 0; i < NUM; i++)  
  78.         {  
  79.             apt[i].x = i*cxClient/NUM;  
  80.             apt[i].y = (int)(cyClient / 2 * (1-sin(TWOPI * i / NUM)));  
  81.         }  
  82.         Polyline(hdc, apt, NUM);  
  83.         EndPaint(hwnd, &ps);  
  84.         return 0;  
  85.   
  86.     case WM_DESTROY:  
  87.         PostQuitMessage(0);  
  88.         return 0;  
  89.     }  
  90.   
  91.     return DefWindowProc(hwnd, message, wParam, lParam);  
  92. }  



6.几个绘图函数:

  1. Rectangle(hdc, xLeft, yTop, xRight, yBottom);  
  2. Ellipse(hdc, xLeft, yTop, xRight, yBottom);  
  3. RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse);  
  4. Arc(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);  
  5. Chord(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);  
  6. Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);  

绘图示例:
  1. /*------------------------------------------------------------------- 
  2.     lineDemo.cpp -- Line-Drawing Demonstration Program 
  3. --------------------------------------------------------------------*/  
  4.   
  5. #include <windows.h>  
  6. #include <math.h>  
  7.   
  8. #define NUM     1000  
  9. #define TWOPI   (2*3.14159)  
  10.   
  11. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  12.   
  13. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
  14. {  
  15.     static TCHAR    szAppName[] = TEXT("lineDemo");  
  16.     HWND            hwnd;  
  17.     MSG             msg;  
  18.     WNDCLASS        wndclass;  
  19.   
  20.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
  21.     wndclass.lpfnWndProc    = WndProc;  
  22.     wndclass.cbClsExtra     = 0;  
  23.     wndclass.cbWndExtra     = 0;  
  24.     wndclass.hInstance      = hInstance;  
  25.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  26.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  27.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  28.     wndclass.lpszMenuName   = NULL;  
  29.     wndclass.lpszClassName  = szAppName;  
  30.   
  31.     if (!RegisterClass(&wndclass))  
  32.     {  
  33.         MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);  
  34.         return 0;  
  35.     }  
  36.   
  37.     hwnd = CreateWindow(szAppName, TEXT("Line Demonstration"),  
  38.                         WS_OVERLAPPEDWINDOW,  
  39.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  40.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  41.                         NULL, NULL, hInstance, NULL);  
  42.   
  43.     ShowWindow(hwnd, iCmdShow);  
  44.     UpdateWindow(hwnd);  
  45.   
  46.     while (GetMessage(&msg, NULL, 0, 0))  
  47.     {  
  48.         TranslateMessage(&msg);  
  49.         DispatchMessage(&msg);  
  50.     }  
  51.   
  52.     return msg.wParam;  
  53. }  
  54.   
  55.   
  56. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  57. {  
  58.     static int      cxClient, cyClient;  
  59.     HDC             hdc;  
  60.     PAINTSTRUCT     ps;  
  61.   
  62.     switch (message)  
  63.     {  
  64.     case WM_SIZE:  
  65.         cxClient = LOWORD(lParam);  
  66.         cyClient = HIWORD(lParam);  
  67.         return 0;  
  68.   
  69.     case WM_PAINT:  
  70.         hdc = BeginPaint(hwnd, &ps);  
  71.   
  72.         Rectangle(hdc, cxClient/8, cyClient/8, 7*cxClient/8, 7*cyClient/8);  
  73.   
  74.         MoveToEx(hdc, 0, 0, NULL);  
  75.         LineTo(hdc, cxClient, cyClient);  
  76.   
  77.         MoveToEx(hdc, 0, cyClient, NULL);  
  78.         LineTo(hdc, cxClient, 0);  
  79.   
  80.         Ellipse(hdc, cxClient/8, cyClient/8, 7*cxClient/8, 7*cyClient/8);  
  81.   
  82.         RoundRect(hdc, cxClient/4, cyClient/4, 3*cxClient/4, 3*cyClient/4, cxClient/4, cyClient/4);  
  83.   
  84.         EndPaint(hwnd, &ps);  
  85.         return 0;  
  86.   
  87.     case WM_DESTROY:  
  88.         PostQuitMessage(0);  
  89.         return 0;  
  90.     }  
  91.   
  92.     return DefWindowProc(hwnd, message, wParam, lParam);  
  93. }  




7.贝塞尔样条曲线:

  1. /*------------------------------------------------------------------- 
  2.     bezier.cpp -- Bezier Splines Demo 
  3. --------------------------------------------------------------------*/  
  4.   
  5. #include <windows.h>  
  6. #include <math.h>  
  7.   
  8. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  9.   
  10. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
  11. {  
  12.     static TCHAR    szAppName[] = TEXT("Bezier");  
  13.     HWND            hwnd;  
  14.     MSG             msg;  
  15.     WNDCLASS        wndclass;  
  16.   
  17.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
  18.     wndclass.lpfnWndProc    = WndProc;  
  19.     wndclass.cbClsExtra     = 0;  
  20.     wndclass.cbWndExtra     = 0;  
  21.     wndclass.hInstance      = hInstance;  
  22.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  23.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  24.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  25.     wndclass.lpszMenuName   = NULL;  
  26.     wndclass.lpszClassName  = szAppName;  
  27.   
  28.     if (!RegisterClass(&wndclass))  
  29.     {  
  30.         MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);  
  31.         return 0;  
  32.     }  
  33.   
  34.     hwnd = CreateWindow(szAppName, TEXT("Bezier Splines Demo"),  
  35.                         WS_OVERLAPPEDWINDOW,  
  36.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  37.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  38.                         NULL, NULL, hInstance, NULL);  
  39.   
  40.     ShowWindow(hwnd, iCmdShow);  
  41.     UpdateWindow(hwnd);  
  42.   
  43.     while (GetMessage(&msg, NULL, 0, 0))  
  44.     {  
  45.         TranslateMessage(&msg);  
  46.         DispatchMessage(&msg);  
  47.     }  
  48.   
  49.     return msg.wParam;  
  50. }  
  51.   
  52.   
  53. void DrawBezier(HDC hdc, POINT apt[])  
  54. {  
  55.     PolyBezier(hdc, apt, 4);  
  56.   
  57.     MoveToEx(hdc, apt[0].x, apt[0].y, NULL);  
  58.     LineTo(hdc, apt[1].x, apt[1].y);  
  59.   
  60.     MoveToEx(hdc, apt[2].x, apt[2].y, NULL);  
  61.     LineTo(hdc, apt[3].x, apt[3].y);  
  62. }  
  63.   
  64. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  65. {  
  66.     static POINT    apt[4];  
  67.     int             cxClient, cyClient;  
  68.     HDC             hdc;  
  69.     PAINTSTRUCT     ps;  
  70.   
  71.     switch (message)  
  72.     {  
  73.     case WM_SIZE:  
  74.         cxClient = LOWORD(lParam);  
  75.         cyClient = HIWORD(lParam);  
  76.   
  77.         apt[0].x = cxClient / 4;  
  78.         apt[0].y = cyClient / 2;  
  79.   
  80.         apt[1].x = cxClient / 2;  
  81.         apt[1].y = cyClient / 4;  
  82.   
  83.         apt[2].x = cxClient / 2;  
  84.         apt[2].y = 3 * cyClient / 4;  
  85.   
  86.         apt[3].x = 3 * cxClient / 4;  
  87.         apt[3].y = cyClient / 2;  
  88.   
  89.         return 0;  
  90.   
  91.     case WM_LBUTTONDOWN:  
  92.     case WM_RBUTTONDOWN:  
  93.     case WM_MOUSEMOVE:  
  94.         if (wParam & MK_LBUTTON || wParam & MK_RBUTTON)  
  95.         {  
  96.             hdc = GetDC(hwnd);  
  97.               
  98.             SelectObject(hdc, GetStockObject(WHITE_PEN));  
  99.             DrawBezier(hdc, apt);  
  100.   
  101.             if (wParam & MK_LBUTTON)  
  102.             {  
  103.                 apt[1].x = LOWORD(lParam);  
  104.                 apt[1].y = HIWORD(lParam);  
  105.             }  
  106.   
  107.             if (wParam & MK_RBUTTON)  
  108.             {  
  109.                 apt[2].x = LOWORD(lParam);  
  110.                 apt[2].y = HIWORD(lParam);  
  111.             }  
  112.               
  113.             SelectObject(hdc, GetStockObject(BLACK_PEN));  
  114.             DrawBezier(hdc, apt);  
  115.   
  116.             ReleaseDC(hwnd, hdc);  
  117.         }  
  118.   
  119.     case WM_PAINT:  
  120.         InvalidateRect(hwnd, NULL, TRUE);  
  121.         hdc = BeginPaint(hwnd, &ps);  
  122.   
  123.         DrawBezier(hdc, apt);  
  124.   
  125.         EndPaint(hwnd, &ps);  
  126.         return 0;  
  127.   
  128.     case WM_DESTROY:  
  129.         PostQuitMessage(0);  
  130.         return 0;  
  131.     }  
  132.   
  133.     return DefWindowProc(hwnd, message, wParam, lParam);  
  134. }  



8.填充区域

PeekMessage

在Windows中有很多”空闲时间“,在这期间所有的消息队列都是空的,Windows就在等待键盘或者鼠标的输入。那么能否在空闲期间从某种程度上获取控制,而一旦有消息加载到程序的消息队列,就释放控制呢?这就是PeekMessage的”用武之地“。

PeekMessage的意思,它是”偷看“而不是”获得“。它允许一个程序检查程序队列中的下一个消息,而不是真实地获得并删除它看到的消息。

GetMessage并不把控制权交还给程序,除非它从程序的消息队列中获得了消息。但PeekMessage却总是立即返回,不管消息是否出现。

随机矩形代码:


  1. /*------------------------------------------------------------------- 
  2.     randRect.cpp -- Displays Random Rectangles 
  3. --------------------------------------------------------------------*/  
  4.   
  5. #include <windows.h>  
  6. #include <stdlib.h>  
  7.   
  8. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  9. void DrawRectangle(HWND);  
  10.   
  11. int cxClient, cyClient;  
  12.   
  13. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
  14. {  
  15.     static TCHAR    szAppName[] = TEXT("RandRect");  
  16.     HWND            hwnd;  
  17.     MSG             msg;  
  18.     WNDCLASS        wndclass;  
  19.   
  20.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
  21.     wndclass.lpfnWndProc    = WndProc;  
  22.     wndclass.cbClsExtra     = 0;  
  23.     wndclass.cbWndExtra     = 0;  
  24.     wndclass.hInstance      = hInstance;  
  25.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  26.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  27.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  28.     wndclass.lpszMenuName   = NULL;  
  29.     wndclass.lpszClassName  = szAppName;  
  30.   
  31.     if (!RegisterClass(&wndclass))  
  32.     {  
  33.         MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);  
  34.         return 0;  
  35.     }  
  36.   
  37.     hwnd = CreateWindow(szAppName, TEXT("Rand Rectangle"),  
  38.                         WS_OVERLAPPEDWINDOW,  
  39.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  40.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  41.                         NULL, NULL, hInstance, NULL);  
  42.   
  43.     ShowWindow(hwnd, iCmdShow);  
  44.     UpdateWindow(hwnd);  
  45.   
  46.     while (TRUE)  
  47.     {  
  48.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  
  49.         {  
  50.             if (msg.message == WM_QUIT)  
  51.                 break;  
  52.             TranslateMessage(&msg);  
  53.             DispatchMessage(&msg);  
  54.         }  
  55.         else  
  56.         {  
  57.             Sleep(100);  
  58.             DrawRectangle(hwnd);  
  59.         }  
  60.     }  
  61.   
  62.     return msg.wParam;  
  63. }  
  64.   
  65.   
  66. void DrawRectangle(HWND hwnd)  
  67. {  
  68.     HBRUSH      hBrush;  
  69.     HDC         hdc;  
  70.     RECT        rect;  
  71.   
  72.     if (cxClient == 0 || cyClient == 0)  
  73.         return;  
  74.   
  75.     SetRect(&rect, rand() % cxClient, rand() % cyClient, rand() % cxClient, rand() % cyClient);  
  76.   
  77.     hBrush = CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256));  
  78.     hdc = GetDC(hwnd);  
  79.   
  80.     FillRect(hdc, &rect, hBrush);  
  81.     ReleaseDC(hwnd, hdc);  
  82.     DeleteObject(hBrush);  
  83. }  
  84.   
  85. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  86. {  
  87.     switch (message)  
  88.     {  
  89.     case WM_SIZE:  
  90.         cxClient = LOWORD(lParam);  
  91.         cyClient = HIWORD(lParam);  
  92.   
  93.         return 0;  
  94.   
  95.     case WM_DESTROY:  
  96.         PostQuitMessage(0);  
  97.         return 0;  
  98.     }  
  99.   
  100.     return DefWindowProc(hwnd, message, wParam, lParam);  
  101. }  



9.矩形与区域的裁剪

InvalidRect函数使显示的矩形区域无效,并产生一个WM_PAINT消息。可以用来擦除客户区的内容,并产生一个WM_PAINT消息。

若处理区域而不是矩形可用:

InvalidateRgn(hwnd, hRgn, bErase);

ValidateRgn(hwnd, hRgn);

CLOVER程序:

由四个椭圆形成一个区域,然后把这个区域选入设备环境,接着从窗口的客户区中心发散绘制一系列直线。这些直线仅出现裁剪区内。

  1. /*------------------------------------------------------------------- 
  2.     clover.cpp -- Clover Drawing Program Using Regions 
  3. --------------------------------------------------------------------*/  
  4.   
  5. #include <windows.h>  
  6. #include <math.h>  
  7.   
  8. #define TWO_PI  (2.0 * 3.14159)  
  9.   
  10. LRESULT CALLBACK WndProc(HWNDUINTWPARAMLPARAM);  
  11. void DrawRectangle(HWND);  
  12.   
  13. int cxClient, cyClient;  
  14.   
  15. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)  
  16. {  
  17.     static TCHAR    szAppName[] = TEXT("clover");  
  18.     HWND            hwnd;  
  19.     MSG             msg;  
  20.     WNDCLASS        wndclass;  
  21.   
  22.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;  
  23.     wndclass.lpfnWndProc    = WndProc;  
  24.     wndclass.cbClsExtra     = 0;  
  25.     wndclass.cbWndExtra     = 0;  
  26.     wndclass.hInstance      = hInstance;  
  27.     wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);  
  28.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  29.     wndclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  30.     wndclass.lpszMenuName   = NULL;  
  31.     wndclass.lpszClassName  = szAppName;  
  32.   
  33.     if (!RegisterClass(&wndclass))  
  34.     {  
  35.         MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);  
  36.         return 0;  
  37.     }  
  38.   
  39.     hwnd = CreateWindow(szAppName, TEXT("Draw a Clover"),  
  40.                         WS_OVERLAPPEDWINDOW,  
  41.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  42.                         CW_USEDEFAULT, CW_USEDEFAULT,   
  43.                         NULL, NULL, hInstance, NULL);  
  44.   
  45.     ShowWindow(hwnd, iCmdShow);  
  46.     UpdateWindow(hwnd);  
  47.   
  48.     while (GetMessage(&msg, NULL, 0, 0))  
  49.     {  
  50.   
  51.         TranslateMessage(&msg);  
  52.         DispatchMessage(&msg);  
  53.     }  
  54.   
  55.     return msg.wParam;  
  56. }  
  57.   
  58. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  59. {  
  60.     static HRGN     hRgnClip;  
  61.     static int      cxClient, cyClient;  
  62.     double          fAngle, fRadius;  
  63.     HCURSOR         hCursor;  
  64.     HDC             hdc;  
  65.     HRGN            hRgnTemp[6];  
  66.     int             i;  
  67.     PAINTSTRUCT     ps;  
  68.   
  69.     switch (message)  
  70.     {  
  71.     case WM_SIZE:  
  72.         cxClient = LOWORD(lParam);  
  73.         cyClient = HIWORD(lParam);  
  74.           
  75.         hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));  
  76.         ShowCursor(TRUE);  
  77.   
  78.         if (hRgnClip)  
  79.             DeleteObject(hRgnClip);  
  80.   
  81.         hRgnTemp[0] = CreateEllipticRgn(0,          cyClient/3,     cxClient/2,     2*cyClient/3);  
  82.         hRgnTemp[1] = CreateEllipticRgn(cxClient/2, cyClient/3,     cxClient,       2*cyClient/3);  
  83.         hRgnTemp[2] = CreateEllipticRgn(cxClient/3, 0,              2*cxClient/3,   cyClient/2);  
  84.         hRgnTemp[3] = CreateEllipticRgn(cxClient/3, cyClient/2,     2*cxClient/3,   cyClient);  
  85.         hRgnTemp[4] = CreateRectRgn(0, 0, 1, 1);  
  86.         hRgnTemp[5] = CreateRectRgn(0, 0, 1, 1);  
  87.         hRgnClip = CreateRectRgn(0, 0, 1, 1);  
  88.   
  89.         CombineRgn(hRgnTemp[4], hRgnTemp[0], hRgnTemp[1], RGN_OR);  
  90.         CombineRgn(hRgnTemp[5], hRgnTemp[2], hRgnTemp[3], RGN_OR);  
  91.         CombineRgn(hRgnClip, hRgnTemp[4], hRgnTemp[5], RGN_XOR);  
  92.   
  93.         for (i = 0; i < 6; i++)  
  94.             DeleteObject(hRgnTemp[i]);  
  95.   
  96.         SetCursor(hCursor);  
  97.         ShowCursor(FALSE);  
  98.   
  99.         return 0;  
  100.   
  101.     case WM_PAINT:  
  102.         hdc = BeginPaint(hwnd, &ps);  
  103.   
  104.         SetViewportOrgEx(hdc, cxClient/2, cyClient/2, NULL);  
  105.         SelectClipRgn(hdc, hRgnClip);  
  106.   
  107.         // hypot 计算直角三角形斜边的长  
  108.         fRadius = _hypot(cxClient/2.0, cyClient/2.0);  
  109.   
  110.         for (fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI/360)  
  111.         {  
  112.             MoveToEx(hdc, 0, 0, NULL);  
  113.             LineTo(hdc, int(fRadius * cos(fAngle) + 0.5), int(-fRadius * sin(fAngle) + 0.5));  
  114.         }  
  115.         EndPaint(hwnd, &ps);  
  116.         return 0;  
  117.   
  118.     case WM_DESTROY:  
  119.         DeleteObject(hRgnClip);  
  120.         PostQuitMessage(0);  
  121.         return 0;  
  122.     }  
  123.   
  124.     return DefWindowProc(hwnd, message, wParam, lParam);  
  125. }  


版权声明:本文为博主原创文章,未经博主允许不得转载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值