Jump to content

Recommended Posts

Posted

Hi everybody :)
I would like to share with you the way I made many controls "untabbable" in a GUI, without adding dozen of lines to the code. In my case, I wanted only the Input controls to be tabbable, while all others controls (radio buttons, check boxes and buttons) would be untabbable.

As style $WS_TABSTOP is forced during the creation of radio buttons, check boxes and buttons, then here is a common way for removing this style just after a control creation :

#include <WindowsConstants.au3>
#include <WinAPISysWin.au3>
...
$idButton_Close = GUICtrlCreateButton("my closing button", 64, 160, 175, 25)
$hButton_Close = GUICtrlGetHandle($idButton_Close)

$iStyle_Button_Close = _WinAPI_GetWindowLong($hButton_Close, $GWL_STYLE)
If BitAND($iStyle_Button_Close, $WS_TABSTOP) = $WS_TABSTOP Then
    _WinAPI_SetWindowLong($hButton_Close, $GWL_STYLE, BitXOR($iStyle_Button_Close, $WS_TABSTOP))
Endif

The problem is that if you have to do same on several controls, then there will be plenty of lines added to your code. So I created a function to reduce the code size, let's see how it was applied to the following GUI, where the only tabbable controls are the 7 Input controls on the right side of the GUI :

462576061_TabonlyonInputcontrols.png.0923ee1255c85cc44f69efbc6303235e.png

Here is the line of code that removes $WS_TABSTOP style from 9 controls :

Remove_Style($WS_TABSTOP, $idRadio_1, $idRadio_2, $idRadio_3, $idRadio_4, _
    $idRadio_11, $idRadio_12, $idCheckbox_CropOnly, $idButton_OK, $idButton_Cancel)

And here is the associated function (which can also be used to remove any style) :

Func Remove_Style($iStyleToRemove, $id1, $id2 = 0, $id3 = 0, $id4 = 0, $id5 = 0, _
    $id6 = 0, $id7 = 0, $id8 = 0, $id9 = 0, $id10 = 0)

    Local $hControl, $iStyle
    For $i = 1 To @NumParams - 1 ; @NumParams between 2 and 11. 1st parameter is the style to remove.
        $hControl = GUICtrlGetHandle(Eval("id" & $i))
        $iStyle = _WinAPI_GetWindowLong($hControl, $GWL_STYLE)
        If BitAND($iStyle, $iStyleToRemove) = $iStyleToRemove Then
            _WinAPI_SetWindowLong($hControl, $GWL_STYLE, BitXOR($iStyle, $iStyleToRemove))
        Endif
    Next

EndFunc ; Remove_Style()

What about the 8 checkboxes corresponding to the 8 Image types ? Well, you can :
* Call the Remove_Style() function a 2nd time, including their 8 id's
* Or tweak the Remove_Style() function to have it accept more than 10 id's per call
* As these 8 checkboxes were created within a loop, then it has been scripted differently :

For $i = 0 To $iMaxImageTypes - 1
    $idCheckbox[$i] = GUICtrlCreateCheckbox(...)
    Remove_Style($WS_TABSTOP, $idCheckbox[$i])
Next

I hope this function will help users facing the same situation :)

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted (edited)

I'm a keyboard kind of operator (prefer keyboard shortcuts to using the mouse).  I can and do appreciate the tab scenario you solved, but I would also employ Accelerators to enable keyboard interaction with the other controls as well.  Looks like it'd be a fairly easy to add that to your controls without much compromise.

i.e.

Choose a &folder
Choose a folder + all &subfolders
Pick them &individually
&Drag them here
&New names (ex..._resized.jpg)
&Overwrite
E&xit Script
&JPG
&PNG
&GIF
&TIFF
&EXIF
&WMF
E&MF
&check if yes
 

 

Maybe you already did this but it's not obvious from the screenshot as the underscores are hidden by default until you press alt.

 

Edited by spudw2k
Posted (edited)
Just now, spudw2k said:

I can and do appreciate the tab scenario you solved, but I would also employ Accelerators to enable keyboard interaction with the other controls as well.

Hi spudw2k, glad you appreciated the tab scenario :)
I haven't done it yet [the keyboard shortcuts] but I will certainly consider it in the future, thanks for your idea.

As we are in the example sections, I would like to explain some specific parts of the script, for example the "enlarged landing zone for dropped files" that I added since my precedent post, it may be useful if any reader needs to do same.

I wanted this "green landing zone" to be bigger than the one you can see in the diagram of my 1st post above, to make the drag and drop process easier (it sure is easier to drop on a larger zone than on a smaller one)

As I didn't want the GUI to be wider, then I found a way of enlarging the landing zone, having all 4  radio buttons participating (in the same Group control). It works great, here is the result :

155498564_Enlargeddropzone.thumb.png.023f0d89940092d8ec7ce95a9107602a.png

1) Diagram on the left shows how the GUI appears immediately after you launch the script :
* 1st radio button in the group is selected ("Choose a folder") and button "Ok" is enabled
* The background of all 4 radio buttons is grey on my computer (it's the gui background color, untouched)

2) Diagram on the right shows how the GUI appears when you check the 4th radio button ("Drag them here")
* 4th radio button in the group is selected and button "Ok" is now disabled
* The background of all 4 radio buttons is now light green and you can drop your files anywhere in the enlarged green zone.

To achieve this, I was very lucky to find 3 posts from guinness, here, there and everywhere (that's a Beatles song title lol). But after having read (and tested) what KaFu replied in the "here" link, then I preferred not to use the "here" function, you'll understand why it you read KaFu's comment.

Guinness "there" link worked fine : keep the original background color of the GUI in a variable, so you can re-apply it to a control in case you need to change the background color of the control (from grey to green in our case, then back to grey)

Here are the 2 corresponding parts of the script. 1st part when GUI is created :

$hGUI_main = GUICreate("Resize image files (v3)", 493, 290, -1, -1, _
    -1, BitOr($WS_EX_ACCEPTFILES, $WS_EX_TOPMOST))

GUICtrlCreateGroup(" How to select image files ? ", 13, 8, 193, 129)
$idRadio_1 = GUICtrlCreateRadio("Choose a folder", 29, 27, 170, 25)
GUICtrlSetState(-1, $GUI_CHECKED)
$idRadio_2 = GUICtrlCreateRadio("Choose a folder + all subfolders", 29, 52, 170, 25)
$idRadio_3 = GUICtrlCreateRadio("Pick them individually", 29, 77, 170, 25)
$idRadio_4 = GUICtrlCreateRadio("Drag them here", 29, 102, 170, 25)
GUICtrlCreateGroup("", -99, -99, 1, 1)
...
GUISetState(@SW_SHOW, $hGUI_main)

; ++++++++++++ Guinness "there"
; Keep the GUI original background color in a variable
Local $hDC = _WinAPI_GetDC($hGUI_main)
$iGuiBackColor = _WinAPI_GetBkColor($hDC) ; Gui MUST be visible (not hidden or minimized)
_WinAPI_ReleaseDC($hGUI_main, $hDC)
; ++++++++++++

$bDropColorVisible = False
...

Now the 2nd part of the script, within the While... Wend loop :

While 1
    If $bDropColorVisible = True And GUICtrlRead($idRadio_4) = $GUI_UNCHECKED Then
        For $i = 1 To 4
            $idVar = Eval("idRadio_" & $i)
            GUICtrlSetBkColor($idVar, $iGuiBackColor)
            GUICtrlSetState($idVar, $GUI_NODROPACCEPTED + (($i < 4) ? (0) : ($GUI_UNCHECKED)))
        Next
        $bDropColorVisible = False
        GUIRegisterMsg($WM_DROPFILES, "")
        GUICtrlSetState($idButton_OK, $GUI_ENABLE)
    EndIf

    $iGetMsg = GUIGetMsg()
    Switch $iGetMsg
        Case $GUI_EVENT_CLOSE, $idButton_Cancel ; or Esc
            ...
        Case $idRadio_1
            $iHow_Choose_img = 1 ; a whole folder (no recursion) using FileSelectFolder()

        Case $idRadio_2
            $iHow_Choose_img = 2 ; a whole folder + subfolders, using FileSelectFolder()

        Case $idRadio_3
            $iHow_Choose_img = 3 ; pick files individually, using FileOpenDialog()

        Case $idRadio_4
            $iHow_Choose_img = 4 ; drag 'n drop files from any Explorer, ACDSee...
            For $i = 1 To 4
                $idVar = Eval("idRadio_" & $i)
                GUICtrlSetBkColor($idVar, 0xDDFFE0) ; light green. 0xC0FFFF (light blue) is ok too
                GUICtrlSetState($idVar, $GUI_DROPACCEPTED + (($i < 4) ? (0) : ($GUI_CHECKED)))
            Next
            $bDropColorVisible = True
            GUIRegisterMsg($WM_DROPFILES, "WM_DROPFILES")
            GUICtrlSetState($idButton_OK, $GUI_DISABLE)
        ...
        Case $idButton_OK, $GUI_EVENT_DROPPED
            $idBad_Control = Check_Control() ; check if all controls got correct values
            ...
    EndSwitch
WEnd

Func WM_DROPFILES() can be found at guinness "everywhere" link.

So thank you guys, UEZ for all your GDI+ examples, guinness for your 3 posts, Melba23 ("don't ever color buttons !"), BrewManNH "It appears that the window and control have to be visible to be detected by this function", KaFu "So depending on the control type this one still needs more tweaking." etc... etc...

Really a great community with helpful people :thumbsup:

Edited by pixelsearch

"I think you are searching a bug where there is no bug... don't listen to bad advice."

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