[原创] 如何通过自定义MessageFilter的方式利用按键方式操作控件滚动条[附源代码]

本文介绍了如何通过自定义MessageFilter实现按键操作控件滚动条,详细讲解了实现原理、应用场景及代码实现,包括注册和注销MessageFilter的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很长一段时间内,一直在做一个SCSF(Smart Client Software Factory)的项目,已经进入UAT阶段。最近,用户提出了一个要求:需要通过按键方式来控制竖直滚动条。具体来讲就是说,如果一个容器内容过多,用户可以通过按键PageUp和PageDown来控制上下的滚动。刚开始,我试图采用注册事件的方式来实现,但是效果不理想,一来是没有一个单一的地方来对所有相关空间进行事件注册操作,二来如果容器被子控件完全遮挡,容器空间的事件将不会正常出发。有个同事提示采用自定义MessageFilter的方式,我觉得可行,于是进行了一番尝试。

一、实现原理简介

对于一个Windows Form应用来说,所有事件的触发都是采用消息(Message)的方式来实现的。比如,你点击了一个按钮,Windows会为这个操作之生成一个消息,并将这个消息分发(Dispatch)给按钮对象。如果能够在消息被分发给目标对象之前,能够对该消息进行了拦截,那么我们就可以按照我们希望的方式从新生成一个消息,并将其发送给我希望的目标对象,那么就能过随心所欲地控制目标对象的行为了。而自定义MessageFilter为我们提供了一个最好的消息拦截方式。

就拿我们上面给出控制滚动条的场景来说,当前容器由于内容过多而产生竖直滚动条(假设子控件的宽度和容器相同),用户键入PageDown按键试图向下滚动。Windows为本次键盘操作生成一个消息,并分发给目标对象(可能并不是我们需要控制的当前容器对象)。在此期间,我们通过MessageFilter对该消息实施拦截,从新产生一个基于“向下滚动”操作的消息,并分发给我们需要对其进行控制的容器,那么就实现了对于容器空间滚动条进行控制的目的。

二、实例应用场景简介

熟悉SCSF的朋友应该很清楚,SCSF的通过一个称为Shell的Form作为主界面,利用一个称为Workspace的容器最为整个应用的工作平台。应用动态运行过程中,各个Module的界面采用相同的方式添加到该Workspace之中。下图的就是我们将要演示的例子运行时的截图,为了简单起见,我直接通过一个System.Windows.Forms.TabControl作为Workspace。主菜单的两个菜单项分别代表两个模块,点击相应的菜单项后,会把相应的界面添加到Workspace中。在这里,我通过System.Windows.Forms.UserControl的方式定义Customer和Order模块的界面,当Customer和Order菜单被点击之后,会动态地在TabControl中添加相应的TabPage,并把相应的UserControl置于其中。由于整个TabControl的高度时固定的,而TabPage中显示的内容则依赖于具体的逻辑,所以对于内容过多的TabPage,将会有一个竖直滚动条。而我们需要通过按键的方式控制的就是当前TabPage的这个滚动条。

image

下面是该Form相关的代码,静态属性ActiveTabPage代表当前显示的TabPage。UserInfo和OrderInfo是两个UserControl,代表与具体模块相关的界面呈现。

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Windows.Forms;
   4:  
   5: namespace MessageFilterDemos
   6: {
   
   7:     public partial class MainForm : Form
   8:     {
   
   9:         public static TabPage ActiveTabPage
  10:         { get;private set; }
  11:  
  12:         private IDictionary<string, UserControl> keyedViews
  13:         { get; set; }
  14:  
  15:         public MainForm()
  16:         {
   
  17:             InitializeComponent();
  18:             this.keyedViews = new Dictionary<string, UserControl>();
  19:         }
  20:  
  21:         protected override void OnLoad(EventArgs e)
  22:         {
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值