利用WM_MENUSELECT消息,去创建THintWindow, THintWindow有一个Canvas属性,可以利用它做的漂亮一点 不过要另外加一个过程,就是定时几秒让hint消失,不然Hint会一直停留在在窗体上网上有例子,楼上贴的链接就可以实现。 不过它里面有一个递归过程GetMenuHintByCaption,看起来有点复杂,下面帮你重新写一个 function GetMenuHintByCaption(ACaption: string; AMenuItem: TMenuItem): string; var i:integer; begin for i:=0 to AMenuItem.Count-1 do begin if AMenuItem.Items[i].Caption=ACaption then Result:=AMenuItem.Items[i].Hint else if AMenuItem.Items[i].Count>0 then Result:=GetMenuHintByCaption(ACaption,AMenuItem.Items[i]); end; end;调用 AHint:= GetMenuHintByCaption(buf,MainMenu1.Items);
别个贴的是主要代码,有些东西应该自己懂得去补充,怎么可能会完完全全的照搬下来就能使用的 private ht: THintWindow; procedure MenuHint(var Msg: TWMMENUSELECT); message WM_MENUSELECT; { Private declarations } public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}function GetMenuHintByCaption(ACaption: string; AMenuItem: TMenuItem): string; var i:integer; begin for i:=0 to AMenuItem.Count-1 do begin if AMenuItem.Items[i].Caption=ACaption then Result:=AMenuItem.Items[i].Hint else if AMenuItem.Items[i].Count>0 then Result:=GetMenuHintByCaption(ACaption,AMenuItem.Items[i]); end; end;procedure TForm1.MenuHint(var Msg: TWMMENUSELECT); var buf:array[0..255] of Char; AHint:string; p: TPoint; ItemID:Word; begin ItemID:= Msg.IDItem; case ItemID of 0..99: begin GetMenuString(GetMenu(Handle), ItemID, buf, Length(buf), MF_BYPOSITION); if buf = EmptyStr then GetMenuString(GetMenu(Handle), ItemID, buf, Length(buf), MF_BYCOMMAND); end; 100..$F000:GetMenuString(GetMenu(Handle), ItemID, buf, Length(buf), MF_BYCOMMAND); $F001..$FFFF:GetMenuString(GetSystemMenu(Handle, False), ItemID, buf, Length(buf), MF_BYCOMMAND); end; AHint:=GetMenuHintByCaption(buf,MainMenu1.Items); if AHint <> '' then begin if not Assigned(ht) then ht:=THintWindow.Create(self); GetCursorPos(p); ht.ActivateHint(Rect(p.x + 10,p.y+5,p.x+200,p.y+30),AHint); end; inherited; end;end.
Demo: Delphi 菜单的Hint (Delphi 2007)主要代码片段: type TForm1 = class(TForm) ... procedure FormCreate(Sender: TObject); private FOldWndProc: Pointer; FHintWindow: THintWindow; procedure MyWndProc(var M: TMessage); ... end;...procedure TForm1.FormCreate(Sender: TObject); begin FOldWndProc := Pointer(SetWindowLong(PopupList.Window, GWL_WNDPROC, Longint(MakeObjectInstance(MyWndProc)))); FHintWindow := THintWindow.Create(Self); FHintWindow.Color := Application.HintColor end;procedure TForm1.MyWndProc(var M: TMessage); var R: TRect; begin if M.Msg = WM_ENTERIDLE then if M.WParam = MSGF_MENU then if IsWindowVisible(FHintWindow.Handle) then if WindowFromPoint(Mouse.CursorPos) <> M.LParam then begin M.Result := 0; ShowWindow(FHintWindow.Handle, SW_HIDE); FHintWindow.Visible := False; Exit end;
CallWindowProc(FOldWndProc, PopupList.Window, M.Msg, M.WParam, M.LParam); if M.Msg = WM_MENUSELECT then begin if Application.Hint <> '' then begin R := FHintWindow.CalcHintRect(Width, Application.Hint, nil); OffsetRect(R, Mouse.CursorPos.X, Mouse.CursorPos.Y + 20); FHintWindow.ActivateHint(R, Application.Hint); SetWindowPos(FHintWindow.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE) end; end; end;
不过要另外加一个过程,就是定时几秒让hint消失,不然Hint会一直停留在在窗体上网上有例子,楼上贴的链接就可以实现。
不过它里面有一个递归过程GetMenuHintByCaption,看起来有点复杂,下面帮你重新写一个
function GetMenuHintByCaption(ACaption: string; AMenuItem: TMenuItem): string;
var
i:integer;
begin
for i:=0 to AMenuItem.Count-1 do
begin
if AMenuItem.Items[i].Caption=ACaption then
Result:=AMenuItem.Items[i].Hint
else if AMenuItem.Items[i].Count>0 then
Result:=GetMenuHintByCaption(ACaption,AMenuItem.Items[i]);
end;
end;调用
AHint:= GetMenuHintByCaption(buf,MainMenu1.Items);
ht: THintWindow;
procedure MenuHint(var Msg: TWMMENUSELECT); message WM_MENUSELECT;
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}function GetMenuHintByCaption(ACaption: string; AMenuItem: TMenuItem): string;
var
i:integer;
begin
for i:=0 to AMenuItem.Count-1 do
begin
if AMenuItem.Items[i].Caption=ACaption then
Result:=AMenuItem.Items[i].Hint
else if AMenuItem.Items[i].Count>0 then
Result:=GetMenuHintByCaption(ACaption,AMenuItem.Items[i]);
end;
end;procedure TForm1.MenuHint(var Msg: TWMMENUSELECT);
var
buf:array[0..255] of Char;
AHint:string;
p: TPoint;
ItemID:Word;
begin
ItemID:= Msg.IDItem;
case ItemID of
0..99: begin
GetMenuString(GetMenu(Handle), ItemID, buf, Length(buf), MF_BYPOSITION);
if buf = EmptyStr then
GetMenuString(GetMenu(Handle), ItemID, buf, Length(buf), MF_BYCOMMAND);
end;
100..$F000:GetMenuString(GetMenu(Handle), ItemID, buf, Length(buf), MF_BYCOMMAND);
$F001..$FFFF:GetMenuString(GetSystemMenu(Handle, False), ItemID, buf, Length(buf), MF_BYCOMMAND);
end; AHint:=GetMenuHintByCaption(buf,MainMenu1.Items); if AHint <> '' then
begin
if not Assigned(ht) then
ht:=THintWindow.Create(self);
GetCursorPos(p);
ht.ActivateHint(Rect(p.x + 10,p.y+5,p.x+200,p.y+30),AHint);
end; inherited;
end;end.
1.每个TMenuItem只要hint有值,那么当鼠标悬浮上去的时候就显示hint提示框。
2.当鼠标离开按钮后hint提示框消失。
3.要求hint提示框显示在鼠标旁边,或是对应按钮的旁边,而不是电脑右下角。
谢谢各位大侠们,求解答。
type
TForm1 = class(TForm)
...
procedure FormCreate(Sender: TObject);
private
FOldWndProc: Pointer;
FHintWindow: THintWindow;
procedure MyWndProc(var M: TMessage);
...
end;...procedure TForm1.FormCreate(Sender: TObject);
begin
FOldWndProc := Pointer(SetWindowLong(PopupList.Window, GWL_WNDPROC,
Longint(MakeObjectInstance(MyWndProc))));
FHintWindow := THintWindow.Create(Self);
FHintWindow.Color := Application.HintColor
end;procedure TForm1.MyWndProc(var M: TMessage);
var
R: TRect;
begin
if M.Msg = WM_ENTERIDLE then
if M.WParam = MSGF_MENU then
if IsWindowVisible(FHintWindow.Handle) then
if WindowFromPoint(Mouse.CursorPos) <> M.LParam then
begin
M.Result := 0;
ShowWindow(FHintWindow.Handle, SW_HIDE);
FHintWindow.Visible := False;
Exit
end;
CallWindowProc(FOldWndProc, PopupList.Window, M.Msg, M.WParam, M.LParam);
if M.Msg = WM_MENUSELECT then
begin
if Application.Hint <> '' then
begin
R := FHintWindow.CalcHintRect(Width, Application.Hint, nil);
OffsetRect(R, Mouse.CursorPos.X, Mouse.CursorPos.Y + 20);
FHintWindow.ActivateHint(R, Application.Hint);
SetWindowPos(FHintWindow.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or
SWP_NOMOVE or SWP_NOSIZE)
end;
end;
end;
自己封装吧Demo都跟你写了~!