###環境
Windows Form C#
Visual Studio 2019
###最終的に実現したい事
帳票のサイズが大きい場合にスクロールバーが自動で表示されるが、その後の
Viewer上に表示した帳票をつかんでドラッグすると帳票を動かせるようにしたい。
###実現するために試したが出来ないこと
●表示されたスクロールバーのオブジェクトにアクセスする
上記のスクロールバーの値変更が出来れば、
マウスの移動距離等から計算して自動的に動かせるかなと思っているのですが
スクロールバーの座標の取得、設定が出来なくて困っております。
お力添え宜しくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
色々とガバガバなので注意してください。
スクロールを担当しているのは、ReportPanel
のようです。
マウスイベントを飲み込んでいるのは、RenderingPanel
のようです。
手元の実験(大きな画像がひとつあるだけのレポート)ではどちらもひとつずつありましたが、レポートによっては変わるのかもしれません(もし複数あったら破綻します)
各コントロールはControls
を追っていくだけで取れました。
マウスイベントを取るためにRenderingPanel
をサブクラス化しました。
後始末用にIDisposable
にしましたが、余計だったかもしれません(WndProcDelegate
がGCされないようフィールドに持っておく必要はあります)
透明なパネルとUIAutomation
も試しましたが、スクロールが細かく制御できない・リポートのリンクが押せないため断念しました。
cs:Form1.cs
1using System; 2using System.Collections.Generic; 3using System.Data; 4using System.Linq; 5using System.Runtime.InteropServices; 6using System.Windows.Forms; 7using Microsoft.Reporting.WinForms; 8 9namespace Questions243538 10{ 11 public partial class Form1 : Form 12 { 13 private readonly ReportViewerScroller scroller; 14 public Form1() 15 { 16 InitializeComponent(); 17 scroller = new ReportViewerScroller(reportViewer1); 18 19 } 20 private void Form1_Load(object sender, EventArgs e) 21 => reportViewer1.RefreshReport(); 22 23 24 private class ReportViewerScroller : IDisposable 25 { 26#pragma warning disable CA2213 // Disposable fields should be disposed 27 private ScrollableControl reportPanel; 28 private Control renderingPanel; 29#pragma warning restore CA2213 // Disposable fields should be disposed 30 31 private const string ReportPanelName = "Microsoft.Reporting.WinForms.ReportPanel"; 32 private const string RenderingPanelName = "Microsoft.Reporting.WinForms.ReportPanel+RenderingPanel"; 33 34 private NativeMethods.WndProcDelegate newWndProc; 35 private IntPtr oldWndProc; 36 37 private bool dragging; 38 private int startX; 39 private int startY; 40 41 public ReportViewerScroller(ReportViewer reportViewer) 42 { 43 reportPanel = GetAllControls(reportViewer, ReportPanelName).First() as ScrollableControl; 44 renderingPanel = GetAllControls(reportViewer, RenderingPanelName).First() as Control; 45 46 newWndProc = new NativeMethods.WndProcDelegate(WindowProc); 47 oldWndProc = NativeMethods.SetWindowLong(renderingPanel.Handle, NativeMethods.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWndProc)); 48 } 49 50 private IntPtr WindowProc(IntPtr hWnd, int Msg, int wParam, int lParam) 51 { 52 switch(Msg) 53 { 54 case NativeMethods.WM_LBUTTONDOWN: 55 dragging = true; 56 startX = Cursor.Position.X + reportPanel.HorizontalScroll.Value; 57 startY = Cursor.Position.Y + reportPanel.VerticalScroll.Value; 58 break; 59 60 case NativeMethods.WM_MOUSEMOVE: 61 if(!dragging) break; 62 63 var x = startX - Cursor.Position.X; 64 var y = startY - Cursor.Position.Y; 65 66 if(0 < x) reportPanel.HorizontalScroll.Value = x; 67 if(0 < y) reportPanel.VerticalScroll.Value = y; 68 break; 69 70 case NativeMethods.WM_LBUTTONUP: 71 dragging = false; 72 break; 73 } 74 75 return NativeMethods.CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam); 76 } 77 78 private static IEnumerable<Control> GetAllControls(Control control) 79 { 80 var controls = control.Controls.Cast<Control>(); 81 return controls.SelectMany(c => GetAllControls(c)).Concat(controls); 82 } 83 private static IEnumerable<Control> GetAllControls(Control control, string typeName) 84 => GetAllControls(control).Where(c => c.GetType().FullName == typeName); 85 86 #region IDisposable Support 87 private bool disposedValue = false; 88 protected virtual void Dispose(bool disposing) 89 { 90 if(!disposedValue) 91 { 92 var hWnd = renderingPanel?.Handle; 93 if(disposing) 94 { 95 reportPanel = null; 96 renderingPanel = null; 97 } 98 99 if(hWnd != null && hWnd.Value != IntPtr.Zero && oldWndProc != IntPtr.Zero) 100 { 101 NativeMethods.SetWindowLong(hWnd.Value, NativeMethods.GWL_WNDPROC, oldWndProc); 102 newWndProc = null; 103 oldWndProc = IntPtr.Zero; 104 } 105 106 disposedValue = true; 107 } 108 } 109 110 ~ReportViewerScroller() => Dispose(false); 111 112 public void Dispose() 113 { 114 Dispose(true); 115 GC.SuppressFinalize(this); 116 } 117 #endregion 118 119 private static class NativeMethods 120 { 121 public delegate IntPtr WndProcDelegate(IntPtr hWnd, int Msg, int wParam, int lParam); 122 [DllImport("user32")] public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newProc); 123 [DllImport("user32")] public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, int wParam, int lParam); 124 125 public const int GWL_WNDPROC = -4; 126 public const int WM_MOUSEMOVE = 0x200; 127 public const int WM_LBUTTONDOWN = 0x0201; 128 public const int WM_LBUTTONUP = 0x0202; 129 } 130 } 131 } 132}
cs:Form1.Designer.cs
1namespace Questions243538 2{ 3 partial class Form1 4 { 5 /// <summary> 6 /// 必要なデザイナー変数です。 7 /// </summary> 8 private System.ComponentModel.IContainer components = null; 9 10 /// <summary> 11 /// 使用中のリソースをすべてクリーンアップします。 12 /// </summary> 13 /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param> 14 protected override void Dispose(bool disposing) 15 { 16 if(disposing && (components != null)) 17 { 18 components.Dispose(); 19 } 20 21 scroller.Dispose(); 22 23 base.Dispose(disposing); 24 } 25 26 #region Windows フォーム デザイナーで生成されたコード 27 28 /// <summary> 29 /// デザイナー サポートに必要なメソッドです。このメソッドの内容を 30 /// コード エディターで変更しないでください。 31 /// </summary> 32 private void InitializeComponent() 33 { 34 this.reportViewer1 = new Microsoft.Reporting.WinForms.ReportViewer(); 35 this.SuspendLayout(); 36 // 37 // reportViewer1 38 // 39 this.reportViewer1.Dock = System.Windows.Forms.DockStyle.Fill; 40 this.reportViewer1.LocalReport.ReportEmbeddedResource = "Questions243538.Report1.rdlc"; 41 this.reportViewer1.Location = new System.Drawing.Point(0, 0); 42 this.reportViewer1.Name = "reportViewer1"; 43 this.reportViewer1.ServerReport.BearerToken = null; 44 this.reportViewer1.Size = new System.Drawing.Size(800, 450); 45 this.reportViewer1.TabIndex = 0; 46 // 47 // Form1 48 // 49 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 50 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 51 this.ClientSize = new System.Drawing.Size(800, 450); 52 this.Controls.Add(this.reportViewer1); 53 this.Name = "Form1"; 54 this.Text = "Form1"; 55 this.Load += new System.EventHandler(this.Form1_Load); 56 this.ResumeLayout(false); 57 58 } 59 60 #endregion 61 62 private Microsoft.Reporting.WinForms.ReportViewer reportViewer1; 63 } 64}
ReportViewer
はpro以上じゃなくても使えるんですね。
入れるのに手間取りましたが^^;
投稿2020/02/27 22:16
編集2023/07/20 15:31総合スコア9862
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/28 05:33
2020/02/28 08:36
2020/03/02 04:08 編集