EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

calcwing.htm
Data
Data
Procedures
MsgLoopMain
WndCreateMain
WndProcMain

This is a GUI module of EuroTool program EuroCalc for Windows.


         EUROASM CPU=X64,SIMD=Yes,Unicode=No
calcwing PROGRAM Format=COFF,Width=64
           %DROPMACRO *
           INCLUDEHEAD argument.htm
           INCLUDE1 winansi.htm,fastcall.htm,winabi.htm,winsgui.htm,winsdlg.htm
           INCLUDE1 cpuext.htm,memory64.htm,string64.htm,status32.htm
           LINK ../objlib/winapi.lib
↑ Data
                             ; Constants.
xBtn  EQU  4                 ; Left  position of buttons array.
yBtn  EQU 120                ; Upper position of buttons array.
wiBtn EQU  70                ; Width of one button.
heBtn EQU  30                ; Height of one button.
[.rodata]                    ; Constant data.
TitleWindow   DB "EuroCalc",0
[.bss]                       ; Variable data.
Msg           DS MSG
WndClassEx    DS WNDCLASSEX
PaintStruct   DS PAINTSTRUCT
hWindowMain   D QWORD
hWindowStatus D QWORD
hDC           D QWORD
hFont         D QWORD
hBrushGrayBg  D QWORD
hBrushWhiteBg D QWORD
InpBufferPtr  D QWORD        ; Pointer
LineSize      D DWORD        ; Max. number of characters in the input line and in the result line, depending on MainWidth.
AveCharWidth  D DWORD        ; Average character width in pixels.
[.text]
MsgLoopMain
Message handling procedure. Entry point of GUI.
Called by
MainCon.
Calls
WndCreateMain,
MsgLoopMain:: PROC
     CALL WndCreateMain
     WinABI ShowWindow,[hWindowMain],SW_SHOW
     WinABI UpdateWindow,[hWindowMain]
.MsgLoop:
     WinABI GetMessage, Msg,0,0,0
     TEST RAX
     JZ .MsgQuit:                                 ; ZF signalizes message WM_QUIT - request for termination.
     WinABI TranslateMessage, Msg                 ; Remap character keys from national keyboards.
     WinABI DispatchMessage,  Msg                 ; Let Windows call our WndProc.
     JMP .MsgLoop:                                ; Wait for another message.
.MsgQuit:
     TerminateProgram
   ENDP MsgLoopMain
WndCreateMain
Register window class and create windows for displaying the output listing.
WndCreateMain:: PROC     ; Register WndClassEx for the main window.
    MOVD [WndClassEx.cbSize],SIZE# WndClassEx
    MOVQ [WndClassEx.lpszClassName],TitleWindow
    MOVD [WndClassEx.style],CS_HREDRAW|CS_VREDRAW
    MOVQ [WndClassEx.lpfnWndProc],WndProcMain
    WinABI GetModuleHandle,0
    MOVQ [WndClassEx.hInstance],RAX
    WinABI LoadIcon,RAX,1             ; The 1st and only icon from [.rsrc] section.
    MOVQ [WndClassEx.hIcon],RAX
    WinABI LoadCursor,0,IDC_IBEAM
    MOVQ [WndClassEx.hCursor],RAX
    MOVQ [WndClassEx.hbrBackground],15+1 ; COLOR_BTNFACE+1
    WinABI RegisterClassExA, WndClassEx
    ; Create the main window.
    WinABI CreateWindowExA,0,       \
           TitleWindow,TitleWindow::,WS_OVERLAPPEDWINDOW, \
           CW_USEDEFAULT,CW_USEDEFAULT,6*(wiBtn+4)+20,7*(heBtn+4)+170,   \
           0, 0, [WndClassEx.hInstance], 0
    MOV [hWindowMain],RAX
    ;  Create other children windows of the main window.
    ; EuroCalc icon.
    WinABI CreateWindowExA,0,="STATIC",="#1",WS_CHILD+WS_VISIBLE+SS_ICON,\
           12,1,16,16,[hWindowMain],0,[WndClassEx.hInstance],0
    WinABI SendMessage,RAX,STM_SETICON,[WndClassEx.hIcon],0
   ; Title EuroCalc version.
    WinABI CreateWindowExA,0,="STATIC", Version::, WS_CHILD+WS_VISIBLE   +SS_SIMPLE, \
            50,10,280,20,[hWindowMain],0,[WndClassEx.hInstance],0
    ; Status window.
    WinABI CreateWindowExA,0,=B'STATIC',=B"", WS_CHILD+WS_VISIBLE+SS_CENTER, \
           4,92,6*(wiBtn+4)-2,24,[hWindowMain],0,[WndClassEx.hInstance],0
    MOV [hWindowStatus],RAX
    ; Set the unproportional font of digits.
    MOV ECX,8
    MOV [AveCharWidth],ECX
    WinABI CreateFont, 24, RCX, 0,0,FW_BOLD,0,0,0, ANSI_CHARSET,0,0,0,FIXED_PITCH|FF_MODERN,=B"Courier New"
    MOV [hFont],RAX
    WinABI SendMessage,[hWindowMain],WM_SETFONT,RAX,1
    ; Edit window width in pixels.
    MOV EAX,6*(wiBtn+4)-2
    XOR EDX,EDX
    MOV ECX,[AveCharWidth]
    DIV ECX
    MOV [LineSize],EAX
    MOV AL,' '
    LEA RDI,[InpBuffer::]
    MOV [InpBufferPtr],RDI
    MOV ECX,640
    REP STOSB
    LEA RDI,[OutBuffer::]
    MOV ECX,640
    REP STOSB
    WinABI CreateSolidBrush,0x00F0F0F0
    MOV [hBrushGrayBg],RAX
    WinABI CreateSolidBrush,0x00FFFFFF
    MOV [hBrushWhiteBg],RAX
    WinABI CreateCaret,[hWindowMain],0,10,3
    ; Array of 6 columns and 7 rows of buttons.
    LEA RDI,[TitleBtns::]
    MOV R14,0x6001            ; Here start WM_USER defined message numbers.
    MOV R13,yBtn
.20:MOV R12,xBtn
.30:CMP R13,yBtn+7*heBtn+7*4
    JAE .90:
    CMP R12,xBtn+ 6*wiBtn+6*4
    JAE .40:
    LEA RCX,[TitleBtnsEnd::]
    LEA RAX,[TitleBtns::]
    SUB RCX,RAX
    XOR EAX,EAX
    REPNE SCASB
WinABI CreateWindowExA,0,=B'BUTTON',RDI, \
          BS_PUSHBUTTON+WS_CHILD+WS_VISIBLE+WS_TABSTOP, \
          R12,R13,wiBtn,heBtn, \
          [hWindowMain],R14,[WndClassEx.hInstance],0
    INC R14
    ADD R12,wiBtn+4
    JMP .30:
.40:ADD R13,heBtn+4
    JMP .20:
.90:RET
   ENDP WndCreateMain
WndProcMain, hWnd, uMsg, wParam, lParam

This is a callback procedure which receives and handles messages for the MainWindow. Message parameters are by FastCall convention provided in registers RCX, RDX, R8, R9, we'll save them to shadow space with macro SaveToShadow . Thanks to this their contents will be available by formal names ( [%hWnd], [%uMsg], [%wParam], [%lParam]), too, in the entire WndProc body.

Messages obtained from Windows are dispatched by WndProcMain to their handlers.
Unhandled messages are passed to DefWindowProc.

Handler input
RCX=[%hWnd] is the main window handle (the same as static [hWindowMain]).
RDX=[%uMsg] is message identifier,
R8=[%wParam] is message w-parameter,
R9=[%lParam] is message l-parameter.
Handler output
RAX=0 if the message was completely processed by the handler. Otherwise the message is processed by WinAPI DefWindowProc and RAX outputs its return value.
Scratch registers RCX,RDX,R8..R11 may be destroyed in the handlers.
Callee-save registers RBX,RSI,RDI,R12..R15 must be restored, if used in the handlers. This provides macro Uses.
Invoked by
WinAPI DispatchMessage.
WndProcMain Procedure hWnd, uMsg, wParam, lParam ; These parameters are provided in RCX,RDX,R8,R9.
    Uses RBX,RBP,RSI,RDI
    SaveToShadow
    ; Fork message uMsg=RAX to its handler using macro Dispatch:
     Dispatch EDX , WM_CHAR, WM_PAINT, WM_CTLCOLORSTATIC, WM_KEYDOWN, WM_SIZE, WM_COMMAND, \
              WM_SETFOCUS, WM_KILLFOCUS, WM_LBUTTONUP, WM_DESTROY
.Def:WinABI DefWindowProc,[%hWnd],[%uMsg],[%wParam],[%lParam]  ; Pass ignored event to DefWindowProc with unchanged arguments.
     JMP .Ret:     ; Go to EndProcedure with result value RAX as returned from DefWindowProc.
     ; All message handlers terminate with a jump to the label .Def: or .Ret0:.
.WM_SIZE:
     MOVZX EDI,R9W                    ; Recalculate the new width of the window in pixels.
     SUB EDI,7
     MOV EAX,EDI
     XOR EDX,EDX
     DIVD [AveCharWidth]
     MOV [LineSize],EAX
     JMP .Ret0:
.WM_CTLCOLORSTATIC:
     CMP R9,[hWindowStatus]
     JNE .Def:
     WinABI SetBkMode, R8, TRANSPARENT
     WinABI SetTextColor, R8, 0x000000C0  ; Red ink.
     MOV RAX,[hBrushGrayBg]
     JMP .Ret:
.WM_SETFOCUS:
     WinABI ShowCaret,[hWindowMain]
     JMP .Ret0:
.WM_KILLFOCUS:
     WinABI HideCaret,[hWindowMain]
     JMP .Ret0:
.WM_LBUTTONUP:                         ; Mouse clicked.
     MOVZX EAX,R9W                     ; X-position in pixels.
     SHR R9,16                         ; Y-position in pixels.
     CMP R9W,28
     JB .Def:
     CMP R9W,50
     JA .10:
     ADD EAX,4                         ; Clicked at the input line. Move caret.
     MOV ECX,[AveCharWidth]
     XOR EDX,EDX
     DIV RCX
     LEA RSI,[InpBuffer::]
     ADD RAX,RSI
     MOV [InpBufferPtr],RAX
     JMP .10:
.WM_PAINT:                              ; Draw input and output line.
     LEA RSI,[PaintStruct]
     WinABI BeginPaint,[hWindowMain], RSI
     MOV [hDC],RAX
     WinABI SelectObject,[hDC],[hFont]
     WinABI SetTextColor, [hDC], 0x00000000   ; Black ink.
     LEA RSI,[InpBuffer::]
     MOV RDI,[InpBufferPtr]
     SUB RDI,RSI
     MOV EAX,[AveCharWidth]
     MUL RDI
     ADD RAX,4
     WinABI SetCaretPos,RAX,52
     MOV ECX,[LineSize]
     WinABI TextOut,[hDC],4,34,RSI,RCX
     WinABI SetTextColor, [hDC], 0x00008000   ; Green ink.
     LEA RSI,[OutBuffer::]
     MOV ECX,[LineSize]
     WinABI TextOut,[hDC],4,56,RSI,RCX
     LEA RSI,[PaintStruct]
     WinABI EndPaint,[hWindowMain],RSI
     JMP .Ret0:
.WM_CHAR:
     MOV RAX,R8
     Dispatch AL,0x08,0x0D,0x3D,0x1B   ; Backspace, Enter, =, Esc.
     LEA RSI,[InpBuffer::]             ; Otherwise AL is an ordinary character.
     MOV ECX,[LineSize]
     LEA RDI,[RSI+RCX-1]
     LEA RSI,[RDI-1]
     MOV RCX,RDI
     SUB RCX,[InpBufferPtr]
     JLE .Ret0:
     STD
       REP MOVSB                       ; Move characters at cursor one position right.
     CLD
     STOSB                             ; Store the new character.
     MOV [InpBufferPtr],RDI
     JNSt [Status::],ArgCalculated,.10:
     RstSt [Status::],ArgCalculated
     LEA RDI,[OutBuffer::]
     MOV ECX,[LineSize]
     MOV AL,' '
     REP STOSB                         ; Erase the old output line if ArgCalculated.
.10: ; Common termination.
     WinABI InvalidateRect,[hWindowMain],0,1
     WinABI UpdateWindow,[hWindowMain]
     WinABI SetFocus,[hWindowMain]
     JMP .Ret0:
.0n2:                                  ; Button #2 [ Bs ].
.0x08:MOV EAX,[LineSize]               ; Key Backspace.
      LEA RSI,[InpBuffer::]
      MOV RDI,[InpBufferPtr]
      CMP RDI,RSI
      JNA .Ret0:
      LEA RCX,[RSI+RAX-1]
      DEC RDI
      SUB RCX,RSI
      MOV [InpBufferPtr],RDI
      LEA RSI,[RDI+1]
      REP MOVSB
      JMP .10:
.WM_KEYDOWN:                           ; Noncharacter key was pressed.
      MOV AX,R8W
      Dispatch AX,VK_LEFT,VK_RIGHT,VK_HOME,VK_END,VK_DELETE,VK_ESCAPE
      JMP .Def:
.VK_LEFT:                              ; Move caret left.
      MOV RDI,[InpBufferPtr]
      LEA RSI,[InpBuffer::]
      CMP RDI,RSI
      JNA .Ret0:
      DEC RDI
      MOV [InpBufferPtr],RDI
      JMP .10:
.VK_RIGHT:                             ; Move caret right.
     MOV RDI,[InpBufferPtr]
     LEA RSI,[InpBuffer::]
     MOV ECX,[LineSize]
     LEA RCX,[RSI+RCX-2]
     CMP RDI,RCX
     JNB .Ret0:
     INC RDI
     MOV [InpBufferPtr],RDI
     JMP .10:
.VK_END:                               ; Move caret at the end of the input.
     LEA RDI,[InpBuffer::]
     MOV ECX,[LineSize]
     LEA RDI,[RDI+RCX-1]
     MOV RSI,RDI
     MOV AL,' '
     STD
       REPE SCASB
     CLD
     ADD RDI,2
     CMP RDI,RSI
     JBE .20:
     DEC RDI
.20: MOV [InpBufferPtr],RDI
     JMP .10:
.VK_HOME:                              ; Move caret at the beginning.
     LEA RSI,[InpBuffer::]
     MOV [InpBufferPtr],RSI
     JMP .10:
.VK_DELETE:                            ; Erase the character below caret.
     LEA RSI,[InpBuffer::]
     MOV ECX,[LineSize]
     ADD RCX,RSI
     MOV RDI,[InpBufferPtr]
     LEA RSI,[RDI+1]
     SUB RCX,RSI
     REP MOVSB
     JMP .10:
.WM_COMMAND:                           ; Clicked somewhere int the main window.
     MOVZX EDX,R8B                     ; Button ordinal.
     CMP EDX,6*7
     JA .Def:
     Dispatch DL,0n1,0n2,0n42          ; DL=1..42 ordinal number of the clicked button.
     LEA RDI,[TitleBtns::]             ; Defined in calcmain.htm.
     LEA RCX,[TitleBtnsEnd::]
     LEA RAX,[TitleBtns::]
     SUB RCX,RAX
     XOR EAX,EAX
.30: REPNE SCASB
     DEC DL
     JNZ .30:
     MOV RSI,RDI                       ; Pointer at the button title.
     MOV ECX,[LineSize]
     LEA RBX,[InpBuffer::]
     ADD RBX,RSI
.35: MOV RDI,[InpBufferPtr]
     CMP RSI,RBX
     JNB .10:
     LODSB
     CMP AL,0
     JE .10:
     STOSB                             ; Store characters form the title to InpBuffer.
     MOV [InpBufferPtr],RDI
     JMP .35:
.0n1:                                  ; Button #1 [ Clr ].
     WinABI SetWindowText,[hWindowStatus],=B""  ; Erase status.
     LEA RDI,[InpBuffer::]
     MOV RBX,RDI
     MOV [InpBufferPtr],RDI
     MOV ECX,640
     MOV AL,' '
     REP STOSB                         ; Erase InpBuffer.
     LEA RDI,[OutBuffer::]
     MOV ECX,640
     REP STOSB                         ; Erase OutBuffer.
     JMP .10:
.0n42:                                 ; Button #42 [ = ].
.0x0D:                                 ; Key Enter.
.0x3D:                                ; Key =.
     ; Perform the calculation. Uses functions included from calcmain.htm.
     WinABI SetWindowText,[hWindowStatus],=B""
     LEA RSI,[InpBuffer::]
     MOV RCX,[InpBufferPtr]
     SUB RCX,RSI
     JZ .0n1:
.40: LODSB
     CMP AL,' '
     JA .50:
     LOOP .40:
     JMP .0n1:
.50: MOV RDI,[InpBufferPtr]
     MOV AL,'='
     STOSB
     LEA RSI,[InpBuffer::]
     MOV ECX,[LineSize]
     LEA RCX,[RSI+RCX-1]
     SUB RCX,RDI
     JLE .10:
     MOV AL,' '
     REP STOSB
     LEA RSI,[InpBuffer::]
     LEA RDI,[Pbuffer::]
     CALL Parse::                      ; Parse the ASCIIZ string at RSI.
     MOV [PbufferEnd::],RDI            ; Store numbers, parenthesis and functions to RDI=Pbuffer.
     JNC .60:
     WinABI SetWindowText,[hWindowStatus],=B"Syntax error."
     JMP .10:
.60: LEA RSI,[Pbuffer::]
     MOV RDX,[PbufferEnd::]
     LEA RDI,[InpBuffer::]
     MOV [InpBufferPtr],RDI
     CALL EchoExpression::
     LEA RDI,[InpBuffer::]
     MOV ECX,[LineSize]
     MOV AL,'='
     REPNE SCASB
     MOV AL,' '
     REP STOSB
     LEA RSI,[Pbuffer::]
     MOV RDX,[PbufferEnd::]
     LEA RDI,[Nbuffer::]
     CALL Deparent::                   ; Remove N-records for parenthesis.
     MOV [NbufferEnd::],RDI
     JNC .70:
     WinABI SetWindowText,[hWindowStatus],=B"Unbalanced parenthesis."
     JMP .10:
.70: CALL Calculate::
     JNC .80:
     WinABI SetWindowText,[hWindowStatus],=B"Error in expression or division by 0."
     JMP .10:
.80: CALL DisplayDecimalProxy::        ; Put the output string to OutBuffer.
     SetSt [Status::],ArgCalculated    ; This trigger tells to erase OutBuffer on new input.
     LEA RDI,[OutBuffer::]
     XOR EAX,EAX
     MOV ECX,[LineSize]
     REPNE SCASB
     DEC RDI
     MOV AL,' '
     REP STOSB
     JMP .10:
.0x1B:                                 ; Key Esc.
.VK_ESCAPE:
.WM_DESTROY:                           ; Program terminates.
     WinABI DestroyCaret
     WinABI DeleteObject,[hFont]
     WinABI ShowWindow,[hWindowMain],SW_HIDE
     WinABI PostQuitMessage,0          ; Tell Windows to quit this program with errorlevel 0.
.Ret0:XOR EAX,EAX                      ; RAX=0 signalizes that the message was processed here.
.Ret:EndProcedure WndProcMain
  ENDPROGRAM calcwing

▲Back to the top▲