본문 바로가기
delphi

TRichEdit에서 기본 컨텍스트 팝업 메뉴(Context Popup Menu) 활성화 방법

by doran365 2024. 8. 8.

TRichEdit 컴포넌트를 사용하다 보면 TMemo와 달리 기본 컨텍스트 팝업 메뉴(실행 취소, 복사, 붙여넣기 등)가 활성화되지 않는 것을 발견하게 됩니다. 이는 Delphi 개발 환경에서 흔히 겪는 문제 중 하나로, 개발자에게 불편함을 초래할 수 있습니다. 이 글에서는 TRichEdit에서 기본 컨텍스트 팝업 메뉴를 활성화하는 방법에 대해 상세히 알아보겠습니다.

TRichEdit 기본 컨텍스트 메뉴의 비활성화 원인

TMemo와 TRichEdit의 차이점

TMemo와 TRichEdit 모두 텍스트를 입력하고 편집할 수 있는 Delphi 컴포넌트입니다. 그러나 TMemo는 기본적으로 간단한 텍스트 입력 기능만을 제공하며, TRichEdit는 좀 더 풍부한 텍스트 형식을 지원합니다. 그럼에도 불구하고 TRichEdit에서는 기본 컨텍스트 메뉴가 자동으로 활성화되지 않는 이유는 무엇일까요?

TMemo는 윈도우즈 운영체제에서 제공하는 기본 텍스트 편집기능을 단순히 래핑(wrapping)한 컴포넌트입니다. 이 때문에 TMemo는 윈도우즈 기본 컨텍스트 메뉴를 자동으로 포함합니다. 반면에 TRichEdit는 Rich Text Format(RTF)을 지원하기 위해 더 복잡한 구조를 가지고 있으며, 기본 컨텍스트 메뉴가 포함되지 않는 것이 그 이유 중 하나입니다.

TRichEdit의 복잡한 구조

TRichEdit는 단순한 텍스트 편집기를 넘어 서식 있는 텍스트 편집 기능을 지원합니다. 이로 인해 더 많은 기능이 요구되며, 결과적으로 기본 컨텍스트 메뉴가 활성화되지 않은 상태로 제공됩니다. 개발자는 직접 컨텍스트 메뉴를 구성하거나 활성화해야 하는 필요성이 생깁니다.

TRichEdit에서 기본 컨텍스트 메뉴 활성화하기

TRichEdit에서 기본 컨텍스트 메뉴를 활성화하려면, 직접적으로 윈도우즈 API를 호출하거나, Delphi에서 제공하는 이벤트 핸들러를 통해 수동으로 메뉴를 설정해야 합니다. 다음 단계별로 이 과정을 알아보겠습니다.

Step 1: 윈도우즈 API 호출

먼저, TRichEdit에 대한 기본 컨텍스트 메뉴를 활성화하기 위해 윈도우즈 API를 사용합니다. 다음 코드를 통해 이를 구현할 수 있습니다:

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;
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]);
      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;
        end;
      end;
    finally
      DestroyMenu(hmnu);
    end;
  finally
    FreeLibrary(hUser32);
  end;
end;

이 코드는 기본 컨텍스트 메뉴를 로드하고, 현재 상황에 맞게 메뉴 아이템을 활성화하거나 비활성화합니다. 각 메뉴 아이템의 상태는 텍스트의 선택 여부와 같은 조건에 따라 동적으로 결정됩니다.

Step 2: 이벤트 핸들러 작성

TRichEdit의 OnContextPopup 이벤트를 이용하여 위에서 작성한 RichEditPopupMenu 프로시저를 호출합니다. 다음 코드를 참고하세요:

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

이 코드에서는 OnContextPopup 이벤트가 발생할 때마다 RichEditPopupMenu 프로시저가 실행되어, 오른쪽 클릭 시 기본 컨텍스트 메뉴가 표시되도록 합니다. Handled := True 설정은 기본 팝업 메뉴가 더 이상 표시되지 않도록 합니다.

TRichEdit의 컨텍스트 메뉴 확장하기

추가 메뉴 아이템

기본 컨텍스트 메뉴 외에도, 특정 기능을 추가하고 싶다면 메뉴에 새로운 항목을 삽입할 수 있습니다. 예를 들어, '서식 복사' 기능을 추가한다고 가정해 보겠습니다.

const
  IDM_FORMATPASTE = 1;  // 새로운 메뉴 아이템 ID

IDM_FORMATPASTE와 같은 새로운 메뉴 항목을 정의한 후, TrackPopupMenu 함수의 Cmd 결과에 따라 이를 처리하는 로직을 추가합니다.

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_FORMATPASTE: FormatPaste(re); // 새로운 기능 추가
end;

서식 복사 기능 구현

FormatPaste 프로시저를 정의하여 서식 복사 기능을 구현합니다.

procedure FormatPaste(re: TRichEdit);
begin
  // 서식 복사 로직 구현
end;

TRichEdit 컨텍스트 메뉴 활성화의 중요성

사용자 경험 개선

TRichEdit에서 기본 컨텍스트 메뉴를 활성화하면 사용자는 더욱 직관적이고 편리하게 텍스트를 편집할 수 있습니다. 이는 사용자 경험을 크게 개선시키며, 애플리케이션의 전반적인 만족도를 높일 수 있습니다.

개발자의 편의성

또한, 개발자 입장에서 기본 컨텍스트 메뉴의 활성화는 반복적인 메뉴 구성 작업을 줄여줍니다. 기본적인 텍스트 편집 기능이 이미 제공되므로, 개발자는 추가적인 기능 구현에 더 집중할 수 있습니다.

결론

TRichEdit에서 기본 컨텍스트 팝업 메뉴를 활성화하는 방법은 간단하면서도 효과적입니다. 이 기능을 통해 사용자에게 익숙한 편집 환경을 제공할 수 있으며, 추가적인 기능을 구현하여 더 나은 사용자 경험을 제공할 수 있습니다. Delphi를 사용한 애플리케이션 개발 시, 이러한 기본적인 기능들을 활성화함으로써 제품의 완성도를 높이고, 사용자 만족도를 극대화할 수 있습니다.