zoukankan      html  css  js  c++  java
  • 跟我一起玩Win32开发(9):绘图(B)

    我们今天继续涂鸦,实践证明,涂鸦是人生一大乐趣。

    首先,我们写一个程序骨架子,以便做实验。

    [cpp] view plain copy
     
    1. #include <Windows.h>  
    2.   
    3. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);  
    4.   
    5. int WINAPI WinMain(  
    6.     HINSTANCE hThisApp,  
    7.     HINSTANCE hPrevApp,  
    8.     LPSTR lpsCmdln,  
    9.     int iShow)  
    10. {  
    11.     WNDCLASS wc;  
    12.     wc.cbClsExtra = 0;  
    13.     wc.cbWndExtra = 0;  
    14.     wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));  
    15.     // 默认光标类型为箭头  
    16.     wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);  
    17.     // 默认应用程序图标  
    18.     wc.hIcon = LoadIcon(hThisApp, IDI_APPLICATION);  
    19.     wc.hInstance = hThisApp;  
    20.     wc.lpfnWndProc = MainWinProc;  
    21.     wc.lpszClassName = L"MyAppTest";  
    22.     wc.lpszMenuName = NULL;  
    23.     wc.style = CS_HREDRAW | CS_VREDRAW;  
    24.     // 注册窗口类  
    25.     RegisterClass(&wc);  
    26.     // 创建窗口  
    27.     HWND hwnd = CreateWindow(  
    28.         L"MyAppTest",  
    29.         L"绘画课",  
    30.         /* 使用 WS_VISIBLE 就不用调用ShowWindow了 */  
    31.         WS_VISIBLE | WS_OVERLAPPEDWINDOW,  
    32.         100,  
    33.         45,  
    34.         500,  
    35.         380,  
    36.         NULL,  
    37.         NULL,  
    38.         hThisApp,  
    39.         NULL);  
    40.     // 消息循环  
    41.     MSG msg;  
    42.     while(GetMessage(&msg, NULL, 0, 0))  
    43.     {  
    44.         TranslateMessage(&msg);  
    45.         DispatchMessage(&msg);  
    46.     }  
    47.     return 0;  
    48. }  
    49.   
    50.   
    51. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  
    52. {  
    53.     switch(msg)  
    54.     {  
    55.     case WM_DESTROY:  
    56.         PostQuitMessage(0);  
    57.         return 0;  
    58.     case WM_PAINT:  
    59.         PAINTSTRUCT ps;  
    60.         BeginPaint(hwnd, &ps);  
    61.                 /* 
    62.                     待实现 
    63.                 */  
    64.         EndPaint(hwnd, &ps);  
    65.         return 0;  
    66.     }  
    67.     return DefWindowProc(hwnd, msg, wParam, lParam);  
    68. }  

     CreatePen函数

    我们要进行素描画创作,所以我们必须想清楚要使用什么样的钢笔,画出什么样的线条。故,画图之前得创建一支钢笔,不然,巧妇难为无米之炊。

    [cpp] view plain copy
     
    1. HPEN  CreatePen(  
    2.       int iStyle, //钢笔的样式,如虚线、实线  
    3.       int cWidth, //线条宽度  
    4.       COLORREF color //线条是啥颜色的  
    5. );  

    第一个参数指定线条的样式,如

    [cpp] view plain copy
     
    1. /* Pen Styles */  
    2. #define PS_SOLID            0  
    3. #define PS_DASH             1       /* -------  */  
    4. #define PS_DOT              2       /* .......  */  
    5. #define PS_DASHDOT          3       /* _._._._  */  
    6. #define PS_DASHDOTDOT       4       /* _.._.._  */  
    7. #define PS_NULL             5  
    8. #define PS_INSIDEFRAME      6  
    9. #define PS_USERSTYLE        7  
    10. #define PS_ALTERNATE        8  

    函数成功创建钢笔后就会返回HPEN,H开头的你就要知道它表示句柄。Pen也是系统资源,所以创建笔后系统要为它一个标识。

    SelectObject函数

    上过美术课,你会知道,有了用于进行素描创作的钢笔还不能动手干活,我们还需要有纸。接下来,调用SelectObject函数,把刚才创建的钢笔与绘图纸关联,就等于把我们创建的绘图资源放进DC工具箱中,

    [cpp] view plain copy
     
    1. HGDIOBJ WINAPI SelectObject(  
    2. HDC hdc, //设备描述表的句柄  
    3. HGDIOBJ h //要放到DC中的资源的句柄  
    4. );  

    调用成功后,返回原先的资源句柄。

    MoveToEx和LineTo

    MoveToEx是设置绘制的起点,下次绘图将从这个点开始。它的最后一个参数将被设置为当前点,即Move后的坐标。LineTo从当前坐标开始,到指定坐标之间绘制一条线段。

    [cpp] view plain copy
     
    1. // 创建钢笔  
    2. HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50));  
    3. // 把笔选到DC中  
    4. SelectObject(ps.hdc, pen);  
    5. // 设定线段的起点  
    6. MoveToEx(ps.hdc, 15, 25, NULL);  
    7. // 绘制线条  
    8. LineTo(ps.hdc, 65, 49);  
    9. LineTo(ps.hdc, 12, 120);  
    10. LineTo(ps.hdc, 250, 78);  
    11. LineTo(ps.hdc, 312, 185);  
    12. DeleteObject(pen);  


    记住,只要是我们创建的句柄,用完后调用DeleteObject函数将其销毁。


     

    PolyBezier函数和PolyBezierTo函数

    两个函数都是用来绘制贝塞尔曲线的,不同的是,PolyBezier函数包含指定的起点和终点,PolyBezierTo是从当前点开始绘制贝塞尔曲线。

    [cpp] view plain copy
     
    1. // 绘制贝塞尔曲线  
    2. pen = CreatePen(PS_DOT, 1, RGB(0,3,255));  
    3. SelectObject(ps.hdc, pen);  
    4. POINT* pts = new POINT[4];  
    5. pts[0].x = 421;  
    6. pts[0].y = 16;  
    7. pts[1].x = 7;  
    8. pts[1].y = 197;  
    9. pts[2].x = 480;  
    10. pts[2].y = 320;  
    11. pts[3].x = 30;  
    12. pts[3].y = 350;  
    13. PolyBezier(ps.hdc, pts, 4);  
    14. delete [] pts;  
    15. // 第二段贝塞尔曲线  
    16. POINT* pts2 = new POINT[3];  
    17. pts2[0].x = 176;  
    18. pts2[0].y = 84;  
    19. pts2[1].x = 17;  
    20. pts2[1].y = 247;  
    21. pts2[2].x = 400;  
    22. pts2[2].y = 490;  
    23. // 移动当前点  
    24. MoveToEx(ps.hdc, 395, 270, NULL);  
    25. PolyBezierTo(ps.hdc, pts2, 3);  
    26. delete [] pts2;  



     

     

     PolyPolyline绘制复合线条

    PolyPolyline函数可以绘制多段复合线条。它的声明如下:

    [cpp] view plain copy
     
    1. BOOL PolyPolyline(  
    2.   HDC hdc,  
    3.   const POINT *lppt,  
    4.   const DWORD *lpdwPolyPoints,  
    5.   DWORD cCount  
    6. );  


     lppt参数指向一个POINT的数组,它包含绘制复合线条所需的所有点;lpdwPolyPoints指向一个数组,这个数字数组指明如何分配点数组。

    例如,lppt有7个点,我计划,前2个点绘制第一条线,接着3个点绘制第二条线,最后2个点绘制第三条线,这样一来,lpdwPolyPolyPoints得值应为:

    {  2, 3, 2 }

    nCount里包含lpdwPolyPolyPoints中的数量,我们上面的例子是3.

    由于两点决定一条线段,因此,lpdwPolyPolyPoints里面的值记得要>=2。

    [cpp] view plain copy
     
    1. // 复杂图形  
    2. pen = CreatePen(PS_DASHDOTDOT, 1, RGB(80,20,160));  
    3. SelectObject(ps.hdc, pen);  
    4. POINT plpts[10] =  
    5. {  
    6.     {47,3}, {11,46}, {28,199}, {203,305}, {94,22},  
    7.     {402,377}, {21,45}, {237,7}, {300,398}, {175,25}  
    8. };  
    9. DWORD arr[4] = { 2, 3, 3, 2};  
    10. PolyPolyline(ps.hdc, &plpts[0], &arr[0], 4);  

    上面的代码将画出以下图形。

     完整的代码清单如下:

    [cpp] view plain copy
     
      1. #include <Windows.h>  
      2.   
      3. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);  
      4.   
      5. int WINAPI WinMain(  
      6.     HINSTANCE hThisApp,  
      7.     HINSTANCE hPrevApp,  
      8.     LPSTR lpsCmdln,  
      9.     int iShow)  
      10. {  
      11.     WNDCLASS wc;  
      12.     wc.cbClsExtra = 0;  
      13.     wc.cbWndExtra = 0;  
      14.     wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));  
      15.     // 默认光标类型为箭头  
      16.     wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);  
      17.     // 默认应用程序图标  
      18.     wc.hIcon = LoadIcon(hThisApp, IDI_APPLICATION);  
      19.     wc.hInstance = hThisApp;  
      20.     wc.lpfnWndProc = MainWinProc;  
      21.     wc.lpszClassName = L"MyAppTest";  
      22.     wc.lpszMenuName = NULL;  
      23.     wc.style = CS_HREDRAW | CS_VREDRAW;  
      24.     // 注册窗口类  
      25.     RegisterClass(&wc);  
      26.     // 创建窗口  
      27.     HWND hwnd = CreateWindow(  
      28.         L"MyAppTest",  
      29.         L"绘画课",  
      30.         /* 使用 WS_VISIBLE 就不用调用ShowWindow了 */  
      31.         WS_VISIBLE | WS_OVERLAPPEDWINDOW,  
      32.         100,  
      33.         45,  
      34.         500,  
      35.         380,  
      36.         NULL,  
      37.         NULL,  
      38.         hThisApp,  
      39.         NULL);  
      40.     // 消息循环  
      41.     MSG msg;  
      42.     while(GetMessage(&msg, NULL, 0, 0))  
      43.     {  
      44.         TranslateMessage(&msg);  
      45.         DispatchMessage(&msg);  
      46.     }  
      47.     return 0;  
      48. }  
      49.   
      50.   
      51. LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  
      52. {  
      53.     switch(msg)  
      54.     {  
      55.     case WM_DESTROY:  
      56.         PostQuitMessage(0);  
      57.         return 0;  
      58.     case WM_PAINT:  
      59.         PAINTSTRUCT ps;  
      60.         BeginPaint(hwnd, &ps);  
      61.         // 创建钢笔  
      62.         HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50));  
      63.         // 把笔选到DC中  
      64.         SelectObject(ps.hdc, pen);  
      65.         // 设定线段的起点  
      66.         MoveToEx(ps.hdc, 15, 25, NULL);  
      67.         // 绘制线条  
      68.         LineTo(ps.hdc, 65, 49);  
      69.         LineTo(ps.hdc, 12, 120);  
      70.         LineTo(ps.hdc, 250, 78);  
      71.         LineTo(ps.hdc, 312, 185);  
      72.         // 绘制贝塞尔曲线  
      73.         pen = CreatePen(PS_DOT, 1, RGB(0,3,255));  
      74.         SelectObject(ps.hdc, pen);  
      75.         POINT* pts = new POINT[4];  
      76.         pts[0].x = 421;  
      77.         pts[0].y = 16;  
      78.         pts[1].x = 7;  
      79.         pts[1].y = 197;  
      80.         pts[2].x = 480;  
      81.         pts[2].y = 320;  
      82.         pts[3].x = 30;  
      83.         pts[3].y = 350;  
      84.         PolyBezier(ps.hdc, pts, 4);  
      85.         delete [] pts;  
      86.         // 第二段贝塞尔曲线  
      87.         POINT* pts2 = new POINT[3];  
      88.         pts2[0].x = 176;  
      89.         pts2[0].y = 84;  
      90.         pts2[1].x = 17;  
      91.         pts2[1].y = 247;  
      92.         pts2[2].x = 400;  
      93.         pts2[2].y = 490;  
      94.         // 移动当前点  
      95.         MoveToEx(ps.hdc, 395, 270, NULL);  
      96.         PolyBezierTo(ps.hdc, pts2, 3);  
      97.         delete [] pts2;  
      98.         // 复杂图形  
      99.         pen = CreatePen(PS_DASHDOTDOT, 1, RGB(80,20,160));  
      100.         SelectObject(ps.hdc, pen);  
      101.         POINT plpts[10] =  
      102.         {  
      103.             {47,3}, {11,46}, {28,199}, {203,305}, {94,22},  
      104.             {402,377}, {21,45}, {237,7}, {300,398}, {175,25}  
      105.         };  
      106.         DWORD arr[4] = { 2, 3, 3, 2};  
      107.         PolyPolyline(ps.hdc, &plpts[0], &arr[0], 4);  
      108.         DeleteObject(pen);  
      109.         EndPaint(hwnd, &ps);  
      110.         return 0;  
      111.     }  
      112.     return DefWindowProc(hwnd, msg, wParam, lParam);  
      113. }  
      114.    
  • 相关阅读:
    网页抓取
    基本数据结构
    小节
    顺序统计量
    线性时间排序
    快速排序
    堆排序 Heapsort
    大数运算
    趣味题,文本中洞的数量
    nginx config配置
  • 原文地址:https://www.cnblogs.com/weekbo/p/8681907.html
Copyright © 2011-2022 走看看