绘图;PolyBezier函数和PolyBezierTo函数;PolyPolyline绘制复合线条

转自:http://blog.csdn.net/tcjiaan/article/details/8538475

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

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

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

[cpp]  view plain  copy
 print ?
  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
 print ?
  1. HGDIOBJ WINAPI SelectObject(  
  2. HDC hdc, //设备描述表的句柄  
  3. HGDIOBJ h //要放到DC中的资源的句柄  
  4. );  

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

 

MoveToEx和LineTo

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

[cpp]  view plain  copy
 print ?
  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
 print ?
  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
 print ?
  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
 print ?
  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
 print ?
  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.    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值