Jump to content

Colored Button Reacts to the Enter key used in an Input box.


Go to solution Solved by Dan_555,

Recommended Posts

Posted (edited)

Hi, 

somehow this button reacts to the Enter from the input box. 

Try pressing enter in the input box, to see that it is not reacting.

Then click on the test button and then activate the input box and press enter few times. 

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiEdit.au3>

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Test", 207, 369)
$Inp1 = GUICtrlCreateInput("0", 2, 19, 121, 22)
GUICtrlSetFont($Inp1, 12, 700, 0, "Ubuntu Mono")

$BTN01 = GUICtrlCreateButton("TEST", 70, 0, 40, 16)
GUICtrlSetBkColor($BTN01, 0x00FF00)
GUICtrlSetFont($BTN01, 8, 700, 0, "Ubuntu Mono")

$Edit1 = GUICtrlCreateEdit("", 3, 86, 201, 281)
GUICtrlSetData($Edit1, "")
GUICtrlSetFont($Edit1, 10, 700, 0, "Consolas")
GUICtrlSetLimit($Edit1, 15000000)

GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
;"            "

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $BTN01
                GUICtrlSetData ($Edit1,"Test" & @CRLF,1)
    EndSwitch
WEnd

So far i have located the error. 

If you remove the GUICtrlSetBkColor($BTN01, 0x00FF00)  line, the script is working as intended.

Any ideas of why is this happening  or how to fix this to work as a colored button ?

Edited by Dan_555

Some of my script sourcecode

Posted
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3> ;;; https://www.autoitscript.com/forum/topic/213492-button-reacts-to-the-enter-key-used-in-an-input-box/
#include <GuiEdit.au3>

Opt("GUIOnEventMode", 1)

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Test", 207, 369)
GUISetOnEvent($GUI_EVENT_CLOSE, OnEvent_CLOSE)

$Inp1 = GUICtrlCreateInput("0", 2, 19, 121, 22)
GUICtrlSetFont($Inp1, 12, 700, 0, "Ubuntu Mono")
GUICtrlSetOnEvent(-1, OnEvent_Inp1)

$Edit1 = GUICtrlCreateEdit("", 3, 86, 201, 281)
GUICtrlSetData($Edit1, "")
GUICtrlSetFont($Edit1, 10, 700, 0, "Consolas")
GUICtrlSetLimit($Edit1, 15000000)
GUICtrlSetOnEvent(-1, OnEvent_Edit1)

$BTN1 = GUICtrlCreateButton("TEST", 70, 0, 40, 16)
GUICtrlSetFont($BTN1, 8, 700, 0, "Ubuntu Mono")
GUICtrlSetBkColor($BTN1, 0x00F000)
GUICtrlSetOnEvent(-1, OnEvent_BTN1)


GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
;"            "

While 1
    Sleep(100)
WEnd

;~  $nMsg = GUIGetMsg()
;~  Switch $nMsg
;~      Case $GUI_EVENT_CLOSE
;~          Exit
;~      Case $BTN1
;~          GUICtrlSetData($Edit1, "Test" & @CRLF, 1)
;~  EndSwitch
;~ WEnd


Func OnEvent_CLOSE()
    GUIDelete()
    Exit
EndFunc

Func OnEvent_Inp1()
    GUICtrlSetData($Edit1, "Inp1" & @CRLF, 1)
EndFunc

Func OnEvent_Edit1()
;~  GUICtrlSetData($Edit1, "Edit1" & @CRLF, 1)
EndFunc

Func OnEvent_BTN1()
    GUICtrlSetData($Edit1, "Test" & @CRLF, 1)
EndFunc

Also happens on event.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • Solution
Posted (edited)

Ok, i have found a 'workaround' for this problem.

The solution is to Create another colored button, which does nothing. I made one with the coordinates/size of 1,1,1,1 which makes it  invisible.

Then after using each colored button, add ControlClick to this button and it will catch the input/return instead.

  

#include <GUIConstantsEx.au3>

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Test", 207, 280)
$Inp1 = GUICtrlCreateInput("0", 2, 19, 121, 22)
GUICtrlSetFont($Inp1, 12, 700, 0, "Ubuntu Mono")

$BTNNOTHING = GUICtrlCreateButton("TEST", 1,1, 1, 1)
GUICtrlSetBkColor($BTNNOTHING, 0x00FF00)

$BTN01 = GUICtrlCreateButton("TEST", 70, 0, 40, 16)
GUICtrlSetFont($BTN01, 8, 700, 0, "Ubuntu Mono")
GUICtrlSetBkColor($BTN01, 0x00FF00)

$Edit1 = GUICtrlCreateEdit("", 3, 86, 201, 181)
GUICtrlSetData($Edit1, "")
GUICtrlSetFont($Edit1, 10, 700, 0, "Consolas")
GUICtrlSetLimit($Edit1, 15000000)

GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
;"            "

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $BTN01
                GUICtrlSetData ($Edit1,"Test" & @CRLF,1)
                ControlClick($Form1,"",$BTNNOTHING)
    EndSwitch
WEnd

 

Edited by Dan_555

Some of my script sourcecode

  • Dan_555 changed the title to Colored Button Reacts to the Enter key used in an Input box.
Posted (edited)

I'm not sure if this was mentioned in the other thread, but after a bit of a play I found GUICtrlSetBkColor() is adding the $BS_DEFPUSHBUTTON style to the button. 

You can revoke it, but it breaks the custom drawing:

$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn),  $GWL_STYLE)
ConsoleWrite("Old Style: " & Hex($iStyle, 8) & @CRLF)
$iStyle = BitAnd(BitNOT($BS_DEFPUSHBUTTON), $iStyle)
_WinAPI_SetWindowLong(GUICtrlGetHandle($idBtn), $GWL_STYLE, $iStyle)
$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn),  $GWL_STYLE)
ConsoleWrite("New Style: " & Hex($iStyle, 8) & @CRLF)

Basically when you press enter in an edit without ES_WANTRETURN, it sends a WM_COMMAND a message that IDOK was clicked.  But if you have a default button defined, that gets sent in place of IDOK.. (Edit: to clarify,  this is expected behavior if you have a default button!)

As a side, when you change the text of the input box and press enter - autoit also sends a WM_COMMAND containing the ControlID of the edit, and a notification code of 0. This one isn't a normally sent by windows - so i guess its part of the mechanism for GuiGetMsg. 

Edited by MattyD
Posted (edited)

  It is curious that the button doesn't initially act like a "default" button though, despite having the style. Once the green button takes focus (clicking, or tabbing past it) it starts to act like a default button should (You just get IDOKs before then!)

Manually setting $DEFPUSHBUTTON (without the GuiCtrlSetBkCol) acts as you'd expect. So there's some funky stuff going on in there...

Nevermind, it seems you need to send DM_SETDEFID to the parent for the default button to take effect. But autoit obviously does that on your behalf..

#AutoIt3Wrapper_UseX64=Y

#include <WinAPI.au3>
#include <GuiConstants.au3>
#include <AutoItConstants.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>

Global $mEdtMsg[]
$mEdtMsg[0x0100] = "EN_SETFOCUS"
$mEdtMsg[0x0200] = "EN_KILLFOCUS"
$mEdtMsg[0x0300] = "EN_CHANGE"
$mEdtMsg[0x0400] = "EN_UPDATE"
$mEdtMsg[0x0500] = "EN_ERRSPACE"
$mEdtMsg[0x0501] = "EN_MAXTEXT"
$mEdtMsg[0x0601] = "EN_HSCROLL"
$mEdtMsg[0x0602] = "EN_VSCROLL"
$mEdtMsg[0x0700] = "EN_ALIGN_LTR_EC"
$mEdtMsg[0x0701] = "EN_ALIGN_RTL_EC"

Global $mBtnMsg[]
$mBtnMsg[0x0000] = "BN_CLICKED"
$mBtnMsg[0x0001] = "BN_PAINT"
$mBtnMsg[0x0002] = "BN_PUSHED"
$mBtnMsg[0x0003] = "BN_UNPUSHED"
$mBtnMsg[0x0004] = "BN_DISABLE"
$mBtnMsg[0x0005] = "BN_DBLCLK"
$mBtnMsg[0x0006] = "BN_SETFOCUS"
$mBtnMsg[0x0007] = "BN_KILLFOCUS"

Global $hGUI = GUICreate("Test GUI", 200, 220)
Global $idBtn1 = GUICtrlCreateButton("Button1", 4, 4, 96, 25)
Global $idBtn2 = GUICtrlCreateButton("Button2", 102, 4, 96, 25)
Global $idInput = GUICtrlCreateInput("Input", 4, 33, 192, 25)
Global $idEdit = GUICtrlCreateEdit("", 4, 62, 192, 150)

Global $mCtrlNames[]
$mCtrlNames[$IDOK] = "IDOK"
$mCtrlNames[$IDCANCEL] = "IDCANCEL"
$mCtrlNames[$idBtn1] = "Button1"
$mCtrlNames[$idBtn2] = "Button2"
$mCtrlNames[$idInput] = "Input"
$mCtrlNames[$idEdit] = "Edit"

$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn2), $GWL_STYLE)
ConsoleWrite("Original Style    : " & Hex($iStyle, 8) & @CRLF)

GuiCtrlSetBkColor($idBtn2, 0x00FF00)

$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn2), $GWL_STYLE)
ConsoleWrite("SetBkCol Style    : " & Hex($iStyle, 8) & @CRLF)

;Clear $BS_DEFPUSHBUTTON
;~ $iStyle = BitAnd(BitNOT($BS_DEFPUSHBUTTON), $iStyle)
;~ ConsoleWrite("Def Cleared Style : " & Hex($iStyle, 8) & @CRLF)
;~ $iStyle = _WinAPI_SetWindowLong(GUICtrlGetHandle($idBtn2), $GWL_STYLE, $iStyle)

$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn2), $GWL_STYLE)
ConsoleWrite("Final Style       : " & Hex($iStyle, 8) & @CRLF)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUISetState()

Local $iMsg
While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

GUIDelete($hGUI)

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Local $iNotifCode = _WinAPI_HiWord($wParam)
    Local $iCtrlId = _WinAPI_LoWord($wParam)
    Local $hCtrl = $lParam
    Local $sCode

    Switch _WinAPI_GetClassName($lParam)
        Case "Edit"
            If MapExists($mEdtMsg, $iNotifCode) Then $sCode = $mEdtMsg[$iNotifCode]
        Case "Button"
            If MapExists($mBtnMsg, $iNotifCode) Then $sCode = $mBtnMsg[$iNotifCode]
    EndSwitch

    ConsoleWrite(StringFormat("%-20s %-10s %-20s Hwnd: %-10s \r\n", _
            "WM_COMMAND", _
            MapExists($mCtrlNames, $iCtrlId) ? $mCtrlNames[$iCtrlId] : $iCtrlId,  _
            $sCode ? $sCode : Hex($iNotifCode, 4), _
            $lParam))

    Return $GUI_RUNDEFMSG
EndFunc
Edited by MattyD
Posted

@MattyD Yes very funky.  Moreover if you check the style you see something unexpected.

#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <GuiButton.au3>
#include <WindowsConstants.au3>

ConsoleWrite(Hex($WS_CHILD) & "/" & Hex($WS_TABSTOP) & "/" & Hex($WS_VISIBLE) & "/" & Hex($BS_NOTIFY) & "/" & Hex($BS_OWNERDRAW) & @CRLF)

$Form1 = GUICreate("Test", 207, 280)

$idBtn = GUICtrlCreateButton("Non UDF", 10, 10, 100, 25)
$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn),  $GWL_STYLE)
ConsoleWrite("before: " & Hex($iStyle, 8) & @CRLF)
GUICtrlSetBkColor(-1, 0x00FF00)
$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn),  $GWL_STYLE)
ConsoleWrite("after: " & Hex($iStyle, 8) & @CRLF)

$hBtn = _GUICtrlButton_Create($Form1, "UDF", 10, 40, 100, 25, $BS_OWNERDRAW)
$iStyle = _WinAPI_GetWindowLong($hBtn,  $GWL_STYLE)
ConsoleWrite("udf: " & Hex($iStyle, 8) & @CRLF)

$idBtn2 = GUICtrlCreateButton("Non UDF 2", 10, 70, 100, 25, $BS_OWNERDRAW)
$iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($idBtn2),  $GWL_STYLE)
ConsoleWrite("after 2: " & Hex($iStyle, 8) & @CRLF)

GUISetState(@SW_SHOW)

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

Setting color of standard button seems to set BS_OWNERDRAW (not $BS_DEFPUSHBUTTON)

But trying to set BS_OWNERDRAW on standard button seems to set $BS_DEFPUSHBUTTON instead.

 

 

Posted

Oh ok that's a rookie mistake on my end -  I was treating it like a bitfield, which we obviously shouldn't be doing!  

$BS_OWNERDRAW = 0x0B which contains a 1 ($BS_DEFPUSHBUTTON).  I reckon that control proc is probably making the same mistake. (looking for BS_DEFPUSHBUTTON when the button is selected, then sending DM_SETDEFID)

Posted (edited)
40 minutes ago, Nine said:

But trying to set BS_OWNERDRAW on standard button seems to set $BS_DEFPUSHBUTTON instead.

Maybe its trying to clear 0x08 / 0x02 (BS_CHECKBOX, BS_RADIOBUTTON) given its a push button?? that leaves the 1 at the end.. just speculating.

0x0B (BS_OWNERDRAW) = 0x08 + 0x02 + 0x01

Edit: ok BS_RADIOBUTTON value was wrong too... apologies, need to go to sleep!

Edited by MattyD
Posted (edited)

@Dan_555 sorry for the hijack - let me know if you'd rather I jump into another thread. 

So... there is a BS_TYPEMASK of 0x0F... And 0x00 through 0x0F are all different button types that should be mutually exclusive:

Global Const $BS_PUSHBUTTON = 0x0000
Global Const $BS_DEFPUSHBUTTON = 0x0001
Global Const $BS_CHECKBOX = 0x0002
Global Const $BS_AUTOCHECKBOX = 0x0003
Global Const $BS_RADIOBUTTON = 0x0004
Global Const $BS_3STATE = 0x0005
Global Const $BS_AUTO3STATE = 0x0006
Global Const $BS_GROUPBOX = 0x0007
Global Const $BS_USERBUTTON = 0x0008
Global Const $BS_AUTORADIOBUTTON = 0x0009
Global Const $BS_PUSHBOX = 0x000A
Global Const $BS_OWNERDRAW = 0x000B
Global Const $BS_SPLITBUTTON = 0x000C
Global Const $BS_DEFSPLITBUTTON = 0x000D
Global Const $BS_COMMANDLINK = 0x000E
Global Const $BS_DEFCOMMANDLINK = 0x000F

When you GuiCtrlCreateButton() you don't always get what you ask for.  (requested Type -> resulting Type) 

00000000 -> 50030000 ( BS_PUSHBUTTON      -> BS_PUSHBUTTON      )
00000001 -> 50010001 ( BS_DEFPUSHBUTTON   -> BS_DEFPUSHBUTTON   )
00000002 -> 50010002 ( BS_CHECKBOX        -> BS_CHECKBOX        )
00000003 -> 50010002 ( BS_AUTOCHECKBOX    -> BS_CHECKBOX        )
00000004 -> 50010004 ( BS_RADIOBUTTON     -> BS_RADIOBUTTON     )
00000005 -> 50010004 ( BS_3STATE          -> BS_RADIOBUTTON     )
00000006 -> 50010006 ( BS_AUTO3STATE      -> BS_AUTO3STATE      )
00000007 -> 50010006 ( BS_GROUPBOX        -> BS_AUTO3STATE      )
00000008 -> 50010000 ( BS_USERBUTTON      -> BS_PUSHBUTTON      )
00000009 -> 50010001 ( BS_AUTORADIOBUTTON -> BS_DEFPUSHBUTTON   )
0000000A -> 5001000A ( BS_PUSHBOX         -> BS_PUSHBOX         )
0000000B -> 50010001 ( BS_OWNERDRAW       -> BS_DEFPUSHBUTTON   )
0000000C -> 5001000C ( BS_SPLITBUTTON     -> BS_SPLITBUTTON     )
0000000D -> 5001000D ( BS_DEFSPLITBUTTON  -> BS_DEFSPLITBUTTON  )
0000000E -> 5001000E ( BS_COMMANDLINK     -> BS_COMMANDLINK     )
0000000F -> 5001000F ( BS_DEFCOMMANDLINK  -> BS_DEFCOMMANDLINK  )

Just a quick comment on the other styles, All buttons initially get: 0x5001000n OR 0x5003000n

  • $WS_CHILD (0x40000000)
  • $WS_VISIBLE (0x10000000)
  • $WS_TABSTOP (0x00010000),
  • The first button created also gets $WS_GROUP (0x00020000) (this makes sense)

And when you click on a button the styles also change: It seems AutoIt tries to set a "default" style to the last button pushed)

50030000 -> 50030001 ( BS_PUSHBUTTON      -> BS_DEFPUSHBUTTON   )
50010001 -> 50010001 ( BS_DEFPUSHBUTTON   -> BS_DEFPUSHBUTTON   )
50010002 -> 50010002 ( BS_CHECKBOX        -> BS_CHECKBOX        )
50010004 -> 50010004 ( BS_RADIOBUTTON     -> BS_RADIOBUTTON     )
50010006 -> 50010006 ( BS_AUTO3STATE      -> BS_AUTO3STATE      )
50010000 -> 50010001 ( BS_PUSHBUTTON      -> BS_DEFPUSHBUTTON   )
5001000A -> 50010001 ( BS_PUSHBOX         -> BS_DEFPUSHBUTTON   )
5001000C -> 5001000D ( BS_SPLITBUTTON     -> BS_DEFSPLITBUTTON  )
5001000D -> 5001000D ( BS_DEFSPLITBUTTON  -> BS_DEFSPLITBUTTON  )
5001000E -> 5001000F ( BS_COMMANDLINK     -> BS_DEFCOMMANDLINK  )
5001000F -> 5001000F ( BS_DEFCOMMANDLINK  -> BS_DEFCOMMANDLINK  )

OK so looking through the list..  (More just dumping my thoughts.  I'm not lobbying for action,  I think this is a "Won't fix" anyway)
We should cut the Radio/Checkbox/Group styles some slack - it s a misuse of the func to create those with GuiCtrlCreateButton... Maybe forcing them to be BS_PUSHBUTTONs on creation could make sense? but anyway...

Requested          |  Result            |  Clicked           | Notes  
-------------------------------------------------------------+----------------------------------------------------------------------
BS_PUSHBUTTON      -> BS_PUSHBUTTON     -> BS_DEFPUSHBUTTON  | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_DEFPUSHBUTTON   -> BS_DEFPUSHBUTTON  -> BS_DEFPUSHBUTTON  | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_CHECKBOX        -> BS_CHECKBOX       -> BS_CHECKBOX       | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_AUTOCHECKBOX    -> BS_CHECKBOX       -> BS_CHECKBOX       | Why not keep as BS_AUTOCHECKBOX?
-------------------------------------------------------------+----------------------------------------------------------------------
BS_RADIOBUTTON     -> BS_RADIOBUTTON    -> BS_RADIOBUTTON    | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_3STATE          -> BS_RADIOBUTTON    -> BS_RADIOBUTTON    | Checkbox turns into a radio button?
-------------------------------------------------------------+----------------------------------------------------------------------
BS_AUTO3STATE      -> BS_AUTO3STATE     -> BS_AUTO3STATE     | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_GROUPBOX        -> BS_AUTO3STATE     -> BS_AUTO3STATE     | Group turns into a checkbox?
-------------------------------------------------------------+----------------------------------------------------------------------
BS_USERBUTTON      -> BS_PUSHBUTTON     -> BS_DEFPUSHBUTTON  | Antiquated Windows 16bit style. Turning this into PUSHBUTTON makes sense.
                                                             | Spiritually its probably closer to OWNERDRAW - but thats not supported here either! 
                                                             | (until you GuiCtrlSetBkColor anyway!)
-------------------------------------------------------------+----------------------------------------------------------------------
BS_AUTORADIOBUTTON -> BS_DEFPUSHBUTTON  -> BS_DEFPUSHBUTTON  | Radio turns into pushbutton?
-------------------------------------------------------------+----------------------------------------------------------------------
BS_PUSHBOX         -> BS_PUSHBOX        -> BS_DEFPUSHBUTTON  | Buttons without a frame. 
                                                             | There's no "default" PUSHBOX style, so it probably shouldn't change when clicked.
                                                             | BS_DEFPUSHBUTTON adds a frame, so its visually not consistant either.
                                                             |
                                                             | PUSHBOXes currently transform into BS_PUSHBUTTONs when they're no longer BS_DEFPUSHBUTTONs,
                                                             | so maybe its better to make them BS_PUSHBUTTONs from the outset if the style is not
                                                             | supported.
-------------------------------------------------------------+----------------------------------------------------------------------
BS_OWNERDRAW       -> BS_DEFPUSHBUTTON  -> BS_DEFPUSHBUTTON  | Pehaps should go to BS_PUSHBUTTON rather than BS_DEFPUSHBUTTON? 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_SPLITBUTTON     -> BS_SPLITBUTTON    -> BS_DEFSPLITBUTTON | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_DEFSPLITBUTTON  -> BS_DEFSPLITBUTTON -> BS_DEFSPLITBUTTON | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_COMMANDLINK     -> BS_COMMANDLINK    -> BS_DEFCOMMANDLINK | 
-------------------------------------------------------------+----------------------------------------------------------------------
BS_DEFCOMMANDLINK  -> BS_DEFCOMMANDLINK -> BS_DEFCOMMANDLINK | 
-------------------------------------------------------------+----------------------------------------------------------------------

Test script...

#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <GuiButton.au3>
#include <WindowsConstants.au3>

$Form1 = GUICreate("Test", 330, 290)

Global $asType[] = [ _
"BS_PUSHBUTTON", _
"BS_DEFPUSHBUTTON", _
"BS_CHECKBOX", _
"BS_AUTOCHECKBOX", _
"BS_RADIOBUTTON", _
"BS_3STATE", _
"BS_AUTO3STATE", _
"BS_GROUPBOX", _
"BS_USERBUTTON", _
"BS_AUTORADIOBUTTON", _
"BS_PUSHBOX", _
"BS_OWNERDRAW", _
"BS_SPLITBUTTON", _
"BS_DEFSPLITBUTTON", _
"BS_COMMANDLINK", _
"BS_DEFCOMMANDLINK"]

For $i = 0 To 0x0F
    $iBtn = GUICtrlCreateButton($asType[$i], Mod($i, 2) * 160 + 10, Floor($i/2) * 35 + 10, 150, 25, $i)
    $iStyle = _WinAPI_GetWindowLong(GUICtrlGetHandle($iBtn),  $GWL_STYLE)
    ConsoleWrite(StringFormat("%s -> %s ( %-18s -> %-18s )", _
        Hex($i, 8), _
        Hex($iStyle, 8), _
        $asType[$i], _
        $asType[BitAND($iStyle, 0x0F)]) & @CRLF)
Next

GUISetState()
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
Edited by MattyD
forgot to show gui!
Posted

@MattyD hello :)
Thanks for the detailed button styles, which made me update the list found in Yashied's control viewer, now managed by argumentum.

Could you please confirm what follows with the AutoIt Window Info tool :
If the styles of the button are 0x50010001, will AutoIt Window Info tool report 0x50010001 or 0x50010000 ?

To reproduce it from OP's initial script :

#include <WinAPISysWin.au3>
...
$BTN01 = GUICtrlCreateButton("TEST", 70, 0, 40, 16, $BS_DEFPUSHBUTTON) ; $BS_DEFPUSHBUTTON = 0x0001
; GUICtrlSetBkColor($BTN01, 0x00FF00)
ConsoleWrite(Hex(_WinAPI_GetWindowLong(GUICtrlGetHandle($BTN01), $GWL_STYLE), 8) & @crlf) ; 0x50010001

On my computer AutoIt Window Info tool reports 0x50010000, so why isn't 0x0001 detected by the tool ?
Thanks

 

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

Posted (edited)

Sure thing,

Mine reports correctly if you roll over the button with the mouse (0x50010001) - but when I drop the finder tool on it I get 0x50010000.

It looks to non-default when the parent window deactivates, and default it again on activate. (need to verify the exact trigger)

This example works as expected with window info. Then Un-subclass the parent, re-run, and you'll see where BM_SETSTYLE kicks in.

#include <winAPI.au3>
#include <GUIButton.au3>
#include <GUIConstants.au3>

$hForm1 = GUICreate("Test", 200, 100)
$BTN01 = GUICtrlCreateButton("TEST", 10, 10, 80, 25, $BS_DEFPUSHBUTTON)
$hBtn = GUICtrlGetHandle($BTN01)
GUISetState()

Global $hWndProc = DllCallbackRegister("WndProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")
Global $pWndProc = DllCallbackGetPtr($hWndProc)
Global $hBtnProc = DllCallbackRegister("btnProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")
Global $pBtnProc = DllCallbackGetPtr($hBtnProc)


_WinAPI_SetWindowSubclass($hForm1, $pWndProc, 1000)
_WinAPI_SetWindowSubclass($hBtn, $pBtnProc, 1000)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd

_WinAPI_RemoveWindowSubclass($hBtn, $pBtnProc, 1000)
_WinAPI_RemoveWindowSubclass($hForm1, $pWndProc, 1000)

Func btnProc($hWnd, $iMsg, $wParam, $lParam, $iIdSubclass, $dwRefData)

    If $iMsg = $BM_SETSTYLE Then ConsoleWrite("!NewStyleReq: " & Hex($wParam) & " RedrawReq:" & Hex($lParam) & @CRLF)

    Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc


Func WndProc($hWnd, $iMsg, $wParam, $lParam, $iIdSubclass, $dwRefData)
    Local $iRet

    Switch $iMsg

        Case $WM_SYSCOMMAND, $WM_COMMAND
            $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)

        Case Else
            $iRet = _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam)

    EndSwitch

    Return $iRet
EndFunc   ;==>WndProc

 

Edited by MattyD
clarity
Posted
28 minutes ago, MattyD said:

Mine reports correctly if you roll over the button with the mouse (0x50010001) - but when I drop the finder tool on it I get 0x50010000.

Thanks for the explanation and the script. I finally understood why mine always showed 0x50010000
It's because I got the "Freeze" option checked since ages :

AutoItv3WindowInfo(whenFreezechecked).png.83a8baafe3f04eda4b7f3948b320c5b6.png

When this option is checked, you can't simply roll over a control, you got to keep LMB pressed until you release it, so the parent window (in our example) will never get focus when the Freeze option is checked and you'll never be able to retrieve 0x50010001 when the option is checked (I guess)

As soon as I unchecked it, then it was possible to activate the parent window, then roll over the button control and retrieve 0x50010001 . Also any window/control rolled over reacts nicely when the Freeze option is unchecked, no more need to keep LMB pressed constantly.

I'm not sure Yashied control viewer tool got this "Freeze" option in its menu  but now that I started to use it with AutoIt Window Info tool, I'll probably get addicted to it :D

BM_SETSTYLE... you made me discover that one too today. Always new features to learn from your posts, thanks !

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

Posted

Quick update on this button behavior thing -

Firstly, I think we can write off PUSHBOXes - I think they're a relic of the past and are kinda broken on the OS side.. So we'll put that in the same category as BS_USERBUTTON.

The default button jumping around seems to be partly windows, partly autoit. As you tab though buttons the default button (with style) should move with the KB focus, but this is a temporary thing. When you click away to say an input - the designated default becomes the default. 

To understand whats going on, we need to distinguish between standard window behaviors, standard dialog behaviors, and AutoIt window behaviors. Hopefully AutoIt doesn't subclass the control procs, but I guess its another variable we can't rule out... (ownerdrawn controls are painted by the parent, so GuiCtrlSetBkColor shouldn't need to alter the btn proc to make that work)

I said earlier DM_SETDEFID actually sets the the "default" pushbutton rather than just the look.  Well that only works for dialogs - which is not what we're dealing with!  The internet led me astray there. I'm not sure how to (gracefully) change the default away from IDOK for a normal window yet.

Looking at the BS_DEFPUSHBUTTON doc, it says: "... If the button is in a dialog box, the user can select the button by pressing the ENTER key, even when the button does not have the input focus." And this seems to track.  I made a window as vanilla as humanly possible, and setting  BS_DEFPUSHBUTTON does nothing but change the appearance. Enter triggers IDOK, which usually would be the default. I will test the style on an actual dialog at some point to see if I'm interpreting the doco correctly.

And yes - when you click in the edit box,  IDOK correctly get the "default" style.

;~ #AutoIt3Wrapper_UseX64=N

#include <WinAPI.au3>
#include <SendMessage.au3>
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <GuiButton.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>

Global Const $CW_USEDEFAULT = 0x80000000
Global Const $DM_GETDEFID = $WM_USER
Global Const $DM_SETDEFID = $WM_USER + 1
Global Const $DM_REPOSITION = $WM_USER + 2

Global $hWndProc = DllCallbackRegister("WndProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")
Global $pWndProc = DllCallbackGetPtr($hWndProc)

$hGUI = GUICreate("", 400, 200)
_WinAPI_SetWindowSubclass($hGUI, $pWndProc, 1000)
_WinAPI_ShowWindow($hGUI)


$hbtnOK = _Button_Create($hGUI, $IDOK, "OK", 10, 10, 80, 25, BitOR($WS_CHILD, $WS_VISIBLE, $WS_TABSTOP, $BS_NOTIFY, $WS_GROUP))
$hbtnCancel = _Button_Create($hGUI, $IDCANCEL, "Cancel", 100, 10, 80, 25, BitOR($WS_CHILD, $WS_VISIBLE, $WS_TABSTOP, $BS_NOTIFY))
$hbtnID3 = _Button_Create($hGUI, 3, "ID3", 190, 10, 80, 25, BitOR($WS_CHILD, $WS_VISIBLE, $WS_TABSTOP, $BS_NOTIFY, $BS_PUSHBOX))
_Edit_Create($hGUI, 5, "ID4", 10, 110, 100, 25, BitOR($WS_CHILD, $WS_VISIBLE, $WS_TABSTOP))
_SendMessage($hbtnCancel, $BM_SETSTYLE, $BS_DEFPUSHBUTTON, True)

While WinExists($hGUI)
    Sleep(500)
WEnd

DllCallbackFree($hWndProc)


Func _Edit_Create($hWnd, $idCtrlID, $sText, $iX, $iY, $iWidth, $iHeight, $iStyle = -1, $iExStyle = -1)
    If $iExStyle = -1 Then $iExStyle = 0
    If @error Then Return SetError(@error, @extended, 0)
    Local $hInstance = _WinAPI_GetWindowLong($hWnd, $GWL_HINSTANCE)
    Return _WinAPI_CreateWindowEx($iExStyle, "Edit", $sText, $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd, $idCtrlID, $hInstance)
EndFunc   ;==>_GUICtrlButton_Create

Func _Button_Create($hWnd, $idCtrlID, $sText, $iX, $iY, $iWidth, $iHeight, $iStyle = -1, $iExStyle = -1)
    If $iExStyle = -1 Then $iExStyle = 0
    If @error Then Return SetError(@error, @extended, 0)
    Local $hInstance = _WinAPI_GetWindowLong($hWnd, $GWL_HINSTANCE)
    Return _WinAPI_CreateWindowEx($iExStyle, "Button", $sText, $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd, $idCtrlID, $hInstance)
EndFunc   ;==>_GUICtrlButton_Create

Func WndProc($hWnd, $iMsg, $wParam, $lParam, $iIdSubclass, $dwRefData)
    Local $iRet

    Switch $iMsg

        Case $WM_COMMAND
            ConsoleWrite("WMC " & Hex(_WinAPI_HiWord($wParam), 4) & " id: " & _WinAPI_LoWord($wParam) & @CRLF) ;Notif code: 6 = $BN_SETFOCUS for buttons.

        Case $WM_DESTROY
            _WinAPI_RemoveWindowSubclass($hWnd, $pWndProc, $iIdSubclass)
            Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)

    EndSwitch

    Return _WinAPI_DefWindowProcW($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Extra tidbit -  I tried to create a window from scratch rather than subclassing. The thought was that AutoIt will always do stuff in WM_CREATE before you can subclass. So  to test normal windows behaviour  I wanted to entirely break out of the AU3 ecosystem.

You can certainly create a GUI this way, but unfortunately you can't handle the kb input correctly. We need access to the main msg loop to call  IsDialogMessageW for the custom window,  but that is squirreled away in the AU3 internals.

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
×
×
  • Create New...