Jump to content

Program crashing when I change which window is in focus.


Recommended Posts

@pixelsearch first of all great job!

in my SciTE PlusBar in Label is ok

1512475-forum12.thumb.png.dc49a6d7c5330bf46f89d3d5cb27b244.png

 

but in Toolbar

1512475-forum13.thumb.png.8bdda599c474c936f7bd56df6bf360c6.png

I don't why, may be i make something wrong

And the other thing is while the rest of the children are fine

1512475-forum14.png.3ea99869bc911b6e28ed5004ce3bf55a.png

in whole window get away a little bit (I know it's not your fault)

I took the courage to tease it a little

Spoiler
; https://www.autoitscript.com/forum/topic/209532-program-crashing-when-i-change-which-window-is-in-focus/?do=findComment&comment=1512394

#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)
        $hWnd = _WinAPI_WindowFromPoint($tPoint)
        If $hWnd = $hGUI Then ContinueLoop
        $hWnd2 = GetRealChild($hWnd)

        If $hWnd2 And $hWnd <> $hWnd2 Then $hWnd = $hWnd2
        If $hWnd <> $hWnd_Old Then
            _GDIPlus_GraphicsClear($hGraphic, 0xFF0000FF)
;~          $aWPos = WinGetPos($hWnd)
            $aWPos = _WinGetPosAccuracy($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

Func _WinGetPosAccuracy($hWnd)
    Local $HWPos[4] ; [0]=X  [1]=Y  [2]=Width  [3]=Height
    If WinExists($hWnd) Then
        $HWPos[0] = _WindowDWMX($hWnd)
        $HWPos[1] = _WindowDWMY($hWnd)
        $HWPos[2] = _WindowDWMWidth($hWnd)
        $HWPos[3] = _WindowDWMHeight($hWnd)
    Else
        Return SetError(1, 0, "")
    EndIf
    Return $HWPos
EndFunc   ;==>_WinGetPosAccuracy

#Region === a short extract from Pal, Peter's AutoIt Library, version 1.25 UDF ===

; https://www.autoitscript.com/forum/topic/201518-pal-peters-autoit-functions-library/

; #FUNCTION# ====================================================================================================================
; Name...........: _WindowDWMWidth
; Description....: Returns window width as registered by the Desktop Window Manager (DWM)
; Syntax.........: _WindowDWMWidth($hGUI)
; Parameters.....: $hGUI                    - Window GUI handle
; Return values..: Desktop Window Manager window width
; Author.........: Peter Verbeek
; Modified.......:
; ===============================================================================================================================
Func _WindowDWMWidth($hGUI)
    ; Try finding width by the Desktop Window Manager, Windows Vista and higher
    Local $tagRect = "struct;long Left;long Top;long Right;long Bottom;endstruct", $tRect = DllStructCreate($tagRect)
    DllCall("Dwmapi.dll", "long", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hGUI), "dword", 9, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error = 0 And DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1) > 0 And DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2) > 0 Then Return DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1)
    ; Alternatively return window width by AutoIt
    Local $aWindow = WinGetPos($hGUI)
    If @error <> 0 Or $aWindow[0] = -32000 Then Return 0                ; correcting for a minimized window
    Return $aWindow[2]
EndFunc   ;==>_WindowDWMWidth
; #FUNCTION# ====================================================================================================================
; Name...........: _WindowDWMHeight
; Description....: Returns window height as registered by the Desktop Window Manager (DWM)
; Syntax.........: _WindowDWMHeight($hGUI)
; Parameters.....: $hGUI                    - Window GUI handle
; Return values..: Desktop Window Manager window height
; Author.........: Peter Verbeek
; Modified.......:
; ===============================================================================================================================
Func _WindowDWMHeight($hGUI)
    ; Try finding width by the Desktop Window Manager, Windows Vista and higher
    Local $tagRect = "struct;long Left;long Top;long Right;long Bottom;endstruct", $tRect = DllStructCreate($tagRect)
    DllCall("Dwmapi.dll", "long", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hGUI), "dword", 9, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error = 0 And DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1) > 0 And DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2) > 0 Then Return DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2)
    ; Alternatively return window height by AutoIt
    Local $aWindow = WinGetPos($hGUI)
    If @error <> 0 Or $aWindow[0] = -32000 Then Return 0                ; correcting for a minimized window
    Return $aWindow[3]
EndFunc   ;==>_WindowDWMHeight
; #FUNCTION# ====================================================================================================================
; Name...........: _WindowDWMX
; Description....: Returns window x coordinate as registered by the Desktop Window Manager (DWM)
; Syntax.........: _WindowDWMWidth($hGUI)
; Parameters.....: $hGUI                    - Window GUI handle
; Return values..: Desktop Window Manager window x coordinate
; Author.........: Peter Verbeek
; Modified.......:
; ===============================================================================================================================
Func _WindowDWMX($hGUI)
    ; Try finding x coordinate by the Desktop Window Manager, Windows Vista and higher
    Local $tagRect = "struct;long Left;long Top;long Right;long Bottom;endstruct", $tRect = DllStructCreate($tagRect)
    DllCall("Dwmapi.dll", "long", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hGUI), "dword", 9, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error = 0 And DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1) > 0 And DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2) > 0 Then Return DllStructGetData($tRect, 1)
    ; Alternatively return window width by AutoIt
    Local $aWindow = WinGetPos($hGUI)
    If @error <> 0 Or $aWindow[0] = -32000 Then Return 0                ; correcting for a minimized window
    Return $aWindow[0]
EndFunc   ;==>_WindowDWMX
; #FUNCTION# ====================================================================================================================
; Name...........: _WindowDWMY
; Description....: Returns window y coordinate as registered by the Desktop Window Manager (DWM)
; Syntax.........: _WindowDWMWidth($hGUI)
; Parameters.....: $hGUI                    - Window GUI handle
; Return values..: Desktop Window Manager window y coordinate
; Author.........: Peter Verbeek
; Modified.......:
; ===============================================================================================================================
Func _WindowDWMY($hGUI)
    ; Try finding y coordinate by the Desktop Window Manager, Windows Vista and higher
    Local $tagRect = "struct;long Left;long Top;long Right;long Bottom;endstruct", $tRect = DllStructCreate($tagRect)
    DllCall("Dwmapi.dll", "long", "DwmGetWindowAttribute", "hwnd", WinGetHandle($hGUI), "dword", 9, "ptr", DllStructGetPtr($tRect), "dword", DllStructGetSize($tRect))
    If @error = 0 And DllStructGetData($tRect, 3) - DllStructGetData($tRect, 1) > 0 And DllStructGetData($tRect, 4) - DllStructGetData($tRect, 2) > 0 Then Return DllStructGetData($tRect, 2)
    ; Alternatively return window width by AutoIt
    Local $aWindow = WinGetPos($hGUI)
    If @error <> 0 Or $aWindow[0] = -32000 Then Return 0                ; correcting for a minimized window
    Return $aWindow[1]
EndFunc   ;==>_WindowDWMY
#EndRegion === a short extract from Pal, Peter's AutoIt Library, version 1.25 UDF ===

 

 

I would like to see some information about the current control somewhere

maybe you should have made a new thread

Again great job!

Thank you

Edited by ioa747
UpDate

I know that I know nothing

Link to comment
Share on other sites

6 hours ago, ioa747 said:

In my SciTE PlusBar in Label is ok   
but in Toolbar   
I don't why, may be i make something wrong

Hi @ioa747
I downloaded your script _PlusBar.au3 to check if I have the same display as yours.
Yes I do, it shows same as your pics, this is because the window $PlusBar_Hwnd got a width of 1794 on my computer and it extends at the right of the Scite Window, that why the red rectangle surrounds an empty zone on the right in your 2nd pic :

Local $PlusBar_Hwnd = GUICreate("_PlusBar", $PB_SZ * $PB_items, ...
ConsoleWrite($PB_SZ * $PB_items & @crlf) ; 1794

This value of 1794 can be found in the following pic : look at the 1st child window of _PlusBar, Size column shows 1794, 28 for this child window having a classname "ToolbarWindow32" :

_PlusBar.png.7483a5ea88212ca74e259780a9c62311.png

Maybe 1794 is too large ?
Just for testing, I forced a width of 1294 in your script (by substracting blindly 500 to the width), like this :

Local $PlusBar_Hwnd = GUICreate("_PlusBar", $PB_SZ * $PB_items - 500, ...
Local $ButtonContext = GUICtrlCreateLabel("    x", $PB_SZ * $PB_items - 500, ...

All icons of PlusBar are still there, even when width = 1294, with a child window showing now a width of 1294 everywhere. So maybe it's just an adjustment you could do, concerning the width of $PlusBar_Hwnd ?

Link to comment
Share on other sites

Thx @Nine I'll try it your way too.

1 hour ago, Nine said:

Great find.

You know, all this was possible only because I was lucky enough to discover one freeware scripted by Nir Sofer (NirSoft) . This guy writes freeware & portable little apps that can be really useful at times. I'm sure many of us have used at least one of them during these last years. For example the GuiPropView that you can see in the pic of my last post, let me please quote Nir who describes his app this way :

GUIPropView displays extensive information about all windows currently opened on your system. The upper pane of GUIPropView displays all top level windows, and when you select a window in the upper pane, the lower pane displays the list of all child windows of the selected top level window. 

You can also select one or more windows and then do some actions on them like close, hide, show, minimize, maximize, disable, enable, and so on... 

Be aware that GUIPropView is a replacement for my very old WinLister tool.

By the way, did you notice the Z-order column in the upper pane of the pic in my last post ?

It's a request I emailed to Nir during November 2022 because this column didn't exist before and I needed it for tests, so I had nothing to lose and sent him a request for this new feature. He probably found the idea interesting because a couple of days after, he released a new version 1.24 of GUIPropView, writing this in the version history :

Version 1.24: 
Added 'Z-order' column to the top level windows list

The link to GUIPropView :
https://www.nirsoft.net/utils/gui_prop_view.html

imho all people here dealing with windows, handles, child windows etc... should give a try to this app. Sorry mods I was a bit long about that but as it's freeware, reliable and useful for the community, then I hope you won't mind.

Thanks for reading.

Link to comment
Share on other sites

@pixelsearch

Thank you for suggestion and explanations

Alone I have never find this 😁

it impresses me, however, because the gui after the initial dimension

shrinks according to the window of the scite and I imagined that the Toolbar follow it.

 

After all I following your suggestion

I thought of changing the initial dimension on the $PlusBar gui

Local $PlusBar_Hwnd = GUICreate("_PlusBar", $PB_SZ * 10, …

and then will auto resized according to the window of the scite

and this happens.

but the Toolbar after its initial dimension it will not adjust to the new gui size

 

is a way to update the Toolbar to the new dimension of gui ?

 

I didn't found a way, and I put in blindly

Local $PlusBar_Hwnd = GUICreate("_PlusBar", $PB_SZ * 40, …

 

(the label is fine, it will find its place by itself according the gui )

 

Thanks again for your time

I know that I know nothing

Link to comment
Share on other sites

I'm not experienced with Toolbar resizing, but I notice this :

Scite  original toolbar : 13 icons x 23 width = 299 width
+
Scite _PlusBar : 78 icons x 23 width = 1794 width (our 1794 !)

299 + 1794 = 2093 pixels width minimum (+ borders...)

So if a user checks all 78 icons to appear in Scite's toolbar (as I just did for a test) through your Menu Editor, then these 78 icons really need a toolbar having a width of 1794, and it will need a monitor display > 2100 width to appear fully in a maximized Scite Window.

My old Excel version does it differently :

2016547065_Excelresizestoolbarwhenitswindowisresized.png.77e02b06aab8b6dc4c64e46f8d20315b.png

When the main window of Excel is resized (here I'm shrinking it) then its toolbars are resized accordingly during the resize process, with icons being removed from the main horizontal toolbar and placed in the little window that you see in the pic. On the contrary, when the main window is enlarged, then icons start to reappear in the main horizontal toolbar.

Maybe there's a way to do same in AutoIt (automatically or during a size message function), I hope someone will indicate it to you, if it's possible.

Edited by pixelsearch
Link to comment
Share on other sites

@Nine I'm trying to display a ToolTip which indicates :
1) Handle + Class name (if it's a top-level window)
2) or Handle + Class name + Ctrl ID (if it's a child window)

This code does it (placed just after _GDIPlus_GraphicsDrawRect)

...
_GDIPlus_GraphicsDrawRect($hGraphic, $aWPos[0], $aWPos[1], $aWPos[2] - 1, $aWPos[3] - 1, $hPen)

Local $ToolTipText = "Handle" & @TAB & $hWnd & @crlf & "Class" & @TAB & _WinAPI_GetClassName($hWnd)

; Ctrl ID in ToolTip shouldn't be used at all for top-level windows, then :
If BitAND(_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), $WS_CHILD) = $WS_CHILD Then
    $ToolTipText &= @crlf & "Ctrl ID" & @TAB & _WinAPI_GetDlgCtrlID($hWnd)
EndIf

ToolTip($ToolTipText)
; ToolTip($ToolTipText, $tPoint.x + 10, $tPoint.y + 10, "", 0, 4) ; 4 = Force tooltip always visible

$hWnd_Old = $hWnd
...

It works fine, but I don't like the position of the tooltip in some cases :
* If you just indicate 1 parameter, like this...

ToolTip($ToolTipText)

...then you won't see any tooltip while hovering at the bottom of the screen (taskbar, traybar) because the tooltip will be displayed under the desktop bottom border

* If you pass all parameters to ToolTip() so you can access the last parameter and set it to 4...

ToolTip($ToolTipText, $tPoint.x + 10, $tPoint.y + 10, "", 0, 4) ; $TIP_FORCEVISIBLE = 4

...then you may find other display issues, for example hovering over the tray bar at the bottom right corner of the desktop will display a full visible ToolTip confined at the bottom right corner, with your mouse cursor hovering over the tooltip...

Maybe the solution would be to check some coords (I'm writing this just as it comes) like the cursor position (useful ?), the red rectangle coords, @DeskTopHeight (@DeskTopWidth ?) just to position the ToolTip at a place where it won't disturb anything visually.

It's fine not to move the ToolTip while the cursor moves : a tooltip should stay where it has been displayed (even if the mouse cursor moves) until another red rectangle is drawn, but at least, we could display the tooltip at the "right" place.

Do you have an idea about this ?
Thanks :)

Link to comment
Share on other sites

Hi @Nine
Thanks for your suggestion. Maybe it's not enough as shown on the 2 pics below :

509147912_ToolTipsinterfere.png.94e1068f054b2b39954f63fb66b73d05.png

Anyway no worry, I'll find a little formula to get rid of this annoying ToolTip location in some cases.
That's why AutoIt Window Information (or some apps doing same, like MS Spy++ or Yashied's Control Viewer) write their results in a "separate" window (which is ignored and not updated when the Finder Tool hovers over it)

Maybe I should do same (instead of using a ToolTip), it would allow to display more infos, we'll see...

Link to comment
Share on other sites

a bit experimental

$aMouse_Pos = MouseGetPos()
; Keep ToolTip on screen
If $aMouse_Pos[0] > (@DesktopWidth - 250) Then
    $iX = $aMouse_Pos[0] - 250
Else
    $iX = $aMouse_Pos[0] + 20
EndIf
If $aMouse_Pos[1] > (@DesktopHeight - 100) Then
    $iY = $aMouse_Pos[1] - 100
Else
    $iY = $aMouse_Pos[1] + 20
EndIf

ToolTip($ToolTipText, $iX, $iY, "info", 1)

 

I know that I know nothing

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...