Захват сообщения WndProc о нажатии определенной кнопки

У меня есть кнопка отмены на моей форме. Я хочу определить внутри метода WndProc, что эта кнопка Cancel нажата, и написать для нее некоторый код. Это абсолютно необходимо, потому что иначе я не смогу отменить все остальные события проверки элементов управления, которые еще предстоит выполнить.

Пожалуйста помоги.

.NET-2.0, WinForms


person Soham Dasgupta    schedule 17.05.2012    source источник
comment
С# или VB? Кроме того, знаете ли вы во время выполнения, где находится кнопка на форме?   -  person Chris Barlow    schedule 17.05.2012
comment
Ну, конечно, это не является абсолютно необходимым, и переопределение метода формы WndProc(), безусловно, ни к чему не приведет. Рассмотрите возможность установки для свойства CausesValidation кнопки значения False и использования события FormClosing формы, чтобы снова установить для e.Cancel значение false.   -  person Hans Passant    schedule 17.05.2012
comment
@ C.Barlow Подойдет любой. Да, это фиксированное положение в моей форме.   -  person Soham Dasgupta    schedule 17.05.2012
comment
@HansPassant Прежде всего, я не закрываю форму в случае нажатия кнопки, я только сбрасываю элементы управления формой. И если есть элементы управления, которые не прошли проверку, то CauseValidation не помогает. Это проверка всегда выполняется.   -  person Soham Dasgupta    schedule 17.05.2012


Ответы (2)


Вот как вы могли бы проанализировать сообщение WndProc для щелчка левой кнопкой мыши на дочернем элементе управления:

protected override void WndProc(ref Message m)
{
    // http://msdn.microsoft.com/en-us/library/windows/desktop/hh454920(v=vs.85).aspx
    // 0x210 is WM_PARENTNOTIFY
    // 513 is WM_LBUTTONCLICK
    if (m.Msg == 0x210 && m.WParam.ToInt32() == 513) 
    {
        var x = (int)(m.LParam.ToInt32() & 0xFFFF);
        var y = (int)(m.LParam.ToInt32() >> 16);

        var childControl = this.GetChildAtPoint(new Point(x, y));
        if (childControl == cancelButton)
        {
            // ...
        }
    }
    base.WndProc(ref m);
}

Кстати: это 32-битный код.

person Emond Erno    schedule 05.06.2012
comment
Будут ли серьезные изменения для 64-битной версии? - person Soham Dasgupta; 05.06.2012
comment
IntPtr будет 64-битным при компиляции для 64-битной версии .NET. Насколько я знаю, это должно работать, но я не проверял. Кстати: я исправил ошибку в коде (заменил 0xFF на 0xFFFF) - person Emond Erno; 05.06.2012
comment
Это абсолютно работает в обычном компоненте Windows, но при использовании DevExpress есть элемент управления LayoutControl, дочерним элементом которого является эта кнопка. Поэтому при нажатии на дочерний элемент управления всегда возвращается LayoutControl вместо кнопки. Любые идеи о том, как обойти это? - person Soham Dasgupta; 05.06.2012
comment
Единственное решение, которое я вижу, - это попытаться найти hwnd интересующего вас элемента управления и просмотреть сообщения. Взгляните на это: msdn.microsoft.com/en-us/magazine/ cc163617.aspx - person Emond Erno; 05.06.2012
comment
Что-нибудь попробую и сообщу. - person Soham Dasgupta; 06.06.2012

И если есть элементы управления, которые не прошли проверку, то CauseValidation не помогает.

Ну, конечно, это то, для чего это свойство было разработано. Вот пример формы, чтобы показать это на работе. Поместите текстовое поле и кнопку на форму. Обратите внимание, как вы можете щелкнуть кнопку, чтобы очистить текстовое поле, даже если поле всегда не проходит проверку. И как можно закрыть форму.

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        textBox1.Validating += new CancelEventHandler(textBox1_Validating);
        button1.Click += new EventHandler(button1_Click);
        button1.CausesValidation = false;
        this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
    }

    private void textBox1_Validating(object sender, CancelEventArgs e) {
        // Always fail validation
        e.Cancel = true;
    }
    void button1_Click(object sender, EventArgs e) {
        // Your Cancel button
        textBox1.Text = string.Empty;
    }
    void Form1_FormClosing(object sender, FormClosingEventArgs e) {
        // Allow the form to close even though validation failed
        e.Cancel = false;
    }
}
person Hans Passant    schedule 17.05.2012
comment
Ну, я использую компоненты DevExpress и могу точно сказать, что он не работает в этом. Если бы вы могли показать мне, как использовать WndProc, чтобы сделать то же самое, это было бы очень полезно. - person Soham Dasgupta; 18.05.2012
comment
Я не могу вам с этим помочь, обратитесь за поддержкой в ​​DevExpress. - person Hans Passant; 18.05.2012
comment
Простой WndProc пример поможет узнать, какое сообщение возникло после нажатия этой кнопки. - person Soham Dasgupta; 18.05.2012