Using the TEdit context menu for TRichEdit
Asked Answered
U

1

8

Is there a simple/clever way to load the standard Windows TEdit menu into this TRichEdit?

I know that I could create a simple menu to simulate the TEdit menu for the simple operations like copy/paste etc. (Example), however I would also like to keep the more advanced menu options such as the unicode options, reading order, and to utilize the same localization strings.

Edit: I have found a possible lead (trying to figure it out as I'm not an MFC expert)...

Unarm answered 18/4, 2012 at 17:34 Comment(8)
I know I have made research about this earlier, and I think that was in connection with a SO question.Pluviometer
@Andreas, and a conclusion :-? My guess is that those menus comes from base Windows classes.Callosity
TLama, yeah, I don't think there is any 'documented' way to get hold of this menu.Pluviometer
@Sertac: Well, that doesn't answer the question, as far as I can see. We all know that you can assign a custom menu to a rich edit control.Pluviometer
@Andreas, I was too quick, the control does not even implement 'GetContextMenu'.Virus
@Ken, I deleted my wrong comment <g>. That control does not implement (E_NOTIMPL) 'GetContextMenu' of 'IRichEditOleCallback'.Virus
@ZigiZ, to the link from your question update. It's also about building the context menu manually.Callosity
@Sertac, I deleted mine too. Just figured that out myself looking for a way to post an answer. <g>Phosphor
U
14

Based on the "possible lead" and a bit of MSDN, I came up with a possible solution. I'm still unable to resolve the reading order issue (and the unicode options). It seems that it works differently for RichEdit than for Edit, and simply setting or getting the WS_EX_RTLREADING flag does not work as excpected. Anyways, here is the code:

procedure RichEditPopupMenu(re: TRichEdit);
const
  IDM_UNDO   = WM_UNDO;
  IDM_CUT    = WM_CUT;
  IDM_COPY   = WM_COPY;
  IDM_PASTE  = WM_PASTE;
  IDM_DELETE = WM_CLEAR;
  IDM_SELALL = EM_SETSEL;
  IDM_RTL    = $8000; // WM_APP ?

  Enables: array[Boolean] of DWORD = (MF_DISABLED or MF_GRAYED, MF_ENABLED);
  Checks: array[Boolean] of DWORD = (MF_UNCHECKED, MF_CHECKED);
var
  hUser32: HMODULE;
  hmnu, hmenuTrackPopup: HMENU;
  Cmd: DWORD;
  Flags: Cardinal;
  HasSelText: Boolean;
  FormHandle: HWND;
  // IsRTL: Boolean;
begin
  hUser32 := LoadLibraryEx(user32, 0, LOAD_LIBRARY_AS_DATAFILE);
  if (hUser32 <> 0) then
  try
    hmnu := LoadMenu(hUser32, MAKEINTRESOURCE(1));
    if (hmnu <> 0) then
    try
      hmenuTrackPopup := GetSubMenu(hmnu, 0);

      HasSelText := Length(re.SelText) <> 0;
      EnableMenuItem(hmnu, IDM_UNDO,   Enables[re.CanUndo]);
      EnableMenuItem(hmnu, IDM_CUT,    Enables[HasSelText]);
      EnableMenuItem(hmnu, IDM_COPY,   Enables[HasSelText]);
      EnableMenuItem(hmnu, IDM_PASTE,  Enables[Clipboard.HasFormat(CF_TEXT)]);
      EnableMenuItem(hmnu, IDM_DELETE, Enables[HasSelText]);
      EnableMenuItem(hmnu, IDM_SELALL, Enables[Length(re.Text) <> 0]);

      // IsRTL := GetWindowLong(re.Handle, GWL_EXSTYLE) and WS_EX_RTLREADING <> 0;
      // EnableMenuItem(hmnu, IDM_RTL, Enables[True]);
      // CheckMenuItem(hmnu, IDM_RTL, Checks[IsRTL]);

      FormHandle := GetParentForm(re).Handle;
      Flags := TPM_LEFTALIGN or TPM_RIGHTBUTTON or TPM_NONOTIFY or TPM_RETURNCMD;
      Cmd := DWORD(TrackPopupMenu(hmenuTrackPopup, Flags,
        Mouse.CursorPos.X, Mouse.CursorPos.Y, 0, FormHandle, nil));
      if Cmd <> 0 then
      begin
        case Cmd of
          IDM_UNDO:   re.Undo;
          IDM_CUT:    re.CutToClipboard;
          IDM_COPY:   re.CopyToClipboard;
          IDM_PASTE:  re.PasteFromClipboard;
          IDM_DELETE: re.ClearSelection;
          IDM_SELALL: re.SelectAll;
          IDM_RTL:; // ?
        end;
      end;
    finally
      DestroyMenu(hmnu);
    end;
  finally
    FreeLibrary(hUser32);
  end;
end;

procedure TForm1.RichEditEx1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
begin
  RichEditPopupMenu(TRichEdit(Sender));
  Handled := True;
end;

Any feedback would be nice :)

Unarm answered 19/4, 2012 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.