Jump to content
David Schwartz

RichEdit Popup question

Recommended Posts

I've always used TRichView when I've needed RichEdit stuff, but where I'm at now doesn't have it, so I'm using TRzRichEdit, which is derived from the standard TRichEdit control. So I apologize in advance if this seems like a basic topic.

 

I have some RichEdits and added a Popup to them. I multiplex the popup across the RichEdits and set a Tag to figure out which one is being used.

 

I know both TMemos and TRichEdits have basic editing stuff wired-in -- cut, copy, paste, etc. I seem to recall that if you don't provide your own Popup, then you get a default with those menu items in it.

 

Anyway, I did not define these common actions and only had my own menu items in the popup. As a result, you CAN use the hotkeys <ctrl-C>, <ctrl-X>, <ctrl-V> etc, but there are no corresponding menu items in the popup.

 

I just added them to the popup explicitly, but now the hot-keys don't work. I defined the hot-keys in the popup menu items, but that doesn't seem to do anything (unless they're disabling the hot-keys instead).

 

Isn't there some way to inherit all of this from the default popup menu? Or ... how do you get these default actions added to your own popup menu without redefining them?

Share this post


Link to post

I don't have any knowledge about your exact problem but:

  1. You have the source so you should be able to see how and why assigning a popup menu to the control affects the standard menu.
  2. Use a TActionList instead of wiring the menu items directly.

Share this post


Link to post
Guest
4 hours ago, David Schwartz said:

Isn't there some way to inherit all of this from the default popup menu? Or ... how do you get these default actions added to your own popup menu without redefining them?

see my sample creating all by code and assinging PopupMenu to RichEdit component, or anyother!

image.thumb.png.4210c924b5b3f4cdaff294e8bbd4ff44.png

 

unit uFormMain;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls,
  Vcl.StdActns,
  System.Actions,
  Vcl.ActnList,
  Vcl.Menus,
  Vcl.ComCtrls;

type
  TfrmFormMain = class(TForm)
    RichEdit1: TRichEdit;
    RichEdit2: TRichEdit;
    Edit1: TEdit;
    Edit2: TEdit;
    RichEdit3: TRichEdit;
    Button1: TButton;
    procedure RichEdit1Enter(Sender: TObject);
    procedure RichEdit1Exit(Sender: TObject);
    procedure RichEdit2Enter(Sender: TObject);
    procedure RichEdit2Exit(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure prcCreatMyItemsAndActionsToMyPopupMenuOnRichEdit;
    procedure prcMyActionNonDefaultExecute(Sender: TObject);
  public
    { Public declarations }
  end;

var
  frmFormMain: TfrmFormMain;

implementation

{$R *.dfm}
{
  Here, my way to show as all can be defined.
  But, exist better way to quick create and definitions by using others functions in your IDE, ok?
  Ex.: to Menu, exist the "NewMenu/NewPopupMenu, etc..." procedure in "VCL.Menus.pas"  - see in your Help or VCL sources!
}

var { for easy access in all form!!! }
  lMyActionList: TActionList;
  lMyPopupMenu : TPopupMenu;

procedure TfrmFormMain.prcCreatMyItemsAndActionsToMyPopupMenuOnRichEdit;
var
  lMyMenuItemCopy              : TMenuItem;
  lMyMenuItemCut               : TMenuItem;
  lMyMenuItemPaste             : TMenuItem;
  lMyMenuItemToNonDefaultAction: TMenuItem;
  //
  // Category: Edit  (my group for Edit actions)
  lMyActionToEditCopy : TEditCopy;
  lMyActionToEditCut  : TEditCut;
  lMyActionToEditPaste: TEditPaste;
  //
  lMyActionNonDefault: TAction;
begin
  // creating our Actions definitions: all in my "Edit" category!
  //
  lMyActionToEditCopy          := TEditCopy.Create(lMyActionList);
  lMyActionToEditCopy.Name     := 'myActionToEditCopy';
  lMyActionToEditCopy.Category := 'ActionToEdit';
  lMyActionToEditCopy.Caption  := 'My&Copy';
  lMyActionToEditCopy.ShortCut := TextToShortCut('Ctrl+C'); // 16451;  // { uppercase or lowercase, does matter }
  // Hint, Image, etc...
  lMyActionToEditCut          := TEditCut.Create(lMyActionList);
  lMyActionToEditCut.Name     := 'myActionToEditCut';
  lMyActionToEditCut.Category := 'ActionToEdit';
  lMyActionToEditCut.Caption  := 'MyC&ut';
  lMyActionToEditCut.ShortCut := TextToShortCut('Ctrl+U'); // 16472;
  //
  lMyActionToEditPaste          := TEditPaste.Create(lMyActionList);
  lMyActionToEditPaste.Name     := 'myActionToEditPaste';
  lMyActionToEditPaste.Category := 'ActionToEdit';
  lMyActionToEditPaste.Caption  := 'My&Paste';
  lMyActionToEditPaste.ShortCut := TextToShortCut('Ctrl+P'); // 16470;
  //
  lMyActionNonDefault           := TAction.Create(lMyActionList);
  lMyActionNonDefault.Name      := 'myActionNonDefault';
  lMyActionNonDefault.Category  := 'ActionToNonDefaultAction';
  lMyActionNonDefault.Caption   := 'My&Non-Default Action';
  lMyActionNonDefault.ShortCut  := TextToShortCut('Ctrl+N');
  lMyActionNonDefault.OnExecute := prcMyActionNonDefaultExecute;

  //
  // creating MenuItems to our PopupMenu
  //
  lMyMenuItemCopy        := TMenuItem.Create(lMyPopupMenu);
  lMyMenuItemCopy.Name   := 'myMenuItemCopy';
  lMyMenuItemCopy.Action := lMyActionToEditCopy;
  //
  lMyMenuItemCut        := TMenuItem.Create(lMyPopupMenu);
  lMyMenuItemCut.Name   := 'myMenuItemCut';
  lMyMenuItemCut.Action := lMyActionToEditCut;
  //
  lMyMenuItemPaste        := TMenuItem.Create(lMyPopupMenu);
  lMyMenuItemPaste.Name   := 'myMenuItemPaste';
  lMyMenuItemPaste.Action := lMyActionToEditPaste;
  //
  lMyMenuItemToNonDefaultAction        := TMenuItem.Create(lMyPopupMenu);
  lMyMenuItemToNonDefaultAction.Name   := 'myMenuItemToNonDefaultAction';
  lMyMenuItemToNonDefaultAction.Action := lMyActionNonDefault;
  //
  // Adding our MenuItems on our PopupMneu
  //
  lMyPopupMenu.Items.Add(lMyMenuItemCopy);
  lMyPopupMenu.Items.Add(lMyMenuItemCut);
  lMyPopupMenu.Items.Add(lMyMenuItemPaste);
  lMyPopupMenu.Items.Add(lMyMenuItemToNonDefaultAction);
end;

procedure TfrmFormMain.prcMyActionNonDefaultExecute(Sender: TObject);
begin
  ShowMessage('Hello world, i''m ' + (Sender as TAction).Name);
end;

procedure TfrmFormMain.FormCreate(Sender: TObject);
begin
  prcCreatMyItemsAndActionsToMyPopupMenuOnRichEdit;
end;

procedure TfrmFormMain.RichEdit1Enter(Sender: TObject);
begin
  RichEdit1.PopupMenu := lMyPopupMenu;
  //
  Edit2.Text := 'RichEdit1.PopupMenu := ' + lMyPopupMenu.Name;
end;

procedure TfrmFormMain.RichEdit1Exit(Sender: TObject);
begin
  RichEdit1.PopupMenu := nil;
  //
  Edit2.Text := 'RichEdit1.PopupMenu := nil';
end;

procedure TfrmFormMain.RichEdit2Enter(Sender: TObject);
begin
  RichEdit2.PopupMenu := lMyPopupMenu;
  //
  Edit2.Text := 'RichEdit2.PopupMenu := ' + lMyPopupMenu.Name;
end;

procedure TfrmFormMain.RichEdit2Exit(Sender: TObject);
begin
  RichEdit2.PopupMenu := nil;
  //
  Edit2.Text := 'RichEdit2.PopupMenu := nil';
end;

initialization

ReportMemoryLeaksOnShutdown := true; // testing "memory leaks"...
//
lMyPopupMenu      := TPopupMenu.Create(nil);
lMyPopupMenu.Name := 'myPopupMenu';
//
lMyActionList      := TActionList.Create(nil); // or Self, etc... you choice how all end!
lMyActionList.Name := 'myActionList';
//

finalization

lMyActionList.Free;
lMyPopupMenu.Free;

end.

 

hug

Share this post


Link to post

Ok, assigning the popup menu in the Enter/Exit events made me go DUH! Yeah, it's a lot easier than what I did with tags. 

 

But all of the boilerplate code for the menu items and actions is already defined somewhere. I mean ... it's there by default if you don't override the PopupMenu.

 

Isn't there some way to "inherit" it? 

Share this post


Link to post
Guest

yeah, you need some like "MergeMenu" items used in TMainMenu!

 

image.thumb.png.ccaed5ca37d8e76351251fefe2de6c94.png

 

  object myPopupMenu1: TPopupMenu
    Left = 584
    Top = 176
    object myPopupMenu1Item11: TMenuItem
      Caption = 'myPopupMenu1_Item1'
    end
    object myPopupMenu1Item21: TMenuItem
      Caption = 'myPopupMenu1_Item2'
    end
    object myPopupMenu1Item31: TMenuItem
      Caption = 'myPopupMenu1_Item3'
    end
  end
  object myPopupMenu2: TPopupMenu
    Left = 584
    Top = 248
    object myPopupMenu2Item11: TMenuItem
      Caption = 'myPopupMenu2_Item1'
    end
    object myPopupMenu2Item21: TMenuItem
      Caption = 'myPopupMenu2_Item2'
    end
    object myPopupMenu2Item31: TMenuItem
      Caption = 'myPopupMenu2_Item3'
    end
  end
  object myPopupMenu3: TPopupMenu
    Left = 584
    Top = 320
  end

 

unit uFormSecond;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.Menus,
  Vcl.StdCtrls,
  Vcl.ComCtrls;

type
  TfrmFormSecond = class(TForm)
    RichEdit1: TRichEdit;
    RichEdit2: TRichEdit;
    RichEdit3: TRichEdit;
    myPopupMenu1: TPopupMenu;
    myPopupMenu1Item11: TMenuItem;
    myPopupMenu1Item21: TMenuItem;
    myPopupMenu1Item31: TMenuItem;
    myPopupMenu2: TPopupMenu;
    myPopupMenu2Item11: TMenuItem;
    myPopupMenu2Item21: TMenuItem;
    myPopupMenu2Item31: TMenuItem;
    myPopupMenu3: TPopupMenu;
    Edit1: TEdit;
    procedure RichEdit1Enter(Sender: TObject);
    procedure RichEdit1Exit(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmFormSecond: TfrmFormSecond;

implementation

{$R *.dfm}

procedure prcMergerPopupMenu(lPMtarget: TPopupMenu; const lPMSource: TPopupMenu);
var
  lMenuItem: TMenuItem;
  lMItmp   : TMenuItem;
begin
  //
  if (lPMtarget = lPMSource) then
    exit;
  //
  // I dont worry about any "AV" here, ok! just for test...
  //
  for lMenuItem in lPMSource.Items do // this is not a recursive copy, but you can increment it if you want!
  begin
    lMItmp := TMenuItem.Create(lPMtarget);
    //
    // if (lPMtarget.FindComponent(lMenuItem.Name) = nil) then // if not used  "(lPMtarget = lPMSource)" above
    begin
      lMItmp.Name     := lMenuItem.Name;
      lMItmp.Caption  := lMenuItem.Caption;
      lMItmp.ShortCut := lMenuItem.ShortCut;
      //
      lPMtarget.Items.Add(lMItmp);
    end;
  end;
end;

procedure TfrmFormSecond.FormCreate(Sender: TObject);
begin
  Self.ActiveControl := Edit1; // just for tests...
  //
  RichEdit2.OnEnter := RichEdit1.OnEnter;
  RichEdit2.OnExit  := RichEdit1.OnExit;
end;

procedure TfrmFormSecond.RichEdit1Enter(Sender: TObject);
begin
  // cleaning old items on my "PopupMenu" with new options
  // else, "AV" can be raised if "items" already exist!
  myPopupMenu3.Items.Clear;
  //
  prcMergerPopupMenu(myPopupMenu3, myPopupMenu1); // PopupMenu1 have 3 menuitems in my test
  //
  prcMergerPopupMenu(myPopupMenu3, myPopupMenu2); // PopupMenu2 have 3 menuitems in my test
  //
  prcMergerPopupMenu(myPopupMenu3, myPopupMenu3); // same PopupMenu's
  //
  (Sender as TRichEdit).PopupMenu := myPopupMenu3;
end;

procedure TfrmFormSecond.RichEdit1Exit(Sender: TObject);
begin
  (Sender as TRichEdit).PopupMenu := nil;
end;

initialization

ReportMemoryLeaksOnShutdown := true;

finalization

end.

 

hug

Edited by Guest

Share this post


Link to post
Guest

all would be more ease if "ADD()" methods dont verify the "Parent" before add new items on PopupMenu!

Share this post


Link to post

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

×