The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: ferby on February 13, 2009, 11:22:12 PM

Title: GetClientRect does not work
Post by: ferby on February 13, 2009, 11:22:12 PM
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
Title: Re: GetClientRect does not work
Post by: jj2007 on February 13, 2009, 11:35:05 PM
GetClientRect returns always zero in rc.left and rc.top
You need GetWindowRect (child) minus GetWindowRect (parent)

Viel Spass ;-)
Title: Re: GetClientRect does not work
Post by: ferby on February 14, 2009, 12:16:50 AM
Thx & Danke ;-)
Title: Re: GetClientRect does not work
Post by: MichaelW on February 14, 2009, 12:27:39 AM
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

Title: Re: GetClientRect does not work
Post by: ferby on February 14, 2009, 01:46:06 AM
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

Title: Re: GetClientRect does not work
Post by: PBrennick on February 14, 2009, 02:05:24 AM
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
Title: Re: GetClientRect does not work
Post by: ferby on February 14, 2009, 02:30:00 AM
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
Title: Re: GetClientRect does not work
Post by: PBrennick on February 14, 2009, 04:13:31 AM
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
Title: Re: GetClientRect does not work
Post by: donkey on February 14, 2009, 06:11:44 AM
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
Title: Re: GetClientRect does not work
Post by: ToutEnMasm on February 14, 2009, 07:25:49 AM

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.






Title: Re: GetClientRect does not work
Post by: jj2007 on February 14, 2009, 08:02:46 AM
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]
Title: Re: GetClientRect does not work
Post by: ferby on February 14, 2009, 01:59:31 PM
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