Jump to content

[Solved] Custom context menus for edit controls


qwert
 Share

Recommended Posts

I've been trying to fashion a custom context menu for an edit control. The help file for context menus clearly states that a direct method is not supported. So I've been trying alternative methods to intercept the right mouse click and take an action. So far, nothing has panned out. The code below shows a method that seems very close. The mouse click is detected, but the menu doesn't display.

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

$hGUI = GUICreate("GUI Context Menu Test", 300, 200)
$label = GUICtrlCreateLabel("", 20, 20, 260, 120)      ; label control solely to support context menu
$edit = GUICtrlCreateEdit("Test", 20, 20, 260, 120)
$button = GUICtrlCreateButton("OK", 120, 170, 70, 20)

$buttoncontext = GUICtrlCreateContextMenu($button)
GUICtrlCreateMenuItem("About button", $buttoncontext)

$idDummy = GUICtrlCreateDummy()                         ; created for a dummy control, because you
$contextmenu = GUICtrlCreateContextMenu($idDummy)       ; can't create a context menu for an edit control
$case_0 = GUICtrlCreateMenuItem("Case 0", $contextmenu)
$case_1 = GUICtrlCreateMenuItem("Case 1", $contextmenu)

GUISetState()

GUIRegisterMsg($WM_CONTEXTMENU, "WM_CONTEXTMENU")

While 1
$nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $button
            MsgBox(0, "Button", "The button was clicked.")
        Case $case_0
            MsgBox(0, "Case 0", "This is Case 0")
        Case $case_1
            MsgBox(0, "Case 1", "This is Case 1")
    EndSwitch
WEnd

Func WM_CONTEXTMENU($hWnd, $iMsg, $iwParam, $ilParam)
    Local $IDCtrl = _WinAPI_GetDlgCtrlID($iwParam)
    Local $x = BitAND($ilParam, 0x0000FFFF), $y = BitShift($ilParam, 16)
    Switch $IDCtrl
        Case $label             ; because $edit doesn't seem to work
            TrackPopupMenu($hWnd, $contextmenu, $x, $y)
    EndSwitch
EndFunc

Func TrackPopupMenu($hWnd, $hMenu, $x, $y)
    ConsoleWrite($x & @CRLF)                ; confirms that the menu is requested
    ConsoleWrite($y & @CRLF)
    DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hMenu, "int", 0, "int", $x, "int", $y, "hwnd", $hWnd, "ptr", 0)
EndFunc

I've seen topics on other forums that seem to indicate that this is possible, but I haven't seen a clear example. (BTW, I'll mention that it's fairly important to me to keep things simple.)

Has anyone been successful at implementing such a menu? ... or maybe have ideas of what to try?

Thanks in advance for any assistance.

 

Edited by qwert
Link to comment
Share on other sites

1 hour ago, qwert said:

BTW, I'll mention that it's fairly important to me to keep things simple

Unfortunately, I don't think any answer to this is going to be simple.

Here's one discussion on how to do it on StackOverflow, and it's definitely not a simple process.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Whoa! ... that's a great solution. I picked up the example on page 2 of that thread and my initial test indicates it does exactly what I need.

FWIW, my take is that subclassing lets you reassign a control (in this case, the edit control) away from the standard processing ... and (if your want) to your own processing.

It's hard to believe that this isn't more widely known/used (I've never seen it, before) because the standard context menu for edit/input controls is so poor (too many unneeded choices!)

Thanks very much!

Link to comment
Share on other sites

Hi qwert,
The solution we talked about :

#include <GUIConstantsEx.au3>

$hGUI = GUICreate("GUI Context Menu Test", 300, 200)
$edit = GUICtrlCreateEdit("Test", 20, 20, 260, 120)

$button = GUICtrlCreateButton("OK", 120, 170, 70, 20)
$buttoncontext = GUICtrlCreateContextMenu($button)
GUICtrlCreateMenuItem("About button", $buttoncontext)

$label = GUICtrlCreateLabel("", 1, 1, 1, 1)
$contextmenu = GUICtrlCreateContextMenu($label)
$case_0 = GUICtrlCreateMenuItem("Case 0", $contextmenu)
$case_1 = GUICtrlCreateMenuItem("Case 1", $contextmenu)
$hcontextmenu = GUICtrlGetHandle($contextmenu)

GUISetState()

While 1
    $aInfo = GUIGetCursorInfo()
    If not @error And $aInfo[3] = 1 And $aInfo[4] = $edit Then
        $mPos = MouseGetPos()
        DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hcontextmenu, _
            "int", 0, "int", $mPos[0], "int", $mPos[1], "hwnd", $hGUI, "ptr", 0)
    EndIf

    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $button
            MsgBox(0, "Button", "The button was clicked.")
        Case $case_0
            MsgBox(0, "Case 0", "This is Case 0")
        Case $case_1
            MsgBox(0, "Case 1", "This is Case 1")
    EndSwitch
WEnd


Good luck :)

Link to comment
Share on other sites

@pixelsearch, thanks for keeping after this and posting the simplest solution!

What I was after all along was a way to have different context menus for different edit controls. Your method does that, nicely.

Here's an example with two edit controls set up with different menus ... and without subclassing or registered message processing:

#include <GUIConstantsEx.au3>

$hGUI = GUICreate("GUI Context Menu Test", 300, 350)
$edit = GUICtrlCreateEdit("Test", 20, 20, 260, 120)
$edit2 = GUICtrlCreateEdit("Also", 20, 180, 260, 120)

$button = GUICtrlCreateButton("OK", 120, 320, 70, 20)
$buttoncontext = GUICtrlCreateContextMenu($button)
GUICtrlCreateMenuItem("About button", $buttoncontext)

$label = GUICtrlCreateLabel("", 1, 1, 1, 1)
$contextmenu = GUICtrlCreateContextMenu($label)
$case_0 = GUICtrlCreateMenuItem("Case 0", $contextmenu)
$case_1 = GUICtrlCreateMenuItem("Case 1", $contextmenu)
$hcontextmenu = GUICtrlGetHandle($contextmenu)

$label2 = GUICtrlCreateLabel("", 1, 1, 1, 1)
$context2 = GUICtrlCreateContextMenu($label2)
$case_2 = GUICtrlCreateMenuItem("Case 2", $context2)
$case_3 = GUICtrlCreateMenuItem("Case 3", $context2)
$hcontext2 = GUICtrlGetHandle($context2)

GUISetState()

While 1
    $aInfo = GUIGetCursorInfo()
    If not @error And $aInfo[3] = 1 And $aInfo[4] = $edit Then
        $mPos = MouseGetPos()
        DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hcontextmenu, _
            "int", 0, "int", $mPos[0], "int", $mPos[1], "hwnd", $hGUI, "ptr", 0)
    EndIf

    If not @error And $aInfo[3] = 1 And $aInfo[4] = $edit2 Then
        $mPos = MouseGetPos()
        DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", $hcontext2, _
            "int", 0, "int", $mPos[0], "int", $mPos[1], "hwnd", $hGUI, "ptr", 0)
    EndIf

$nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $button
            MsgBox(0, "Button", "The button was clicked.", 1)
        Case $case_0
            MsgBox(0, "Case 0", "This is Case 0", 1)
        Case $case_1
            MsgBox(0, "Case 1", "This is Case 1", 1)
        Case $case_2
            MsgBox(0, "Case 2", "This is Case 2", 1)
        Case $case_3
            MsgBox(0, "Case 3", "This is Case 3", 1)
    EndSwitch
WEnd

I'm impressed. (Sorry I couldn't see the forest amongst the trees in your first script!)

Thanks, again!

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...