Sign in to follow this  
Followers 0
mac1

active slider border

22 posts in this topic

Hi All,

I've tried various control styles when adding two sliders.

But I've not found the one that makes the dotted line border invisible when the mouse is clicked on the slider.

Is there such a style?

Thanks,

Mac

Share this post


Link to post
Share on other sites



I do not know why but if you place a label above it is ok.

#include <GUIConstants.au3>

$Form1 = GUICreate("Form1", 633, 454, 193, 115)
$Label1 = GUICtrlCreateLabel("", 120, 80, 36, 17)
$Slider1 = GUICtrlCreateSlider(120, 96, 145, 49)
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch
WEnd


Get Beta versions Here Get latest SciTE editor Here AutoIt 1-2-3 by Valuater - A great starting point.

Time you enjoyed wasting is not wasted time ......T.S. Elliot
Suspense is worse than disappointment................Robert Burns
God help the man who won't help himself, because no-one else will...........My Grandmother

Share this post


Link to post
Share on other sites

Did you move the control?

I just tried this code and when you click on the slider control to move it, I get a dotted line border around the slider control.

Share this post


Link to post
Share on other sites

Did you move the control?

I just tried this code and when you click on the slider control to move it, I get a dotted line border around the slider control.

I thought I had but obviously not. :">


Get Beta versions Here Get latest SciTE editor Here AutoIt 1-2-3 by Valuater - A great starting point.

Time you enjoyed wasting is not wasted time ......T.S. Elliot
Suspense is worse than disappointment................Robert Burns
God help the man who won't help himself, because no-one else will...........My Grandmother

Share this post


Link to post
Share on other sites

Hi, I know this is definitely a painful way there'd have to be a better way then this but ...

#include <GUIConstants.au3>

$Form1 = GUICreate("Form1", 633, 454, 193, 115)
$Slider1 = GUICtrlCreateSlider(120, 96, 145, 49)
_SliderMask(120, 96, 145, 49)
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch
WEnd

Func _SliderMask($sX, $sY, $sW, $sH)
    GUICtrlCreateLabel("", $sX - 1, $sY - 1, 2, $sH + 1)
    GUICtrlSetState(-1,$GUI_DISABLE)
    GUICtrlCreateLabel("", $sX + 1, $sY -1, $sW - 1, 2)
    GUICtrlSetState(-1,$GUI_DISABLE)
    GUICtrlCreateLabel("", ($sX + $sW) - 1, $sY -1, 2, $sH + 1)
    GUICtrlSetState(-1,$GUI_DISABLE)
    GUICtrlCreateLabel("", $sX + 1, ($sY + $sH) - 1, $sW - 1, 2)
    GUICtrlSetState(-1,$GUI_DISABLE)
EndFunc

Cheers

Share this post


Link to post
Share on other sites

windows message handling would do it

i found these code project forum posts

http://www.codeguru.com/forum/archive/index.php/t-79707.html

http://www.codeguru.com/forum/archive/inde...p/t-342904.html

search for 'remove focus rectangle' in google

don't know how to code this one, looks like handle WM_ACTIVATE and WM_SETFOCUS messages for slider hwnd

Hi,

That dotted rect is a focus rectangle.

To get rid of it try to handle WM_SETFOCUS for slider, and after call to default handler do this:

CClientDC dc(this);

CRect rctClient;

GetClientRect(&rctClient);

//Next call should erase focus rect if rctClient matches the rect which was used for drawing

//default focus. Otherwise, try to deflate rctClient slightly.

dc.DrawFocusRect(rctClient);

Hope this helps,

Oleg.


I see fascists...

Share this post


Link to post
Share on other sites

Hmm...I was hoping it would be easier...looks like I'll need to dig out my old copy of Petzold...

Spoofing Windows messages, ya just gotta love it.

Now where is that bloody big Petzold book, I think it was being a door stop in the attic... :)

Share this post


Link to post
Share on other sites

Ok, I wipped up a quick example based on code lifted from elsewhere on the forum trying to grab just the setfocus from a particular slider...but it doesn't seen to get the slider setfocus. What did I get wrong?

#include <GuiConstants.au3>

Global Const $WM_ACTIVATE = 0x0006

Global Const $WM_SETFOCUS = 0x0007

Global Const $WM_HSCROLL = 0x0114

Global Const $WM_VSCROLL = 0x0115

Global $slider_ctrl_id[2]

$Gui = GuiCreate("Slider Update Demo", 250, 200)

GUIRegisterMsg($WM_HSCROLL, "WM_HVSCROLL")

GUIRegisterMsg($WM_VSCROLL, "WM_HVSCROLL")

GUIRegisterMsg($WM_ACTIVATE, "WM_ACTIVATE")

For $i = 0 To 1

$slider_ctrl_id[$i] = GUICtrlCreateSlider(20 + 20*$i, 50, 30, 120, $TBS_VERT)

Next

$Vertical_Label = GUICtrlCreateLabel("Vertical Slider Read: 0", 20, 20, 200)

$Horizontal_Label = GUICtrlCreateLabel("Horizontal Slider Read: 0", 80, 120, 200)

$misc_label = GUICtrlCreateLabel("lala", 120, 130, 50, 50)

;$Vertical_Slider = GUICtrlCreateSlider(20, 50, 30, 120, BitOr($GUI_SS_DEFAULT_SLIDER, $TBS_VERT))

;$Horizontal_Slider = GUICtrlCreateSlider(60, 150, 160, 30)

GUISetState()

While 1

$Msg = GUIGetMsg()

Switch $Msg

Case -3

Exit

EndSwitch

WEnd

Func WM_HVSCROLL($hWndGUI, $MsgID, $WParam, $LParam)

Switch $LParam

Case GUICtrlGetHandle($slider_ctrl_id[0])

GUICtrlSetData($Vertical_Label, "Vertical Slider Read: " & GUICtrlRead($slider_ctrl_id[0]))

Case GUICtrlGetHandle($slider_ctrl_id[1])

GUICtrlSetData($Horizontal_Label, "Horizontal Slider Read: " & GUICtrlRead($slider_ctrl_id[1]))

EndSwitch

EndFunc

Func WM_ACTIVATE($hWndGUI, $MsgID, $WParam, $LParam)

Switch $LParam

Case GUICtrlGetHandle($slider_ctrl_id[0])

MsgBox(0,"",$LParam)

GUICtrlSetData($misc_label, "")

EndSwitch

EndFunc

Share this post


Link to post
Share on other sites

Problem is that GuiRegisterMsg() doesn't catch messages of controls, only the window.

You'd have to subclass the slider control.

First have to get this Callback UDF.

And then like this

(merge of your code and subclass example from Callback UDF)

#include <GuiConstants.au3>
#include "DllCallBack.au3"

Global Const $WM_SETFOCUS = 0x0007

$Gui = GUICreate("Slider Update Demo", 250, 200)
$Vertical_Label = GUICtrlCreateLabel("Vertical Slider Read: 0", 20, 20, 200)
$Horizontal_Label = GUICtrlCreateLabel("Horizontal Slider Read: 0", 80, 120, 200)
$Vertical_Slider = GUICtrlCreateSlider(20, 50, 30, 120, BitOr($GUI_SS_DEFAULT_SLIDER, $TBS_VERT))
$Horizontal_Slider = GUICtrlCreateSlider(60, 150, 160, 30)

; Register callback function
$pMyWindowProc = _DllCallBack ("_MyWindowProc", "hwnd;uint;long;ptr", $_DllCallBack_Subclass)
; Retrieve a pointer to the original WindowProc and set the new one to our Callback function
$pOriginalWindowProc = _WinSubclass(GUICtrlGetHandle($Horizontal_Slider), $pMyWindowProc)
_WinSubclass(GUICtrlGetHandle($Vertical_Slider), $pMyWindowProc)

GUISetState()
While 1
    Switch GUIGetMsg()
        Case -3
            _DllCallBack_Free($pOriginalWindowProc)
            Exit
    EndSwitch
WEnd

Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam)
    ;Fake setfocus
    If $uiMsg = $WM_SETFOCUS Then Return 0
    ; Returning a Pointer to the original WindowProc means: We did not process this message.
    ; Do not call CallWindowProc() api yourself, the stub will do that for you!
    Return $pOriginalWindowProc
EndFunc   ;==>_MyWindowProc

;-- Wrapper for SetWindowLong API
Func _WinSubclass($hWnd, $lpNewWindowProc)
    ;#define GWL_WNDPROC (-4)
    Local $aTmp, $sFunc = "SetWindowLong"
    If @Unicode Then $sFunc &= "W"
    $aTmp = DllCall("user32.dll", "ptr", $sFunc, "hwnd", $hWnd, "int", -4, "ptr", $lpNewWindowProc)
    If @error Then Return SetError(1, 0, 0)
    If $aTmp[0] = 0 Then Return SetError(1, 0, 0)
    Return $aTmp[0]
EndFunc   ;==>_WinSubclass

Your choice if it's worth the trouble or not.


"be smart, drink your wine"

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Problem is that GuiRegisterMsg() doesn't catch messages of controls, only the window.

You'd have to subclass the slider control.

First have to get this Callback UDF.

And then like this

(merge of your code and subclass example from Callback UDF)

#include <GuiConstants.au3>
#include "DllCallBack.au3"

Global Const $WM_SETFOCUS = 0x0007

$Gui = GUICreate("Slider Update Demo", 250, 200)
$Vertical_Label = GUICtrlCreateLabel("Vertical Slider Read: 0", 20, 20, 200)
$Horizontal_Label = GUICtrlCreateLabel("Horizontal Slider Read: 0", 80, 120, 200)
$Vertical_Slider = GUICtrlCreateSlider(20, 50, 30, 120, BitOr($GUI_SS_DEFAULT_SLIDER, $TBS_VERT))
$Horizontal_Slider = GUICtrlCreateSlider(60, 150, 160, 30)

; Register callback function
$pMyWindowProc = _DllCallBack ("_MyWindowProc", "hwnd;uint;long;ptr", $_DllCallBack_Subclass)
; Retrieve a pointer to the original WindowProc and set the new one to our Callback function
$pOriginalWindowProc = _WinSubclass(GUICtrlGetHandle($Horizontal_Slider), $pMyWindowProc)
_WinSubclass(GUICtrlGetHandle($Vertical_Slider), $pMyWindowProc)

GUISetState()
While 1
    Switch GUIGetMsg()
        Case -3
            _DllCallBack_Free($pOriginalWindowProc)
            Exit
    EndSwitch
WEnd

Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam)
    ;Fake setfocus
    If $uiMsg = $WM_SETFOCUS Then Return 0
    ; Returning a Pointer to the original WindowProc means: We did not process this message.
    ; Do not call CallWindowProc() api yourself, the stub will do that for you!
    Return $pOriginalWindowProc
EndFunc   ;==>_MyWindowProc

;-- Wrapper for SetWindowLong API
Func _WinSubclass($hWnd, $lpNewWindowProc)
    ;#define GWL_WNDPROC (-4)
    Local $aTmp, $sFunc = "SetWindowLong"
    If @Unicode Then $sFunc &= "W"
    $aTmp = DllCall("user32.dll", "ptr", $sFunc, "hwnd", $hWnd, "int", -4, "ptr", $lpNewWindowProc)
    If @error Then Return SetError(1, 0, 0)
    If $aTmp[0] = 0 Then Return SetError(1, 0, 0)
    Return $aTmp[0]
EndFunc   ;==>_WinSubclass

Your choice if it's worth the trouble or not.

Siao, youre're ahead of me on understanding subclassing. So this question is more to do with helping me to understand it.

I looks to me like subclassing is a process of 'diverting' a notification from a control so that you can change it's behaviour. (I will start reading up on this ) But if that's the case, how does it work with a slider control which doesn't give any notifications?

No doubt my question makes my lack of understanding obvious but I hope you can sort me out.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Siao, youre're ahead of me on understanding subclassing. So this question is more to do with helping me to understand it.

I looks to me like subclassing is a process of 'diverting' a notification from a control so that you can change it's behaviour. (I will start reading up on this ) But if that's the case, how does it work with a slider control which doesn't give any notifications?

No doubt my question makes my lack of understanding obvious but I hope you can sort me out.

Subclassing is defining a custom message handling procedure, which will override default windowproc by taking place before it (and either handling a message by itself, or passing it down to the default proc). Controls have their own window procs. Parent window has it's own. With GuiRegisterMsg() you only hook up the main window's proc - it doesn't "see" messages sent for controls (which is the case here - there are messages, including WM_SETFOCUS, you can see those with Winspector Spy for example). With that Callback/Subclass thing you hook up the control's proc.

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

Thanks Siao,

I forgot/overlooked the parent/child thing.

Thanks for the example.

I see the example accomplishes some of what my original intent.

It does not create a focus rectangle when the mouse activates the control.

Unfortunately, it displays part of the focus rectangle as the slider is moved.

Any idea what message is causing that?

Share this post


Link to post
Share on other sites

I'm trying to do the same thing...remove dots around slider, but I'm getting a critical error and it is crapping out on me when I try to run my slightly modified version since the callback is incorporated now.

The error is:

!>19:39:54 AutoIT3.exe ended.rc:-1073741819

#include <GuiConstants.au3>
;#include "DllCallBack.au3"

;Global Const $WM_SETFOCUS = 0x0007
Global Const $_DllCallBack_Subclass = 4
$Gui = GUICreate("Slider Update Demo", 250, 200)
$Vertical_Label = GUICtrlCreateLabel("Vertical Slider Read: 0", 20, 20, 200)
$Horizontal_Label = GUICtrlCreateLabel("Horizontal Slider Read: 0", 80, 120, 200)
$Vertical_Slider = GUICtrlCreateSlider(20, 50, 30, 120, BitOr($GUI_SS_DEFAULT_SLIDER, $TBS_VERT))
$Horizontal_Slider = GUICtrlCreateSlider(60, 150, 160, 30)

; Register callback function
$pMyWindowProc = DllCallbackRegister("_MyWindowProc", "hwnd;uint;long;ptr", $_DllCallBack_Subclass)
; Retrieve a pointer to the original WindowProc and set the new one to our Callback function
$pOriginalWindowProc = _WinSubclass(GUICtrlGetHandle($Horizontal_Slider), $pMyWindowProc)
_WinSubclass(GUICtrlGetHandle($Vertical_Slider), $pMyWindowProc)

GUISetState()
While 1
    Switch GUIGetMsg()
        Case -3
            DllCallBackFree($pOriginalWindowProc)
            Exit
    EndSwitch
WEnd

Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam)
    ;Fake setfocus
    If $uiMsg = $WM_SETFOCUS Then Return 0
    ; Returning a Pointer to the original WindowProc means: We did not process this message.
    ; Do not call CallWindowProc() api yourself, the stub will do that for you!
    Return $pOriginalWindowProc
EndFunc   ;==>_MyWindowProc

;-- Wrapper for SetWindowLong API
Func _WinSubclass($hWnd, $lpNewWindowProc)
    ;#define GWL_WNDPROC (-4)
    Local $aTmp, $sFunc = "SetWindowLong"
    If @Unicode Then $sFunc &= "W"
    $aTmp = DllCall("user32.dll", "ptr", $sFunc, "hwnd", $hWnd, "int", -4, "ptr", $lpNewWindowProc)
    If @error Then Return SetError(1, 0, 0)
    If $aTmp[0] = 0 Then Return SetError(1, 0, 0)
    Return $aTmp[0]
EndFunc   ;==>_WinSubclass

Also, how do I get this to work on an onevent script?

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

"slightly modified" so it wouldn't work with neither DllCallback.au3 nor DllCallbackRegister() :D

Have you even checked DllCallbackRegister reference in the helpfile? The parameters you are passing don't make sense.

Basic template for subclassing would be (needs beta for CallWindowProc wrapper, or you could DllCall that function directly):

; create your GUI, controls...
;

; subclass the window/control:
$wProcNew = DllCallbackRegister("_NewWindowProc", "int", "hwnd;uint;wparam;lparam")
$wProcOld = _WinAPI_SetWindowLong($hWndTarget, $GWL_WNDPROC, DllCallbackGetPtr($wProcNew));where $hWndTarget is the handle of window/control, as returned by GuiCreate(), GuiCtrlGetHandle(), etc.

; your custom callback function:
Func _NewWindowProc($hWnd, $Msg, $wParam, $lParam)
;do whatever you need, for example:
    Switch $Msg
        Case $WM_COMMAND
            ConsoleWrite("You have WM_COMMAND message." & @CRLF)
        Case $WM_NOTIFY
            ConsoleWrite("You have WM_NOTIFY message." & @CRLF)
    EndSwitch
    
;pass the unhandled messages to default WindowProc
    Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $uiMsg, $wParam, $lParam)
EndFunc

; optional - restoring default WindowProc and/or cleaning up on Exit, just to play nice:
_WinAPI_SetWindowLong($hWndTarget, $GWL_WNDPROC, $wProcOld)
DllCallbackFree($wProcNew)

Everything else (such as OnEvent/GuiGetMsg mode choice) is irrelevant.

Edited by Siao

"be smart, drink your wine"

Share this post


Link to post
Share on other sites

#15 ·  Posted

Thanks, I did look at the DllCallbackRegister reference, just not properly...I didn't notice the change around, when I glanced at it in there, I just immediately switched the functions around to match. Anyway, I couldn't get this working...probably because I was trying to get it to work with dll instead of the beta...don't really want to play with the beta. So I decided to go ahead and deal with the DllCallback.au3. Seemed alright at first, then I noticed it stopped numerous other functions from working. Could I get a little more help on this please with your new version using the dll version?

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

Thanks, I did look at the DllCallbackRegister reference, just not properly...I didn't notice the change around, when I glanced at it in there, I just immediately switched the functions around to match. Anyway, I couldn't get this working...probably because I was trying to get it to work with dll instead of the beta...don't really want to play with the beta. So I decided to go ahead and deal with the DllCallback.au3. Seemed alright at first, then I noticed it stopped numerous other functions from working. Could I get a little more help on this please with your new version using the dll version?

Smashly has shown a much easier way, and BigDod was nearly there.

Here is smashly's solution, a bit different and made into a little function.

#include <GUIConstants.au3>
Opt("mousecoordmode", 2)

$Form1 = GUICreate("Form1", 633, 454, 193, 115)
$Slider1 = _GUICtrlCreateSliderB(120, 96, 145, 49)
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch

WEnd

;create a slider with no dotted border

Func _GUICtrlCreateSliderB($x, $y, $w, $h)
    Local $sld = GUICtrlCreateSlider($x, $y, $w, $h, $WS_CLIPSIBLINGS)
    GUICtrlCreateLabel("", $x, $y - 1, $w, 2)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlCreateLabel("", $x, $y + $h - 1, $w, 2)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlCreateLabel("", $x - 1, $y, 2, $h)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlCreateLabel("", $x + $w - 1, $y, 2, $h)
    GUICtrlSetState(-1, $GUI_DISABLE)
    Return $sld
    Return $sld
EndFunc ;==>_GUICtrlCreateSliderB

EDIT: made a function to create the slider.

EDIT 2: credited smashly and added the disable lines for the labels as he did because without that it is still possible to get the dotted lines to show.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#17 ·  Posted

I think there is a much easier way, and BigDod was nearly there I think.

.......
Nice that you added the slider to inside the function :)

huh hum.. looks similar

Cheers

Share this post


Link to post
Share on other sites

#18 ·  Posted

Nice that you added the slider to inside the function :)

huh hum.. looks similar

Cheers

smashly,

I hadn't noticed that, I got the idea from BigDod's post, or so I thought, but you obviously beat me to it by a long way, and looking at what you did it's hard to believe I didn't copy it. Either it's a case of great minds... or maybe I am able to take things in without realising it. I'll make sure you are credited.

martin


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#19 ·  Posted

In the smashly/ martin example, there is a tiny mistake.

In the _GUICtrlCreateSliderB( ) function, the line:-

GUICtrlCreateLabel("", $x + $w - 1, $y, 2, $y)

should be

GUICtrlCreateLabel("", $x + $w - 1, $y, 2, $h)

When a vertical slider is created, it is obvious, when you find it, that the last $y should be the $h variable.

Share this post


Link to post
Share on other sites

#20 ·  Posted

In the smashly/ martin example, there is a tiny mistake.

In the _GUICtrlCreateSliderB( ) function, the line:-

GUICtrlCreateLabel("", $x + $w - 1, $y, 2, $y)

should be

GUICtrlCreateLabel("", $x + $w - 1, $y, 2, $h)

When a vertical slider is created, it is obvious, when you find it, that the last $y should be the $h variable.

Thanks Malkey, correction made.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

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