DocumentStitchWindow.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. using PaintDotNet.SystemLayer;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.Reflection;
  8. using System.Threading;
  9. using System.Windows.Forms;
  10. namespace PaintDotNet
  11. {
  12. /// <summary>
  13. /// 抽出来在图像拼接弹窗里面使用
  14. /// </summary>
  15. internal class DocumentStitchWindow : DocumentStitchView
  16. {
  17. private ZoomBasis zoomBasis;
  18. protected override void OnLayout(LayoutEventArgs e)
  19. {
  20. if (this.zoomBasis == ZoomBasis.FitToWindow)
  21. {
  22. ZoomToPreviewWindow();
  23. // This bizarre ordering of setting PanelAutoScroll prevents some very weird layout/scroll-without-scrollbars stuff.
  24. PanelAutoScroll = true;
  25. PanelAutoScroll = false;
  26. }
  27. base.OnLayout(e);
  28. }
  29. protected override void OnResize(EventArgs e)
  30. {
  31. if (this.zoomBasis == ZoomBasis.FitToWindow)
  32. {
  33. PerformLayout();
  34. }
  35. base.OnResize(e);
  36. }
  37. public DocumentStitchWindow()
  38. {
  39. this.InitToolsAndManager();
  40. InitializeComponent();
  41. this.zoomBasis = ZoomBasis.FitToWindow;
  42. InitializeBottomEvent();
  43. this.MouseEvent_Del(null, null);
  44. }
  45. private void InitializeComponent()
  46. {
  47. }
  48. protected override void Dispose(bool disposing)
  49. {
  50. base.Dispose(disposing);
  51. }
  52. public override void ZoomIn()
  53. {
  54. this.ZoomBasis = ZoomBasis.ScaleFactor;
  55. base.ZoomIn();
  56. }
  57. public override void ZoomIn(double factor)
  58. {
  59. this.ZoomBasis = ZoomBasis.ScaleFactor;
  60. base.ZoomIn(factor);
  61. }
  62. public override void ZoomOut()
  63. {
  64. this.ZoomBasis = ZoomBasis.ScaleFactor;
  65. base.ZoomOut();
  66. }
  67. public override void ZoomOut(double factor)
  68. {
  69. this.ZoomBasis = ZoomBasis.ScaleFactor;
  70. base.ZoomOut(factor);
  71. }
  72. public event EventHandler ZoomBasisChanging;
  73. protected virtual void OnZoomBasisChanging()
  74. {
  75. if (ZoomBasisChanging != null)
  76. {
  77. ZoomBasisChanging(this, EventArgs.Empty);
  78. }
  79. }
  80. public event EventHandler ZoomBasisChanged;
  81. protected virtual void OnZoomBasisChanged()
  82. {
  83. if (ZoomBasisChanged != null)
  84. {
  85. ZoomBasisChanged(this, EventArgs.Empty);
  86. }
  87. }
  88. //public int OffsetH
  89. //{
  90. // set
  91. // {
  92. // this.panel.AutoScrollPosition.X = value;
  93. // }
  94. //}
  95. /// <summary>
  96. /// 持有mat的有效区域
  97. /// </summary>
  98. public OpenCvSharp.Mat StitchMat
  99. {
  100. get
  101. {
  102. if (this.StitchDocument == null || this.StitchDocument.surface == null) return null;
  103. return this.StitchDocument.surface.StitchMat;
  104. }
  105. }
  106. /// <summary>
  107. /// 持有mat的绘制区域
  108. /// </summary>
  109. public Rectangle StitchBounds
  110. {
  111. get
  112. {
  113. return this.StitchDocument.surface.stitchBounds;
  114. }
  115. set
  116. {
  117. this.StitchDocument.surface.stitchBounds = value;
  118. }
  119. }
  120. /// <summary>
  121. /// 持有mat的绘制区域
  122. /// </summary>
  123. public int StitchWidth
  124. {
  125. get
  126. {
  127. return this.StitchDocument.surface.StitchWidth;
  128. }
  129. }
  130. /// <summary>
  131. /// 持有mat的绘制区域
  132. /// </summary>
  133. public int StitchHeight
  134. {
  135. get
  136. {
  137. return this.StitchDocument.surface.StitchHeight;
  138. }
  139. }
  140. /// <summary>
  141. /// 合适大小
  142. /// </summary>
  143. public void ZoomToPreviewWindow()
  144. {
  145. if (this.StitchDocument != null)
  146. {
  147. Rectangle max = ClientRectangleMax;
  148. ScaleFactor zoom = ScaleFactor.Min(max.Width - 10,
  149. this.StitchBounds.Width,
  150. max.Height - 10,
  151. this.StitchBounds.Height,
  152. ScaleFactor.MinValue);
  153. ScaleFactor min = ScaleFactor.Min(zoom, ScaleFactor.OneToOne);
  154. this.ScaleFactor = min;
  155. }
  156. }
  157. public ZoomBasis ZoomBasis
  158. {
  159. get
  160. {
  161. return this.zoomBasis;
  162. }
  163. set
  164. {
  165. if (this.zoomBasis != value)
  166. {
  167. OnZoomBasisChanging();
  168. this.zoomBasis = value;
  169. //this.panel.AutoScrollOffset
  170. switch (this.zoomBasis)
  171. {
  172. case ZoomBasis.FitToWindow:
  173. ZoomToPreviewWindow();
  174. //// Enable PanelAutoScroll only long enough to recenter the view
  175. //PanelAutoScroll = true;
  176. //PanelAutoScroll = false;
  177. // this would be unset by the scalefactor changes in ZoomToWindow
  178. this.zoomBasis = ZoomBasis.FitToWindow;
  179. break;
  180. case ZoomBasis.ScaleFactor:
  181. //PanelAutoScroll = true;
  182. break;
  183. default:
  184. throw new InvalidEnumArgumentException();
  185. }
  186. OnZoomBasisChanged();
  187. }
  188. }
  189. }
  190. protected override void HandleMouseWheel(Control sender, MouseEventArgs e)
  191. {
  192. if (Control.ModifierKeys == Keys.Control && !disableWheel && this.compositionSurface != null)
  193. {
  194. double mouseDelta = (double)e.Delta / 120.0f;
  195. Rectangle visibleDocBoundsStart = this.VisibleDocumentBounds;
  196. System.Drawing.Point mouseDocPt = this.MouseToDocument(sender, new System.Drawing.Point(e.X, e.Y));
  197. RectangleF visibleDocDocRect1 = this.VisibleDocumentRectangleF;
  198. PointF mouseNPt = new PointF(
  199. (mouseDocPt.X - visibleDocDocRect1.X) / visibleDocDocRect1.Width,
  200. (mouseDocPt.Y - visibleDocDocRect1.Y) / visibleDocDocRect1.Height);
  201. Rectangle rc = this.PanelClientRectangle;
  202. int width = this.SurfaceScrollableWidth;
  203. int height = this.SurfaceScrollableHeight;
  204. //获取鼠标在图像中的坐标定位
  205. double originX = 0.5;
  206. double originY = 0.5;
  207. double ptxInDoc = mouseDocPt.X * this.ScaleRatio;
  208. double ptyInDoc = mouseDocPt.Y * this.ScaleRatio;
  209. if (rc.Width < width)
  210. {
  211. originX = (ptxInDoc + this.PanelScrollPosition.X - 0.0) / width;
  212. }
  213. if (rc.Height < height)
  214. {
  215. originY = (ptyInDoc + this.PanelScrollPosition.Y - 0.0) / height;
  216. }
  217. const double factor = 1.12;
  218. double mouseFactor = Math.Pow(factor, Math.Abs(mouseDelta));
  219. if (e.Delta > 0)
  220. {
  221. this.ZoomIn(mouseFactor);
  222. }
  223. else if (e.Delta < 0)
  224. {
  225. this.ZoomOut(mouseFactor);
  226. }
  227. RectangleF visibleDocDocRect2 = this.VisibleDocumentRectangleF;
  228. PointF scrollPt2 = new PointF(
  229. mouseDocPt.X - visibleDocDocRect2.Width * mouseNPt.X,
  230. mouseDocPt.Y - visibleDocDocRect2.Height * mouseNPt.Y);
  231. this.DocumentScrollPositionF = scrollPt2;
  232. int width2 = this.SurfaceScrollableWidth;
  233. int height2 = this.SurfaceScrollableHeight;
  234. if ((rc.Width < width2 || rc.Height < height2) && (rc.Width < width || rc.Height < height))
  235. {
  236. //根据鼠标在图像中的坐标重新定位放大后的图像
  237. this.PanelScrollPosition = new System.Drawing.Point(
  238. (int)(width2 * originX - ptxInDoc + 0),
  239. (int)(height2 * originY - ptyInDoc + 0));
  240. }
  241. else if (rc.Width < width2 || rc.Height < height2)
  242. {
  243. this.PanelScrollPosition = new System.Drawing.Point((int)(width2 - rc.Width) / 2 + 0, (int)(height2 - rc.Height) / 2 + 0);
  244. }
  245. else
  246. {
  247. this.PanelScrollPosition = new System.Drawing.Point((int)(width2 - rc.Width) / 2 + 0, (int)(height2 - rc.Height) / 2 + 0);
  248. }
  249. Rectangle visibleDocBoundsEnd = this.VisibleDocumentBounds;
  250. if (visibleDocBoundsEnd != visibleDocBoundsStart)
  251. {
  252. // Make sure the screen updates, otherwise it can get a little funky looking
  253. this.Update();
  254. }
  255. }
  256. base.HandleMouseWheel(sender, e);
  257. }
  258. protected override void OnLoad(EventArgs e)
  259. {
  260. base.OnLoad(e);
  261. }
  262. public event EventHandler ActiveLayerChanged;
  263. protected void OnLayerChanged()
  264. {
  265. this.Focus();
  266. if (ActiveLayerChanged != null)
  267. {
  268. ActiveLayerChanged(this, EventArgs.Empty);
  269. }
  270. }
  271. /// <summary>
  272. /// 初始化底部按钮的各种事件
  273. /// </summary>
  274. private void InitializeBottomEvent()
  275. {
  276. /*//缩小按钮
  277. this.PanelBottom.zoomOutButton.Click += new EventHandler(ZoomOutButton_Click);
  278. //放大按钮
  279. this.PanelBottom.zoomInButton.Click += new EventHandler(zoomInButton_Click);*/
  280. }
  281. private void ZoomOutButton_Click(object sender, EventArgs e)
  282. {
  283. this.ZoomOut();
  284. }
  285. private void zoomInButton_Click(object sender, EventArgs e)
  286. {
  287. this.ZoomIn();
  288. }
  289. public event EventHandler ToolChanging;
  290. protected void OnToolChanging()
  291. {
  292. if (ToolChanging != null)
  293. {
  294. ToolChanging(this, EventArgs.Empty);
  295. }
  296. }
  297. public event EventHandler ToolChanged;
  298. protected void OnToolChanged()
  299. {
  300. if (ToolChanged != null)
  301. {
  302. ToolChanged(this, EventArgs.Empty);
  303. }
  304. }
  305. /// <summary>
  306. /// Updates any pertinent EXIF tags, such as "Creation Software", to be
  307. /// relevant or up-to-date.
  308. /// </summary>
  309. /// <param name="document"></param>
  310. private void UpdateExifTags(StitchDocument document)
  311. {
  312. PropertyItem pi = Exif.CreateAscii(ExifTagID.Software, PdnInfo.GetProductName(false));
  313. document.Metadata.ReplaceExifValues(ExifTagID.Software, new PropertyItem[1] { pi });
  314. }
  315. private sealed class OurProgressEvents : IFileTransferProgressEvents
  316. {
  317. private TransferProgressDialog progressDialog;
  318. private ICancelable cancelSink;
  319. private int itemCount = 0;
  320. private int itemOrdinal = 0;
  321. private string itemName = string.Empty;
  322. private long totalWork;
  323. private long totalProgress;
  324. private const int maxPBValue = 200; // granularity of progress bar. 100 means 1%, 200 means 0.5%, etc.
  325. private bool cancelRequested = false;
  326. private ManualResetEvent operationEnded = new ManualResetEvent(false);
  327. public OurProgressEvents()
  328. {
  329. }
  330. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "cancelSink")]
  331. public void BeginOperation(IWin32Window owner, EventHandler callWhenUIShown, ICancelable cancelSink)
  332. {
  333. if (this.progressDialog != null)
  334. {
  335. throw new InvalidOperationException("Operation already in progress");
  336. }
  337. this.progressDialog = new TransferProgressDialog();
  338. this.progressDialog.Text = PdnResources.GetString("ShowFileDialog.TransferProgress.Title");
  339. this.progressDialog.Icon = Utility.ImageToIcon(PdnResources.GetImageResource("Icons.MenuFileOpenIcon.png").Reference);
  340. this.progressDialog.Title = PdnResources.GetString("ShowFileDialog.ItemText.Initializing");
  341. this.progressDialog.ProgressBar.Style = ProgressBarStyle.Marquee;
  342. this.progressDialog.ProgressBar.Maximum = maxPBValue;
  343. this.progressDialog.CancelClicked +=
  344. delegate (object sender, EventArgs e)
  345. {
  346. this.cancelRequested = true;
  347. this.cancelSink.RequestCancel();
  348. UpdateUI();
  349. };
  350. EventHandler progressDialog_Shown =
  351. delegate (object sender, EventArgs e)
  352. {
  353. callWhenUIShown(this, EventArgs.Empty);
  354. };
  355. this.cancelSink = cancelSink;
  356. this.itemOrdinal = 0;
  357. this.cancelRequested = false;
  358. this.itemName = string.Empty;
  359. this.itemCount = 0;
  360. this.itemOrdinal = 0;
  361. this.totalProgress = 0;
  362. this.totalWork = 0;
  363. this.progressDialog.Shown += progressDialog_Shown;
  364. this.progressDialog.ShowDialog(owner);
  365. this.progressDialog.Shown -= progressDialog_Shown;
  366. this.progressDialog.Dispose();
  367. this.progressDialog = null;
  368. this.cancelSink = null;
  369. }
  370. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "itemCount")]
  371. public void SetItemCount(int itemCount)
  372. {
  373. if (this.progressDialog.InvokeRequired)
  374. {
  375. this.progressDialog.BeginInvoke(new Procedure<int>(SetItemCount), new object[] { itemCount });
  376. }
  377. else
  378. {
  379. this.itemCount = itemCount;
  380. UpdateUI();
  381. }
  382. }
  383. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "itemOrdinal")]
  384. public void SetItemOrdinal(int itemOrdinal)
  385. {
  386. if (this.progressDialog.InvokeRequired)
  387. {
  388. this.progressDialog.BeginInvoke(new Procedure<int>(SetItemOrdinal), new object[] { itemOrdinal });
  389. }
  390. else
  391. {
  392. this.itemOrdinal = itemOrdinal;
  393. this.totalWork = 0;
  394. this.totalProgress = 0;
  395. UpdateUI();
  396. }
  397. }
  398. public void SetItemInfo(string itemInfo)
  399. {
  400. if (this.progressDialog.InvokeRequired)
  401. {
  402. this.progressDialog.BeginInvoke(new Procedure<string>(SetItemInfo), new object[] { itemInfo });
  403. }
  404. else
  405. {
  406. this.itemName = itemInfo;
  407. UpdateUI();
  408. }
  409. }
  410. public void BeginItem()
  411. {
  412. if (this.progressDialog.InvokeRequired)
  413. {
  414. this.progressDialog.BeginInvoke(new Procedure(BeginItem), null);
  415. }
  416. else
  417. {
  418. this.progressDialog.ProgressBar.Style = ProgressBarStyle.Continuous;
  419. }
  420. }
  421. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "totalWork")]
  422. public void SetItemWorkTotal(long totalWork)
  423. {
  424. if (this.progressDialog.InvokeRequired)
  425. {
  426. this.progressDialog.BeginInvoke(new Procedure<long>(SetItemWorkTotal), new object[] { totalWork });
  427. }
  428. else
  429. {
  430. this.totalWork = totalWork;
  431. UpdateUI();
  432. }
  433. }
  434. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "totalProgress")]
  435. public void SetItemWorkProgress(long totalProgress)
  436. {
  437. if (this.progressDialog.InvokeRequired)
  438. {
  439. this.progressDialog.BeginInvoke(new Procedure<long>(SetItemWorkProgress), new object[] { totalProgress });
  440. }
  441. else
  442. {
  443. this.totalProgress = totalProgress;
  444. UpdateUI();
  445. }
  446. }
  447. public void EndItem(WorkItemResult result)
  448. {
  449. if (this.progressDialog.InvokeRequired)
  450. {
  451. this.progressDialog.BeginInvoke(new Procedure<WorkItemResult>(EndItem), new object[] { result });
  452. }
  453. else
  454. {
  455. }
  456. }
  457. public void EndOperation(OperationResult result)
  458. {
  459. if (this.progressDialog.InvokeRequired)
  460. {
  461. this.progressDialog.BeginInvoke(new Procedure<OperationResult>(EndOperation), new object[] { result });
  462. }
  463. else
  464. {
  465. this.progressDialog.Close();
  466. }
  467. }
  468. public WorkItemFailureAction ReportItemFailure(Exception ex)
  469. {
  470. if (this.progressDialog.InvokeRequired)
  471. {
  472. object result = this.progressDialog.Invoke(
  473. new Function<WorkItemFailureAction, Exception>(ReportItemFailure),
  474. new object[] { ex });
  475. return (WorkItemFailureAction)result;
  476. }
  477. else
  478. {
  479. WorkItemFailureAction result;
  480. result = ShowFileTransferFailedDialog(ex);
  481. return result;
  482. }
  483. }
  484. private WorkItemFailureAction ShowFileTransferFailedDialog(Exception ex)
  485. {
  486. WorkItemFailureAction result;
  487. Icon formIcon = this.progressDialog.Icon;
  488. string formTitle = PdnResources.GetString("ShowFileDialog.ItemFailureDialog.Title");
  489. Image taskImage = PdnResources.GetImageResource("Icons.WarningIcon.png").Reference;
  490. string introTextFormat = PdnResources.GetString("ShowFileDialog.ItemFailureDialog.IntroText.Format");
  491. string introText = string.Format(introTextFormat, ex.Message);
  492. TaskButton retryTB = new TaskButton(
  493. PdnResources.GetImageResource("Icons.MenuImageRotate90CWIcon.png").Reference,
  494. PdnResources.GetString("ShowFileDialog.RetryTB.ActionText"),
  495. PdnResources.GetString("ShowFileDialog.RetryTB.ExplanationText"));
  496. TaskButton skipTB = new TaskButton(
  497. PdnResources.GetImageResource("Icons.HistoryFastForwardIcon.png").Reference,
  498. PdnResources.GetString("ShowFileDialog.SkipTB.ActionText"),
  499. PdnResources.GetString("ShowFileDialog.SkipTB.ExplanationText"));
  500. TaskButton cancelTB = new TaskButton(
  501. PdnResources.GetImageResource("Icons.CancelIcon.png").Reference,
  502. PdnResources.GetString("ShowFileDialog.CancelTB.ActionText"),
  503. PdnResources.GetString("ShowFileDialog.CancelTB.ExplanationText"));
  504. List<TaskButton> taskButtons = new List<TaskButton>();
  505. taskButtons.Add(retryTB);
  506. // Only have the Skip button if there is more than 1 item being transferred.
  507. // If only 1 item is begin transferred, Skip and Cancel are essentially synonymous.
  508. if (this.itemCount > 1)
  509. {
  510. taskButtons.Add(skipTB);
  511. }
  512. taskButtons.Add(cancelTB);
  513. int width96 = (TaskDialog.DefaultPixelWidth96Dpi * 4) / 3; // 33% wider
  514. TaskButton clickedTB = TaskDialog.Show(
  515. this.progressDialog,
  516. formIcon,
  517. formTitle,
  518. taskImage,
  519. true,
  520. introText,
  521. taskButtons.ToArray(),
  522. retryTB,
  523. cancelTB,
  524. width96,
  525. false,
  526. 0,
  527. out bool unuse);
  528. if (clickedTB == retryTB)
  529. {
  530. result = WorkItemFailureAction.RetryItem;
  531. }
  532. else if (clickedTB == skipTB)
  533. {
  534. result = WorkItemFailureAction.SkipItem;
  535. }
  536. else
  537. {
  538. result = WorkItemFailureAction.CancelOperation;
  539. }
  540. return result;
  541. }
  542. private void UpdateUI()
  543. {
  544. int itemCount2 = Math.Max(1, this.itemCount);
  545. double startValue = (double)this.itemOrdinal / (double)itemCount2;
  546. double endValue = (double)(this.itemOrdinal + 1) / (double)itemCount2;
  547. long totalWork2 = Math.Max(1, this.totalWork);
  548. double lerp = (double)this.totalProgress / (double)totalWork2;
  549. double newValue = Utility.Lerp(startValue, endValue, lerp);
  550. int newValueInt = (int)Math.Ceiling(maxPBValue * newValue);
  551. if (this.cancelRequested)
  552. {
  553. this.progressDialog.CancelEnabled = false;
  554. this.progressDialog.Title = PdnResources.GetString("ShowFileDialog.ItemText.Canceling");
  555. this.progressDialog.ProcessMsg = string.Empty;
  556. this.progressDialog.ProgressBar.Style = ProgressBarStyle.Marquee;
  557. }
  558. else
  559. {
  560. this.progressDialog.CancelEnabled = true;
  561. this.progressDialog.Title = this.itemName;
  562. string progressFormat = PdnResources.GetString("ShowFileDialog.ProgressText.Format");
  563. string progressText = string.Format(progressFormat, this.itemOrdinal + 1, this.itemCount);
  564. this.progressDialog.ProcessMsg = progressText;
  565. this.progressDialog.ProgressBar.Style = ProgressBarStyle.Continuous;
  566. this.progressDialog.ProgressBar.Value = newValueInt;
  567. }
  568. }
  569. }
  570. /// <summary>
  571. /// 分栏显示禁止滚动改变图片大小
  572. /// </summary>
  573. bool disableWheel = false;
  574. DateTime _time;
  575. protected override void MouseEvent_Move(object sender, MouseEventArgs e)
  576. {
  577. if (this.compositionSurface != null)
  578. {
  579. if ((DateTime.Now - _time).TotalMilliseconds > 20)
  580. {
  581. _time = DateTime.Now;
  582. base.MouseEvent_Move(sender, e);
  583. }
  584. }
  585. }
  586. protected override void MouseEvent_Down(object sender, MouseEventArgs e)
  587. {
  588. if (tools != null)
  589. {
  590. //tools[activeTool].OnMouseDown(this, e);
  591. tools[_activeTool].InvokeMember("OnMouseDown",
  592. BindingFlags.Public |
  593. BindingFlags.Static |
  594. BindingFlags.InvokeMethod,
  595. null,
  596. null,
  597. new object[2] { this, e });
  598. }
  599. }
  600. }
  601. }