using PaintDotNet.Base.CommTool; using PaintDotNet.Base.Functionodel; using PaintDotNet.SystemLayer; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; using System.Resources; using System.Threading; using System.Windows.Forms; namespace PaintDotNet { /// /// This Form class is used to fix a few bugs in Windows Forms, and to add a few performance /// enhancements, such as disabling opacity != 1.0 when running in a remote TS/RD session. /// We derive from this class instead of Windows.Forms.Form directly. /// public class PdnBaseForm : Form, ISnapManagerHost { public static string xmlPath = ""; static PdnBaseForm() { Application.EnterThreadModal += new EventHandler(Application_EnterThreadModal); Application.LeaveThreadModal += new EventHandler(Application_LeaveThreadModal); Application_EnterThreadModal(null, EventArgs.Empty); } // This set keeps track of forms which cannot be the current modal form. private static Stack> parentModalForms = new Stack>(); private static bool IsInParentModalForms(Form form) { foreach (List
formList in parentModalForms) { foreach (Form parentModalForm in formList) { if (parentModalForm == form) { return true; } } } return false; } private static List GetAllPeerForms(Form form) { if (form == null) { return new List(); } if (form.Owner != null) { return GetAllPeerForms(form.Owner); } List forms = new List(); forms.Add(form); forms.AddRange(form.OwnedForms); return forms; } private static void Application_EnterThreadModal(object sender, EventArgs e) { Form activeForm = Form.ActiveForm; List allPeerForms = GetAllPeerForms(activeForm); parentModalForms.Push(allPeerForms); } private static void Application_LeaveThreadModal(object sender, EventArgs e) { parentModalForms.Pop(); } protected override void OnShown(EventArgs e) { isShown = true; Tracing.LogFeature("ShowDialog(" + GetType().FullName + ")"); base.OnShown(e); } public bool IsShown { get { return this.isShown; } } private bool isShown = false; private bool enableOpacity = true; private double ourOpacity = 1.0; // store opacity setting so that when we go from disabled->enabled opacity we can set the correct value private SnapManager snapManager = null; private System.ComponentModel.IContainer components; private bool instanceEnableOpacity = true; private static bool globalEnableOpacity = true; private FormEx formEx; private bool processFormHotKeyMutex = false; // if we're already processing a form hotkey, don't let other hotkeys execute. private static Dictionary> hotkeyRegistrar = null; /// /// 分析设置存储信息 /// protected AnalyzeSettingModel analyzeSettingModel; public AnalyzeSettingModel AnalyzeSettingModel { get { return this.analyzeSettingModel; } set { this.analyzeSettingModel = value; } } /// /// Registers a form-wide hot key, and a callback for when the key is pressed. /// The callback must be an instance method on a Control. Whatever Form the Control /// is on will process the hotkey, as long as the Form is derived from PdnBaseForm. /// public static void RegisterFormHotKey(Keys keys, Function callback) { IComponent targetAsComponent = callback.Target as IComponent; IHotKeyTarget targetAsHotKeyTarget = callback.Target as IHotKeyTarget; if (targetAsComponent == null && targetAsHotKeyTarget == null) { throw new ArgumentException("target instance must implement IComponent or IHotKeyTarget", "callback"); } if (hotkeyRegistrar == null) { hotkeyRegistrar = new Dictionary>(); } Function theDelegate = null; if (hotkeyRegistrar.ContainsKey(keys)) { theDelegate = hotkeyRegistrar[keys]; theDelegate += callback; hotkeyRegistrar[keys] = theDelegate; } else { theDelegate = new Function(callback); hotkeyRegistrar.Add(keys, theDelegate); } if (targetAsComponent != null) { targetAsComponent.Disposed += TargetAsComponent_Disposed; } else { targetAsHotKeyTarget.Disposed += TargetAsHotKeyTarget_Disposed; } } private bool ShouldProcessHotKey(Keys keys) { Keys keyOnly = keys & ~Keys.Modifiers; if (keyOnly == Keys.Back || keyOnly == Keys.Delete || keyOnly == Keys.Left || keyOnly == Keys.Right || keyOnly == Keys.Up || keyOnly == Keys.Down || keys == (Keys.Control | Keys.A) || // select all keys == (Keys.Control | Keys.Z) || // undo keys == (Keys.Control | Keys.Y) || // redo keys == (Keys.Control | Keys.X) || // cut keys == (Keys.Control | Keys.C) || // copy keys == (Keys.Control | Keys.V) || // paste keys == (Keys.Shift | Keys.Delete) || // cut (left-handed) keys == (Keys.Control | Keys.Insert) || // copy (left-handed) keys == (Keys.Shift | Keys.Insert) // paste (left-handed) ) { Control focused = Utility.FindFocus(); if (focused is TextBox || focused is ComboBox || focused is UpDownBase) { return false; } } return true; } private static void TargetAsComponent_Disposed(object sender, EventArgs e) { ((IComponent)sender).Disposed -= TargetAsComponent_Disposed; RemoveDisposedTarget(sender); } private static void TargetAsHotKeyTarget_Disposed(object sender, EventArgs e) { ((IHotKeyTarget)sender).Disposed -= TargetAsHotKeyTarget_Disposed; RemoveDisposedTarget(sender); } static void RemoveDisposedTarget(object sender) { // Control was disposed, but it never unregistered for its hotkeys! List keysList = new List(hotkeyRegistrar.Keys); foreach (Keys keys in keysList) { Function theMultiDelegate = hotkeyRegistrar[keys]; foreach (Delegate theDelegate in theMultiDelegate.GetInvocationList()) { if (object.ReferenceEquals(theDelegate.Target, sender)) { UnregisterFormHotKey(keys, (Function)theDelegate); } } } } public static void UnregisterFormHotKey(Keys keys, Function callback) { if (hotkeyRegistrar != null) { //Function theDelegate = hotkeyRegistrar[keys]; //theDelegate -= callback; //hotkeyRegistrar[keys] = theDelegate; IComponent targetAsComponent = callback.Target as IComponent; if (targetAsComponent != null) { targetAsComponent.Disposed -= TargetAsComponent_Disposed; } IHotKeyTarget targetAsHotKeyTarget = callback.Target as IHotKeyTarget; if (targetAsHotKeyTarget != null) { targetAsHotKeyTarget.Disposed -= TargetAsHotKeyTarget_Disposed; } if (hotkeyRegistrar.ContainsKey(keys)/*theDelegate.GetInvocationList().Length == 0*/) { Function theDelegate = hotkeyRegistrar[keys]; theDelegate -= callback; hotkeyRegistrar.Remove(keys); } if (hotkeyRegistrar.Count == 0) { hotkeyRegistrar = null; } } } public void Flash() { UI.FlashForm(this); } public void RestoreWindow() { if (WindowState == FormWindowState.Minimized) { UI.RestoreWindow(this); } } /// /// Returns the currently active modal form if the process is in the foreground and is active. /// /// /// If Form.ActiveForm is modeless, we search up the chain of owner forms /// to find its modeless owner form. /// public static Form CurrentModalForm { get { Form theForm = Form.ActiveForm; while (theForm != null && !theForm.Modal && theForm.Owner != null) { theForm = theForm.Owner; } return theForm; } } /// /// Gets whether the current form is the processes' top level modal form. /// public bool IsCurrentModalForm { get { if (IsInParentModalForms(this)) { return false; } if (this.ContainsFocus) { return true; } foreach (Form ownedForm in this.OwnedForms) { if (ownedForm.ContainsFocus) { return true; } } return (this == CurrentModalForm); } } private bool IsTargetFormActive(object target) { Control targetControl = null; if (targetControl == null) { Control asControl = target as Control; if (asControl != null) { targetControl = asControl; } } if (targetControl == null) { IFormAssociate asIFormAssociate = target as IFormAssociate; if (asIFormAssociate != null) { targetControl = asIFormAssociate.AssociatedForm; } } // target is not a control, or a type of non-control that we recognize as hosted by a control if (targetControl == null) { return false; } Form targetForm = targetControl.FindForm(); // target is not on a form if (targetForm == null) { return false; } // is the target on the currently active form? Form activeModalForm = CurrentModalForm; if (targetForm == activeModalForm) { return true; } // Nope. return false; } private static object GetConcreteTarget(object target) { Delegate asDelegate = target as Delegate; if (asDelegate == null) { return target; } else { return GetConcreteTarget(asDelegate.Target); } } protected virtual bool ProcessFormHotKey(Keys keyData) { bool processed = false; if (this.processFormHotKeyMutex) { processed = true; } else { this.processFormHotKeyMutex = true; try { if (hotkeyRegistrar != null && hotkeyRegistrar.ContainsKey(keyData)) { Function theDelegate = hotkeyRegistrar[keyData]; Delegate[] invokeList = theDelegate.GetInvocationList(); for (int i = invokeList.Length - 1; i >= 0; --i) { Function invokeMe = (Function)invokeList[i]; object concreteTarget = GetConcreteTarget(invokeMe.Target); if (IsTargetFormActive(concreteTarget)) { bool result = invokeMe(keyData); if (result) { // The callback handled the key. processed = false; break; } } } } } finally { this.processFormHotKeyMutex = false; } } return processed; } private void OnProcessCmdKeyRelay(object sender, FormEx.ProcessCmdKeyEventArgs e) { bool handled = e.Handled; if (!handled) { handled = ProcessCmdKeyData(e.KeyData); e.Handled = handled; } } public bool RelayProcessCmdKey(ref Message msg, Keys keyData) { return ProcessCmdKeyData(keyData); } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { bool processed = ProcessCmdKeyData(keyData); if (!processed) { processed = base.ProcessCmdKey(ref msg, keyData); } return processed; } private bool ProcessCmdKeyData(Keys keyData) { bool shouldHandle = ShouldProcessHotKey(keyData); if (shouldHandle) { bool processed = ProcessFormHotKey(keyData); return processed; } else { return false; } } public static void UpdateAllForms() { try { foreach (Form form in Application.OpenForms) { try { form.Update(); } catch (Exception) { } } } catch (InvalidOperationException) { } } /*protected override void OnHelpRequested(HelpEventArgs hevent) { if (!hevent.Handled) { Utility.ShowHelp(this); hevent.Handled = true; } base.OnHelpRequested(hevent); }*/ public static EventHandler EnableOpacityChanged; private static void OnEnableOpacityChanged() { if (EnableOpacityChanged != null) { EnableOpacityChanged(null, EventArgs.Empty); } } public bool EnableInstanceOpacity { get { return instanceEnableOpacity; } set { instanceEnableOpacity = value; this.DecideOpacitySetting(); } } /// /// Gets or sets a flag that enables or disables opacity for all PdnBaseForm instances. /// If a particular form's EnableInstanceOpacity property is false, that will override /// this property being 'true'. /// public static bool EnableOpacity { get { return globalEnableOpacity; } set { globalEnableOpacity = value; OnEnableOpacityChanged(); } } /// /// Gets or sets the titlebar rendering behavior for when the form is deactivated. /// /// /// If this property is false, the titlebar will be rendered in a different color when the form /// is inactive as opposed to active. If this property is true, it will always render with the /// active style. If the whole application is deactivated, the title bar will still be drawn in /// an inactive state. /// public bool ForceActiveTitleBar { get { return this.formEx.ForceActiveTitleBar; } set { this.formEx.ForceActiveTitleBar = value; } } private ThreadPriority originalPriority; protected override void OnScroll(ScrollEventArgs se) { Thread.CurrentThread.Priority = this.originalPriority; base.OnScroll(se); } public PdnBaseForm() { this.originalPriority = Thread.CurrentThread.Priority; Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; UI.InitScaling(this); this.SuspendLayout(); InitializeComponent(); this.formEx = new PaintDotNet.SystemLayer.FormEx(this, new RealParentWndProcDelegate(this.RealWndProc)); this.Controls.Add(this.formEx); this.formEx.Visible = false; DecideOpacitySetting(); this.ResumeLayout(false); this.formEx.ProcessCmdKeyRelay += OnProcessCmdKeyRelay; } protected override void OnLoad(EventArgs e) { if (!this.DesignMode) { LoadResources(); } base.OnLoad(e); } public virtual void LoadResources() { if (!this.DesignMode) { string stringName = this.Name + ".Localized"; string stringValue = StringsResourceManager.GetString(stringName); if (stringValue != null) { try { bool boolValue = bool.Parse(stringValue); if (boolValue) { LoadLocalizedResources(); } } catch (Exception) { } } } } protected virtual ResourceManager StringsResourceManager { get { return PdnResources.Strings; } } private void LoadLocalizedResources() { LoadLocalizedResources(this.Name, this); } private void ParsePair(string theString, out int x, out int y) { string[] split = theString.Split(','); x = int.Parse(split[0]); y = int.Parse(split[1]); } private void LoadLocalizedResources(string baseName, Control control) { // Text string textStringName = baseName + ".Text"; string textString = this.StringsResourceManager.GetString(textStringName); if (textString != null) { control.Text = textString; } // Location string locationStringName = baseName + ".Location"; string locationString = this.StringsResourceManager.GetString(locationStringName); if (locationString != null) { try { int x; int y; ParsePair(locationString, out x, out y); control.Location = new Point(x, y); } catch (Exception ex) { Tracing.Ping(locationStringName + " is invalid: " + locationString + ", exception: " + ex.ToString()); } } // Size string sizeStringName = baseName + ".Size"; string sizeString = this.StringsResourceManager.GetString(sizeStringName); if (sizeString != null) { try { int width; int height; ParsePair(sizeString, out width, out height); control.Size = new Size(width, height); } catch (Exception ex) { Tracing.Ping(sizeStringName + " is invalid: " + sizeString + ", exception: " + ex.ToString()); } } // Recurse foreach (Control child in control.Controls) { if (child.Name == null || child.Name.Length > 0) { string newBaseName = baseName + "." + child.Name; LoadLocalizedResources(newBaseName, child); } else { Tracing.Ping("Name property not set for an instance of " + child.GetType().Name + " within " + baseName); } } } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); if (!e.Cancel) { this.ForceActiveTitleBar = false; } } private void EnableOpacityChangedHandler(object sender, EventArgs e) { DecideOpacitySetting(); } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); PdnBaseForm.EnableOpacityChanged += new EventHandler(EnableOpacityChangedHandler); UserSessions.SessionChanged += new EventHandler(UserSessions_SessionChanged); DecideOpacitySetting(); } protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); PdnBaseForm.EnableOpacityChanged -= new EventHandler(EnableOpacityChangedHandler); UserSessions.SessionChanged -= new EventHandler(UserSessions_SessionChanged); } /// /// Clean up any resources being used. /// protected override void Dispose(bool disposing) { if (disposing) { if (components != null) { components.Dispose(); components = null; } } base.Dispose(disposing); } /// /// Sets the opacity of the form. /// /// The new opacity value. /// /// Depending on the system configuration, this request may be ignored. For example, /// when running within a Terminal Service (or Remote Desktop) session, opacity will /// always be set to 1.0 for performance reasons. /// public new double Opacity { get { return this.ourOpacity; } set { if (enableOpacity) { // Bypassing Form.Opacity eliminates a "black flickering" that occurs when // the form transitions from Opacity=1.0 to Opacity != 1.0, or vice versa. // It appears to be a result of toggling the WS_EX_LAYERED style, or the // fact that Form.Opacity re-applies visual styles when this value transition // takes place. SystemLayer.UI.SetFormOpacity(this, value); } this.ourOpacity = value; } } /// /// Decides whether or not to have opacity be enabled. /// private void DecideOpacitySetting() { if (UserSessions.IsRemote || !PdnBaseForm.globalEnableOpacity || !this.EnableInstanceOpacity) { if (this.enableOpacity) { try { UI.SetFormOpacity(this, 1.0); } // This fails in certain odd situations (bug #746), so we just eat the exception. catch (System.ComponentModel.Win32Exception) { } } this.enableOpacity = false; } else { if (!this.enableOpacity) { // This fails in certain odd situations (bug #746), so we just eat the exception. try { UI.SetFormOpacity(this, this.ourOpacity); } catch (System.ComponentModel.Win32Exception) { } } this.enableOpacity = true; } } public double ScreenAspect { get { Rectangle bounds = System.Windows.Forms.Screen.FromControl(this).Bounds; double aspect = (double)bounds.Width / (double)bounds.Height; return aspect; } } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.SuspendLayout(); // // PdnBaseForm // this.AutoScaleDimensions = new SizeF(96F, 96F); this.AutoScaleMode = AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(291, 270); this.Name = "PdnBaseForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "PdnBaseForm"; this.ResumeLayout(false); } #endregion public event MovingEventHandler Moving; protected virtual void OnMoving(MovingEventArgs mea) { if (Moving != null) { Moving(this, mea); } } public event CancelEventHandler QueryEndSession; protected virtual void OnQueryEndSession(CancelEventArgs e) { if (QueryEndSession != null) { QueryEndSession(this, e); } } private void UserSessions_SessionChanged(object sender, EventArgs e) { this.DecideOpacitySetting(); } void RealWndProc(ref Message m) { OurWndProc(ref m); } protected override void WndProc(ref Message m) { if (this.formEx == null) { base.WndProc(ref m); } else if (!this.formEx.HandleParentWndProc(ref m)) { OurWndProc(ref m); } } private void OurWndProc(ref Message m) { switch (m.Msg) { case 0x0216: // WM_MOVING unsafe { int* p = (int*)m.LParam; Rectangle rect = Rectangle.FromLTRB(p[0], p[1], p[2], p[3]); MovingEventArgs mea = new MovingEventArgs(rect); OnMoving(mea); p[0] = mea.Rectangle.Left; p[1] = mea.Rectangle.Top; p[2] = mea.Rectangle.Right; p[3] = mea.Rectangle.Bottom; m.Result = new IntPtr(1); } break; // WinForms doesn't handle this message correctly and wrongly returns 0 instead of 1. case 0x0011: // WM_QUERYENDSESSION CancelEventArgs e = new CancelEventArgs(); OnQueryEndSession(e); m.Result = e.Cancel ? IntPtr.Zero : new IntPtr(1); break; default: base.WndProc(ref m); break; } } public SnapManager SnapManager { get { if (this.snapManager == null) { this.snapManager = new SnapManager(); } return snapManager; } } public Size ClientSizeToWindowSize(Size clientSize) { Size baseClientSize = ClientSize; Size baseWindowSize = Size; int extraWidth = baseWindowSize.Width - baseClientSize.Width; int extraHeight = baseWindowSize.Height - baseClientSize.Height; Size windowSize = new Size(clientSize.Width + extraWidth, clientSize.Height + extraHeight); return windowSize; } public Size WindowSizeToClientSize(Size windowSize) { Size baseClientSize = ClientSize; Size baseWindowSize = Size; int extraWidth = baseWindowSize.Width - baseClientSize.Width; int extraHeight = baseWindowSize.Height - baseClientSize.Height; Size clientSize = new Size(windowSize.Width - extraWidth, windowSize.Height - extraHeight); return clientSize; } public Rectangle ClientBoundsToWindowBounds(Rectangle clientBounds) { Rectangle currentBounds = this.Bounds; Rectangle currentClientBounds = this.RectangleToScreen(ClientRectangle); Rectangle newWindowBounds = new Rectangle( clientBounds.Left - (currentClientBounds.Left - currentBounds.Left), clientBounds.Top - (currentClientBounds.Top - currentBounds.Top), clientBounds.Width + (currentBounds.Width - currentClientBounds.Width), clientBounds.Height + (currentBounds.Height - currentClientBounds.Height)); return newWindowBounds; } public Rectangle WindowBoundsToClientBounds(Rectangle windowBounds) { Rectangle currentBounds = this.Bounds; Rectangle currentClientBounds = this.RectangleToScreen(ClientRectangle); Rectangle newClientBounds = new Rectangle( windowBounds.Left + (currentClientBounds.Left - currentBounds.Left), windowBounds.Top + (currentClientBounds.Top - currentBounds.Top), windowBounds.Width - (currentBounds.Width - currentClientBounds.Width), windowBounds.Height - (currentBounds.Height - currentClientBounds.Height)); return newClientBounds; } public void EnsureFormIsOnScreen() { if (this.WindowState == FormWindowState.Maximized) { return; } if (this.WindowState == FormWindowState.Minimized) { return; } Screen ourScreen; try { ourScreen = Screen.FromControl(this); } catch (Exception) { ourScreen = null; } if (ourScreen == null) { ourScreen = Screen.PrimaryScreen; } Rectangle currentBounds = Bounds; Rectangle newBounds = EnsureRectIsOnScreen(ourScreen, currentBounds); Bounds = newBounds; } public static Rectangle EnsureRectIsOnScreen(Screen screen, Rectangle bounds) { Rectangle newBounds = bounds; Rectangle screenBounds = screen.WorkingArea; // Make sure the bottom and right do not fall off the edge, by moving the bounds if (newBounds.Right > screenBounds.Right) { newBounds.X -= (newBounds.Right - screenBounds.Right); } if (newBounds.Bottom > screenBounds.Bottom) { newBounds.Y -= (newBounds.Bottom - screenBounds.Bottom); } // Make sure the top and left haven't fallen off, by moving if (newBounds.Left < screenBounds.Left) { newBounds.X = screenBounds.Left; } if (newBounds.Top < screenBounds.Top) { newBounds.Y = screenBounds.Top; } // Make sure that we are not too wide / tall, by resizing if (newBounds.Right > screenBounds.Right) { newBounds.Width -= (newBounds.Right - screenBounds.Right); } if (newBounds.Bottom > screenBounds.Bottom) { newBounds.Height -= (newBounds.Bottom - screenBounds.Bottom); } // All done. return newBounds; } public virtual void CreateProjectName(AnalyzeSettingModel model) { } public virtual void CreateProjectName(AnalyzeSettingModel model, int id) { } public virtual void GetCreateName(string name) { } public virtual void GetCreateName(string name, string desc) { } /// /// 从xml读取对应分析报告的设置项 /// public void SetAnalyzeModelFromXml(string languageName) { string filePath = Application.StartupPath + "\\Config\\" + xmlPath + "\\" + "AnalyzeSavedModel.xml"; if (System.IO.File.Exists(filePath)) { AnalyzeSavedModel analyzeSavedModel = XmlSerializeHelper.DESerializer(FileOperationHelper.ReadStringFromFile(filePath, FileMode.Open)); if (analyzeSavedModel.modelItems != null && analyzeSavedModel.modelItems.Count > 0) { AnalyzeSavedModel.ModelItem modelItem = analyzeSavedModel.modelItems.Find(a => a.languageName == languageName); if (modelItem != null && modelItem.analyzeSettingModel != null) { this.analyzeSettingModel = modelItem.analyzeSettingModel; } } } } /// /// 计算并修改DataGridView的列宽度 /// 使其看起来舒服一点 /// /// /// public void AutoSizeColumn(DataGridView dgViewFiles, int offset) { int width = 0; //使列自使用宽度 //对于DataGridView的每一个列都调整 for (int i = 0; i < dgViewFiles.Columns.Count; i++) { //将每一列都调整为自动适应模式 dgViewFiles.AutoResizeColumn(i, DataGridViewAutoSizeColumnMode.AllCells); //记录整个DataGridView的宽度 width += dgViewFiles.Columns[i].Width + offset; } //判断调整后的宽度与原来设定的宽度的关系,如果是调整后的宽度大于原来设定的宽度, //则将DataGridView的列自动调整模式设置为显示的列即可, //如果是小于原来设定的宽度,将模式改为填充。 if (width > dgViewFiles.Size.Width) { dgViewFiles.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; for (int i = 0; i < dgViewFiles.Columns.Count; i++) { dgViewFiles.Columns[i].Width += offset; } } else { for (int i = 0; i < dgViewFiles.Columns.Count; i++) { dgViewFiles.Columns[i].Width = (int)(dgViewFiles.Size.Width / dgViewFiles.Columns.Count); } //dgViewFiles.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; } //冻结某列 从左开始 0,1,2 //dgViewFiles.Columns[1].Frozen = true; } } }