あなたは完全に間違ったアプローチを取っています。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
で を 1x1 の四角形に設定するだけです。THintInfo.CursorPos
マウスを動かさなくても定期的にヒントを更新する場合はTHintInfo.ReshowTimeout
、ミリ秒単位でゼロ以外の間隔を設定します。