Winforms крадет нажатия клавиш из COM-компонента?

У меня есть COM-компонент C++ ATL, который отображает всплывающее окно (обычное Win32, с использованием стиля WS_POPUP), которое позволяет пользователю вводить некоторую информацию для поиска. Этот компонент был довольно тщательно протестирован на форме VB6 (в первую очередь для простоты отладки), но мы хотим использовать его с .NET winforms.

Любопытная вещь, которую мы обнаружили при вызове компонента из среды winforms, заключается в том, что определенные нажатия клавиш больше не доходят до нашего всплывающего окна. Например: мы создали подкласс окна редактирования во всплывающем окне, чтобы прослушивать клавишу ESC и закрывать всплывающее окно. В VB6 это прекрасно работает, но в winforms всплывающее окно никогда не получает событие keydown для ESC (это происходит для других клавиш, таких как стандартные буквенно-цифровые символы).

Использование компонента довольно тривиально, но я приведу здесь краткий пример, чтобы избежать любых вопросов:

public partial class Form1 : Form
{
    CustomPopup panel;

    public Form1()
    {    
        panel = new CustomPopup(); //This is the COM object
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Point p = this.PointToScreen(button1.Location);
        // Display the popup, which gives focus to a child WC_EDIT field
        panel.ShowPopupAt(p.X, p.Y);
    }
}

Как видите, не так уж и много. Итак, какие идеи о том, что в winforms съедает наши нажатия клавиш и как мы можем остановить это?


person Toji    schedule 21.10.2010    source источник
comment
ОХ!!!!! Хорошо, это действительно меня бесит, но я нашел обходной путь: пока мои события WM_KEYDOWN уносятся в эфир, мои события WM_KEYUP проходят нормально. В моем конкретном случае я могу использовать это, но это далеко не общее решение этой проблемы. Я не собираюсь помечать тикет как закрытый, пока мы не получим какое-то объяснение, почему сообщения об нажатии клавиш подавляются и как это обойти. (Именно такие вещи постепенно заставили меня презирать .NET)   -  person Toji    schedule 21.10.2010


Ответы (1)


Попробуйте подавить обработку Windows Forms сообщения WND (в элементе управления/форме, похищающем сообщение):

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_LBUTTONUP || m.Msg == WM_LBUTTONDBLCLK
       )
    {
        return;
    }
    base.WndProc(ref m);
}
person Jeff    schedule 21.10.2010
comment
Я уже переопределил WndProc, ищущий сообщение, и он никогда не получает его, так что это не сработает. Если я зарегистрируюсь как IMessageFiler, я увижу его в PreFilterMessage, и, что интересно, дескриптор окна, который он отображает, кажется правильным, если я найду окно в Spy++, но он все еще не соответствует моему подклассу proc. - person Toji; 21.10.2010
comment
Если ваша форма крадет фокус и вы никогда не нажимаете метод WndProc, что-то не так. Вы уверены, что обрабатываете WndProc для конкретного элемента управления, который крадет фокус? - person Jeff; 21.10.2010
comment
Я не уверен на 100%, но, учитывая, что программа состоит из формы, кнопки и моего всплывающего окна, вариантов не так уж и много. :) - person Toji; 21.10.2010
comment
Небольшое обновление: теперь я просматриваю сообщения для каждого отдельного окна, которое я создаю (форма, кнопка, всплывающая панель и поле редактирования), и единственное место, где я когда-либо видел нажатие клавиши ESC, находится в PreMessageFilter, что, по-видимому, указывает на то, что .NET подавляет сообщение до того, как оно будет отправлено в какие-либо окна. :П - person Toji; 21.10.2010