News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

GetClientRect does not work

Started by ferby, February 13, 2009, 11:22:12 PM

Previous topic - Next topic

ferby

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

jj2007

GetClientRect returns always zero in rc.left and rc.top
You need GetWindowRect (child) minus GetWindowRect (parent)

Viel Spass ;-)

ferby


MichaelW

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

eschew obfuscation

ferby

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


PBrennick

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
The GeneSys Project is available from:
The Repository or My crappy website

ferby

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

PBrennick

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
The GeneSys Project is available from:
The Repository or My crappy website

donkey

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
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

ToutEnMasm


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.







jj2007

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]

ferby

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