GetTextMetrics, TextOut and SetTextAlign all use "windows.h". If I include
"windows.h" in the MASM32 program and assemble it, errors occur.
If I take "windows.h" out I get undefined errors on the three items above.
I know "windows.h" was written for C++ but how can I get a "windows.h"
that will assemble in MASM32? And is that what I want to do?????
Any help would be appreciated.
J. P. Shankle
jpsd...@digital.net
Jack/Donna Shankle <jpsd...@digital.net> wrote in message
news:s2e21k...@corp.supernews.com...
;----------------------------------------------------------------------------;
;
SYSDATA.ASM ;
;----------------------------------------------------------------------------;
; Sample program that accesses the SYSINFO.DLL
functions. ;
;----------------------------------------------------------------------------;
.model small, pascal, nearstack
.286
?WINPROLOGUE = 1
include win.inc ; Converted from WINDOWS.H
include dll.inc ; SYSINFO.DLL definitions
include sysdata.inc ; equates for dialog controls
;----------------------------------------------------------------------------;
; Prototypes & External
Definitions ;
;----------------------------------------------------------------------------;
NPBYTE TYPEDEF NEAR PTR BYTE
WinMain PROTO PASCAL, hInstance:HANDLE, hPrevInstance:HANDLE,
lpszCmdLine:LPSTR, nCmdShow:SWORD
WndProc PROTO FAR PASCAL, :HWND, :WORD, :SWORD, :SDWORD
SetDlg PROTO, :HWND
SetKeyb PROTO, :HWND
SetTime PROTO, :HWND
int2hex PROTO, :WORD, :NPBYTE
SetItem PROTO, :HWND, :WORD, :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 ;
;----------------------------------------------------------------------------;
TIMER_SECS EQU 1000t ; timer interval: 1000 mill = 1
second
fNUMLOCK EQU 020h ; Flags within the Keyboard
Status word
fCAPLOCK EQU 040h ; that indicate different key
modes
fSHIFTS EQU 003h
fCONTROL EQU 004h
;----------------------------------------------------------------------------;
; Data
Segments ;
;----------------------------------------------------------------------------;
.const
szAppName SBYTE "SysData",0
szSysIcon SBYTE "SysIcon",0
szTooManyTimers SBYTE "Too many clocks or timers!",0
szError SBYTE "Error",0
szCoNotInst SBYTE "Not Found",0
szCoInst SBYTE "Found",0
szOff SBYTE "Off",0
szOn SBYTE "On",0
hex BYTE '0123456789ABCDEF' ; Table of hexadecimal
digits
; for int2hex function
ProcTable NPBYTE sz8086
NPBYTE sz80186
NPBYTE sz80286
NPBYTE sz80386
NPBYTE sz80486
sz8086 SBYTE "8086",0
sz80186 SBYTE "80186",0
sz80286 SBYTE "80286",0
sz80386 SBYTE "80386",0
sz80486 SBYTE "80486",0
.data
HexValue BYTE "xxxxh",0
Initialized BYTE 0
;----------------------------------------------------------------------------;
; Code
Segment ;
;----------------------------------------------------------------------------;
.code
;----------------------------------------------------------------------------;
;
WinMain ;
;----------------------------------------------------------------------------;
;
;
; Main routine called by Windows in program start. If no previous
instances, ;
; sets up a window class and registers it, then sets up the message
loop. ;
;
;
;----------------------------------------------------------------------------;
WinMain PROC, hInstance:HANDLE, hPrevInstance:HANDLE,
lpszCmdLine:LPSTR, nCmdShow:SWORD
LOCAL msg:MSG, wndclass:WNDCLASS
; 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 WORD PTR [di].lpfnWndProc, LROFFSET WndProc
mov WORD PTR [di].lpfnWndProc+2, SEG WndProc
mov [di].cbWndExtra, DLGWINDOWEXTRA
xor ax,ax
mov [di].style,ax
mov [di].cbClsExtra, ax
INVOKE LoadIcon, hInstance, ADDR szSysIcon
mov [di].hIcon, ax
mov ax, hInstance
mov [di].hInstance, ax
INVOKE LoadCursor, NULL, IDC_ARROW
mov [di].hCursor, ax
mov [di].hbrBackground, COLOR_WINDOW +1
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)
INVOKE CreateDialog, hInstance, ADDR szAppName, 0, NULL
mov si, ax
INVOKE ShowWindow, si, nCmdShow
;---- Create Timer for Window
INVOKE SetTimer, si, 1, TIMER_SECS, NULL
.IF (ax == 0)
INVOKE MessageBox, si,ADDR szTooManyTimers,
ADDR szAppName,
MB_ICONEXCLAMATION OR MB_OK
mov ax, FALSE
INVOKE PostQuitMessage, 0 ; Quit.
.ENDIF
;---- Message Loop
.WHILE TRUE
INVOKE GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (ax == 0)
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessage, ADDR msg
.ENDW
mov ax, msg.wParam
doRet:
ret
WinMain ENDP
;----------------------------------------------------------------------------;
;
SetTime ;
;
;
; Reads the System Time with GetSysTime, sets up the Dialog Item
TIME_TEXT ;
; with the resulting string. Then does the same for
DATE_TEXT. ;
;----------------------------------------------------------------------------;
SetTime PROC, hDlg:HWND
INVOKE GetSysTime
INVOKE SetDlgItemText, hDlg, TIME_TEXT, dx::ax
INVOKE GetSysDate
INVOKE SetDlgItemText, hDlg, DATE_TEXT, dx::ax
ret
SetTime ENDP
;----------------------------------------------------------------------------;
;
SetKeyb ;
;
;
; Assumes DI has the keyboard status. Gets the control's text into
buffer. ;
; If the control's status has changed (if buffer+1 is not what it would
be ;
; set to) then set it to On or Off, otherwise
return ;
;----------------------------------------------------------------------------;
SetItem PROC, hDlg:HWND, item:WORD, flag:WORD
LOCAL buffer[3]:BYTE
INVOKE GetDlgItemText, hDlg, item, ADDR buffer, 3
mov bx, di
and bx, flag
.IF bx
.IF (byte ptr buffer+1 != 'n') ; 'n' means we have 'On'
mov bx, OFFSET szOn
.ELSE
jmp doRet
.ENDIF
.ELSE
.IF (byte ptr buffer+1 != 'f') ; 'f' means we have 'Off'
mov bx, OFFSET szOff
.ELSE
jmp doRet
.ENDIF
.ENDIF
INVOKE SetDlgItemText, hDlg, item, ds::bx
doRet:
ret
SetItem ENDP
;----------------------------------------------------------------------------;
;
SetKeyb ;
;
;
; Reads the keyboard status with GetSysInfo, then uses SetItem to set
the ;
; appropiate controls in the dialog
box. ;
;----------------------------------------------------------------------------;
SetKeyb PROC, hDlg:HWND
INVOKE GetSysInfo
mov es, dx
mov si, ax
ASSUME SI:PTR SYSINFO
mov di, es:[si].wKbStatus
INVOKE SetItem, hDlg, NUMLOCK,fNUMLOCK
INVOKE SetItem, hDlg, CAPLOCK,fCAPLOCK
INVOKE SetItem, hDlg, CONTROL,fCONTROL
INVOKE SetItem, hDlg, SHIFTS, fSHIFTS
ASSUME SI:NOTHING
ret
SetKeyb ENDP
;----------------------------------------------------------------------------;
;
SetDlg ;
;
;
; Reads the System Time with GetSysTime, sets up the Dialog Item
TIME_TEXT ;
; with the resulting string. Then does the same for DATE_TEXT. Then gets
the ;
; other system information with GetSysInfo and sets the appropiate
Dialog ;
; Items. Note that KEYBSTAT and VIDEOMODE take the hex of the value
returned.;
; Since ES is not guaranteed to be preserved, have to restore it after
every ;
; SetDlgItemInt or Text. A table is used to look up the processor
type. ;
;----------------------------------------------------------------------------;
SetDlg PROC, hDlg:HWND
INVOKE SetTime, hDlg
INVOKE SetKeyb, hDlg
INVOKE GetSysInfo
mov di, dx
mov si, ax
ASSUME SI:PTR SYSINFO
lea ax, [si].szWinVer
INVOKE SetDlgItemText, hDlg, WINVERSION, di::ax
lea ax, [si].szDOSVer
INVOKE SetDlgItemText, hDlg, DOSVERSION, di::ax
lea ax, [si].szROM
INVOKE SetDlgItemText, hDlg, ROMBIOS, di::ax
mov es, di
mov al, es:[si].cFloppy
INVOKE SetDlgItemInt, hDlg, FLOPPIES, al, FALSE
mov es, di
mov bl, es:[si].cVidMode
INVOKE int2hex, bl, ADDR HexValue
INVOKE SetDlgItemText, hDlg, VIDEOMODE, ADDR HexValue
mov es, di
.IF es:[si].bCoproc
mov ax, OFFSET szCoInst
.ELSE
mov ax, OFFSET szCoNotInst
.ENDIF
INVOKE SetDlgItemText, hDlg, COPROC, ds::ax
mov es, di
mov bl, es:[si].cProcType
.IF (bl < 5)
xor bh, bh
shl bx, 1
mov ax, ProcTable[bx]
.ELSE
mov ax, OFFSET szError
.ENDIF
INVOKE SetDlgItemText, hDlg, PROCTYPE, ds::ax
ASSUME SI:NOTHING
ret
SetDlg ENDP
;----------------------------------------------------------------------------;
; int2hex
; Converts a WORD into its hexadecimal representation.
; Based on Chapter 4 of the MASM Programmer's guide
;----------------------------------------------------------------------------;
int2hex PROC NEAR USES ax bx si, number:WORD, string:NPBYTE
mov bx, OFFSET hex ; load table address
mov si, string
mov ax, number ; load value to convert
shr ax, 12 ; shift right to get into table index
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si], al ; store as last byte
mov ax, number ; load value to convert
shr ax, 8 ; shift right to get into table index
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si+1], al ; store as third to last byte
mov ax, number ; load value to convert
shr ax, 4 ; shift right to get into table index
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si+2], al ; store as second to last byte
mov ax, number ; load value to convert
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si+3], al ; store as last byte in string
ret
int2hex ENDP
;----------------------------------------------------------------------------;
;
WndProc ;
;
;
; Because this is a Dialog Box/Window, we cannot intercept the
WM_CREATE ;
; message to set up the initial values of the Dialog Box. We have to
wait for;
; the timer or the keyboard status to change to set values. Initialized
is a ;
; flag to determine if the other values need to be
set. ;
; If we get a timer message, set the time and
date. ;
; If we get a KEYDOWN or KEYUP message, set the Keyboard
Status ;
; If we get a WININICHANGE, SETFOCUS, or SYSKEYUP, some data could
change. ;
; Reset the dialog
items ;
; A Close Window will get us
out. ;
;----------------------------------------------------------------------------;
WndProc PROC FAR PASCAL, hWnd:HWND, iMessage:WORD, wParam:SWORD,
lParam:SDWORD
; Windows gives us: the handle of the Window, the Message ID,
; and two parameters for the message
.IF (iMessage == WM_TIMER)
.IF Initialized
INVOKE SetTime, hWnd
.ELSE
mov Initialized, TRUE
INVOKE SetDlg, hWnd
.ENDIF
.ELSEIF (iMessage == WM_KEYDOWN) || (iMessage == WM_KEYUP)
.IF Initialized
INVOKE SetKeyb, hWnd
.ELSE
mov Initialized, TRUE
INVOKE SetDlg, hWnd
.ENDIF
.ELSEIF (iMessage == WM_SETFOCUS) || (iMessage == WM_SYSKEYUP)\
|| (iMessage == WM_WININICHANGE)
INVOKE SetDlg, hWnd
jmp doDefault
.ELSEIF (iMessage==WM_DESTROY)
INVOKE KillTimer, hWnd, 1
INVOKE PostQuitMessage, 0
.ELSE
doDefault:
INVOKE DefWindowProc, hWnd, iMessage, wParam,lParam
jmp doRet
.ENDIF
mov ax, 0
cwd
doRet:
ret
WndProc ENDP
END __astart ; so that the code of the application will
; start with the Windows start-up code