2010-06-19 4 views
3

AxAcroPDF проглатывает все связанные с ключом события, как только он получает фокус, включая ярлыки, нажатия клавиш и т. Д. Я добавил фильтр сообщений, и он также не получает никаких сообщений, связанных с ключами. Это компонент COM, может ли это быть релевантным?AxAcroPDF проглатывание ключей, как заставить его остановиться?

Есть ли способ поймать их перед тем, как управление начнет их глотать?

ответ

4

Ганс прав, Acrobat Reader порождает два дочерних процесса AcroRd32, с которыми у вас нет прямого доступа из вашего управляемого кода.

Я экспериментировал с этим и у вас есть три жизнеспособных вариантов:

  1. Вы можете создать глобальной системы крюк, а затем искать и отфильтровывать/реагировать на WM_SETFOCUS сообщения, отправляемые вашему ребенку AcroRd32 окна. Вы можете выполнить часть этого из 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(); 
    } 
    
+0

+1 для краткого ответа, хотя конкретный приемлемый взлом не сработал для меня (исключить событие + TextBox вместо события LostFocus в ListBox) - я попробовал другое предлагаемое решение, которое очень сильно фигурирует в ответах на вопросы axAcroPDF + focus в Интернете - с помощью таймера и активации его сразу после вызова AxAcroPDF.LoadFile, установки фокуса обратно в форму внутри обработчика события Tick и дезактивации таймера сразу после этого. –

2

Это компонент COM вне процесса обработки, вот в чем проблема. Совершенно в нарушение требований Windows SDK, изложенных в SetParent(). Как только его окно получает фокус, цикл сообщения в процессе acroread.exe получает все сообщения, ваш фильтр сообщений больше не видит сообщений.

Технически это можно сделать с помощью SetWindowsHookEx(), чтобы внедрить DLL в процесс и контролировать сообщения с помощью WH_GETMESSAGE. Но вы не можете написать такую ​​DLL на языке C#.

Главный сосать, я знаю. Кажется, что с этой программой никогда не было недостатка.

+0

Adobe нарушает требования к SDK? Скажите, что это не так! Исправление звучит как нечто большее, чем я могу оправдать мои потребности на данный момент, но хорошо знать в случае изменений в будущем. –

4

Я мог бы, наконец, до смешного простой ответ. До сих пор в тестировании это работает.

Пострадавший от этой проблемы в течение довольно долгого времени и создавший сложную систему каждой пользовательской записи управления, из которой последний раз фокусировался и используя таймер, чтобы откидывать назад (когда acropdf схватил его). Я повторно рассмотрел эту проблему и прочитал большое количество ответов (поиск последних решений). Полученная информация помогла мне с этой идеей.

Идея заключается в том, чтобы отключить (AcroPDF) управление в то время как он погрузка, в следующем примере (код уменьшенное для ясности)

AxAcroPDF_this.Enabled = False AxAcroPDF_this.src = m_src

Затем по таймеру, скажем, 1 секунду.

AxAcroPDF_this.Enabled = False

В принципе идея заключается в том, чтобы сказать Windows, чтобы не позволить пользователям использовать контроль AcroPDF пока не разрешено, так просить Windows, чтобы предотвратить его попадание фокуса (поскольку пользователи не могут там) ,

Пока это держится, я отредактирую это, если что-нибудь изменится. Если это не работает полностью для вас, то, возможно, идея указывает на полезное направление.

+0

Я создал метод расширения для этого (только для Windows Forms): https: //gist.github.com/bertvansteen/ec180b645fd6bcfd179e – bvs

1

По какой-то причине ответ Тима, отключив управление AxAcroPDF напрямую, не работал в моем случае. Событие «Оставить» в ранее выбранном текстовом поле никогда не будет срабатывать.

Что работает с вложением элемента управления AxAcroPDF внутри отключенного GroupBox. Поскольку пользователям моего приложения нужно видеть только PDF, а не взаимодействовать с ним, свойство Enabled GroupBox устанавливается в конструкторе False.