diff --git a/Bin/SunnyUI.dll b/Bin/SunnyUI.dll index f0935255..8fbcfd6f 100644 Binary files a/Bin/SunnyUI.dll and b/Bin/SunnyUI.dll differ diff --git a/Bin/SunnyUI.pdb b/Bin/SunnyUI.pdb index 270df6dd..24359ed0 100644 Binary files a/Bin/SunnyUI.pdb and b/Bin/SunnyUI.pdb differ diff --git a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe index afbf4e2f..23fa8877 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.Demo.exe and b/SunnyUI.Demo/Bin/SunnyUI.Demo.exe differ diff --git a/SunnyUI.Demo/Bin/SunnyUI.dll b/SunnyUI.Demo/Bin/SunnyUI.dll index f0935255..8fbcfd6f 100644 Binary files a/SunnyUI.Demo/Bin/SunnyUI.dll and b/SunnyUI.Demo/Bin/SunnyUI.dll differ diff --git a/SunnyUI.Demo/FMain.Designer.cs b/SunnyUI.Demo/FMain.Designer.cs index 14d4b190..74338fd4 100644 --- a/SunnyUI.Demo/FMain.Designer.cs +++ b/SunnyUI.Demo/FMain.Designer.cs @@ -37,7 +37,6 @@ this.uiLogo1 = new Sunny.UI.UILogo(); this.uiAvatar = new Sunny.UI.UIAvatar(); this.StyleManager = new Sunny.UI.UIStyleManager(this.components); - this.imageList1 = new System.Windows.Forms.ImageList(this.components); this.Header.SuspendLayout(); this.SuspendLayout(); // @@ -46,17 +45,18 @@ this.Aside.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240))))); this.Aside.ItemHeight = 36; this.Aside.LineColor = System.Drawing.Color.Black; + this.Aside.Location = new System.Drawing.Point(2, 145); this.Aside.MenuStyle = Sunny.UI.UIMenuStyle.Black; this.Aside.ShowOneNode = true; this.Aside.ShowTips = true; - this.Aside.Size = new System.Drawing.Size(250, 575); + this.Aside.Size = new System.Drawing.Size(250, 573); this.Aside.Style = Sunny.UI.UIStyle.Custom; // // Header // this.Header.Controls.Add(this.uiAvatar); this.Header.Controls.Add(this.uiLogo1); - this.Header.ImageList = this.imageList1; + this.Header.Location = new System.Drawing.Point(2, 35); treeNode1.ImageIndex = 1; treeNode1.Name = "节点0"; treeNode1.Text = "控件"; @@ -72,7 +72,7 @@ treeNode3, treeNode4}); this.Header.SelectedIndex = 0; - this.Header.Size = new System.Drawing.Size(1024, 110); + this.Header.Size = new System.Drawing.Size(1020, 110); this.Header.Style = Sunny.UI.UIStyle.Custom; this.Header.MenuItemClick += new Sunny.UI.UINavBar.OnMenuItemClick(this.Header_MenuItemClick); // @@ -92,19 +92,12 @@ // this.uiAvatar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.uiAvatar.Font = new System.Drawing.Font("微软雅黑", 12F); - this.uiAvatar.Location = new System.Drawing.Point(943, 25); + this.uiAvatar.Location = new System.Drawing.Point(939, 25); this.uiAvatar.Name = "uiAvatar"; this.uiAvatar.Size = new System.Drawing.Size(66, 70); this.uiAvatar.TabIndex = 4; this.uiAvatar.Text = "uiAvatar1"; // - // imageList1 - // - this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); - this.imageList1.TransparentColor = System.Drawing.Color.Transparent; - this.imageList1.Images.SetKeyName(0, "002.png"); - this.imageList1.Images.SetKeyName(1, "025.png"); - // // FMain // this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F); @@ -112,8 +105,10 @@ this.ClientSize = new System.Drawing.Size(1024, 720); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "FMain"; + this.Padding = new System.Windows.Forms.Padding(2, 35, 2, 2); + this.ShowDragStretch = true; + this.ShowRadius = false; this.Text = "SunnyUI.Net"; - this.WindowStateChange += new Sunny.UI.UIForm.OnWindowStateChange(this.FMain_WindowStateChange); this.Header.ResumeLayout(false); this.ResumeLayout(false); @@ -124,6 +119,5 @@ private UILogo uiLogo1; private UIAvatar uiAvatar; private UIStyleManager StyleManager; - private System.Windows.Forms.ImageList imageList1; } } \ No newline at end of file diff --git a/SunnyUI.Demo/FMain.resx b/SunnyUI.Demo/FMain.resx index a8d2899d..8afef9d3 100644 --- a/SunnyUI.Demo/FMain.resx +++ b/SunnyUI.Demo/FMain.resx @@ -117,56 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 150, 17 - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w - LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABS - CQAAAk1TRnQBSQFMAgEBAgEAARABAAEQAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo - AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA - AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 - AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA - AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm - AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM - AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA - ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz - AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ - AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM - AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA - AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA - AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ - AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ - AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA - AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm - ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ - Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz - AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA - AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM - AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM - ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM - Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA - AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM - AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ - AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz - AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm - AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw - AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/xIAAW8BJQFGAUwCbwKT - Am8BTAFGASUBbzIAAbQMGQG0IQABCQK0AQkBAAEJBLQBCQEAAQkCtAEJAQABtAH0CgcB9AG0IQABtAIZ - AbUBiwG1BBkBtQGLAbUCGQG0AQABtAH0AQcC/wEHAv8BBwL/AQcB9AG0IQABtA4ZAbQBAAG0AfQKBwH0 - AbQhAAG0AfQGCQH0AfEB8AG8AgcB9AG0AQABuwH0AQcC/wEHAv8BBwL/AQcB9AG7IQABtAH0ARkBCQK0 - AQkBGQf0AbQBAAHcAf8KBwH/AdwhAAG6AfQBGQGLAkwBiwEZAfQB8QHwAbwCBwH0AboBAAHcAf8BTwKe - AZcCngGXAp4BTwH/AdwhAAHcAf8BtAFSAsMBUgG0B/8B3AEAAdwB/wNPAZcCTwGXA08B/wHcIQAB3AH/ - AbQBdQL2AXUBtAH/AfEB8AG8AgcB/wHcAQAB3Az/AdwhAAHcAf8B1QIiAZoBIgHVB/8B3AEADiUhAAHc - Af8B1QQVAdUB/wLcAbsCtAH/AdwBAAElAUcB3AH/AbQIRwElIQAB3A7/AdwBAAFGAeMBbwHrAW8E4wFv - AesBbwHjAUYhAAEZAtwCCQYZAgkC3AEZAQABFgFHAewBvAHsBE0B7AG8AewBRwEWNAABkgHzAZIEAAGS - AfMBkjYAAfEB7wHxBAAB8QHvAfEjAAFCAU0BPgcAAT4DAAEoAwABQAMAARADAAEBAQABAQUAAYAXAAP/ - AQAC/wGAAQEEAAL/AYABAQQAAQgBEAGAAQEGAAGAAQEGAAGAAQEGAAGAAQEGAAGAAQEGAAGAAQEGAAGA - AQEGAAGAAQEGAAGAAQEGAAGAAQEGAAGAAQEGAAGAAQEEAAL/AeMBxwQAAv8B4wHHBAAL - - 17, 17 diff --git a/SunnyUI/Controls/UINavMenu.cs b/SunnyUI/Controls/UINavMenu.cs index 7bbb715c..6dd716b4 100644 --- a/SunnyUI/Controls/UINavMenu.cs +++ b/SunnyUI/Controls/UINavMenu.cs @@ -40,7 +40,12 @@ namespace Sunny.UI public UINavMenu() { - SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true); + SetStyle(ControlStyles.DoubleBuffer | + ControlStyles.AllPaintingInWmPaint | + ControlStyles.OptimizedDoubleBuffer, true); + + base.UpdateStyles(); + BorderStyle = BorderStyle.None; //HideSelection = false; DrawMode = TreeViewDrawMode.OwnerDrawAll; diff --git a/SunnyUI/Forms/UIForm.cs b/SunnyUI/Forms/UIForm.cs index 620f3188..d6043472 100644 --- a/SunnyUI/Forms/UIForm.cs +++ b/SunnyUI/Forms/UIForm.cs @@ -19,7 +19,8 @@ * 2020-01-01: V2.2.0 增加文件说明 * 2020-05-30: V2.2.5 更新标题移动、双击最大化/正常、到顶最大化、最大化后拖拽正常 * 2020-07-01: V2.2.6 仿照QQ,重绘标题栏按钮 - * 2020-07-05: V2.2.6 UIForm:更新窗体控制按钮圆角和跟随窗体圆角变化。 + * 2020-07-05: V2.2.6 更新窗体控制按钮圆角和跟随窗体圆角变化。 + * 2020-09-17: V2.2.7 重写WindowState相关代码 ******************************************************************************/ using System; @@ -39,10 +40,6 @@ namespace Sunny.UI private UIStatusForm statusForm; - public delegate void OnWindowStateChange(object sender, FormWindowState state); - - public event OnWindowStateChange WindowStateChange; - public UIForm() { InitializeComponent(); @@ -52,11 +49,32 @@ namespace Sunny.UI SetStyle(UIStyles.Style); } - SetStyle(ControlStyles.UserPaint, true); - SetStyle(ControlStyles.AllPaintingInWmPaint, true); - SetStyle(ControlStyles.DoubleBuffer, true); + base.SetStyle( + ControlStyles.UserPaint | + ControlStyles.DoubleBuffer | + ControlStyles.OptimizedDoubleBuffer | + ControlStyles.AllPaintingInWmPaint | + ControlStyles.ResizeRedraw | + ControlStyles.SupportsTransparentBackColor, true); UpdateStyles(); + Version = UIGlobal.Version; + FormBorderStyle = FormBorderStyle.None; + base.MaximumSize = ShowFullScreen ? Screen.PrimaryScreen.Bounds.Size : Screen.PrimaryScreen.WorkingArea.Size; + } + + //不显示FormBorderStyle属性 + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public new FormBorderStyle FormBorderStyle + { + get { return base.FormBorderStyle; } + set + { + base.FormBorderStyle = FormBorderStyle.None; + Console.WriteLine(value); + } } public void Render() @@ -357,8 +375,7 @@ namespace Sunny.UI if (MinimizeBox) { - MinimizeBoxRect = new Rectangle(MaximizeBox ? MaximizeBoxRect.Left - 28 - 2 : ControlBoxRect.Left - 28 - 2, - ControlBoxRect.Top, 28, 28); + MinimizeBoxRect = new Rectangle(MaximizeBox ? MaximizeBoxRect.Left - 28 - 2 : ControlBoxRect.Left - 28 - 2, ControlBoxRect.Top, 28, 28); ControlBoxLeft = MinimizeBoxRect.Left - 2; } else @@ -458,21 +475,20 @@ namespace Sunny.UI { if (InControlBox) { - Close(); InControlBox = false; + Close(); } if (InMinBox) { - base.WindowState = FormWindowState.Minimized; - WindowStateChange?.Invoke(this, FormWindowState.Minimized); InMinBox = false; + WindowState = FormWindowState.Minimized; } if (InMaxBox) { - ShowMaximize(); InMaxBox = false; + ShowMaximize(); } } } @@ -490,7 +506,8 @@ namespace Sunny.UI private void ShowMaximize(bool IsOnMoving = false) { Screen screen = Screen.FromPoint(MousePosition); - if (windowState == FormWindowState.Normal) + base.MaximumSize = ShowFullScreen ? Screen.PrimaryScreen.Bounds.Size : Screen.PrimaryScreen.WorkingArea.Size; + if (WindowState == FormWindowState.Normal) { size = Size; // 若窗体从正常模式->最大化模式,该操作是由移动窗体至顶部触发的,记录的是移动前的窗体位置 @@ -500,11 +517,9 @@ namespace Sunny.UI Left = screen.Bounds.Left; Top = screen.Bounds.Top; SetFormRoundRectRegion(this, 0); - if (ShowFullScreen) base.WindowState = FormWindowState.Maximized; - windowState = FormWindowState.Maximized; - WindowStateChange?.Invoke(this, FormWindowState.Maximized); + WindowState = FormWindowState.Maximized; } - else if (windowState == FormWindowState.Maximized) + else if (WindowState == FormWindowState.Maximized) { if (size.Width == 0 || size.Height == 0) { @@ -516,11 +531,9 @@ namespace Sunny.UI screen.Bounds.Top + screen.WorkingArea.Height / 2 - Size.Height / 2); if (location.X == 0 && location.Y == 0) location = center; - Location = StartPosition == FormStartPosition.CenterScreen ? center : location; + Location = location; SetFormRoundRectRegion(this, ShowRadius ? 5 : 0); - windowState = FormWindowState.Normal; - base.WindowState = FormWindowState.Normal; - WindowStateChange?.Invoke(this, FormWindowState.Normal); + WindowState = FormWindowState.Normal; } Invalidate(); @@ -625,7 +638,7 @@ namespace Sunny.UI { if (FormMoveMouseDown && !MousePosition.Equals(mouseOffset)) { - if (windowState == FormWindowState.Maximized) + if (WindowState == FormWindowState.Maximized) { int MaximizedWidth = Width; int LocationX = Left; @@ -695,6 +708,8 @@ namespace Sunny.UI InControlBox = InMaxBox = InMinBox = false; } } + + base.OnMouseMove(e); } protected override void OnMouseLeave(EventArgs e) @@ -754,7 +769,7 @@ namespace Sunny.UI if (ShowRect) { Point[] points; - bool unShowRadius = !ShowRadius || windowState == FormWindowState.Maximized || + bool unShowRadius = !ShowRadius || WindowState == FormWindowState.Maximized || (Width == Screen.PrimaryScreen.WorkingArea.Width && Height == Screen.PrimaryScreen.WorkingArea.Height); if (unShowRadius) @@ -840,7 +855,7 @@ namespace Sunny.UI // ? FontAwesomeIcons.fa_window_restore // : FontAwesomeIcons.fa_window_maximize, 24, Color.White, MaximizeBoxRect, 1); - if (windowState == FormWindowState.Maximized) + if (WindowState == FormWindowState.Maximized) { e.Graphics.DrawRectangle(Color.White, MaximizeBoxRect.Left + MaximizeBoxRect.Width / 2 - 5, @@ -872,7 +887,7 @@ namespace Sunny.UI MaximizeBoxRect.Top + MaximizeBoxRect.Height / 2 + 3); } - if (windowState == FormWindowState.Normal) + if (WindowState == FormWindowState.Normal) { e.Graphics.DrawRectangle(Color.White, MaximizeBoxRect.Left + MaximizeBoxRect.Width / 2 - 5, @@ -1137,7 +1152,7 @@ namespace Sunny.UI /// The instance containing the event data. private void CtrlMouseDown(object sender, MouseEventArgs e) { - if (windowState == FormWindowState.Maximized) + if (WindowState == FormWindowState.Maximized) { return; } @@ -1162,7 +1177,7 @@ namespace Sunny.UI return; } - if (windowState == FormWindowState.Maximized) + if (WindowState == FormWindowState.Maximized) { SetFormRoundRectRegion(this, 0); } @@ -1200,35 +1215,15 @@ namespace Sunny.UI public string CloseAskString { get; set; } - private FormWindowState windowState = FormWindowState.Normal; - - public new FormWindowState WindowState - { - get => windowState; - set - { - if (value == FormWindowState.Minimized) - { - base.WindowState = FormWindowState.Minimized; - return; - } - - ShowMaximize(); - windowState = value; - } - } - protected override CreateParams CreateParams { get { - if (this.FormBorderStyle == FormBorderStyle.None) + if (base.FormBorderStyle == FormBorderStyle.None) { - // 当边框样式为FormBorderStyle.None时 // 点击窗体任务栏图标,可以进行最小化 - const int WS_MINIMIZEBOX = 0x00020000; CreateParams cp = base.CreateParams; - cp.Style = cp.Style | WS_MINIMIZEBOX; + cp.Style |= 0x00020000; return cp; } else @@ -1238,27 +1233,67 @@ namespace Sunny.UI } } - public void Show(FormWindowState state) + private bool showDragStretch; + [Description("显示边框可拖拽调整窗体大小"), Category("SunnyUI"), DefaultValue(false)] + public bool ShowDragStretch { - ShowFullScreen = false; - - switch (state) + get => showDragStretch; + set { - case FormWindowState.Minimized: - WindowState = FormWindowState.Minimized; - base.WindowState = FormWindowState.Minimized; - break; - case FormWindowState.Maximized: - base.WindowState = FormWindowState.Normal; - WindowState = FormWindowState.Normal; - ShowMaximize(); - break; - case FormWindowState.Normal: - base.WindowState = FormWindowState.Normal; - WindowState = FormWindowState.Maximized; - ShowMaximize(); - break; + showDragStretch = value; + if (value) + { + ShowRect = true; + ShowRadius = false; + Padding = new Padding(2, showTitle ? TitleHeight : 2, 2, 2); + } } } + + #region 拉拽调整窗体大小 + const int WM_LEFT = 10; + const int WM_RIGHT = 11; + const int WM_TOP = 12; + const int WM_TOPLEFT = 13; + const int WM_TOPRIGHT = 14; + const int WM_BOTTOM = 15; + const int WM_BOTTOMLEFT = 0x10; + const int WM_BOTTOMRIGHT = 17; + protected override void WndProc(ref Message m) + { + base.WndProc(ref m); + + if (ShowDragStretch && WindowState == FormWindowState.Normal && m.Msg == 0x0084) + { + Point vPoint = new Point((int)m.LParam & 0xFFFF, (int)m.LParam >> 16 & 0xFFFF); + vPoint = PointToClient(vPoint); + int dragSize = 5; + if (vPoint.X <= dragSize) + { + if (vPoint.Y <= dragSize) + m.Result = (IntPtr)WM_TOPLEFT; + else if (vPoint.Y >= ClientSize.Height - dragSize) + m.Result = (IntPtr)WM_BOTTOMLEFT; + else m.Result = (IntPtr)WM_LEFT; + } + else if (vPoint.X >= ClientSize.Width - dragSize) + { + if (vPoint.Y <= dragSize) + m.Result = (IntPtr)WM_TOPRIGHT; + else if (vPoint.Y >= ClientSize.Height - dragSize) + m.Result = (IntPtr)WM_BOTTOMRIGHT; + else m.Result = (IntPtr)WM_RIGHT; + } + else if (vPoint.Y <= dragSize) + { + m.Result = (IntPtr)WM_TOP; + } + else if (vPoint.Y >= ClientSize.Height - dragSize) + { + m.Result = (IntPtr)WM_BOTTOM; + } + } + } + #endregion } } \ No newline at end of file diff --git a/SunnyUI/Properties/AssemblyInfo.cs b/SunnyUI/Properties/AssemblyInfo.cs index 8a8c88be..1f58c385 100644 --- a/SunnyUI/Properties/AssemblyInfo.cs +++ b/SunnyUI/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值, // 方法是按如下所示使用“*”: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.2.7.0")] -[assembly: AssemblyFileVersion("2.2.7.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.8.0")] +[assembly: AssemblyFileVersion("2.2.8.0")] \ No newline at end of file diff --git a/SunnyUI/SunnyUI.csproj b/SunnyUI/SunnyUI.csproj index bd9e55e0..cbf916cb 100644 --- a/SunnyUI/SunnyUI.csproj +++ b/SunnyUI/SunnyUI.csproj @@ -411,6 +411,7 @@ + Component diff --git a/SunnyUI/Units/USuspendCtrlAltDel.cs b/SunnyUI/Units/USuspendCtrlAltDel.cs new file mode 100644 index 00000000..74a80078 --- /dev/null +++ b/SunnyUI/Units/USuspendCtrlAltDel.cs @@ -0,0 +1,180 @@ +/****************************************************************************** + * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。 + * CopyRight (C) 2012-2020 ShenYongHua(沈永华). + * QQ群:56829229 QQ:17612584 EMail:SunnyUI@qq.com + * + * Blog: https://www.cnblogs.com/yhuse + * Gitee: https://gitee.com/yhuse/SunnyUI + * GitHub: https://github.com/yhuse/SunnyUI + * + * SunnyUI.dll can be used for free under the GPL-3.0 license. + * If you use this code, please keep this note. + * 如果您使用此代码,请保留此说明。 + ****************************************************************************** + * 文件名称: USuspendCtrlAltDel.cs + * 文件说明: 通过挂起winlogon线程来屏蔽Ctrl+Alt+Delete + * 当前版本: V2.2 + * 创建日期: 2020-01-01 + * + * 2020-09-17: V2.2.7 增加文件说明 +******************************************************************************/ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Sunny.UI +{ + /// + /// 通过挂起winlogon.exe线程来屏蔽Ctrl+Alt+Delete + /// 程序需要管理员权限 + /// 需要提升进程权限为SE_PRIVILEGE_ENABLED权限 + /// winlogon管理着开关机登录界面等功能 + /// 调用Suspend挂起winlogon.exe,用完后需要Resume,否则无法调用关机界面 + /// + public static class SuspendCtrlAltDelete + { + public static void GetSeDebugPrivilege() + { + IntPtr hToken; + LUID luidSEDebugNameValue = new LUID(); + + + if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken)) + { + Console.WriteLine("OpenProcessToken() failed, error = {0} . SeDebugPrivilege is not available", Marshal.GetLastWin32Error()); + return; + } + else + { + Console.WriteLine("OpenProcessToken() successfully"); + } + + if (!LookupPrivilegeValue(null, SE_DEBUG_NAME, ref luidSEDebugNameValue)) + { + Console.WriteLine("LookupPrivilegeValue() failed, error = {0} .SeDebugPrivilege is not available", Marshal.GetLastWin32Error()); + CloseHandle(hToken); + return; + } + else + { + Console.WriteLine("LookupPrivilegeValue() successfully"); + } + + TOKEN_PRIVILEGES tkpPrivileges = new TOKEN_PRIVILEGES(); + tkpPrivileges.PrivilegeCount = 1; + tkpPrivileges.Privilege.Luid = luidSEDebugNameValue; + tkpPrivileges.Privilege.Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(hToken, false, ref tkpPrivileges, 0, IntPtr.Zero, 0)) + { + Console.WriteLine("LookupPrivilegeValue() failed, error = {0} .SeDebugPrivilege is not available", Marshal.GetLastWin32Error()); + } + else + { + Console.WriteLine("SeDebugPrivilege is now available"); + } + CloseHandle(hToken); + Console.ReadLine(); + } + + public static void Suspend() + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.ProcessName == "winlogon") + { + + IntPtr p = OpenThread(PROCESS_ALL_ACCESS, false, (IntPtr)process.Threads[0].Id); + SuspendThread(p); + CloseHandle(p); + } + } + } + + public static void Resume() + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.ProcessName == "winlogon") + { + IntPtr p = OpenThread(PROCESS_ALL_ACCESS, false, (IntPtr)process.Threads[0].Id); + ResumeThread(p); + CloseHandle(p); + } + } + } + + const int PROCESS_ALL_ACCESS = 0x001F03FF; + const string SE_DEBUG_NAME = "SeDebugPrivilege"; + const uint SE_PRIVILEGE_ENABLED = 0x00000002; + const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000; + const uint STANDARD_RIGHTS_READ = 0x00020000; + const uint TOKEN_ASSIGN_PRIMARY = 0x0001; + const uint TOKEN_DUPLICATE = 0x0002; + const uint TOKEN_IMPERSONATE = 0x0004; + const uint TOKEN_QUERY = 0x0008; + const uint TOKEN_QUERY_SOURCE = 0x0010; + const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; + const uint TOKEN_ADJUST_GROUPS = 0x0040; + const uint TOKEN_ADJUST_DEFAULT = 0x0080; + const uint TOKEN_ADJUST_SESSIONID = 0x0100; + const uint TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY; + const uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | + TOKEN_ADJUST_SESSIONID); + + + [DllImport("kernel32.dll")] + private static extern IntPtr OpenThread(int dwDesiredAccess, bool bInheritHandle, IntPtr dwThreadId); + + [DllImport("kernel32.dll")] + private static extern bool CloseHandle(IntPtr hObject); + + [DllImport("kernel32")] + private static extern int SuspendThread(IntPtr hThread); + + [DllImport("kernel32")] + private static extern int ResumeThread(IntPtr hThread); + + [DllImport("advapi32.dll", SetLastError = true)] + private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle); + + [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, + [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid); + + [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, + [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, + [MarshalAs(UnmanagedType.Struct)] ref TOKEN_PRIVILEGES NewState, + uint BufferLength, IntPtr PreviousState, uint ReturnLength); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct LUID + { + internal int LowPart; + internal uint HighPart; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct TOKEN_PRIVILEGES + { + internal int PrivilegeCount; + internal LUID_AND_ATTRIBUTES Privilege; + } + + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct LUID_AND_ATTRIBUTES + { + internal LUID Luid; + internal uint Attributes; + } + } +}