;Win10A.asm : RC Dialog /Edit Control/IsDialogMessage - NO DefPushbutton (October 26, 2023) %ifdef NOTES: The " %include " paths at the start of the file might need to be changed to suit your own disk directory setup. Command Lines: Assembly: nasm -f win32 -E asmerror Win10A.asm -o Win10A.obj Linking: GoLink.exe: golink.exe /entry:start Win10A.obj Win10A.res kernel32.dll user32.dll =================================================================== %endif %include '\nasm32\inc\win32\windows.inc' %include '\nasm32\inc\win32\kernel32.inc' %include '\nasm32\inc\win32\user32.inc' %include '\nasm32\inc\win32\gdi32.inc' %include '\nasm32\inc\nasm32.inc' [section .data] ;Strucs wcx times WNDCLASSEX_size db 0 msg times MSG_size db 0 ;Handles hInstance dd 0 hWnd dd 0 hWndDlg dd 0 ;Equates Menu_Win10A EQU 1000 IDM_DLGBOX equ 1020 IDM_HELP equ 1080 Dlg_Win10A equ 2000 IDC_EDIT equ 2010 IDM_MENU equ 2020 ;Various labels countChar dd 0 szMenuName db "Menu_Win10A",0x0 szTitle db 'Win10A - /Dialog/Edit/No DefPushbutton',0x0 szClass db 'Win10A Class',0x0 DlgTxtBuf times 10h db "0" lDlgTxtBuf equ $-DlgTxtBuf [section .text] start: proc Win10A invoke GetModuleHandleA, dword NULL mov [hInstance], eax invoke WinMain,dword [hInstance],dword NULL,dword NULL,dword SW_SHOWNORMAL invoke ExitProcess,dword NULL ret endproc proc WinMain ,hInst,hPinst,CmdLn,dwShow ;Memory block reserved for wcx [WNDCLASSEX] has no data yet. ;A different method of populating memory slots. push dword WNDCLASSEX_size pop dword [wcx + WNDCLASSEX.cbSize] push dword argv(hInst) pop dword [wcx + WNDCLASSEX.hInstance] push dword szClass pop dword [wcx + WNDCLASSEX.lpszClassName] push dword WndProc ; Adr of WndProc pop dword [wcx + WNDCLASSEX.lpfnWndProc] push dword COLOR_BTNFACE +1 pop dword [wcx + WNDCLASSEX.hbrBackground] ;When the array wcx is created the system fills it with zeroes and ;_LoadWCX doesn't overwrite lpszMenuName with any value. This is to ; keep the macro as a quick generic tool. ;Note that the hMenu parameter of CreateWindowEx stays as NULL. push dword Menu_Win10A pop dword [wcx +WNDCLASSEX.lpszMenuName] invoke RegisterClassExA, dword wcx ;Create the window invoke CreateWindowExA,\ WS_EX_OVERLAPPEDWINDOW,\ szClass,\ szTitle,\ WS_OVERLAPPEDWINDOW +WS_VISIBLE,\ 100, 120, 600, 232,\ NULL,\ NULL,\ dword [hInstance],\ NULL mov [hWnd], eax ;Process windows messages MsgGet: invoke GetMessageA, dword msg, dword NULL, dword NULL, dword NULL cmp eax,0 jnz MsgDlgCheck jmp MsgEnd MsgDlgCheck: invoke IsDialogMessageA,dword [hWndDlg], msg cmp eax,TRUE ; TRUE =message from dialog box. jz MsgGet ;Is from dialog box. DON'T feed it back to Windows. ; Get next message MsgProcess: invoke TranslateMessage, dword msg invoke DispatchMessageA, dword msg jmp MsgGet MsgEnd: ret endproc ;------------------------------------------------------- ;Windows callback function ;We don't trap for WM_CLOSE because we don't have any need ; to interrupt the process of destroying the window. proc WndProc, hWin, uMsg, wParam, lParam cmp dword argv(uMsg), WM_COMMAND jz near wpMenu cmp dword argv(uMsg), WM_CHAR jz near IsChar cmp dword argv(uMsg), WM_DESTROY jz near ExitWin10A jmp DefWndProc ;End of traps. Pass msg to DefWndProc wpMenu: cmp dword argv(wParam),IDM_DLGBOX ;lParam value ignored. Only menu and jz wpIsRunning? ; accelerator keyhits in main win. xor eax,eax ret wpIsRunning?: cmp dword [hWndDlg],0 ;hWndDlg =0 if dialog not already loaded. jz near wpCreateDlg xor eax,eax ;Dialog already loaded so bypass. ret wpCreateDlg: invoke CreateDialogParamA,\ dword [hInstance],\ Dlg_Win10A,\ dword argv(hWin),\ DlgProc,\ dword NULL mov dword [hWndDlg],eax xor eax,eax ret IsChar: cmp dword argv(wParam),VK_ESCAPE jz IsEsc xor eax,eax ret IsEsc: invoke SendMessageA,dword argv(hWin),WM_CLOSE,NULL,NULL xor eax,eax ;Win10A doesn't TRAP for WM_CLOSE so any request to ret ;end the application results in an immediate shut-down. DefWndProc: invoke DefWindowProcA, dword argv(hWin), dword argv(uMsg),\ dword argv(wParam),dword argv(lParam) ret ;Exit procecure ExitWin10A: ;Quit the application invoke PostQuitMessage,dword NULL xor eax,eax ret endproc ;WndProc ;-------------------------------------------------------------- ;Dialog callback function ;Here, we MUST trap WM_CLOSE because DefDlgProc doesn't send a WM_DESTROY ; message to a dialog box automatically after WM_CLOSE. proc DlgProc, hDlg, msgDlg,wParamDlg, lParamDlg IsCommand?: cmp dword argv(msgDlg),WM_COMMAND jz near dpCommand cmp dword argv(msgDlg),WM_CLOSE jz near dpClose mov eax,FALSE ; Dlg proc returns FALSE if message not handled. ret dpCommand: mov eax, dword argv(wParamDlg) cmp dword argv(lParamDlg),0 ;This isn't really necessary. Menu +NO pushbutton jz dplPZero ; always reports 0 in lParam. mov eax,TRUE ret dplPZero: cmp ax,IDOK ;if enter key + no defpushbutton then wParam(LOWORD) =IDOK jz dpDefBut IsDlgEsc?: cmp ax,IDCANCEL ;Esc. jz dpClose mov eax,TRUE ret dpDefBut: ;Which control has focus invoke GetFocus invoke GetDlgCtrlID,eax cmp ax,IDC_EDIT jz dpText ;If Edit has focus then continue. Otherwise leave. mov eax,TRUE ;We handled WM_COMMAND ret dpText: invoke GetDlgItemTextA, dword argv(hDlg),IDC_EDIT, DlgTxtBuf, lDlgTxtBuf mov dword [countChar],eax invoke GetDC,dword [hWnd] ; Get Device Context for MAIN window. push eax invoke TextOutA,eax,0,0,DlgTxtBuf,dword [countChar] pop eax invoke ReleaseDC, dword [hWnd], eax mov eax,TRUE ret dpClose: invoke InvalidateRect,dword [hWnd],0,1 ;Erase main window. mov eax, dword [hWndDlg] invoke DestroyWindow,dword argv(hDlg) ;Kill dialog/edit box. mov dword [hWndDlg],0 ;So we can keep making new dialogs as the old ones ; are destroyed. mov eax,TRUE ret endproc ;DlgProc ;mcamember May 10, 2024