News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Problems with MapWindowPoints

Started by Ar0n, August 10, 2015, 04:55:57 PM

Previous topic - Next topic

Ar0n

Hello guys, I'm trying to center a child window horizontrally using SetWindowPos, however, SetWindowPos takes as input X and Y so I need to get the Y value (vertical), I use MapWindowPoints for that, but it looks like this is not working... also, my textbox simply disappears! help please!

include \masm32\include\masm32rt.inc
.686

WinMain proto :HWND,:UINT,:WPARAM,:LPARAM

.const
   ClassName db "MainWinClass",0
   AppName  db "Main Window",0
   
   cedit db "edit",0
   
.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?
   hedit HWND ?
.code
start:
   invoke GetModuleHandle, NULL
   mov    hInstance,eax
   invoke GetCommandLine
   mov    CommandLine,eax
   invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
   invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
   LOCAL wc:WNDCLASSEX
   LOCAL msg:MSG
   
   mov   wc.cbSize,SIZEOF WNDCLASSEX
   mov   wc.style, CS_HREDRAW or CS_VREDRAW
   mov   wc.lpfnWndProc, OFFSET WndProc
   mov   wc.cbClsExtra,NULL
   mov   wc.cbWndExtra,NULL
   mrm   wc.hInstance,hInstance
   mov   wc.hbrBackground,COLOR_BTNFACE+1
   mov   wc.lpszMenuName,NULL
   mov   wc.lpszClassName,OFFSET ClassName
   
   invoke LoadIcon,NULL,IDI_APPLICATION
   mov   wc.hIcon,eax
   mov   wc.hIconSm,eax
   
   invoke LoadCursor,NULL,IDC_ARROW
   mov   wc.hCursor,eax
   

   invoke RegisterClassEx, addr wc
   INVOKE CreateWindowEx,0,ADDR ClassName,ADDR AppName,\
           DS_3DLOOK or DS_CENTER or DS_MODALFRAME or DS_SHELLFONT or WS_CAPTION or \
           WS_VISIBLE or WS_GROUP or WS_SYSMENU or WS_THICKFRAME, \
           0 , 0 ,400,400,NULL,NULL,\
           hInst,NULL

   .WHILE TRUE
      invoke GetMessage, ADDR msg,NULL,0,0
      .BREAK .IF !eax
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage, ADDR msg
   .ENDW
   mov     eax,msg.wParam
   ret
WinMain endp


GetYRelativeToParent proc Child:HWND
    LOCAL Parent:HWND
    LOCAL Point:POINT
   
    invoke GetParent,Child
    mov Parent, eax
    xor eax, eax
    mov Point.x, eax
    mov Point.y, eax
    invoke MapWindowPoints, Child, Parent, addr Point, 1
    mov eax, Point.y
   
    ret

GetYRelativeToParent endp


CenterHorizontal proc Child:HWND
    LOCAL Parent:HWND
    LOCAL Rect1:RECT
    LOCAL Rect2:RECT
   
    invoke GetParent, Child
    mov Parent, eax
    invoke GetClientRect, Parent, addr Rect1
    invoke GetWindowRect, Child, addr Rect2
    invoke GetYRelativeToParent, Child   
    mov edx, eax
    mov ecx, Rect1.right
    add ecx, Rect2.left
    sub ecx, Rect2.right
    sar ecx,1
    invoke SetWindowPos, Child, 0, ecx, edx, 0, 0, SWP_NOZORDER or SWP_NOSIZE
    ret

CenterHorizontal endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   
   .IF uMsg==WM_CREATE
        invoke CreateWindowEx, WS_EX_CLIENTEDGE ,addr cedit, NULL, WS_CHILD or WS_VISIBLE, \
        0, 40, 200, 200, hWnd, NULL, hInstance, NULL
       
        mov hedit, eax       
   .ELSEIF uMsg==WM_DESTROY
      invoke PostQuitMessage,NULL
      xor eax,eax
    .ELSEIF uMsg==WM_SIZING
      invoke CenterHorizontal,  hedit       
   .ELSEIF uMsg==WM_CREATE
      xor eax,eax
   .ELSE
      invoke DefWindowProc,hWnd,uMsg,wParam,lParam     
   .ENDIF
   ret

WndProc endp
end start



jj2007


rrr314159

Hello ArOn,

MapWindowPoints is not relevant here, you can center it by changing CenterHorizontal as follows:

;   invoke GetXRelativeToParent, Child    ; comment these two lines out
;   mov edx, eax
    mov edx, Rect1.bottom                      ; add these 4 lines
    add edx, Rect2.top
    sub edx, Rect2.bottom
    sar edx,1


The textbox starts out not centered, but it centers when you resize; I suppose you know what to do about that since it's not part of your question

[edit] jj, just read your post, I was wondering about that myself but changing it to Point.x is wrong. Apparently, MapWindowPoints not needed anyway
I am NaN ;)

Ar0n

Quote from: jj2007 on August 10, 2015, 05:28:37 PM
mov eax, Point.y

Sure?
Yeah, this function returns the Y value of the child window ( I noticed that I wrote "GetXRelativeToParent", sorry for the confusion, it should be "GetYRelativeToParent", I fixed it).

Quote from: rrr314159 on August 10, 2015, 05:29:56 PM
Hello ArOn,

MapWindowPoints is not relevant here, you can center it by changing CenterHorizontal as follows:

;   invoke GetXRelativeToParent, Child    ; comment these two lines out
;   mov edx, eax
    mov edx, Rect1.bottom                      ; add these 4 lines
    add edx, Rect2.top
    sub edx, Rect2.bottom
    sar edx,1


The textbox starts out not centered, but it centers when you resize; I suppose you know what to do about that since it's not part of your question

[edit] jj, just read your post, I was wondering about that myself but changing it to Point.x is wrong. Apparently, MapWindowPoints not needed anyway

well, clearing my question, I want to center a child window to its parent, but only horizontally, without moving the vertical position, so I need to get the Y coordinate that corresponds to the vertical posision then pass that value to SetWindowPos, that is why I use MapWindowPoints...


jj2007

Quote from: Ar0n on August 10, 2015, 05:57:44 PMwell, clearing my question, I want to center a child window to its parent, but only horizontally, without moving the vertical position, so I need to get the Y coordinate that corresponds to the vertical posision then pass that value to SetWindowPos, that is why I use MapWindowPoints...

It should look like this:

    invoke GetWindowRect, Child, addr Rect2
    deb 4, "y", eax, $Err$(), Rect2.top
    mov ecx, Rect1.right      ; full width parent
    add ecx, Rect2.left
    sub ecx, Rect2.right            ; minus width child
    sar ecx,1
    invoke SetWindowPos, Child, 0, ecx, Rect2.top, 0, 0, SWP_NOZORDER or SWP_NOSIZE


... but I've run into trouble: Rect2.top is way too high, 2000 and more ::)

Ar0n

Quote from: jj2007 on August 10, 2015, 07:35:52 PM

It should look like this:

    invoke GetWindowRect, Child, addr Rect2
    deb 4, "y", eax, $Err$(), Rect2.top
    mov ecx, Rect1.right      ; full width parent
    add ecx, Rect2.left
    sub ecx, Rect2.right            ; minus width child
    sar ecx,1
    invoke SetWindowPos, Child, 0, ecx, Rect2.top, 0, 0, SWP_NOZORDER or SWP_NOSIZE


... but I've run into trouble: Rect2.top is way too high, 2000 and more ::)

: error A2008: syntax error : integer:

deb 4, "y", eax, $Err$(), Rect2.top

is it me or? unable to build that code...

jj2007

Sorry, comment out the deb, it's MasmBasic.

I get rubbish values from invoke GetWindowRect, hedit, addr somerect, wherever I put it. Is it just me?
Win7-64

Ar0n

Quote from: jj2007 on August 10, 2015, 08:16:02 PM
Sorry, comment out the deb, it's MasmBasic.

I get rubbish values from invoke GetWindowRect, hedit, addr somerect, wherever I put it. Is it just me?
Win7-64
jj2007, GetWindowRect seems to work well to me :P same Win7-64

Edited:
Guys, I realized that if I remove WS_EX_CLIENTEDGE (CreateWindowEx), my code works perfectly!
any idea?  :icon_eek:  :icon_eek: :icon_eek: .MapWindowPoints returns the correct coordinates.

TouEnMasm

The WS_EX_CLIENTEDGE add a border to the window.
A border had a size not given by the windows API.
To know it play with GetWindowRect and GetclientRect on the same window handle.
The substract of the two will give the size of the border.

You have need also of the ScreenToClient
Fa is a musical note to play with CL

dedndave


jj2007

Quote from: Ar0n on August 10, 2015, 08:29:20 PMjj2007, GetWindowRect seems to work well to me :P same Win7-64
...
my code works perfectly!

Can you do me a favour and post source and exe? My GetWindowRect continues to return rubbish.

hutch--

You normally subtract the top X or Y from the bottom X or Y to get the size.

Ar0n



Quote from: jj2007 on August 10, 2015, 11:51:02 PM
Quote from: Ar0n on August 10, 2015, 08:29:20 PMjj2007, GetWindowRect seems to work well to me :P same Win7-64
...
my code works perfectly!

Can you do me a favour and post source and exe? My GetWindowRect continues to return rubbish.
I added it.

Quote from: ToutEnMasm on August 10, 2015, 09:57:33 PM
The WS_EX_CLIENTEDGE add a border to the window.
A border had a size not given by the windows API.
To know it play with GetWindowRect and GetclientRect on the same window handle.
The substract of the two will give the size of the border.

You have need also of the ScreenToClient

Yeah, that seems to be the solution :-P but it looks somewhat rustic... sorry if it would be the right way.

Quote from: dedndave on August 10, 2015, 11:00:44 PM
i thought we already did this, Aron - lol

http://masm32.com/board/index.php?topic=3994.msg42085#msg42085
dedndave, I need to center the child window horizontally. Yes, it seems that I just delete the part to center the window vertically but can not leave this value to zero, that's why I need the original coordinates.

Quote from: hutch-- on August 11, 2015, 12:25:45 AM
You normally subtract the top X or Y from the bottom X or Y to get the size.
hutch, I don't need the size of the child window, I need the coordinates relative to its parent...

Guys, at this point, I'm not sure if I'm implying my problem ... :-P



dedndave

not tested, but give it a try

we perform horizontal center, just as before (EBX)

then, we use ScreenToClient to convert the screen coordinates into client coordinates (left and top only)
we use the previous child top coordinate
and, we use the SWP_NOSIZE flag so that we do not have to calculate width or height

CenterChildHrz PROTO :HWND,:HWND
;
;
;
CenterChildHrz PROC USES EBX hWnd:HWND,hChild:HWND

    LOCAL   _rcClient   :RECT
    LOCAL   _rcChild    :RECT

    INVOKE  GetClientRect,hWnd,addr _rcClient
    INVOKE  GetWindowRect,hChild,addr _rcChild

    mov     ebx,_rcClient.right
    add     ebx,_rcChild.left
    sub     ebx,_rcChild.right
    sar     ebx,1

    INVOKE  ScreenToClient,hWnd,addr _rcChild.left

    xor     eax,eax
    INVOKE  SetWindowPos,hChild,eax,ebx,_rcChild.top,eax,eax,SWP_NOZORDER or SWP_NOSIZE
    ret

CenterChildHrz ENDP

rrr314159

Quote from: ArOnGuys, at this point, I'm not sure if I'm implying my problem ... :-P

- I'm glad u fixed your problem, assuming you're happy without the "clientedge" (works on my system also). I'm with jj2007, thought simply Rect2.top might do it, but the value is way off. Curious why, will look into it when I get to it ... or just wait for him to figure it out :biggrin:
I am NaN ;)