AxAcroPDF吞咽钥匙,如何让它停下来?

AxAcroPDF一旦获得焦点就会吞下所有与密钥相关的事件,包括快捷方式,按键等。我添加了一个消息filter,它也没有得到任何与密钥相关的消息。 这是一个COM组件,可能是相关的吗?

在控制开始吞咽之前有没有办法捕捉到这些?

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

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

  1. 您可以创建一个全局系统挂钩 ,然后查找并过滤/响应发送到您的子AcroRd32窗口的WM_SETFOCUS消息。 您可以使用包装器库在C#中完成其中的一些操作,例如: http : //www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx

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

  2. 查找备用PDF查看控件 。 有关一些商业组件,请参阅此答案: .net PDF Viewer控件 ,或自行滚动: 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(); } 

我可能最终会得到一个非常简单的答案。 到目前为止,在测试中这是有效的。

经历了相当一段时间的这个问题,并且已经构建了一个复杂的系统,每个自定义控制记录中的哪一个最后有焦点并使用计时器来反转焦点(当acropdf抓住它时)我重新审视了这个问题并阅读了大量的答案(寻找最近的解决方案)。 收集的信息帮助了我的想法。

这个想法是在加载时禁用(acropdf)控件,如下例所示(代码为了清晰起见而减少)

AxAcroPDF_this.Enabled =假AxAcroPDF_this.src = m_src

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

AxAcroPDF_this.Enabled = False

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

到目前为止,这是持续的,如果有任何变化,我将编辑它。 如果它不能完全适合你,那么这个想法可能会指向一个有用的方向。

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

从技术上讲,通过使用SetWindowsHookEx()将DLL注入进程并使用WH_GETMESSAGE监视消息是可以修复的。 但是你不能用C#语言编写这样的DLL。

很重要,我知道。 该计划似乎从来没有缺乏它。

出于某种原因,蒂姆的答案,直接禁用AxAcroPDF控件,在我的情况下不起作用。 以前选择的文本框上的Leave事件也不会触发。

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