Windows 将多个控件合二为一
Posted
技术标签:
【中文标题】Windows 将多个控件合二为一【英文标题】:Windows Forms Multiple Controls In One 【发布时间】:2021-02-18 07:07:37 【问题描述】:我想请教一些建议。我在 Windows 窗体编程方面没有足够的经验,所以我不知道处理此任务的适当方法是什么。
我目前正在从四个面板创建一个矩形。 (这些矩形不代表下面的代码,它们使用不同的大小)
private System.Windows.Forms.Panel rectangleLeftVertical;
private System.Windows.Forms.Panel rectangleRightVertical;
private System.Windows.Forms.Panel rectangleTopHorizontal;
private System.Windows.Forms.Panel rectangleBottomHorizontal;
// ...
this.rectangleLeftVertical.Location = new System.Drawing.Point(100, 100);
this.rectangleLeftVertical.Size = new System.Drawing.Size(3, 100);
this.rectangleRightVertical.Location = new System.Drawing.Point(200, 100);
this.rectangleRightVertical.Size = new System.Drawing.Size(3, 100);
this.rectangleTopHorizontal.Location = new System.Drawing.Point(100, 100);
this.rectangleTopHorizontal.Size = new System.Drawing.Size(100, 3);
this.rectangleBottomHorizontal.Location = new System.Drawing.Point(100, 200);
this.rectangleBottomHorizontal.Size = new System.Drawing.Size(103, 3);
它完全按照我的意愿工作,我只想将所有内容封装到一个自定义 Windows 控件中。 自定义组件大小当然应该调整面板的大小。它还有一个属性来决定边框的大小。
我不想改变任何东西,我不想以不同的方式进行绘图(使用 graphics.paint 解决方案)。它不适合我的用例。
我尝试使用 UserControl,但是它不合适,因为它会绘制矩形的整个内部 - 这是我要避免的。
如果它也可以在 Windows 窗体设计器中使用,那就更好了 - 但这是非常不必要的。不过那真的很好。
你们建议我如何解决这个问题?任何帮助将非常感激。这可能不是一个难题,我只是缺乏经验。谢谢!
【问题讨论】:
当你说绘画时,你的意思是面板被重新绘画以响应调整大小事件? 如果你需要一条不同颜色的线你会怎么做?像你这样画线非常效率低下,我怀疑你有支持你的“用户案例”的论据,而且你已经遇到了处理背景的问题。 @RossBush 我不确定你指的是什么。我需要矩形的内部完全透明,因为我有另一个进程停靠在它下面的面板上 - 因此使用任何类型的 Color.Transparent 都不起作用(它将隐藏边框内的内容)。 控件使用完全相同的“缓慢且非常闪烁”技术重新绘制自己。换句话说,您不是在快速绘制线条,而是在创建另一个窗口,所有开销(事件循环、内存、资源)都......绘制线条。无意冒犯,我试图说服您编写自定义控件(就像我之前评论中的那个),为其添加属性并正确进行。 这个问题可能会导致xy problem 【参考方案1】:您可以通过创建一个表示您要保留/丢弃的表单区域的 GraphicsPath 对象来实现此目的。从覆盖整个表单的矩形开始,然后删除面板的中间部分,只留下边框。然后从该 GraphicsPath 构建一个 Region 并将其分配给 Form 的 Region 属性。这将产生一个仅存在于边框所在的表单。从 GraphicsPath 中删除的中间区域在您的表单中实际上将不存在,因此覆盖下方的任何内容都将直接显示。
这里有一个简单的例子,它制作了一个可以通过窗格的边框拖动的四窗格“窗口”:
public partial class Form1 : Form
public Form1()
InitializeComponent();
this.TopMost = true;
this.BackColor = Color.Red; // just so you can see it better
this.FormBorderStyle = FormBorderStyle.None;
private void Form1_Shown(object sender, EventArgs e)
GraphicsPath path = new GraphicsPath();
// add the main rectangle:
path.AddRectangle(new Rectangle(new Point(0, 0), this.Size));
// punch some holes in our main rectangle
// this will make a standard "windowpane" with four panes
// and a border width of ten pixels
Size sz = new Size((this.Width - (3 * 10))/2, (this.Height - (3 * 10))/2);
path.FillMode = FillMode.Alternate;
path.AddRectangle(new Rectangle(new Point(10, 10), sz));
path.AddRectangle(new Rectangle(new Point(20 + sz.Width, 10), sz));
path.AddRectangle(new Rectangle(new Point(10, 20 + sz.Height), sz));
path.AddRectangle(new Rectangle(new Point(20 + sz.Width, 20 + sz.Height), sz));
// build a region from our path and set the forms region to that:
this.Region = new Region(path);
public const int HTCAPTION = 0x2;
public const int WM_NCHITTEST = 0x84;
public const int HTCLIENT = 1;
protected override void WndProc(ref Message m)
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
if (m.Result.ToInt32() == HTCLIENT)
m.Result = (IntPtr)HTCAPTION;
在我编辑时在此页面顶部运行的示例:
如果您的叠加层可以调整大小和/或调整,只需重建一个新的 GraphicsPath,更改矩形并重新分配从新 GraphicsPath 构建的区域。
您也可以删除主窗体的.Opacity
,这样您就可以看到部分边框了。
【讨论】:
太棒了!这比我想要的还要好。非常感谢!我在 UserControl 而不是单独的表单中使用它,这当然也适用于相同的逻辑。竖起大拇指?以上是关于Windows 将多个控件合二为一的主要内容,如果未能解决你的问题,请参考以下文章
具有多个页面的 Windows Phone 8.1 自定义控件