【问题标题】:DefWindowProc call not working on Windows 8DefWindowProc 调用在 Windows 8 上不起作用
【发布时间】:2012-12-02 16:33:55
【问题描述】:

我在从 C# winform 调用 Windows 8 上的 DefWindowsProc 时遇到问题。我有这个表单,我需要它可以从表单内的任何地方拖动。

这是我的代码。

[DllImport("user32.dll")]
static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool ReleaseCapture(IntPtr hwnd);

const uint WM_SYSCOMMAND = 0x112;
const uint MOUSE_MOVE = 0xF012;

public void Drag()
{
    DefWindowProc(this.Handle, WM_SYSCOMMAND, (UIntPtr)MOUSE_MOVE, IntPtr.Zero);
}


private void OnMainPanelMouseDown(object sender, MouseEventArgs e)
{
    Control ctrl = sender as Control;
    ReleaseCapture(ctrl.Handle);

    this.Drag(); // put the form into drag mode.
}

DefWindowProc 总是返回 0 但我无法拖动我的窗口。此调用适用于 XP、Vista 和 7,但不适用于 8。我猜这与在 Windows 8 上无法正常运行的 DefWindowProc 的声明有关。

请注意,在 Windows 8 上,我使用 .NET 4.0 框架构建应用程序,而在其他平台上,我使用 2.0 版本构建软件。

【问题讨论】:

    标签: c# .net windows winforms windows-8


    【解决方案1】:

    我用稍微不同的方法实现了你的功能。

    我正在运行 Windows 8 和 Visual Studio 2012。

    我在框架的所有版本(版本 2、3、4、4.5)中测试了我的解决方案。

    当然,您的主窗体需要捕获 mouse_down() 方法。

      private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(282, 253);
            this.Name = "Form1";
            this.Text = "Form1";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mouse_down);
            this.ResumeLayout(false);
    
        }
    

    首先我定义了一个名为 UnsafeNativeMethods 的类:

    [SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods
    {
        public const int WM_NCLBUTTONDOWN = 0xA1;
        public const int HT_CAPTION = 0x2;
    
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hwnd, uint Msg, int wParam, int lParam);
    
        [DllImport("User32.dll", EntryPoint = "ReleaseCapture")]
        public static extern bool ReleaseCapture();
    
    }
    

    在您希望用鼠标从任意位置移动的表单内:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void mouse_down(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                UnsafeNativeMethods.ReleaseCapture();
                UnsafeNativeMethods.SendMessage(Handle, UnsafeNativeMethods.WM_NCLBUTTONDOWN, UnsafeNativeMethods.HT_CAPTION, 0);
            }
        }
    
    
    }
    

    【讨论】:

    • 这根本没有解决问题,窗口仍然无法移动到屏幕的上边缘之外。
    【解决方案2】:

    我重新编写了示例以查看 DefWindowProc() 的行为是否不同。不是。拖动时,表单仍会停靠在边缘。

    不过,这里是代码:

    [SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods2
    {
        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref int lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
    
        [DllImport("user32")]
        public static extern int ReleaseCapture(IntPtr hwnd);
    
        public const int WM_SYSCOMMAND = 0x112;
        public const int MOUSE_MOVE = 0xF012;
    }
    

    这是表单内的代码。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void mouse_down(object sender, MouseEventArgs e)
        {
            Control ctrl = sender as Control;
            UnsafeNativeMethods2.ReleaseCapture(ctrl.Handle);
            this.Drag(); // put the form into drag mode.
    
        }
        public void Drag()
        {
            UnsafeNativeMethods2.DefWindowProc(this.Handle, UnsafeNativeMethods2.WM_SYSCOMMAND, (IntPtr) UnsafeNativeMethods2.MOUSE_MOVE, IntPtr.Zero);
        }
    }
    

    我的 DefWindowProc() 声明与你的略有不同。

    归根结底,这两种方法都实现了相同的结果 - 能够从表单中的任何位置拖动窗口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 1970-01-01
      • 2012-12-07
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多