I’m particularly looking to suppress the system menu that pops up on a StringGadget right-click and replace it with something more useful.
Any ideas?
Dave
Code: Select all
EnableExplicit
Global.i evWW, SG_CBn
Procedure.i SG_CB(hW, msg, wP, lP)
  Protected.i ri
  Select msg
  Case #WM_CONTEXTMENU
    Debug "Context Menu"
  Case #WM_RBUTTONDOWN
    Debug "RM Click"
  Default
    ri = CallWindowProc_(SG_CBn, hW, msg, wP, lP)
  EndSelect
  ProcedureReturn ri
EndProcedure
If OpenWindow(0, 0, 0, 230, 120, "EVENTTYPES EXAMPLE...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  StringGadget(1, 10, 10, 150, 100, "TEST")
  SG_CBn = SetWindowLongPtr_(GadgetID(1), #GWL_WNDPROC, @SG_CB())
  Repeat
    evWW = WaitWindowEvent()
  Until evWW = #PB_Event_CloseWindow
EndIfNope, I still can’t find anything relevant. There’s a Shardik post for detecting right-click on a ButtonGadget for Windows/Linux. I’m probably searching on the wrong terms. Maybe a separate section for cross-platform examples’d be a good idea.skywalk wrote:Search for Shardik's cross platform examples. This is Windows only.
Code: Select all
EnableExplicit
Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Procedure SubclassGadget(GadgetID.I, NewClassName.S)
  Protected GadgetClass.I = CocoaMessage(0, GadgetID(GadgetID), "class")
  Protected NewGadgetClass.I
  NewGadgetClass = objc_allocateClassPair_(GadgetClass, NewClassName, 0)
  objc_registerClassPair_(NewGadgetClass)
  object_setClass_(GadgetID(GadgetID), NewGadgetClass)
  ProcedureReturn NewGadgetClass
EndProcedure
ProcedureC ContextMenuCallback(Object.I, Selector.I, TextView.I, Menu.I,
  Event.I, Index.I)
  ; ----- Suppress context menu
  ProcedureReturn 0
EndProcedure
ProcedureC RightMouseDownCallback(Object.I, Selector.I, Event.I)
  Debug "Right mouse button down detected!"
EndProcedure
Define SubclassedStringGadget.I
OpenWindow(0, 270, 100, 350, 70, "Detect right mouse button down")
StringGadget(0, 80, 25, 170, 20, "")
SetActiveGadget(0)
SubclassedStringGadget = SubclassGadget(0, "SubclassedStringGadget")
class_addMethod_(SubclassedStringGadget, sel_registerName_("rightMouseDown:"),
  @RightMouseDownCallback(), "v@:@")
class_addMethod_(SubclassedStringGadget,
  sel_registerName_("textView:menu:forEvent:atIndex:"),
  @ContextMenuCallback(), "v@:@@@@")
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindowCode: Select all
SubclassedStringGadget = SubclassGadget(0, "SubclassedStringGadget")
class_addMethod_(SubclassedStringGadget, sel_registerName_("rightMouseDown:"),
  @RightMouseDownCallback(), "v@:@")
class_addMethod_(SubclassedStringGadget,
  sel_registerName_("textView:menu:forEvent:atIndex:"),
  @ContextMenuCallback(), "v@:@@@@")
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)
Code: Select all
objc_registerClassPair_(NewGadgetClass)Code: Select all
ProcedureC RightMouseDownCallback(Object.I, Selector.I, Event.I)
  Debug "Right mouse button down detected!"
EndProcedure
Please take a look into the following advanced example which allows to subclass multiple StringGadgets on MacOS. It identifies the number of the StringGadget in the RightMouseDownCallback and displays the number of the right-clicked StringGadget. And it further demonstrates how to display a customized popup menu when right-clicking into the 2nd StringGadget.HarrysLad wrote:Your code does everything I need for one StringGadget but, on my particular application, I have 10 StringGadgets. Four of them require a popup-menu to be attached but all of them need the system popup to be suppressed.
Code: Select all
EnableExplicit
Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define i.I
Define SubclassedStringGadget.I
Dim StringGadgetID(2) ; Number of StringGadgets - 1
Procedure SubclassGadget(GadgetID.I, NewClassName.S)
  Protected GadgetClass.I = CocoaMessage(0, GadgetID(GadgetID), "class")
  Protected NewGadgetClass.I
  NewGadgetClass = objc_allocateClassPair_(GadgetClass, NewClassName, 0)
  objc_registerClassPair_(NewGadgetClass)
  object_setClass_(GadgetID(GadgetID), NewGadgetClass)
  ProcedureReturn NewGadgetClass
EndProcedure
ProcedureC ContextMenuCallback(Object.I, Selector.I, TextView.I, Menu.I,
  Event.I, Index.I)
  ; ----- Suppress context menu
  ProcedureReturn 0
EndProcedure
ProcedureC RightMouseDownCallback(Object.I, Selector.I, Event.I)
  Shared StringGadgetID.I()
  Protected i.I
  For i = 0 To ArraySize(StringGadgetID())
    If Object = StringGadgetID(i)
      If i = 1
        DisplayPopupMenu(0, WindowID(0))
      Else
        Debug "Right mouse button down on StringGadget " + Str(i + 1)
        Break
      EndIf
    EndIf
  Next i
EndProcedure
OpenWindow(0, 270, 100, 350, 130, "Detect right mouse button down")
; ----- Prepare popup menu for StringGadget 2
If CreatePopupMenu(0)
  MenuItem(0, "Menu item 1")
  MenuItem(1, "Menu item 2")
EndIf
For i = 0 To ArraySize(StringGadgetID())
  StringGadgetID(i) = StringGadget(i, 80, 25 + i * 30, 170, 20, "")
  SubclassedStringGadget = SubclassGadget(i, "SubclassedStringGadget" + Str(i))
  class_addMethod_(SubclassedStringGadget,
    sel_registerName_("rightMouseDown:"),
    @RightMouseDownCallback(), "v@:@")
  class_addMethod_(SubclassedStringGadget,
    sel_registerName_("textView:menu:forEvent:atIndex:"),
    @ContextMenuCallback(), "v@:@@@@")
Next i
CocoaMessage(0, StringGadgetID(0), "setDelegate:", AppDelegate)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Menu
      Debug "Menu item " + Str(EventMenu() + 1) + " was selected"
  EndSelect
ForEverCode: Select all
EnableExplicit
#Event_StringGadget_RightClick = #PB_Event_FirstCustomValue
#StringGadget = 0
OpenWindow(0, 270, 100, 350, 75,
  "Detect right click and suppress context menu")
StringGadget(0, 80, 25, 170, 25, "")
SetActiveGadget(0)
CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux ; -------------------------------------------------
    ProcedureC ButtonPressCallback(*Widget.GtkWidget,
      *EventButton.GdkEventButton, UserData.I)
      If *EventButton\button = 3
        PostEvent(#Event_StringGadget_RightClick)
        ProcedureReturn #True
      EndIf
    EndProcedure
    g_signal_connect_(GadgetID(#StringGadget), "button-press-event",
      @ButtonPressCallback(), 0)
  CompilerCase #PB_OS_MacOS ; -------------------------------------------------
    Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
      "NSApplication sharedApplication"), "delegate")
    Define SubclassedStringGadget.I
    ProcedureC ContextMenuCallback(Object.I, Selector.I, TextView.I, Menu.I,
      Event.I, Index.I)
      ProcedureReturn 0
    EndProcedure
    ProcedureC RightMouseDownCallback(Object.I, Selector.I, Event.I)
      PostEvent(#Event_StringGadget_RightClick)
    EndProcedure
    SubclassedStringGadget = objc_allocateClassPair_(CocoaMessage(0,
      GadgetID(#StringGadget), "class"), "SubclassedStringGadget", 0)
    objc_registerClassPair_(SubclassedStringGadget)
    object_setClass_(GadgetID(#StringGadget), SubclassedStringGadget)
    class_addMethod_(SubclassedStringGadget,
      sel_registerName_("rightMouseDown:"),
      @RightMouseDownCallback(), "v@:@")
    class_addMethod_(SubclassedStringGadget,
      sel_registerName_("textView:menu:forEvent:atIndex:"),
      @ContextMenuCallback(), "v@:@@@@")
    CocoaMessage(0, GadgetID(#StringGadget), "setDelegate:", AppDelegate)
  CompilerCase #PB_OS_Windows ; -----------------------------------------------
    Define DefaultStringGadgetCallback.I
    Procedure CustomStringGadgetCallback(WindowHandle.I, Msg.I, WParam.I,
      LParam.I)
      Shared DefaultStringGadgetCallback.I
      Protected Result.I
      If Msg <> #WM_CONTEXTMENU
        Result = CallWindowProc_(DefaultStringGadgetCallback, WindowHandle, Msg,
          WParam, LParam)
      Else
        PostEvent(#Event_StringGadget_RightClick)
      EndIf
      ProcedureReturn Result
    EndProcedure
    DefaultStringGadgetCallback = SetWindowLongPtr_(GadgetID(#StringGadget),
      #GWL_WNDPROC, @CustomStringGadgetCallback())
CompilerEndSelect ; -----------------------------------------------------------
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #Event_StringGadget_RightClick
      Debug "Right click into StringGadget detected!"
  EndSelect
ForEverCode: Select all
EnableExplicit
#NumStringGadgets = 3
Enumeration #PB_Event_FirstCustomValue
  #Event_StringGadget_RightClick
  #Event_StringGadget_RightClick_PopupMenu
EndEnumeration
Define i.I
Dim StringGadgetID.I(#NumStringGadgets - 1)
CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_MacOS ; -------------------------------------------------
    Define AppDelegate.I = CocoaMessage(0, CocoaMessage(0, 0,
      "NSApplication sharedApplication"), "delegate")
    ProcedureC ContextMenuCallback(Object.I, Selector.I, TextView.I, Menu.I,
      Event.I, Index.I)
      ; ----- Suppress context menu
      ProcedureReturn 0
    EndProcedure
    
    ProcedureC RightMouseDownCallback(Object.I, Selector.I, Event.I)
      Shared StringGadgetID.I()
      Protected i.I
      For i = 0 To #NumStringGadgets - 1
        If Object = StringGadgetID(i)
          If i = 1
            PostEvent(#Event_StringGadget_RightClick_PopupMenu, 0, i)
          Else
            PostEvent(#Event_StringGadget_RightClick, 0, i)
          EndIf
          Break
        EndIf
      Next i
    EndProcedure
    Procedure SubclassGadget(GadgetID.I, NewClassName.S)
      Protected GadgetClass.I = CocoaMessage(0, GadgetID(GadgetID), "class")
      Protected NewGadgetClass.I
      NewGadgetClass = objc_allocateClassPair_(GadgetClass, NewClassName, 0)
      objc_registerClassPair_(NewGadgetClass)
      object_setClass_(GadgetID(GadgetID), NewGadgetClass)
      
      class_addMethod_(NewGadgetClass,
        sel_registerName_("rightMouseDown:"),
        @RightMouseDownCallback(), "v@:@")
      class_addMethod_(NewGadgetClass,
        sel_registerName_("textView:menu:forEvent:atIndex:"),
        @ContextMenuCallback(), "v@:@@@@")
    EndProcedure
  CompilerCase #PB_OS_Windows ; -----------------------------------------------
    Define  DefaultStringGadgetCallback.I
    Procedure CustomStringGadgetCallback(WindowHandle.I, Msg.I, WParam.I,
      LParam.I)
      Shared DefaultStringGadgetCallback.I
      Shared StringGadgetID.I()
      Protected i.I
      Protected Result.I
      If Msg = #WM_CONTEXTMENU
        For i = 0 To #NumStringGadgets - 1
          If WParam = StringGadgetID(i)
            If i = 1
              PostEvent(#Event_StringGadget_RightClick_PopupMenu, 0, i)
            Else
              PostEvent(#Event_StringGadget_RightClick, 0, i)
            EndIf
            
            Break
          EndIf
        Next i
      Else
        Result = CallWindowProc_(DefaultStringGadgetCallback, WindowHandle,
          Msg, WParam, LParam)
      EndIf
      ProcedureReturn Result
    EndProcedure
CompilerEndSelect ; -----------------------------------------------------------
OpenWindow(0, 270, 100, 340, 130, "Detect right mouse button down")
; ----- Prepare popup menu for StringGadget 2
If CreatePopupMenu(0)
  MenuItem(0, "Menu item 1")
  MenuItem(1, "Menu item 2")
EndIf
For i = 0 To #NumStringGadgets - 1
  StringGadgetID(i) = StringGadget(i, 80, 25 + i * 30, 170, 20, "")
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_MacOS ; -----------------------------------------------
      SubclassGadget(i, "SubclassedStringGadget" + Str(i))
    CompilerCase #PB_OS_Windows ; ---------------------------------------------
      DefaultStringGadgetCallback = SetWindowLongPtr_(StringGadgetID(i),
        #GWL_WNDPROC, @CustomStringGadgetCallback())
  CompilerEndSelect ; ---------------------------------------------------------
Next i
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  CocoaMessage(0, StringGadgetID(0), "setDelegate:", AppDelegate)
CompilerEndIf
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Menu
      Debug "Menu item " + Str(EventMenu() + 1) + " was selected"
    Case #Event_StringGadget_RightClick
      Debug "Right mouse button down on StringGadget " + Str(EventGadget() + 1)
    Case #Event_StringGadget_RightClick_PopupMenu
      DisplayPopupMenu(0, WindowID(0))
  EndSelect
ForEver