回答編集履歴

1

見直しキャンペーン中

2023/07/20 15:31

投稿

TN8001
TN8001

スコア9862

test CHANGED
@@ -1,437 +1,219 @@
1
1
  **色々とガバガバなので注意してください。**
2
2
 
3
-
4
-
5
3
  スクロールを担当しているのは、`ReportPanel`のようです。
6
-
7
4
  マウスイベントを飲み込んでいるのは、`RenderingPanel`のようです。
8
5
 
9
-
10
-
11
6
  手元の実験(大きな画像がひとつあるだけのレポート)ではどちらもひとつずつありましたが、レポートによっては変わるのかもしれません(もし複数あったら破綻します)
12
-
13
7
  各コントロールは`Controls`を追っていくだけで取れました。
14
8
 
15
-
16
-
17
9
  マウスイベントを取るために`RenderingPanel`をサブクラス化しました。
18
-
19
10
  後始末用に`IDisposable`にしましたが、余計だったかもしれません(`WndProcDelegate`がGCされないようフィールドに持っておく必要はあります)
20
11
 
21
-
22
-
23
12
  透明なパネルと`UIAutomation`も試しましたが、スクロールが細かく制御できない・リポートのリンクが押せないため断念しました。
24
13
 
25
-
26
-
27
- ```C#
14
+ ```cs:Form1.cs
28
-
29
15
  using System;
30
-
31
16
  using System.Collections.Generic;
32
-
33
17
  using System.Data;
34
-
35
18
  using System.Linq;
36
-
37
19
  using System.Runtime.InteropServices;
38
-
39
20
  using System.Windows.Forms;
40
-
41
21
  using Microsoft.Reporting.WinForms;
42
22
 
43
-
44
-
45
23
  namespace Questions243538
46
-
47
24
  {
48
-
49
25
  public partial class Form1 : Form
50
-
51
26
  {
52
-
53
27
  private readonly ReportViewerScroller scroller;
54
-
55
28
  public Form1()
56
-
57
- {
29
+ {
58
-
59
30
  InitializeComponent();
60
-
61
31
  scroller = new ReportViewerScroller(reportViewer1);
62
32
 
63
-
64
-
65
- }
33
+ }
66
-
67
34
  private void Form1_Load(object sender, EventArgs e)
68
-
69
35
  => reportViewer1.RefreshReport();
70
36
 
71
37
 
72
-
73
-
74
-
75
38
  private class ReportViewerScroller : IDisposable
76
-
77
- {
39
+ {
78
-
79
40
  #pragma warning disable CA2213 // Disposable fields should be disposed
80
-
81
41
  private ScrollableControl reportPanel;
82
-
83
42
  private Control renderingPanel;
84
-
85
43
  #pragma warning restore CA2213 // Disposable fields should be disposed
86
44
 
87
-
88
-
89
45
  private const string ReportPanelName = "Microsoft.Reporting.WinForms.ReportPanel";
90
-
91
46
  private const string RenderingPanelName = "Microsoft.Reporting.WinForms.ReportPanel+RenderingPanel";
92
47
 
93
-
94
-
95
48
  private NativeMethods.WndProcDelegate newWndProc;
96
-
97
49
  private IntPtr oldWndProc;
98
50
 
99
-
100
-
101
51
  private bool dragging;
102
-
103
52
  private int startX;
104
-
105
53
  private int startY;
106
54
 
107
-
108
-
109
55
  public ReportViewerScroller(ReportViewer reportViewer)
110
-
111
- {
56
+ {
112
-
113
57
  reportPanel = GetAllControls(reportViewer, ReportPanelName).First() as ScrollableControl;
114
-
115
58
  renderingPanel = GetAllControls(reportViewer, RenderingPanelName).First() as Control;
116
59
 
117
-
118
-
119
60
  newWndProc = new NativeMethods.WndProcDelegate(WindowProc);
120
-
121
61
  oldWndProc = NativeMethods.SetWindowLong(renderingPanel.Handle, NativeMethods.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWndProc));
122
-
123
- }
62
+ }
124
-
125
-
126
63
 
127
64
  private IntPtr WindowProc(IntPtr hWnd, int Msg, int wParam, int lParam)
128
-
129
- {
65
+ {
130
-
131
66
  switch(Msg)
132
-
133
67
  {
134
-
135
68
  case NativeMethods.WM_LBUTTONDOWN:
136
-
137
69
  dragging = true;
138
-
139
70
  startX = Cursor.Position.X + reportPanel.HorizontalScroll.Value;
140
-
141
71
  startY = Cursor.Position.Y + reportPanel.VerticalScroll.Value;
142
-
143
72
  break;
144
73
 
145
-
146
-
147
74
  case NativeMethods.WM_MOUSEMOVE:
148
-
149
75
  if(!dragging) break;
150
76
 
151
-
152
-
153
77
  var x = startX - Cursor.Position.X;
154
-
155
78
  var y = startY - Cursor.Position.Y;
156
79
 
157
-
158
-
159
80
  if(0 < x) reportPanel.HorizontalScroll.Value = x;
160
-
161
81
  if(0 < y) reportPanel.VerticalScroll.Value = y;
162
-
163
82
  break;
164
83
 
165
-
166
-
167
84
  case NativeMethods.WM_LBUTTONUP:
168
-
169
85
  dragging = false;
170
-
171
86
  break;
172
-
173
87
  }
174
88
 
175
-
176
-
177
89
  return NativeMethods.CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam);
178
-
179
- }
90
+ }
180
-
181
-
182
91
 
183
92
  private static IEnumerable<Control> GetAllControls(Control control)
184
-
185
- {
93
+ {
186
-
187
94
  var controls = control.Controls.Cast<Control>();
188
-
189
95
  return controls.SelectMany(c => GetAllControls(c)).Concat(controls);
190
-
191
- }
96
+ }
192
-
193
97
  private static IEnumerable<Control> GetAllControls(Control control, string typeName)
194
-
195
98
  => GetAllControls(control).Where(c => c.GetType().FullName == typeName);
196
99
 
197
-
198
-
199
100
  #region IDisposable Support
200
-
201
101
  private bool disposedValue = false;
202
-
203
102
  protected virtual void Dispose(bool disposing)
204
-
205
- {
103
+ {
206
-
207
104
  if(!disposedValue)
208
-
209
105
  {
210
-
211
106
  var hWnd = renderingPanel?.Handle;
212
-
213
107
  if(disposing)
214
-
215
108
  {
216
-
217
109
  reportPanel = null;
218
-
219
110
  renderingPanel = null;
220
-
221
111
  }
222
112
 
223
-
224
-
225
113
  if(hWnd != null && hWnd.Value != IntPtr.Zero && oldWndProc != IntPtr.Zero)
226
-
227
114
  {
228
-
229
115
  NativeMethods.SetWindowLong(hWnd.Value, NativeMethods.GWL_WNDPROC, oldWndProc);
230
-
231
116
  newWndProc = null;
232
-
233
117
  oldWndProc = IntPtr.Zero;
234
-
235
118
  }
236
119
 
237
-
238
-
239
120
  disposedValue = true;
240
-
241
121
  }
242
-
243
- }
122
+ }
244
-
245
-
246
123
 
247
124
  ~ReportViewerScroller() => Dispose(false);
248
125
 
249
-
250
-
251
126
  public void Dispose()
252
-
253
- {
127
+ {
254
-
255
128
  Dispose(true);
256
-
257
129
  GC.SuppressFinalize(this);
258
-
259
- }
130
+ }
260
-
261
131
  #endregion
262
132
 
263
-
264
-
265
133
  private static class NativeMethods
266
-
267
- {
134
+ {
268
-
269
135
  public delegate IntPtr WndProcDelegate(IntPtr hWnd, int Msg, int wParam, int lParam);
270
-
271
136
  [DllImport("user32")] public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newProc);
272
-
273
137
  [DllImport("user32")] public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, int wParam, int lParam);
274
138
 
275
-
276
-
277
139
  public const int GWL_WNDPROC = -4;
278
-
279
140
  public const int WM_MOUSEMOVE = 0x200;
280
-
281
141
  public const int WM_LBUTTONDOWN = 0x0201;
282
-
283
142
  public const int WM_LBUTTONUP = 0x0202;
284
-
285
- }
143
+ }
286
-
287
- }
144
+ }
288
-
289
145
  }
290
-
291
146
  }
292
-
293
147
  ```
294
148
 
295
-
296
-
297
- ```C#
149
+ ```cs:Form1.Designer.cs
298
-
299
150
  namespace Questions243538
300
-
301
151
  {
302
-
303
152
  partial class Form1
304
-
305
153
  {
306
-
307
154
  /// <summary>
308
-
309
155
  /// 必要なデザイナー変数です。
310
-
311
156
  /// </summary>
312
-
313
157
  private System.ComponentModel.IContainer components = null;
314
158
 
315
-
316
-
317
159
  /// <summary>
318
-
319
160
  /// 使用中のリソースをすべてクリーンアップします。
320
-
321
161
  /// </summary>
322
-
323
162
  /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
324
-
325
163
  protected override void Dispose(bool disposing)
326
-
327
- {
164
+ {
328
-
329
165
  if(disposing && (components != null))
330
-
331
- {
166
+ {
332
-
333
167
  components.Dispose();
334
-
335
- }
168
+ }
336
-
337
-
338
169
 
339
170
  scroller.Dispose();
340
171
 
341
-
342
-
343
172
  base.Dispose(disposing);
344
-
345
- }
173
+ }
346
-
347
-
348
174
 
349
175
  #region Windows フォーム デザイナーで生成されたコード
350
176
 
351
-
352
-
353
177
  /// <summary>
354
-
355
178
  /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
356
-
357
179
  /// コード エディターで変更しないでください。
358
-
359
180
  /// </summary>
360
-
361
181
  private void InitializeComponent()
362
-
363
- {
182
+ {
364
-
365
183
  this.reportViewer1 = new Microsoft.Reporting.WinForms.ReportViewer();
366
-
367
184
  this.SuspendLayout();
368
-
369
- //
185
+ //
370
-
371
186
  // reportViewer1
372
-
373
- //
187
+ //
374
-
375
188
  this.reportViewer1.Dock = System.Windows.Forms.DockStyle.Fill;
376
-
377
189
  this.reportViewer1.LocalReport.ReportEmbeddedResource = "Questions243538.Report1.rdlc";
378
-
379
190
  this.reportViewer1.Location = new System.Drawing.Point(0, 0);
380
-
381
191
  this.reportViewer1.Name = "reportViewer1";
382
-
383
192
  this.reportViewer1.ServerReport.BearerToken = null;
384
-
385
193
  this.reportViewer1.Size = new System.Drawing.Size(800, 450);
386
-
387
194
  this.reportViewer1.TabIndex = 0;
388
-
389
- //
195
+ //
390
-
391
196
  // Form1
392
-
393
- //
197
+ //
394
-
395
198
  this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
396
-
397
199
  this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
398
-
399
200
  this.ClientSize = new System.Drawing.Size(800, 450);
400
-
401
201
  this.Controls.Add(this.reportViewer1);
402
-
403
202
  this.Name = "Form1";
404
-
405
203
  this.Text = "Form1";
406
-
407
204
  this.Load += new System.EventHandler(this.Form1_Load);
408
-
409
205
  this.ResumeLayout(false);
410
206
 
411
-
412
-
413
- }
207
+ }
414
-
415
-
416
208
 
417
209
  #endregion
418
210
 
419
-
420
-
421
211
  private Microsoft.Reporting.WinForms.ReportViewer reportViewer1;
422
-
423
212
  }
424
-
425
213
  }
426
-
427
214
  ```
428
215
 
429
-
430
-
431
216
  ---
432
217
 
433
-
434
-
435
218
  `ReportViewer`はpro以上じゃなくても使えるんですね。
436
-
437
219
  入れるのに手間取りましたが^^;