swnuwangyun-曲终人散成一梦,繁华落尽原是空

专注于:移动设备(Windows Mobile),射频识别(RFID, EPC),嵌入式系统。还有技术攻关,呵呵!

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  51 随笔 :: 1 文章 :: 103 评论 :: 5 Trackbacks

.NET中微软提供了NotifyIcon类来处理应用程序在托盘区的图标显示,并且该对象可以设置一个ContextMenu对象,方便应用程序进行快捷操作。但是,ContextMenu是以右键点击的方式弹出来的,而实际开发中用户经常要求左键单击的时候也能够弹出菜单进行操作,可是微软在NotifyIcon中并没有提供相应的方法来设置,仅有的一个ContextMenu.Show方法也因为NotifyIcon不是Control对象而苦难重重。

到底是怎么回事,难道是微软不推荐我们这样操作?GOOGLE了一下,这个问题还真不少,有一个人的观点很有趣:他说从界面设计角度来说,右键是默认的、众所周知的、被期望的操作方法,而很多开发者却想方设法来破坏这些规则,因此他拒绝帮助别人处理此问题。看了之后觉得很气愤,不错,我们愿意遵循众所周知的界面操作方式以提供用户一致的界面体验,为了验证在NotifyIcon对象上的默认操作方式,我考察了其它第三方软件的处理方式,以我电脑上正在运行的程序为例,分析结果如下:

  • MSN Messenger的NotifyIcon在左键和右键单击时,均弹出相同的菜单。
  • Outlook的NotifyIcon在左键和右键单击时,均弹出相同的菜单。
  • ActiveSync的NotifyIcon在左键和右键单击时,均弹出相同的菜单。
  • Windows Security Alerts,在左键单击时直接激活程序界面,右键单击弹出菜单。

看看吧,4款微软自家的产品,处理的方式也不完全相同,按照少数服从多数的原则,在左键单击时应该也弹出相同的菜单。

DEEP SHIT! 微软简直是在玩我们,.net框架在处理win32的时候,不应当仅仅是简单的封装和不负责任的改进。

那么,让我们GOOGLE一下看是否有相应的解决方法吧。

首先是从ContextMenu.Show入手,网上的分析是使用该函数可以把菜单正确弹出来,但确无法关闭此菜单,而且似乎是没有办法来解决,除非添加一个“关闭”项,强迫用户点击。

另一方面,搜索到一个利用反射的方法来完美处理的方法,代码如下,具体原理我也不想研究了。

Type t = typeof(NotifyIcon);
MethodInfo mi = t.GetMethod("ShowContextMenu", BindingFlags.NonPublic | BindingFlags.Instance);
mi.Invoke(this.notifyIcon1, null);

晕,居然是反射调用Private方法,真是服了,幸亏微软没有完全把路毒死,否则肯定有人找它拼命!

posted on 2007-03-30 18:39 swnuwangyun 阅读(2432) 评论(14)  编辑 收藏

评论

#1楼  2007-03-30 19:16 Clark Zheng      
反射调用Private方法?
  回复  引用  查看    

#2楼  2007-03-30 19:23 U2U      
真恐怖。。。。
  回复  引用  查看    

#3楼  2007-03-30 19:43 航天奇侠      
有这么难么?
有空研究一下。

  回复  引用  查看    

#4楼  2007-03-30 22:07 软件~民工      
微软就是乱搞~
  回复  引用  查看    

#5楼  2007-03-30 23:30 双鱼座      
同情一下。好彩我平时不用WinForm的,要不然抱怨一定比你多。
查了一下,ShowContextMenu方法仅仅是在响应WM_RBUTTONUP消息时被调用过一次。
  回复  引用  查看    

#6楼  2007-03-30 23:43 Anders.Zhao      
受教了,第一次知道有方可以违反系统的限制,调用私有成员,谢谢楼主
  回复  引用  查看    

#7楼  2007-03-31 08:43 rex,xiang      
1. Win32API: SendMessage()就好了。
2. 或者是重载WinProc,把左键点击的消息也换成右键的消息就好了。
  回复  引用  查看    

#8楼  2007-03-31 08:51 双鱼座      
@rex,xiang
每个人都会象你这样想。但是:
1.NotifyIcon是一个Component,句柄没有公开。冲谁SendMessage?
2.WinProc也没有公开,否则连SendMessage都可以省了。
  回复  引用  查看    

#9楼  2007-03-31 09:00 老Q      
.net的 winform程序设计的确实很垃圾的
我的一个项目里用winform做了客户端,那个郁闷阿
感觉.net的我inform跟高中生做的一样
  回复  引用  查看    

#10楼  2007-03-31 09:02 随风流月      
@老Q
速度与简洁。
如果觉得 Winform 垃圾,直接 MFC 开发也不是不可以。
大不了把 .Net 的类库 COM 公开一下。
  回复  引用  查看    

#11楼 [楼主] 2007-03-31 09:57 swnuwangyun      
其实倒不是说要放弃Winfom,而是觉得微软此处处理的不是很合适。正如楼上所说的,我们可以采用强大的MFC,甚至直接调用WIN32 API,但是Winform还是有它的优点,其面向对象的设计确实简化了我们的界面开发,但是就是灵活性差了点,觉得微软在封装WIN32的时候,应该做些改进,毕竟WIN32 用了这么多年了,稳定但也不乏一些垃圾,这些垃圾不应该也被封装进去,而是应该加以改进,当然不是在API层改进,而是在FRAMEWORK层改进。如今.NET3.0都出来了,不知道WINFORM是否有所变动?
  回复  引用  查看    

#12楼 [楼主] 2007-03-31 09:59 swnuwangyun      
# re: 关于NotifyIcon的抱怨。。。 2007-03-31 08:43 rex,xiang
1. Win32API: SendMessage()就好了。
2. 或者是重载WinProc,把左键点击的消息也换成右键的消息就好了。 回复 更多评论

双鱼座说的不错,而且我们也不能随意更改系统消息,偷梁换柱,那样系统不乱套了吗,其它地方需要左键怎么办呢?
  回复  引用  查看    

#13楼  2007-03-31 11:20 小陆      
微软的系统现在不是在开发,而是在维护。
每一个版本都要小心翼翼的做到向前兼容,甚至要去兼容以前版本的缺陷。在标准和兼容之间不断权衡妥协。
有一个网站经常介绍微软产品中的这些现象,向我们介绍一些微软产品奇怪的特征,看上去甚至有些愚蠢,到底是如何一步步形成的。
如果新的系统装上去,很多旧的软件不能用了,新的软件装上去,很多功能找不到了,人们的第一反应就是把它卸载。
不知道这个NotifyIcon是不是又一个折衷的产物。
  回复  引用  查看    

#14楼  2007-03-31 17:00 rex,xiang      
@双鱼座
谢谢你的提醒,我的确搞错了。sealed 的 class, 也没有Handle属性。 :(

public sealed class NotifyIcon : Component
  回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-03-30 18:41 编辑过