Page 1 sur 1
[R] Survol et appui de bouton
Posté : ven. 28 févr. 2014 10:06
par ZDS
Bonjour à tous.
Je cherche à mettre en place un composant de type bouton qui au survol exécute une fonction, et quand on appuye dessus (appui sans relache) effectue qqchose et quand on le relache effectue autre chose. Typiquement : Un bouton au bout d'un input de type password qui :
- quand on le hover : colorie l'input en rouge
- quand on le unhover : redonne la couleur de base à l'input (noir)
- quand on le pousse : affiche le texte en clair
- quand on le relache : cache le texte comme d'habitude (avec les points )
Je sais déjà le faire, mais à la manière crado, c'est à dire avec des boucles moches et du GUIGetCursorInfo. Je souhaiterais donc savoir si quelqu'un saurait comment faire cela proprement, c'est à dire avec un
GuiRegisterMsg ($WM_NOTIFY ou $WM_COMMAND ou autre, je ne maîtrise pas vraiment cet aspect :s).
Voici mon code de départ, merci d'avance pour votre aide !
► Afficher le texteCode avec boucles
Code : Tout sélectionner
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
; Variables
Global $dimension[2] = [200, 80]
; Composants graphiques
Global $GUI = GUICreate("Essai de champ password", $dimension[0], $dimension[1], Default, Default, 0x80800000) ; $WS_POPUP = 0x80000000 ; $WS_BORDER = 0x00800000
Global $title = GUICtrlCreateLabel("Password", 10, 10, $dimension[0]-55, 25, Default, 0x00100000) ; $GUI_WS_EX_PARENTDRAG = 0x00100000
Global $quit = GUICtrlCreateButton("X", $dimension[0]-35, 10, 25, 25)
Global $input = GUICtrlCreateInput("Passw0rd!", 10, 45, $dimension[0]-55, 25, 0x0020) ; $ES_PASSWORD = 0x0020
Global $input2 = GUICtrlCreateInput("Passw0rd!", 10, 45, $dimension[0]-55, 25)
Global $button = GUICtrlCreateButton("", $dimension[0]-35, 45, 25, 25)
; Mise à jour des composants graphiques
GUICtrlSetBkColor($title, -2) ; $GUI_BKCOLOR_TRANSPARENT = -2
GUICtrlSetFont($title, 15, 800)
GUICtrlSetState($input2, $GUI_HIDE)
GUISetState(@SW_SHOW, $GUI)
Local $stop = False, $hover = False, $pushed = False, $previous = ""
Do
; Traitement classique des événements
Local $msg = GUIGetMsg()
If @error = 0 Then
Switch $msg
Case -3 ; $GUI_EVENT_CLOSE = -3
$stop = True
Case $quit
$stop = True
EndSwitch
EndIf
; Traitement en boucle
Local $info = GUIGetCursorInfo($GUI)
If @error = 0 Then
; Item survolé
Switch $info[4]
Case $button ; Hover
If Not $hover Then
$hover = True
GUICtrlSetColor($input, 0xFF0000) ; Rouge = 0xFF0000
EndIf
Case Else ; Unhover
If $hover Then
$hover = False
GUICtrlSetColor($input, 0x000000) ; Noir = 0x000000
EndIf
EndSwitch
; Item appuyé
Local $cond = $hover And $info[2] And $info[4] = $button
If Not $pushed And $cond Then ; Appuyé
$pushed = True
GUICtrlSetState($input, $GUI_HIDE)
GUICtrlSetState($input2, $GUI_SHOW)
EndIf
If $pushed And Not $cond Then ; Relaché
$pushed = False
GUICtrlSetState($input2, $GUI_HIDE)
GUICtrlSetState($input, $GUI_SHOW)
EndIf
EndIf
; Changement dans l'input
If $previous <> GUICtrlRead($input) Then
$previous = GUICtrlRead($input)
GUICtrlSetData($input2, $previous)
EndIf
Until $stop
GUIDelete($GUI)
A bientôt !
PS: D'avance désolé pour la partie dégueulasse du code, je n'ai pas réussi à enlever le style $ES_PASSWORD du champ, donc "obligé" de faire deux inputs qui se chevauchent.
EDIT : Problème [R]ésolu en séparant les deux fonctionnements : généraliste pour le hover/unhover, et spécifique au bouton pour le push/release (cf _GuiCtrlButton_***).
Re: [..] Survol et appui de bouton
Posté : ven. 28 févr. 2014 14:17
par TommyDDR
Il existe pas mal d'UDF sur le hover, je vais en profiter pour vous orienter vers le mien.
Voici un exemple :
► Afficher le textecode
Code : Tout sélectionner
#include <StaticConstants.au3>
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include "_GUICtrlSetOnHover.au3"
Opt("GUIOnEventMode", 1)
Opt("MustDeclareVars", 1)
Global $labelBouton[14]
Global $gui = GUICreate("test", 150, 300)
GUISetOnEvent($GUI_EVENT_CLOSE, "quit")
For $i = 0 To UBound($labelBouton, 1)-1
$labelBouton[$i] = GUICtrlCreateLabel("Label - Bouton " & $i, 10, 10+$i*20, 130, 15, $SS_CENTER)
_GUICtrlSetOnHover($labelBouton[$i], "_Hover", "_Hover", "_Hover", "_Hover")
Next
GUISetState(@SW_SHOW, $gui)
While(True)
Sleep(10)
WEnd
;~ $ctrlId -> ID du control
;~ $type -> type d'action (1= hoverin, 2= hoverout, 3= clic, 4= clic relaché
;~ $isMe -> indique si le clic initié correspond au control hovered (renvoie true si pas de clic) Ce parametre sert lors d'un clic glissé
Func _Hover($ctrlId, $type, $isMe)
Select
Case $type = 1 And $isMe
GUICtrlSetBkColor($ctrlId, 0xA0D9EA)
Case $type = 2 And $isMe
GUICtrlSetBkColor($ctrlId, $GUI_BKCOLOR_TRANSPARENT)
Case $type = 3 And $isMe
GUICtrlSetBkColor($ctrlId, 0x00A2E8)
Case $type = 4
GUICtrlSetBkColor($ctrlId, $GUI_BKCOLOR_TRANSPARENT)
Local $cur = GUIGetCursorInfo($gui)
_Hover($cur[4], 1, True)
If($isMe) Then
For $i = 0 To UBound($labelBouton, 1)-1
If($labelBouton[$i] = $ctrlId) Then
ToolTip("Clic bouton : " & $i)
ExitLoop
EndIf
Next
EndIf
EndSelect
EndFunc
Func quit()
Exit
EndFunc
Re: [..] Survol et appui de bouton
Posté : ven. 28 févr. 2014 19:23
par ZDS
Bonjour TommyDDR,
Ce n'est pas ce que je recherche, ton UDF à peu de chose près est basé sur le même type d'algo que mon script. Ce qui change fondamentalement est la multitude des GuiRegisterMsg (avec les listings), l'utilisation du _IsPressed pour l'état du clic (que je suis obligé d'éviter à tout prix, car la présence de cette fonction, me demandez pas pourquoi, déclenche parfois des faux-positifs avec BitDefender, comme avec l'UPX), et le survol en regardant la position d'un bouton et comparer à la position du contrôle avec User32.WindowFromPoint. C'est beaucoup trop consommateur de ressources et complexe pour ce que j'ai à faire.
Voici un canevas de ce à quoi j'en suis, je cherche seulement à capter les hover/unhover/clic/relache dans la partie en rouge :
► Afficher le texteCanevas
Code : Tout sélectionner
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
; Constantes inconnues
[color=#FF0000]Global Const $UNKNOWN_VALUE_FOR_HOVERING = 0x123456789ABCDEF
Global Const $UNKNOWN_VALUE_FOR_UNHOVERING = 0x123456789ABCDEF
Global Const $UNKNOWN_VALUE_FOR_PUSHING = 0x123456789ABCDEF
Global Const $UNKNOWN_VALUE_FOR_RELEASING = 0x123456789ABCDEF
Global Const $tagNMHDR = "struct; hwnd hWndFrom;uint_ptr IDFrom;INT Code; endstruct"[/color]
; Variables
Global $dimension[2] = [200, 80]
; Composants graphiques
Global $GUI = GUICreate("Essai de champ password", $dimension[0], $dimension[1], Default, Default, 0x80800000) ; $WS_POPUP = 0x80000000 ; $WS_BORDER = 0x00800000
Global $title = GUICtrlCreateLabel("Password", 10, 10, $dimension[0]-55, 25, Default, 0x00100000) ; $GUI_WS_EX_PARENTDRAG = 0x00100000
Global $quit = GUICtrlCreateButton("X", $dimension[0]-35, 10, 25, 25)
Global $input = GUICtrlCreateInput("Passw0rd!", 10, 45, $dimension[0]-55, 25, 0x0020) ; $ES_PASSWORD = 0x0020
Global $input2 = GUICtrlCreateInput("Passw0rd!", 10, 45, $dimension[0]-55, 25)
Global $button = GUICtrlCreateButton("", $dimension[0]-35, 45, 25, 25)
; Mise à jour des composants graphiques
GUICtrlSetBkColor($title, -2) ; $GUI_BKCOLOR_TRANSPARENT = -2
GUICtrlSetFont($title, 15, 800)
GUICtrlSetState($input2, $GUI_HIDE)
[color=#FF0000]GUIRegisterMsg($WM_NOTIFY, "notify")[/color]
GUISetState(@SW_SHOW, $GUI)
Local $stop = False, $previous = ""
Do
; Traitement classique des événements
Local $msg = GUIGetMsg()
If @error = 0 Then
Switch $msg
Case -3 ; $GUI_EVENT_CLOSE = -3
$stop = True
Case $quit
$stop = True
EndSwitch
EndIf
; Changement dans l'input
If $previous <> GUICtrlRead($input) Then
$previous = GUICtrlRead($input)
GUICtrlSetData($input2, $previous)
EndIf
Until $stop
GUIDelete($GUI)
Func notify($hWnd, $Msg, $wParam, $lParam)
Local $info = DllStructCreate($tagNMHDR, $lParam)
[color=#FF0000]If $Hwnd = $GUI Then ; Il manque la détection du bouton $button[/color]
Switch [color=#FF0000]DllStructGetData($info, "Code")[/color]
Case $UNKNOWN_VALUE_FOR_HOVERING
hoveringButton()
Case $UNKNOWN_VALUE_FOR_UNHOVERING
unhoveringButton()
Case $UNKNOWN_VALUE_FOR_PUSHING
pushingButton()
Case $UNKNOWN_VALUE_FOR_RELEASING
releasingButton()
EndSwitch
EndIf
Return $GUI_RUNDEFMSG
EndFunc
Func hoveringButton()
ConsoleWrite(" => hoveringButton"&@CRLF)
GUICtrlSetColor($input, 0xFF0000) ; Rouge = 0xFF0000
EndFunc
Func unhoveringButton()
ConsoleWrite(" => unhoveringButton"&@CRLF)
GUICtrlSetColor($input, 0x000000) ; Noir = 0x000000
EndFunc
Func pushingButton()
ConsoleWrite(" => pushingButton"&@CRLF)
GUICtrlSetState($input, $GUI_HIDE)
GUICtrlSetState($input2, $GUI_SHOW)
EndFunc
Func releasingButton()
ConsoleWrite(" => releasingButton"&@CRLF)
GUICtrlSetState($input2, $GUI_HIDE)
GUICtrlSetState($input, $GUI_SHOW)
EndFunc
Merci d'avance !
Re: [..] Survol et appui de bouton
Posté : ven. 28 févr. 2014 22:37
par mikell
Yo
Tu as regardé (& testé) l'exemple du fichier d'aide pour _GUICtrlButton_Create ?
... yé parie qué noun

Re: [..] Survol et appui de bouton
Posté : ven. 28 févr. 2014 22:50
par jguinch
@mikell : j'avais cherché un peu cet après-midi et j'étais justement tombé sur l'aide de _GUICtrlButton_Create.
C'est pas mal, il y a du WM_COMMAND et WM_NOTIFY. Avec cet exemple, il y a de quoi gérer le survol du bouton et le clic (mouseup), par contre pour le mousedown sur le bouton, j'ai pas trouvé... Ca m'intéresserais de savoir...
Re: [..] Survol et appui de bouton
Posté : sam. 01 mars 2014 10:06
par ZDS
Je l'ai vu et testé tout ce qui était exemple coté _GUICtrlButton_SetSplitInfo et compagnie (raté, Mikell ^^), j'ai juste oublié de le dire ici, mais j'avais prévenu sur le site anglophone.
Comme dit jguinch, il n'y a pas de push/release, et surtout c'est limité au bouton, alors que je cherche un hover/unhover/push/release quelque soit le contrôle (edit, input, button, progressbar, etc...) J'ai trouvé qqchose qui fonctionne que pour les boutons, mais pas pour les autres types de controles (issu des _guictrlbutton); il doit bien exister un code en GuiRegisterMsg qui soit généraliste, non? Ca serait un comble ^^
Re: [..] Survol et appui de bouton
Posté : sam. 01 mars 2014 10:58
par mikell
@jguinch
Sur un bouton un clic n'est enregistré qu'au mouseup, pour le mousedown on peut tricher en donnant le focus à un autre controle et en surveillant $BN_SETFOCUS
Bon courage pour un GuiRegisterMsg généraliste, ça m'intéressera aussi

Re: [..] Survol et appui de bouton
Posté : sam. 01 mars 2014 16:04
par jguinch
Bon, j'ai regardé un peu, mais c'est vrai qu'on trouve pas grand-chose sur les forums...
Du coup, j'ai cherché par moi-même en jouant avec les différents "Windows Messages Codes", bien que je ne suis maîtrise pas du tout GUIRegisterMsg.
Je me suis arrêté sur WM_SETCURSOR qui, je pense, peut être une bonne solution.
Voilà ce que j'ai bricolé :
► Afficher le texte
Code : Tout sélectionner
#Include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
Global $hover, $hoverLast
Global $click, $clickLast
; Variables
Global $dimension[2] = [200, 80]
; Composants graphiques
Global $GUI = GUICreate("Essai de champ password", $dimension[0], $dimension[1], Default, Default, 0x80800000) ; $WS_POPUP = 0x80000000 ; $WS_BORDER = 0x00800000
Global $title = GUICtrlCreateLabel("Password", 10, 10, $dimension[0]-55, 25, Default, 0x00100000) ; $GUI_WS_EX_PARENTDRAG = 0x00100000
Global $quit = GUICtrlCreateButton("X", $dimension[0]-35, 10, 25, 25)
Global $input = GUICtrlCreateInput("Passw0rd!", 10, 45, $dimension[0]-55, 25, 0x0020) ; $ES_PASSWORD = 0x0020
Global $input2 = GUICtrlCreateInput("Passw0rd!", 10, 45, $dimension[0]-55, 25)
Global $button = GUICtrlCreateButton("", $dimension[0]-35, 45, 25, 25)
; Mise à jour des composants graphiques
GUICtrlSetBkColor($title, -2) ; $GUI_BKCOLOR_TRANSPARENT = -2
GUICtrlSetFont($title, 15, 800)
GUICtrlSetState($input2, $GUI_HIDE)
GUISetState(@SW_SHOW, $GUI)
GUIRegisterMsg($WM_SETCURSOR, "WM_SETCURSOR")
While 1
$msg = GUIGetMsg()
If $msg = -3 OR $msg = $quit Then Exit
WEnd
Func WM_SETCURSOR($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $ilParam
$hitTest = BitShift($ilParam, 16)
Switch $iwParam
Case GUICtrlGetHandle($button)
$hover = True
Switch $hitTest
Case $WM_LBUTTONDOWN
$click = True
Case Else
$click = False
EndSwitch
Case Else
$hover = False
EndSwitch
If $hover = True AND $hoverLast = False Then
$hoverLast = True
GUICtrlSetColor($input, 0xFF0000)
GUICtrlSetColor($input2, 0xFF0000)
ElseIf $hover = False AND $hoverLast = True Then
$hoverLast = False
GUICtrlSetColor($input, 0)
GUICtrlSetColor($input2, 0)
GUICtrlSetState($input2, $GUI_HIDE)
GUICtrlSetState($input, $GUI_SHOW)
EndIf
If $click = True AND $clickLast = False Then
$clickLast = True
GUICtrlSetState($input, $GUI_HIDE)
GUICtrlSetState($input2, $GUI_SHOW)
ElseIf $click = False AND $clickLast = True Then
$clickLast = False
GUICtrlSetState($input2, $GUI_HIDE)
GUICtrlSetState($input, $GUI_SHOW)
EndIf
Return $GUI_RUNDEFMSG
EndFunc
C'est peut-être un peu brouillon, mais ça a l'air de fonctionner pas trop mal (sauf si on relâche le bouton en dehors de la GUI

)
Re: [..] Survol et appui de bouton
Posté : sam. 01 mars 2014 18:33
par mikell
Je maintiens que l'exemple de l'aide permet d'avoir le push/release (bouton) même pour un release hors-gui si on joue sur le focus
► Afficher le texte
Code : Tout sélectionner
#include <GUIConstantsEx.au3>
#include <GuiButton.au3>
#include <WindowsConstants.au3>
$hGUI = GUICreate("Buttons", 400, 400)
$iMemo = GUICtrlCreateEdit("", 119, 10, 276, 374, $WS_VSCROLL)
$btn = _GUICtrlButton_Create($hGUI, "Button1", 10, 10, 90, 50)
$fake = GUICtrlCreateLabel("", -10, 0, 1, 1)
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd
Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
#forceref $hWnd, $Msg, $wParam
Local Const $BCN_HOTITEMCHANGE = -1249
Local $tNMBHOTITEM = DllStructCreate("hwnd hWndFrom;int IDFrom;int Code;dword dwFlags", $lParam)
Local $nNotifyCode = DllStructGetData($tNMBHOTITEM, "Code")
Local $nID = DllStructGetData($tNMBHOTITEM, "IDFrom")
Local $hCtrl = DllStructGetData($tNMBHOTITEM, "hWndFrom")
Local $dwFlags = DllStructGetData($tNMBHOTITEM, "dwFlags")
Local $sText = ""
Switch $nNotifyCode
Case $BCN_HOTITEMCHANGE
If BitAND($dwFlags, 0x10) = 0x10 Then
$sText = "mouse hover"
ElseIf BitAND($dwFlags, 0x20) = 0x20 Then
$sText = "mouse nix hover"
GUICtrlSetState($fake, $GUI_FOCUS)
EndIf
MemoWrite($sText)
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY
Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
#forceref $hWnd, $Msg
Local $nNotifyCode = BitShift($wParam, 16)
Local $nID = BitAND($wParam, 0x0000FFFF)
Local $hCtrl = $lParam
Local $sText = ""
Switch $hCtrl
Case $btn
Switch $nNotifyCode
Case $BN_CLICKED
$sText = "mouse up (clic)"
GUICtrlSetState($fake, $GUI_FOCUS)
Case $BN_SETFOCUS
$sText = "mouse down"
Case $BN_KILLFOCUS
$sText = "mouse up (killfocus)"
EndSwitch
MemoWrite($sText)
Return 0
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_COMMAND
Func MemoWrite($sMessage)
GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
EndFunc ;==>MemoWrite
Quel serait l'intérêt de détecter le push/release pour un contrôle autre qu'un bouton ?
Re: [..] Survol et appui de bouton
Posté : sam. 01 mars 2014 19:59
par jguinch
Ah OK, j'avais pas compris ça.
C'est quand même pas simple...

Re: [..] Survol et appui de bouton
Posté : sam. 01 mars 2014 22:50
par ZDS
C'est surtout le hovering multi-controles qui m'interesse, c'est vrai que je pense pouvoir me débrouiller autrement pour le push/release (j'essayerai de délèguer ça selon le controle si c'est pour un drag'n'drop ou autre). Mais le hovering lui, j'aimerai limiter les ressources et le déclencher uniquement lorsque l'event correspondant du GUIRegisterMsg apparait : encore faut il savoir lequel c'est. Pour info, dans le cas d'un bouton c'est CODE = -1249 (FLAG = 17 pour un hover, et FLAG = 33 pour un unhover), mais Mikell l'avait déjà dans son code.
Merci en tout cas pour votre aide, j'ai pas fini d'investiguer ^^
PS@jguinch: la détection d'un clic souris complètement généralisé, c'est de la triche, autant utiliser la fonction de mon premier exemple, elle consommera pas plus ^^
EDIT@Mikell: Si la détection de l'event est possible, c'est que celui-ci est envoyé qu'on le capture ou pas. Donc forcément, ça sera moins consommateur que de rajouter une couche (car si il est envoyé, il l'est aussi lors du script première version et ignoré, donc un truc qui consomme pour rien et part à la poubelle comme lors d'un oubli de passage de pointeur).
Re: [..] Survol et appui de bouton
Posté : dim. 02 mars 2014 00:26
par mikell
Pas vraiment d'accord
Une détection généraliste sera (par nature) forcément gourmande en ressources, et dans ce cas pour le hover le WM_SETCURSOR de jguinch posé avec condition(s) est tout à fait honorable
► Afficher le texte
Code : Tout sélectionner
#include <WindowsConstants.au3>
Global $test, $nix
$hGUI = GUICreate("Buttons", 400, 400)
$iMemo = GUICtrlCreateEdit("", 119, 10, 276, 374, $WS_VSCROLL)
$button = GUICtrlCreateButton("Button1", 10, 10, 90, 50)
GUISetState()
GUIRegisterMsg($WM_SETCURSOR, "WM_SETCURSOR")
While GUIGetMsg()<>-3
WEnd
Func WM_SETCURSOR($hWnd, $iMsg, $iwParam, $ilParam)
If $iwParam<>$test Then
Switch $iwParam
Case GUICtrlGetHandle($button)
GUICtrlSetData($iMemo, "mouse hover" & @CRLF, 1)
$nix = 1
Case Else
If $nix Then GUICtrlSetData($iMemo, "mouse nix hover" & @CRLF, 1)
$nix = 0
EndSwitch
$test = $iwParam
EndIf
Return 'GUI_RUNDEFMSG'
EndFunc
jguinch a écrit :C'est quand même pas simple...

Là on est bien d'accord
