0

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 バージョンを使用してソフトウェアを構築しています。

4

2 に答える 2

2

少し異なるアプローチで機能を実現しました。

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


}
于 2012-12-02T17:57:38.630 に答える
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() は、あなたのものとは少し異なって宣言されています。

要するに、どちらの方法でも同じ結果が得られます。つまり、フォーム内のどこからでもウィンドウをドラッグできます。

于 2012-12-02T19:01:45.017 に答える