Hello,
i build a application with a window and a button.
Now I try to get the button size and position wirth the function GetClientRect
bottom and right is correct but left and top is 0, and i don't know why.
can anybody help?
.386
.model flat,stdcall
option casemap:none
include C:\masm32\include\windows.inc
include C:\masm32\include\user32.inc
include C:\masm32\include\kernel32.inc
includelib C:\masm32\lib\user32.lib
includelib C:\masm32\lib\kernel32.lib
.data?
hInstance HINSTANCE ?
h_window HWND ?
h_button HWND ?
.data
AppNameDefault db "FD3",0
; Classen Namen
btnClass db "BUTTON",0
.code
START:
Window proc
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL CoordRect: RECT
invoke GetModuleHandleA, NULL
mov hInstance,eax
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET EVENTS
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE + 1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET AppNameDefault
invoke LoadIconA,hInstance,500
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursorA,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassExA, addr wc
INVOKE CreateWindowExA, NULL, ADDR AppNameDefault, ADDR AppNameDefault,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
NULL, NULL, hInstance, NULL
mov h_window,eax
INVOKE ShowWindow, h_window, SW_SHOW
INVOKE UpdateWindow, h_window
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ERROR PART ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ERSTELLE BUTTON
invoke CreateWindowExA, NULL, ADDR btnClass, NULL, WS_CHILD or WS_VISIBLE, 150, 150, 150, 150, h_window, ebx, hInstance, NULL
mov h_button, eax
invoke GetClientRect, h_button, ADDR(CoordRect)
;cmp CoordRect.bottom,0 --> not null ?
cmp CoordRect.left,0 ;--> why NULL???
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ERROR PART END ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
je @exit_program
@infinite_loop:
INVOKE GetMessageA, ADDR msg, NULL, 0, 0
; falls Benutzer Fenster schließt
cmp eax, 0
je @exit_program
INVOKE TranslateMessage, ADDR msg
INVOKE DispatchMessageA, ADDR msg
jmp @infinite_loop
@exit_program:
invoke ExitProcess, 0
Window ENDP
EVENTS PROC hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
EVENTS ENDP
END START
GetClientRect returns always zero in rc.left and rc.top
You need GetWindowRect (child) minus GetWindowRect (parent)
Viel Spass ;-)
Thx & Danke ;-)
This is a quick demo of both, built on a MASM32 in-memory, modal dialog.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
;
; Build this as a console app so print will work.
;
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
hInst dd 0
hEdit dd 0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
DialogProc proc hwndDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL rc:RECT
SWITCH uMsg
CASE WM_SIZE, WM_MOVE
invoke GetClientRect, hwndDlg, ADDR rc
loc 1,2
print "GetClientRect (client coordinates): "
print str$(rc.left),","
print str$(rc.top),","
print str$(rc.right),","
print str$(rc.bottom)," "
invoke GetWindowRect, hwndDlg, ADDR rc
loc 1,4
print "GetWindowRect (screen coordinates): "
print str$(rc.left),","
print str$(rc.top),","
print str$(rc.right),","
print str$(rc.bottom)," "
CASE WM_COMMAND
.IF wParam == IDCANCEL
invoke EndDialog, hwndDlg, NULL
.ENDIF
CASE WM_CLOSE
invoke EndDialog, hwndDlg, NULL
ENDSW
return 0
DialogProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke GetModuleHandle, NULL
mov hInst, eax
Dialog "TEST",\
"MS Sans Serif",8,\
WS_OVERLAPPEDWINDOW or DS_CENTER,\
0,0,0,120,90,1024
CallModalDialog hInst,0,DialogProc,NULL
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
Hello,
there are some new problems :-(
I build a macro to get the upper left corner (X: left, Y: zop) and width: right and height: bottom from a control
h_window = Window Handle
h_control = Button Handle
LOCAL CoordRect: RECT
LOCAL CoordRect2: RECT
GET_CONTROL_POINTS macro h_control
push eax
push ebx
invoke GetWindowRect, h_control, ADDR(CoordRect)
invoke GetWindowRect, h_window, ADDR(CoordRect2)
;OK
mov eax, CoordRect.left
sub eax, CoordRect2.left
mov CoordRect.left, eax
; Error, because of the TitleBar (If a Button is on relativ Position 0 and the window absolute position is 100, then the button absolute position is ~110. 110 - 100 = 10, but it should be 0 :-(
mov eax, CoordRect.top
sub eax, CoordRect2.top
mov CoordRect.top, eax
; Don't know why it doesn't work
mov eax, CoordRect2.right
sub eax, CoordRect.right
sub eax, CoordRect.left ; Get Width
mov CoordRect.right, eax
; Don't know why it doesn't work
mov eax, CoordRect2.bottom
sub eax, CoordRect.bottom
sub eax, CoordRect.top ; Höhe ausrechnen
mov CoordRect.bottom, eax
pop ebx
pop eax
; ACHTUNG: BUG bei TOP wegen Titelleiste
; BUG Höhe Stimmt nicht?!
endm
Remember when using GetClientRect that the Right and Bottom values are actually the width and height of the button. You do not need to calculate them.
Paul
Hello,
two problems solve, but the Top Value is false. Because i have to subtract the window title hight.
How can i get the window title high + menue high (if there is a menue) or how i can get the absolute position of the client area?
GET_CONTROL_POINTS macro h_control
push eax
push ebx
; für top und left
invoke GetWindowRect, h_control, ADDR(CoordRect)
invoke GetWindowRect, h_window, ADDR(CoordRect2)
mov eax, CoordRect.left
sub eax, CoordRect2.left
mov CoordRect.left, eax
; Not the real TOP Value, because its the real Top Value + Window Title Hight
mov eax, CoordRect.top
sub eax, CoordRect2.top
mov CoordRect.top, eax
; für right (width) und bottom (heigh)
invoke GetClientRect, h_control, ADDR(CoordRect2)
mov eax, CoordRect2.right
mov CoordRect.right, eax
mov eax, CoordRect2.bottom
mov CoordRect.bottom, eax
pop ebx
pop eax
; ACHTUNG: BUG bei TOP wegen Titelleiste
endm
If you are using a menu, use GetMenuItemRect.
If you are using an edit control, use EM_GETRECT.
If you are using a StatusBar, use SB_GETRECT.
If you are using a Tab Control, use TabCtrl_GetItemRect.
If you are using a ToolBar, use TB_GETITEMRECT.
There are a few others like for the TAB itself in a TAB Control or a TreeView but I think I covered what you may need.
Take a look at SubtractRect.
Paul
Maybe I'm missing something here, are you simply trying to convert client coordinates to screen coordinates ?
invoke GetClientRect, [hwnd], offset rect
invoke ClientToScreen, [hwnd], offset rect
it will set the top/left to a screen point and keep the width and height. If you need all of it changed...
invoke GetClientRect, [hwnd], offset rect
invoke ClientToScreen, [hwnd], offset rect
invoke ClientToScreen, [hwnd], offset rect.right
You can also use MapWindowPoints to do the conversion if you want all points converted (as above)
invoke GetClientRect, [hwnd], offset rect
invoke MapWindowPoints, [hwnd], HWND_DESKTOP, offset rect, 2
Edgar
Perhaps did you not understand the poetic definition of the RECT structure.If you prefered a mathematic one,here is a definition that use X,Y coordinate and than can be understand without headaches.
Quote
;this one exist in the header's file
POINT STRUCT
x DWORD ?
y DWORD ?
POINT ENDS
;---------- this one can replace the RECT structure ------------------------------
FRECT STRUCT
min POINT <>
max POINT <>
FRECT ENDS
And all is clear.Call the GetClientRect with FRECT and you can extract the height (Y-Y) and the widht (X-X) without read winhelp to do that.
Pseudo code:
height = max.Y - min.Y
widht = max.X - min.X
You don't want negative number,so you never use min - max.
One more :bg
MyProc proc uses edi
LOCAL rcP:RECT, rcC:RECT, px, py, border, LocBuf[100]:BYTE
invoke GetSystemMetrics, SM_CXSIZEFRAME
mov border, eax
lea edi, LocBuf
invoke GetWindowRect, hParent, addr rcP
m2m px, rcP.right
m2m py, rcP.bottom
invoke GetClientRect, hParent, addr rcP
mov eax, rcP.right
add eax, border
sub px, eax ; effective offset left
mov eax, rcP.bottom
add eax, border
sub py, eax ; effective offset top
invoke GetWindowRect, hButton1, addr rcC
invoke lstrcpy, edi, chr$("left", 9)
mov ecx, rcC.left
sub ecx, px
invoke lstrcat, edi, str$(ecx)
invoke lstrcat, edi, chr$(13, 10, "top", 9)
mov ecx, rcC.top
sub ecx, py
invoke lstrcat, edi, str$(ecx)
invoke lstrcat, edi, chr$(13, 10, "right", 9)
mov ecx, rcC.right
sub ecx, px
invoke lstrcat, edi, str$(ecx)
invoke lstrcat, edi, chr$(13, 10, "bottom", 9)
mov ecx, rcC.bottom
sub ecx, py
invoke lstrcat, edi, str$(ecx)
sm hStatic, WM_SETTEXT, 0, edi
ret
MyProc endp
[attachment deleted by admin]
Hello,
thx for help, my final version
; Hohle die Controll Points in CoordRect relativ zum linken oberen Fenster Punkt
; h_control = Handle vom Controll
; h_window = Handle vom Window
; CoordRect und CoordRect2 = RECT
GET_CONTROL_POINTS macro h_control
push eax
push ebx
; für top und left
invoke GetWindowRect, h_control, ADDR(CoordRect)
; zu relativen coordinaten mappen
invoke MapWindowPoints, 0, h_window, ADDR(CoordRect), 2
; für right (width) und bottom (heigh)
invoke GetClientRect, h_control, ADDR(CoordRect2)
mov eax, CoordRect2.right
mov CoordRect.right, eax
mov eax, CoordRect2.bottom
mov CoordRect.bottom, eax
pop ebx
pop eax
endm