using PaintDotNet.SystemLayer; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using System.Reflection; using System.Threading; using System.Windows.Forms; namespace PaintDotNet { /// /// 抽出来在图像拼接弹窗里面使用 /// internal class DocumentStitchWindow : DocumentStitchView { private ZoomBasis zoomBasis; protected override void OnLayout(LayoutEventArgs e) { if (this.zoomBasis == ZoomBasis.FitToWindow) { ZoomToPreviewWindow(); // This bizarre ordering of setting PanelAutoScroll prevents some very weird layout/scroll-without-scrollbars stuff. PanelAutoScroll = true; PanelAutoScroll = false; } base.OnLayout(e); } protected override void OnResize(EventArgs e) { if (this.zoomBasis == ZoomBasis.FitToWindow) { PerformLayout(); } base.OnResize(e); } public DocumentStitchWindow() { this.InitToolsAndManager(); InitializeComponent(); this.zoomBasis = ZoomBasis.FitToWindow; InitializeBottomEvent(); this.MouseEvent_Del(null, null); } private void InitializeComponent() { } protected override void Dispose(bool disposing) { base.Dispose(disposing); } public override void ZoomIn() { this.ZoomBasis = ZoomBasis.ScaleFactor; base.ZoomIn(); } public override void ZoomIn(double factor) { this.ZoomBasis = ZoomBasis.ScaleFactor; base.ZoomIn(factor); } public override void ZoomOut() { this.ZoomBasis = ZoomBasis.ScaleFactor; base.ZoomOut(); } public override void ZoomOut(double factor) { this.ZoomBasis = ZoomBasis.ScaleFactor; base.ZoomOut(factor); } public event EventHandler ZoomBasisChanging; protected virtual void OnZoomBasisChanging() { if (ZoomBasisChanging != null) { ZoomBasisChanging(this, EventArgs.Empty); } } public event EventHandler ZoomBasisChanged; protected virtual void OnZoomBasisChanged() { if (ZoomBasisChanged != null) { ZoomBasisChanged(this, EventArgs.Empty); } } //public int OffsetH //{ // set // { // this.panel.AutoScrollPosition.X = value; // } //} /// /// 持有mat的有效区域 /// public OpenCvSharp.Mat StitchMat { get { if (this.StitchDocument == null || this.StitchDocument.surface == null) return null; return this.StitchDocument.surface.StitchMat; } } /// /// 持有mat的绘制区域 /// public Rectangle StitchBounds { get { return this.StitchDocument.surface.stitchBounds; } set { this.StitchDocument.surface.stitchBounds = value; } } /// /// 持有mat的绘制区域 /// public int StitchWidth { get { return this.StitchDocument.surface.StitchWidth; } } /// /// 持有mat的绘制区域 /// public int StitchHeight { get { return this.StitchDocument.surface.StitchHeight; } } /// /// 合适大小 /// public void ZoomToPreviewWindow() { if (this.StitchDocument != null) { Rectangle max = ClientRectangleMax; ScaleFactor zoom = ScaleFactor.Min(max.Width - 10, this.StitchBounds.Width, max.Height - 10, this.StitchBounds.Height, ScaleFactor.MinValue); ScaleFactor min = ScaleFactor.Min(zoom, ScaleFactor.OneToOne); this.ScaleFactor = min; } } public ZoomBasis ZoomBasis { get { return this.zoomBasis; } set { if (this.zoomBasis != value) { OnZoomBasisChanging(); this.zoomBasis = value; //this.panel.AutoScrollOffset switch (this.zoomBasis) { case ZoomBasis.FitToWindow: ZoomToPreviewWindow(); //// Enable PanelAutoScroll only long enough to recenter the view //PanelAutoScroll = true; //PanelAutoScroll = false; // this would be unset by the scalefactor changes in ZoomToWindow this.zoomBasis = ZoomBasis.FitToWindow; break; case ZoomBasis.ScaleFactor: //PanelAutoScroll = true; break; default: throw new InvalidEnumArgumentException(); } OnZoomBasisChanged(); } } } protected override void HandleMouseWheel(Control sender, MouseEventArgs e) { if (Control.ModifierKeys == Keys.Control && !disableWheel && this.compositionSurface != null) { double mouseDelta = (double)e.Delta / 120.0f; Rectangle visibleDocBoundsStart = this.VisibleDocumentBounds; System.Drawing.Point mouseDocPt = this.MouseToDocument(sender, new System.Drawing.Point(e.X, e.Y)); RectangleF visibleDocDocRect1 = this.VisibleDocumentRectangleF; PointF mouseNPt = new PointF( (mouseDocPt.X - visibleDocDocRect1.X) / visibleDocDocRect1.Width, (mouseDocPt.Y - visibleDocDocRect1.Y) / visibleDocDocRect1.Height); Rectangle rc = this.PanelClientRectangle; int width = this.SurfaceScrollableWidth; int height = this.SurfaceScrollableHeight; //获取鼠标在图像中的坐标定位 double originX = 0.5; double originY = 0.5; double ptxInDoc = mouseDocPt.X * this.ScaleRatio; double ptyInDoc = mouseDocPt.Y * this.ScaleRatio; if (rc.Width < width) { originX = (ptxInDoc + this.PanelScrollPosition.X - 0.0) / width; } if (rc.Height < height) { originY = (ptyInDoc + this.PanelScrollPosition.Y - 0.0) / height; } const double factor = 1.12; double mouseFactor = Math.Pow(factor, Math.Abs(mouseDelta)); if (e.Delta > 0) { this.ZoomIn(mouseFactor); } else if (e.Delta < 0) { this.ZoomOut(mouseFactor); } RectangleF visibleDocDocRect2 = this.VisibleDocumentRectangleF; PointF scrollPt2 = new PointF( mouseDocPt.X - visibleDocDocRect2.Width * mouseNPt.X, mouseDocPt.Y - visibleDocDocRect2.Height * mouseNPt.Y); this.DocumentScrollPositionF = scrollPt2; int width2 = this.SurfaceScrollableWidth; int height2 = this.SurfaceScrollableHeight; if ((rc.Width < width2 || rc.Height < height2) && (rc.Width < width || rc.Height < height)) { //根据鼠标在图像中的坐标重新定位放大后的图像 this.PanelScrollPosition = new System.Drawing.Point( (int)(width2 * originX - ptxInDoc + 0), (int)(height2 * originY - ptyInDoc + 0)); } else if (rc.Width < width2 || rc.Height < height2) { this.PanelScrollPosition = new System.Drawing.Point((int)(width2 - rc.Width) / 2 + 0, (int)(height2 - rc.Height) / 2 + 0); } else { this.PanelScrollPosition = new System.Drawing.Point((int)(width2 - rc.Width) / 2 + 0, (int)(height2 - rc.Height) / 2 + 0); } Rectangle visibleDocBoundsEnd = this.VisibleDocumentBounds; if (visibleDocBoundsEnd != visibleDocBoundsStart) { // Make sure the screen updates, otherwise it can get a little funky looking this.Update(); } } base.HandleMouseWheel(sender, e); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); } public event EventHandler ActiveLayerChanged; protected void OnLayerChanged() { this.Focus(); if (ActiveLayerChanged != null) { ActiveLayerChanged(this, EventArgs.Empty); } } /// /// 初始化底部按钮的各种事件 /// private void InitializeBottomEvent() { /*//缩小按钮 this.PanelBottom.zoomOutButton.Click += new EventHandler(ZoomOutButton_Click); //放大按钮 this.PanelBottom.zoomInButton.Click += new EventHandler(zoomInButton_Click);*/ } private void ZoomOutButton_Click(object sender, EventArgs e) { this.ZoomOut(); } private void zoomInButton_Click(object sender, EventArgs e) { this.ZoomIn(); } public event EventHandler ToolChanging; protected void OnToolChanging() { if (ToolChanging != null) { ToolChanging(this, EventArgs.Empty); } } public event EventHandler ToolChanged; protected void OnToolChanged() { if (ToolChanged != null) { ToolChanged(this, EventArgs.Empty); } } /// /// Updates any pertinent EXIF tags, such as "Creation Software", to be /// relevant or up-to-date. /// /// private void UpdateExifTags(StitchDocument document) { PropertyItem pi = Exif.CreateAscii(ExifTagID.Software, PdnInfo.GetProductName(false)); document.Metadata.ReplaceExifValues(ExifTagID.Software, new PropertyItem[1] { pi }); } private sealed class OurProgressEvents : IFileTransferProgressEvents { private TransferProgressDialog progressDialog; private ICancelable cancelSink; private int itemCount = 0; private int itemOrdinal = 0; private string itemName = string.Empty; private long totalWork; private long totalProgress; private const int maxPBValue = 200; // granularity of progress bar. 100 means 1%, 200 means 0.5%, etc. private bool cancelRequested = false; private ManualResetEvent operationEnded = new ManualResetEvent(false); public OurProgressEvents() { } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "cancelSink")] public void BeginOperation(IWin32Window owner, EventHandler callWhenUIShown, ICancelable cancelSink) { if (this.progressDialog != null) { throw new InvalidOperationException("Operation already in progress"); } this.progressDialog = new TransferProgressDialog(); this.progressDialog.Text = PdnResources.GetString("ShowFileDialog.TransferProgress.Title"); this.progressDialog.Icon = Utility.ImageToIcon(PdnResources.GetImageResource("Icons.MenuFileOpenIcon.png").Reference); this.progressDialog.Title = PdnResources.GetString("ShowFileDialog.ItemText.Initializing"); this.progressDialog.ProgressBar.Style = ProgressBarStyle.Marquee; this.progressDialog.ProgressBar.Maximum = maxPBValue; this.progressDialog.CancelClicked += delegate (object sender, EventArgs e) { this.cancelRequested = true; this.cancelSink.RequestCancel(); UpdateUI(); }; EventHandler progressDialog_Shown = delegate (object sender, EventArgs e) { callWhenUIShown(this, EventArgs.Empty); }; this.cancelSink = cancelSink; this.itemOrdinal = 0; this.cancelRequested = false; this.itemName = string.Empty; this.itemCount = 0; this.itemOrdinal = 0; this.totalProgress = 0; this.totalWork = 0; this.progressDialog.Shown += progressDialog_Shown; this.progressDialog.ShowDialog(owner); this.progressDialog.Shown -= progressDialog_Shown; this.progressDialog.Dispose(); this.progressDialog = null; this.cancelSink = null; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "itemCount")] public void SetItemCount(int itemCount) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(SetItemCount), new object[] { itemCount }); } else { this.itemCount = itemCount; UpdateUI(); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "itemOrdinal")] public void SetItemOrdinal(int itemOrdinal) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(SetItemOrdinal), new object[] { itemOrdinal }); } else { this.itemOrdinal = itemOrdinal; this.totalWork = 0; this.totalProgress = 0; UpdateUI(); } } public void SetItemInfo(string itemInfo) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(SetItemInfo), new object[] { itemInfo }); } else { this.itemName = itemInfo; UpdateUI(); } } public void BeginItem() { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(BeginItem), null); } else { this.progressDialog.ProgressBar.Style = ProgressBarStyle.Continuous; } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "totalWork")] public void SetItemWorkTotal(long totalWork) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(SetItemWorkTotal), new object[] { totalWork }); } else { this.totalWork = totalWork; UpdateUI(); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "totalProgress")] public void SetItemWorkProgress(long totalProgress) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(SetItemWorkProgress), new object[] { totalProgress }); } else { this.totalProgress = totalProgress; UpdateUI(); } } public void EndItem(WorkItemResult result) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(EndItem), new object[] { result }); } else { } } public void EndOperation(OperationResult result) { if (this.progressDialog.InvokeRequired) { this.progressDialog.BeginInvoke(new Procedure(EndOperation), new object[] { result }); } else { this.progressDialog.Close(); } } public WorkItemFailureAction ReportItemFailure(Exception ex) { if (this.progressDialog.InvokeRequired) { object result = this.progressDialog.Invoke( new Function(ReportItemFailure), new object[] { ex }); return (WorkItemFailureAction)result; } else { WorkItemFailureAction result; result = ShowFileTransferFailedDialog(ex); return result; } } private WorkItemFailureAction ShowFileTransferFailedDialog(Exception ex) { WorkItemFailureAction result; Icon formIcon = this.progressDialog.Icon; string formTitle = PdnResources.GetString("ShowFileDialog.ItemFailureDialog.Title"); Image taskImage = PdnResources.GetImageResource("Icons.WarningIcon.png").Reference; string introTextFormat = PdnResources.GetString("ShowFileDialog.ItemFailureDialog.IntroText.Format"); string introText = string.Format(introTextFormat, ex.Message); TaskButton retryTB = new TaskButton( PdnResources.GetImageResource("Icons.MenuImageRotate90CWIcon.png").Reference, PdnResources.GetString("ShowFileDialog.RetryTB.ActionText"), PdnResources.GetString("ShowFileDialog.RetryTB.ExplanationText")); TaskButton skipTB = new TaskButton( PdnResources.GetImageResource("Icons.HistoryFastForwardIcon.png").Reference, PdnResources.GetString("ShowFileDialog.SkipTB.ActionText"), PdnResources.GetString("ShowFileDialog.SkipTB.ExplanationText")); TaskButton cancelTB = new TaskButton( PdnResources.GetImageResource("Icons.CancelIcon.png").Reference, PdnResources.GetString("ShowFileDialog.CancelTB.ActionText"), PdnResources.GetString("ShowFileDialog.CancelTB.ExplanationText")); List taskButtons = new List(); taskButtons.Add(retryTB); // Only have the Skip button if there is more than 1 item being transferred. // If only 1 item is begin transferred, Skip and Cancel are essentially synonymous. if (this.itemCount > 1) { taskButtons.Add(skipTB); } taskButtons.Add(cancelTB); int width96 = (TaskDialog.DefaultPixelWidth96Dpi * 4) / 3; // 33% wider TaskButton clickedTB = TaskDialog.Show( this.progressDialog, formIcon, formTitle, taskImage, true, introText, taskButtons.ToArray(), retryTB, cancelTB, width96, false, 0, out bool unuse); if (clickedTB == retryTB) { result = WorkItemFailureAction.RetryItem; } else if (clickedTB == skipTB) { result = WorkItemFailureAction.SkipItem; } else { result = WorkItemFailureAction.CancelOperation; } return result; } private void UpdateUI() { int itemCount2 = Math.Max(1, this.itemCount); double startValue = (double)this.itemOrdinal / (double)itemCount2; double endValue = (double)(this.itemOrdinal + 1) / (double)itemCount2; long totalWork2 = Math.Max(1, this.totalWork); double lerp = (double)this.totalProgress / (double)totalWork2; double newValue = Utility.Lerp(startValue, endValue, lerp); int newValueInt = (int)Math.Ceiling(maxPBValue * newValue); if (this.cancelRequested) { this.progressDialog.CancelEnabled = false; this.progressDialog.Title = PdnResources.GetString("ShowFileDialog.ItemText.Canceling"); this.progressDialog.ProcessMsg = string.Empty; this.progressDialog.ProgressBar.Style = ProgressBarStyle.Marquee; } else { this.progressDialog.CancelEnabled = true; this.progressDialog.Title = this.itemName; string progressFormat = PdnResources.GetString("ShowFileDialog.ProgressText.Format"); string progressText = string.Format(progressFormat, this.itemOrdinal + 1, this.itemCount); this.progressDialog.ProcessMsg = progressText; this.progressDialog.ProgressBar.Style = ProgressBarStyle.Continuous; this.progressDialog.ProgressBar.Value = newValueInt; } } } /// /// 分栏显示禁止滚动改变图片大小 /// bool disableWheel = false; DateTime _time; protected override void MouseEvent_Move(object sender, MouseEventArgs e) { if (this.compositionSurface != null) { if ((DateTime.Now - _time).TotalMilliseconds > 20) { _time = DateTime.Now; base.MouseEvent_Move(sender, e); } } } protected override void MouseEvent_Down(object sender, MouseEventArgs e) { if (tools != null) { //tools[activeTool].OnMouseDown(this, e); tools[_activeTool].InvokeMember("OnMouseDown", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[2] { this, e }); } } } }