读书人

跟小弟我一起玩Win32开发(9):绘图(

发布时间: 2013-01-28 11:49:56 作者: rapoo

跟我一起玩Win32开发(9):绘图(B)

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

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

#include <Windows.h>LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hThisApp,HINSTANCE hPrevApp,LPSTR lpsCmdln,int iShow){WNDCLASS wc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));// 默认光标类型为箭头wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);// 默认应用程序图标wc.hIcon = LoadIcon(hThisApp, IDI_APPLICATION);wc.hInstance = hThisApp;wc.lpfnWndProc = MainWinProc;wc.lpszClassName = L"MyAppTest";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW | CS_VREDRAW;// 注册窗口类RegisterClass(&wc);// 创建窗口HWND hwnd = CreateWindow(L"MyAppTest",L"绘画课",/* 使用 WS_VISIBLE 就不用调用ShowWindow了 */WS_VISIBLE | WS_OVERLAPPEDWINDOW,100,45,500,380,NULL,NULL,hThisApp,NULL);// 消息循环MSG msg;while(GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_DESTROY:PostQuitMessage(0);return 0;case WM_PAINT:PAINTSTRUCT ps;BeginPaint(hwnd, &ps);                /*                    待实现                */EndPaint(hwnd, &ps);return 0;}return DefWindowProc(hwnd, msg, wParam, lParam);}

CreatePen函数

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

HPEN  CreatePen(      int iStyle, //钢笔的样式,如虚线、实线      int cWidth, //线条宽度      COLORREF color //线条是啥颜色的);

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

/* Pen Styles */#define PS_SOLID            0#define PS_DASH             1       /* -------  */#define PS_DOT              2       /* .......  */#define PS_DASHDOT          3       /* _._._._  */#define PS_DASHDOTDOT       4       /* _.._.._  */#define PS_NULL             5#define PS_INSIDEFRAME      6#define PS_USERSTYLE        7#define PS_ALTERNATE        8

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

SelectObject函数

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

HGDIOBJ WINAPI SelectObject(HDC hdc, //设备描述表的句柄HGDIOBJ h //要放到DC中的资源的句柄);

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

MoveToEx和LineTo

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

// 创建钢笔HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50));// 把笔选到DC中SelectObject(ps.hdc, pen);// 设定线段的起点MoveToEx(ps.hdc, 15, 25, NULL);// 绘制线条LineTo(ps.hdc, 65, 49);LineTo(ps.hdc, 12, 120);LineTo(ps.hdc, 250, 78);LineTo(ps.hdc, 312, 185);DeleteObject(pen);


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

跟小弟我一起玩Win32开发(9):绘图(B)


PolyBezier函数和PolyBezierTo函数

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

// 绘制贝塞尔曲线pen = CreatePen(PS_DOT, 1, RGB(0,3,255));SelectObject(ps.hdc, pen);POINT* pts = new POINT[4];pts[0].x = 421;pts[0].y = 16;pts[1].x = 7;pts[1].y = 197;pts[2].x = 480;pts[2].y = 320;pts[3].x = 30;pts[3].y = 350;PolyBezier(ps.hdc, pts, 4);delete [] pts;// 第二段贝塞尔曲线POINT* pts2 = new POINT[3];pts2[0].x = 176;pts2[0].y = 84;pts2[1].x = 17;pts2[1].y = 247;pts2[2].x = 400;pts2[2].y = 490;// 移动当前点MoveToEx(ps.hdc, 395, 270, NULL);PolyBezierTo(ps.hdc, pts2, 3);delete [] pts2;


跟小弟我一起玩Win32开发(9):绘图(B)

PolyPolyline绘制复合线条

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

  BOOL PolyPolyline(    HDC hdc,    const POINT *lppt,    const DWORD *lpdwPolyPoints,    DWORD cCount  );


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

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

{ 2, 3, 2 }

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

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

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

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

跟小弟我一起玩Win32开发(9):绘图(B)

完整的代码清单如下:

#include <Windows.h>LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hThisApp,HINSTANCE hPrevApp,LPSTR lpsCmdln,int iShow){WNDCLASS wc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));// 默认光标类型为箭头wc.hCursor = LoadCursor(hThisApp, IDC_ARROW);// 默认应用程序图标wc.hIcon = LoadIcon(hThisApp, IDI_APPLICATION);wc.hInstance = hThisApp;wc.lpfnWndProc = MainWinProc;wc.lpszClassName = L"MyAppTest";wc.lpszMenuName = NULL;wc.style = CS_HREDRAW | CS_VREDRAW;// 注册窗口类RegisterClass(&wc);// 创建窗口HWND hwnd = CreateWindow(L"MyAppTest",L"绘画课",/* 使用 WS_VISIBLE 就不用调用ShowWindow了 */WS_VISIBLE | WS_OVERLAPPEDWINDOW,100,45,500,380,NULL,NULL,hThisApp,NULL);// 消息循环MSG msg;while(GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_DESTROY:PostQuitMessage(0);return 0;case WM_PAINT:PAINTSTRUCT ps;BeginPaint(hwnd, &ps);// 创建钢笔HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50));// 把笔选到DC中SelectObject(ps.hdc, pen);// 设定线段的起点MoveToEx(ps.hdc, 15, 25, NULL);// 绘制线条LineTo(ps.hdc, 65, 49);LineTo(ps.hdc, 12, 120);LineTo(ps.hdc, 250, 78);LineTo(ps.hdc, 312, 185);// 绘制贝塞尔曲线pen = CreatePen(PS_DOT, 1, RGB(0,3,255));SelectObject(ps.hdc, pen);POINT* pts = new POINT[4];pts[0].x = 421;pts[0].y = 16;pts[1].x = 7;pts[1].y = 197;pts[2].x = 480;pts[2].y = 320;pts[3].x = 30;pts[3].y = 350;PolyBezier(ps.hdc, pts, 4);delete [] pts;// 第二段贝塞尔曲线POINT* pts2 = new POINT[3];pts2[0].x = 176;pts2[0].y = 84;pts2[1].x = 17;pts2[1].y = 247;pts2[2].x = 400;pts2[2].y = 490;// 移动当前点MoveToEx(ps.hdc, 395, 270, NULL);PolyBezierTo(ps.hdc, pts2, 3);delete [] pts2;// 复杂图形pen = CreatePen(PS_DASHDOTDOT, 1, RGB(80,20,160));SelectObject(ps.hdc, pen);POINT plpts[10] ={{47,3}, {11,46}, {28,199}, {203,305}, {94,22},{402,377}, {21,45}, {237,7}, {300,398}, {175,25}};DWORD arr[4] = { 2, 3, 3, 2};PolyPolyline(ps.hdc, &plpts[0], &arr[0], 4);DeleteObject(pen);EndPaint(hwnd, &ps);return 0;}return DefWindowProc(hwnd, msg, wParam, lParam);} 

读书人网 >编程

热点推荐