继续写定时强制休息程序。
定时/倒计时功能使用了定时器。当强制休息时间还剩30秒时,我们就在屏幕右下角显示倒计时窗口。
要在屏幕右下角显示倒计时窗口,在计算窗口位置时,我们可以不用考虑系统任务栏的高度等问题,而直接在桌面工作区中进行定位。
实践感觉,自下向上显示倒计时窗口要比渐显效果更能吸引电脑用户的注意力。另外,加上一些音乐、声音提示效果会更好。这也算是对《MASM32编程实现窗口渐入渐出效果》(http://blog.youkuaiyun.com/Purpleendurer/archive/2008/09/18/2949159.aspx)一文的补充,因为该文中的使用的是预先定义好的对话框资源,本文则是在程序运行时才创建窗口。
在窗口中使用标签或文本框来显示倒计时信息,实现起来会比较简单,但我没有这样做,而是使用了TextOut()来输出,因为这样一来,我们可以使用CreateFont()函数来创建所需要的大字体,用SetTextColor()设置字体颜色,用SetBkColor()设置背景颜色,从而使信息更醒目,显示效果更好。
当然,为了方便起见,在下面的演示程序中,我使用了系统默认字体,没有加入美化的代码。
(源程序和可执行文件下载地址:http://download.youkuaiyun.com/source/643871)
;Function:在屏幕右下角自下向上显示倒计时窗口
;Author:PurpleEndurer
;DevEnv:WinXPSP2+MASM32v7
;log
;----------------------------------------------------
;2008-09-23Created!
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.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
include/masm32/ include/gdi32.inc
includelib/masm32/ lib/gdi32.lib
WinMain proto: DWORD,: DWORD,: DWORD,: DWORD
;.const
ID_TIMER equ1
c_TimeWinWidth equ240 ;倒计时窗口宽度
c_TimeWinHeight equ60 ;倒计时窗口高度
.data
g_szTimeWinClsName db "TimeWinCls",0
g_szAppName db "强制休息!",0
g_dwRemainTime dd34
g_szRemainTimelabel dword
g_bD10 db?
g_bD1 db?
g_szRest db "秒后强制休息!" ;,0
c_RemainTimeLen equ$-g_szRemainTime
.data?
g_hHInstanceHINSTANCE?
g_stPtStPAINTSTRUCT<?>
g_hDcHDC?
g_hWndMainHWND?
g_dwTimeTextTop dword?
g_dwTimeTextLeft dword?
.code
start:
invokeGetModuleHandle,NULL
movg_hHInstance, eax
invokeWinMain,g_hHInstance,NULL,NULL,SW_SHOWDEFAULT
invokeExitProcess, eax
WinMain prochInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow: DWORD
LOCALwc:WNDCLASSEX
LOCALmsg:MSG
LOCALhwnd:HWND
movwc.cbSize,SIZEOFWNDCLASSEX
movwc.style,CS_HREDRAW orCS_VREDRAW
movwc.lpfnWndProc, OFFSETWndProc
movwc.cbClsExtra,NULL
movwc.cbWndExtra,NULL
pushg_hHInstance
popwc.hInstance
movwc.hbrBackground,25 ;淡黄色窗口
movwc.lpszMenuName,NULL
movwc.lpszClassName, OFFSETg_szTimeWinClsName
invokeLoadIcon,NULL,IDI_APPLICATION
movwc.hIcon, eax
movwc.hIconSm, eax
invokeLoadCursor,NULL,IDC_ARROW
movwc.hCursor, eax
invokeRegisterClassEx, addrwc ;WS_EX_TOPMOST
;---创建窗口
invokeCreateWindowEx,NULL, ADDRg_szTimeWinClsName, ADDRg_szAppName/
,WS_POPUP+WS_VISIBLE+WS_BORDER,CW_USEDEFAULT,CW_USEDEFAULT/
,0,0,NULL,NULL/
,hInst,NULL
movhwnd, eax
invokeShowWindow,hwnd,SW_HIDE ;SW_SHOWNORMAL
;invokeUpdateWindow,hwnd
.WHILE TRUE
invokeGetMessage, ADDRmsg,NULL,0,0
.BREAK .IF(! eax)
invokeTranslateMessage, ADDRmsg
invokeDispatchMessage, ADDRmsg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
;///////////////////////////////
;功能:计算显示倒计时信息输出位置
;输入:无
;输出:无
;//////////////////////////////
GetTimeTextPos proc
localstTM:TEXTMETRIC
invokeGetDC,g_hWndMain
;---取窗口默认字体信息
mov ebx, eax
invokeGetTextMetrics, ebx, addrstTM
;---计算信息输出位置的y坐标
mov eax,stTM.tmHeight
add eax,c_TimeWinHeight
shr eax,2 ;/4
movg_dwTimeTextTop, eax
;---计算信息输出位置的x坐标
mov eax,stTM.tmAveCharWidth ;tmMaxCharWidth
mov bl,c_RemainTimeLen/2
mul bl
mov ebx,c_TimeWinWidth/2
sub ebx, eax
movg_dwTimeTextLeft, ebx ;eax
ret
GetTimeTextPos endp
;///////////////////////////////
;功能:将倒计时窗口移至屏幕右下角
;输入:无
;输出:无
;//////////////////////////////
SetWinToScrRightDown proc
localstDeskRect:RECT
;---取桌面工作区高度
invokeSystemParametersInfo,SPI_GETWORKAREA,NULL, addrstDeskRect,NULL
;---倒计时窗口左上角x坐标
mov eax,stDeskRect.right
sub eax,c_TimeWinWidth
;---倒计时窗口左上角y坐标
mov ebx,stDeskRect.bottom
sub ebx,c_TimeWinHeight
;---移动窗口
invokeSetWindowPos,g_hWndMain,HWND_TOPMOST, eax, ebx/
,c_TimeWinWidth,c_TimeWinHeight,SWP_NOREDRAW ;SWP_SHOWWINDOW
ret
SetWinToScrRightDown endp
WndProc prochWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IFuMsg==WM_DESTROY
invokePostQuitMessage,NULL
.ELSEIFuMsg==WM_CREATE
mov eax,hWnd
movg_hWndMain, eax
invokeSetTimer,g_hWndMain,ID_TIMER,1000,NULL
invokeSetWinToScrRightDown ;将倒计时窗口移至屏幕右下角
invokeGetTimeTextPos ;计算显示倒计时信息输出位置
.ELSEIFuMsg==WM_TIMER
decg_dwRemainTime
.ifg_dwRemainTime==30
;--- 还剩30秒时自下向上显示窗口
invokeAnimateWindow,g_hWndMain,500h,AW_ACTIVATE+AW_VER_NEGATIVE ;AW_BLEND
.endif
.ifg_dwRemainTime>0
;---秒数数字转字符
mov eax,g_dwRemainTime
mov dl,10
div dl
add ax,'00'
mov word ptrg_bD10, ax
;---要求重绘窗口
invokeInvalidateRect,g_hWndMain,NULL, TRUE
jmp@WndProcZeroRet
.else
invokeKillTimer,g_hWndMain,ID_TIMER
.endif
.ELSEIFuMsg==WM_PAINT
invokeBeginPaint,g_hWndMain, ADDRg_stPtSt
movg_hDc, eax ;Gethandletodevicecontext
;---输出倒计时信息
invokeTextOut,g_hDc,g_dwTimeTextLeft,g_dwTimeTextTop, ADDRg_szRemainTime,c_RemainTimeLen
invokeEndPaint,hWnd, ADDRg_stPtSt
.ELSE
@@:
invokeDefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
@WndProcZeroRet:
xor eax, eax
ret
WndProc endp
endstart