Windows 程式設計/GDI 和繪圖
此頁面為Windows 程式設計書籍中的一個存根。您可以透過擴充套件它來提供幫助。
本頁將討論使用 Windows GDI 庫進行圖形和繪圖。
GDI 是 Windows 的原始圖形 API。但是,DirectX 圖形基礎架構 現在推薦用於其改進的 GPU 函式使用、alpha 混合 和 抗鋸齒[1]。
裡面有什麼?以及它們的預設值
| GDI 物件(每種型別一個) | Windows 版本 | 設定函式 | 獲取函式 | |
| 畫筆 | 零寬度黑色畫筆(表示在任何縮放比例下 1 畫素寬度) | 2 | SelectObject(SelectPen、SelectBrush、SelectFont) | GetCurrentObject |
| 畫刷 | 白色實心畫刷 | 2 | ||
| 字型 | 系統預設字型 | 2 | ||
| 調色盤 | 系統預設調色盤(見下文) | 3 | SelectPalette | |
| 顏色空間 | ? | 4 | SetColorSpace | |
| 目標點陣圖(不適用於元檔案上下文) | 取決於建立 DC 的函式 | 2 | SelectObject(SelectBrush) | |
| 裁剪區域 | 取決於建立 DC 的函式 | 2 | GetClipRgn(GetClipBox) | |
| 數字 | ||||
| 對映模式、縮放和偏移量 | 1 單位 = 1 畫素,原點 = 左/上 | 2 | Get/Set MapMode、WindowOrgEx、WindowExtEx、ViewportOrgEx、ViewportExtEx | |
| 變換矩陣(旋轉、剪下、縮放、偏移量) | 平等 | 4 | SetWorldTransform、ModifyTransform | GetWorldTransform |
| 文字顏色,也用於涉及 blt 操作的黑白 | 黑色 | 2 | SetTextColor | GetTextColor |
| 背景顏色,用於文字 / 網格畫刷 / 虛線背景和一些 blt 操作 | 白色 | 2 | SetBkColor | GetBkColor |
| 斜接限制(銳利多邊形角的裁剪) | 10.0F(線寬的十倍) | 4 | SetMiterLimit | GetMiterLimit |
| 畫刷原點(用於對齊圖案畫刷) | 0/0 | 2 | SetBrushOrgEx | GetBrushOrgEx |
| 列舉和布林開關 | ||||
| 啟用高階 GDI 函式 | 否 | 4 | SetGraphicsMode | GetGraphicsMode |
| 複雜多邊形內或外(PolyFillMode) | 交替規則 | 2 | SetPolyFillMode | GetPolyFillMode |
| 文字對齊 | 頂部/左側 | 2 | SetTextAlign | GetTextAlign |
| 文字 / 網格畫刷 / 虛線輸出是否具有不透明背景顏色 | 有背景 | 2 | SetBkMode | GetBkMode |
| 點陣圖在 blt 操作中如何拉伸 | ? | 3 | SetStretchBltMode | GetStretchBltMode |
| 畫筆 / 畫刷和表面如何組合(布林運算) | 複製畫筆 | 2 | SetROP2 | GetROP2 |
| 其他 | ||||
| 路徑(準備好的線) | 空路徑 | 4 | BeginPath、EndPath ... | - |
| 上下文堆疊 | 空 | 2 | SaveDC | RestoreDC |
待續...
Windows 使用畫刷來繪製顏色並使用預定義的圖案填充區域。畫刷的最小尺寸為 8X8 畫素,並且與畫筆類似,具有三個基本特徵:大小、圖案和顏色。由於其 8X8 畫素的最小尺寸,畫刷被認為具有圖案,而不是像畫筆那樣的樣式。圖案可以是實色、網格、對角線或任何其他使用者定義的組合,甚至是點陣圖圖案。
case WM_PAINT:
{
/* This will paint a red rectangle */
HDC holdBrush;
HDC hdc = BeginPaint(hwnd, &ps);
HBRUSH hBrush = CreateSolidBrush(RGB(255,0,0));
holdBrush = SelectObject(hdc, hBrush);
Rectangle(hdc, 10, 10, 100, 100);
DeleteObject(hBrush);
/* Memory management has been omitted for brevity */
EndPaint(hwnd, &ps);
break;
}
畫刷物件背後是什麼?
| 在建立時,請參見 LOGBRUSH 結構 | 修改 |
|---|---|
| 顏色(RGB 顏色,可以在實現時進行抖動) | SetDCBrushColor |
| 樣式(實心、網格或點陣圖) | - |
| 點陣圖(對於點陣圖樣式) | - |
| 實現時的隱藏欄位 | |
| 引用裝置上下文(跟蹤實現是否仍然有效) | UnrealizeObject |
| 裝置相關,可能是抖動的點陣圖,通常為 8x8 尺寸 | - |
請注意,點陣圖圖案畫刷的行為與網格畫刷不同,即使點陣圖看起來像網格。網格畫刷是透明的,而點陣圖畫刷是不透明的。如果使用黑白點陣圖,黑色將被替換為裝置上下文的文字顏色,白色將被替換為背景顏色。(這正是 BitBlt() 的行為。)SetBkMode() 不會起作用。但是,DC 的 ROP2 會起作用。
畫筆用於建立繪製的形狀周圍的邊框。
| 可見欄位,請參見 LOGPEN 結構 | Windows 版本 | 修改 |
|---|---|---|
| 寬度,以水平(!) 邏輯單位表示,0 = 1 畫素 | 2 | - |
| 樣式(實心或某種點線) | 2 | - |
| 使用者點線樣式(對於使用者選擇的樣式) | 4 | - |
| 顏色 | 2 | SetDCPenColor |
| 畫刷(內容:見上文) | 4 | - |
| 幾何/裝飾標誌 | 4 | - |
| 提示如何繪製線端 | 4 | - |
| 提示如何繪製線連線 | 4 | - |
| 隱藏欄位 | ||
| 引用裝置上下文(跟蹤其他隱藏欄位的有效性) | 2 | UnrealizeObject? |
| 以裝置畫素表示的寬度 | 2 | - |
| 給定顏色的調色盤索引 | 2 | - |
| 用於填充寬線的裝置相關點陣圖 | 2 | - |
導致寬度大於 1 裝置畫素(而不是邏輯單位)的線將作為具有繞線規則的多邊形繪製。線顏色永遠不會進行抖動,除非使用具有實心畫刷的 ExtCreatePen。
字型用於以各種樣式和尺寸顯示文字和符號。Windows 2(非常基本)、3.1(引入 TrueType)和 4+(Unicode;世界變換旋轉和映象;傾斜度可能與旋轉不同)之間的字型管理存在內部較大差異。
請參見 LOGFONT 結構以瞭解可見欄位。
隱藏欄位包括
- 引用裝置上下文
- 裝置相關點陣圖字體表示
因此,將字型選擇到裝置上下文(SelectObject)可能很耗時,尤其是對於大型亞洲字型和大型字型尺寸,需要從 TrueType 模板中“繪製”所有字形到點陣圖中。此外,與所有 GDI 物件一樣,最好不要在一個上下文之間選擇一個物件,因為使隱藏檔案失效可能是一個耗時的過程。請注意,任何 GDI 物件都不能選擇到多個 DC 中。
在 Windows 中,繪圖通常由 WM_PAINT 訊息處理。以下是繪製紅色正方形的示例
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
// RECT defines the upper-left and lower-right corners of a rectangle
RECT rectangle = {50, 50, 250, 250};
HBRUSH hbr = CreateSolidBrush(RGB(125, 0, 0));
FillRect(ps.hdc, &rectangle, hbr);
DeleteObject(hbr);
EndPaint(hwnd, &ps);
}
break;
首先,我們建立 PAINTSTRUCT 變數 ps。這是一個包含有關繪畫操作的資訊的資料結構。下一行呼叫 BeginPaint。這將初始化 ps,然後用相關資訊填充它。對於此示例,我們只需要 ps 的 hdc 成員。這是一個指向我們視窗裝置上下文的控制代碼。接下來,我們建立一個矩形。這包含我們要繪製此矩形的左上角和右下角座標。座標相對於視窗客戶區的左上角。我們還必須建立一個畫刷,否則 Windows 將不知道要使用什麼顏色來繪製矩形。最後,我們呼叫 FillRect,並傳遞引數 ps.hdc、指向 rectangle 的指標和 hbr(我們的畫刷)。這會將矩形直接繪製到我們視窗的裝置上下文,然後從那裡繪製到螢幕上。在每次繪畫操作後,都需要清理我們使用的任何 GDI 物件,在本例中為 hbr 和 ps。
由於 Windows 應該響應 WM_PAINT 和 WM_PRINTCLIENT,因此編寫 WM_PAINT 處理程式的一般規則如下
case WM_PRINTCLIENT: OnPaint((HDC)wParam, NULL); break;
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
OnPaint(ps.hdc, &ps.rcPaint); // It's a good idea to manage the update area. Other PAINTSTRUCT fields are of less usefulness.
EndPaint(hwnd, &ps);
}break;
// Somewhere else
void OnPaint(HDC dc, RECT* rcUpdate) {
...
}
- ↑ QuinnRadich. "Windows 圖形架構概述 - Win32 應用". learn.microsoft.com. 檢索於 2023-04-11.