質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

解決済

1回答

1298閲覧

Microsoft Report Viewerのスクロールバーにアクセスしたい

TaikiMurata

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

1グッド

0クリップ

投稿2020/02/26 00:53

###環境
Windows Form C#
Visual Studio 2019
###最終的に実現したい事
帳票のサイズが大きい場合にスクロールバーが自動で表示されるが、その後の
Viewer上に表示した帳票をつかんでドラッグすると帳票を動かせるようにしたい。
###実現するために試したが出来ないこと
●表示されたスクロールバーのオブジェクトにアクセスする

上記のスクロールバーの値変更が出来れば、
マウスの移動距離等から計算して自動的に動かせるかなと思っているのですが
スクロールバーの座標の取得、設定が出来なくて困っております。

お力添え宜しくお願いします。

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TaikiMurata

2020/02/28 05:33

神技でした…!!! 参考までに宜しければもう一つ教えて頂きたいのですが、 スクロールを担当しているのは、ReportPanelのようです。 マウスイベントを飲み込んでいるのは、RenderingPanelのようです。 ↑これらを調べる方法というのは手探りでやるしかないのでしょうか?
TN8001

2020/02/28 08:36

これといった情報が見つからなかったため地道に調査しました^^ ReportPanelは適当にスクロールさせた状態でブレークし、Controlsをいっこいっこ見ていきましたw 比較的手前にありました。 RenderingPanelはSpy++で、メッセージが来ているものを最下層から調べました。 一番下がそれで、MouseMove +=としても呼ばれなかったため飲み込んでると判断しました。
TaikiMurata

2020/03/02 04:08 編集

Controlについては地道にやるしかないのですね… 一応その手法を自分もやってはいたのですが目的の物を探し当てることが出来ませんでした OTL もう少し根気強くやっていればPanelに関しては自力解決できたのかもしれません(; ・`д・´) Spy++調べて使ってみます! ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問