Modify ↓

#4112 new Feature Request

_WinAPI_MapWindowPoints addition

Reported by: MattyD Owned by:
Milestone: Component: Standard UDFs
Version: Severity: None
Keywords: Cc:

Description

Hey JP,

I thought this one would probably be a good candidate for an adding to WinAPIConv.au3. FWIW I've thrown in the $HWND_DESKTOP definition to service it, but its not really necessary. ​Microsoft Documentation.

Thanks,
Matt

Global Const $HWND_DESKTOP = 0

Func _WinAPI_MapWindowPoints($hWndFom, $hWndTo, $tPoints, $iCount)
    Local $aCall = DllCall("User32.dll", "int", "MapWindowPoints", "hwnd", $hWndFom, "hwnd", $hWndTo, "struct*", $tPoints, "int", $iCount)
    If @error Then Return SetError(@error, @extended, $aCall)
    Return $aCall[0]
EndFunc

Example: (I can simplify if need be.)

#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7

#include <WinAPI.au3>
#include <GuiConstants.au3>

Global $g_hMainWnd, $g_hChildWnd, $g_idWinPos, $g_idClientPos, $g_idButton

_Example()

Func _Example()
        GUIRegisterMsg($WM_MOVE, "MoveSize")
        GUIRegisterMsg($WM_SIZE, "MoveSize")

        $g_hMainWnd = GUICreate("Main Window", 500, 400, -1, -1, $WS_SIZEBOX)
        GUICtrlCreateLabel("Popup window's rect, relative to the top-left of the main window's client area.", 10, 10, 500, 20)
        $g_idWinPos = GUICtrlCreateLabel("", 10, 30, 500, 20)

        GUICtrlCreateLabel("Popup's window's client rect, relative to the top-left of the main window's client area.", 10, 55, 500, 20)
        $g_idClientPos = GUICtrlCreateLabel("", 10, 75, 500, 20)

        $g_hChildWnd = GUICreate("Popup Window", 200, 125, -1, -1, BitOR($WS_POPUP, $WS_CAPTION), 0, $g_hMainWnd)
        Local $sMsg = "The popup will re-position itself relative to its parent." & @CRLF & @CRLF & _
                 "Move or resize the parent window to trigger the action."
        GUICtrlCreateLabel($sMsg, 10, 10, 180, 80, $SS_CENTER)
        $g_idButton = GUICtrlCreateButton("Re-Center", 60, 90, 80, 25)

        GUISetState(@SW_SHOW, $g_hMainWnd)
        GUISetState(@SW_SHOW, $g_hChildWnd)

        While 1
                Switch GUIGetMsg()
                        Case $GUI_EVENT_CLOSE
                                ExitLoop
                        Case $g_idButton
                                PositionPopUpWindow($g_hChildWnd)
                EndSwitch
        WEnd

        GUIDelete($g_hChildWnd)
        GUIDelete($g_hMainWnd)
EndFunc

Func MoveSize($hWnd, $iMsg, $wParam, $lParam)

        Switch $hWnd
                Case $g_hMainWnd
                        PositionPopUpWindow($g_hChildWnd)
                        If $iMsg = $WM_SIZE Then UpdateLabels()

                Case $g_hChildWnd
                        UpdateLabels()

        EndSwitch

        Return _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func PositionPopUpWindow($hWnd)
        Local $hOwner = _WinAPI_GetWindow($hWnd, $GW_OWNER)

        Local $tWndPos = _WinAPI_GetWindowRect($hWnd)
        Local $iWndW =  DllStructGetData($tWndPos, "Right") - DllStructGetData($tWndPos, "Left")
        Local $iWndH =  DllStructGetData($tWndPos, "Bottom") - DllStructGetData($tWndPos, "Top")

        Local $tOwnerPos = _WinAPI_GetClientRect($hOwner)
        Local $iOwnerW =  DllStructGetData($tOwnerPos, "Right") - DllStructGetData($tOwnerPos, "Left")
        Local $iOwnerH =  DllStructGetData($tOwnerPos, "Bottom") - DllStructGetData($tOwnerPos, "Top")

        ; Position window
        ; (Convert point relative to main window -> screen coords)
        Local $tPoint = DllStructCreate($tagPOINT)
        DllStructSetData($tPoint, "X", ($iOwnerW - $iWndW)/2)
        DllStructSetData($tPoint, "Y", ($iOwnerH - $iWndH)/2)
        _WinAPI_MapWindowPoints($hOwner, 0, $tPoint, 1)

        _WinAPI_SetWindowPos($hWnd, $HWND_TOP, DllStructGetData($tPoint, "X"), DllStructGetData($tPoint, "Y"), _
                        0, 0, BitOR($SWP_NOSIZE, $SWP_NOZORDER, $SWP_SHOWWINDOW, $SWP_NOACTIVATE))
EndFunc

Func UpdateLabels()
        ; Popup window's non-client position relative to main window's client area.
        ; (Convert screen coords -> points relative to main window)
        Local $tWndPos = _WinAPI_GetWindowRect($g_hChildWnd)
        _WinAPI_MapWindowPoints(0, $g_hMainWnd, $tWndPos, 2)
        GUICtrlSetData($g_idWinPos, _
                StringFormat("Left: [ %4d ] Top: [ %4d ] Right: [ %4d ] Bottom: [ %4d ]", _
                DllStructGetData($tWndPos, "Left"), DllStructGetData($tWndPos, "Top"), _
                DllStructGetData($tWndPos, "Right"), DllStructGetData($tWndPos, "Bottom")))

        ; Popup window's client position relative to main window's client area.
        ; (Convert points relative to popup window -> points relative to main window)
        Local $tClientPos = _WinAPI_GetClientRect($g_hChildWnd)
        _WinAPI_MapWindowPoints($g_hChildWnd, $g_hMainWnd, $tClientPos, 2)
        GUICtrlSetData($g_idClientPos, _
                StringFormat("Left: [ %4d ] Top: [ %4d ] Right: [ %4d ] Bottom: [ %4d ]", _
                DllStructGetData($tClientPos, "Left"), DllStructGetData($tClientPos, "Top"), _
                DllStructGetData($tClientPos, "Right"), DllStructGetData($tClientPos, "Bottom")))
EndFunc

Func _WinAPI_MapWindowPoints($hWndFom, $hWndTo, $tPoints, $iCount)
    Local $aCall = DllCall("User32.dll", "int", "MapWindowPoints", "hwnd", $hWndFom, "hwnd", $hWndTo, "struct*", $tPoints, "int", $iCount)
    If @error Then Return SetError(@error, @extended, $aCall)
    Return $aCall[0]
EndFunc

Suggested Documentation:

###User Defined Function###
_WinAPI_MapWindowPoints

###Description###
Converts a set of points from a coordinate space relative to one window to a coordinate space relative to another window.

###Syntax###
#include <WinAPIConv.au3>
_WinAPI_MapWindowPoints( $hWndFom, $hWndTo, $tPoints, $iCount )

###Parameters###
@@ParamTable@@
$hWndFrom
	A handle to the window from which points are converted. If this parameter is 0 or $HWND_DESKTOP, the points are presumed to be in screen coordinates.
$hWndTo
	A handle to the window to which points are converted. If this parameter is 0 or $HWND_DESKTOP, the points are converted to screen coordinates.
$tPoints
	A struct containing an array of POINT structures that contain the set of points to be converted.
$iCount
	The number of POINTs in the $tPoints struct.
@@End@@

###ReturnValue###
@@ReturnTable@@
Success:	low-order word: The number of pixels added to the horizontal coordinate of each source point.
	high-order word: The number of pixels added to the vertical coordinate of each source point.
Failure:	0. Call _WinAPI_SetLastError prior to calling this method to differentiate an error return value from a legitimate "0" return value.
@@End@@

###Remarks###
If hWndFrom or hWndTo (or both) have the $WS_EX_LAYOUTRTL extended style and precisely two points are passed in $tPoints, _WinAPI_MapWindowPoints will interpret those two points as a RECT and possibly automatically swap the left and right fields of that rectangle to ensure that left is not greater than right. If you need to map precisely two independent points and don't want the RECT logic applied to them by _WinAPI_MapWindowPoints, you must call _WinAPI_MapWindowPoints with one POINT at a time.

###Related###
_WinAPI_ScreenToClient, _WinAPI_ClientToScreen

###Example###
@@IncludeExample@@

Attachments (0)

Change History (0)

Modify Ticket

Action
as new The ticket will remain with no owner.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.