📄 winclock.asm
字号:
; Initializes the logfont struct, sizes the Initial Window, Makes the Menu. ;
; ;
; For the size of the initial window: We get the DC for the entire display, ;
; and calculate the size of the font into tmetric. With that, we allow for ;
; the necessary distance from the top right corner so that there's enough ;
; space for the text. ;
; ;
;----------------------------------------------------------------------------;
Initialize PROC USES si di, pxStart:PINT, pyStart:PINT,
pxClient:PINT, pyClient:PINT
; px,py,Start,Client will hold the dimensions of the initial
; window to create
LOCAL hFont:HFONT, hDC:HDC, tmetric:TEXTMETRIC
; locals: a handle to a font, one to a device context,
; and a textmetric structure
;
;---- Initialize the logfont structure
;
mov bx, OFFSET logfont
ASSUME bx:PTR LOGFONT
xor ax, ax
mov [bx].lfHeight, INIT_FONT; Initial Font Height
mov [bx].lfWidth, ax ; width's set according to hght
mov [bx].lfEscapement, ax
mov [bx].lfOrientation, ax
mov [bx].lfWeight, FW_NORMAL
mov [bx].lfItalic, al
mov [bx].lfUnderline, al
mov [bx].lfStrikeOut, al
mov [bx].lfCharSet, ANSI_CHARSET
mov [bx].lfOutPrecision, al
mov [bx].lfClipPrecision, al
mov [bx].lfQuality, al
mov [bx].lfPitchAndFamily, DEFAULT_PITCH OR FF_SWISS
mov [bx].lfFaceName, NULL
ASSUME bx:NOTHING
;---- Get Initial Size for the Window Based on Font
xor dx, dx
INVOKE CreateIC, ADDR szDisplay, dx::dx, dx::dx, dx::dx
mov hDC, ax
INVOKE CreateFontIndirect, ADDR logfont
mov hFont, ax
INVOKE SelectObject, hDC, ax
mov hFont, ax
INVOKE GetTextMetrics, hDC, ADDR tmetric
INVOKE SelectObject, hDC, hFont
INVOKE DeleteObject, ax
INVOKE DeleteDC, hDC
INVOKE GetSystemMetrics, SM_CXDLGFRAME ; Set window width
shl ax, 1 ; frame*2
mov bx, tmetric.tmAveCharWidth ; width of font
mov cl, 4 ; to shift
shl bx, cl ; width*16
add ax, bx ; frame*2 + width*16
mov si, pxClient ; address to store in
mov [si], ax ; store
INVOKE GetSystemMetrics, SM_CXSCREEN ; screen x-length
mov si, pxClient ; window width
sub ax, [si] ; start=corner-winWdth
mov si, pxStart ; store result
mov [si], ax
INVOKE GetSystemMetrics, SM_CYDLGFRAME ; Set Height
shl ax, 1 ; frame*2
mov bx, tmetric.tmHeight ; height*2
shl bx, 1
add ax, bx ; add
mov si, pyClient ; store in pyClient
mov [si], ax
IF TOP_CORNER ; if Top Corner,
xor ax, ax ; yStart=0
ELSE ; else,
INVOKE GetSystemMetrics, SM_CYSCREEN
mov si, pyClient ; yStart = ScreenHgth
sub ax, [si] ; minus yHeight
ENDIF
mov si, pyStart ; set yStart
mov [si], ax
;
;---- Initialize the Menu
;
INVOKE CreatePopupMenu
mov hMenu, ax
; Date is Initially Enabled
INVOKE AppendMenu, hMenu, MF_STRING OR MF_CHECKED, IDM_DATE,
ADDR szDateCmd
INVOKE AppendMenu, hMenu, MF_STRING, IDM_ALARM,ADDR szAlarmCmd
INVOKE AppendMenu, hMenu, MF_STRING, IDM_SET, ADDR szSetCmd
INVOKE AppendMenu, hMenu, MF_SEPARATOR, 0, NULL
INVOKE AppendMenu, hMenu, MF_STRING OR MF_CHECKED, IDM_ONTOP,
ADDR szOnTopCmd
INVOKE AppendMenu, hMenu, MF_STRING, IDM_MINIMIZE,
ADDR szMinimizeCmd
INVOKE AppendMenu, hMenu, MF_STRING, IDM_EXIT, ADDR szExitCmd
INVOKE AppendMenu, hMenu, MF_SEPARATOR, 0, NULL
INVOKE AppendMenu, hMenu, MF_STRING, IDM_ABOUT,ADDR szAboutCmd
ret
Initialize ENDP
;----------------------------------------------------------------------------;
; SetupTimer ;
;----------------------------------------------------------------------------;
; ;
; Setup a timer with the specified interval. If we can't set up the timer, ;
; output a message box and exit the program. ;
;----------------------------------------------------------------------------;
SetupTimer PROC NEAR, hWnd:HWND, Interval:WORD
; hWnd is the Handle of the Window to associate the timer with
; Interval is the interval in milliseconds
INVOKE SetTimer, hWnd, 1, Interval, NULL
.IF (ax == 0)
INVOKE MessageBox, hWnd,ADDR szTooManyTimers,
ADDR szAppName,
MB_ICONEXCLAMATION OR MB_OK
mov ax, FALSE
INVOKE PostQuitMessage, 0 ; Quit.
.ENDIF
ret
SetupTimer ENDP
;----------------------------------------------------------------------------;
; AlarmSetup ;
;----------------------------------------------------------------------------;
; ;
; If we're going to set the alarm, kill the timer, show the scroll bar, and ;
; resize the fonts. Enable the Alarm after it has been re-set. ;
; ;
; If we just set up the alarm, get a new timer, ;
; check the menu to enable the alarm, hide the scrollbar, resize the fonts ;
; When creating the top window this is called to set up the initial timer. ;
; ;
;----------------------------------------------------------------------------;
AlarmSetup PROC, hWnd:HWND
; hWnd is the handle of the window that received WinPaint
.IF SetAlarm
INVOKE KillTimer, hWnd, 1
INVOKE Resize, hWnd
INVOKE ShowScrollBar, hWndScrol, SB_CTL, TRUE
INVOKE SetFocus, hWndScrol
INVOKE InvalidateRect, hWnd, NULL, TRUE
mov EnableAlarm, MF_CHECKED
mov TestAlarm, TRUE
.ELSE
INVOKE SetupTimer, hWnd, TIMER_SECS
INVOKE CheckMenuItem, hMenu, IDM_ALARM, EnableAlarm
INVOKE ShowScrollBar, hWndScrol, SB_CTL, FALSE
INVOKE Resize, hWnd
INVOKE InvalidateRect, hWnd, NULL, TRUE
.ENDIF
ret
AlarmSetup ENDP
;----------------------------------------------------------------------------;
; Resize ;
;----------------------------------------------------------------------------;
; ;
; Simple resizing, without taking into account aspect ratio. ;
; If we're setting the alarm, the scroll bar height will be (client hgt)/16, ;
; the length will be (client lenght)-(2*Scroll Bar Height), and the top will ;
; will start (in Client coordinates), at one SB Height right and 2 SBHeights ;
; up from the left bottom corner. Fonts width will be length/10, height will ;
; be (client height)-(3*Scroll bar height). The Scroll bar is also displayed.;
; ;
; If we're not setting the alarm, and we're not minimized, font width will be;
; length/TIME_LEN and height will be either client height or client height/2,;
; depending on the date being enabled or not. ;
; ;
; If font height is more than MAX_HEIGHT, then height is MAX_HEIGHT, and the ;
; TextRect.top is computed so that Drawing the text on the client area will ;
; be centered. ;
; ;
; If we're minimized, width=length/ICON_LEN, height is client height. ;
; ;
; The TextRect is used so that it's not recomputed everytime the Window is ;
; repainted. ;
; ;
;----------------------------------------------------------------------------;
Resize PROC, hWnd:HWND
; hWnd is the handle of the window that received WinPaint
LOCAL rect:RECT
; holds a rectangle structure
INVOKE SetFocus, hWnd ; take focus out of child window
INVOKE GetClientRect, hWnd, ADDR rect ; get new rect.size
;---- Find desired Text Height
.IF SetAlarm
;---- Calculate New TextRect allowing for Scroll Bar
mov bx, rect.bottom ; SXstart is length / 8
shr bx, 3
mov cx, rect.right ; SLength=CLenght-2*SHeight
sub cx, bx
sub cx, bx
mov dx, rect.bottom ; SYstart will be CHgt-2*SHgt
sub dx, bx
sub dx, bx
mov TextRect.bottom, dx ; bottom = CHgt - 3*SHgt
sub TextRect.bottom, bx
INVOKE MoveWindow, hWndScrol, bx, dx, cx, bx, FALSE
INVOKE SetScrollPos,hWndScrol,SB_CTL,AlarmTime,TRUE
mov ax,TextRect.bottom ; Try to use Full Height
; for font height
;---- Else (not setting the alarm)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -