急: 怎么样才能做出一个像 SyGate 一样的 Hint --- From xiao.lit(200分)

  • 主题发起人 主题发起人 xiao.lit
  • 开始时间 开始时间
X

xiao.lit

Unregistered / Unconfirmed
GUEST, unregistred user!
在 SyGate 使用的过程中, 我发现它的一个特点: 会在 Tray Icon 上面<br>提示当前的状态, 如:<br>Dialling use 169 ...<br>Verifying user name and password<br>network connected<br>之类的提示信息<br><br>请问这可以通过哪个 API 可以实现?<br>Shell_NotifyIcon() 里设置的 Tip 属性要鼠标移动过去才能提示, 但是 SyGate<br>不需要鼠标的动作也能提示, 这是怎么实现的呢?
 
很急啊, 大伙儿帮帮忙, 分不够还可以加
 
根本不是hint,只是自己根据不同的状态写不同的字符串。
 
你是用控件还是用API代码实现的Tary Icon,如果是用控件的话,可以直接设置HINT属性<br>就可以了,用API的话,我就不知道了。 :(
 
为什么不可能用stayontop的无边界窗口来模拟呢
 
to zyy04: &nbsp; &nbsp; &nbsp;能说详细一点么?<br>to 教父: &nbsp; &nbsp; &nbsp; 我是用 API 来做的<br>to eyes4: &nbsp; &nbsp; &nbsp;我试过, 我使用了一个非模态对话框来模拟但是效果不理想<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;窗体有时候收不到 WM_PAINT 消息, 我将窗体属性设置为<br> SetWindowPos(&amp;wndTopMost, x - width,<br> y - height , width, height,SWP_NOACTIVATE);<br>然后将一个窗口, 比如说是我的脑最大化最小化几次后, 窗体就不见了, 很是奇怪<br>
 
Shell_NotifyIcon()函数 的 NOTIFYICONDATA 结构的 szTip 成员赋值就可以了。<br><br>typedef struct _NOTIFYICONDATA { // nid &nbsp;<br>&nbsp; &nbsp; DWORD cbSize; <br>&nbsp; &nbsp; HWND hWnd; <br>&nbsp; &nbsp; UINT uID; <br>&nbsp; &nbsp; UINT uFlags; <br>&nbsp; &nbsp; UINT uCallbackMessage; <br>&nbsp; &nbsp; HICON hIcon; <br>&nbsp; &nbsp; char szTip[64]; <br>} NOTIFYICONDATA, *PNOTIFYICONDATA; <br><br>
 
to sharkHun:<br>谢谢. &nbsp;这个办法已经试过了<br>这里设置的 Tip 要鼠标移到图标上面才显示<br>我要的是在任何情况下都能显示
 
用模态对话框已经可以实现. 但是效果不是很好, 只能将就一下<br>使用 SetForegroundWindow() 将窗口设置为最前, 这样, 所有的窗口都不能挡住它<br>我觉得使用一个对话框来显示这些内容太奢侈了, 如果能直接显示出来会好一点.<br><br>各位请继续
 
Come on, 不是要我拿个对话框交差吧
 
to xiao.lit:<br>&nbsp; &nbsp; 如果你能找到Delphi里对TTM_XXXX消息(即ToolTip消息)以及TOOLINFO的定义可能就好办了。我是没找到:(<br><br>我用THintWindow试了一下,显示效果还行,可是显示的时机不好控制。所以只好用定时器了,供你参考一下吧——<br><br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls, ComCtrls, ShellApi, AppEvnts, ExtCtrls;<br><br>const<br>&nbsp; WM_MYICON = WM_USER + 2000;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; ApplicationEvents1: TApplicationEvents;<br>&nbsp; &nbsp; tmrHint: TTimer;<br>&nbsp; &nbsp; tmrHide: TTimer;<br>&nbsp; &nbsp; procedure FormCreate(Sender: TObject);<br>&nbsp; &nbsp; procedure ApplicationEvents1Minimize(Sender: TObject);<br>&nbsp; &nbsp; procedure FormClose(Sender: TObject; var Action: TCloseAction);<br>&nbsp; &nbsp; procedure tmrHintTimer(Sender: TObject);<br>&nbsp; &nbsp; procedure tmrHideTimer(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; IconData: TNotifyIconData;<br>&nbsp; &nbsp; HintPos: TPoint;<br>&nbsp; &nbsp; WinHint: THintWindow;<br>&nbsp; &nbsp; procedure WMMyIcon(var Message: TMessage); message WM_MYICON;<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>&nbsp; IconData.cbSize := SizeOf(TNotifyIconData);<br>&nbsp; IconData.Wnd := Handle;<br>&nbsp; IconData.uID := 0;<br>&nbsp; IconData.uCallbackMessage := WM_MYICON;<br>&nbsp; IconData.hIcon := Application.Icon.Handle;<br>&nbsp; IconData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;<br>&nbsp; IconData.szTip := '';<br>&nbsp; WinHint := THintWindow.Create(Application);<br>&nbsp; WinHint.Color := clInfoBk;<br>&nbsp; tmrHint.Interval := Application.HintPause;<br>&nbsp; tmrHide.Interval := Application.HintHidePause;<br>end;<br><br>procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);<br>begin<br>&nbsp; WinHint.Free;<br>end;<br><br>procedure TForm1.ApplicationEvents1Minimize(Sender: TObject);<br>begin<br>&nbsp; Hide;<br>&nbsp; Shell_NotifyIcon(NIM_ADD, @IconData);<br>end;<br><br>procedure TForm1.WMMyIcon(var Message: TMessage);<br>begin<br>&nbsp; case Message.LParam of<br>&nbsp; &nbsp; WM_LBUTTONDBLCLK: begin<br>&nbsp; &nbsp; &nbsp; Shell_NotifyIcon(NIM_DELETE, @IconData);<br>&nbsp; &nbsp; &nbsp; tmrHint.Enabled := False;<br>&nbsp; &nbsp; &nbsp; WinHint.ReleaseHandle;<br>&nbsp; &nbsp; &nbsp; Show;<br>&nbsp; &nbsp; &nbsp; Application.Restore;<br>&nbsp; &nbsp; &nbsp; Application.BringToFront;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; WM_MOUSEMOVE: begin<br>&nbsp; &nbsp; &nbsp; if not tmrHint.Enabled then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; HintPos := Mouse.CursorPos;<br>&nbsp; &nbsp; &nbsp; &nbsp; tmrHint.Enabled := True;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br>procedure TForm1.tmrHintTimer(Sender: TObject);<br>var<br>&nbsp; s: String;<br>&nbsp; R: TRect;<br>begin<br>&nbsp; s := FormatDateTime('HH"时"MM"分"SS"秒"', Time);<br>&nbsp; with WinHint do begin<br>&nbsp; &nbsp; R := CalcHintRect(Canvas.TextWidth(StringOfChar('H', 64)), s, nil);<br>&nbsp; &nbsp; OffSetRect(R, HintPos.x, HintPos.y - R.Bottom - 10);<br>&nbsp; &nbsp; ActivateHint(R, s);<br>&nbsp; end;<br>&nbsp; tmrHide.Enabled := True;<br>end;<br><br>procedure TForm1.tmrHideTimer(Sender: TObject);<br>begin<br>&nbsp; tmrHide.Enabled := False;<br>&nbsp; WinHint.ReleaseHandle;<br>&nbsp; tmrHint.Enabled := False;<br>end;<br><br>end.
 
非常感谢 dq. 我用的是 D3, 以上代码编译时有点麻烦, 不过都算 OK 了<br>显示的时机果然不好控制, 看来一个 Timer 少不了的了<br>我看了一下 THintWindow 的源代码(controls.pas), 发现它也是用一个 Window 来显示 Tips 的<br>看来还是不能摆脱窗体的限制<br><br>&lt;b&gt;难道职能这样么?&lt;/b&gt;
 
仔细观察了一下SyGate和网络监视器的提示,我觉得它们可能也是用的自己的窗口。<br>因为标准的ToolTip有一个黑边儿,它们的没有,而且还有换行和格式控制。<br>我这儿装SyGate的机子没有Spy,你可以用Spy++看一下:<br>找所有类名为“tooltips_class32”的窗口,选择截它们的消息,然后把鼠标放在SyGate<br>的图标上看有没有反应;如果都没有那就应该说明它用的不是szTip。<br><br>用窗口倒没什么,不过还是时机的问题;不知道它们是怎么掌握的,但是也可以看出有延时……<br>如果你实在不想单开窗口的话,我再给你出个馊主意:)——<br>比如可以在回调函数的WM_MOUSEMOVE响应代码里<br>用WindowFromPoint(座标就用鼠标当前位置稍往右上一点儿,得估计了)<br>找到标准的提示窗口(通过GetClassName判断类名)的Handle;<br>然后用GetDC得到它的客户区DC,这样就可以直接在上面输出字符串了。<br><br>——这个方法的关键就是找准ToolTip窗口,所以我说要是能找到Delphi里对ToolTip消息的定义就好办了。<br>我看了一下API的说明,觉得发消息应该可以,而且也可以改变提示内容的,就省得自己画了。<br>不过因为没找到相关的消息和那个重要结构TOOLINFO的定义,所以还不知道具体行不行:)<br><br>再听听别人的看法吧。
 
多人接受答案了。
 
已经交差了, 做了个冒牌货hehe
 
后退
顶部