📄 winclock.asm
字号:
;----------------------------------------------------------------------------;
; winclock.ASM ;
;----------------------------------------------------------------------------;
; ;
; Sample MASM 6.1 program using the Windows API Interface. It heavily relies ;
; on the MASM 6.x high level constructs like INVOKE and .IF/.ELSE/.ENDIF. ;
; The program, although simple enough, actually does quite a bit. Double ;
; clicking on the window will bring up a popup menu with other options, ;
; including setting an alarm. ;
; ;
; Adding to this code should be simple enough. New features could include ;
; making sure that fonts are displayed with the appropiate aspect ratio. ;
; ;
; Note that this program doesn't attempt to teach how to program in Windows. ;
; For that you should consult the Windows Software Developers Kit or other ;
; reference books. ;
; ;
;----------------------------------------------------------------------------;
.model small, pascal, nearstack
.286
?WINPROLOGUE = 1
NOKERNEL = 1
NOSOUND = 1
NOCOMM = 1
NODRIVERS = 1
include win.inc ; Converted from WINDOWS.H
;----------------------------------------------------------------------------;
; Prototypes & External Definitions ;
;----------------------------------------------------------------------------;
WinMain PROTO PASCAL, hInstance:HANDLE, hPrevInstance:HANDLE,
lpszCmdLine:LPSTR, nCmdShow:SWORD
WndProc PROTO FAR PASCAL, :HWND, :WORD, :SWORD, :SDWORD
Initialize PROTO, :PINT, :PINT, :PINT, :PINT
Resize PROTO, :HWND
SetupTimer PROTO, :HWND, :WORD
extern __astart:proc ; When Windows load an app, it expects astart
; to have the necessary start-up code. We get
; astart from APPENTRY.ASM
;----------------------------------------------------------------------------;
; Numeric Equates ;
;----------------------------------------------------------------------------;
INIT_FONT EQU 30t ; initial font height
MAX_HEIGHT EQU 100 ; Maximum Font Height
TOP_CORNER EQU 1 ; Set to 0 for Lower-Right Corner Clock
IDM_DATE EQU 1t ; definitions for Menu items
IDM_ALARM EQU 2t
IDM_SET EQU 3t
IDM_MENU EQU 4t
IDM_EXIT EQU 5t
IDM_ABOUT EQU 6t
IDM_MINIMIZE EQU 7t
IDM_ONTOP EQU 8t
AMPM EQU 3t ; length of am/pm strings
SCROLLCHILD EQU 30t ; identifies scroll: any number will do
MAXTIME EQU 1439t ; max # of minutes
TIMER_SECS EQU 1000t ; timer interval: 1000 mill = 1 second
TIMER_MINS EQU 60000t ; interval for 1 minute: 1000 * 60
ICON_LEN EQU 7t ; # of chars to display icon time
;----------------------------------------------------------------------------;
; Data Segments ;
;----------------------------------------------------------------------------;
.const
szAppName SBYTE "WINClock",0
DateFmt SBYTE " %s %2d, %04d ",13,10,0
TimeFmt SBYTE " %d:%02d:%02d %s ",0
IconFmt SBYTE " %d:%02d ",0
AlarmFmt SBYTE " %d:%02d %s ",0
szAMPM SBYTE "am",0,"pm",0
szTooManyTimers SBYTE "Too many clocks or timers!",0
szAlarmMsg SBYTE "Remember your Appointment!",0
szMonths SBYTE "Jan",0,"Feb",0,"Mar",0,"Apr",0,"May",0,"Jun",0,
"Jul",0,"Aug",0,"Sep",0,"Oct",0,"Nov",0,"Dec",0
szDateCmd SBYTE "Enable &Date", 0
szSetCmd SBYTE "S&et Alarm",0
szAlarmCmd SBYTE "Enable &Alarm", 0
szOnTopCmd SBYTE "Always on &Top",0
szMinimizeCmd SBYTE "&Minimize", 0
szExitCmd SBYTE "E&xit", 0
szAboutCmd SBYTE "About &Clock...", 0
szAboutText SBYTE "Assembler Program Using the Windows API", 0
szDisplay SBYTE "DISPLAY", 0 ; to get a handle to entire display
szScrollBar SBYTE "scrollbar", 0 ; to create scrollbar 'class'
.data
EnableDate BYTE MF_CHECKED ; Date initially enabled
EnableAlarm BYTE MF_UNCHECKED ; Alarm initially disabled
AlwaysOnTop BYTE MF_CHECKED ; Window will be on topmost
Iconized BYTE FALSE ; Clock initially Normal Size
TestAlarm BYTE FALSE ; so that we know to test for the alarm
SetAlarm BYTE FALSE ; signalling while we set the alarm
AlarmTime WORD (MAXTIME/2)+1 ; initial alarm time: 12:00 pm
.data?
cBuffer SBYTE 40 dup (?) ; buffer to receive text for drawing
hMenu HMENU ? ; handle to Popup Menu
logfont LOGFONT { } ; logical font structure
hWndScrol HWND ? ; handle to the scroll window
TextRect RECT { } ; rectangle to draw text in
;----------------------------------------------------------------------------;
; Code Segment ;
;----------------------------------------------------------------------------;
.code
;----------------------------------------------------------------------------;
; WinMain ;
;----------------------------------------------------------------------------;
; ;
; Main routine called by Windows in program start. If no previous instances, ;
; sets up a window class and registers it. Initializes the program with ;
; Initialize, creates a top window with the coordinates from Initialize, sets;
; up a child scroll bar control, and sets up the message loop. ;
; ;
;----------------------------------------------------------------------------;
WinMain PROC, hInstance:HANDLE, hPrevInstance:HANDLE,
lpszCmdLine:LPSTR, nCmdShow:SWORD
LOCAL msg:MSG, wndclass:WNDCLASS, xStart:SWORD,
yStart:SWORD, xClient:SWORD, yClient:SWORD
; Local variables: msg: message to be used in the message loop
; wndclass: temp. to store window class
; x,y Start-Client: Size of Initial Window
;
;--- Check for previous instances
;
.IF (hPrevInstance == 0)
lea di, wndclass ; because we use a NEARSTACK,
ASSUME di:PTR WNDCLASS ; ss=ds
mov ax, CS_HREDRAW OR CS_VREDRAW OR CS_DBLCLKS
mov [di].style, ax
mov WORD PTR [di].lpfnWndProc, LROFFSET WndProc
mov WORD PTR [di].lpfnWndProc+2, SEG WndProc
xor ax,ax
mov [di].cbClsExtra, ax
mov [di].cbWndExtra, ax
mov [di].hIcon, ax ; null icon: we will draw it
mov ax, hInstance
mov [di].hInstance, ax
INVOKE LoadCursor, NULL, IDC_ARROW
mov [di].hCursor, ax
INVOKE GetStockObject, WHITE_BRUSH
mov [di].hbrBackground, ax
xor ax, ax
mov WORD PTR [di].lpszMenuName, ax
mov WORD PTR [di].lpszMenuName+2, ax
mov WORD PTR [di].lpszClassName, OFFSET szAppName
mov WORD PTR [di].lpszClassName+2, ds
INVOKE RegisterClass, di
.IF (ax == 0)
mov ax, FALSE
jmp doRet
.ENDIF
ASSUME di:NOTHING
.ENDIF ;--- End of IF (hPrevInstance == 0)
;
;---- Initialize
;
INVOKE Initialize, ADDR xStart, ADDR yStart,
ADDR xClient, ADDR yClient
;
;---- Create Top Window
;
INVOKE CreateWindowEx, WS_EX_TOPMOST, ADDR szAppName,
ADDR szAppName, WS_BORDER OR WS_POPUP OR WS_THICKFRAME,
xStart, yStart, xClient, yClient, NULL, NULL,
hInstance, NULL
mov si, ax ; keep hWnd in SI, since SI doesn't
; change after function calls
INVOKE ShowWindow, si, SW_SHOWNOACTIVATE
INVOKE UpdateWindow, si
;
;----Create Scroll Child Window
;
INVOKE CreateWindow, ADDR szScrollBar, NULL,
WS_CHILD OR WS_VISIBLE OR WS_TABSTOP OR SBS_HORZ,
0, 0, 0, 0, si, SCROLLCHILD, hInstance, NULL
mov hWndScrol, ax
INVOKE SetScrollRange, ax, SB_CTL, 0, MAXTIME, FALSE
INVOKE SetScrollPos, hWndScrol, SB_CTL, AlarmTime, FALSE
INVOKE ShowScrollBar, hWndScrol, SB_CTL, TRUE
INVOKE ShowWindow, hWndScrol, SW_SHOWNOACTIVATE
INVOKE UpdateWindow, hWndScrol
;
;---- Message Loop
;
.WHILE TRUE
INVOKE GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (ax == 0)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
;
;---- Return to Windows
;
mov ax, msg.wParam
doRet:
ret
WinMain ENDP
;----------------------------------------------------------------------------;
; Initialize ;
;----------------------------------------------------------------------------;
; ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -