Jump to content
Mbee

Can I setup a Right-Click On Event func for a Specific Control?

Recommended Posts

Mbee

I've been reading the fora concerning crafting a GUI that can process right-cllicks, but from what I can tell, you have to set up an "$GUI_EVENT_SECONDARYUP" for the entire GUI rather than set up the equivalent for some specific controls. Is that right? 

I always use On Event Mode. Is there any way to do it on a control by control basis instead of the whole shootin' match?

Thanks!

Edited by Mbee

Share this post


Link to post
Share on other sites
water

Please have a look at GUIRegisterMsg to register a user defined function for a known Windows Message ID (WM_MSG).


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Mbee

Thanks, water, but it looks like there are dozens and dozens of  Windows Message IDs. Which do I use to detect a right-click? WM_NCMBUTTONUP?

And since it appears that these Message IDs are for the entire GUI rather than a specific control (unless I'm even stupider than I thought), how can I figure out which specific control the user right-clicked on?  And remember that I want to use On Event mode...

ETA: It looks like the answer to my first question is: WM_RBUTTONUP. Is that right?

Edited by Mbee
Added possible answer to first question

Share this post


Link to post
Share on other sites
water

The Windows Messages depend on the control you right-click on.
In the function you call you can select the control you want to process.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Mbee

Please forgive me, water, for testing your patience, but I've read everything I can find on the subject in the AutoIt help forum but I still have no idea how to code this.

Consider this scenario: I want to create several buttons that can recognize when the user presses a right-click instead of a left-click. So I create the button control as follows:

GUICtrlCreateButton("1",30,620,305,28,$BS_CENTER,-1)

How do I add the WM_RBUTTONUP callback to that specific control ID?

If that's not the way it's done, perhaps I should instead call something like GUIRegisterMsg($WM_RBUTTONUP, "_RightButtonClickedSomewhere") to cover the whole GUI instead of specific controls. But if so, in the _RightButtonClickedSomewhere() function, how do I determine which specific control the right-click was pressed on?

Would you be so kind as to indulge my noobiness and provide some concrete example, please?

Share this post


Link to post
Share on other sites
water

The messages a button can send are described here: https://msdn.microsoft.com/en-us/library/windows/desktop/bb775941(v=vs.85).aspx#handling_button_messages

Will try to create an example tomorrow.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Mbee

Thanks, water!  Especially for your gracious offer to write up an example.  But for now, there's no need to write that up, as I now have the basic ideas necessary.

Instead, I'll post my code once I've worked it up if I'm still having problems and ask again.

I appreciate your responses.

Share this post


Link to post
Share on other sites
water

Great :)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Mbee

:Sigh: I accidentally deleted the previous post attempt, so here it is again...

I've struggled to try to figure this out on my own, but considering I'm only a few steps above an AutoIt GUI noob, my attempts haven't worked so far. The appropriate tutorial and other examples of trying to recognize right-clicks have confused me, since different authors have taken different approaches and some of the details seem to conflict with the other examples. A key issue is that I still don't know precisely which message handler to register.  In the non-working code that follows, I've tried to use $WM_NOTIFY. PLEASE suggest a better alternative if there is one!

I'll post the full code if you like, but the snippett to follow should give you the idea. (One example suggested using Dummy controls, so I added some, but I'm unfamilar with their coding and operation).  What is happening is that it seems like right clicks are not being recognized at all.

Opt("GUIOnEventMode", 1) ; Use 'On Event Mode' to handle GUI controls

Global $G_RightClickCntrlID, $G_RightClickMsgCode, $G_RightClicked

$G_RightClicked = False

Global $RightClickTestGUI = GUICreate("RightClickTestGUI",308,122,-1,-1,BitOr($WS_SYSMENU,$WS_VISIBLE),-1)
GUISetOnEvent($GUI_EVENT_CLOSE, "_MyGUIClose", $RightClickTestGUI)
Global $G_DummyOne = GUICtrlCreateDummy()
GUICtrlSetOnEvent(-1,"_MyDummy1Clicked")
Global $G_Butn01 = GUICtrlCreateButton("ButOne",38,38,100,30,$BS_CENTER,-1)
GUICtrlSetOnEvent(-1,"_MyBut1Clicked")
GUICtrlSetFont(-1,12,400,0,"Consolas")
Global $G_DummyTwo = GUICtrlCreateDummy()
GUICtrlSetOnEvent(-1,"_MyDummy2Clicked")
Global $G_Butn02 = GUICtrlCreateButton("ButTwo",172,38,100,30,$BS_CENTER,-1)
GUICtrlSetOnEvent(-1,"_MyBut2Clicked")
GUICtrlSetFont(-1,12,400,0,"Consolas")

GUIRegisterMsg($WM_NOTIFY, "_MyNotifyHandler")

While True
    Sleep(1000) ; Sleep forever a second at a time
WEnd

Func _MyNotifyHandler($hWndGUI, $MsgID, $WParam, $LParam)
    #forceref $hWndGUI, $MsgID, $WParam, $LParam
    Local $Lf_IsSpecialButton, $Lf_CntrlID, $Lf_MsgCode

    Local $tNMHDR = DllStructCreate("int;int;int", $LParam)
    If @error Then Return

    $Lf_CntrlID = $tNMHDR.IDFrom
    $Lf_MsgCode = $tNMHDR.Code
    $Lf_IsSpecialButton = False
    $G_RightClicked = False

    If ($Lf_CntrlID = 0) And ($Lf_MsgCode = 0) Then Return $GUI_RUNDEFMSG
    _MyUpdStatusMsg("Significant Notify event - $Lf_CntrlID = " & $Lf_CntrlID & " $Lf_MsgCode = " & $Lf_MsgCode)
;
    Select
        Case ($Lf_CntrlID = $G_Butn01) Or ($Lf_CntrlID = $G_Butn02)
            $Lf_IsSpecialButton = True
            If $Lf_MsgCode = $NM_RCLICK Then $G_RightClicked = True
        Case Else
            $Lf_IsSpecialButton = False
            $G_RightClicked = False
    EndSelect

    If $Lf_IsSpecialButton And $G_RightClicked Then
        _MyUpdStatusMsg("--Right Clicked Special - $Lf_CntrlID = " & $Lf_CntrlID & " $Lf_MsgCode = " & $Lf_MsgCode)
    EndIf
    Return $GUI_RUNDEFMSG
EndFunc

Func _MyBut1Clicked()
    If $G_RightClicked Then
        _MyUpdStatusMsg("Right Click on Button 1 Pressed")
    Else
        _MyUpdStatusMsg("Normal Button 1 Click")
    EndIf
EndFunc

Func _MyBut2Clicked()
    If $G_RightClicked Then
        _MyUpdStatusMsg("Right Click on Button 2 Pressed")
    Else
        _MyUpdStatusMsg("Normal Button 2 Click")
    EndIf
EndFunc

Func _MyDummy1Clicked()
    _MyUpdStatusMsg("Dummy 1 Clicked")
EndFunc

Func _MyDummy2Clicked()
    _MyUpdStatusMsg("Dummy 2 Clicked")
EndFunc

Func _MyGUIClose()
    If $L_ShowStatus Then
        _MyUpdStatusMsg("Cleaning up and exiting")
        If $L_LogToFile Then FileClose($L_LogFileHdl)
        Sleep(200)
        StatusMsgs_Destroy()
    EndIf
    GUIDelete($RightClickTestGUI)
    Exit
EndFunc

What am I doing wrong?

Thanks!

Edited by Mbee

Share this post


Link to post
Share on other sites
water

When posting code please post a working example we can play with. In your code snippet function _MyUpdStatusMsg is missing.

Add some debugging code (SciTE offers a lot of tools) to check which (if any) of your functions gets called.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites
Mbee

Ok, as I wrote in my previous post, I offered to post the whole thing upon request.  But do you want me to also post the necessary "ModStatusMessages.au3" UDF which is a modified version of Kobashi's StatusMsgs UDF?

Alternatively, we can wait while I try a different approach and see if I still need help?

Share this post


Link to post
Share on other sites
AutoBert

It's also possible without RegisterMsg using GUIGetCursorInfo():

#include <GUIConstantsEx.au3>
#include <Array.au3>

Opt("GUIOnEventMode", 1)
Opt('MustDeclareVars', 1)

Global $aBtnIds[10][2]


Global $hGui = GUICreate('Buttontest', 105, 145)
Global $msg, $Handle, $aPos

For $i = 0 To 8
    $aBtnIds[$i][0] = GUICtrlCreateButton($i + 1, 10 + Mod($i, 3) * 30, 10 + Int($i / 3) * 30, 25, 25)
    GUICtrlSetOnEvent(-1, '_Click')
    GUICtrlSetBkColor(-1, 0x12345678)
    $aBtnIds[$i][1] = 'leer'
Next
$aBtnIds[9][0] = GUICtrlCreateButton('OK', 10, 110, 90, 25)
GUICtrlSetOnEvent(-1, '_Colors')
ConsoleWrite('OK: ' & $aBtnIds[$i][0] & @CRLF)
GUISetOnEvent($GUI_EVENT_CLOSE,'_Exit')
GUISetOnEvent($GUI_EVENT_SECONDARYUP,'_RightClick')
GUISetState()

While 1
    Sleep(10000)
WEnd

Func _SetColor($iBtn, $bPrimary=False)
    Local $sButton
    ConsoleWrite('_SetColor: ' & $iBtn & @TAB&$bPrimary&@CRLF)
    If $bPrimary Then
        $sButton = 'Primary'
        If $aBtnIds[$iBtn][1]='leer' Then GUICtrlSetBkColor($aBtnIds[$iBtn][0], 0x990000)
        $aBtnIds[$iBtn][1]='rot'
    Else
        $sButton = 'Secondary'
        If $aBtnIds[$iBtn][1]='leer' Then GUICtrlSetBkColor($aBtnIds[$iBtn][0], 0x059122)
        $aBtnIds[$iBtn][1]='grün'
    EndIf
    MsgBox(0, $sButton & ' Buttonclick', 'Button with ID ' & $aBtnIds[$iBtn][0] & ' was clicked.' & @CRLF & 'The text of the button is: ' & ControlGetText('Buttontest', '', $aBtnIds[$iBtn][0]) & @CRLF, 5, $hGui)
    ConsoleWrite(GUICtrlRead($aBtnIds[$iBtn][0]) & @CRLF)
EndFunc   ;==>_Click

Func _Click()
    Local $iBtn = @GUI_CtrlId - $aBtnIds[0][0]
    ConsoleWrite('_Click: ' & $iBtn & @CRLF)
    _SetColor($iBtn,True)
EndFunc   ;==>_Click

Func _RightClick()
    $aPos = GUIGetCursorInfo()
    Local $iBtn=$aPos[4] - $aBtnIds[0][0]
    ConsoleWrite('_RightClick: '&$iBtn&@TAB&GUICtrlRead($iBtn)&@CRLF)
    _SetColor($iBtn)
EndFunc

Func _Colors()
    Local $sText = '', $aBtns
    For $i = 0 To 8
        $sText &= $aBtnIds[$i][1]
        If $i < 8 Then $sText &= '|'
    Next
    ConsoleWrite($sText & @CRLF)
    $aBtns = StringSplit($sText, '|')
    $aBtns[0] = UBound($aBtns) - 1
    _ArrayDisplay($aBtns, 'Farben', '', 32)
EndFunc   ;==>_Colors

Func _exit()
    Exit
EndFunc

 

  • Like 1

Share this post


Link to post
Share on other sites
Mbee

Thanks, AutoBert!  That's what Melba23's example I linked to above does (uses GUIGetCursorInfo()), and both of you solved it far more easily and comprehensibly than what I read from the tutorial about using GUIRegisterMsg() calls!

But what I found particularly pleasing about your example is that I learned from it that buttons can be colored (or at least their backgrounds).  I suppose that is different from colored buttons generally, which I understood to be very problematic and couldn't be fixed without a fundamental rewrite somewhere in the bowels of AutoIt?

Anyway, thanks again for helping out again!

 

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

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.