Jump to content

How to preven my scrollable tabs from grabbing focus?


Recommended Posts

Hi!

My goal is to make tabs that I can scroll. As I understand there there is no correct way of doing it so I have to use trick that uses child windows to do this.

I use M23's code for my include:

#include <GUIConstantsEx.au3>
#include "GUIScrollbars_Ex.au3"

Dim $tabWindows[2]


$hGui = GUICreate("Scrollable tabs", 640, 480, -1, -1, $WS_CLIPCHILDREN + $WS_MINIMIZEBOX + $WS_CAPTION + $WS_POPUP + $WS_SYSMENU)
GUICtrlCreateLabel("Label on main gui", 5, 5, Default, 20)
$tabs = GUICtrlCreateTab(5, 25, 630, 450)

$tab1 = GUICtrlCreateTabItem("Tab 1")
$tab2 = GUICtrlCreateTabItem("Tab 2")

$pos = ControlGetPos($hGui, "", $tabs)

$tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
GUISetBkColor(0xffffff)
GUICtrlCreateLabel("Hello World!",10,10)

$tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
GUISetBkColor(0xffffff)
GUICtrlCreateLabel("Label", 10, 10, 25, 25)
GUICtrlSetTip(-1, "Label hint")


GUISetState(@SW_SHOW, $hGui)
_GUIScrollbars_Generate($tabWindows[1], 500, 1000)


; This is the current active tab
$iLastTab = GUICtrlRead($tabs)
GUISetState(@SW_SHOW, $tabWindows[$iLastTab])

$lastLabelIndex = -1


While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $tabs
            $currentTab = GUICtrlRead($tabs)
            If $currentTab <> $iLastTab Then
                GUISetState(@SW_HIDE, $tabWindows[$iLastTab])
                GUISetState(@SW_SHOW, $tabWindows[$currentTab])
                $iLastTab = $currentTab ;
            EndIf
    EndSwitch
WEnd

However when I click on labels under tabs then those child windows grab focus from parent. And whenever I switch tabs, parent window flashes focus. Is there way to prevent this or even better, add scrollbars directly to tabs instead of using GUIs to wrap content?

edited

Link to post
Share on other sites

Hi E1M1 :)
I got a result which looks promising, based on pure Child windows (the ones created with $WS_CHILD style)
As you noticed, the other kind of Child windows (the ones created with $WS_EX_MDICHILD extended style) grab focus when you click on controls they contain, which seems a normal behavior as they are totally separate windows.

Here is a reworked version of your script. There's a hidden button when you scroll down in Tab2 :

#include <GUIConstantsEx.au3>
#include "GUIScrollbars_Ex.au3"

Dim $tabWindows[2]

$hGui = GUICreate("Scrollable tabs", 640, 480, -1, -1, _
    $WS_CLIPCHILDREN + $WS_MINIMIZEBOX + $WS_CAPTION + $WS_POPUP + $WS_SYSMENU)
GUICtrlCreateLabel("Label on main gui", 5, 5, Default, 20)

Local $iXtabs = 5, $iYtabs = 25
$tabs = GUICtrlCreateTab($iXtabs, $iYtabs, 0 ,0)
GUICtrlCreateTabItem("Tab 1")
GUICtrlCreateTabItem("Tab 2")
GUICtrlCreateTabItem("") ; end tabitem definition

$pos = ControlGetPos($hGui, "", $tabs)
Local $iHtabs = $pos[3]

$tabWindows[0] = GUICreate("test", 600, 400, $iXtabs +2, $iYtabs + $iHtabs +1, $WS_CHILD, -1 , $hGUI)
GUISetBkColor(0xffffff)
GUICtrlCreateLabel("Hello World!", 10, 10)

$tabWindows[1] = GUICreate("test", 600, 400, $iXtabs +2, $iYtabs + $iHtabs +1, $WS_CHILD, -1 , $hGUI)
GUISetBkColor(0xffffff)
GUICtrlCreateLabel("Label", 10, 10, 30, 25)
GUICtrlSetTip(-1, "Label hint")
$idButton = GUICtrlCreateButton("Hidden", 290, 650, 80, 30)

_GUIScrollbars_Generate($tabWindows[1], 800, 1000)

GUISetState(@SW_SHOW, $hGui)

; This is the current active tab
$iLastTab = GUICtrlRead($tabs)
GUISetState(@SW_SHOW, $tabWindows[$iLastTab])

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $tabs
            $currentTab = GUICtrlRead($tabs)
            If $currentTab <> $iLastTab Then
                GUISetState(@SW_HIDE, $tabWindows[$iLastTab])
                GUISetState(@SW_SHOW, $tabWindows[$currentTab])
                $iLastTab = $currentTab
            EndIf
        Case $idButton
            MsgBox($MB_TOPMOST, "Hidden Button", "Pressed")
    EndSwitch
WEnd

To make it convenient for our readers, I attach below Melba23's original UDF named GUIScrollbars_Ex.au3 (original dated 05/13/2018) as found in his thread.

GUIScrollbars_Ex.au3

Link to post
Share on other sites

Thanks!

 

It took me a while to figure out why simply updating window styles didnt fix it. Does anyone know why this new code requires GUICtrlCreateTab to be width = 0 and  height = 0? And why now windows appear below it if I make it size 100,100 for example? Like previously they appeared on top of tab container.

edited

Link to post
Share on other sites
9 hours ago, E1M1 said:

It took me a while to figure out why simply updating window styles didnt fix it.

Probably because child windows created with $WS_EX_MDICHILD or $WS_CHILD don't behave the same way at all.
The script below corresponds to your initial script, plus 2 label controls added (1 in each Tab control)

#include <GUIConstantsEx.au3>
#include "GUIScrollbars_Ex.au3"

Dim $tabWindows[2]

$hGui = GUICreate("Scrollable tabs", 640, 480, -1, -1, _
    $WS_CLIPCHILDREN + $WS_MINIMIZEBOX + $WS_CAPTION + $WS_POPUP + $WS_SYSMENU)
GUICtrlCreateLabel("Label on main gui", 5, 5, Default, 20)

$tabs = GUICtrlCreateTab(5, 25, 630, 450)
GUICtrlCreateTabItem("Tab 1")
GUICtrlCreateLabel("Label in Tab1", 100, 100)
GUICtrlCreateTabItem("Tab 2")
GUICtrlCreateLabel("Label in Tab2", 150, 150)
GUICtrlCreateTabItem("") ; end tabitem definition

$pos = ControlGetPos($hGui, "", $tabs)

$tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
; $tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_CHILD, -1, $hGUI)

GUISetBkColor(0xffffff)
GUICtrlCreateLabel("Label in Child1",10,10)

$tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
; $tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_CHILD, -1, $hGUI)

GUISetBkColor(0xffffff)
GUICtrlCreateLabel("Label in Child2", 10, 50)
GUICtrlSetTip(-1, "Label hint")

GUISetState(@SW_SHOW, $hGui)
_GUIScrollbars_Generate($tabWindows[1], 500, 1000)

; This is the current active tab
$iLastTab = GUICtrlRead($tabs)
GUISetState(@SW_SHOW, $tabWindows[$iLastTab])

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $tabs
            $currentTab = GUICtrlRead($tabs)
            If $currentTab <> $iLastTab Then
                GUISetState(@SW_HIDE, $tabWindows[$iLastTab])
                GUISetState(@SW_SHOW, $tabWindows[$currentTab])
                $iLastTab = $currentTab ;
            EndIf
    EndSwitch
WEnd

1) When you run the script like this :

$tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
; $tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_CHILD, -1, $hGUI)
...
$tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
; $tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_CHILD, -1, $hGUI)

Then the labels displayed are the Child windows labels and the scrollbar is visible in Tab2, which means that the child windows created with $WS_EX_MDICHILD are in the foreground. Unfortunately they grab focus from parent and you don't want this behavior in your 1st post.

2) When you run the script like that :

; $tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
$tabWindows[0] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_CHILD, -1, $hGUI)
...
; $tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_POPUP, $WS_EX_MDICHILD, $hGui)
$tabWindows[1] = GUICreate("test", $pos[2] - 10, $pos[3] - 30, 7, 50, $WS_CHILD, -1, $hGUI)

Then the labels displayed are the Tab labels and the scrollbar is not visible in Tab2, which means that the child windows created with $WS_CHILD are in the background, covered by the Parent Tab control.

This gave me the idea to create a Tab control having width = 0 and height = 0, so there will be no overlapping at all between the Tab control and the $WS_CHILD windows. Gladly it worked fine and the "grab focus" issue was solved too.

9 hours ago, E1M1 said:

And why now windows appear below it if I make it size 100,100 for example? Like previously they appeared on top of tab container.

This is because you use a constant (50) for the Y position of the Child Windows, while I use the variable $iHtabs (Tab control height) to calculate precisely the Y position of the Child windows, so they won't overlap the Tab control :

$pos = ControlGetPos($hGui, "", $tabs)
Local $iHtabs = $pos[3]
$tabWindows[0] = GUICreate("test", 600, 400, $iXtabs +2, $iYtabs + $iHtabs +1, $WS_CHILD, -1 , $hGUI)

 

Edited by pixelsearch
typo
Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...