
; This is a Win32 demo which uses a modal dialog to test data entry of 
; integer and real real numbers into a program

; Ron Thomas 13/9/99 

.386
.model flat, stdcall

include windows.inc
include user32.inc
include kernel32.inc
include gdi32.inc
include comctl32.inc

includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
includelib masm32.lib
includelib comctl32.lib	
includelib fplib.lib

EXTERNDEF PASCAL atof:proc			; Float Point procs
EXTERNDEF PASCAL ftoa:proc			;
EXTERNDEF PASCAL falog:proc			;

WinMain	  PROTO :DWORD, :DWORD, :DWORD, :SDWORD
 
.data

range		equ spinmin SHL 16 or spinmax	; Spin range; high word is min & low word is max 
		
ClassName	db "SimpleWinClass",0
AppName		db "Data Menu",0
MenuName	db "DataMenu",0
RealDlgName	db "RealDlg",0		; Name of Dialog Real entry box "	"	"
IntDlgName	db "IntDlg",0		; Name of Digits integer entry box 
AboutDlgName	db "About",0		; Name of About dialog box	"	"	"
screentext	db "For a radius of ",0	 
screentext2	db "The circle's area is ",0
	
numberstring	db '57.32',25 DUP (' '),0	; Space for a 30 byte string 	
numberstring2	db 30 DUP (' ')		; FP ASCII output buffer, need not be zero terminated
					; as # of char is returned by atof 

default		dd	6			; Initialised value value for Spin control 
digits		dd	6		

StatusMsg	db 'A Status Message Box',0
Status		db 'Status',0
	
.data?

hInstance HINSTANCE	?
CommandLine LPSTR	?
hPen	dd		?

.const

spinmin		equ	2			; Set limits for the digits dialog
spinmax		equ	18			;

ID_OK		equ	1
ID_CANCEL	equ	2

IDC_REAL	equ	1000
IDC_SPIN1	equ	1001
IDC_INTEGER	equ	1002
IDC_EDIT	equ	3000
IDC_BUTTON	equ	3001
IDC_EXIT	equ	3002
	
ID_DATA_REAL	equ	40001
ID_HELP_ABOUT	equ	40002
ID_HELP_EXIT	equ	40003
ID_DATA_STATUS	equ	40004
ID_DATA_INT	equ	40005

;Macros
;------
RGB	MACRO   red, green, blue	;; Get composite number from red green and blue bytes 

	mov	al,blue			;; ,,,blue	
	shl	eax,8			;; ,,blue,

	add	al,green		;; ,,blue,green
	shl	eax,8			;; ,blue,green,
	add	al,red			;; ,blue,green,red
	and	eax,0FFFFFFh		;; Mask out top byte to complete COLORREF dword 

	ENDM

LOWORD	MACRO 	bigword	;; Retrieves the low word from double word argument

	mov	eax,bigword
	and	eax,0FFFFh	;; Set to low word 
	ENDM
;---------------------------------------------------------------------------
.code
start:
	invoke GetModuleHandle, NULL
	mov    hInstance,eax
	invoke GetCommandLine
        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
	invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
	LOCAL wc:WNDCLASSEX
	LOCAL msg:MSG
        LOCAL hwnd:HWND
	mov   wc.cbSize,SIZEOF WNDCLASSEX
	mov   wc.style, CS_HREDRAW or CS_VREDRAW
	mov   wc.lpfnWndProc, OFFSET WndProc
	mov   wc.cbClsExtra,NULL
	mov   wc.cbWndExtra,NULL
        push  hInstance
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_WINDOW+1
        mov   wc.lpszMenuName,OFFSET MenuName
	mov   wc.lpszClassName,OFFSET ClassName
        invoke LoadIcon,NULL,IDI_APPLICATION
	mov   wc.hIcon,eax
        mov   wc.hIconSm,0
        invoke LoadCursor,NULL,IDC_ARROW
	mov   wc.hCursor,eax
        invoke RegisterClassEx, addr wc
        INVOKE CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
        mov   hwnd,eax
        INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
        INVOKE UpdateWindow, hwnd
        .WHILE TRUE
                INVOKE GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                INVOKE TranslateMessage, ADDR msg
                INVOKE DispatchMessage, ADDR msg
        .ENDW
        mov     eax,msg.wParam
        ret
WinMain endp


RealDlgProc PROC hDlg:HWND, iMsg:DWORD, wParam:WPARAM, lParam:LPARAM

;	Controls the dialog to read in an integer number for the # of digits
;	--------------------------------------------------------------------
 
        mov  eax,iMsg
        .IF     eax==WM_INITDIALOG
 
        .ELSEIF eax==WM_COMMAND

	    LOWORD wParam
	    
                .IF eax==ID_OK

		    invoke GetDlgItemText, hDlg,IDC_REAL,ADDR numberstring,30
	            invoke EndDialog,hDlg,TRUE
                        
		.ELSEIF eax==IDCANCEL

		    invoke EndDialog, hDlg,FALSE

                .ENDIF
        .ELSE
                mov eax,FALSE
                ret
        .ENDIF

        mov  eax,TRUE
        ret
RealDlgProc endp


IntDlgProc PROC hDlg:HWND, iMsg:DWORD, wParam:WPARAM, lParam:LPARAM

;	Controls the dialog to read a real number into the program
;	----------------------------------------------------------

LOCAL icex:INITCOMMONCONTROLSEX 

	mov	icex.dwSize,sizeof icex

	mov	icex.dwICC,ICC_UPDOWN_CLASS

	invoke  InitCommonControlsEx, ADDR icex		; Initialise use of controls
 
        mov  eax,iMsg

        .IF     eax==WM_INITDIALOG

;	We now intialise the spin control for edit control (identified as an autobuddy)
 
	    invoke SendDlgItemMessage, hDlg, IDC_SPIN1, UDM_SETRANGE,0,range ; Set range 
 	    invoke SendDlgItemMessage, hDlg, IDC_SPIN1, UDM_SETPOS,0,default ; Set default value
	   
        .ELSEIF eax==WM_COMMAND

	    LOWORD wParam

            .IF eax==ID_OK

                invoke GetDlgItemInt, hDlg,IDC_INTEGER, NULL, 0 ; Get data value from edit box

	        mov	default,eax	; Update the display value

		.IF	eax < spinmin

		  mov   eax,spinmin	; If entered edit box value is < min, limit it to minimum 
 		  mov   digits,eax	; and we need to limit it to the min

	   	.ELSEIF eax > spinmax

		  mov	eax,spinmax	; Likewise limit edit box max value
		  mov   digits,eax

		.ELSE  
		  mov	digits,eax	; Store the required # digits
		.ENDIF

		invoke EndDialog, hDlg,TRUE
         
	    .ELSEIF eax==IDCANCEL

		invoke EndDialog, hDlg,FALSE

            .ENDIF

        .ELSE
                mov eax,FALSE
                ret
        .ENDIF

        mov  eax,TRUE
        ret
IntDlgProc endp

AboutDlg PROC hDlg:HWND, iMsg:DWORD, wParam:WPARAM, lParam:LPARAM

        mov  eax,iMsg

        .IF eax==WM_INITDIALOG

	  mov eax,TRUE
	  ret

        .ELSEIF eax==WM_COMMAND

            LOWORD  wParam

            .IF eax==ID_OK
                invoke EndDialog, hDlg,0	 
		mov eax,TRUE
		ret
	    .ENDIF
	    
        .ENDIF

        mov  eax,FALSE
        ret

AboutDlg endp

WndProc proc uses ebx esi edi, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

LOCAL ps:PAINTSTRUCT, hdc:HDC, hMenu:HMENU

	mov   eax,uMsg
	
        .IF eax==WM_COMMAND

	    LOWORD wParam
	    .IF     eax==ID_DATA_REAL	; Display the Real Number dialog box

	        invoke DialogBoxParam,hInstance, ADDR RealDlgName,hWnd,ADDR RealDlgProc,NULL 	
	        invoke InvalidateRect, hWnd,NULL,TRUE
		invoke UpdateWindow, hWnd

  	    .ELSEIF eax==ID_DATA_INT		; Display the "Set Digits" dialog box

		invoke DialogBoxParam,hInstance, ADDR IntDlgName,hWnd,ADDR IntDlgProc,NULL 	
		invoke InvalidateRect, hWnd,NULL,TRUE
		invoke UpdateWindow, hWnd

	    .ELSEIF eax==ID_DATA_STATUS		; Display the Status message box

	        invoke MessageBox,hWnd,ADDR StatusMsg,ADDR Status,MB_ICONEXCLAMATION or MB_OK

            .ELSEIF eax==ID_HELP_ABOUT
                invoke DialogBoxParam,hInstance, ADDR AboutDlgName,hWnd,ADDR  AboutDlg,NULL

 	    .ELSEIF eax==ID_HELP_EXIT
	        invoke SendMessage,hWnd,WM_CLOSE,0,0
            .ENDIF
	
	.ELSEIF eax==WM_PAINT

		invoke BeginPaint,hWnd,ADDR ps
		mov    hdc,eax	

		RGB    0,0,255			; Create blue pen 	
		invoke CreatePen,PS_SOLID,8,eax ; Solid and 8 pixels wide
		mov    hPen,eax
		invoke SelectObject,hdc,hPen

		finit				; use default initialisation

		mov	esi,offset numberstring	; Point at ASCII string

		call	atof 			; Convert ASCII string to FP number
 
		fld	st			; Take 2nd copy of radius
		fmul				; Calculate the circle area
		fldpi
		fmul				; pi*r*r

		invoke Ellipse,hdc,10,10,400,400; draw a circle with broad pen
		
		mov	esi,offset numberstring2; Point at ASCII output buffer

		mov	eax,digits			; Request 6 digits after the decimal
	
		call	ftoa 			; Convert float into string
						; return FP string length in eax.
		push	eax			; Save it

		invoke lstrlen, ADDR screentext			; Get string length in eax
		invoke TextOut,hdc,100,190,ADDR screentext,eax	; Print string within circle

		invoke lstrlen, ADDR numberstring		
		invoke TextOut,hdc,250,190,ADDR numberstring,eax; Original input number

		invoke lstrlen, ADDR screentext2			
		invoke TextOut,hdc,100,220,ADDR screentext2,eax	; Print string within circle

		pop	eax			; Recover the length of the FP number 		
		invoke TextOut,hdc,250,220,ADDR numberstring2,eax; Print out the result
		
		invoke  ValidateRect,hWnd,NULL
		invoke  EndPaint,hWnd,ADDR ps
			  	
	.ELSEIF eax==WM_DESTROY

		invoke DeleteObject,hPen
		invoke PostQuitMessage,NULL
        .ELSE
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam
                ret
	.ENDIF

        xor    eax,eax
	ret
WndProc endp

        end start
