怎样在Image的Hint上动态显示目前鼠标的位置?(100分)

  • 主题发起人 主题发起人 hanson
  • 开始时间 开始时间
H

hanson

Unregistered / Unconfirmed
GUEST, unregistred user!

我想在鼠标移动时,用TImage的Hint显示当前鼠标所在Image上的坐标,
可是我改变了HInt的值以后,Hint框仍显示原来的内容,如果我强行把Hint
框藏起来,它又不出来了,必须用鼠标单击一下Image后才出来或将鼠标先移
动到其它控件上再回来才行! 我想作到不用点击,再移动鼠标时坐标自动
显示再Hint框中,而且Hint框随鼠标移动!

谢谢

 

另外,别告诉我自己做一个窗口来模仿Hint框,我还是想用
现成的!
 
好像不太可能.至少在VCL内部的体制下.
我们来看一看hint的处理过程.

在每一个TControl的消息处理时,对TWMMouseMove都有一个处理,
去调用Application.HintMouseMove,在HintMouseMove里判断是否
应该去出现一个新的hint window;

procedure TApplication.HintMouseMessage(Control: TControl; var
Message: TMessage);
var
NewHintControl: TControl;
Pause: Integer;
WasHintActive: Boolean;
begin
NewHintControl := GetHintControl(FindDragTarget(Control.ClientToScreen(SmallPointToPoint
(TWMMouse(Message).Pos)), True));
//这一句试图得出当前的拥有hint权的Control;

if (NewHintControl = nil) or not NewHintControl.ShowHint then
CancelHint
//若showhint被封锁,就把原来可能有的hint窗口关掉;

else
begin
if (NewHintControl <> FHintControl) or
(not PtInRect(FHintCursorRect,
Control.ClientToScreen(SmallPointToPoint(TWMMouse(Message).Pos))))
then

// 关键就在这个条件判断上: 它的判断条件是鼠标是不是在FHintCursorRect
//的内部.而为了节省时间,delphi是在显示hint窗口( 在activateHint函数中)的
//时候置FHintCursorRect为当前HintControl的Rect;
//而如果在当前的image上已经有hint出现了,就不会出现满足条件的情况!

begin
//下面是处理出现一个新的hint window;

WasHintActive := FHintActive;
if WasHintActive then
Pause := FHintShortPause else
Pause := FHintPause;
CancelHint;
FHintActive := WasHintActive;
FHintControl := NewHintControl;
StartHintTimer(Pause, tmShow);

end;
end;
end;

一个很显然的想法是能不能自己改FHintCursorRect,但这是Tapplication
私有的,并且ActivateHint, HintMouseMessage, CancelHint,都是这样.

只要cancelRect或HintMouseMessage中的一个能override,事情就都好办.
可惜好像不能.
而且,只要沿用这个体系来处理hint,在一个control内永远不能动态更改
hint.

要是有什么UpdateHint就好了,可惜和ActivateHint有关的属性全都是
私有的.

除非你全部抛弃这样的体制,自己画hintwindow,不然....

去找找控件吧,因该有人早做好了.这可实在是很需要的效果.
 
有第三方的控件你用不用?
 
APPLICATION所有的HINT都使用同一个窗口.
APPLICATION生成时会自动创建一个THINTWINDOW类的窗口。
你可以APPLICATION.COMPONENTS AS THINTWINDOW得到此窗口,
可以在它的CANVAS上直接TEXTOUT,或用方法ActivateHint,窗口
具体的位置可以用IMAGE1.CLINTTOSCREEN得到,窗口大小通过方法
CalcHintRect得到。因为是手工ACTIVE HINT WINDOW,所以无需设置
IMAGE的SHOWHINT值。
 
不过我认为有这工夫还不如用lable模仿一个
Onimageenter:lable1.visible:=true;
onimageexit:label1.visible:=false;
onimagemouseover:label1.left:=image1.left+x;
label1.top:=image1.top+y;
这样不是更省事!还可以自定义label1的字体...
 
用label可不行, 至少得用panel
 
为什么?他用TImage,不会挡住。
 
to tlaobao :
漂亮! well done!
 
建议不要使用Hint Window来动态显示鼠标的坐标, 应该用StatusBar来显示鼠标坐
标. 原因有二个:

1. 在Image上面显示任何移动的窗体都会在窗体移动后刷新Image, 如果Image较大
的话, 就会产生闪烁现象.
2. Hint 窗体有延时, 不适于显示变化频繁的信息.

如果实在想实现那个Hint效果, 除了你现在使用的方法外, 就是用delphi fan2所提
出的TLabel了, 没有更好的办法了. 即使你现在使用的方法, 也应该让Hint窗体的位置相对固定(例如: 在图像的四个角上), 不要数着鼠标频繁移动.
 
用label至少缺个边框。如果这个image在某个panel中, 用label有时可能被cut掉
一部分(如果label的位置超出这个panel的话)。
用panel模拟也有同样毛病, 如果该panel超出form的边界的话。
 
我试了一下,果然刷新比较慢.可是这个感觉实在是很好的,如果有时间可以用
双缓冲自己编程序和Timage一起显示吧.
 
谢谢大家帮忙!

我认为tlaolao的办法很好,只是少了Hint弹出的延时效果!

曹晓钢分析的源码也很精辟!


 

Similar threads

D
回复
0
查看
744
DelphiTeacher的专栏
D
D
回复
0
查看
718
DelphiTeacher的专栏
D
D
回复
0
查看
672
DelphiTeacher的专栏
D
D
回复
0
查看
909
DelphiTeacher的专栏
D
后退
顶部