News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Recent posts

#1
RosAsm / Re: IsChildWindow (For simple ...
Last post by guga - Today at 01:44:55 AM
Btw, i had to create this thing for an update i made on GetWindowPos. I updated an old RosAsm function, and now it is correctly retrieving the values in logical pixels. I also emulated a routine for DPI awareness. I tested all these functions during last night. It seems they are working, specially the GetWindowPos because my old version wasn´t returning the proper values. https://masm32.com/board/index.php?topic=12744.msg138665#msg138665
#2
The Orphanage / Re: The Adventures of Nugget
Last post by zedd - Today at 01:40:41 AM
Nugget continues in the pond...

Silly dog.  :joking:

We were mad at her, but also found it hilarious at the same time.
Sorry for the crappy quality, my sister made the video (out of my control)
#3
The Orphanage / Re: The Adventures of Nugget
Last post by zedd - Today at 01:39:11 AM
Nugget acting a fool in the pond.  :azn:

Thats Gypsy our lab chasing her.
Sorry for the crappy quality, my sister made the video (out of my control)
#4
RosAsm / Re: IsChildWindow (For simple ...
Last post by guga - Today at 01:29:09 AM
Hi Zedd

I did that yesterday. You can identify the child inside a child of a child and so on. Here is

https://masm32.com/board/index.php?topic=12742.0

What u have to do is basically search for it´s parents.

The 1st thing is work with 2 handles (as in the MS Ischild). One for the Parent windows (any parent) and other for the window itself from where u want to identify.

I started with 2 basic steps

I - Check for Validations

1 - Check if the parent handle is valid. If its not, then you exit the function.
    call 'USER32.IsWindow' D@hWndParent
    On eax = 0, ExitP
2 - Check if the handle of the window itself is working. If not, also exit the function.
    call 'USER32.IsWindow' D@hWnd
    On eax = 0, ExitP
3 - Validate the thread´s desktop to see if the window you want to check is, in fact, attached to anything in your desktop without any problems. This is how IsChild do internally, btw
    call 'kernel32.GetCurrentThreadId'
    call 'user32.GetThreadDesktop' eax
    On eax = 0, ExitP
4 - Finally try to validate the desktop window, to also see if everything is ok.
    ; Validate default desktop window
    call 'USER32.GetDesktopWindow'
    On eax = 0, ExitP

II - Start analyzing the window transversely, trying to hunt it´s parents.

1 - I 1st created a local variable containing the copy of the input hWnd, and named it as CurrentWnd, meaning this will be updated to be checked on each loop

Immediately inside the loop, the 1st thing to do is get the style of the window. Any child windows must contains, at least WS_CHILD flag. After you get the style you must AND the returned value from GetWindowLong (with GWL_STYLE) with the OR of WS_POPUP+WS_CHILD. This is the exact same behavior as the Api (ISChild) inside user32.dll
        ; Get window style
        call 'USER32.GetWindowLongA' D@CurrentWnd, &GWL_STYLE
        ; Check if window is a child: (style & (WS_POPUP | WS_CHILD)) == WS_CHILD
        and eax (&WS_POPUP+&WS_CHILD)   ; Bitwise OR for mask

If the resultant AND / OR operation is WS_CHILD only, then you are quite sure that your windows is a Child one. If the resultant comparison is not WS_CHILD, then, you can exit the loop (and the function with FALSE because the handle does not belongs to child.

2 - If the comparison is ok, you start getting the parent of the "CurrentWnd" Variable. (Remember, you are still inside the loop) If the returned value from GetParent is 0 your hWnd is also not a child and you can exit the function with FALSE.
If the resultant value (of CurrentWnd) is the same as the input hWndParent, then you found your child, and you can return TRUE, since the handle you are trying to analyze is definitely a child.
If the resultant value (of CurrentWnd) is not the same as the inputted Parent (hWndParent), then, you need to continue the loop

The loop routine is at:
    .While D@CurrentWnd <> 0
        ; Get window style
        call 'USER32.GetWindowLongA' D@CurrentWnd, &GWL_STYLE

        ; Check if window is a child: (style & (WS_POPUP | WS_CHILD)) == WS_CHILD
        and eax (&WS_POPUP+&WS_CHILD)   ; Bitwise OR for mask
        .If eax = &WS_CHILD
             ;  Get parent window
            Call 'USER32.GetParent' D@CurrentWnd
            mov D@CurrentWnd eax
            ; Check if parent is NULL
            On eax = 0, ExitP
            ; Check if parent matches hWndParent
            If eax = D@hWndParent
                mov eax &TRUE
                ExitP
            End_If
        .Else
            ; Not a child window, stop traversal
            xor eax eax
            ExitP
        .End_If


If after all iterations, the loops ends without finding anything, then, this is definitely not a child.

The whole function is this (The information) is on the link i posted.
Proc IsChild:
    Arguments @hWndParent, @hWnd
    Local @CurrentWnd, @Style
    Uses ecx, edx

    ; Validate input windows
    call 'USER32.IsWindow' D@hWndParent
    On eax = 0, ExitP
    call 'USER32.IsWindow' D@hWnd
    On eax = 0, ExitP

    ; Validate thread's desktop
    call 'kernel32.GetCurrentThreadId'
    call 'user32.GetThreadDesktop' eax
    On eax = 0, ExitP

    ; Validate default desktop window
    call 'USER32.GetDesktopWindow'
    On eax = 0, ExitP

    ; Initialize CurrentWnd = hWnd
    mov eax D@hWnd | mov D@CurrentWnd eax
    ; Traverse parent chain
    .While D@CurrentWnd <> 0
        ; Get window style
        call 'USER32.GetWindowLongA' D@CurrentWnd, &GWL_STYLE

        ; Check if window is a child: (style & (WS_POPUP | WS_CHILD)) == WS_CHILD
        and eax (&WS_POPUP+&WS_CHILD)   ; Bitwise OR for mask
        .If eax = &WS_CHILD
             ;  Get parent window
            Call 'USER32.GetParent' D@CurrentWnd
            mov D@CurrentWnd eax
            ; Check if parent is NULL
            On eax = 0, ExitP
            ; Check if parent matches hWndParent
            If eax = D@hWndParent
                mov eax &TRUE
                ExitP
            End_If
        .Else
            ; Not a child window, stop traversal
            xor eax eax
            ExitP
        .End_If

    .End_While

    ; Default return FALSE
    xor eax eax

EndP
#5
16 bit DOS Programming / Re: Problem With Reading Keybo...
Last post by jejump - Today at 12:05:29 AM
Reading port 64h bit 0 was the answer!!  I guess I misled myself originally to believe I had to poll port 20h bit 1 because there was no interrupt connectivity after applying the mask and that would be my only way of detecting keyboard activity.  Turns out I don't need to do that.  I also eliminated the EOI on the interrupt and DMA hardware.

Thanks for helping!!   :thumbsup:
#6
RosAsm / Re: IsChildWindow (For simple ...
Last post by zedd - April 23, 2025, 11:30:54 PM
What about for when a window on the desktop has a dialog box open which has several controls. How does it deal with "grandchildren" Windows? (Child of a child), or even (child of a child of a child)?  :biggrin:  Of course I don't use rosasm, but just wondering if you had considered those scenarios.
#7
RosAsm / IsChildWindow (For simple iden...
Last post by guga - April 23, 2025, 11:15:49 PM
Hi guys, i made a simpler variation of mine IsChild function here. This is also based on the core that exists in User32.dll but tweaked to ensure a more wide scenario (multiple desktops, for example).


;;
  IsChildWindow
  Determines whether a window is a child window by checking for a valid parent
  and the WS_CHILD style.

  Arguments:
    hWnd (in): Handle to the window to test.

  Return Value:
    Returns TRUE (1) if hWnd is a child window (has WS_CHILD style and a valid parent).
    Returns FALSE (0) if hWnd is not a child window (e.g., top-level, popup, invalid handle,
    or no parent).

  Remarks:
    - General-purpose function for checking child window status, similar to IsChildForWindowPos
      but with full validations for standalone use.
    - Uses GetAncestor to retrieve the immediate parent window.
    - Validates window handles, thread desktop, and default desktop for robustness.
    - Checks WS_CHILD style (and not WS_POPUP) via GetWindowLongA.
    - Unlike IsChild, does not check for a specific parent-child or descendant relationship,
      making it simpler and single-argument.
    - Preserves ECX and EDX registers as per calling convention.
    - Suitable for scenarios like GetWindowPosEx (to choose GetClientRect vs. GetWindowRect)
      or other checks for child window status.

  Author: Gustavo Trigueiros (aka: Beyond2000!)
  Build Date: April 2025 (v1.0)
;;

Proc IsChildWindow:
    Arguments @hWnd
    Local @CurrentWnd, @Style, @hWndParent
    Uses ecx, edx

    ; Validate input windows
    ; Ensures hWnd is a valid window to prevent crashes or invalid operations
    call 'USER32.IsWindow' D@hWnd
    On eax = 0, ExitP

    ; Get parent or owner window
    ; GA_PARENT retrieves the immediate parent (e.g., dialog for a button)
    ; Returns NULL for top-level or popup windows, which aren't children
    Call 'USER32.GetAncestor' D@hWnd, &GA_PARENT
    On eax = 0, ExitP
    mov D@hWndParent eax

    ; Validate parent window handle
    ; Ensures the parent is a valid window, as GetAncestor may return a stale handle
    call 'USER32.IsWindow' D@hWndParent ; is the parent also a window ?
    On eax = 0, ExitP

    ; Validate thread's desktop
    ; Ensures the current thread has a valid desktop context
    call 'kernel32.GetCurrentThreadId'
    call 'user32.GetThreadDesktop' eax
    On eax = 0, ExitP

    ; Validate default desktop window
    ; Ensures the desktop window is accessible, for robustness in multi-desktop scenarios
    call 'USER32.GetDesktopWindow'
    On eax = 0, ExitP

    ; Check window style to determine if hWnd is a child
    ; GetWindowLongA retrieves GWL_STYLE, which includes WS_CHILD or WS_POPUP flags
    Call 'USER32.GetWindowLongA' D@hWnd, &GWL_STYLE
    ; Mask style to check for WS_CHILD (and not WS_POPUP)
    ; WS_CHILD indicates a child window; WS_POPUP indicates a non-child
    and eax (&WS_POPUP+&WS_CHILD)
    If eax = &WS_CHILD
        ; hWnd has WS_CHILD and a valid parent, so it's a child window
        mov eax &TRUE
    Else
        ; hWnd is not a child window (e.g., popup, top-level, or invalid style)
        xor eax eax
    End_If

EndP
#8
RosAsm / GetWindowPos function
Last post by guga - April 23, 2025, 11:10:57 PM
Hi Guys, i made a specialized function to retrieve the windows position (x, y, width and height) outputting the value as Logical pixels.

General Info
;;
    GetWindowPos v 1.2
        Retrieves the position and size of a window, adjusted for DPI scaling, in physical pixels.
        Returns coordinates relative to the parent's client area (for child windows) or screen/owner
        coordinates (for non-child windows), with border adjustments for child windows. Compatible
        with Windows XP, 7, and later, using system DPI for scaling.

  Arguments:
    hWnd (in): Handle to the window (child, top-level, dialog, control, etc.).
    PosStruct (out): Pointer to a WINPOS structure to receive the position and size.
                     The output values of WINPOS (cx, cy, width, height) are in logical pixels.

  Return Value:
    For child windows: Returns the parent window handle (hParent) on success.
    For non-child windows: Returns TRUE (1) on success.
    Returns 0 on failure (invalid hWnd, PosStruct, or system errors).

  WINPOS Structure:
    [WINPOS:
     WINPOS.cx: D$ 0      ; x-coordinate of the window's upper-left corner (pixels). The value can also be negative. See Remarks
     WINPOS.cy: D$ 0      ; y-coordinate of the window's upper-left corner (pixels). The value can also be negative. See Remarks
     WINPOS.width: D$ 0   ; Width of the window (pixels).
     WINPOS.height: D$ 0]  ; Height of the window (pixels).
    - Child windows: cx, cy are relative to the parent's client area, adjusted for borders;
      width, height are client dimensions.
    - Non-child windows: cx, cy are in screen coordinates (hParent = NULL) or owner's
      client coordinates (hParent = owner), no border adjustment; width, height include borders.

  Remarks:
    - Enhanced version of GetWindowPos to handle child and non-child windows with DPI awareness.
    - Uses GetClientRect for child windows, GetWindowRect for non-child windows.
    - Converts coordinates to parent's client area (child) or screen/owner (non-child) using MapWindowPoints.
    - Adjusts child window coordinates for borders using WINDOWINFO.cxWindowBorders, cyWindowBorders.
    - All coordinates and borders are in logical pixels before SSE2 scaling.
    - Scales coordinates and sizes to physical pixels using system DPI from GetDeviceCaps,
      ensuring compatibility with Windows XP and 7 (no GetDpiForWindow or manifest required).
    - Uses SSE2 to vectorize DPI scaling (ratio = Dpi / 96) for performance, with rounding to nearest.
    - Borders are subtracted in logical pixels before scaling; SSE2 scaling (mulps) applies DPI ratio
      to adjusted coordinates (e.g., cx = 10 - 2 = 8, then 8 * 1.5 = 12), correctly accounting for
      border's effect in physical pixels (e.g., 2 * 1.5 = 3).
    - No separate border scaling is needed, as WINPOS and borders are both in logical pixels.
    - Assumes System DPI Awareness (default without manifest), using primary monitor's DPI.
    - Does not support per-monitor DPI (unavailable on XP/7); all windows use system DPI.
    - Uses LOGPIXELSX for DPI scaling, as X and Y DPI are equal in standard Windows configurations.
    - Color depth experiments (e.g., (16M >> 8) & 511 = 36) are unrelated to DPI; GetDeviceCaps provides accurate DPI.
    - Validates window handles, thread desktop, and default desktop for robustness.
    - Preserves ECX and EDX registers as per calling convention.
    - Uses PosStruct directly for rectangle operations, eliminating temporary buffers.
    - Returns physical pixels for cx, cy, width, height, suitable for precise rendering or positioning.
    - Fallback to no scaling (Dpi = 96) if DPI retrieval fails.

  Usage Example:
    [WINPOS:
     WINPOS.cx: D$ 0
     WINPOS.cy: D$ 0
     WINPOS.width: D$ 0
     WINPOS.height: D$ 0]
    call 'USER32.GetDlgItem' D@hDlg, 156  ; Get control handle
    call GetWindowPosEx eax, WINPOS
    If eax = 0
        ; Handle failure
    Else_If eax = 1
        ; Non-child window, use WINPOS
    Else
        ; Child window, eax = hParent, use WINPOS and parent
    End_If

    Notes:
            Negative values for cx and cy - Why and When cx and cy Can Be Negative ?

            The cx and cy values in the WINPOS structure come from the left and top fields of the temporary Rect (a WINPOS structure)
            after MapWindowPoints transforms coordinates. Negative values arise when the window's top-left corner is positioned
            to the left or above the origin (0,0) of the target coordinate system. The target coordinate system depends on the window type:
                * Child windows: Parent's client coordinates (origin at the top-left of the parent's client area).
                " Non-child windows: Screen coordinates (hParent = NULL) or owner's client coordinates (hParent = owner).
               
                Here are some specific situations for each case, including whether dragging a window off the desktop contributes.

                1. Child Windows
                    * How MapWindowPoints Works:
                        * GetClientRect(hWnd, @Rect) sets @Rect to {left: 0, top: 0, right: client_width, bottom: client_height}
                          (client coordinates of hWnd).
                        * MapWindowPoints(hWnd, hParent, @Rect, 2) converts the points (left, top) and (right, bottom) from
                            hWnd's client coordinates to hParent's client coordinates.
                        * The parent's client area has its origin (0,0) at the top-left of its client area (excluding the parent's
                          borders, title bar, etc.).
                        * If hWnd's client area is positioned left or above the parent's client area origin, left (cx) or top (cy) become negative.
                    * Situations:
                        * Negative Positioning in Dialogs: In dialog-based applications, a child control (e.g., an edit box) can
                          be placed at a negative position relative to the dialog's client area. This is common in dialog templates
                          or dynamic layouts where controls are offset for visual effects or alignment.
                        * Example: A dialog template (in a .rc file) defines an edit control at
                                   CONTROL "Edit", IDC_EDIT, "EDIT", WS_CHILD, -10, -5, 100, 20.
                        * The edit control's client area top-left is at (-10, -5) in the dialog's client coordinates.
                        * After MapWindowPoints, @Rect.left = -10, @Rect.top = -5, so cx = -10, cy = -5.
                        * Border adjustment (e.g., cxWindowBorders = 2) makes it more negative: cx = -10 - 2 = -12.
                     * Dynamic Positioning:
                          If code programmatically moves a child window using SetWindowPos(hWnd, NULL, -10, -5, width, height, SWP_NOZORDER),
                          the child's position becomes negative relative to the parent's client area.
                        * Parent Scrolling: In a scrollable parent (e.g., a dialog with a scrollable client area), a child control's
                          position may appear negative when the parent is scrolled, shifting the child's relative position above or
                          left of the visible client area origin.
                     * Dragging Off Desktop?:
                        * Not Applicable:
                            Child windows (e.g., controls in a dialog) cannot be dragged by the user, as they are
                            fixed within the parent's client area. Negative cx, cy for child windows result from deliberate positioning
                            (via dialog templates or SetWindowPos), not user interaction like dragging.
                     * Visualization:
                        * Imagine a dialog's client area as a canvas starting at (0,0). If an edit control is placed at (-10, -5),
                          its top-left corner is outside the dialog's client area (to the left and above). This is valid in Windows
                          and results in negative cx, cy.
                2. Non-Child Windows
                    " How MapWindowPoints Works:
                        * GetWindowRect(hWnd, @Rect) sets @Rect to {left, top, right, bottom} in screen coordinates (entire window, including borders).
                        * MapWindowPoints(0, hParent, @Rect, 2) converts these screen coordinates to:
                            " Screen coordinates (if hParent = NULL): No change, but negative values are possible from GetWindowRect.
                            " Owner's client coordinates (if hParent is an owner window).
        Conclusion
            * Can cx, cy Be Negative?: Yes, for both child and non-child windows.
            * Situations:
            * Child Windows: Negative positions in dialog templates, programmatic SetWindowPos to negative coordinates,
                             or scrollable parent offsets. Not from dragging, as child windows are fixed.
            * Non-Child Windows: Multi-monitor setups (secondary monitor with negative coordinates), popups above/left of an
                                 owner's client area, or dragging/programmatic positioning off the primary monitor's left/top edge.
                                 Dragging off desktop is a valid case for top-level windows.



  Author: Gustavo Trigueiros (aka: Beyond2000!/Guga)
  Build Date: May 2012 (v1.0), Updated April 2025 (v1.4)
;;

Function

[DpiAdjust: F$ (1/96)]

Proc GetWindowPos::
    Arguments @hWnd, @PosStruct
    Local @hParent, @IsChild, @Dpi, @hDC, @AdjustForDpi, @Return
    Structure @WINDOWINFO 96,  @WINDOWINFO.cbSizeDis 0,  @WINDOWINFO.rcWindow_leftDis 4,  @WINDOWINFO.rcWindow_topDis 8,
                               @WINDOWINFO.rcWindow_rightDis 12,  @WINDOWINFO.rcWindow_bottomDis 16,  @WINDOWINFO.rcClient_leftDis 20,
                               @WINDOWINFO.rcClient_topDis 24,  @WINDOWINFO.rcClient_rightDis 28,  @WINDOWINFO.rcClient_bottomDis 32,
                               @WINDOWINFO.dwStyleDis 36,  @WINDOWINFO.dwExStyleDis 40,  @WINDOWINFO.dwWindowStatusDis 44,  @WINDOWINFO.cxWindowBordersDis 48,
                               @WINDOWINFO.cyWindowBordersDis 52,  @WINDOWINFO.atomWindowTypeDis 56,  @WINDOWINFO.wCreatorVersionDis 58,
                               @XMMReg0Dis 62, @XMMReg1Dis 78
    Uses ecx, edx

    ; Preserve XMM registers efficiently
    movdqu X@XMMReg0Dis XMM0
    movdqu X@XMMReg1Dis XMM1

    xor eax eax
    On D@hWnd = 0, ExitP
    On D@PosStruct = 0, ExitP

    ; Validate thread's desktop
    Call 'KERNEL32.GetCurrentThreadId'
    Call 'USER32.GetThreadDesktop' eax
    On eax = 0, ExitP

    ; Validate default desktop window
    Call 'USER32.GetDesktopWindow'
    On eax = 0, ExitP

    ; Validate window handle
    Call 'USER32.IsWindow' D@hWnd
    On eax = 0, ExitP

    ; Get parent or owner window
    Call 'USER32.GetAncestor' D@hWnd, &GA_PARENT
    mov D@hParent eax

    ; Validate parent handle (NULL is valid for top-level windows)
    If D@hParent <> 0
        Call 'USER32.IsWindow' D@hParent
        On eax = 0, ExitP
    End_If

    ; Get system DPI for scaling
    ; Use GetDeviceCaps on primary monitor's DC (hDC = NULL) to get LOGPIXELSX
    ; Default to 96 (100% scaling) if retrieval fails
    mov D@Dpi 96
    Call 'user32.GetDC' &NULL
    mov D@hDC eax
    If eax <> 0
        Call 'GDI32.GetDeviceCaps' D@hDC, &LOGPIXELSX ; No need to calculate for LOGPIXELSY, since they are basically the same
        If eax <> 0
            mov D@Dpi eax
        End_If
        call 'user32.ReleaseDC' &NULL, D@hDC
    End_If

    ; get a ratio for be fast. x*dpi/96 = x*Ratio, where ratio = Dpi/96
    mov D@AdjustForDpi &FALSE
    If D@dpi <> 96 ; If dpi is not 96, then we need to compute a ratio
        movss xmm0 X$DpiAdjust
        cvtsi2ss xmm1 D@Dpi ; converts a signed integer to double
        mulss xmm1 xmm0 | pshufd xmm1 xmm1 SSE_FILL_DWORDS ; our ratio is now in the 4 dwords of the xmm1 register
        mov D@AdjustForDpi &TRUE
    End_If

    ; Check if this is a child window
    call IsChildForWindowPos D@hParent, D@hWnd
    mov D@IsChild eax
    If eax = 0
        ; Non-child window: Get window rect and convert to parent/owner coords. Since we use the the same structure we need to correct the size here
        call 'USER32.GetWindowRect' D@hWnd, D@PosStruct
        mov ecx D@PosStruct
        mov eax D$ecx+WINPOS.widthDis | sub eax D$ecx+WINPOS.cxDis | mov D$ecx+WINPOS.widthDis eax  ; width = right - left
        mov eax D$ecx+WINPOS.heightDis | sub eax D$ecx+WINPOS.cyDis | mov D$ecx+WINPOS.heightDis eax  ; height = bottom - top
        ; and now we an pass to MapWindowPoints get cx and cy - which can be negative
        call 'USER32.MapWindowPoints' 0, D@hParent, D@PosStruct, 2 ; values will be converted to logical pixels
    Else
        ; Child window: Get client rect and convert to parent coords
        call 'USER32.GetClientRect' D@hWnd, D@PosStruct
        mov ecx D@PosStruct
        mov eax D$ecx+WINPOS.widthDis | sub eax D$ecx+WINPOS.cxDis | mov D$ecx+WINPOS.widthDis eax  ; width = right - left
        mov eax D$ecx+WINPOS.heightDis | sub eax D$ecx+WINPOS.cyDis | mov D$ecx+WINPOS.heightDis eax  ; height = bottom - top
        ; and now we an pass to MapWindowPoints get cx and cy - which can be negative. values will be converted to logical pixels
        call 'USER32.MapWindowPoints' D@hWnd, D@hParent, D@PosStruct, 2
    End_If

    ; Adjust for borders only for child windows
    If D@IsChild = &TRUE
        call 'RosMem.FastZeroMem' D@WINDOWINFO, 64 ; Size_of_WINDOWINFO is, in fact 64 bytes nd not 60
        mov D@WINDOWINFO.cbSizeDis 64
        call 'USER32.GetWindowInfo' D@hWnd, D@WINDOWINFO ; the information retrieved is also in logical pixels
        mov ecx D@PosStruct
        mov eax D@WINDOWINFO.cxWindowBordersDis | sub D$ecx+WINPOS.cxDis eax  ; adjust X for borders
        mov eax D@WINDOWINFO.cyWindowBordersDis | sub D$ecx+WINPOS.cyDis eax  ; adjust Y for borders
        mov eax D@hParent ; Also sucess, but we return the hParent, instead of &TRUE. So you can kow that hwnd is a child windows
    Else
        mov eax &TRUE ; On sucess, and if hWnd is a window, returns &TRUE
    End_If
    mov D@Return eax

    If D@AdjustForDpi = &TRUE
        mov ecx D@PosStruct
        movdqu xmm0 X$ecx | SSE_CONV_4INT_TO_4FLOAT xmm0 | mulps xmm0 xmm1 | SSE_CONV_4FLOAT_TO_4INT_ROUND xmm0 | movdqu X$ecx xmm0
    End_If

    mov eax D@Return

    ; Restore XMM registers
    movdqu XMM0 X@XMMReg0Dis
    movdqu XMM1 X@XMMReg1Dis

EndP


Function helper

;;
  IsChildForWindowPos
  Specialized version of IsChild for use with GetWindowPosEx. Determines whether a window
  is a child or descendant of a specified parent window, assuming input validation is done
  by the caller.
 
  Arguments:
    hWndParent (in): Handle to the potential parent window (may be NULL for top-level windows).
    hWnd (in): Handle to the window to test (assumed valid).
 
  Return Value:
    Returns TRUE (1) if hWnd is a child or descendant of hWndParent.
    Returns FALSE (0) if:
      - hWndParent is NULL or invalid.
      - hWnd is not a child window (lacks WS_CHILD style or has WS_POPUP).
      - The parent chain ends without reaching hWndParent.
 
  Remarks:
    - Optimized for GetWindowPosEx, which validates hWnd, hWndParent, and desktop context.
    - Skips redundant IsWindow, GetThreadDesktop, and GetDesktopWindow checks.
    - Traverses the parent chain using GetParent until hWndParent is found or a non-child
      window is encountered.
    - Preserves ECX and EDX registers.
    - Assumes hWnd is valid (checked by GetWindowPosEx) and hWndParent is either valid,
      NULL, or invalid (checked before traversal).
 
  Author: Gustavo Trigueiros (aka: Beyond2000!)
  Build Date: April 2025 (v1.0)
;;

Proc IsChildForWindowPos:
    Arguments @hWndParent, @hWnd
    Local @CurrentWnd, @Style
    Uses ecx, edx

    ; Initialize return value
    xor eax eax
    On D@hWndParent = 0, ExitP

    ; Initialize CurrentWnd = hWnd
    mov eax D@hWnd | mov D@CurrentWnd eax
    ; Traverse parent chain
    .While D@CurrentWnd <> 0
        ; Get window style
        call 'USER32.GetWindowLongA' D@CurrentWnd, &GWL_STYLE

        ; Check if window is a child: (style & (WS_POPUP | WS_CHILD)) == WS_CHILD
        and eax (&WS_POPUP+&WS_CHILD)   ; Bitwise OR for mask
        .If eax = &WS_CHILD
             ;  Get parent window
            Call 'USER32.GetParent' D@CurrentWnd
            mov D@CurrentWnd eax
            ; Check if parent is NULL
            On eax = 0, ExitP
            ; Check if parent matches hWndParent
            If eax = D@hWndParent
                mov eax &TRUE
                ExitP
            End_If
        .Else
            ; Not a child window, stop traversal
            xor eax eax
            ExitP
        .End_If

    .End_While

    ; Default return FALSE
    xor eax eax

EndP


Macros used:

[SSE_FILL_DWORDS 0]         ; Fill all 4 Dwords in a xmm register with the value of the 1st Dword. So, we are copying the 1st Dword to all others 3
                            ; Ex: mov al 053 | imul eax eax 01010101 | movd xmm1 ax | pshufd xmm1 xmm1 SSE_FILL_DWORDS ; the contents of each one of all 8 words in xmm1 will be 053


[pshufd | pshufd #1 #2 #3]

[SSE_ABS_REAL4 | pslld #1 1 | psrld #1 1] ; pslld xmm1 1 | psrld xmm1 1
[SSE_CONV_4INT_TO_4FLOAT | cvtdq2ps #1 #1] ; pslld xmm1 1 | psrld xmm1 1 cvtdq2ps xmm1 xmm1
[SSE_FIND_REAL4_MAX | pshufd xmm7 #1 SSE_SWAP_DWORDS | maxps #1 xmm7 | pshufd xmm7 #1 SSE_INVERT_DWORDS | maxps #1 xmm7]
[SSE_CONV_4FLOAT_TO_4INT | cvttps2dq #1 #1]; Convert four floats to integers (truncate)
[SSE_CONV_4FLOAT_TO_4INT_ROUND | cvtps2dq #1 #1] ; Convert four floats to integers (round to nearest)

#9
Miscellaneous Projects / Re: PDB Dumper (Ported to C)
Last post by guga - April 23, 2025, 09:42:28 PM
Tks Timo. I´ll compare it wit the one i have for msdia120

Do u want me to send to you the sdk ?
#10
16 bit DOS Programming / Re: Problem With Reading Keybo...
Last post by jejump - April 23, 2025, 09:06:01 PM
Excellent information here!  I'm going to change the method of how I detect a key press to reading port 64h.  I wondered about the mouse hardware maybe causing conflict even though I don't have a mouse driver loaded.  Thanks for the tips!