Карта сайтаСсылкиКонтакты

Как отобразить подсказку в пункте меню

PDF Печать
Статьи

Когда мышь находится над компонентом (например TButton), а свойство ShowHint равно True и есть какой-то текст в свойстве Hint этого компонента, то появляется окошко подсказки для этого компонента.

Главное меню с всплывающей подсказкой

Но из-за особенностей Windows, даже если Вы установите свойство Hint для меню, подсказка появляться не будет. Но можно использовать событие OnHint объекта Application для отображения подсказки в строке состояния.

Когда пользователь выбирает пункт меню, отправляется сообщение WM_MENUSELECT. Если Вы хотите добавить подсказку в пункт меню, нужно просто соответствующим образом обработать сообщение WM_MENUSELECT.

Краткая информация: Сообщение WM_MENUSELECT посылается владельцу меню (Form1), когда пользователь выбирает пункт меню (не щелчок). Используя метод FindItem класса TMenu, Вы можете получить пункт выбранного меню. Как только мы узнаем, над каким пунктом меню находится указатель мыши, мы вызываем метод DoActivateHint класса TMenuItemHint.

Поскольку Вы не можете полностью полагаться на метод Application.ActivateHint для отображения подсказки в пунктах меню (работа меню полностью происходит в Windows), чтобы получить подсказку, нужно создать свою собственную версию окна подсказки путем выведения нового класса от THintWindow.

Итак, класс TMenuItemHint, потомок от THintWindow:


unit HintClass;

interface

uses
  Windows, Controls, Menus, ExtCtrls, Classes, Forms;

type
  TMenuItemHint = class(THintWindow)
  private
    activeMenuItem: TMenuItem;
    showTimer: TTimer;
    hideTimer: TTimer;
    procedure HideTime(Sender: TObject);
    procedure ShowTime(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
    procedure DoActivateHint(menuItem: TMenuItem);
    destructor Destroy; override;
  end;

implementation

{ TMenuItemHint }

constructor TMenuItemHint.Create(AOwner: TComponent);
begin
  inherited;

  showTimer:= TTimer.Create(Self);
  showTimer.Interval:= Application.HintPause;

  hideTimer:= TTimer.Create(Self);
  hideTimer.Interval:= Application.HintHidePause;
end; { *Create* }

destructor TMenuItemHint.Destroy;
begin
  hideTimer.OnTimer:= nil;
  showTimer.OnTimer:= nil;
  Self.ReleaseHandle;
  inherited;
end; { *Destroy* }

procedure TMenuItemHint.DoActivateHint(menuItem: TMenuItem);
begin
  { Ускоряем удаление старого окна подсказки }
  hideTime(Self);

  if (menuItem = nil) or (menuItem.Hint = '') then
  begin
    activeMenuItem:= nil;
    Exit;
  end;

  activeMenuItem:= menuItem;

  showTimer.OnTimer:= ShowTime;
  hideTimer.OnTimer:= HideTime;
end; { *DoActivateHint* }

procedure TMenuItemHint.HideTime(Sender: TObject);
begin
  { Скрываем (удаляем) окно подсказки}
  Self.ReleaseHandle;
  hideTimer.OnTimer:= nil;
end; { *HideTime* }

procedure TMenuItemHint.ShowTime(Sender: TObject);
var
  r: TRect;
  wdth: integer;
  hght: integer;
begin
  if activeMenuItem <> nil then
  begin
    { Позиция и размеры }
    wdth:= Canvas.TextWidth(activeMenuItem.Hint);
    hght:= Canvas.TextHeight(activeMenuItem.Hint);

    r.Left:= Mouse.CursorPos.X + 16;
    r.Top:= Mouse.CursorPos.Y + 16;
    r.Right:= r.Left + wdth + 6;
    r.Bottom:= r.Top + hght + 4;

    ActivateHint(r, activeMenuItem.Hint);
  end;
  showTimer.OnTimer:= nil;  
end;

end.

И само приложение, на форме которого находится TMainMenu, TApplicationEvents (для вывода подсказки в строку состояния), TStatusBar просто для наглядности.

Здесь мы обрабатываем сообщение WM_MENUSELECT, чтобы определиться с пунктом меню.

Ниже приводится полный текст кода формы приложения.


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, HintClass, AppEvnts, ComCtrls;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    mnuFile: TMenuItem;
    mnuOpen: TMenuItem;
    mnuSave: TMenuItem;
    N4: TMenuItem;
    mnuExit: TMenuItem;
    StatusBar1: TStatusBar;
    ApplicationEvents1: TApplicationEvents;
    N1: TMenuItem;
    N11: TMenuItem;
    imagejpg1: TMenuItem;
    PopupMenu1: TPopupMenu;
    N2: TMenuItem;
    N3: TMenuItem;
    N5: TMenuItem;
    N6: TMenuItem;
    procedure ApplicationEvents1Hint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure mnuExitClick(Sender: TObject);
  private
    { Private declarations }
    myHint: TMenuItemHint;
    procedure WMMenuSelect(var Msg: TWMMenuSelect); message WM_MENUSELECT;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
begin
  { Выводим подсказку в панель состояния }
  StatusBar1.SimpleText:= Application.Hint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  myHint:= TMenuItemHint.Create(Self);
end;

procedure TForm1.mnuExitClick(Sender: TObject);
begin
  Close;
end;

procedure TForm1.WMMenuSelect(var Msg: TWMMenuSelect);
var
  menuItem: TMenuItem;
  hSubMenu: HMENU;
begin
  inherited; // из TCustomForm

  menuItem:= nil;
  if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then
  begin
    if Msg.MenuFlag and MF_POPUP = MF_POPUP then
    begin
      hSubMenu:= GetSubMenu(Msg.Menu, Msg.IDItem);
      menuItem:= Self.Menu.FindItem(hSubMenu, fkHandle);
    end
    else
    begin
      menuItem:= Self.Menu.FindItem(Msg.IDItem, fkCommand);
    end;
  end;

  myHint.DoActivateHint(menuItem);
end;

end.

Можно скачать исходный код программы.


 

Добавить комментарий


Защитный код
Обновить