Jump to content

Program crashing when I change which window is in focus.


Recommended Posts

Good evening,

I wrote a short program intended to help me determine Control IDs, but it crashes when I change the window focus to anything else.

#include <GUIConstants.au3>
#include <Array.au3>

Opt("GUIOnEventMode", 1)

GUICreate("ControlID Decoder",300,115)
    GUISetFont(12)
    GUISetOnEvent($GUI_EVENT_CLOSE, "Decoder_Events")
    GUISetOnEvent($GUI_EVENT_MINIMIZE, "Decoder_Events")
    GUISetOnEvent($GUI_EVENT_RESTORE, "Decoder_Events")
    Global $Window_Label = GUICtrlCreateLabel("Active Window:",5,5,290,24)
    Global $ControlID_Label = GUICtrlCreateLabel("ControlID:",5,32,290,24)
    Global $X_Coord_Label = GUICtrlCreateLabel("X:",5,59,290,24)
    Global $Y_Coord_Label = GUICtrlCreateLabel("Y:",5,86,290,24)
GUISetState(@SW_SHOW)

While 1
    Sleep(100)
    Local $Cursor_Info_Array = GUIGetCursorInfo("[active]")
    Local $Active_Window_Title = WinGetTitle("[active]")
    GUICtrlSetData($Window_Label, "Active Window: " & $Active_Window_Title)
    GUICtrlSetData($ControlID_Label, "ControlID: " & $Cursor_Info_Array[4])
    GUICtrlSetData($X_Coord_Label, "X: " & $Cursor_Info_Array[0])
    GUICtrlSetData($Y_Coord_Label, "Y: " & $Cursor_Info_Array[1])
WEnd

Func Decoder_Events()
   Select
      Case @GUI_CtrlId = $GUI_EVENT_CLOSE
         Exit
      Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
      Case @GUI_CtrlId = $GUI_EVENT_RESTORE
   EndSelect
EndFunc

If I comment out the CUICtrlSetData lines which contain $Cursor_Info_Array, the program does not crash.

Scite doesn't seem to find any errors.

Any ideas what I did wrong?

Link to comment
Share on other sites

Hi baconaise
As you're not testing a possible @error returned by GUIGetCursorInfo, then I suggest this :

#include <GUIConstants.au3>
#include <Array.au3>

Opt("GUIOnEventMode", 1)

Local $hGUI = GUICreate("ControlID Decoder",300,115, -1, -1, -1, $WS_EX_TOPMOST)
GUISetFont(12)
GUISetOnEvent($GUI_EVENT_CLOSE, "Decoder_Events")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "Decoder_Events")
GUISetOnEvent($GUI_EVENT_RESTORE, "Decoder_Events")

Global $Window_Label = GUICtrlCreateLabel("Active Window:",5,5,290,24)
Global $ControlID_Label = GUICtrlCreateLabel("ControlID:",5,32,290,24)
Global $X_Coord_Label = GUICtrlCreateLabel("X:",5,59,290,24)
Global $Y_Coord_Label = GUICtrlCreateLabel("Y:",5,86,290,24)

GUISetState(@SW_SHOW)

While 1
    Sleep(100)
    Local $Cursor_Info_Array = GUIGetCursorInfo($hGUI)
    ; If Not @error Then
        Local $Active_Window_Title = WinGetTitle("[active]")
        GUICtrlSetData($Window_Label, "Active Window: " & $Active_Window_Title)
        GUICtrlSetData($ControlID_Label, "ControlID: " & $Cursor_Info_Array[4])
        GUICtrlSetData($X_Coord_Label, "X: " & $Cursor_Info_Array[0])
        GUICtrlSetData($Y_Coord_Label, "Y: " & $Cursor_Info_Array[1])
    ; EndIf
WEnd

Func Decoder_Events()
   Select
      Case @GUI_CtrlId = $GUI_EVENT_CLOSE
         Exit
      Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
      Case @GUI_CtrlId = $GUI_EVENT_RESTORE
   EndSelect
EndFunc

Does it solve your issue ?

Link to comment
Share on other sites

Hi pixelsearch,

That prevents the program from crashing when I switch windows, but it does not provide me GUIGetCursorInfo for any new windows I click. Given that I was intending to use this program to identify ControlIDs of other windows, I can't say it solves my issue.

Thank you for trying.

Link to comment
Share on other sites

 

46 minutes ago, baconaise said:

but it does not provide me GUIGetCursorInfo for any new windows I click.

Hi @baconaise  Just i saw in help  https://www.autoitscript.com/autoit3/docs/functions/GUIGetCursorInfo.htm

The mouse cursor position is successful only on an window created by a GUICreate(). When no winhandle it will be successful if the GUI Windows is active.

that doesn't pass with   GUIGetCursorInfo("[active]")  

I know that I know nothing

Link to comment
Share on other sites

Link to comment
Share on other sites

@Nine do you think the following script could be used as a 1st step ?
It's based on your idea of using  _WinAPI_WindowFromPoint() to retrieve any handle found at cursor position.

; 1st script
; ==========

#include <GDIPlus.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt('MustDeclareVars', 1)
HotKeySet("{ESC}", "_Quit") ; <===================
Global $hGUI, $hGraphic, $hPen

_Main()

Func _Main()
    Local $aMPos, $aWPos, $hWnd = 0, $hWnd_Old = -1

    ; Create a transparent GUI covering the desktop
    $hGUI = GUICreate("GDI+", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
    GUISetBkColor(0xABCDEF)
    _WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF)

    ; Create a structure that defines any point to be checked.
    Local $tPoint = DllStructCreate($tagPOINT)

    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hPen = _GDIPlus_PenCreate(0xFFFF0000, 4) ; alpha channel = 0xFF (opaque), red = 0xFF0000, width = 4 (pixels)

    GUISetState(@SW_SHOW, $hGUI)

    While 1
        $aMPos = MouseGetPos()
        DllStructSetData($tPoint, "x", $aMPos[0])
        DllStructSetData($tPoint, "y", $aMPos[1])
        $hWnd = _WinAPI_WindowFromPoint($tPoint)
        If $hWnd <> $hWnd_Old Then
            ; _WinAPI_RedrawWindow($hGUI) ; works with AutoIt 3.3.14.5, not with 3.3.16.1
            ; e.g.
            ; _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE) ; flags 0x01 + 0x04 (default)

            ; _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE + $RDW_UPDATENOW) ; works with both versions of AutoIt
            ; _WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE + $RDW_ERASENOW)  ; works with both versions of AutoIt

            _GDIPlus_GraphicsClear($hGraphic, 0xFFABCDEF) ; Nine's way (works with both versions of AutoIt)

            $aWPos = WinGetPos($hWnd)
            _GDIPlus_GraphicsDrawRect($hGraphic, $aWPos[0], $aWPos[1], $aWPos[2], $aWPos[3], $hPen)
            ; ToolTip("Ctrl ID = " & _WinAPI_GetDlgCtrlID($hWnd)) ; shouldn't be used for top-level windows
            $hWnd_Old = $hWnd
        EndIf
        Sleep(10)
    WEnd
EndFunc   ;==>_Main

Func _Quit()
    ; Clean up resources
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_ShutDown()
    GUIDelete($hGUI)
    Exit
EndFunc   ;==>_Quit

 

Edited by pixelsearch
Reworked the flags of _WinAPI_RedrawWindow so the script runs on AutoIt 3.3.14.5 and 3.3.16.1 . Added Nine's way too.
Link to comment
Share on other sites

@pixelsearch  Nice job.  Only thing with my setup (Win7, non-aero), the rectangle is only flashing a fraction of a second. 

Replacing _WinAPI_RedrawWindow with _GDIPlus_GraphicsClear solves the issue.

Link to comment
Share on other sites

Houston, we have a problem :D

The script from my precedent post runs differently, depending on the version of AutoIt we use :

1) AutoIt version 3.3.14.5 (2018) => result ok :

1939171849_3.3_14_5ok.png.cbd3a80baf41cf46999eb541b753e40f.png

The red rectangle drawn by the script appears clearly, stable, solid, and it will stay like this until the mouse hovers another window, then another red rectangle will surround the new window.

2) AutoIt versions 3.3.15.1 beta (2020) until AutoIt version 3.3.16.1 stable (2022) : result not ok :

574202144_3.3_16.1notok.png.6e02e18136d617ebdf93b9b7094c8ee7.png

The red rectangle appears briefly, then disappears immediately, even when the mouse doesn't move (Nine uses AutoIt version 3.3.16.1 and noticed this behavior in his precedent post)

2 hours ago, Nine said:

Replacing _WinAPI_RedrawWindow with _GDIPlus_GraphicsClear solves the issue.

Sorry but I didn't find the way to make this change as the screen goes immediately black (or white) depending on the color used in _GDIPlus_GraphicsClear() during the loop. Could you please indicate the new line(s) that worked for you ?
Thanks

@jpm in case you read this, if you still have the stable version of AutoIt 3.3.14.5 (2018), could you please confirm there's something wrong, then I'll open a Trac ticket pointing to this post ?

For the record, I already compared a couple of functions in both AutoIt versions (_WinAPI_RedrawWindow etc...) but didn't notice anything special. Also, the help file which indicates the changes between versions (including beta versions) doesn't show anything special (though I checked it maybe too quickly)

Link to comment
Share on other sites

I just experimented the flags of _WinAPI_RedrawWindow() and found this :

* Their value is 5 by default, e.g. $RDW_INVALIDATE (0x0001) + $RDW_ERASE (0x0004) .

* As 0x0001 + 0x0004 works fine with AutoIt 3.3.14.5 then I started to add blindly another value when running the script with AutoIt 3.3.16.1, bingo !

* If you add $RDW_UPDATENOW (0x0100) or if you add $RDW_ERASENOW (0x0200) then it works fine with both versions of AutoIt

@Nine could you please test it with your version of AutoIt 3.3.16.1 and share your results ?

_WinAPI_RedrawWindow($hGUI, 0, 0, 0x0001 + 0x0004 + 0x0100)
; or
_WinAPI_RedrawWindow($hGUI, 0, 0, 0x0001 + 0x0004 + 0x0200)

Thanks

Link to comment
Share on other sites

Thanks @ioa747 for testing :)

I just read an interesting sentence found in Msdn page, concerning the RedrawWindow function :

The following flags control when repainting occurs. RedrawWindow will not repaint unless one of these flags is specified :

RDW_ERASENOW  [...]
RDW_UPDATENOW [...]

These are the same 2 flags that I tested "blindly", it would have been a good idea to read msdn first !

Now I'm gonna update my initial post to add RDW_UPDATENOW (0x0100) . Even if both flags work (RDW_UPDATENOW and RDW_ERASENOW), maybe RDW_UPDATENOW is a better choice as it processes WM_PAINT "before the function returns". On the contrary $RDW_ERASENOW processes WM_PAINT messages "at the ordinary time", we'll see...
 

Link to comment
Share on other sites

4 hours ago, pixelsearch said:

Sorry but I didn't find the way to make this change

The color you specify in _GDIPlus_GraphicsClear needs to be the same as the transparent color you use (in my case I decided to use 0000FF instead of ABCDEF -- so it must be  FF0000FF in GraphicClear).

ps.  I kind of busy right now -- I'll test your modification later, if you don't mind

Edited by Nine
Link to comment
Share on other sites

@Nine you're right, it works too when I use this line in the loop...

_GDIPlus_GraphicsClear($hGraphic, 0xFFABCDEF)

...instead of :

_WinAPI_RedrawWindow($hGUI, 0, 0, $RDW_INVALIDATE + $RDW_ERASE + $RDW_UPDATENOW)

Can you imagine I started the script with _GDIPlus_GraphicsClear() but I couldn't make it because of the wrong color parameter I indicated, so I switched to _WinAPI_RedrawWindow

I'm gonna add your solution with _GDIPlus_GraphicsClear in the script above.

Link to comment
Share on other sites

@Nine I don't find any difference of speed between the 3 of them (GraphicsClear, RedrawWindow using UPDATENOW, RedrawWindow using ERASENOW) they do the job at the speed of sound without flickering. Anyway it's good to have several solutions in case something turns bad one day.

What could turn bad ?
No idea, but I got an eye on this paragraph of the RedrawWindow function :

By default, the windows affected by RedrawWindow depend on whether the specified window has the WS_CLIPCHILDREN style. Child windows that are not the WS_CLIPCHILDREN style are unaffected; non-WS_CLIPCHILDREN windows are recursively validated or invalidated until a WS_CLIPCHILDREN window is encountered. 

The following flags control which windows are affected by the RedrawWindow function.
Flag                Description
RDW_ALLCHILDREN     Includes child windows, if any, in the repainting operation. 
RDW_NOCHILDREN      Excludes child windows, if any, from the repainting operation

So for now, let's use... _GDIPlus_GraphicsClear() and see where it goes. At least we won't have flags to manage.
And if GraphicsClear isn't enough for special cases, then we'll add more flags to RedrawWindow :D

Link to comment
Share on other sites

@Nine could you please have a look at these 2 pics :

1824326286_PropritsdeAffichage.png.6948dbed3a1984b0e627d8f10749af01.png

952922442_GuiPropViewAutoIt.png.3a5f1e359d3fa9ebc40b88dff3851283.png

There are 19 child windows in the parent window ("Propriétés de l'affichage")

1) With my 1st script found above in this thread, I can highlight only 7 child windows out of 19, when the mouse is hovered over the controls. The windows I can't highlight are :
* All windows found inside any groupbox control
* The disabled button "Appliquer" found at the bottom right corner of the pic : this is because, as read on msdn :

The WindowFromPoint function does not retrieve a handle to a hidden or disabled window, even if the point is within the window.

2) My 2nd script below highlights correctly all the child windows (19) when they're hovered over :

; 2nd script
; ==========

#include <GDIPlus.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

HotKeySet("{ESC}", "_Quit") ; <===================
Local $hWnd_old = 0

; Create a structure that defines any point to be checked.
$tPoint = DllStructCreate($tagPOINT)

; Create a transparent GUI covering the desktop
$hGUI = GUICreate("Window viewer", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
GUISetBkColor(0xABCDEF)
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xABCDEF)

_GDIPlus_Startup()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hPen = _GDIPlus_PenCreate(0xFFFF0000, 4) ; alpha channel = 0xFF (opaque), red = 0xFF0000, width = 4 (pixels)

GUISetState(@SW_SHOW, $hGUI)

While 1
    Local $aMPos = MouseGetPos() ; screen coords
    DllStructSetData($tPoint, "x", $aMPos[0])
    DllStructSetData($tPoint, "y", $aMPos[1])

    ; $hParent = _WinAPI_GetParent(_WinAPI_WindowFromPoint($tPoint)) ; BAD (returns the handle of hidden ClassName RunDLL on some disabled controls)
    $hParent = _WinAPI_GetAncestor(_WinAPI_WindowFromPoint($tPoint), $GA_PARENT) ; ok

    $hWnd = 0
    $aChild = _WinAPI_EnumChildWindows($hParent)

    If Not @error Then
        For $i = 1 To $aChild[0][0]
            $hParent = _WinAPI_GetParent($aChild[$i][0])
            $tPoint = _WinAPI_GetMousePos(True, $hParent) ; mouse coords relative to parent client area

            ; $hWnd = _WinAPI_WindowFromPoint($tPoint) ; BAD (returns the group control when mouse hovered over a control inside it...
            ;                                            ...also a disabled window handle isn't retrieved with this function)
            ; $hWnd = _WinAPI_ChildWindowFromPoint($hParent, $tPoint)   ; BAD (returns the group control)
            ; $hWnd = _WinAPI_ChildWindowFromPointEx($hParent, $tPoint) ; BAD (returns the group control)
            $hWnd = _WinAPI_RealChildWindowFromPoint($hParent, $tPoint) ; ok (even on disabled controls) . Function not found in AutoIt

            If $hWnd = $aChild[$i][0] Then
                $tRect = _WinAPI_GetWindowRect($hWnd)
                ExitLoop
            EndIf
        Next
    EndIf

    If $hWnd <> $hWnd_old Then
        _GDIPlus_GraphicsClear($hGraphic, 0xFFABCDEF)
        If $hWnd Then
            _GDIPlus_GraphicsDrawRect($hGraphic, $tRect.Left, $tRect.Top, _
            $tRect.Right - $tRect.Left, $tRect.Bottom - $tRect.Top, $hPen)
        EndIf
        $hWnd_old = $hWnd
    EndIf
    Sleep(10)
WEnd

Func _Quit()
    ; Clean up resources
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_ShutDown()
    GUIDelete($hGUI)
    Exit
EndFunc   ;==>_Quit

; #FUNCTION# ====================================================================================================================
; Author.........: pixelsearch
; Modified.......:
; ===============================================================================================================================
Func _WinAPI_RealChildWindowFromPoint($hWnd, $tPOINT)
    Local $aRet = DllCall('user32.dll', 'hwnd', 'RealChildWindowFromPoint', 'hwnd', $hWnd, 'struct', $tPOINT)
    If @error Then Return SetError(@error, @extended, 0)

    Return $aRet[0]
EndFunc   ;==>_WinAPI_RealChildWindowFromPoint

But there's still an issue :
* The 1st script (WindowFromPoint only) could highlight the whole parent window when the mouse hovered over :
=> the parent title bar : great !
=> the bottom of the parent window (at the left of the OK button) : also great !
=> the disabled "Appliquer" button : very bad.

* The 2nd script (WindowFromPoint + RealChildWindowFromPoint [this last function not found in AutoIt]) does the following when the mouse hovers over :
=> the parent title bar : highlights... the desktop (red rectangle surrounds the desktop) : bad
=> the bottom of the parent window (at the left of the OK button) : highlights the desktop :bad
=> the disabled "Appliquer" button : correctly highlighted, great !

Do you think there's an easy way to combine both scripts in a 3rd (and last) script so all functionalities could work correctly ?

I'll try again from my side and post here if I find a solution.
Thanks for reading :)

Edit: I'm trying to do a full test (when windows are found between the hovered window and the Desktop, when the mouse hovers over the title bar or a place in the window which is not a control, when the mouse hovers over a disabled control etc...) . I'm studying all the handles returned by the different functions in these different scenarios. If something looks correct, then I'll report here in a new post.

Edited by pixelsearch
Link to comment
Share on other sites

Nice job again @pixelsearch

I came up with this.  What do you think ?

#include <Array.au3>
#include <GDIPlus.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt('MustDeclareVars', 1)

HotKeySet("{ESC}", "_Quit") ; <===================
Global $hGraphic, $hPen

_Main()

Func _Main()
  Local $hGUI = GUICreate("GDI+", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
  GUISetBkColor(0x0000FF)
  _WinAPI_SetLayeredWindowAttributes($hGUI, 0x0000FF)

  Local $tPoint = DllStructCreate($tagPOINT)

  _GDIPlus_Startup()
  $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
  $hPen = _GDIPlus_PenCreate(0xFFFF0000, 5)   ; alpha channel = 0xFF (opaque), red = 0xFF0000, width = 5 (pixels)

  GUISetState()

  Local $hWnd, $hRoot, $hWnd2, $hWnd_Old = -1, $aWPos

  While True
    $tPoint = _WinAPI_GetMousePos()
    $hWnd = _WinAPI_WindowFromPoint($tPoint)
    $hWnd2 = GetRealChild($hWnd)
    If $hWnd2 And $hWnd <> $hWnd2 Then $hWnd = $hWnd2
    If $hWnd <> $hWnd_Old Then
      _GDIPlus_GraphicsClear($hGraphic, 0xFF0000FF)
      $aWPos = WinGetPos($hWnd)
      _GDIPlus_GraphicsDrawRect($hGraphic, $aWPos[0], $aWPos[1], $aWPos[2], $aWPos[3], $hPen)
      $hWnd_Old = $hWnd
    EndIf
    Sleep(100)
  WEnd
EndFunc   ;==>_Main

Func _Quit()
  ; Clean up resources
  _GDIPlus_PenDispose($hPen)
  _GDIPlus_GraphicsDispose($hGraphic)
  _GDIPlus_Shutdown()
  Exit
EndFunc   ;==>_Quit

Func _WinAPI_RealChildWindowFromPoint($hWnd, $tPoint)
  Local $aRet = DllCall('user32.dll', 'hwnd', 'RealChildWindowFromPoint', 'hwnd', $hWnd, 'struct', $tPoint)
  If @error Then Return SetError(@error, @extended, 0)
  Return $aRet[0]
EndFunc   ;==>_WinAPI_RealChildWindowFromPoint

Func GetRealChild($hWnd)
  Local $tPoint, $hRoot = _WinAPI_GetAncestor($hWnd, $GA_ROOT)
  If $hWnd = $hRoot Then
    $tPoint = _WinAPI_GetMousePos(True, $hWnd)
    Return _WinAPI_ChildWindowFromPointEx($hWnd, $tPoint)
  EndIf
  Local $hParent = _WinAPI_GetAncestor($hWnd, $GA_PARENT)
  Local $aChild = _WinAPI_EnumChildWindows($hParent)
  If @error Then Return 0

  Local $hFound

  For $i = 1 To $aChild[0][0]
    $hParent = _WinAPI_GetParent($aChild[$i][0])
    $tPoint = _WinAPI_GetMousePos(True, $hParent)
    $hFound = _WinAPI_RealChildWindowFromPoint($hParent, $tPoint)
    If $hFound = $aChild[$i][0] Then Return $hFound
  Next
  Return 0
EndFunc   ;==>GetRealChild

 

Link to comment
Share on other sites

@Nine there's one additional thing that could be improved.
You certainly noticed what happens when the mouse hovers over... the red rectangle drawn by the script itself. It will start to flicker until the mouse is moved from there.

Why does it flicker ?
Because the red rectangle got its parent handle = $hGUI , so this red rectangle is immediately cleared as soon as it's hovered upon, followed by the immediate apparition of a red rectangle surrounding the GUI (e.g. around the desktop in our case) and this little game will repeat itself several times per second. To avoid this, one additional line in the script seems enough. Instead of...

$hWnd = _WinAPI_WindowFromPoint($tPoint)
$hWnd2 = GetRealChild($hWnd)

...we can change it to :

$hWnd = _WinAPI_WindowFromPoint($tPoint)
If $hWnd = $hGUI Then ContinueLoop
$hWnd2 = GetRealChild($hWnd)

Now it's not flickering anymore. For the record, I was about to do it the complicated way, e.g. by checking the position of the cursor compared to the position of the red rectangle :

GraphicsDrawRect.thumb.png.f67544bf337add31dd86ac803b79f4cf.png

There are some interesting points in the 5 pics above (zoomed) which were created with the following code :

$hPen = _GDIPlus_PenCreate (0xFFFF0000, 1) ; then 2, 3, 4, 5
_GDIPlus_GraphicsDrawRect($hGraphic, 3, 3, 10, 10, $hPen)

1) The 4 white squares are here just as a visual reminder of the original rectangle position, when the pen got a 1 pixel width.
2) When the pen width is 2, then an outer red rectangle of 1 pixel is added to the original one.
3) When the pen width is 3, then an inner red rectangle of 1 pixel is added to the original one.
4) 4 pixels => same as 2 (outer)
5) 5 pixels => same as 3 (inner) etc...

This explains why the biggest rectangle placed at 0, 0 and surrounding the desktop displays only 3 pixels width (when $hpen width = 5), that's because 2 pixels are here but not visible, they're beyond the desktop limits as shown in pic 5 above (if we consider for a moment that the 4 white squares correspond exactly to the 4 corners of the desktop).

I also noticed that even when creating the rectangle with a width and a height = 10, then you can see that in fact the width and the height are not 10 but 11 (in pic 1)

Maybe it has something to do with what we read on msdn, GetWindowRect function ?

Remarks
In conformance with conventions for the RECT structure, the bottom-right coordinates of the returned rectangle are exclusive.
In other words, the pixel at (right, bottom) lies immediately outside the rectangle.

Or even in PtInRect function :

The PtInRect function determines whether the specified point lies within the specified rectangle.
A point is within a rectangle if it lies on the left or top side or is within all four sides.
A point on the right or bottom side is considered outside the rectangle.

Maybe...

Edited by pixelsearch
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...