6642


現在C#/.net4.5環境においてWindowsフォームを使った  
Win8タブレット向けのアプリケーションを作成しています。

アプリでは、

> ■PanelA  
>  ├■Button1  
>  ├■Button2  
>  ├■Button3  
>  …

といった形で、パネルの子コントロールとしてボタンを並べて配置している箇所があります。  
このとき、PanelAにはスクロールバーが表示される状態になっており、  
PanelA上の何も無い箇所をスワイプするとスクロールを行ってくれるのですが、  
Button上を起点にスワイプするとスクロールされません。

調べて試してみたのですが、WPFではScrollViewer.PanningModeを設定することで、  
ボタン上からのスワイプによってスクロールされることを確認しました。  
ただ、WPFとの混合運用は極力避けたいと考えており、  
まずはWindowsフォームでそもそもこの機構を実現するのは難しいのかどうかも合わせて、  
ご教授いただけないでしょうか。

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


CC BY-SA 3.0
2015-02-17T08:39:29.620
6632
2015-02-17T11:29:11.087
6051
question
c# windows wpf winforms
Windowsフォームアプリにおけるスワイプによるスクロールについて


`Button`の様なクリックのみで動作するコントロールであれば、`MouseDown`や`MouseMove`の中で親コントロールに`Capture`を設定すれば親がドラッグされているかのように動作させられます。下のコードはクリックをキャンセルしてPanelを水平スクロールさせるサンプルになります。

[code]

    public partial class Form1 : Form
    {
        private int _PreviousX;
    
        public Form1()
        {
            // デザイナー上ではpanel1の中にButtonが水平に並べてあります。
            InitializeComponent();
    
            // パネル内のコントロールにイベントハンドラーを設定
            foreach (Control c in panel1.Controls)
            {
                c.Click += (s, args) => MessageBox.Show(s.ToString());
                c.MouseDown += Button_MouseDown;
                c.MouseMove += Button_MouseMove;
            }
        }
    
        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            // パネルが普通にクリックされた場合
            panel1.Capture = true;
            _PreviousX = panel1.PointToScreen(e.Location).X;
        }
    
        private void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (panel1.Capture)
            {
                // パネルのドラッグ処理
                var x = panel1.PointToScreen(e.Location).X;
                panel1.HorizontalScroll.Value = Math.Min(
                                                    Math.Max(
                                                        panel1.HorizontalScroll.Minimum,
                                                        panel1.HorizontalScroll.Value + _PreviousX - x),
                                                        panel1.HorizontalScroll.Maximum);
                _PreviousX = x;
            }
        }
    
        private void panel1_MouseUp(object sender, MouseEventArgs e)
        {
            panel1.Capture = false;
        }
    
        private void Button_MouseDown(object sender, MouseEventArgs e)
        {
            // ボタンがクリックされた場合
            var c = (Control)sender;
    
            c.Capture = true;
    
            _PreviousX = c.PointToScreen(e.Location).X;
        }
    
        private void Button_MouseMove(object sender, MouseEventArgs e)
        {
            var c = (Control)sender;
            if (c.Capture)
            {
                // ボタンが押された状態である程度動いたらpanel1にイベントを付け替える
                var x = panel1.PointToScreen(e.Location).X;
                if (Math.Abs(x - _PreviousX) > 3)
                {
                    c.Capture = false;
                    panel1.Capture = true;
                }
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2015-02-17T11:29:11.087
6642
2015-02-17T11:29:11.087
5750
6632
answer