你采取了完全错误的方法。与其使用OnMouseMove
事件手动设置Hint
和调用Application.ActivateHint()
,不如让 VCL 为您处理一切。
使用TApplication.OnShowHint
事件,或者子类化 StringGrid 来拦截CM_HINTSHOW
消息,以自定义 StringGrid 的本机提示的行为方式。任何一种方法都可以让您访问THintInfo
记录,这允许您在显示/更新当前提示之前对其进行自定义。特别是,该THintInfo.CursorRect
成员允许您设置 VCL 用来跟踪鼠标并决定何时/是否需要触发新OnShowHint
事件或CM_HINTSHOW
消息以更新当前提示的矩形,而鼠标仍在显示的控件内提示。该更新比现在的更新更加干净和无缝TApplication.ActivateHint()
。
例如:
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnShowHint := AppShowHint;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Application.OnShowHint := nil;
end;
procedure TForm1.AppShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo);
var
Col, Row: Longint;
begin
if HintInfo.HintControl := StringGrid1 then
begin
StringGrid1.MouseToCell(HintInfo.CursorPos.X, HintInfo.CursorPos.Y, Col, Row);
if (Col >= 0) and (Row >= 0) then
begin
HintInfo.CursorRect := StringGrid1.CellRect(Col, Row);
HintInfo.HintStr := StringGrid1.Cells[Col, Row];
end;
end;
end;
或者:
private
OldWndProc: TWndMethod;
procedure TForm1.FormCreate(Sender: TObject);
begin
OldWndProc := StringGrid1.WindowProc;
StringGrid1.WindowProc := StringGridWndProc;
end;
procedure TForm1.StringGridWndProc(var Message: TMessage);
var
HintInfo: PHintInfo;
Col, Row: Longint;
begin
if Message.Msg = CM_HINTSHOW then
begin
HintInfo := PHintInfo(Message.LParam);
StringGrid1.MouseToCell(HintInfo.CursorPos.X, HintInfo.CursorPos.Y, Col, Row);
if (Col >= 0) and (Row >= 0) then
begin
HintInfo.CursorRect := StringGrid1.CellRect(Col, Row);
HintInfo.HintStr := StringGrid1.Cells[Col, Row];
Exit;
end;
end;
OldWndProc(Message);
end;
如果您希望在单元格内的每次鼠标移动时更新提示,只需将 设置THintInfo.CursorRect
为当前THintInfo.CursorPos
位置的 1x1 矩形。如果您希望即使鼠标没有移动也能定期更新提示,请将 设置为THintInfo.ReshowTimeout
非零间隔(以毫秒为单位)。