Захват сообщений WndProc в Windows Vista и выше с использованием .NET - PullRequest
0 голосов
/ 21 марта 2011

У меня есть приложение для окон .net 2.0.

Я переопределил метод WndProc для захвата действий пользователя в форме

Ex:

const int HTCLOSE           = 0x0014;
bool m_bCloseButtonActive   = false;

if (m.Msg == WM_NCHITTEST)
{
    base.WndProc(ref m);
    m_bCloseButtonActive = (m.Result.ToInt32() == HTCLOSE);
}

На основании значения m_bCloseButtonActive я предпринимаю дальнейшие действия.

Проблема, с которой я сталкиваюсь сейчас, заключается в том, что моя форма не закрывается, поскольку она не может зафиксировать событие нажатия кнопки «Закрыть» в операционных системах Vista и выше (даже в Windows 7).

то есть условие m.Result.ToInt32 () == HTCLOSE никогда не выполняется, и моя форма никогда не закрывается, когда я нажимаю кнопку закрытия.

Мое приложение работает в предыдущих ОС (Windows 2000, XP, XP Embedded). Также интересно то, что это работает, когда я указываю

Application.VisualStyleState = System.Windows.Forms.VisualStyles.VisualStyleState.ClientAreaEnabled;

Есть идеи, что здесь происходит. Связано ли это с Windows Desktop Manager, мое приложение не может перехватить событие нажатия кнопки закрытия.

Заранее спасибо

Ответы [ 2 ]

6 голосов
/ 21 марта 2011

Тестовые сообщения о попадании не кажутся мне подходящим способом сделать это. Например, что если пользователь закрывает форму через системное меню или комбинацию клавиш Alt + F4?

Я думаю, что вы должны отвечать на WM_SYSCOMMAND сообщения с wParam == SC_CLOSE.

Windows Aero принципиально отличается в том, что касается обработки не клиентской области, что объясняет, почему она работает в 2000 / XP и когда вы отключаете DWM. Но использование WM_SYSCOMMAND работает во всех версиях Windows.

Обратите внимание, что вам необходимо внимательно прочитать документацию MSDN для WM_SYSCOMMAND, поскольку параметры сообщения содержат дополнительную информацию, которую необходимо скрыть. Чтобы обнаружить кнопку закрытия, вам нужен код, подобный следующему:

const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_SYSCOMMAND)
        if ((m.WParam.ToInt32() & 0xFFF0) == SC_CLOSE)
            MessageBox.Show("close button pressed");
    }
    base.WndProc(ref m);
}

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

0 голосов
/ 21 марта 2011

Наконец-то это сработало ... Я использовал WM_NCMOUSEMOVE вместо информации HITTEST, не относящейся к клиенту. WParam содержал все связанные события.

Эта ссылка помогла: http://social.msdn.microsoft.com/Forums/en/windowsuidevelopment/thread/9a8a63c8-79b5-43a8-82eb-f659be947add

const int WM_NCMOUSEMOVE =0x00A0;

  if (m.Msg == WM_NCMOUSEMOVE)
    {
    base.WndProc(ref m);
    if ((m.WParam.ToInt32() == HTCLOSE))
    {
      m_bCloseButtonActive = true;
    }
   }
...