在開發 Windows 桌面應用程式時,常需要在螢幕右下角顯示視窗(如倒計時提醒),但必須避免遮擋系統任務欄。這就需要準確獲取任務欄的高度,以便正確計算視窗位置。本文介紹一個使用 MASM32 組合語言呼叫 Windows API 來獲取任務欄高度的經典方法。
Windows 系統提供了 SystemParametersInfo 函數,配合 SPI_GETWORKAREA 參數可獲取「桌面工作區」的矩形範圍。工作區即排除任務欄後的可用螢幕區域。通過比較螢幕完整解析度與工作區矩形,即可推算任務欄的位置與高度。
SystemParametersInfo(SPI_GETWORKAREA, ...) 取得工作區矩形 stDeskRect。stDeskRect.top != 0,表示任務欄位於螢幕上方,其高度即為 stDeskRect.top。SM_CYSCREEN,若螢幕高度不等於工作區底部座標 stDeskRect.bottom,則任務欄在底部,高度為兩者之差;若相等,則任務欄在左右側,高度即螢幕高度(較少見)。; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Function: 計算並顯示系統任務欄高度
; Author: PurpleEndurer
; DevEnv: Win XP SP2 + MASM32 v7
; log
; ----------------------------------------------------
; 2008-09-21 Created!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
GetTaskBarHeight proto
.data
g_hHInstance HINSTANCE ?
g_szAppName db "系統任務欄高度", 0
g_szFmtPerD db "系統任務欄高度為:%d", 0
g_szBuf200 db 200 dup(0)
g_szFailtGetHeight db "未能取得!", 0
.code
start:
invoke GetModuleHandle, NULL
mov g_hHInstance, eax
invoke GetTaskBarHeight
inc eax
.if ZERO?
push MB_ICONERROR
push offset g_szAppName
push offset g_szFailtGetHeight
.else
dec eax
invoke wsprintf, addr g_szBuf200, addr g_szFmtPerD, eax
push MB_ICONINFORMATION
push offset g_szAppName
push offset g_szBuf200
.endif
push NULL
call MessageBox
invoke ExitProcess, eax
;///////////////////////////////
;Fun: 計算系統任務欄高度
; In: (none)
;Out: 若失敗 eax=-1, 否則 eax=高度值
; //////////////////////////////
GetTaskBarHeight proc
local stDeskRect: RECT
;--- 取桌面工作區大小
invoke SystemParametersInfo, SPI_GETWORKAREA, NULL, addr stDeskRect, NULL
test eax, eax
.if !ZERO?
; 取得了嗎?
;--- 如果桌面工作區左上角 y 座標值不為零,
; 說明任務欄在螢幕上方
.IF stDeskRect.top != 0
mov eax, stDeskRect.top ; 工作區左上角 y 座標值即任務欄高度
.ELSE
;--- 取螢幕高度
invoke GetSystemMetrics, SM_CYSCREEN
test eax, eax
jz @GetTaskBarHeightFailRet ; 未能取得
.if eax != stDeskRect.bottom
;--- 如果螢幕高度與桌面工作區右下角 y 座標值相同,
; 那麼任務欄在螢幕兩側,螢幕高度即任務欄高度
; 否則任務欄在螢幕下方,螢幕高度與桌面工作區右下角 y 座標值之差即任務欄高度
sub eax, stDeskRect.bottom
.endif
.ENDIF
.else
@GetTaskBarHeightFailRet:
mov eax, -1
.endif
ret
GetTaskBarHeight endp
end start
此方法不依賴註冊表或非文檔化介面,純粹使用標準 Windows API,兼容性極佳,適用於 Windows 9x 至最新版本。掌握此技巧,能讓您的桌面小工具更專業、更貼合使用者體驗。