winform--分页控件
新建一个用户组件,直接上代码:
/* * 作者:pengyan zhang * 邮箱:3073507793@qq.com * 博客:https://www.cnblogs.com/zpy1993-09 * 时间:2024-04-12 18:36 */ public partial class CPPageComponent : FlowLayoutPanel { #region 事件 /// <summary> /// 委托 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public delegate void CPPageEventHandler(object sender, PageEventArgs e); /// <summary> /// 开关状态发生改变时引发的事件 /// </summary> public event CPPageEventHandler PageEvent; #endregion /// <summary> /// 当点击某一页被选中时 /// </summary> [Category("SimpleUI"), Description("被选中时的背景颜色"), DefaultValue(typeof(Color), "0, 159, 149")] public Color CP_PageCheckBackColor { get { return PageCheckBackColor; } set { PageCheckBackColor = value; } } private Color PageCheckBackColor = Color.FromArgb(0, 159, 149); /// <summary> /// 当某一页未被选中时的背景颜色 /// </summary> [Category("SimpleUI"), Description("未被选中时的背景颜色"), DefaultValue(typeof(Color), "255, 255, 255")] public Color CP_PageUnCheckBackColor { get { return PageUnCheckBackColor; } set { PageUnCheckBackColor = value; } } private Color PageUnCheckBackColor = Color.FromArgb(255, 255, 255); /// <summary> /// 当某一页被选中时字体颜色 /// </summary> [Category("SimpleUI"), Description("被选中时的字体颜色"), DefaultValue(typeof(Color), "255, 255, 255")] public Color CP_PageCheckFontColor { get { return PageCheckBackColor; } set { PageCheckBackColor = value; } } private Color PageCheckFontColor= Color.FromArgb(255, 255, 255); /// <summary> /// 当某一页未被选中的字体颜色 /// </summary> [Category("SimpleUI"), Description("未被选中时的字体颜色"), DefaultValue(typeof(Color), "0, 0,0")] public Color CP_PageUnCheckFontColor { get { return PageUnCheckBackColor; } set { PageUnCheckBackColor = value; } } private Color PageUnCheckFontColor = Color.FromArgb(0, 0, 0); /// <summary> /// 当鼠标进入某一页时 /// </summary> [Category("SimpleUI"), Description("鼠标进入时的背景颜色"), DefaultValue(typeof(Color), "224, 224, 224")] public Color CP_ageEneterColor { get { return PageEneterColor; } set { PageEneterColor = value; } } private Color PageEneterColor= Color.FromArgb(224, 224, 224); private Label labelLastPage { get; set; } private Label labelNextPage { get; set; } private TextBox PageBox { get; set; } private Label CurrentPageControl { get; set; } private Label labelLeft { get; set; } private Label labelRight { get; set; } private List<Label> pages { get; set; } private int page { get; set; } = 0; private int PageSize { get; set; } = 10; private int PageIndex { get; set; } = 1; private int SumPage { get; set; } private Label label_StartPage { get; set; } private Label label_EndPage { get; set; } private int[] PageArr { get; set; } = new[] { 10, 20, 50, 100 }; private FlowLayoutPanel flowLayoutPanel { get; set; } private Label Drop { get;set; } private Popup pop { get; set; } public CPPageComponent() { InitializeComponent(); } public CPPageComponent(IContainer container) { container.Add(this); InitializeComponent(); } private void page_Painit(object? sender, PaintEventArgs e) { Control control = sender as Control; ControlPaint.DrawBorder(e.Graphics,//获取进行绘制的图形 new Rectangle(0, 0, control.Width, control.Height),//绘制控件所在工作区域 Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid,//边框类型,选择实线边框,也有虚线等种类;下面这四个重复的传参是设置工作区上下左右边框的功能 Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid, Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid, Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid); } protected override void OnResize(EventArgs ea) { this.Height = 31; base.OnResize(ea); } private void Label_Click(object? sender, EventArgs e) { var label = sender as Label; if ((int)label.Tag == (int)CurrentPageControl.Tag) return; int currentpage = (int)label.Tag; this.PageIndex= currentpage; PrePage(currentpage, label); } private void label_MouseEnter_Click(object? sender, EventArgs e) { var label = sender as Label; if (CurrentPageControl != label) { label.Cursor = Cursors.Hand; label.BackColor = PageEneterColor; } } private void label_MouseLeave_Click(object? sender, EventArgs e) { var label = sender as Label; if (CurrentPageControl != label) label.BackColor = PageUnCheckBackColor; } private void Pagebox_TextChanged(object? sender, EventArgs e) { PageBox.Text = Regex.Replace(PageBox.Text, "[^0-9]", ""); if (PageBox.Text == "0") PageBox.Text = ""; } private void label_Sure_MouseEnter_Click(object? sender, EventArgs e) { var label = sender as Label; label.Cursor = Cursors.Hand; label.BackColor = PageEneterColor; label.ForeColor = PageUnCheckFontColor; } private void label_Sure_MouseLeave_Click(object? sender, EventArgs e) { var label = sender as Label; label.BackColor = PageUnCheckBackColor; } private void label_Sure_Click(object? sender, EventArgs e) { if (string.IsNullOrEmpty(PageBox.Text)) return; int pageCount = int.Parse(PageBox.Text); PageSure(pageCount); } private void labelNextPage_MouseEnter_Click(object? sender, EventArgs e) { var label = sender as Label; if ((int)CurrentPageControl.Tag == page) label.Cursor = Cursors.No; else { label.Cursor = Cursors.Hand; label.BackColor = PageEneterColor; } } private void labelNextPage_MouseLeave_Click(object? sender, EventArgs e) { var label = sender as Label; label.BackColor = PageUnCheckBackColor ; } private void labelNextPage_Click(object? sender, EventArgs e) { if ((int)CurrentPageControl.Tag == page) return; if ((int)CurrentPageControl.Tag == page-1 && page > 6) { CurrentPageControl.BackColor = PageUnCheckBackColor; CurrentPageControl.ForeColor = PageUnCheckFontColor; CurrentPageControl = label_EndPage; CurrentPageControl.BackColor = PageCheckBackColor; CurrentPageControl.ForeColor = PageUnCheckFontColor; return; } for (int i = 0; i < pages.Count; i++) { if ((int)CurrentPageControl.Tag + 1 == (int)pages[i].Tag){ PrePage((int)CurrentPageControl.Tag+1, pages[i]); break;} } } private void LastPage_MouseEnter_Click(object? sender, EventArgs e) { var label = sender as Label; if ((int)CurrentPageControl.Tag == 1) label.Cursor = Cursors.No; else {label.Cursor = Cursors.Hand;label.BackColor = PageEneterColor;} } private void LastPage_MouseLeave_Click(object? sender, EventArgs e) { var label = sender as Label; label.BackColor = PageUnCheckBackColor; } private void LastPage_Click(object? sender, EventArgs e) { if ((int)CurrentPageControl.Tag == 1) return; if ((int)CurrentPageControl.Tag == 2&&page>6) { CurrentPageControl.BackColor = PageUnCheckBackColor; CurrentPageControl.ForeColor = PageUnCheckFontColor; CurrentPageControl = label_StartPage; CurrentPageControl.BackColor = PageCheckBackColor; CurrentPageControl.ForeColor = PageCheckFontColor; return; } for (int i = 0; i < pages.Count; i++) { if ((int)CurrentPageControl.Tag - 1 == (int)pages[i].Tag) { PrePage((int)CurrentPageControl.Tag -1, pages[i]);break; } } } /// <summary> /// 初始化分页 /// </summary> /// <param name="page"></param> public void SetPage(int page) { this.Controls.Clear(); if (page == 0) return; labelLastPage = new Label(); labelLastPage.AutoSize = false; labelLastPage.Size = new Size(60, 30); labelLastPage.Text = "上一页"; labelLastPage.TextAlign = ContentAlignment.MiddleCenter; labelLastPage.BackColor = PageUnCheckBackColor; labelLastPage.Margin = new Padding(0, 0, 2, 0); labelLastPage.Paint += page_Painit; labelLastPage.Click += LastPage_Click; labelLastPage.MouseLeave += LastPage_MouseLeave_Click; labelLastPage.MouseEnter += LastPage_MouseEnter_Click; this.Controls.Add(labelLastPage); DealPage(page); labelNextPage = new Label(); labelNextPage.AutoSize = false; labelNextPage.Size = new Size(60, 30); labelNextPage.Text = "下一页"; labelNextPage.Margin = new Padding(0, 0, 10, 0); labelNextPage.TextAlign = ContentAlignment.MiddleCenter; labelNextPage.BackColor = PageUnCheckBackColor; labelNextPage.Paint += page_Painit; labelNextPage.Click += labelNextPage_Click; labelNextPage.MouseLeave += labelNextPage_MouseLeave_Click; labelNextPage.MouseEnter += labelNextPage_MouseEnter_Click; this.Controls.Add(labelNextPage); Label labelLastRange = new Label(); labelLastRange.AutoSize = false; labelLastRange.Size = new Size(40, 30); labelLastRange.Text = "到第"; labelLastRange.Margin = new Padding(0, 0, 0, 0); labelLastRange.TextAlign = ContentAlignment.MiddleCenter; labelLastRange.BackColor = PageUnCheckBackColor; this.Controls.Add(labelLastRange); PageBox = new TextBox(); PageBox.Size = new Size(50, 30); PageBox.Margin = new Padding(0, 2, 0, 0); PageBox.Paint += page_Painit; PageBox.TextChanged += Pagebox_TextChanged; this.Controls.Add(PageBox); Label labelRangePage = new Label(); labelRangePage.AutoSize = false; labelRangePage.Size = new Size(30, 30); labelRangePage.Text = "页"; labelRangePage.Margin = new Padding(0, 0, 2, 0); labelRangePage.TextAlign = ContentAlignment.MiddleCenter; labelRangePage.BackColor = PageUnCheckBackColor; this.Controls.Add(labelRangePage); Label label_Sure = new Label(); label_Sure.AutoSize = false; label_Sure.Size = new Size(50, 30); label_Sure.Text = "确定"; label_Sure.Margin = new Padding(0, 0, 2, 0); label_Sure.TextAlign = ContentAlignment.MiddleCenter; label_Sure.BackColor = PageUnCheckBackColor; label_Sure.Paint += page_Painit; label_Sure.Click += label_Sure_Click; label_Sure.MouseLeave += label_Sure_MouseLeave_Click; label_Sure.MouseEnter += label_Sure_MouseEnter_Click; this.Controls.Add(label_Sure); Label labelSum = new Label(); labelSum.AutoSize = false; labelSum.Size = new Size(80, 30); labelSum.Text = "共 " + page + " 条"; labelSum.Margin = new Padding(0, 0, 2, 0); labelSum.TextAlign = ContentAlignment.MiddleCenter; labelSum.BackColor = PageUnCheckBackColor; this.Controls.Add(labelSum); DropPage(); } private void DealPage(int SumPage) { this.SumPage = SumPage; page = SumPage % PageSize > 0 ? SumPage / PageSize + 1 : SumPage / PageSize; pages = new List<Label>(); if (page < 7) { for (int i = 1; i <= page; i++) { Label label = new Label(); label.Parent = this; label.AutoSize = false; label.Size = new Size(30, 30); label.Text = i.ToString(); label.Tag = i; label.Margin = new Padding(0, 0, 2, 0); label.TextAlign = ContentAlignment.MiddleCenter; label.BackColor = PageUnCheckBackColor; label.Paint += page_Painit; label.Click += Label_Click; label.MouseLeave += label_MouseLeave_Click; label.MouseEnter += label_MouseEnter_Click; this.Controls.Add(label); pages.Add(label); } pages[0].BackColor = PageCheckBackColor; pages[0].ForeColor = PageCheckFontColor; CurrentPageControl = pages[0]; } else { string[] PageArr = new string[] { "1","...","2","3","4","5","6","...",page.ToString() }; for (int i = 0; i < PageArr.Length; i++) { Label label = new Label(); label.Parent = this; label.AutoSize = false; label.Text = PageArr[i]; if (i == 1) { label.Size = new Size(50, 30); label.Tag = -1; label.BackColor = PageUnCheckBackColor; label.Visible = false; labelLeft = label; } else if (i == 7) { label.BackColor = PageUnCheckBackColor; label.Size = new Size(50, 30); label.Tag = 0; labelRight = label; } else { label.Size = new Size(30, 30); label.Tag = int.Parse(PageArr[i]); label.Click += Label_Click; if (i == 6) label.Visible = false; label.BackColor = PageUnCheckBackColor; label.MouseLeave += label_MouseLeave_Click; label.MouseEnter += label_MouseEnter_Click; if (i > 1 && i < 7) pages.Add(label); if (i == 0) { label.BackColor = PageCheckBackColor; label.ForeColor = PageCheckFontColor; CurrentPageControl = label; label_StartPage = label; } if (i == 8) label_EndPage = label; } label.Margin = new Padding(0, 0, 2, 0); label.TextAlign = ContentAlignment.MiddleCenter; label.Paint += page_Painit; this.Controls.Add(label); } } // if (PageEvent != null) PageEvent.Invoke(CurrentPageControl, new PageEventArgs(1, this.PageSize)); } private void DropPage() { Drop = new Label(); Drop.AutoSize = false; Drop.Size = new Size(60, 30); Drop.Text = this.PageSize.ToString(); Drop.Tag = this.PageSize; Drop.Margin = new Padding(0, 0, 10, 0); Drop.TextAlign = ContentAlignment.MiddleLeft; Drop.ImageAlign = ContentAlignment.MiddleRight; Drop.Image = Properties.Resources.bottom_pull; Drop.BackColor = PageUnCheckBackColor; Drop.Paint += page_Painit; Drop.Click += Drop_Click; Drop.MouseLeave += Drop_MouseLeave_Click; Drop.MouseEnter += Drop_MouseEnter_Click; this.Controls.Add(Drop); flowLayoutPanel=new FlowLayoutPanel(); flowLayoutPanel.Width = 60; int height = 0; for (int i = 0; i < PageArr.Length; i++) { Label label = new Label(); label.Tag = PageArr[i]; label.Text = PageArr[i].ToString() ; label.AutoSize = false; label.Height = 30; label.Width = 60; label.TextAlign = ContentAlignment.MiddleCenter; label.BackColor = PageUnCheckBackColor; label.Click += DropItem_Click; label.MouseEnter += Dropitem_MouseEnterClick; label.MouseLeave += Dropitem_MouseLeaveClick; label.Paint += Drop_Paint; height +=30; flowLayoutPanel.Controls.Add(label); } //如果子项的高大于下拉框的4倍高度,某人为4倍高度 if (height > 30 * 4) { flowLayoutPanel.Height = 30 * 4; } else//如果小于4倍高度,那么就等于累计高度 { flowLayoutPanel.Height = height; } } private void Drop_Paint(object? sender, PaintEventArgs e) { Control control = sender as Control; ControlPaint.DrawBorder(e.Graphics,//获取进行绘制的图形 new Rectangle(0, 0, control.Width, control.Height),//绘制控件所在工作区域 Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid,//边框类型,选择实线边框,也有虚线等种类;下面这四个重复的传参是设置工作区上下左右边框的功能 Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid, Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid, Color.FromArgb(224, 224, 224), 1, ButtonBorderStyle.Solid); } private void Dropitem_MouseLeaveClick(object? sender, EventArgs e) { var label = sender as Label; label.Cursor = Cursors.Hand; label.BackColor = PageUnCheckBackColor; label.ForeColor = PageUnCheckFontColor; } private void Dropitem_MouseEnterClick(object? sender, EventArgs e) { var label = sender as Label; label.BackColor = PageCheckBackColor; label.ForeColor =PageCheckFontColor; } private void DropItem_Click(object? sender, EventArgs e) { var label = sender as Label; this.Controls.Clear(); this.PageSize = (int)label.Tag; this.Drop.Text = label.Tag.ToString(); SetPage(this.SumPage); if (PageEvent != null) PageEvent.Invoke(CurrentPageControl, new PageEventArgs(1, this.PageSize)); pop.Close(); } private void Drop_MouseEnter_Click(object? sender, EventArgs e) { var label = sender as Label; label.BackColor = PageEneterColor; } private void Drop_MouseLeave_Click(object? sender, EventArgs e) { var label = sender as Label; label.Cursor = Cursors.Hand; label.BackColor = PageUnCheckBackColor; label.ForeColor = PageUnCheckFontColor; } private void Drop_Click(object? sender, EventArgs e) { Label label = sender as Label; pop = new Popup(flowLayoutPanel); pop.Show(label); } /// <summary> /// 点击页码或者点击上一页,写一页按钮 /// </summary> /// <param name="currentpage"></param> /// <param name="label"></param> private void PrePage(int currentpage, Label label) { CurrentPageControl.BackColor = PageUnCheckBackColor; CurrentPageControl.ForeColor = PageUnCheckFontColor; if (page < 7) CurrentPageControl = label; else { int count = 0; if (currentpage - 1 < 4) { CurrentPageControl = label; if (currentpage == 4 && pages[0].Visible == true) { for (int i = 2; i < 6; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == currentpage) CurrentPageControl = pages[count]; count++; } } if (currentpage <= 3 && labelLeft.Visible == true) { for (int i = 2; i < 6; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == currentpage) CurrentPageControl = pages[1]; count++; } } if (labelLeft.Visible == true) labelLeft.Visible = false; if (pages[4].Visible == true) pages[4].Visible = false; if (pages[0].Visible == false) pages[0].Visible = true; if (labelRight.Visible == false) labelRight.Visible = true; } else { if (page - currentpage < 4) { CurrentPageControl = label; if (page - currentpage == 3 && labelRight.Visible == true) { if (pages[4].Visible == false) pages[4].Visible = true; for (int i = currentpage - 2; i < currentpage + 3; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == currentpage) CurrentPageControl = pages[count]; count++; } } if (pages[0].Visible == false) pages[0].Visible = true; if (page - currentpage == 3 && labelRight.Visible == false) { for (int i = currentpage - 2; i < currentpage + 3; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (count == 2) CurrentPageControl = pages[2]; count++; } } if (page - currentpage < 3) { if (pages[0].Visible == true) pages[0].Visible = false; if (pages[4].Visible == false) pages[4].Visible = true; for (int i = page - 5; i < page; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == currentpage) CurrentPageControl = pages[count]; count++; } } if (labelLeft.Visible == false) labelLeft.Visible = true; if (labelRight.Visible == true) labelRight.Visible = false; } else { if (pages[0].Visible == false) pages[0].Visible = true; if (pages[4].Visible == false) pages[4].Visible = true; if (labelLeft.Visible == false) labelLeft.Visible = true; if (labelRight.Visible == false) labelRight.Visible = true; for (int i = currentpage - 2; i < currentpage + 3; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == currentpage) CurrentPageControl = pages[count]; count++; } } } } CurrentPageControl.BackColor = PageCheckBackColor; CurrentPageControl.ForeColor = PageCheckFontColor; if (PageEvent != null) PageEvent.Invoke(currentpage,new PageEventArgs((int)label.Tag,this.PageSize)); } /// <summary> /// 跳转页,点击跳转到某一页 /// </summary> /// <param name="pageCount"></param> private void PageSure(int pageCount) { if (pageCount > 0 && pageCount <= page) { CurrentPageControl.BackColor = PageUnCheckBackColor; CurrentPageControl.ForeColor = PageUnCheckFontColor; if (page < 7) { pages.ForEach(m => { if ((int)m.Tag == pageCount) CurrentPageControl = m; }); } else { int count = 0; if (pageCount < 5) { CurrentPageControl = label_StartPage; for (int i = 2; i < 6; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == pageCount) CurrentPageControl = pages[count]; count++; } if (labelLeft.Visible == true) labelLeft.Visible = false; if (labelRight.Visible == false) labelRight.Visible = true; if (pages[0].Visible == false) pages[0].Visible = true; if (pages[4].Visible == true) pages[4].Visible = false; } else { if (labelRight.Visible == true) labelRight.Visible = false; if (pages[0].Visible == true) pages[0].Visible = false; if (pages[4].Visible == false) pages[4].Visible = true; //如果选中的是最后一页 CurrentPageControl = label_EndPage; if (page - pageCount <= 3) { if (page - pageCount == 3) if (pages[0].Visible == false) pages[0].Visible = true; for (int i = page - 5; i < page; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == pageCount) CurrentPageControl = pages[count]; count++; } } else { for (int i = pageCount - 2; i < pageCount + 3; i++) { pages[count].Tag = i; pages[count].Text = i.ToString(); if (i == pageCount) CurrentPageControl = pages[count]; count++; } if (labelRight.Visible == false) labelRight.Visible = true; if (pages[0].Visible == false) pages[0].Visible = true; if (pages[4].Visible == false) pages[4].Visible = true; } if (labelLeft.Visible == false) labelLeft.Visible = true; } } } else PageBox.Text = ""; CurrentPageControl.BackColor = PageCheckBackColor; CurrentPageControl.ForeColor = PageCheckFontColor; if (PageEvent != null) PageEvent.Invoke(CurrentPageControl, new PageEventArgs(pageCount, this.PageSize)); } }
cpPageComponent1.SetPage(200);
效果:
PopUp:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SimpleUI.Pop { internal struct GripBounds { private const int GripSize = 6; private const int CornerGripSize = 12; private Rectangle clientRectangle; public Rectangle ClientRectangle => clientRectangle; public Rectangle Bottom { get { Rectangle result = ClientRectangle; result.Y = result.Bottom - 6 + 1; result.Height = 6; return result; } } public Rectangle BottomRight { get { Rectangle result = ClientRectangle; result.Y = result.Bottom - 12 + 1; result.Height = 12; result.X = result.Width - 12 + 1; result.Width = 12; return result; } } public Rectangle Top { get { Rectangle result = ClientRectangle; result.Height = 6; return result; } } public Rectangle TopRight { get { Rectangle result = ClientRectangle; result.Height = 12; result.X = result.Width - 12 + 1; result.Width = 12; return result; } } public Rectangle Left { get { Rectangle result = ClientRectangle; result.Width = 6; return result; } } public Rectangle BottomLeft { get { Rectangle result = ClientRectangle; result.Width = 12; result.Y = result.Height - 12 + 1; result.Height = 12; return result; } } public Rectangle Right { get { Rectangle result = ClientRectangle; result.X = result.Right - 6 + 1; result.Width = 6; return result; } } public Rectangle TopLeft { get { Rectangle result = ClientRectangle; result.Width = 12; result.Height = 12; return result; } } public GripBounds(Rectangle clientRectangle) { this.clientRectangle = clientRectangle; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace SimpleUI.Pop { internal class UnsafeMethods { public enum TrackerEventFlags : uint { TME_HOVER = 1u, TME_LEAVE = 2u, TME_QUERY = 0x40000000u, TME_CANCEL = 0x80000000u } internal struct TRACKMOUSEEVENT { public uint cbSize; public uint dwFlags; public IntPtr hwndTrack; public uint dwHoverTime; } internal struct MINMAXINFO { public Point reserved; public Size maxSize; public Point maxPosition; public Size minTrackSize; public Size maxTrackSize; } internal struct RECT { public int left; public int top; public int right; public int bottom; public Rectangle Rect => new Rectangle(left, top, right - left, bottom - top); public RECT(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } public static RECT FromXYWH(int x, int y, int width, int height) { return new RECT(x, y, x + width, y + height); } public static RECT FromRectangle(Rectangle rect) { return new RECT(rect.Left, rect.Top, rect.Right, rect.Bottom); } } internal struct WINDOWPOS { internal IntPtr hwnd; internal IntPtr hWndInsertAfter; internal int x; internal int y; internal int cx; internal int cy; internal uint flags; } public struct NCCALCSIZE_PARAMS { public RECT rectProposed; public RECT rectBeforeMove; public RECT rectClientBeforeMove; public WINDOWPOS lpPos; } public const int WM_LBUTTONDOWN = 513; public const int WM_RBUTTONDOWN = 516; public const int WM_MBUTTONDOWN = 519; public const int WM_NCLBUTTONDOWN = 161; public const int WM_NCRBUTTONDOWN = 164; public const int WM_NCMBUTTONDOWN = 167; public const int WM_NCCALCSIZE = 131; public const int WM_NCHITTEST = 132; public const int WM_NCPAINT = 133; public const int WM_NCACTIVATE = 134; public const int WM_MOUSELEAVE = 675; public const int WS_EX_NOACTIVATE = 134217728; public const int HTTRANSPARENT = -1; public const int HTLEFT = 10; public const int HTRIGHT = 11; public const int HTTOP = 12; public const int HTTOPLEFT = 13; public const int HTTOPRIGHT = 14; public const int HTBOTTOM = 15; public const int HTBOTTOMLEFT = 16; public const int HTBOTTOMRIGHT = 17; public const int WM_USER = 1024; public const int WM_REFLECT = 8192; public const int WM_COMMAND = 273; public const int CBN_DROPDOWN = 7; public const int WM_GETMINMAXINFO = 36; public static readonly IntPtr TRUE = new IntPtr(1); public static readonly IntPtr FALSE = new IntPtr(0); [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("user32.dll")] public static extern int ReleaseDC(IntPtr hwnd, IntPtr hDC); [DllImport("user32")] public static extern bool TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack); [DllImport("user32.dll")] public static extern bool SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); internal static int HIWORD(int n) { return (n >> 16) & 0xFFFF; } internal static int HIWORD(IntPtr n) { return HIWORD((int)(long)n); } internal static int LOWORD(int n) { return n & 0xFFFF; } internal static int LOWORD(IntPtr n) { return LOWORD((int)(long)n); } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing.Drawing2D; using System.Linq; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using System.Windows.Forms.VisualStyles; namespace SimpleUI.Pop { [ToolboxItem(false)] public class Popup : ToolStripDropDown { private const int frames = 5; private const int totalduration = 100; private const int frameduration = 20; private Control content; private bool fade; private bool focusOnOpen = true; private bool acceptAlt = true; private Popup ownerPopup; private Popup childPopup; private bool _resizable; private bool resizable; private ToolStripControlHost host; private Size minSize; private Size maxSize; private bool _isOpen; private bool resizableTop; private bool resizableLeft; private VisualStyleRenderer sizeGripRenderer; public Control Content => content; public bool UseFadeEffect { get { return fade; } set { if (fade != value) { fade = value; } } } public bool FocusOnOpen { get { return focusOnOpen; } set { focusOnOpen = value; } } public bool AcceptAlt { get { return acceptAlt; } set { acceptAlt = value; } } public bool Resizable { get { return resizable && _resizable; } set { resizable = value; } } public new Size MinimumSize { get { return minSize; } set { minSize = value; } } public new Size MaximumSize { get { return maxSize; } set { maxSize = value; } } public bool IsOpen => _isOpen; protected override CreateParams CreateParams { [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] get { CreateParams createParams = base.CreateParams; createParams.ExStyle |= 134217728; return createParams; } } public Popup(Control content) { Popup popup = this; if (content == null) { throw new ArgumentNullException("content"); } this.content = content; fade = SystemInformation.IsMenuAnimationEnabled && SystemInformation.IsMenuFadeEnabled; _resizable = true; AutoSize = false; DoubleBuffered = true; base.ResizeRedraw = true; host = new ToolStripControlHost(content); base.Padding = (base.Margin = (host.Padding = (host.Margin = Padding.Empty))); MinimumSize = content.MinimumSize; content.MinimumSize = content.Size; MaximumSize = content.MaximumSize; content.MaximumSize = content.Size; base.Size = content.Size; content.Location = Point.Empty; Items.Add(host); content.Disposed += delegate { content = null; popup.Dispose(disposing: true); }; content.RegionChanged += delegate { UpdateRegion(); }; content.Paint += delegate (object sender, PaintEventArgs e) { PaintSizeGrip(e); }; UpdateRegion(); } protected override bool ProcessDialogKey(Keys keyData) { if (acceptAlt && (keyData & Keys.Alt) == Keys.Alt) { if ((keyData & Keys.F4) != Keys.F4) { return false; } Close(); } return base.ProcessDialogKey(keyData); } protected void UpdateRegion() { if (base.Region != null) { base.Region.Dispose(); base.Region = null; } if (content.Region != null) { base.Region = content.Region.Clone(); } } public void Show(Control control) { Show(control, control.ClientRectangle); } public void Show(Control control, bool center) { Show(control, control.ClientRectangle, center); } public void Show(Control control, Rectangle area) { Show(control, area, center: false); } public void Show(Control control, Rectangle area, bool center) { if (control == null) { throw new ArgumentNullException("control"); } SetOwnerItem(control); resizableTop = (resizableLeft = false); Point p = control.PointToScreen(new Point(area.Left, area.Top + area.Height)); Rectangle workingArea = Screen.FromControl(control).WorkingArea; if (center) { if (p.X + (area.Width + base.Size.Width) / 2 > workingArea.Right) { resizableLeft = true; p.X = workingArea.Right - base.Size.Width; } else { resizableLeft = true; p.X -= (base.Size.Width - area.Width) / 2; } } else if (p.X + base.Size.Width > workingArea.Left + workingArea.Width) { resizableLeft = true; p.X = workingArea.Left + workingArea.Width - base.Size.Width; } if (p.Y + base.Size.Height > workingArea.Top + workingArea.Height) { resizableTop = true; p.Y -= base.Size.Height + area.Height; } p = control.PointToClient(p); Show(control, p, ToolStripDropDownDirection.BelowRight); } protected override void SetVisibleCore(bool visible) { double opacity = base.Opacity; if (visible && fade && focusOnOpen) { base.Opacity = 0.0; } base.SetVisibleCore(visible); if (!visible || !fade || !focusOnOpen) { return; } for (int i = 1; i <= 5; i++) { if (i > 1) { Thread.Sleep(20); } base.Opacity = opacity * (double)i / 5.0; } base.Opacity = opacity; } private void SetOwnerItem(Control control) { if (control != null) { if (control is Popup) { Popup popup = (ownerPopup = control as Popup); ownerPopup.childPopup = this; base.OwnerItem = popup.Items[0]; } else if (control.Parent != null) { SetOwnerItem(control.Parent); } } } protected override void OnSizeChanged(EventArgs e) { content.MinimumSize = base.Size; content.MaximumSize = base.Size; content.Size = base.Size; content.Location = Point.Empty; base.OnSizeChanged(e); } protected override void OnOpening(CancelEventArgs e) { if (content.IsDisposed || content.Disposing) { e.Cancel = true; return; } UpdateRegion(); base.OnOpening(e); } protected override void OnOpened(EventArgs e) { if (ownerPopup != null) { ownerPopup._resizable = false; } if (focusOnOpen) { content.Focus(); } _isOpen = true; base.OnOpened(e); } protected override void OnClosed(ToolStripDropDownClosedEventArgs e) { if (ownerPopup != null) { ownerPopup._resizable = true; } _isOpen = false; base.OnClosed(e); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { if (!InternalProcessResizing(ref m, contentControl: false)) { base.WndProc(ref m); } } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] public bool ProcessResizing(ref Message m) { return InternalProcessResizing(ref m, contentControl: true); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] private bool InternalProcessResizing(ref Message m, bool contentControl) { if (m.Msg == 134 && m.WParam != IntPtr.Zero && childPopup != null && childPopup.Visible) { childPopup.Hide(); } if (!Resizable) { return false; } if (m.Msg == 132) { return OnNcHitTest(ref m, contentControl); } if (m.Msg == 36) { return OnGetMinMaxInfo(ref m); } return false; } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] private bool OnGetMinMaxInfo(ref Message m) { UnsafeMethods.MINMAXINFO mINMAXINFO = (UnsafeMethods.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(UnsafeMethods.MINMAXINFO)); mINMAXINFO.maxTrackSize = MaximumSize; mINMAXINFO.minTrackSize = MinimumSize; Marshal.StructureToPtr((object)mINMAXINFO, m.LParam, fDeleteOld: false); return true; } private bool OnNcHitTest(ref Message m, bool contentControl) { int x = UnsafeMethods.LOWORD(m.LParam); int y = UnsafeMethods.HIWORD(m.LParam); Point pt = PointToClient(new Point(x, y)); GripBounds gripBounds = new GripBounds(contentControl ? content.ClientRectangle : base.ClientRectangle); IntPtr intPtr = new IntPtr(-1); if (resizableTop) { if (resizableLeft && gripBounds.TopLeft.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)13)); return true; } if (!resizableLeft && gripBounds.TopRight.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)14)); return true; } if (gripBounds.Top.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)12)); return true; } } else { if (resizableLeft && gripBounds.BottomLeft.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)16)); return true; } if (!resizableLeft && gripBounds.BottomRight.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)17)); return true; } if (gripBounds.Bottom.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)15)); return true; } } if (resizableLeft && gripBounds.Left.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)10)); return true; } if (!resizableLeft && gripBounds.Right.Contains(pt)) { m.Result = (contentControl ? intPtr : ((IntPtr)11)); return true; } return false; } public void PaintSizeGrip(PaintEventArgs e) { if (e == null || e.Graphics == null || !resizable) { return; } Size clientSize = content.ClientSize; using Bitmap image = new Bitmap(16, 16); using (Graphics graphics = Graphics.FromImage(image)) { if (Application.RenderWithVisualStyles) { if (sizeGripRenderer == null) { sizeGripRenderer = new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal); } sizeGripRenderer.DrawBackground(graphics, new Rectangle(0, 0, 16, 16)); } else { ControlPaint.DrawSizeGrip(graphics, content.BackColor, 0, 0, 16, 16); } } GraphicsState gstate = e.Graphics.Save(); e.Graphics.ResetTransform(); if (resizableTop) { if (resizableLeft) { e.Graphics.RotateTransform(180f); e.Graphics.TranslateTransform(-clientSize.Width, -clientSize.Height); } else { e.Graphics.ScaleTransform(1f, -1f); e.Graphics.TranslateTransform(0f, -clientSize.Height); } } else if (resizableLeft) { e.Graphics.ScaleTransform(-1f, 1f); e.Graphics.TranslateTransform(-clientSize.Width, 0f); } e.Graphics.DrawImage(image, clientSize.Width - 16, clientSize.Height - 16 + 1, 16, 16); e.Graphics.Restore(gstate); } } }
.Net Core
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)