News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Controls problem

Started by vogelsang, December 12, 2013, 04:35:16 AM

Previous topic - Next topic

vogelsang

Hi assembly coders,

again i need your help. I'm trying to convert to 64 bit Iczelion example from chapter 9. App "works" but it should create two controls and they don't appear on app window. So i thought i if they don't appear it probably must be messed something with creating them. CreateWindowEx in both cases returns zero. So i called GetLastError after creating. Error code:

ERROR_TLW_WITH_WSCHILD 1406(0x57E) Cannot create a top-level child window.

I have googled for that error but i don't feel, that i could handle myself with this.

source:

;--------MAKE-------------------------------------------------------------
;rc controls.rc
;assembling:
;jwasm -win64 controls.asm
;linking:
;link /SUBSYSTEM:WINDOWS controls.obj controls.res
;
;--------INCLUDES---------------------------------------------------------
option casemap:none ;set case sensitive on - this is important for the inc below

include /JWASM/wininc208/include/windows.inc ;this file contains consts, datatypes and func protos for the libraries below

includelib      /JWASM/wininc208/lib64/kernel32.lib
includelib      /JWASM/wininc208/lib64/user32.lib
includelib      /JWASM/wininc208/lib64/gdi32.lib

;--------DATA-------------------------------------------------------------
.CONST

ButtonID    EQU 1
EditID      EQU 2
IDM_HELLO    EQU 1
IDM_CLEAR    EQU 2
IDM_GETTEXT EQU 3
IDM_EXIT    EQU 4

.data
ClassName db "SimpleWinClass",0
AppName db "Using controls test",0
MenuName db "FirstMenu",0
ButtonClassName db "button",0
ButtonText db "Our first button",0
EditClassName db "edit",0
TestString db "Wow! I'm in editor.",0

;BSS data
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hwndButton HWND ?
hwndEdit HWND ?
buffer db 512 dup (?)

hwnd dq ?
wc WNDCLASSEX <>
msg MSG <>

;--------CODE-------------------------------------------------------------
.code

WinMainCRTStartup PROC FRAME
push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
.endprolog

sub rsp,32
mov ecx,NULL
call GetModuleHandleA
mov hInstance, rax

call GetCommandLineA
mov CommandLine, rax

mov rcx, hInstance
mov rdx, NULL
mov r8, CommandLine
mov r9d, SW_SHOWDEFAULT
call WinMain

mov ecx, eax
call ExitProcess
ALIGN 4
WinMainCRTStartup ENDP

;--------WINMAIN----------------------------------------------------------
WinMain PROC FRAME hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow

push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
sub rsp, 14*8 ;make sure rsp is 16-byte aligned
.allocstack 14*8
.endprolog

mov hInst, rcx   ;store param1 in shadow space
;prepare class for registration
mov wc.cbSize, SIZEOF WNDCLASSEXA
mov wc.style, CS_HREDRAW or CS_VREDRAW
lea rax, WndProc
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
mov wc.hInstance, rcx ;wc.hInstance = hInst
mov wc.hbrBackground, COLOR_BTNFACE+1
lea rax, MenuName
mov wc.lpszMenuName, rax
lea rax, ClassName
mov wc.lpszClassName, rax

mov edx, IDI_APPLICATION
mov ecx, NULL
call LoadIconA
mov wc.hIcon, rax
mov wc.hIconSm, rax

mov edx, IDC_ARROW
mov ecx, NULL
call LoadCursorA
mov wc.hCursor,rax

lea rcx, wc
call RegisterClassExA
;creating window based on class registrated above
mov qword ptr [rsp+11*8], NULL ;lpParam
mov rax, hInst
mov qword ptr [rsp+10*8], rax ;hInstance
xor rax, rax
mov qword ptr [rsp+9*8], rax ;hMenu
mov dword ptr [rsp+8*8], eax ;hWndParent
mov dword ptr [rsp+7*8], 200 ;nHeight
mov dword ptr [rsp+6*8], 300 ;nWidth
mov dword ptr [rsp+5*8], CW_USEDEFAULT ;Y
mov dword ptr [rsp+4*8], CW_USEDEFAULT ;X
mov r9d, WS_OVERLAPPEDWINDOW ;dwStyle
lea r8, AppName ;lpWindowName
lea rdx, ClassName ;lpClassName
mov rcx, WS_EX_CLIENTEDGE ;dwExStyle
call CreateWindowExA ;create window
mov hwnd, rax

mov rdx, SW_SHOWNORMAL
mov rcx, rax
call ShowWindow
mov rcx, hwnd
call UpdateWindow
;-------MESSAGE LOOP------------------------------------------------------
msg_loop:
lea rcx, msg
        mov rdx, NULL
        mov r8, 0
        mov r9, 0
        call GetMessageA

        test rax, rax
        jz exit_WinMain
        lea rcx, msg
        call TranslateMessage

        lea rcx, msg
        call DispatchMessageA
jmp msg_loop
;-------MESSAGE LOOP END--------------------------------------------------
exit_WinMain:
mov rax, msg.wParam
add rsp, 14*8 ;restore stack
pop rbp
ret
ALIGN 4
WinMain ENDP

;-------WNDPROC-----------------------------------------------------------
WndProc PROC FRAME hWnd:HWND, uMsg:QWORD, wParam:WPARAM, lParam:LPARAM

sub rsp, 13*8
.allocstack 13*8
.endprolog

cmp edx, WM_DESTROY ;if WM_DESTROY exit program
jne msg_create ;otherwise check if it was WM_CREATE

xor rcx, rcx ;RCX == NULL
call PostQuitMessage
xor rax, rax
jmp exit_WndProc
msg_create:
cmp edx, WM_CREATE
jne msg_command ;Create controls on window create event

xor rax, rax
mov qword ptr [rsp+11*8], rax
mov rax, hInstance
mov qword ptr [rsp+10*8], rax
mov rax, EditID
mov qword ptr [rsp+9*8], rax ;give control ID number
mov rax, hwnd
mov qword ptr [rsp+8*8], rax
mov dword ptr [rsp+7*8], 25
mov dword ptr [rsp+6*8], 200
mov dword ptr [rsp+5*8], 35
mov dword ptr [rsp+4*8], 50
mov r9d, WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or ES_AUTOHSCROLL
xor r8, r8 ;R8 == NULL
lea rdx, EditClassName
mov rcx, WS_EX_CLIENTEDGE
call CreateWindowExA ;create EditBox
mov hwndEdit, rax

call GetLastError

mov rcx, hwndEdit
call SetFocus

mov qword ptr [rsp+11*8], NULL
mov rax, hInstance
mov qword ptr [rsp+10*8], rax
mov qword ptr [rsp+9*8], ButtonID ;give control ID number
mov rax, hwnd
mov qword ptr [rsp+8*8], rax ;
mov dword ptr [rsp+7*8], 25
mov dword ptr [rsp+6*8], 200
mov dword ptr [rsp+5*8], 70
mov dword ptr [rsp+4*8], 50
mov r9d, WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON
lea r8, ButtonText
lea rdx, ButtonClassName
xor rcx, rcx
call CreateWindowExA ;create Button
mov hwndButton, rax

call GetLastError

xor rax, rax
jmp exit_WndProc
msg_command:
cmp edx, WM_COMMAND
jne no_msg

test r9, r9
jnz btn_pressed

cmp r8w, IDM_HELLO
jne idm_clear

lea rdx, TestString
mov rcx, hwndEdit
call SetWindowText

xor r9, r9
mov r8, VK_END
mov rdx, WM_KEYDOWN
mov rcx, hwndEdit
call SendMessage

xor rax, rax
jmp exit_WndProc
idm_clear:
cmp r9w, IDM_CLEAR
jne idm_gettext

xor rdx, rdx
mov rcx, hwndEdit
call SetWindowText

xor rax, rax
jmp exit_WndProc
idm_gettext:
cmp r9w, IDM_GETTEXT
jne destroy_wnd

mov r8d, 512
lea rdx, buffer
mov rcx, hwndEdit
call GetWindowText

mov r9, MB_OK
lea r8, AppName
lea rdx, buffer
xor rcx, rcx
call MessageBox

xor rax, rax
jmp exit_WndProc
destroy_wnd:
mov rcx, hwnd
call DestroyWindow

xor rax, rax
jmp exit_WndProc
btn_pressed:
cmp r9w, ButtonID
jne no_msg

shr r9d, 16
cmp r9w, BN_CLICKED

xor r9, r9
mov r8, IDM_GETTEXT
mov rdx, WM_COMMAND
mov rcx, hwnd
call SendMessage

xor rax, rax
jmp exit_WndProc
no_msg:
call DefWindowProcA ;parameters for this function comming unchanged from start of this proc
exit_WndProc:
add rsp, 13*8 ;restore stack
ret
ALIGN 4
WndProc ENDP
END
;--------EOF---------------------------------------------------------------


rc file:

#define IDM_HELLO   1
#define IDM_CLEAR   2
#define IDM_GETTEXT 3
#define IDM_EXIT    4

FirstMenu MENU
{
    POPUP "&Test controls"
    {
        MENUITEM "&Say hi", IDM_HELLO
        MENUITEM "&Clear edit field", IDM_CLEAR
        MENUITEM "&Get text", IDM_GETTEXT
        MENUITEM SEPARATOR
        MENUITEM "E&xit", IDM_EXIT
    }
}


Maybe something else is wrong? Any ideas, hints?
Thanks in advance.



jj2007

Is hwnd nonzero? It seems not... try hWnd.

dedndave

a window can either be a parent or a child  :)
a child must have a parent
and, for a parent, the desktop is essentially the parent-parent (grandparent window ?)  :P

dedndave

when you create the top window, you are using dword values for qword parms ???
that means the high dword is - whatever

jj2007

Dave, it's just a typo. Instead of local hWnd, Vogelsang used global hwnd, which is not yet set in the WM_CREATE handler.

dedndave

;creating window based on class registrated above
mov qword ptr [rsp+11*8], NULL ;lpParam
mov rax, hInst
mov qword ptr [rsp+10*8], rax ;hInstance
xor rax, rax
mov qword ptr [rsp+9*8], rax ;hMenu
mov dword ptr [rsp+8*8], eax ;hWndParent
mov dword ptr [rsp+7*8], 200 ;nHeight
mov dword ptr [rsp+6*8], 300 ;nWidth
mov dword ptr [rsp+5*8], CW_USEDEFAULT ;Y
mov dword ptr [rsp+4*8], CW_USEDEFAULT ;X
mov r9d, WS_OVERLAPPEDWINDOW ;dwStyle
lea r8, AppName ;lpWindowName
lea rdx, ClassName ;lpClassName
mov rcx, WS_EX_CLIENTEDGE ;dwExStyle
call CreateWindowExA ;create window


hWndParent is a QWORD parameter
he sets the low DWORD to 0 using EAX
the high DWORD is whatever is on the stack (garbage)

i dunno - maybe 64-bit handles are 32 bits wide ?

vogelsang

Quote from: jj2007 on December 12, 2013, 04:49:37 AM
Is hwnd nonzero? It seems not... try hWnd.

You mean hWnd WndProc param? I have replaced all hwnd in WndProc with hWnd and now window doesn't appear at all. And I've initialized it in shadow space right after proc entry.

dedndave

you don't want to replace all of them
some need to be the local WndProc parm
some need to be the global variable

a lot of guys use hWnd for the local parm
then, hWin, hwnd or something for the global variable

i have started using hwndMain for the global label name   :P
a little less confusing

qWord

If you use the PROC's parameter, you must setup RBP probably (push rbp; mov rbp,rsp; sub rsp,14*8;) and then fill the shadow space of hWnd.

BTW: xor eax,eax does the same as xor rax,rax, but is one byte shorter...
MREAL macros - when you need floating point arithmetic while assembling!

vogelsang

Quote from: qWord on December 12, 2013, 05:30:34 AM
If you use the PROC's parameter, you must setup RBP probably (push rbp; mov rbp,rsp; sub rsp,14*8;) and then fill the shadow space of hWnd.

I've added:

WndProc PROC
push rbp
.pushreg rbp
mov rbp,rsp
.setframe rbp, 0
sub rsp, 14*8 ;make sure rsp is 16-byte aligned
.allocstack 14*8
.endprolog
        ...
add rsp, 14*8 ;restore stack
pop rbp
ret
ALIGN 4
WndProc ENDP

it looks better. Controls are now on app window. but Clear Edit, GetText and MessageBoxes doesn't working. What a mess :biggrin:

vogelsang

You're answering really quick and i don't have time to embrace it. Switching between my source code, forum and debugger. Sorry i've edited my ealier post and now discusion looks a bit unclear.

qWord

r9w is used as LOWORD(wParam) --> r8w.
MREAL macros - when you need floating point arithmetic while assembling!

vogelsang

Quote from: qWord on December 12, 2013, 06:11:11 AM
r9w is used as LOWORD(wParam) --> r8w.

Thanks all for help and really great thanks qWord :greenclp:

japheth


;jwasm -win64 controls.asm


You should always add the -Zp8 option for 64-bit - else you have to expect strange errors.