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了。
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了。