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

Win32 組合語言教學:用戶區文字繪製(DrawText / BeginPaint / EndPaint / GetClientRect)

     編輯:組合語言

教學目標

示範在 WM_PAINT 中正確繪製文字:取得裝置環境(BeginPaint)、查詢用戶區大小(GetClientRect)、以 DrawText 置中單行顯示、釋放裝置環境(EndPaint)。對比低層 TextOut,DrawText 內建換行、置中、裁剪功能,更適合動態版面。

核心流程與關鍵結構

PAINTSTRUCT 與 RECT

LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT

; RECT 結構 (Windows.inc 定義)
RECT STRUCT
  left   LONG ?
  top    LONG ?
  right  LONG ?
  bottom LONG ?
RECT ENDS

GetClientRect(hWnd, &rect) 回傳用戶區座標:left=top=0,right=寬度,bottom=高度。

WM_PAINT 處理範例

.ELSEIF uMsg==WM_PAINT
  INVOKE BeginPaint, hWnd, ADDR ps
  MOV hdc, EAX
  INVOKE GetClientRect, hWnd, ADDR rect
  INVOKE DrawText, hdc, ADDR OurText, -1, ADDR rect, \
       DT_SINGLELINE OR DT_CENTER OR DT_VCENTER
  INVOKE EndPaint, hWnd, ADDR ps

DrawText 參數完整解析

DrawText PROTO hdc:HDC, lpString:DWORD, nCount:DWORD, lpRect:DWORD, uFormat:DWORD
參數說明
hdc裝置環境控制代碼
lpString欲繪製字串位址,以 0 結尾或由 nCount 指定長度
nCount字元數,-1 表以 0 結尾字串自動計算
lpRect格式化矩形區域 (RECT),同時作為裁剪區
uFormat格式旗標組合 (OR)

常用 uFormat 旗標

  • DT_SINGLELINE:單行模式,忽略換行字元,垂直置中需配合 DT_VCENTER
  • DT_CENTER:水平置中
  • DT_VCENTER:垂直置中 (僅單行有效)
  • DT_WORDBREAK:單字換行
  • DT_CALCRECT:不實際繪製,僅計算所需矩形大小 (輸出於 lpRect)
  • DT_NOCLIP:不裁剪,略過邊界檢查略微加速
  • DT_EXPANDTABS:展開 Tab 字元
  • DT_RIGHT:靠右對齊

BeginPaint / EndPaint 必備規則

  1. 成對呼叫:每個 WM_PAINT 必須且只能呼叫一次 BeginPaint / EndPaint
  2. 自動驗證無效區:BeginPaint 內部會呼叫 ValidateRect,清除無效區旗標。若不處理 WM_PAINT 也不呼叫 DefWindowProc,會陷入無限 WM_PAINT 風暴。
  3. 剪輯區自動設定:BeginPaint 依 PAINTSTRUCT.rcPaint 設定 DC 剪輯區,繪圖指令自動限制於需更新區域,提升效能。
  4. 不可跨訊息持有 HDC:EndPaint 釋放 DC,下一個訊息必須重新 BeginPaint 或 GetDC。

DrawText vs TextOut

特性DrawTextTextOut
換行處理內建 (DT_WORDBREAK)無,需自行計算
對齊/置中旗標控制 (DT_CENTER/VCENTER)需自行計算座標
裁剪以 lpRect 為裁剪區依 DC 剪輯區
回傳值文字高度 (邏輯單位)成功非零
適用場景動態版面、標籤、按鈕文字固定座標、高效能繪圖迴路

非 WM_PAINT 繪圖替代方案

  • 方案 A:GetDC → 繪圖 → ReleaseDC (即時回饋,不持久)
  • 方案 B:InvalidateRect(hWnd, NULL, TRUE) → UpdateWindow(hWnd) 強制同步發送 WM_PAINT (持久化,建議做法)

常見錯誤

  • ❌ 忘記 EndPaint → DC 洩漏、後續 BeginPaint 失敗
  • ❌ DrawText 的 lpRect 傳遞錯誤位址 → 存取違規
  • ❌ nCount 傳正數但字串含 0 → 截斷顯示
  • ❌ 用 DT_VCENTER 於多行文字 → 垂直置中失效
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved