让菜单项显示Hint

Delphi的菜单项,就算设置了Hint,它也不会显示,因为没有ShowHint属性。
Delphi自身给出的解决方法是通过一个StatusBar来接收菜单的Hint。
但是,用过Java的Swing的人都知道,在Swing里对一个菜单设置Hint是有效的,它能够被显示出来。
那么是否Delphi也能够显示呢?本文即是给出了一种解决方案。

首先,我们先对Delphi自己的THintWindow类进行一个分析,当用户把鼠标移到TEdit或是其他的带有Hint的控件上时,将触发THintWindow类内的ActivateHint()方法,而鼠标移到菜单项上时,不论是否设置了Hint,都不会触发这个方法。因此,第一步就是要截获鼠标移入菜单的事件,其次就是手动的让Hint窗口显示出来。

我不知道鼠标移入菜单会触发什么消息,但是我知道一定与菜单有关,于是打开Messages.pas,搜一下MENU,可以在这个单元内,发现一些以WM_开头的,带有MENU的消息,稍做推测加测试即可知道,鼠标移入菜单时,触发了WM_MENUSELECT消息。

然后事情就简单了,自己覆盖一下Form的消息循环:

procedure TForm1.WndProc(var msg: TMessage);
begin
case msg.Msg of
    WM_MENUSELECT: ShowHintOnMenu(Handle, msg.WParamLo);
end;
inherited WndProc(msg);
end;

ShowHintMenu()的实现如下:

procedure TForm1.ShowHintOnMenu(h: HWND; wParam: Integer);
var
buf: array[0..255] of Char;
AHint: string;
p: TPoint;
begin
case wParam of
    0..99 :
    begin
      GetMenuString(GetMenu(h), wParam, buf, Length(buf), MF_BYPOSITION);
      if buf = EmptyStr then
        GetMenuString(GetMenu(h), wParam, buf, Length(buf), MF_BYCOMMAND);
    end;
    100..$F000 :
     begin
       GetMenuString(GetMenu(h), wParam, buf, Length(buf), MF_BYCOMMAND);
     end;
    $F001..$FFFF :
    begin
      GetMenuString(GetSystemMenu(h, False), wParam, buf, Length(buf), MF_BYCOMMAND);
    end;
end;
memo1.Lines.Add(buf);
AHint := GetMenuHintByCaption(buf, nil);
memo1.Lines.Add(AHint);
if AHint <> EmptyStr then
begin
    GetCursorPos(p);
    if ht = nil then
      ht := THintWindow.Create(nil);
    ht.ActivateHint(Rect(p.x + 10,p.y+5,p.x+200,p.y+30),AHint);
end;
end;

其中还有一个GetMenuHintByCaption()方法,实现如下:

function TForm1.GetMenuHintByCaption(ACaption: string; AMenuItem: TMenuItem): string;
var
mi: TMenuItem;
begin
Result := EmptyStr;
if AMenuItem = nil then
begin
    for mi in MainMenu1.Items do
    begin
      if mi.Caption = ACaption then
      begin
        Result := mi.Hint;
        Break;
      end;
      if Result = EmptyStr then
        if mi.Count > 0 then
          Result := GetMenuHintByCaption(ACaption, mi);
    end;
end
else
begin

    for mi in AMenuItem do
    begin
      if mi.Caption = ACaption then
      begin
        Result := mi.Hint;
        Break;
      end;
      if Result = EmptyStr then
        if mi.Count > 0 then
          Result := GetMenuHintByCaption(ACaption, mi);
    end;
end;
end;

这样,我们就能在鼠标移入菜单项时,显示出Hint了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值