31460


お世話になります。

タイトルバーを持たないフォームでドラッグ移動をさせようと、下記のサイト様  
<http://dobon.net/vb/dotnet/form/moveform.html>  
を拝見してソースを組んでいるのですが、二つ目のサンプル、コントロール上でも  
移動できるようにするでは、すべてが同じフォームの中に存在しているので、  
このコードでもできると思うのですが、自分で別にクラス化したユーザコントロールを  
貼り付けた場合、どのようなコードにすればよいでしょうか。  
[![画像の説明をここに入力](https://i.stack.imgur.com/O9PEj.png)](https://i.stack.imgur.com/O9PEj.png)  
既にクラス化されているので、図のようにラベルやピクチャボックスに後から  
MouseDownやMouseMoveの処理を追加することはできません。それなら、  
クラス化するときにラベルやピクチャボックスにMouseDownやMouseMoveの処理を  
追加しておけばよいかというと、本来必要でない(フォームではないので、  
持って動かすという処理はこの時点では必要ない)処理を入れるのはふさわしくないと  
思います。

やはり、この自作のユーザーコントロールをフォームに張り付けた後、  
フォーム側のコードからMouseDownやMouseMoveの処理を実装したいのですが、  
通常通りにやると、ラベルやピクチャボックスでドラッグすると、  
それらのコントロールにマウス処理が働いてしまい、うまくいきません。  
サンプルに書かれてある内容通りです。

力ずくでやるのであれば、ラベルやピクチャボックスにフォームからアクセスすれば  
できそうではありますが、あまりきれいなコードにはならないと思っています。

図のラベルやピクチャボックスの場所でも、ドラッグ移動できるようにするきれいな方法を  
ご教授いただけますでしょうか。

よろしくお願いいたします。


CC BY-SA 3.0
2016-12-27T07:09:01.190
31458
2017-01-15T14:42:41.353
2017-01-09T14:35:48.913
8000
9374
question
c# winforms
C# タイトルバー以外の場所でフォームをドラッグさせる方法について


`Label`や`PictureBox`のイベントハンドラーで`UserControl`のイベントを発生させればよいのでは。

[code]

    public partial class UserControl1 : UserControl
    {
        private void label1_MouseDown(object sender, MouseEventArgs e)
        {
            var c = (Control)sender;
            base.OnMouseDown(new MouseEventArgs(e.Button, e.Clicks, c.Left + e.X, c.Top + e.Y, e.Delta));
        }
    
        private void label1_MouseMove(object sender, MouseEventArgs e)
        {
            var c = (Control)sender;
            base.OnMouseMove(new MouseEventArgs(e.Button, e.Clicks, c.Left + e.X, c.Top + e.Y, e.Delta));
        }
    }
    
[/code]

## 追記

`UserControl`上のコントロールでマウスイベントを無視する手段としては、`WndProc`をオーバーライドしてヒットテストを無視する方法があります。

[code]

    class CustomLabel : Label
    {
        private const int WM_NCHITTEST = 0x84;
        private const int HTTRANSPARENT = -1;
    
        protected override void WndProc(ref Message message)
        {
            if (message.Msg == (int)WM_NCHITTEST)
            {
                message.Result = (IntPtr)HTTRANSPARENT;
            }
            else
            {
                base.WndProc(ref message);
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2016-12-27T07:29:37.970
31460
2016-12-28T07:36:59.490
2016-12-28T07:36:59.490
5750
5750
31458
answer


きれいな方法ではないですが、あとから全体的にWindowメッセージを処理したいのであれば、  
WH_GETMESSAGEでSetWindowsHookExを使用して、  
GetMessageをフックして必要な処理を行う方法もあります。


CC BY-SA 3.0
2017-01-15T14:42:41.353
31873
2017-01-15T14:42:41.353
20114
31458
answer