在 Windows 95 時代,微軟引入了一系列強化的用戶界面控件,統稱為「通用控件」。這些控件包含工具列、狀態列、樹狀檢視、清單檢視、進度條、分頁控件等,極大地豐富了視窗應用程式的互動體驗。本文將系統介紹通用控件的架構、初始化機制、類別名稱對照表,並提供 MASM 組合語言實作範例,示範進度條與狀態列的協同運作。
Windows 95 相較於 Windows 3.x,內建了多種現代化界面元件。早期程式設計師需自行繪製這些控件,如今它們已封裝於 comctl32.dll 中,供所有應用程式共享,節省記憶體資源。主要控件如下:
除 Rich Edit 控件(位於 richedxx.dll)外,其餘控件程式碼皆集中於 comctl32.dll,採動態連結方式載入,避免重複佔用記憶體。
呼叫 InitCommonControls 函式是使用通用控件的前置條件。該函式本體僅有一條 ret 指令,真正目的是在程式的 PE 標頭「匯入表」中註冊 comctl32.dll,使載入器自動映射該 DLL。實際的控件類別註冊工作發生於 DLL 進入點,完成後即可透過 CreateWindowEx 以類別名稱建立控件實例。
Rich Edit 掃描則需額外呼叫 LoadLibrary 動態載入 richedxx.dll,用畢再以 FreeLibrary 釋放。
幾乎所有通用控件皆可透過 CreateWindowEx 或 CreateWindow 建立,只需傳入正確的類別名稱。部分控件提供封裝函式以簡化操作:
CreateToolbarEx
CreateStatusWindow
CreatePropertySheetPage
PropertySheet
ImageList_Create
以下為標準類別名稱(VC++ 資源編輯器標準,與其他文獻可能不同):
| 類別名稱 | 對應控件 |
|---|---|
| ToolbarWindow32 | Toolbar |
| tooltips_class32 | Tooltip |
| msctls_statusbar32 | Status bar |
| SysTreeView32 | Tree view |
| SysListView32 | List view |
| SysAnimate32 | Animation |
| SysHeader32 | Header |
| msctls_hotkey32 | Hot-key |
| msctls_progress32 | Progress bar |
| RICHEDIT | Rich edit |
| msctls_updown32 | Up-down |
| SysTabControl32 | Tab |
Property Sheet、Image List 等擁有專屬建立函式;Drag List 實為可伸縮 ListBox,無獨立類別名稱。
通用控件與父視窗通訊不使用 WM_COMMAND,改以 WM_NOTIFY 傳遞 NMHDR 結構指標,父視窗則發送 TVM_、LVM_ 等專用訊息控制控件行為。控件專有樣式(如 Tree View 的 TVS_XXXX、List View 的 LVS_XXXX)需參考 Win32 API 文件設定。
範例程式建立主視窗,於 WM_CREATE 時建立進度條與狀態列,並啟動計時器每 100ms 遞增進度條,完成時於狀態列顯示「Finished!」並彈出訊息框。
; 建立進度條
invoke CreateWindowEx, NULL, ADDR ProgressClass, NULL,
WS_CHILD+WS_VISIBLE, 100, 200, 300, 20, hWnd, IDC_PROGRESS, hInstance, NULL
mov hwndProgress, eax
; 設定範圍 0-1000,步進 10
mov eax, 1000
mov CurrentStep, eax
shl eax, 16
invoke SendMessage, hwndProgress, PBM_SETRANGE, 0, eax
invoke SendMessage, hwndProgress, PBM_SETSTEP, 10, 0
; 建立狀態列
invoke CreateStatusWindow, WS_CHILD+WS_VISIBLE, NULL, hWnd, IDC_STATUS
mov hwndStatus, eax
; 建立計時器
invoke SetTimer, hWnd, IDC_TIMER, 100, NULL
.elseif uMsg==WM_TIMER
invoke SendMessage, hwndProgress, PBM_STEPIT, 0, 0
sub CurrentStep, 10
.if CurrentStep==0
invoke KillTimer, hWnd, TimerID
mov TimerID, 0
invoke SendMessage, hwndStatus, SB_SETTEXT, 0, addr Message
invoke MessageBox, hWnd, addr Message, addr AppName, MB_OK+MB_ICONINFORMATION
invoke SendMessage, hwndStatus, SB_SETTEXT, 0, 0
invoke SendMessage, hwndProgress, PBM_SETPOS, 0, 0
.endif
範例特意將 InitCommonControls 置於 ExitProcess 之後,證明該函式僅作 PE 匯入表註冊用途,控件仍能正常運作。
掌握通用控件的初始化、類別名稱、建立方式與 WM_NOTIFY 通訊機制,是開發現代化 Windows 介面應用程式的基石。搭配 MASM 組合語言的精確控制,可打造高效能、小體積的視窗程式。