Sorry to bring this up! But I was curious about how windows messages work :)
I made a dialog that just had a single textbox on it and was hoping to use WM_KEYDOWN to handle when a key was pressed on it, but nothing happens when i try it! :(
So i looked at some msdn stuff or maybe it was a tutorial.. i dont remember but anyways they did something weird stuff with SendMessage, Im guessing the control has its own messages to be handled or something?
can someone point me in the right direction? sorry to bother!
include \masm32\include\masm32rt.inc
WinProc PROTO :HWND, :UINT, :WPARAM, :LPARAM
.code
start:
invoke DialogBoxParam, rv(GetModuleHandle, 0), 1, 0, OFFSET WinProc, 0
invoke ExitProcess, 0
WinProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
mov eax, uMsg
.if eax == WM_CLOSE
invoke EndDialog, hWnd, 0
.elseif eax == WM_KEYDOWN
.if wParam == VK_RETURN
invoke EndDialog, hWnd, 0
.endif
.else
mov eax, 0
.endif
ret
WinProc endp
end start
WM_KEYDOWN (http://msdn.microsoft.com/en-us/library/ms646280(VS.85).aspx) and similar messages are posted to the window with the keyboard focus. In a dialog with only an edit control the edit control will have the keyboard focus. One easy method of intercepting the edit control messages is to subclass the edit control, see Subclassing a Window (http://msdn.microsoft.com/en-us/library/ms633570(v=VS.85).aspx#subclassing_window).
;==============================================================================
; Build as console app.
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
IDC_EDIT equ 101
;==============================================================================
.data
lpPrevEditProc dd 0
hwndEdit dd 0
.code
;==============================================================================
EditProc proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_KEYDOWN
print "WM_KEYDOWN",13,10
CASE WM_KEYUP
print "WM_KEYUP",13,10
ENDSW
invoke CallWindowProc, lpPrevEditProc, hwnd, uMsg, wParam, lParam
ret
EditProc endp
;==============================================================================
DialogProc proc hwndDlg:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_INITDIALOG
invoke GetDlgItem, hwndDlg, IDC_EDIT
mov hwndEdit, eax
invoke SetWindowLong, hwndEdit, GWL_WNDPROC, EditProc
mov lpPrevEditProc, eax
CASE WM_SIZE
mov eax, lParam
movzx eax, ax
mov edx, lParam
shr edx, 16
invoke MoveWindow, hwndEdit, 0, 0, eax, edx, TRUE
CASE WM_COMMAND
SWITCH wParam
CASE IDCANCEL
invoke EndDialog, hwndDlg, NULL
ENDSW
CASE WM_CLOSE
invoke EndDialog, hwndDlg, NULL
ENDSW
return 0
DialogProc endp
;==============================================================================
start:
;==============================================================================
Dialog "Test", \
"FixedSys", 11, \
WS_OVERLAPPED or WS_SYSMENU or DS_CENTER, \
1, \
0,0,100,75, \
1024
DlgEdit WS_BORDER or ES_MULTILINE or ES_WANTRETURN or WS_VSCROLL or \
WS_HSCROLL or ES_AUTOVSCROLL or ES_AUTOHSCROLL, \
0,0,0,0,IDC_EDIT ; will be sized in WM_SIZE handler
invoke GetModuleHandle, NULL
CallModalDialog eax, 0, DialogProc, NULL
exit
;==============================================================================
end start
one thing i have learned...
dialogs are very different from client windows
in a client window, WM_KEYDOWN acts as you might expect :P
dialogs may be a little harder to learn, but more useful - they do a lot more stuff
Regarding where the WM_KEYDOWN and similar messages get posted, an application window with a child control that can and does have the keyboard focus will behave the same way as the dialog.
;==============================================================================
; Build as a console app.
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
hInst dd 0
hWnd dd 0
hwndEdit dd 0
_x dd 0
_y dd 0
wc WNDCLASSEX <>
msg MSG <>
className db "test_class",0
.code
;==============================================================================
WndProc proc hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
SWITCH uMsg
CASE WM_CREATE
invoke CreateWindowEx,0,chr$("EDIT"),0,
WS_VISIBLE or WS_CHILDWINDOW or \
ES_MULTILINE or ES_WANTRETURN or WS_VSCROLL or \
WS_HSCROLL or ES_AUTOVSCROLL or ES_AUTOHSCROLL,
0,0,0,0,hwnd,1000,0,0
mov hwndEdit, eax
invoke SetFocus, hwndEdit
CASE WM_SIZE
mov eax, lParam
movzx eax, ax
mov edx, lParam
shr edx, 16
invoke MoveWindow, hwndEdit, 0, 0, eax, edx, TRUE
CASE WM_KEYDOWN
print "WM_KEYDOWN",13,10
CASE WM_KEYUP
print "WM_KEYUP",13,10
CASE WM_CLOSE
invoke DestroyWindow, hwnd
CASE WM_DESTROY
invoke PostQuitMessage, NULL
DEFAULT
invoke DefWindowProc, hwnd, uMsg, wParam, lParam
ENDSW
ret
WndProc endp
;==============================================================================
start:
;==============================================================================
mov hInst, rv(GetModuleHandle, NULL)
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInst
mov wc.hbrBackground, rv(GetStockObject, BLACK_BRUSH)
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET className
mov wc.hIcon, rv(LoadIcon, NULL, IDI_APPLICATION)
mov wc.hCursor, rv(LoadCursor, NULL, IDC_ARROW)
mov wc.hIconSm, 0
invoke RegisterClassEx, ADDR wc
W = 400
H = 300
invoke GetSystemMetrics, SM_CXSCREEN
shr eax, 1
sub eax, W / 2
mov _x, eax
invoke GetSystemMetrics, SM_CYSCREEN
shr eax, 1
sub eax, H / 2
mov _y, eax
invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW,
ADDR className,
chr$("Test"),
WS_OVERLAPPED or WS_SYSMENU,
_x, _y, W, H,
NULL, NULL,
hInst, NULL
mov hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
msgLoop:
invoke GetMessage, ADDR msg, NULL, 0, 0
.IF eax != 0
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp msgLoop
.ENDIF
exit msg.wParam
;==============================================================================
end start
"Regarding where the WM_KEYDOWN and similar messages get posted, an application window with a child control that can and does have the keyboard focus will behave the same way as the dialog."
So WM_KEYDOWN can only be intercepted by hijacking the WndProc stuff with the SetWindowLong?
I got it to work by the way!! Thanks a lot MichaelW!
include \masm32\include\masm32rt.inc
WinProc PROTO :HWND, :UINT, :WPARAM, :LPARAM
.data
hEdit dd 0
.code
start:
main proc
LOCAL wcex :WNDCLASSEX
LOCAL msg :MSG
mov wcex.hInstance, rv(GetModuleHandle, 0)
mov wcex.lpszClassName, chr$("GUIClass")
mov wcex.lpfnWndProc, OFFSET WinProc
mov wcex.hbrBackground, COLOR_WINDOW
mov wcex.hCursor, rv(LoadCursor, 0, IDC_ARROW)
mov wcex.cbSize, SIZEOF WNDCLASSEX
invoke RegisterClassEx, ADDR wcex
invoke CreateWindowEx, 0, wcex.lpszClassName, chr$("Gui stuff"), 010c80000h, 0,0,200,200,0,0, wcex.hInstance, 0
.while 1
invoke GetMessage, ADDR msg, 0, 0, 0
.break .if eax == 0 || eax == -1
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.endw
invoke ExitProcess, 0
ret
main endp
EditProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
mov eax, uMsg
.if eax == WM_KEYDOWN
print "KEYDOWN!"
.endif
invoke CallWindowProc, hEdit, hWnd, uMsg, wParam, lParam
ret
EditProc endp
WinProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
mov eax, uMsg
.if eax == WM_CLOSE
invoke PostQuitMessage, 0
.elseif eax == WM_CREATE
invoke CreateWindowEx, 0, chr$("EDIT"), 0, 010000000h + WS_CHILD + ES_MULTILINE, 0,0,200,200, hWnd, 1000,0,0
invoke SetWindowLong, eax, GWL_WNDPROC, OFFSET EditProc
mov hEdit, eax
.elseif eax == WM_KEYDOWN
print "WM_KEYDOWN that doesn't post on typing"
.else
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
.endif
ret
WinProc endp
end start