程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Win32開發入門(9) 繪圖(B)

Win32開發入門(9) 繪圖(B)

編輯:關於C++

我們今天繼續塗鴉,實踐證明,塗鴉是人生一大樂趣。

首先,我們寫一個程序骨架子,以便 做實驗。

#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函數將其銷毀 。

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;

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);

上面的代碼將畫出以下圖形。

完整的代碼清單如下:

#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);     
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved