简体   繁体   English

如何显示覆盖面板控件中所有内容的矩形?

[英]How can I display a rectangle that overlaps everything in a panel control?

I want to display a rectangle drawing over EVERYTHING inside of a panel control. 我想在面板控件的所有内容上显示一个矩形图。 I only have a WebBrowser in the panel control as of now. 到目前为止,面板控件中只有一个WebBrowser。 If I start run the program WITHOUT adding the WebBrowser to the panel control, then I will be able to see the rectangle. 如果我开始运行程序而没有将WebBrowser添加到面板控件中,那么我将能够看到矩形。 But, if I add the WebBrowser to the panel control, then it will overlap my rectangle drawing. 但是,如果我将WebBrowser添加到面板控件中,则它将与我的矩形图重叠。

How can I create a rectangle drawing INSIDE of a panel control, that will overlap everything? 如何在面板控件的内部创建一个矩形图,该矩形图将覆盖所有内容? (always on top) (总在最前面)

The code below will draw a blue rectangle inside of the panel control. 下面的代码将在面板控件内绘制一个蓝色矩形。 But it will not be shown, because the panel contains a WebBrowser. 但是它不会显示,因为该面板包含一个WebBrowser。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Graphics_Overlay
{
    public partial class GraphicsOverlayForm : Form
    {
        public GraphicsOverlayForm()
        {
            InitializeComponent();

            Panel panel = new Panel();
            panel.Dock = DockStyle.Fill;
            panel.Paint += panel_Paint;

            WebBrowser webBrowser = new WebBrowser();
            webBrowser.Dock = DockStyle.Fill;
            webBrowser.Url = new Uri("http://stackoverflow.com/");

            Controls.Add(panel);

            // If I comment out the line below then I will
            // be able to see my blue rectangle.
            panel.Controls.Add(webBrowser);
        }

        private void panel_Paint(object sender, PaintEventArgs e)
        {
            ShowLineJoin(e);
        }

        private void ShowLineJoin(PaintEventArgs e)
        {
            // Create a new pen.
            Pen skyBluePen = new Pen(Brushes.Blue);

            // Set the pen's width.
            skyBluePen.Width = 1;

            // Set the LineJoin property.
            skyBluePen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;

            // Draw a rectangle.
            e.Graphics.DrawRectangle(skyBluePen,
                new Rectangle(0, 0, 200, 200));

            //Dispose of the pen.
            skyBluePen.Dispose();
        }
    }
}

This is not possible. 这是不可能的。 If you add the WebBrowser as a child control of the panel, it will be displayed on top of the Panel's background area. 如果将WebBrowser添加为面板的子控件,它将显示面板背景区域的顶部 The Panel's background area is, of course, where you are drawing the blue rectangle. 当然,面板的背景区域是绘制蓝色矩形的位置。 Your drawing is still there, the WebBrowser control is just being displayed on top of it. 您的图形仍然存在,WebBrowser控件仅显示在其顶部。

There are three possible solutions that come to mind, listed here in no particular order: 我想到了三种可能的解决方案,这里没有按特定顺序列出:

  1. Set the Visible property of the WebBrowser control to false whenever you want the blue rectangle (or whatever is drawn on the background of the Panel control to be visible). 每当您希望蓝色矩形(或在Panel控件的背景上绘制的任何内容都可见)时,请将WebBrowser控件的Visible属性设置为false Set WebBrowser.Visible to true again so that the WebBrowser control can be used. 再次将WebBrowser.Visible设置为true ,以便可以使用WebBrowser控件。

  2. Rather than adding the WebBrowser control as a child control of the Panel, which is in turn a child control of the container form, add both the Panel and WebBrowser control as children of your container form. 而不是将WebBrowser控件添加为Panel的子控件(后者又是容器窗体的子控件),而是将Panel和WebBrowser控件都添加为容器窗体的子控件。 In other words, flatten the hierarchy. 换句话说,扁平化层次结构。 Because this removes the parent-child relationship, you can now alter the Z order of the controls, changing which one is visible. 因为这消除了父子关系,所以您现在可以更改控件的Z顺序,从而更改可见的控件。 This is trivial in WinForms using the SendToBack and BringToFront member functions. 在WinForms中,使用SendToBackBringToFront成员函数很简单。

  3. Create a new control, named something like BlueRectangle or DrawingSurface or whatever, that inherits from System.Windows.Forms.Control . 创建一个控件,该控件的名称类似于BlueRectangleDrawingSurface或其他名称,该控件继承自System.Windows.Forms.Control Override its OnPaint event and put your drawing code there. 覆盖其OnPaint事件,并将您的绘图代码放在此处。 Add an instance of this control class to your Panel control, as a child. 将此控件类的实例作为子级添加到Panel控件中。 Effectively, then, your Panel control will have two children: a BlueRectangle control and a WebBrowser control. 实际上,您的Panel控件将具有两个子控件: BlueRectangle控件和WebBrowser控件。 Shuffle back and forth between the two by changing the Z order, as described above, with SendToBack and BringToFront . 如上所述,通过使用SendToBackBringToFront更改Z顺序在两者之间来回BringToFront

On an unrelated note, you should prefer the using statement as a way of ensuring that an object implementing IDisposable is automatically disposed, rather than explicitly calling the Dispose method. 无关紧要的是,您应该首选using语句,以确保自动处置实现IDisposable的对象,而不是显式调用Dispose方法。 For example, write your ShowLineJoin method like this: 例如,这样编写ShowLineJoin方法:

private void ShowLineJoin(PaintEventArgs e)
{
    // Create a new pen with the specified color and width.
    using (Pen skyBluePen = new Pen(Brushes.Blue, 1))
    {
        // Set the LineJoin property.
        skyBluePen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;

        // Draw a rectangle.
        e.Graphics.DrawRectangle(skyBluePen,
        new Rectangle(0, 0, 200, 200));
    }
}

Simpler, easier to read, and safer. 更简单,更易读,更安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM