代码之家  ›  专栏  ›  技术社区  ›  Joel Rein

吞下钥匙,怎么让它停下来?

  •  3
  • Joel Rein  · 技术社区  · 15 年前

    AxAcroPDF在获得焦点后会立即吞下所有与键相关的事件,包括快捷方式、按键等。我添加了一个消息过滤器,它也不会获得任何与键相关的消息。这是一个COM组件,有关系吗?

    有没有办法在控制装置开始吞咽它们之前抓住它们?

    4 回复  |  直到 15 年前
        1
  •  4
  •   Community CDub    5 年前

    Hans是正确的,Acrobat Reader在托管代码中生成两个子AcroRd32进程,您无法直接访问这些进程。

    我已经尝试过了,你有三个可行的选择:

    1. 全球系统挂钩 ,然后在32个窗口中查找并过滤/响应发送给您孩子的WM\U SETFOCUS消息。通过使用包装器库,您可以在C#中完成其中的一些工作,例如: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx

      您还需要确定正确的进程,因为您的应用程序可能有多个实例,或者AcroRd32的其他实例。这是最确定的解决方案,但由于您的应用程序现在将过滤发送到存在的每个窗口的消息,因此我通常不推荐这种方法,因为这样您的程序可能会对系统稳定性产生负面影响。

    2. 替代PDF查看控件 .net PDF Viewer control http://www.codeproject.com/KB/applications/PDFViewerControl.aspx

    3. 找到一个 可接受的黑客攻击

      DateTime _lastRenav = DateTime.MinValue;
      
      public Form1()
      {
          InitializeComponent();
      
          listBox1.LostFocus += new EventHandler(listBox1_LostFocus);
      }
      
      private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
      {
          axAcroPDF1.src = "sample.pdf";  //this will cause adobe to take away the focus
          _lastRenav = DateTime.Now;
      }
      
      void listBox1_LostFocus(object sender, EventArgs e)
      {
          //restores focus if it were the result of a listbox navigation
          if ((DateTime.Now - _lastRenav).TotalSeconds < 1)
              listBox1.Focus();
      }
      
        2
  •  4
  •   L_J    5 年前

    我终于有了一个可笑的简单答案。到目前为止,在测试这是工作。

    在这个问题困扰了相当长的一段时间之后,我建立了一个复杂的系统,每个自定义控件记录下它们中的哪一个最后有焦点,并使用计时器将焦点翻转回来(当acropdf抓到它时),我重新研究了这个问题,并阅读了大量的答案(寻找最新的解决方案)。收集到的信息帮助我想出了这个主意。

    其思想是在加载时禁用(acropdf)控件,如以下示例所示(为清晰起见,代码减少)

    AxAcroPDF_this.Enabled = False
    
    AxAcroPDF_this.src = m_src
    

    然后在计时器上,说1秒钟后。

    AxAcroPDF_this.Enabled = True
    

    基本上,这个想法是告诉Windows在允许之前不要让用户使用acropdf控件,因此要求Windows阻止它获得焦点(因为不允许用户进入)。

        3
  •  2
  •   Hans Passant    15 年前

    这是一个进程外COM组件,这就是问题所在。完全违反了SetParent()中规定的Windows SDK要求。一旦它的窗口获得焦点,acroread.exe进程中的消息循环将获得所有消息,消息过滤器将无法再看到任何消息。

    从技术上讲,可以通过使用SetWindowsHookEx()将DLL注入进程并使用WH\u GETMESSAGE监视消息来修复此问题。但是你不能用C语言写这样的DLL。

    少校,我知道。这个项目似乎从来都不缺少它。

        4
  •  2
  •   MikeTV    11 年前

    由于某种原因,Tim的答案,直接禁用AxAcroPDF控件,在我的例子中不起作用。先前选择的文本框上的Leave事件也不会触发。

    工作原理是将AxAcroPDF控件嵌套在禁用的GroupBox中。由于我的应用程序的用户只需要查看PDF,而不需要与之交互,因此在设计器中GroupBox的Enabled属性设置为False。

    推荐文章