我在使用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.我猜它与DefWindowProc的解除有关,但在Windows 8上效果不佳。
请注意,在Windows 8上,我正在使用.NET 4.0框架构建我的应用程序,但在其他平台上我使用2.0版本来构建软件。
答案 0 :(得分:2)
我通过稍微不同的方法实现了您的功能。
我正在运行Windows 8和Visual Studio 2012。
我测试了我的解决方案所有版本的框架,版本2,3,4,5.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);
}
}
}
答案 1 :(得分:1)
我重新编写了示例,看看行为是否与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()声明与你的略有不同。
最重要的是,两种方法都能达到相同的效果 - 能够从窗体中的任何位置拖动窗口。