Popover.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Drawing2D;
  4. using System.Windows.Forms;
  5. namespace travelExport
  6. {
  7. public partial class Popover : Form
  8. {
  9. private int triangleSize = 10; // 小三角的边长
  10. private int triangleOffset; // 小三角的水平偏移量(相对于弹出框)
  11. public Popover()
  12. {
  13. // 初始化弹出框样式
  14. this.FormBorderStyle = FormBorderStyle.None; // 无边框
  15. this.StartPosition = FormStartPosition.Manual; // 手动设置位置
  16. this.BackColor = Color.White; // 背景颜色
  17. this.Padding = new Padding(10); // 内边距
  18. this.ShowInTaskbar = false; // 不在任务栏显示
  19. this.Opacity = 0.95; // 设置透明度
  20. this.Size = new Size(300, 150); // 默认大小
  21. // 圆角边框设置
  22. this.Load += (s, e) => ApplyRoundedCorners();
  23. // 当弹出框失去焦点时关闭
  24. this.Deactivate += (s, e) => this.Close();
  25. // 添加内容
  26. Label label = new Label
  27. {
  28. Text = "这是一个带指向箭头的圆角弹出框",
  29. AutoSize = true,
  30. Dock = DockStyle.Top
  31. };
  32. Button button = new Button
  33. {
  34. Text = "确认",
  35. Dock = DockStyle.Bottom
  36. };
  37. button.Click += (s, e) => this.Close(); // 点击关闭弹出框
  38. this.Controls.Add(button);
  39. //this.Controls.Add(label);
  40. }
  41. // 圆角和三角指向处理
  42. private void ApplyRoundedCorners()
  43. {
  44. int cornerRadius = 20; // 圆角半径
  45. var path = new GraphicsPath();
  46. // 绘制上方圆角矩形
  47. path.AddArc(0, triangleSize, cornerRadius, cornerRadius, 180, 90);
  48. path.AddArc(this.Width - cornerRadius, triangleSize, cornerRadius, cornerRadius, 270, 90);
  49. path.AddArc(this.Width - cornerRadius, this.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90);
  50. path.AddArc(0, this.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
  51. path.CloseFigure();
  52. // 绘制小三角
  53. var triangle = new PointF[]
  54. {
  55. new PointF(triangleOffset - triangleSize / 2, triangleSize),
  56. new PointF(triangleOffset + triangleSize / 2, triangleSize),
  57. new PointF(triangleOffset, 0)
  58. };
  59. path.AddPolygon(triangle);
  60. this.Region = new Region(path);
  61. }
  62. // 根据目标控件的位置调整弹出框的位置
  63. public void AdjustPosition(Control target, int margin = 10)
  64. {
  65. var screenBounds = Screen.FromControl(target).WorkingArea;
  66. var targetBounds = target.RectangleToScreen(target.ClientRectangle);
  67. // 默认弹出框显示在控件下方
  68. var x = targetBounds.Left;
  69. var y = targetBounds.Bottom + margin;
  70. // 如果弹出框超出屏幕右侧,调整到控件右侧
  71. if (x + this.Width > screenBounds.Right)
  72. {
  73. x = screenBounds.Right - this.Width - margin;
  74. }
  75. // 如果弹出框超出屏幕下方,调整到控件上方
  76. if (y + this.Height > screenBounds.Bottom)
  77. {
  78. y = targetBounds.Top - this.Height - margin;
  79. }
  80. // 确保弹出框不会超出屏幕左侧或顶部
  81. x = Math.Max(x, screenBounds.Left + margin);
  82. y = Math.Max(y, screenBounds.Top + margin);
  83. this.Location = new Point(x, y);
  84. // 计算小三角的水平偏移量
  85. triangleOffset = targetBounds.Left + targetBounds.Width / 2 - x;
  86. }
  87. }
  88. }