none
如何获取系统托盘某个图标的坐标区域 RRS feed

  • 问题

  • 这个是我在网上找到的,用关键字 获取系统托盘区图标的坐标 在谷歌里查到的,可是不知道应该怎么用,看前后文应该是用Delphi写的,在C#中如何实现这个功能?

    获取系统托盘某个图标的坐标区域,如果要隐藏某个图标例如音量的图标,也很方便,改改就可以了
          function GetSysTrayIconRect(Text: string): TRect;
          {
             返回系统托盘中指定文字的图标的矩形区域。
             例如返回音量控制图标的矩形区域:
             GetSysTrayIconRect('音量');
          }
          begin
             result := GetToolBarButtonRect(GetSysTrayWnd, Text);
          end;
    2009年10月31日 6:13

答案

  • 你好!

    你先前的问题不是解决了吗?上面的代码不是C#的所以編不过。

    知识改变命运,奋斗成就人生!
    • 已标记为答案 qiyao 2009年10月31日 10:55
    2009年10月31日 6:23
    版主

全部回复

  • 你好!

    你先前的问题不是解决了吗?上面的代码不是C#的所以編不过。

    知识改变命运,奋斗成就人生!
    • 已标记为答案 qiyao 2009年10月31日 10:55
    2009年10月31日 6:23
    版主
  • X.X.Y 您好。前面的帖子,您帮助我解决了一个问题,就是获得鼠标当前坐标的问题,但是,您的方案我感觉有些问题,现描述如下:

    notifyIcon1_MouseMove()方法中将当前鼠标的坐标值保存在lastPoint中,只要鼠标在系统托盘图标范围内移动,则lastPoint中的值就会一直更新;
    timer1_Tick()方法中用当前鼠标的坐标值和lastPoint中的值进行比较,如果不同则判断为鼠标离开了
    这个方法有个必要条件,那就是notifyIcon1_MouseMove()方法必须在timer1_Tick()方法先执行,可是,我找了半天也没有找到两个方法那个会先执行的说明
    怕如果出现下面的情况:如果正在执行timer1_Tick()方法的时候,我动了鼠标,那timer1_Tick()方法中得到的鼠标坐标值一定和保存原来坐标值的lastPoint中的内容不同,因为notifyIcon1_MouseMove()还没有更新lastPoint中的内容,则会造成错误的判断。
    正好在网上又找到了我前面发的那段程序,想如果能知道系统托盘中图标的范围,则一定不会出现错误判断的情况,所以又才发了这个帖子。
    呵呵,因为我是搞单片机的,对程序的稳定性习惯性地想多了些,如果不当,也请你原谅。

    2009年10月31日 7:18
  • 1 邮于 timer 默认间隔是 100 毫秒很快,我认为是不存在你所述的问题的
    2 如果你获取到拖盘图标的区域,你可能使用 timer 去检测当前的坐标是否在这个区域之内。如果你的想法如我所述。那么先前的方法和现在的方法本质上都是判断当前鼠标的坐标是否在托盘图标区域。


    知识改变命运,奋斗成就人生!
    2009年10月31日 7:31
    版主
  • 问题的关键是两个方法是否会同时运行,如果可以,你的方法就可以正常执行,我可以在timer1_Tick()方法中进行多次判断,让notifyIcon1_MouseMove()方法有足够的时间更新lastPoint中的值,如果不能同时运行,那我说的问题就有可能出现的,虽然概率很低。
    请教中

    2009年10月31日 7:37
  • 那你可以换种思路去做,在 mousermove 事件中去将 timer 的 enable 设置为 true. timer 检测后再将 enable 设为 false. 这样相当于延时执行,move 事件在前, timer 处理在后。
    知识改变命运,奋斗成就人生!
    2009年10月31日 8:13
    版主
  • 在新窗口里用timer的目的就是让新出现的窗口里按等时间间隔显示实时的数据,如果按这个方法,如果我的鼠标不动,则新窗口的数据将不再更新,如果我一直晃动鼠标,新窗口的数据又将以极快的速度在更新,不符合设计的要求呢。
    我正在查MSDN里的System.Windows.Forms.ToolBar 类的资料,希望能有所发现。
    2009年10月31日 8:26
  • 这里需要使用一些方法,比如短时间内连续触发 mousemove 事件,最终的监测只做一次,而不是多次。
    知识改变命运,奋斗成就人生!
    2009年10月31日 8:29
    版主
  • 你好!
         可以在Timer的触发事件中判断鼠标是否移动了,Cursor.Position可以获得鼠标位置,第一次把位置保存起来,下一次和这个值做比较,看鼠标是否移动了!
    周雪峰
    2009年10月31日 8:40
    版主
  • 现在程序的设计是想当程序最小化到系统托盘后,如果鼠标移动到系统托盘的该程序的图标上,就显示一个新窗口,新窗口里的数据按等时间间隔进行刷新。
    通过notifyIcon1_MouseMove()方法可以打开新的窗口,可是,如果鼠标还在系统托盘的图标上移动,就不能关闭窗口,必须等鼠标移出这个范围后才能关闭,否则会出现的情况是
    鼠标在图标范围内一移动,新窗口就关闭了,因为新窗口是判断鼠标是否移动的,鼠标动一个像素,都会使新窗口关闭了,而用户怎么可能把鼠标定位在触发notifyIcon1_MouseMove()方法就立刻停住鼠标呢?
    一定有惯性的,有的鼠标很灵敏,不动鼠标,像素点都会晃动呢。感觉楼上的方法不可行呢。
    2009年10月31日 8:51
  • 刚回复完,就想到了一个方法:
    设置一个全局变量A,默认为空
    notifyIcon1_MouseMove()方法打开新窗口后,延时秒0.5后把当前的鼠标坐标赋值给lastPoint(假设用户肯定会在0.5秒内停住鼠标不动)
    Timer方法正常更新数据,当全局变量A不等于空后再判断鼠标的坐标并且和lastPoint中的值进行比较,如果不同,就关闭窗口。
    这个方法应该是个变通的方法。如果能得到图标的范围进行判断是最好的,可是,我刚才去看了MSDN中的System.Windows.Forms.ToolBar的资料
    我的水平太低了,只能看懂方法和属性两种图标的意思,知道这些是表示方法和属性,其他很多图标都看不懂,连那些图标表示什么意思都不明白。路还很长很长。

    请X.X.Y和周雪峰两位先生看下这个方法是否可行?
    2009年10月31日 9:01
  • 这方法是可行的。这个方法和我们给你建议的方法是一样的,只是实现方式不同。另外我第一次给你的示例也并未出现,在图标范围内移动隐藏窗体的问题。
    知识改变命运,奋斗成就人生!
    2009年10月31日 9:07
    版主
  • 这个事件默认就支持气球提示,你设置这些属性就可以了:
    http://msdn.microsoft.com/zh-cn/library/system.windows.forms.notifyicon.balloontiptext%28VS.80%29.aspx

    你可以在BalloonTipShown事件中启动Timer来更新数据
    在BalloonTipClosed事件中关闭Timer就可以了!

    我感觉如此设计比较合理!
    周雪峰
    2009年10月31日 9:18
    版主
  • 您的第一次回复中的方法是先把新窗口建立了,只是不显示,感觉这样会浪费系统资源,也许我写单片机程序习惯了节省每一个字节的内存。
    因为显示新窗口的动作毕竟还是很少的,我还是想在鼠标移动到图标上后再建立窗口,在新窗口判断鼠标已经移开图标后关闭窗口,节省系统资源。在我没有明白我这样有什么坏处的情况下。
    只是纯技术上的讨论,绝不没有半点对您及周雪峰的不尊敬,我对2位能如此无私的帮助我这个新人是感谢万分的。

    2009年10月31日 9:20
  • 气球提示不能自己关闭,必须要手工关闭,我以前也想用这个功能的。


    补充一下

    notifyIcon1_MouseMove()方法打开新窗口后,延时秒0.5后把当前的鼠标坐标赋值给lastPoint(假设用户肯定会在0.5秒内停住鼠标不动)

    这个方法应该改为一直检测鼠标的坐标,直到鼠标坐标不变后,就保存当前鼠标的坐标值供新窗口判断用。
    2009年10月31日 9:21
  • 不推荐这样设计,这样通常令客户十分的疑惑!
    如果想显示用户控制的窗体,最好让用户点击,而不要破坏气球提示的行为!
    周雪峰
    2009年10月31日 9:34
    版主
  • 这个新窗口只是显示一些实时的数据,具体的功能设置是有一个主窗口的,在双击图标后就会恢复主窗口,用户所有的操作都在主窗口中进行。

    2009年10月31日 9:36
  • 你好!
         实际上你不用这么客气啊!
         大家一起交流技术嘛,只是观点不同,并不涉及到尊重与否的问题啊!
         很高兴和你讨论这个问题呢!
         气球提示是可以设置显示显示时间的,时间到了自己就会自己关闭了啊!我感觉这可以满足你的需求!如果我没有领会你的真正需求,请进一步说明你的详细需求!
    周雪峰
    2009年10月31日 10:28
    版主
  • 呵呵,我只是个初学者,学这个才半个月,只能向你们学习呢。

    程序的设计是程序有一个主窗口,在主窗口里可以进行各种设置,当主窗口最小化到系统托盘后,如果鼠标移动到系统托盘的该程序的图标上,就显示一个提示窗口,提示窗口里的数据按等时间间隔进行刷新(实时数据,目前定为间隔1秒)。

    通过notifyIcon1_MouseMove()方法可以打开提示窗口,问题的关键是如何知道鼠标离开了系统托盘里的图标.

    现在的解决方法是
    notifyIcon1_MouseMove()方法里打开新窗口,并且开始比较鼠标的坐标,如果鼠标的坐标不变了,则将鼠标的坐标保存在一个全局变量中,并且将鼠标状态标志位置位

    提示窗口里的Timer方法正常显示数据的同时,检测鼠标状态标志位,如果鼠标状态标志位置位,则表示鼠标已经停住了,就比较当前的鼠标坐标和已经保存的鼠标坐标,如果两者不同,则表示鼠标又已经移动了,就关闭提示窗口,将鼠标状态标志位复位。一次操作完成。


    不知道我描述的是否清楚。

    2009年10月31日 10:43
  • 这个问题现在已经解决了,程序测试已经通过,非常感谢两位的帮助。现在结贴了,分已送上,谢谢。
    2009年10月31日 10:54
  • 这个控件并没有提供鼠标离开的事件啊!
    周雪峰
    2009年10月31日 11:44
    版主