| 函數 | 呼叫者 | 用途 |
ScreenSaverProc | 系統 (螢保視窗) | 主視窗程序,處理動畫、計時器、輸入終止邏輯 |
ScreenSaverConfigureDialog | 控制台「顯示內容」 | 設定對話框程序,讀寫 .ini/登錄檔 |
RegisterDialogClasses | 控制台 | 註冊設定對話框所需視窗類別,標準對話框可直接 RET TRUE |
資源檔規範(必要條件)
#define ICO_MAIN 100 ; 必須為 100,控制台顯示用圖示
#define DLG_SETUP 2003 ; 必須為 2003,設定對話框模板 ID
ICO_MAIN ICON "Resource\Main.ico"
DLG_SETUP DIALOG DISCARDABLE 0,0,300,120
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "螢幕保護程式"
FONT 9, "新細明體"
BEGIN
DEFPUSHBUTTON "確定(&O)", IDOK, 240,10,50,14
PUSHBUTTON "取消(&C)", IDCANCEL, 240,29,50,14
END
STRINGTABLE DISCARDABLE
BEGIN
100 "我的螢幕保護程式" ; ID=100,字串表首項,控制台列表顯示名稱
END
最小實作範本 (MASM32)
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
INCLUDE WINDOWS.INC
INCLUDE USER32.INC
INCLUDE KERNEL32.INC
INCLUDE SCRNSAVE.INC
INCLUDELIB SCRNSAVE.LIB
INCLUDELIB MSVCRT.LIB
ICO_MAIN EQU 100
DLG_SETUP EQU 2003
.DATA?
hInstance DD ?
hWinMain DD ?
.CODE
; --------------------------------------------------
; 設定對話框程序
; --------------------------------------------------
ScreenSaverConfigureDialog PROC USES EBX EDI ESI, \
hWnd:DWORD, wMsg:DWORD, wParam:DWORD, lParam:DWORD
MOV EAX, wMsg
.IF EAX == WM_CLOSE
INVOKE EndDialog, hWnd, NULL
.ELSEIF EAX == WM_COMMAND
MOV EAX, wParam
.IF EAX == IDOK
; 儲存設定至 .ini / 登錄檔
INVOKE EndDialog, hWnd, NULL
.ELSEIF EAX == IDCANCEL
INVOKE EndDialog, hWnd, NULL
.ENDIF
.ELSE
MOV EAX, FALSE
RET
.ENDIF
MOV EAX, TRUE
RET
ScreenSaverConfigureDialog ENDP
; --------------------------------------------------
; 主螢保視窗程序
; --------------------------------------------------
ScreenSaverProc PROC USES EBX EDI ESI, \
hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
MOV EAX, uMsg
.IF EAX == WM_CREATE
INVOKE GetModuleHandle, NULL
MOV hInstance, EAX
MOV EAX, hWnd
MOV hWinMain, EAX
; 初始化:載入位圖、建立計時器等
INVOKE SetTimer, hWinMain, TIMER_ID, 100, NULL
.ELSEIF EAX == WM_DESTROY
INVOKE KillTimer, hWinMain, TIMER_ID
; 釋放資源
.ELSEIF EAX == WM_TIMER
; 繪製動畫幀
XOR EAX, EAX
RET
.ELSEIF EAX == WM_ERASEBKGND
; 自行繪製背景 (若交給 DefScreenSaverProc 會得到黑底)
; 範例:填充自訂背景筆刷
; INVOKE GetDC, hWnd ...
; XOR EAX, EAX
; RET
.ENDIF
INVOKE DefScreenSaverProc, hWnd, uMsg, wParam, lParam
RET
ScreenSaverProc ENDP
; --------------------------------------------------
; 註冊對話框類別 (標準對話框無需額外註冊)
; --------------------------------------------------
RegisterDialogClasses PROC USES EBX EDI ESI, hInst:DWORD
MOV EAX, TRUE
RET
RegisterDialogClasses ENDP
END WinMain
關鍵開發須知
- 兩個獨立執行環境:
ScreenSaverProc 由系統在螢保啟動時載入;ScreenSaverConfigureDialog 由控制台進程載入。**兩者記憶體空間完全隔離**,不可共用全域變數。設定必須寫入 .ini 或登錄檔,WM_CREATE 讀取。
- 資源獨立載入:兩個程序各自在
WM_CREATE/WM_INITDIALOG 載入位圖、圖示等資源 (LoadBitmap/LoadIcon),不可假設已在記憶體中。
- 計時器驅動動畫:
WM_TIMER (通常 30~100ms) 是動畫主迴路,配合 InvalidateRect/UpdateWindow 觸發 WM_PAINT 繪製。
- WM_ERASEBKGND:若自行處理背景,**必須攔截並返回 0**,否則
DefScreenSaverProc 會重繪黑底造成閃爍。
- 建置輸出:
LINK /SUBSYSTEM:WINDOWS ... 產生 xxx.exe → 改名 xxx.scr → 複製至 Windows\System32 或 Windows 目錄。
除錯技巧
- 直接以命令列執行
xxx.scr 會進入預覽模式(視窗化非全螢幕)
xxx.scr /c 啟動設定對話框(模擬控制台呼叫)
xxx.scr /p 在指定視窗內嵌預覽(控制台「預覽」按鈕)
- 在
ScreenSaverProc 加入 OutputDebugString 觀察訊息流向
- 上一篇文章: Win32 組合語言教學:用戶區文字繪製(DrawText / BeginPaint / EndPaint / GetClientRect)
- 下一篇文章: Win32 組合語言教學:MessageBox 訊息框與 INVOKE 參數型別檢查
Copyright ©
程式碼之家 All Rights Reserved