首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Win32 開發入門(9):繪圖基礎——畫筆、貝茲曲線與複合線條

     編輯:關於C++

繪圖前置作業:畫筆的建立與選入

繪圖前必須建立畫筆 (HPEN) 並選入裝置內容 (DC):

HPEN pen = CreatePen(PS_DASH, 1, RGB(0,255,50)); // 建立虛線畫筆
SelectObject(ps.hdc, pen); // 選入 DC
// 繪圖操作...
DeleteObject(pen); // 用完釋放

CreatePen 參數說明

  • iStyle:線條樣式(PS_SOLID 實線、PS_DASH 虛線、PS_DOT 點線、PS_DASHDOT 虛點線、PS_DASHDOTDOT 雙點虛線等)
  • cWidth:線條寬度
  • color:COLORREF 顏色值(用 RGB 宏產生)

基本繪圖函式

  • MoveToEx(hdc, x, y, NULL):設定當前繪圖起點
  • LineTo(hdc, x, y):從當前點畫直線到指定座標
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);

連續線段繪製結果

貝茲曲線繪製

PolyBezier

一次繪製多段三次貝茲曲線,需提供 3n+1 個控制點(n 為曲線段數)。

POINT* pts = new POINT[4];
pts[0] = {421, 16}; pts[1] = {7, 197};
pts[2] = {480, 320}; pts[3] = {30, 350};
PolyBezier(ps.hdc, pts, 4); // 1 條曲線需 4 點
delete[] pts;

PolyBezierTo

從「當前點」開始繪製,需 3n 個控制點。


MoveToEx(ps.hdc, 395, 270, NULL); // 設定起點
POINT* pts2 = new POINT[3];
pts2[0] = {176, 84}; pts2[1] = {17, 247}; pts2[2] = {400, 490};
PolyBezierTo(ps.hdc, pts2, 3); // 1 條曲線需 3 點
delete[] pts2;

貝茲曲線繪製結果

複合線條

PolyPolyline 可一次繪製多條不相連的線條組合。


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}; // 每組點數:2+3+3+2=10
PolyPolyline(ps.hdc, plpts, arr, 4);

arr 陣列指定每條線條使用的點數,每組至少 2 點。

複合線條繪製結果

完整程式碼清單

#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 | 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));
            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] = {421, 16}; pts[1] = {7, 197};
            pts[2] = {480, 320}; pts[3] = {30, 350};
            PolyBezier(ps.hdc, pts, 4);
            delete[] pts;
            
            POINT* pts2 = new POINT[3];
            pts2[0] = {176, 84}; pts2[1] = {17, 247}; pts2[2] = {400, 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, arr, 4);
            DeleteObject(pen);
            
            EndPaint(hwnd, &ps);
        } return 0;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

重點整理

  • CreatePen 建立畫筆,SelectObject 選入 DC,用畢 DeleteObject 釋放
  • MoveToEx/LineTo 繪製連續線段
  • PolyBezier:指定起點的貝茲曲線(3n+1 點)
  • PolyBezierTo:從當前點開始的貝茲曲線(3n 點)
  • PolyPolyline:一次繪製多條獨立線條,透過陣列指定每組點數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved