作者分享使用 MASM32 (組合語言) 呼叫 user32.dll 中的 AnimateWindow API,實作對話方塊的淡入淡出動畫,作為定時休息提醒工具的 UI 效果。
BOOL AnimateWindow(
HWND hwnd, // 目標視窗控制代碼
DWORD dwTime, // 動畫持續時間 (毫秒),建議 200ms 以上
DWORD dwFlags // 動畫類型旗標組合
);
| 旗標 | 值 | 效果 |
|---|---|---|
| AW_SLIDE | 0x40000 | 滑入/滑出 (預設為滾動) |
| AW_ACTIVATE | 0x20000 | 啟動視窗 (顯示時使用) |
| AW_BLEND | 0x80000 | 淡入/淡出 (僅限最上層視窗) |
| AW_HIDE | 0x10000 | 隱藏視窗 (關閉時使用) |
| AW_CENTER | 0x0010 | 向中心收縮/從中心展開 |
| AW_HOR_POSITIVE | 0x0001 | 從左向右滑入 |
| AW_VER_POSITIVE | 0x0004 | 從上向下滑入 |
| AW_VER_NEGATIVE | 0x0008 | 從下向上滑入 |
失敗情況:視窗有邊框、已顯示又呼叫顯示、已隱藏又呼叫隱藏。
; AninWin.asm - 示範 AnimateWindow 淡入淡出
.586
.model flat, stdcall
option casemap:none
; 巨集:同時 include .inc 與 includelib .lib
incboth macro incl
include d:\masm32\include\incl.inc
includelib d:\masm32\lib\incl.lib
endm
include d:\masm32\include\windows.inc
incboth kernel32
incboth user32
incboth gdi32
incboth comctl32
incboth shell32
DlgProc PROTO :HWND, :UINT, :WPARAM, :LPARAM
.const
IDD_dlgSetState equ 1000
.data
g_szAnimWin db "AnimateWindow", 0
g_szUser32Dll db "user32.dll", 0
g_szEditCls db "edit", 0
.data?
hInstance HINSTANCE ?
pAnimateWindow DD ?
.code
start:
invoke GetModuleHandle, NULL
mov [hInstance], eax
invoke DialogBoxParam, [hInstance], IDD_dlgSetState, NULL, OFFSET DlgProc, NULL
invoke ExitProcess, NULL
invoke InitCommonControls
DlgProc proc hWnd:HWND, wMsg:UINT, lParam:LPARAM, wParam:WPARAM
.if wMsg == WM_INITDIALOG
; 取得 AnimateWindow 位址
invoke SendMessage, [hWnd], WM_SETTEXT, NULL, OFFSET g_szAnimWin
invoke GetModuleHandle, OFFSET g_szUser32Dll
invoke GetProcAddress, eax, OFFSET g_szAnimWin
mov [pAnimateWindow], eax
; 取得位址成功 -> 淡入顯示
.if [pAnimateWindow]
push AW_BLEND + AW_ACTIVATE
push 400h ; 1024 ms
push [hWnd]
call [pAnimateWindow]
.endif
invoke InvalidateRect, hWnd, 0, TRUE
.elseif wMsg == WM_CLOSE
; 淡出關閉
.if [pAnimateWindow]
push AW_BLEND + AW_HIDE
push 400h
push [hWnd]
call [pAnimateWindow]
.endif
invoke EndDialog, [hWnd], NULL
.else
mov eax, FALSE
ret
.endif
xor eax, eax
ret
DlgProc endp
end start
; rsrc.rc
#include "\masm32\include\resource.h"
#define IDC_lblAppInfo 3009
#define IDD_dlgSetState 1000
IDD_dlgSetState DIALOG 10, 10, 120, 114
STYLE 0x0004 | DS_CENTER | WS_CAPTION | DS_SYSMODAL | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "Get Color"
FONT 9, "新細明體"
{
LTEXT "purpleendurer@163.com\n2004.04.02 廣西河池\n開發環境:MASM32 V8", IDC_lblAppInfo, 0, 75, 105, 30, WS_DISABLED + SS_CENTER
}
GetModuleHandle("user32.dll") + GetProcAddress("AnimateWindow"),避免靜態連結相依性,支援舊版 Windows (API 存在才呼叫)。AW_BLEND + AW_ACTIVATE 淡入並置頂;AW_BLEND + AW_HIDE 淡出並銷毀。400h (1024ms) 讓淡入淡出較緩慢,適合提醒類視窗。.asm + .rc → ml /c /coff + rc → link /subsystem:windows。SetLayeredWindowAttributes 實作更精細的透明度動畫。AnimateWindow 達到同樣效果。短短幾十行組合語言,即可賦予視窗專業級的動畫體驗,展現底層 API 的威力與 MASM32 的開發效率。