Sign in to follow this  
Followers 0
nago

Sliders / OnEvent mode

16 posts in this topic

#1 ·  Posted (edited)

Erm, skip down to post #10 if you would :P

Edited by nago

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Hey, I'm new to AutoIt scripting and while I have found a way to accomplish what I was trying to do, I have the sneaking suspicion there is a more efficient way lurking around the corner.

I have a GUI I constructed with the Koda window tool (it's very nice!) and I have created a slider called $processpriority_adv which ranges from 0-5. I created a label with a border next to it called $label1, which I intend to use to show what the processpriority slider correlates to.

So, at the end of my main GUI loop, I have something like:

if GuiCtrlRead($processpriority_adv) = "0" AND GuiCtrlRead($label1) <> "Idle" Then GuiCtrlSetData($label1,"Idle")
if GuiCtrlRead($processpriority_adv) = "1" AND GuiCtrlRead($label1) <> "Below Normal" Then GuiCtrlSetData($label1,"Below Normal")
if GuiCtrlRead($processpriority_adv) = "2" AND GuiCtrlRead($label1) <> "Normal" Then GuiCtrlSetData($label1,"Normal")
if GuiCtrlRead($processpriority_adv) = "3" AND GuiCtrlRead($label1) <> "Above Normal" Then GuiCtrlSetData($label1,"Above Normal")
if GuiCtrlRead($processpriority_adv) = "4" AND GuiCtrlRead($label1) <> "High" Then GuiCtrlSetData($label1,"High")
if GuiCtrlRead($processpriority_adv) = "5" AND GuiCtrlRead($label1) <> "Realtime" Then GuiCtrlSetData($label1,"Realtime")

And this does the trick without flicker, but I was wondering if there was a more intelligent way to do it?

I wasn't sure if there was a way to change it 'only if the slider was touched', or something that made more sense.

I don't want to settle into bad habits!

You've definitely got the right idea by only updating the label when required so you wont get any flicker.

The code below may be a more efficient way of doing it for the following reasons.

The controls $processpriority_adv and $label1 are only read when the position of the slider has been moved.

The values of the two controls are only read once and then checked against the possible values.

Global $sLabelValue = ''
While 1 
    Switch GUIGetMsg()
        Case $processpriority_adv
            $sLabelValue = GuiCtrlRead($label1)
            Switch GuiCtrlRead($processpriority_adv)
                Case "0"
                    If $sLabelValue <> "Idle" Then GuiCtrlSetData($label1,"Idle")
                Case "1"
                    If $sLabelValue <> "Below Normal" Then GuiCtrlSetData($label1,"Below Normal")
                Case "2"
                    If $sLabelValue <> "Normal" Then GuiCtrlSetData($label1,"Normal")
                Case "3"
                    If $sLabelValue <> "Above Normal" Then GuiCtrlSetData($label1,"Above Normal")
                Case "4"
                    If $sLabelValue <> "High" Then GuiCtrlSetData($label1,"High")
                Case "5"
                    If $sLabelValue <> "Realtime" Then GuiCtrlSetData($label1,"Realtime")
                Case Else
                    ; Invalid value do nothing
            EndSwitch
        Case Else 
    EndSwitch
WEnd

Edited: I missed reading the GUIGetMsg() in my original code. Hence my code was running for every message.

Edited by Bowmore

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Share this post


Link to post
Share on other sites

You can set variable according to slider position, instead of check and set data every time:

$sLabelData = ""
Switch GuiCtrlRead($processpriority_adv)
    Case 0
        $sLabelData = "Idle"
    Case 1
        $sLabelData = "Below Normal"
    Case 2
        $sLabelData = "Normal"
    Case 3
        $sLabelData = "Above Normal"
    Case 4
        $sLabelData = "High"
    Case 5
        $sLabelData = "Realtime"
EndSwitch

If $sLabelData <> "" Then _GuiCtrlSetData($label1, $sLabelData)

Func _GUICtrlSetData($CtrlID, $sData, $sDefault="", $iCheck=1)
    If $iCheck = 0 Or ($iCheck = 1 And GUICtrlRead($CtrlID) <> $sData) Then Return GUICtrlSetData($CtrlID, $sData, $sDefault)
    Return 0
EndFunc

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

AutoIt is simple, subtle, elegant. © AutoIt Team

Share this post


Link to post
Share on other sites

And before you decide what's the fastest solution profile your code! Take a look at the code profile link in my signature.

When I wrote it I tested If..ElseIf..., case and switch. At the time switch was way slower than if. But that can have changed by now as the AutoIt developers are tuning bottlenecks when they find the time and intrest..:P

Share this post


Link to post
Share on other sites

You've definitely got the right idea by only updating the label when required so you wont get any flicker.

The code below may be a more efficient way of doing it for the following reasons.

The controls $processpriority_adv and $label1 are only read when the position of the slider has been moved.

The values of the two controls are only read once and then checked against the possible values.

Hi, your approach seems to work well, though I changed the main select/case part to just "if $processpriority_adv then / etc / endif"

mostly to see if that would work all the same and it seems to. I find myself more comfortable in the company of "if/then/else/then" over these newfangled switch/select/case dealies :P

My new question is; $processpriority_adv isn't only true when the slider is being touched, is it? I tried testing it out and it seems to evaluate even when it's not being touched... or is my understanding wrong?

MSCreator: Thank you for your code too, but I have to admit that I didn't understand it as well as Bowmore's code, so I went with his because I was more familiar with the method... Still a bit fuzzy on this ;)

Share this post


Link to post
Share on other sites

Hi,

If MsCreatoR's version bamboozled you then wonder what my effort at a working example will do...lol

#include <GuiConstants.au3>

Global $OldValue
Dim $Value = StringSplit("Idle|Below Normal|Normal|Above Normal|High|Realtime", "|")

$Gui = GUICreate(":-)", 170, 80)
$Label = GUICtrlCreateLabel("", 5, 5, 160, 20, $SS_CENTER)
GUICtrlSetFont(-1, 12, 700)
$Slider = GUICtrlCreateSlider(5, 30, 160, 45, $TBS_BOTH)
GUICtrlSetLimit(-1, 6, 1)
GUICtrlSetData(-1, 1)
GUISetState(@SW_SHOW, $Gui)

While 1
    If GUICtrlRead($Slider) <> $OldValue Then
        GUICtrlSetData($Label, $Value[GUICtrlRead($Slider)])
        $OldValue = GUICtrlRead($Slider)
    EndIf
    If GUIGetMsg() = -3 Then ExitLoop
WEnd

Cheers

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

I actually found myself needing to switch over to OnEvent mode, and while I need to worry about re-coding this behaviour as discussed in this thread, I ran into some other problems.

I decided not to start a new topic to avoid clutter, but basically I had to switch to OnEvent mode because my window intends to be just an "addon" gui to an existing AU3 script that may be doing other things in the meanwhile; so I figured OnEvent made a better fit for what I was trying to do..

The problem I've run into is that I'm trying to call my little GUI with a hotkey, which seems to work.

Currently, I use a function (called by the hotkey) that looks like:

Func fKeyIniCfgGui()
    if not $IniCfgGui Then
        fCreateIniCfgGui()
        fShowIniCfgGui()
    Else 
        fShowIniCfgGui()
    Endif
EndFunc

where $IniCfgGui is the handle (is that the right term?) for my window.

This seemed to work great when I had my window "close" by using SetGuiState(@SW_HIDE,$IniCfgGui);

but I've decided that actually Deleting the entire GUI is a more proper fit for closing the gui,

and I've now found that my hotkey function doesn't work as expected anymore.

Ultimately, how can I tell if a window exists?

Edit: I just realized my code may look a little extraneous if I'm deleting the GUI every time, but I'm trying to prevent launching multiple copies of the window at a time.

Edited by nago

Share this post


Link to post
Share on other sites

Just a hunch, but do you change the value of $IniCfgGui when you destroy the window?

You could also try:

Local $gui = GUICreate("TEST")
GUISetState(@SW_SHOW, $gui)
ConsoleWrite("EXISTS:=" & WinExists($gui) & @CRLF)
Exit

Happy Scripting..:P

Share this post


Link to post
Share on other sites

Just a hunch, but do you change the value of $IniCfgGui when you destroy the window?

I wasn't changing the value, no. I thought the variable that corresponded to the window itself would be false if the window was destroyed, but that didn't seem to be the case.

WinExists though, eh? That's what I'm lookin' fer! Thanks :P

Share this post


Link to post
Share on other sites

I was trying to switch my previous attempt at a GUI to using OnEvent mode, since I felt it was a better fit for what I was trying to accomplish than the default messageloop, as the main script should be free to do things while this Gui is open.

That said, I have a slider with a ctrlID assigned to $processpriority_adv and a label next to it under $prioritylabel_adv .

The general idea is that the user can configure the process priority of the script with the slider, so the slider goes from 0 to 5.

The label is for showing what the number of the slider actually corresponds to, so I have two things in place at the moment;

1) In the gui creation function:

GuiCtrlSetOnEvent($processpriority_adv,"fProcessSlider")

2) and the corresponding function:

Func fProcessSlider()
    local $sLabelValue = $prioritylabel_adv
    Switch GuiCtrlRead($processpriority_adv)
        Case "0"
            If $sLabelValue <> "Idle" Then GuiCtrlSetData($prioritylabel_adv,"Idle")
        Case "1"
            If $sLabelValue <> "Below Normal" Then GuiCtrlSetData($prioritylabel_adv,"Below Normal")
        Case "2"
            If $sLabelValue <> "Normal" Then GuiCtrlSetData($prioritylabel_adv,"Normal")
        Case "3"
            If $sLabelValue <> "Above Normal" Then GuiCtrlSetData($prioritylabel_adv,"Above Normal")
        Case "4"
            If $sLabelValue <> "High" Then GuiCtrlSetData($prioritylabel_adv,"High")
        Case "5"
            If $sLabelValue <> "Realtime" Then GuiCtrlSetData($prioritylabel_adv,"Realtime")
    EndSwitch
EndFunc

The issue here is that the GuiCtrlSetOnEvent seems to be triggered for the slider only after the slider is RELEASED from the mouseclick, so I can't update the label in realtime, just as a reaction to when the user lets go.

Is there either another way to call a loop to change my label that will be called when the slider is first clicked (and ends the loop when it's let go) or a parameter to give to GuiCtrlSetOnEvent to tell it to be a little more proactive?

Share this post


Link to post
Share on other sites

A mini example..

#include <GUIConstants.au3>

GUICreate("slider",220,100, 100,200)
GUISetBkColor (0x00E0FFFF)  ; will change background color

$slider1 = GUICtrlCreateSlider (10,10,200,20)
GUICtrlSetLimit(-1,200,0)   ; change min/max value
$button = GUICtrlCreateButton ("Value?",75,70,70,20)
GUISetState()
GUICtrlSetData($slider1,45) ; set cursor

Do
    $n=GUIGetMsg()
    $Info=GUIGetCursorInfo()
    If $Info[4]=$slider1 And $Info[2] Then
        $Bool=True
        GUICtrLSetData($button,GUICtrlRead($slider1))
    EndIf
Until $n = $GUI_EVENT_CLOSE

Share this post


Link to post
Share on other sites

Not to seem ungrateful, but I do really need to keep my GUI using the OnEvent mode instead of MessageLoop; there are other things going on elsewhere in the script that my GUI shouldn't be interrupting.

If, as a side effect of needing to run in OnEvent mode I can't update a little label in realtime, that's OK; but I'd really like to know if I can have my cake and eat it too.

Thanks,

Nago

Share this post


Link to post
Share on other sites

Not to seem ungrateful, but I do really need to keep my GUI using the OnEvent mode instead of MessageLoop; there are other things going on elsewhere in the script that my GUI shouldn't be interrupting.

If, as a side effect of needing to run in OnEvent mode I can't update a little label in realtime, that's OK; but I'd really like to know if I can have my cake and eat it too.

Thanks,

Nago

You can put that in a while loop

Share this post


Link to post
Share on other sites

Far as I know there is only one event for slider control "releasedcapture".

The _GUICtrlSlider_Create shows an example of this using the wm_notify event.


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

You can put that in a while loop

How do I call that loop, though? I don't want my GUI hogging the spotlight, as the script is going to be doing other things elsewhile... so just creating a loop after the creation of the GUI won't work out for me, I think? Since if it's listening and waiting to hear about the slider, it's not going to be worrying about the rest of the script. Unless I am grossly misunderstanding you, and for that I apologize. Honest.

I have a pretty good idea of how to check what the slider's value is and update the label based on that, but what I'm having issue with is when and how to call that function in a way that doesn't tie up my script. Currently I call the function by setting GuiCtrlSetOnEvent($processpriority_adv,"fProcessSlider") in advance, but this merely reacts to the button being released.

If there were, say, a way to specify to GuiCtrlSetOnEvent that the event I am linking it to is the button press and not the button release, then I could easily link that to a loop that does what it needs to and just checks to see when the button is released, and when it is, cease the loop.

Far as I know there is only one event for slider control "releasedcapture".

The _GUICtrlSlider_Create shows an example of this using the wm_notify event.

Do you have a link to the relevant docs? I'm really terribly ...erm, Not so bright with AU3 yet. I googled for wm_notify on autoitscript.com and found only one reference to it in the docs under the winmsg list, which I don't really know what to do with...yet.

I'm sorry I'm such a newb at this, but believe me that your help is appreciated. Sorry if I'm frustratingly dumb.

Share this post


Link to post
Share on other sites

Have a look at this:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt('GUIOnEventMode', 1)

GUICreate('Test', 250, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, '_Exit')
$label = GUICtrlCreateLabel('', 0, 0, 50, 20)
$slider = GUICtrlCreateSlider(50, 0, 200, 20)
GUISetState()

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')

Do
    Sleep(100)
Until 0

Func WM_NOTIFY($hWnd, $iMsg, $iWParam, $iLParam)
    Local $iWLoWord = BitAND($iWParam, 0xFFFF)
    If $iWLoWord = $slider Then
        GUICtrlSetData($label, GUICtrlRead($slider))
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc

Func _Exit()
    Exit
EndFunc

Share this post


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
Sign in to follow this  
Followers 0