【问题标题】:Altering the Window Bounds in a WM_MOVING handler without triggering Aero Shake在 WM_MOVING 处理程序中更改窗口边界而不触发 Aero Shake
【发布时间】:2018-10-07 01:33:32
【问题描述】:

我遇到的问题是,如果我更改 WM_MOVING 消息的 LParam 以将我的表单保持在某个位置,根据 this 是合法的,Windows Aero Shake 功能将被触发并且所有其他 Windows 最小化。可以通过在 Visual Studio 中创建 Windows 窗体项目并将以下代码粘贴到窗体中来重现该行为:

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 认为我以其他方式摇动 Window 吗?

谢谢!

【问题讨论】:

  • 不,这不是要阻止用户最大化表单,这个例子只是非常简单,我真正做的是将窗口捕捉到某些“Dock Areas”
  • 我回复的评论突然消失了
  • @SergeyShevchenko 这对我的情况不起作用,因为它只在移动开始时触发一次,我需要在移动时改变窗口的边界
  • 好的,我刚刚编译了你的代码,发现窗口一直保持在同一个位置,所以我决定——这就是你想要实现的。我会再举一个例子……

标签: c# windows winforms


【解决方案1】:

坦率地说,我不知道是否可以为特定窗口禁用 Aero Shake。但我可以建议一种解决方法,以防止触发 Aero Shake。

有可能将所有鼠标输入仅定向到一个窗口(这也会对 Aero Shake 处理程序隐藏鼠标事件)。检查MSDN 处的SetCapture 描述。我们还需要GetCaptureReleaseCapture 函数。

有一点需要注意:一旦您将鼠标捕获设置为窗口 - 您负责处理所有鼠标输入。因此,要实现目标,您需要实现自己的处理程序来移动窗口。幸运的是,这并不难。

这是一个带有对话框的代码示例,该对话框在移动时更改其大小,并在移动完成后恢复大小。 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);
    }
}

【讨论】:

    猜你喜欢
    • 2018-04-11
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 2015-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多