Jerry@完美生活

青春的岁月,我们身不由己,只因这胸中,燃烧的梦想;青春的岁月,放浪的生涯,就任这时光,奔腾如流水。 体会这狂野,体会孤独,体会这欢乐,爱恨离别;体会这狂野,体会孤独,这是我的完美生活,也是你的完美生活。 我多想看到你,那依旧灿烂的笑容,再一次释放自己,胸中那灿烂的情感,我多想告诉你,那依旧灿烂的笑容,再一次释放自己。

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

最近写了一个程序,客户需要用Enter切换输入焦点,像TAB键那样(Windows Form, .net)。据说国内的很多应用软件都是这样,已经成为一种事实上的标准了。

既然是一种事实上的标准了,我想应该就有至少一种标准的实现吧。立刻请教一位在国内的软件公司作开发的朋友,他们公司的解决方案是:继承所有需要转换的控件,如TextBox ComboBox 重载OnKeyDown方法,如果输入Enter 向应用程序发送TAB键盘事件。
 
向应用程序发送TAB键盘事件非常好,然而,继承所有的控件,实在不敢恭维,代码分散在各处且不说,如果碰到一个第三方控件,不能继承怎么办?

既然实现一个功能,而且实现的代码一样,首先应该考虑,能否在一个地方实现,不是在所有的控件中做同样的事。既然是截获控件的事件,首先想到的当然是Control.WndProc,因为它是所有控件的基类,然而,我们不能去修改Control。这时,想到MessageFilter是理所当然的了。

.net framework允许应用程序在消息派发到ControlForm之前截获到他。你只需要实现IMessageFilter,并通过Application.AddMessageFilter把它加到Application中。我们就可以为这个应用实现一个MessageFilter,如果收到WM_KEYDOWN事件,并且KeyEnter,其它的修饰键没有被按下的情况下,向应用程序发送TAB键盘事件,同时返回true,不往下派发Enter键,实现代码如下:

     public class MessageFilter : IMessageFilter
         {
                   private readonly static IList StopControlTypes =

                           new Type[] {typeof(TextBox), typeof(ComboBox)};
                   private const int WM_KEYDOWN = 0x100;

                    public MessageFilter()
                   {
                   }
                    public bool PreFilterMessage(ref Message m)
                   {
                            if (m.Msg == WM_KEYDOWN && Control.ModifierKeys == Keys.None && m.WParam.ToInt32() == (int)Keys.Enter)
                            {
                                     Control ctr = Control.FromHandle(m.HWnd);
                                     if (ctr == null)
                                     {
                                               ctr = Control.FromChildHandle(m.HWnd);
                                     }

                                      if (ctr != null && StopControlTypes.IndexOf(ctr.GetType()) >= 0)
                                     {
                                               SendKeys.Send("{Tab}");
                                               return true;
                                     }
                            }

                             return false;
                   }
         }      

代码很简单。细细一想,你会发现,前一种方法是一种方法是一个纯OO的解决方案,而后一种,是一个AOP的解决方案,用Enter键实现切换焦点是程序的一个方面。 在程序中适当应用一些AOP的思想,虽然整体看来不是那么OO,却非常受用。

posted on 2005-05-24 20:11  Jerry Zhou  阅读(2235)  评论(8)    收藏  举报