1、==========================================================================

c#中怎样禁用鼠标左键的使用,其实我们可以通过ImessageFilter接口下的PreFilterMessage方法、Application类的AddMessageFilter方法,RemoveMessageFilter方法和Message结构的Msg属性来禁用鼠标左键。Message结构包装Windows发送的消息,可使用该结构包装消息,并将其分配给窗口过程以进行调度,还可以使用该结构获取系统向应用程序或控件发送的关于某个消息的信息。

使用PreFilterMessage方法在调度消息之前将其筛选出来。语法格式如下:

Bool PreFilterMessage(refMessage m)

参数说明:

m:要调度的消息,无法修改此消息。

返回值:如果筛选消息并禁止消息被调度,则为True;如果允许消息继续到达下一个筛选器或控件,则为False。使用AddMessageFilter方法添加消息筛选器以便在向目标传送Windows消息时监视这些消息。使RemoveMessageFilter 从应用程序的消息泵移除一个消息筛选器。

下面给出大家一下主要代码:


Public partial class Form1:Form,ImessageFilter

{

    Public Form1()

    {

        InitializeComponent();

    }

 Public bool PreFilterMessage(ref System.Windows.Forms.Message MyMessage)

{

     //不响应鼠标左键消息

    If(MyMessage.Msg>=513 && MyMessage.Msg<=515)

       {

         Return true;

       }

   Return false;

}

Private voi button1_Click(object sender,EventArgs e)

{

   Application.AddMessageFilter(this);

   MessageBox.show(“鼠标左键已经被禁止,请用Tab键执行操作”,”信息提示”,

MessageBoxButtons.OK,MessageBoxIcn.Information);

}

Private void button2_Click(object sender,EventArgs e)

{

   Application.RemoveMessageFilter(this);

   MessageBox.Show(“鼠标左键已经被解禁,可以执行操作!”,”信息提示”,

MessageBoxButtons.OK,messageBoxIcon.Information)

}

}

鼠标移动:512

鼠标左键:

down:513

up:     514

double click:515

鼠标右键:

down:516

up:517

鼠标滚轮:522

=============================================================================

2、=========================================================================

还存在一些问题,再研究一下
1、ComponentDispatcher其实可以不用
2、new一个DispatcherFrame其实是把一个消息循环(姑且称作嵌套消息循环)当做一个DispatchFrame来处理,在这个消息循环结束之前,原来的代码就是阻塞的
3、正是因为第二个原因,如果再次弹出一个窗口,将是在前一个嵌套消息循环中,再次执行2,也就会导致第一个窗口关闭,并不会立即执行后面的代码。

【场景描述】

某些时候可能会有这种需求,一个用户界面里面分为好多个功能区域。这些功能区域有时候会有一些“模态”的弹出窗口的交互,这些弹出窗口需要:
1、只影响当前区域。即鼠标或者键盘无法操作当前区域,而其他区域不受影响。比如说,有好多个选项卡页面,每个选项卡页面弹出的窗口只影响当前选项卡,而不影响其他的选项卡。
2、窗口未关闭之前,后面的代码不执行,即“阻塞”。

【问题分析】

WPF中的窗口的弹出提供了两个方法:Show和ShowDialog。其中,Show方式是一个非“阻塞”的方法,即:调用完Show之后立即返回,后面的代码将立即被执行,但是这个方法不会挡住整个窗口。而ShowDialog方法是一个“阻塞”的方法,即调用完ShowDialog之后需要等窗口关闭代码才会继续执行。然而,ShowDialog会挡住整个窗口,而不是指定的区域。
综合这个两个方法考虑,其实,对于场景中的第一条,我们可以考虑通过调用Show让窗口弹出之后,即将该区域置为IsEnabled=false来模拟“模态”的窗口,这个倒不是很难。问题在于第二条,如何让窗口“阻塞”住当前代码的继续执行呢?即:
var win = new MyDialog();
win.Show();
// 关闭后才要执行的代码
1、用一个while死循环,直到关闭才跳出。如果采用这种方式,那我们不得不好好考虑一下,在UI线程做死循环UI还有没有办法响应。当然,方法是有的,可以实现一个WPF版的DoEvents方法,然后在循环中调用。DoEvents相关的代码可以参见:http://www.cnblogs.com/sheva/archive/2006/08/24/485790.html
2、用异步模式来写。代码将类似于:
var win = new MyDialog();
// MyCloseCallback是一个窗口关闭时调用的回调
win.Show(MyCloseCallback);
这样确实可以满足需求,不过我们不得不忍受把一份代码拆开为两份来写的痛苦。当然,匿名方法和Lamba可以带来一些缓解,但是写起来始终不是那么舒服。
难道,我们除了使用可怕的while死循环+DoEvents,或者忍受别扭的代码之外,就没有别的办法了么?

【揭开ShowDialog的面纱】

其实,回过头再去想,为什么ShowDialog方法就可以阻塞代码的执行呢?如果我们能够知道如何阻塞代码,然后把“挡住”整个窗口的部分给去掉,不就OK了么?
好,我们请出神器Reflector打开Window的ShowDialog方法一窥究竟。


public bool? ShowDialog()
{
    
    try
    {
        this._showingAsDialog = true;
        this.Show();
    }
    catch
    {
        
    }
    finally
    {
        this._showingAsDialog = false;
    }
    
}

核心的部分如上所示,其实ShowDialog只是置了一个状态,最主要的代码还是在Show里面。好,我们接着转战到Show


public void Show()
{
    this.VerifyContextAndObjectState();
    this.VerifyCanShow();
    this.VerifyNotClosing();
    this.VerifyConsistencyWithAllowsTransparency();
    this.UpdateVisibilityProperty(Visibility.Visible);
    this.ShowHelper(BooleanBoxes.TrueBox);
}  

前面都是在做一些检查,最终的调用原来跑到了ShowHelper


private object ShowHelper(object booleanBox)
{
    if (!this._disposed)
    {
       
        if (this._showingAsDialog && this._isVisible)
        {
            try
            {
                ComponentDispatcher.PushModal();
                this._dispatcherFrame = new DispatcherFrame();
                Dispatcher.PushFrame(this._dispatcherFrame);
            }
            finally
            {
                ComponentDispatcher.PopModal();
            }
        }
    }
    return null;
}    

关键一步看来是:
ComponentDispatcher.PushModal();
ComponentDispatcher是个什么东东?MSDN之:

Enables shared control of the message pump between Win32 and WPF in interoperation scenarios.
原来是用于操作消息循环的。
而这两句:
this._dispatcherFrame = new DispatcherFrame();
Dispatcher.PushFrame(this._dispatcherFrame);
如果有看过DoEvents的实现,就好理解了,简单的说,这里其实是让UI可以继续处理消息队列。

【实现】

有了以上准备,我们就很好处理了。
1、首先,我们通过模仿ShowHelper中的代码,来实现阻塞代码的执行
2、其次,我们通过设置IsEnabled属性来模拟“模态”的效果。


 public class MyDialog : Window
    {
        private DispatcherFrame _dispatcherFrame;
        private FrameworkElement _container = null;
        private double _lastLeft = 0.0;
        private double _lastTop = 0.0;         public void Open(FrameworkElement container)
        {
            if (container != null)
            {
                _container = container;
                // 通过禁用来模拟模态的对话框
                _container.IsEnabled = false;
                // 保持总在最上
                this.Owner = GetOwnerWindow(container);
                if (this.Owner != null)
                {
                    this.Owner.Closing += new System.ComponentModel.CancelEventHandler(Owner_Closing);
                }
                // 通过监听容器的Loaded和Unloaded来显示/隐藏窗口
                _container.Loaded += new RoutedEventHandler(Container_Loaded);
                _container.Unloaded += new RoutedEventHandler(Container_Unloaded);
            }
            this.Show();
            try
            {
                ComponentDispatcher.PushModal();
                _dispatcherFrame = new DispatcherFrame(true);
                Dispatcher.PushFrame(_dispatcherFrame);
            }
            finally
            {
                ComponentDispatcher.PopModal();
            }
        }         // 在Owner关闭的时候关闭
        private void Owner_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.Close();
        }         private void Container_Unloaded(object sender, RoutedEventArgs e)
        {
            // 只能通过这种方式隐藏,而不能通过Visiblity = Visibility.Collapsed,否则会失效
            _lastLeft = this.Left;
            _lastTop = this.Top;
            this.Left = -10000;
            this.Top = -10000;
        }         private void Container_Loaded(object sender, RoutedEventArgs e)
        {
            this.Left = _lastLeft;
            this.Top = _lastTop;
        }         protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
            if (_container != null)
            {
                _container.Loaded -= Container_Loaded;
                _container.Unloaded -= Container_Unloaded;
            }
            if (this.Owner != null)
            {
                this.Owner.Closing -= Owner_Closing;
            }
        }         protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            // 当关闭终止消息循环
            if (_dispatcherFrame != null)
            {
                _dispatcherFrame.Continue = false;
            }
            // 这里必须强制调用一下
            // 否则出现同时点开多个窗口时,只有一个窗口让代码继续
            ComponentDispatcher.PopModal();
            if (_container != null)
            {
                _container.IsEnabled = true;
            }
        }         private Window GetOwnerWindow(FrameworkElement source)
        {
            var parent = VisualTreeHelper.GetParent(source) as FrameworkElement;
            if (parent == null)
                return null;
            var win = parent as Window;
            return
                win != null ?
                parent as Window :
                GetOwnerWindow(parent);
        }
    }

使用的时候


            var btn = sender as Button;
            var dialog = new MyDialog
            {
                Width = 300,
                Height = 200,
                Content = btn.Tag,
                WindowStartupLocation = WindowStartupLocation.CenterOwner
            };
            var border = this.FindName((string)btn.Tag) as Border;
            dialog.Open(border);
            // 在窗口关闭之前不会执行
            MessageBox.Show(string.Format("{0}上弹出对话框结束!", btn.Tag));

代码下载

/Files/RMay/TryMessageBox.zip

WPF 键盘全局接收消息的更多相关文章

  1. wpf键盘记录器

    很简单的一个wpf键盘记录器 这个程序我一样用了全局勾子,之前用的都是winform上运行了,前一段时间 在国外的论坛上逛看到了一个wpf能用的就做了一个小程序记录一下,为了方便大家直关的看我在页面上 ...

  2. WPF向系统发送消息 并传递结构体

    场景 :需要开发一个通讯组件 流程为:界面-开启接收服务-通过发送组件发送信息到 其他客户端和服务端 接受服务接收其他客户端发送的消息 需要传递给对应组件或者界面 因此会出现类库重复引用问题.因为采用 ...

  3. XMPP客户端开发(2)--发送接收消息

    客户端连接上服务器并登录以后,可以发送.接收消息. 首先需要定义Chat,MessageListener和ChatMessageListener几个变量: private static Chat ch ...

  4. [转] C#中发送消息给指定的窗口,以及接收消息

    原文C#中发送消息给指定的窗口,以及接收消息 public class Note { //声明 API 函数 [DllImport("User32.dll", EntryPoint ...

  5. 终于懂了:Delphi消息的Result域出现的原因——要代替回调函数的返回值!(MakeObjectInstance不会帮助处理(接收)消息回调函数的返回值)

    MakeObjectInstance应该不会帮助处理(接收)消息回调函数的返回值,可是有时候又确实需要这个返回值,这可怎么办呢?我是看到这段文字的时候,想到这个问题的: 当WM_PAINT不是由Inv ...

  6. RocketMQ源码 — 三、 Consumer 接收消息过程

    Consumer pull message 订阅 在Consumer启动之前先将自己放到一个本地的集合中,再以后获取消费者的时候会用到,同时会将自己订阅的信息告诉broker 接收消息 consume ...

  7. 【Spring】使用Spring和AMQP发送接收消息(上)

    讲AMQP之前,先讲下传统的JMS的消息模型,JMS中主要有三个参与者:消息的生产者.消费者.传递消息的通道(队列或者主题),两种消息模型如下:通道是队列: 通道是队列: 通道是主题: 在JMS中,虽 ...

  8. 微信企业号接收消息(使用SpringMVC)

    微信企业号接收消息(使用SpringMVC) 微信企业号接收消息(使用SpringMVC) 将应用设置在回调模式时,企业可以通过回调URL接收员工回复的消息,以及员工关注.点击菜单.上报地理位置等事件 ...

  9. 【Spring】使用Spring和AMQP发送接收消息(中)

    上篇讲了RabbitMQ连接工厂的作用是用来创建RabbitMQ的连接,本篇就来讲讲RabbitMQ的发送消息.通过RabbitMQ发送消息最简单的方式就是将connectionFactory Bea ...

随机推荐

  1. deep_learning_cross_entropy

    交叉熵损失函数 交叉熵代价函数(Cross-entropy cost function)是用来衡量人工神经网络(ANN)的预测值与实际值的一种方式.与二次代价函数相比,它能更有效地促进ANN的训练.在 ...

  2. 静态static最基础的知识

    static静态: 常见修饰的内容: 1.变量: 修饰变量时,叫静态变量或类变量.此变量为类所有随着虚拟机加载类是而加载入方法区,此静态变量为该类所有对象共享,在内存中只有一个副本,它 当且仅当 类的 ...

  3. Linux 命令配置IP

    配置静态IP:ip addr add 192.168.18.18/24 dev eth0 启动网卡:ifup eth0/ifup ifcfg-eth0 添加默认网关路由:ip route add de ...

  4. PHP代码执行流程

    怎么样?有点了解了么.说实话,单看这个,我本人是有点懵的,不过,不要怕.咱们来慢慢地看下. 首先,在网上找的信息说PHP代码执行的顺序是这样的,第一步是词法分析,第二步是语法分析,第三步是转化为opc ...

  5. docker安装kafka快速入门

    docker安装kafka快速入门 1.安装zookeeper docker search zookeeperdocker pull zookeeperdocker run -d -v /home/s ...

  6. LIBUSB_TRANSFER_ERROR

    首先, 我的设备是一个KNX无线接受模块, 利用UART与主机相连, 看到的设备就是ttyUSBx 利用libusb写了一个程序, 调用同步I/O 的API, 即libusb_bulk_transfe ...

  7. linux 命令格式和帮助

    命令的格式: command [options] [arguments] command:命令 options:  --单词全称   或   -单字简称 如: ls --all 等于     ls - ...

  8. ABC065D Built[最小生成树]

    这题和某道最短路题神似.对于任意点对,将他们连边,不如将他们分别沿$x,y$轴方向上点按顺序连起来,这样不仅可能多连通一些点,也花费更低,所以按照最短路那题的连边方式跑一个kruskal就行了. #i ...

  9. 【原】maven web项目eclipse搭建

    1.new->other->Maven Project,点击next 2.继续next 3.选择maven-archetype-webapp,如果找不到可以再Filter里面搜索web,就 ...

  10. 题解 【NOIP2016】组合数问题

    [NOIP2016]组合数问题 Description Input 第一行有两个整数t, k,其中t代表该测试点总共有多少组测试数据,k的意义见[问题描述]. 接下来t行每行两个整数n, m,其中n, ...