Изменение границ окна в обработчике WM_MOVING без запуска Aero Shake - PullRequest
0 голосов
/ 26 апреля 2018

У меня проблема в том, что если я изменю LParam сообщения WM_MOVING, чтобы моя форма оставалась на определенной позиции, что является законным в соответствии с this , функция Windows Aero Shake будет запущена, и все другие окна сворачиваются. Поведение можно воспроизвести, создав проект Windows Forms в Visual Studio и вставив следующий код в форму:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace FormsTest
{
    public partial class ShakeTest : Form
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        public const int WM_MOVING = 0x0216;

        public ShakeTest()
        {
            InitializeComponent();
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {

                case WM_MOVING:
                    {
                        RECT rec;
                        rec.bottom = 500;
                        rec.left = 100;
                        rec.top = 100;
                        rec.right = 500;

                        Marshal.StructureToPtr(rec, m.LParam, true);

                        m.Result = new IntPtr(1);
                    }

                    break;
            }

            base.WndProc(ref m);
        }
    }
}

Если вы теперь возьмете строку заголовка окна и немного переместите мышь, то жест встряхивания должен сработать, даже если окно вообще не движется.

Я проверял это только в Windows 10.

Итак, мой вопрос, могу ли я отключить функцию встряхивания для определенного окна или процесса? Если нет, могу ли я помешать Windows думать, что я потрясаю Окно любым другим способом?

Спасибо!

1 Ответ

0 голосов
/ 27 апреля 2018

Честно говоря, я не знаю, возможно ли отключить Aero Shake для определенного окна. Но я могу предложить обходной путь, который предотвратит срабатывание Aero Shake.

Существует возможность направить весь ввод мыши только в одно окно (и это также скрывает события мыши от обработчика Aero Shake). Проверьте описание SetCapture на MSDN . Также нам понадобятся функции GetCapture и ReleaseCapture.

Есть одно замечание: после того, как вы установили захват мыши в окне - вы отвечаете за обработку всего ввода мыши. Таким образом, для достижения цели вам нужно реализовать собственный обработчик, который будет перемещать окно. К счастью, это не так сложно.

Вот пример кода с диалоговым окном, которое меняет свой размер при перемещении и восстанавливает размер по окончании перемещения. Aero Shake также никогда не срабатывает.

public partial class ShakeTest : Form
{
    [DllImport("user32.dll")]
    static extern IntPtr SetCapture(IntPtr hWnd);
    [DllImport("user32.dll")]
    static extern IntPtr GetCapture();
    [DllImport("user32.dll")]
    static extern bool ReleaseCapture();

    public const int WM_LBUTTONUP = 0x0202;
    public const int WM_MOUSEMOVE = 0x0200;
    public const int WM_NCLBUTTONDOWN = 0x00A1;
    public const int HTCAPTION = 2;

    private Point _lastCursorPos;
    private Size _origianlSize;

    public ShakeTest()
    {
        InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {

            // We need to get the moment when the user clicked on a non-client area
            case WM_NCLBUTTONDOWN:
                // We are interested only in a click on a title bar
                if ((int) m.WParam == HTCAPTION)
                {
                    // Set the capture so all the mouse input will be handled by this window
                    SetCapture(Handle);

                    // Keep the current cursor position to use it during the moving.
                    _lastCursorPos = Cursor.Position;

                    // Keep the original window size.
                    _origianlSize = Size;

                    // And change the dialog size to whatever you want
                    Size = new Size(300, 300);
                }
                break;

            // Once we got the capture, we need to handle mouse moving by ourself
            case WM_MOUSEMOVE:

                // Check that our window has the capture
                if (GetCapture() == Handle)
                {
                    // Change the position of a window
                    Left += Cursor.Position.X - _lastCursorPos.X;
                    Top += Cursor.Position.Y - _lastCursorPos.Y;

                    _lastCursorPos = Cursor.Position;
                }
                break;

            // When the left mouse button is released - it's time to release the mouse capture
            case WM_LBUTTONUP:

                // Check that our window has the capture
                if (GetCapture() == Handle)
                {
                    // Release the mouse capture
                    ReleaseCapture();

                    // Restore the size
                    Size = _origianlSize;
                }
                break;
        }

        base.WndProc(ref m);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...