maillady Posted August 28, 2012 Share Posted August 28, 2012 (edited) Hi,This example demonstrates how to replace the default context menu in an edit control with your ownUses _WinAPI_CallWindowProc, a good function that requires more examples expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Constants.au3> #include <GuiMenu.au3> #include <WinAPI.au3> #include <GUIEdit.au3> ; modified from help example: _WinAPI_CallWindowProc $hGui = GUICreate("Custom context menu for Edit Control example", 489, 354, -1, -1) $editBox = GUICtrlCreateEdit("", 8, 40, 473, 305) GUICtrlSetData(-1, "New text") $checkBox = GUICtrlCreateCheckbox("Use our own context menu", 8, 8, 241, 17) GUICtrlSetState($checkBox, $GUI_CHECKED) ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;!! subclass for $editBox $w_editBoxProcNew = DllCallbackRegister("_MyWindowProc", "ptr", "hwnd;uint;long;ptr") $w_editBoxProcOld = _WinAPI_SetWindowLong(GUICtrlGetHandle($editBox), $GWL_WNDPROC, DllCallbackGetPtr($w_editBoxProcNew)) _WinAPI_SetWindowLong(GUICtrlGetHandle($editBox), $GWL_WNDPROC, DllCallbackGetPtr($w_editBoxProcNew)) ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;!! our context menu for $editBox $DummyMenu = GUICtrlCreateDummy() $ContextMenu = GUICtrlCreateContextMenu($DummyMenu) $TestMenuItem = GUICtrlCreateMenuItem("Our Custom Context Menu", $ContextMenu) GUICtrlSetState($TestMenuItem, $GUI_DEFBUTTON) GUICtrlCreateMenuItem("", $ContextMenu) $UndoMenuItem = GUICtrlCreateMenuItem("&Undo", $ContextMenu) GUICtrlCreateMenuItem("", $ContextMenu) $CutMenuItem = GUICtrlCreateMenuItem("&Cut", $ContextMenu) $CopyMenuItem = GUICtrlCreateMenuItem("&Copy", $ContextMenu) $PasteMenuItem = GUICtrlCreateMenuItem("&Paste", $ContextMenu) $DeleteMenuItem = GUICtrlCreateMenuItem("&Delete", $ContextMenu) GUICtrlCreateMenuItem("", $ContextMenu) $SelectAllMenuItem = GUICtrlCreateMenuItem("&Select all", $ContextMenu) GUICtrlCreateMenuItem("", $ContextMenu) $InsertDateMenuItem = GUICtrlCreateMenuItem("&Insert Date and Time", $ContextMenu) GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg ; toggle our context menu on / off Case $checkBox If BitAND(GUICtrlRead($checkBox), $GUI_CHECKED) = $GUI_CHECKED Then _WinAPI_SetWindowLong(GUICtrlGetHandle($editBox), $GWL_WNDPROC, DllCallbackGetPtr($w_editBoxProcNew)) Else _WinAPI_SetWindowLong(GUICtrlGetHandle($editBox), $GWL_WNDPROC, $w_editBoxProcOld) EndIf Case $GUI_EVENT_CLOSE ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;!! we must free the callback before exit !! _WinAPI_SetWindowLong(GUICtrlGetHandle($editBox), $GWL_WNDPROC, $w_editBoxProcOld) DllCallbackFree($w_editBoxProcNew) Exit EndSwitch WEnd ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;!! process our context menu messages Func MenuItem($iSelected) Switch $iSelected Case $TestMenuItem _GUICtrlEdit_AppendText($editBox, @CRLF & "Our Custom Context Menu") Case $UndoMenuItem _GUICtrlEdit_Undo($editBox) Case $CutMenuItem MenuItem($CopyMenuItem) MenuItem($DeleteMenuItem) Case $CopyMenuItem Local $aSel, $sText $aSel = _GUICtrlEdit_GetSel($editBox) If ($aSel[0] <> $aSel[1]) Then $sText = StringMid(_GUICtrlEdit_GetText($editBox), $aSel[0] + 1, ($aSel[1] - $aSel[0]) + 1) ClipPut($sText) EndIf Case $PasteMenuItem Local $sText = ClipGet() If (Not @error) Then _GUICtrlEdit_ReplaceSel($editBox, $sText, True) Case $DeleteMenuItem _GUICtrlEdit_ReplaceSel($editBox, "", True) Case $SelectAllMenuItem _GUICtrlEdit_SetSel($editBox, 0, -1) Case $InsertDateMenuItem _GUICtrlEdit_ReplaceSel($editBox, @CRLF & @YEAR &"/"& @MON &"/"& @MDAY &" "& @HOUR &":" & @MIN &":" & @SEC) EndSwitch EndFunc ;==>ShowMenu ; auxilary function to update menu item states, not required Func UpdateMenuStates() Local $aSel = _GUICtrlEdit_GetSel($editBox) Local $iLen = _GUICtrlEdit_GetTextLen($editBox) _GUICtrlEnabled($UndoMenuItem, _GUICtrlEdit_CanUndo($editBox)) _GUICtrlEnabled($CutMenuItem, ($aSel[0]<>$aSel[1])) _GUICtrlEnabled($CopyMenuItem, ($aSel[0]<>$aSel[1])) _GUICtrlEnabled($PasteMenuItem, (StringLen(ClipGet())>0)) _GUICtrlEnabled($DeleteMenuItem, ($aSel[0]<>$aSel[1])) _GUICtrlEnabled($SelectAllMenuItem, ($iLen>0) And ($iLen<>$aSel[0]+$aSel[1])) EndFunc ;==>SetMenuTexts ; auxilary function to enable / disable controls, not required Func _GUICtrlEnabled($CtrlID, $fTrue = True) If $fTrue Then GUICtrlSetState($CtrlID, $GUI_ENABLE) Else GUICtrlSetState($CtrlID, $GUI_DISABLE) EndIf EndFunc ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;!! our window subclass for $editBox Func _MyWindowProc($hWnd, $uiMsg, $wParam, $lParam) Switch $uiMsg Case $WM_CONTEXTMENU If $hWnd = GUICtrlGetHandle($editBox) Then ; show our context menu UpdateMenuStates() Local $iSelected = _GUICtrlMenu_TrackPopupMenu(GUICtrlGetHandle($ContextMenu), $hWnd, -1, -1, 1, 1, 2) MenuItem($iSelected) Return 0 EndIf EndSwitch ;pass the unhandled messages to default WindowProc Return _WinAPI_CallWindowProc($w_editBoxProcOld, $hWnd, $uiMsg, $wParam, $lParam) EndFunc ;==>_MyWindowProcHave a good day Edited August 29, 2012 by maillady JScript 1 Link to comment Share on other sites More sharing options...
JScript Posted August 28, 2012 Share Posted August 28, 2012 (edited) Excellent demonstration of example, killing the following sentence:"Note: You can not create context menus for controls That Already have context menus system, ie input or edit controls."The final must be in the following sequence:Case $GUI_EVENT_CLOSE ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;!! we must free the callback before exit !! _WinAPI_SetWindowLong(GUICtrlGetHandle($editBox), $GWL_WNDPROC, $w_editBoxProcOld) DllCallbackFree($w_editBoxProcNew) Exit***** stars!Regards,João Carlos. Edited August 28, 2012 by JScript http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!) Somewhere Out ThereJames Ingram Download Dropbox - Simplify your life!Your virtual HD wherever you go, anywhere! Link to comment Share on other sites More sharing options...
maillady Posted August 29, 2012 Author Share Posted August 29, 2012 Consider updated. JScript thanks for your kind words. Cheers Link to comment Share on other sites More sharing options...
funkey Posted August 29, 2012 Share Posted August 29, 2012 (edited) I made something similar nearly 2 years ago. I deactivated unnecessary things for demonstration. I will have a look at your solution. Thanks for sharing! expandcollapse popup;Universal Variable Table ;2010 Nov 25 ;~ #include "libnodave.au3" #Include #include #include #include #include #include #Include ;~ Opt("GUIResizeMode", 1) Opt("GUIOnEventMode", 1) Global $sTitle = "UniVarTab für SIMATIC S7-300 und S7-400 über TCP/IP" Global $Ini = @ScriptDir & "UniVarTab.ini" Global $hProc = DllCallBackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam") Global $OriginalWindowProc Global $aGridLines[1] Global $Socket_SPS, $di_SPS, $dc_SPS Global $LastID FileInstall("UniVarTab.ini", $Ini, 0) Global $aSPS = IniReadSection($Ini, "SPS") Global $hGui = GUICreate($sTitle, 800, 605) GUISetOnEvent(-3, "_Exit") GUIRegisterMsg(0x4E, "_WM_NOTIFY") Global $hCombo = GUICtrlCreateCombo("", 10, 5, 200, 60, 0x3) For $i = 1 To $aSPS[0][0] GUICtrlSetData(-1, $aSPS[$i][0], $aSPS[1][0]) Next Global $hBtnConnect = GUICtrlCreateButton("Verbinden", 220, 5, 100, 20) GUICtrlSetOnEvent(-1, "_Connect") Global $hBtnView = GUICtrlCreateCheckbox("Beobachten", 330, 5, 100, 20, 0x1000) GUICtrlSetOnEvent(-1, "_View") GUICtrlSetState(-1, 128) Global $hInput = GUICtrlCreateInput("", 0, 0, 0, 0, 0x280) GUICtrlSetState(-1, $GUI_HIDE) Global $HeaderX = 10, $HeaderY = 40 GUICtrlCreateLabel("", $HeaderX, $HeaderY, 30, 20, -1, 0x1) Global $hHeader = _GUICtrlHeader_Create($hGui) _GUICtrlHeader_SetUnicodeFormat($hHeader, True) Global $aHeaderWidth[6] = [30, 120, 340, 100, 100, 90] _GUICtrlHeader_AddItem($hHeader, "", $aHeaderWidth[0]) _GUICtrlHeader_AddItem($hHeader, "Operand", $aHeaderWidth[1]) _GUICtrlHeader_AddItem($hHeader, "Kommentar", $aHeaderWidth[2]) _GUICtrlHeader_AddItem($hHeader, "Anzeigeformat", $aHeaderWidth[3]) _GUICtrlHeader_AddItem($hHeader, "Statuswert", $aHeaderWidth[4]) _GUICtrlHeader_AddItem($hHeader, "Steuerwert", $aHeaderWidth[5]) ControlMove($sTitle, "", "SysHeader321", $HeaderX, $HeaderY, 780) Global $aHeaderPos[6] For $i = 0 To 5 $aHeaderPos[$i] = _GUICtrlHeader_GetItemRect($hHeader, $i) Next Local $hDummy = GUICtrlCreateDummy() Global $FormatContext = GUICtrlCreateContextMenu($hDummy) Global $aMenu[5][2] = [["Binär"], ["Bool"], ["Dezimal"], ["Hexadezimal"], ["Gleitpunkt"]] For $i = 0 To UBound($aMenu) - 1 $aMenu[$i][1] = GUICtrlCreateMenuItem($aMenu[$i][0], $FormatContext) GUICtrlSetOnEvent(-1, "_WriteFormat") Next $aGridLines[0] = _NewGridLine() GUISetState() While 1 Sleep(20000) WEnd Func _View() If GUICtrlRead(@GUI_CtrlId) = 1 Then ;~ AdlibRegister("_GetData", 1000) ;~ _GetData() Else ;~ AdlibUnRegister("_GetData") EndIf EndFunc Func _Connect() Local $Index = GUICtrlSendMsg($hCombo, 0x147, 0, 0) Local $aParam = StringSplit($aSPS[$Index+1][1], ";", 2) If GUICtrlRead(@GUI_CtrlId) = "Verbinden" Then ;~ _daveTCPConnect($aParam[0], $Socket_SPS, $di_SPS, $dc_SPS, $aParam[1], $aParam[2], $aSPS[$Index+1][0]) If @error Then MsgBox(16, "Error " & @error, "Verbindung zur SPS konnte nicht hergestellt werden.") Else GUICtrlSetState($hCombo, 128) GUICtrlSetState($hBtnView, 64) GUICtrlSetData(@GUI_CtrlId, "Trennen") EndIf Else ;~ $ViewMode = 0 ;~ $ViewActive = 0 ;~ _daveTCPDisconnect($Socket_SPS, $di_SPS, $dc_SPS) GUICtrlSetData(@GUI_CtrlId, "Verbinden") GUICtrlSetState($hBtnView, 128) GUICtrlSetState($hCombo, 64) EndIf EndFunc ;~ Func _GetData() ;~ ConsoleWrite("Lesen" & @cr) ;~ Local $aTemp = $aGridLines[0] ;~ Local $sAdresse = GUICtrlRead($aTemp[1]) ;~ Local $Area = _GetArea($sAdresse) ;~ Local $DB = _GetDB($sAdresse) ;~ Local $StartByte = _GetByte($sAdresse) ;~ _daveReadBytes($dc_SPS, $Area, $DB, $StartByte, 4) ;~ GUICtrlSetData($aTemp[4], _daveGetFloat($dc_SPS)) ;~ EndFunc ;~ Func _GetDB($sAdresse) ;~ If StringLeft($sAdresse, 2) 'DB' Then Return 0 ;~ Return StringTrimLeft(StringLeft($sAdresse, StringInStr($sAdresse, '.') -1), 2) ;~ EndFunc ;~ Func _AdresseGetBit($sAdresse) ;~ Return StringRight($sAdresse, 1) ;~ EndFunc ;~ Func _GetByte($sAdresse) ;~ Local $string = StringRegExp($sAdresse, '(d+).*d*z', 3) ; Dank an Oscar von Autoit.de für diesen regulären Ausdruck ;~ Return $string[0] ;~ EndFunc ;~ Func _GetArea($sAdresse) ;~ Switch StringLeft($sAdresse, 1) ;~ Case 'D' ;~ Return $daveDB ;~ Case 'E', 'I' ;~ Return $daveInputs ;~ Case 'A', 'O' ;~ Return $daveOutputs ;~ Case 'M', 'F' ;~ Return $daveFlags ;~ Case 'T' ;~ Return $daveTimer ;~ Case 'Z' ;~ Return $daveCounter ;~ Case Else ;~ Return 0 ;~ EndSwitch ;~ EndFunc Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) Local $hWndFrom, $iIDFrom, $iCode Local $tNMHDR, $tNMHEADER $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") $tNMHEADER = DllStructCreate($tagNMHEADER, $ilParam) Switch $hWndFrom Case $hHeader Switch $iCode Case -321 _Reset_HeaderWidth(DllStructGetData($tNMHEADER, "Item")) EndSwitch EndSwitch Return "GUI_RUNDEFMSG" EndFunc ;==>_WM_NOTIFY Func _Reset_HeaderWidth($iIndex) _GUICtrlHeader_SetItemWidth($hHeader, $iIndex, $aHeaderWidth[$iIndex]) EndFunc Func _WriteFormat() GUICtrlSetData($LastID, GUICtrlRead(@GUI_CtrlId, 1)) EndFunc Func _NewGridLine() Local $aLabel[6], $aPos, $iTemp For $i = 0 To 5 $aPos = $aHeaderPos[$i] Switch $i Case 0 $aLabel[$i] = GUICtrlCreateLabel("*>", $aPos[0] + $HeaderX, $aPos[3] + $HeaderY, $aPos[2] - $aPos[0], $aPos[3] - $aPos[1], -1, 0x1) GUICtrlSetOnEvent(-1, "_AddNewGridLine") Case 4 $aLabel[$i] = GUICtrlCreateLabel("", $aPos[0] + $HeaderX, $aPos[3] + $HeaderY, $aPos[2] - $aPos[0], $aPos[3] - $aPos[1], -1, 0x1) GUICtrlSetBkColor(-1, 0xcfcfcf) Case Else $aLabel[$i] = GUICtrlCreateEdit("", $aPos[0] + $HeaderX, $aPos[3] + $HeaderY, $aPos[2] - $aPos[0], $aPos[3] - $aPos[1], 0, 0x1) EndSwitch $iTemp = $aPos[3] - $aPos[1] $aPos[1] += $iTemp $aPos[3] += $iTemp $aHeaderPos[$i] = $aPos Next $OriginalWindowProc = _WinSubclass(GUICtrlGetHandle($aLabel[3]), DllCallbackGetPtr($hProc)) Return $aLabel EndFunc Func _AddNewGridLine() If UBound($aGridLines) = 5 Then Return ReDim $aGridLines[UBound($aGridLines) + 1] $aGridLines[UBound($aGridLines) - 1] = _NewGridLine() EndFunc Func _Exit() GUISetState(@SW_HIDE, $hGui) ;~ _daveTCPDisconnect($Socket_SPS, $di_SPS, $dc_SPS) ;~ _DaveDeInit() _GUICtrlHeader_Destroy($hHeader) GUIDelete() DllCallBackFree($hProc) Exit EndFunc Func _ShowFormatMenu() ;~ _GUICtrlMenu_TrackPopupMenu(GUICtrlGetHandle($FormatContext), $hGui) DllCall("user32.dll", "int", "TrackPopupMenuEx", "hwnd", GUICtrlGetHandle($FormatContext), "int", 0, "int", MouseGetPos(0), "int", MouseGetPos(1), "hwnd", $hGui, "ptr", 0) EndFunc Func _WindowProc($hWnd, $uiMsg, $wParam, $lParam) ; Disable the context menu and show your own menu Local $aTemp Switch $uiMsg Case $WM_CONTEXTMENU For $i = 0 To UBound($aGridLines) - 1 $aTemp = $aGridLines[$i] If $hWnd = GUICtrlGetHandle($aTemp[3]) Then $LastID = $aTemp[3] _ShowFormatMenu() Return 0 EndIf Next EndSwitch Return _WinAPI_CallWindowProc($OriginalWindowProc, $hWnd, $uiMsg, $wParam, $lParam) EndFunc Func _WinSubclass($hWnd, $lpNewWindowProc) Return _WinAPI_SetWindowLong($hWnd, $GWL_WNDPROC, $lpNewWindowProc) EndFunc Edit: Ini-File should look like this: [SPS] Name=IP;Rack;Slot Edited August 29, 2012 by funkey Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now