c # - Ændring af vinduesbunden i en WM\_MOVING-handler uden at udløse Aero Shake

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har problemet, at hvis jeg ændrer LParam til en WM\_MOVING-besked for at holde min formular i en bestemt stilling, som er lovlig i henhold til dette, bliver Windows Aero Shake-funktionen udløst, og alle andre Windows minimerer. Opførelsen kan gengives ved at oprette et Windows Forms Project i Visual Studio og indsætte følgende kode i formularen: [6]


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);
        }
    }
}


Hvis du nu tager fat i vinduets titellinje og bevæger musen rundt lidt, skal Shake gestus udløses, selvom vinduet slet ikke bevæger sig.


Jeg har kun testet dette på Windows 10 indtil nu.


Så mit spørgsmål er, kan jeg deaktivere Shake-funktionen til et bestemt vindue eller proces? Hvis ikke, kan jeg forhindre, at Windows tænker på at jeg ryster vinduet på nogen anden måde?


Tak!

Bedste reference


Helt ærligt ved jeg ikke, om det er muligt at deaktivere Aero Shake for et bestemt vindue. Men jeg kan foreslå en løsning, der forhindrer aero shake i at udløse.


Der er mulighed for at styre hele musens indgang til kun et vindue (og dette vil også skjule museventyrene fra Aero Shake-håndteringen). Kontroller beskrivelsen SetCapture på MSDN. Vi skal også bruge en GetCapture]] og ReleaseCapture funktioner. [7]


Der er en bemærkning: Når du har indstillet musen til et vindue, er du ansvarlig for at håndtere alle musens input. For at nå målet skal du implementere din egen håndterer, der flytter vinduet. Heldigvis er det ikke så svært.


Her er en kodeeksempel med en dialog, der ændrer størrelsen, når den bevæger sig og genopretter størrelsen, når bevægelsen er færdig. Aero Shake udløses heller aldrig.


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);
    }
}