AxAcroPDF一旦获得焦点就会吞下所有与键相关的事件,包括快捷键,按键等。我添加了一个消息过滤器,它也没有得到任何与键相关的消息。它是一个COM组件,可能是相关的吗?
在控制开始吞咽之前有没有办法捕捉这些?
答案 0 :(得分:4)
汉斯是正确的,Acrobat Reader会产生两个您无法直接访问托管代码的子AcroRd32进程。
我已经尝试过这个,你有三个可行的选择:
您可以创建全局系统挂钩,然后查找并过滤/响应发送到您的子AcroRd32窗口的WM_SETFOCUS消息。您可以使用包装器库在C#中完成其中的一些操作,例如:http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx
您还需要识别正确的进程,因为可能有多个应用程序实例或AcroRd32的其他实例。这是最确定的解决方案,但由于您的应用程序现在将过滤发送到现有的每个窗口的消息,我通常不建议使用此方法,因为这样您的程序可能会对系统稳定性产生负面影响。
查找备用PDF查看控件。请参阅此答案,了解一些商业广告组件:.net PDF Viewer control,或推广您自己的广告:http://www.codeproject.com/KB/applications/PDFViewerControl.aspx
找到可接受的黑客。根据您的应用程序需要的强大程度,以下代码可能是合适的(它适用于我的情况):
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();
}
答案 1 :(得分:4)
我可能最终会得到一个非常简单的答案。到目前为止,测试工作正在发挥作用。
经历了这个问题很长一段时间并且已经建立了一个复杂的系统,每个自定义控制记录中的哪一个最后有焦点并使用计时器将焦点翻转回来(当acropdf抓住它时)我重新审视了这个问题并阅读了大量的答案(寻找最近的解决方案)。收集的信息帮助了我的想法。
这个想法是在加载时禁用(acropdf)控件,如下例所示(代码为了清晰而减少)
AxAcroPDF_this.Enabled = False AxAcroPDF_this.src = m_src
然后在计时器上,说1秒后。
AxAcroPDF_this.Enabled = False
基本上,我们的想法是告诉Windows不允许用户在允许之前使用acropdf控件,因此要求Windows阻止它获得焦点(因为不允许用户使用)。
到目前为止,这是持续的,如果有任何变化,我会编辑它。如果它不能完全适合你,那么这个想法可能会指向一个有用的方向。
答案 2 :(得分:2)
这是一个进程外的COM组件,这就是问题所在。完全违反了SetParent()中规定的Windows SDK要求。一旦窗口获得焦点,acroread.exe进程中的消息循环将获取所有消息,您的消息过滤器将无法再看到任何消息。
从技术上讲,通过使用SetWindowsHookEx()将DLL注入进程并使用WH_GETMESSAGE监视消息是可以修复的。但是你不能用C#语言编写这样的DLL。
主要很糟糕,我知道。该程序似乎从来没有缺乏它。
答案 3 :(得分:1)
出于某种原因,Tim的答案,直接禁用AxAcroPDF控件,在我的情况下不起作用。以前选择的文本框上的Leave事件也不会触发。
正在工作的是将AxAcroPDF控件嵌套在禁用的GroupBox中。由于我的应用程序的用户只需要查看PDF而不是与之交互,因此GroupBox的Enabled属性在设计器中设置为False。