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

Win32 螢幕保護程式開發完整指南:SCRNSAVE.LIB 架構與實作範本

     編輯:組合語言

螢幕保護程式本質

  • 副檔名 .scr 的標準 PE 執行檔(由 .exe 改名)
  • 系統閒置觸發:發送 WM_SYSCOMMAND, wParam=SC_SCREENSAVE 給前景視窗,前景視窗啟動 SYSTEM.INI [boot] ScreenSaveActive 指定的 .scr
  • 可透過攔截 WM_SYSCOMMAND/SC_SCREENSAVE 並不傳遞 DefWindowProc 來禁止啟動(影片播放、燒錄軟體常用)

SCRNSAVE.LIB 提供的基礎設施

  • 內建 WinMain 入口,程式尾以 END WinMain 結束
  • 自動建立全螢幕視窗(WS_POPUP | WS_VISIBLE,覆蓋工作列)
  • 預設訊息處理:
    • WM_SETCURSOR → 隱藏游標
    • WM_PAINT → 黑色背景
    • WM_LBUTTONDOWN/MBUTTONDOWN/RBUTTONDOWN/KEYDOWN/MOUSEMOVE → 終止
    • WM_ACTIVATE, wParam=FALSE → 終止
  • 提供 DefScreenSaverProc 處理上述預設行為,開發者可選擇性轉發

必須實作的三個匯出函數(.DEF 指定 EXPORTS)

資源檔規範(必要條件)

#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 觀察訊息流向
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
函數呼叫者用途
ScreenSaverProc系統 (螢保視窗)主視窗程序,處理動畫、計時器、輸入終止邏輯
ScreenSaverConfigureDialog控制台「顯示內容」設定對話框程序,讀寫 .ini/登錄檔
RegisterDialogClasses控制台註冊設定對話框所需視窗類別,標準對話框可直接 RET TRUE