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

Win32 開發入門(3):視窗重繪機制與 WM_PAINT 處理

     編輯:關於C++

視窗重繪觸發時機

  • 視窗被遮擋後重新顯示
  • 視窗大小改變
  • 視窗最小化後還原

此時系統傳送 WM_PAINT 訊息要求重繪。

自動重繪:類別樣式 CS_HREDRAW | CS_VREDRAW

註冊視窗類別時設定:


wc.style = CS_HREDRAW | CS_VREDRAW; // 水平/垂直大小改變時自動重繪整個用戶區

若未設定,縮放視窗會殘留舊內容 (黑色區塊)。

空白視窗

未設定重繪樣式縮放殘留

設定重繪樣式後正常

背景畫刷與 COLOR_WINDOW


wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

COLOR_WINDOW 為系統色彩常數 (值 5),+1 取得對應的系統畫刷控制代碼 (值 6,即 COLOR_WINDOWFRAME),系統會自動填充背景。

系統色彩常數定義

WM_PAINT 繪圖流程


case WM_PAINT: {
    PAINTSTRUCT ps;
    BeginPaint(hwnd, &ps);        // 取得繪圖 DC,ps.rcPaint 為需重繪矩形
    // 繪圖操作...
    EndPaint(hwnd, &ps);          // 釋放 DC,驗證更新區域
} return 0;

注意:BeginPaint/EndPaint 僅能用於 WM_PAINT 處理中,其他場合需用 GetDC/ReleaseDC。

文字繪製與顏色


SetTextColor(ps.hdc, RGB(10, 0, 255)); // 設定文字顏色
DrawText(ps.hdc, L"朋友,你好。", -1, &ps.rcPaint, DT_CENTER);

藍色文字置中

多行文字:PolyTextOut


POLYTEXT polys[] = {
    {2, 2, 3, L"大家", ETO_CLIPPED, ps.rcPaint, &arr1[0]},
    {2, 25, 3, L"新年好", ETO_CLIPPED, ps.rcPaint, &arr2[0]},
    {30, 60, 3, L"快樂", ETO_CLIPPED, ps.rcPaint, &arr3[0]}
};
PolyTextOut(ps.hdc, polys, 3);

各項可指定座標、字元數、間距陣列,但字符渲染品質較 DrawText 略遜。

PolyTextOut 多行文字

填充圖形


HBRUSH hb = CreateSolidBrush(RGB(0,255,0));
HBRUSH orgBrs = (HBRUSH)SelectObject(ps.hdc, hb);
Ellipse(ps.hdc, 135, 35, 202, 170); // 繪製填充橢圓
SelectObject(ps.hdc, orgBrs);
DeleteObject(hb);

填充橢圓

完整程式碼清單


#include <Windows.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrvInstance, LPSTR lpCommandLine, int cmdShow) {
    WCHAR* cln = L"MyApp";
    WNDCLASS wc = { };
    wc.hInstance = hInstance;
    wc.lpszClassName = cln;
    wc.lpfnWndProc = WindowProc;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wc);
    
    HWND hMainwind = CreateWindow(cln, L"繪製視窗", WS_OVERLAPPEDWINDOW,
                                  20, 12, 450, 300, NULL, NULL, hInstance, NULL);
    if (hMainwind == NULL) return 0;
    ShowWindow(hMainwind, SW_NORMAL);
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_PAINT: {
            PAINTSTRUCT ps; BeginPaint(hwnd, &ps);
            SetTextColor(ps.hdc, RGB(10, 0, 255));
            DrawText(ps.hdc, L"朋友,你好。", -1, &ps.rcPaint, DT_CENTER);
            
            // 多行文字示範
            int arr1[2] = {45,0}, arr2[3] = {35,40,0}, arr3[2] = {32,0};
            POLYTEXT polys[] = {
                {2,2,3,L"大家",ETO_CLIPPED,ps.rcPaint,&arr1[0]},
                {2,25,3,L"新年好",ETO_CLIPPED,ps.rcPaint,&arr2[0]},
                {30,60,3,L"快樂",ETO_CLIPPED,ps.rcPaint,&arr3[0]}
            };
            PolyTextOut(ps.hdc, polys, 3);
            
            // 填充橢圓
            HBRUSH hb = CreateSolidBrush(RGB(0,255,0));
            HBRUSH orgBrs = (HBRUSH)SelectObject(ps.hdc, hb);
            Ellipse(ps.hdc, 135, 35, 202, 170);
            SelectObject(ps.hdc, orgBrs);
            DeleteObject(hb);
            
            EndPaint(hwnd, &ps);
        } return 0;
        case WM_DESTROY:
            PostQuitMessage(0); return 0;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

重點整理

  • CS_HREDRAW | CS_VREDRAW 讓視窗大小改變時自動重繪整個用戶區
  • wc.hbrBackground 設定背景畫刷,配合系統色彩常數
  • WM_PAINT 流程:BeginPaint → 繪圖 → EndPaint (自動管理 DC)
  • DrawText 繪製單行/多行文字,支援對齊選項
  • SetTextColor 設定文字顏色,影響後續文字繪製
  • PolyTextOut 一次繪製多行文字,可控制字符間距
  • 填充圖形:CreateSolidBrush → SelectObject → 繪圖 → SelectObject 還原 → DeleteObject
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved