AxAcroPDF吞键,如何让它停止?

发布于 2024-09-06 05:48:00 字数 126 浏览 5 评论 0原文

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

有什么办法可以在控制者开始吞下它们之前抓住它们吗?

The AxAcroPDF swallows all key-related events as soon as it gets focus, including shortcuts, key presses, etc. I added a message filter, and it doesn't get any key-related messages either. It's a COM component, could that be relevant?

Is there any way to catch these before the control starts swallowing them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

太阳哥哥 2024-09-13 05:48:00

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

我对此进行了试验,您有三个可行的选择:

  1. 您可以创建一个全局系统挂钩,然后查找并过滤/响应发送到您的子 AcroRd32 窗口的 WM_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;
    
    公共表格1()
    {
        初始化组件();
    
        listBox1.LostFocus += new EventHandler(listBox1_LostFocus);
    }
    
    私人无效listBox1_SelectedIndexChanged(对象发送者,EventArgs e)
    {
        axAcroPDF1.src = "样本.pdf"; //这将导致 adobe 夺走焦点
        _lastRenav = 日期时间.Now;
    }
    
    void listBox1_LostFocus(对象发送者,EventArgs e)
    {
        //如果是列表框导航的结果,则恢复焦点
        if ((DateTime.Now - _lastRenav).TotalSeconds < 1)
            listBox1.Focus();
    }
    

Hans is correct, the Acrobat Reader spawns two child AcroRd32 processes which you have no direct access to from within your managed code.

I have experimented with this and you have three viable options:

  1. You can create a global system hook, and then look for and filter out / respond to WM_SETFOCUS messages sent to your child AcroRd32 windows. You can accomplish some of this from within C# by using a wrapper library, such as the one here: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx

    You also need to identify the correct processes as there may be more than one instance of your application, or other instances of AcroRd32. This is the most deterministic solution, but because your application will now be filtering messages sent to every single window in existence, I generally don't recommend this approach because then your program could negatively affect system stability.

  2. Find an alternate PDF viewing control. See this answer for a few commercial components: .net PDF Viewer control , or roll your own: http://www.codeproject.com/KB/applications/PDFViewerControl.aspx

  3. Find an acceptable hack. Depending on how robust your application needs to be, code such as the following may be suitable (it was suitable for my case):

    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();
    }
    
牵你的手,一向走下去 2024-09-13 05:48:00

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

遭受这个问题困扰相当长一段时间,并为每个自定义控件构建了一个复杂的系统,记录其中哪个控件最后获得焦点,并使用计时器将焦点翻转回来(当 acropdf 抓住它时),我重新审视了这个问题并阅读了大量答案(寻找最近的解决方案)。收集到的信息帮助我有了这个想法。

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

AxAcroPDF_this.Enabled = False

AxAcroPDF_this.src = m_src

然后在计时器上,例如 1 秒后。

AxAcroPDF_this.Enabled = True

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

到目前为止,这仍然有效,如果有任何变化,我会编辑它。如果它不完全适合您,那么也许这个想法指出了一个有用的方向。

I might finally have a ridiculously simple answer. So far in testing this is working.

Having suffered from this problem for quite some time and having built a complex system of each custom control recording which of them last had focus and using a timer to flip focus back (when acropdf grabbed it) I revisited this problem and read a great number of answers (looking for recent solutions). The information gleaned helped me with the idea.

The idea is to disable the (acropdf) control whilst it is loading as in the following example (code reduced for clarity)

AxAcroPDF_this.Enabled = False

AxAcroPDF_this.src = m_src

Then on a timer, after say 1 second.

AxAcroPDF_this.Enabled = True

Basically the idea is to tell Windows not to let users use the acropdf control until allowed, so asking Windows to prevent it from getting focus (because users are not allowed in there).

So far this is holding up, I will edit this if anything changes. If it doesn't work completely for you then maybe the idea points into a useful direction.

闻呓 2024-09-13 05:48:00

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

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

我知道,主要很糟糕。该计划似乎从来不缺乏它。

It is an out-of-process COM component, that's the problem. Completely in violation of Windows SDK requirements as laid out in SetParent(). Once its window gets the focus, the message loop in the acroread.exe process gets all the messages, your message filter cannot see any messages anymore.

Technically it is fixable by using SetWindowsHookEx() to inject a DLL into the process and monitor messages with WH_GETMESSAGE. But you can't write such a DLL in the C# language.

Major suck, I know. There never seems to be any lack of it with that program.

_蜘蛛 2024-09-13 05:48:00

由于某种原因,蒂姆的回答(直接禁用 AxAcroPDF 控件)在我的情况下不起作用。先前选择的文本框上的离开事件也永远不会触发。

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

For some reason Tim's answer, disabling the AxAcroPDF control directly, didn't work in my case. The Leave event on the previously-selected Textbox would never fire, either.

What is working is nesting the AxAcroPDF control inside of a disabled GroupBox. Since the users of my application need to only see the PDF, not interact with it, the GroupBox's Enabled property is set to False in the designer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文