借鉴控件顶部的面板中(C#的WinForms) [英] Drawing on top of controls inside a panel (C# WinForms)

查看:223
本文介绍了借鉴控件顶部的面板中(C#的WinForms)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经不是几次问多了,但到目前为止,我还没有能够找到一个很好的解决方案吧。

I know this question had been asked more than a few times, but so far I haven't been able to find a good solution for it.

我有一个面板上其他控制。
我想在面板划一条线就可以和所有控件的顶部

I've got a panel with other control on it.
I want to draw a line on it and on top of all the controls in the panel

我遇到了3种解决方案(非他们的工作,我想要的方式):

I came across 3 types of solutions (non of them worked the way I wanted) :

  1. 拿到桌面DC和绘制在屏幕上。
    这将借鉴其他应用程序,如果他们重叠的形式。

  1. Get the desktop DC and Draw on the screen.
    This will draw on other applications if they overlap the form.

覆盖面板的的CreateParams:

Overriding the panel's "CreateParams":

=

protected override CreateParams CreateParams {  
  get {  
    CreateParams cp;  
    cp = base.CreateParams;  
    cp.Style &= ~0x04000000; //WS_CLIPSIBLINGS
    cp.Style &= ~0x02000000; //WS_CLIPCHILDREN
    return cp;  
  }  
}

//注意我也试着禁用WS_CLIPSIBLINGS

//NOTE I've also tried disabling WS_CLIPSIBLINGS

,然后画线的OnPaint()。 但是......由于面板的OnPaint被称为控制在它的OnPaint之前, 控件的绘制里面简单地描绘上线的顶部。
我见过有人建议使用一个消息过滤器来听WM_PAINT mesages,并使用一个计时器,但我不认为这解决方法是好习惯或有效的。
你会怎么做 ?决定内部控制已完成在X毫秒绘制,并设置定时器至X毫秒?


and then drawing the line OnPaint(). But... Since the panel's OnPaint is called before the OnPaint of the controls in it, the drawing of the controls inside simply paints on top of the line.
I've seen someone suggest using a message filter to listen to WM_PAINT mesages, and use a timer, but I don't think this solution is either "good practice" or effective.
What would you do ? Decide that the controls inside have finished drawing after X ms, and set the timer to X ms ?


该屏幕截图显示的面板WS_CLIPSIBLINGS和WS_CLIPCHILDREN关闭。
蓝线是画在小组的OnPaint,并简单地被画上的文本框和标签。
红线画在上面,只是因为它没有被从面板的OnPaint中涂(它实际上描绘成一个按钮被点击的结果)


This screen shot shows the panel with WS_CLIPSIBLINGS and WS_CLIPCHILDREN turned off.
The Blue line is painted at the Panel's OnPaint, and simply being painted on by the textboxes and label.
The Red line is painted on top only because it's not being painted from the panel's OnPaint (It's actually painted as a result of a Button being clicked)


第三:创建透明层和在该层的顶部上绘制
我创建使用透明控制:

3rd: Creating a transparent layer and drawing on top of that layer.
I've created a transparent control using:

protected override CreateParams CreateParams {  
  get {  
    CreateParams cp = base.CreateParams;  
    cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT  
    return cp;  
  }  
}

问题依旧,将在小组及其所有控件的顶部透明的控制。
使用我试着将它停在面前:BringToFront(),但它似乎并没有帮助
。 我已经把它在线路控制的OnPaint()方法处理。
我应该尝试把它在其他地方?
- 这也具有在板的顶部的另一个控制产生问题。 (捕捉鼠标点击等)

The problem is still, putting the transparent control on top of the Panel and all its controls.
I've tried bringing it to the front using: "BringToFront()" , but it didn't seem to help.
I've put it in the Line control's OnPaint() handler.
Should I try putting it somewhere else ??
- This also creates issue with having another control on top of the panel. (catching the mouse clicks etc..)

任何帮助将是很大的AP preciated!

**编辑: 黑线是什么,我试图做一个样本。 (用于Windows画图画吧)

** The black line is a sample of what I was trying to do. (used windows paint to paint it)

推荐答案

原来,这比我想象的容易许多。谢谢你不接受我的任何其他的答案。下面是两个步骤来创建一个 Fline F loating - 对不起,这是已故):

Turns out this is a whole lot easier than I thought. Thanks for not accepting any of my other answers. Here is the two-step process for creating a Fline (floating line - sorry, it's late):

第1步:添加一个用户控件到您的项目,并命名为Fline。添加以下的使用语句:

Step 1: Add a UserControl to your project and name it "Fline". Add the following to the using statements:

using System.Drawing.Drawing2D;

第2步:添加以下到Fline的Resize事件:

Step 2: Add the following to the Fline's Resize event:

int wfactor = 4; // half the line width, kinda
// create 6 points for path
Point[] pts = {
    new Point(0, 0), 
    new Point(wfactor, 0), 
    new Point(Width, Height - wfactor),
    new Point(Width, Height) ,
    new Point(Width - wfactor, Height),
    new Point(0, wfactor) };
// magic numbers! 
byte[] types = {
    0, // start point
    1, // line
    1, // line
    1, // line
    1, // line
    1 }; // line 
GraphicsPath path = new GraphicsPath(pts, types);
this.Region = new Region(path);

编译,然后拖动Fline到窗体或面板。重要提示:默认背景色相同的形式,让修改Fline的背景色为红色或明显的东西(在设计器)。一个奇怪的怪癖这个是当你拖动它周围的设计也显示为固体块,直到你释放它 - 而不是一个巨大的交易

Compile, and then drag a Fline onto your form or panel. Important: the default BackColor is the same as the form, so change the Fline's BackColor to Red or something obvious (in the designer). One weird quirk about this is that when you drag it around in the designer it shows as a solid block until you release it - not a huge deal.

该控件可以出现在前面或后面的任何其他控制。如果设置启用为false,它仍然将是可见的,但不会上的控制鼠标事件干扰下。

This control can appear in front of or behind any other control. If you set Enabled to false, it will still be visible but will not interfere with mouse events on the controls underneath.

您将要提高,这当然你的目的,但是这显示了基本的原则。您可以使用同样的技术来创建任何形状你喜欢(这个我最初的测试取得了三角形)的控制。

You'll want to enhance this for your purposes, of course, but this shows the basic principle. You can use the same technique for creating a control of whatever shape you like (my initial test of this made a triangle).

更新:这使得一个很好的密集一行程序了。只要把这个在你的用户控件的Resize事件:

Update: this makes a nice dense one-liner, too. Just put this in your UserControl's Resize event:

this.Region=new Region(new System.Drawing.Drawing2D.GraphicsPath(new Point[]{new Point(0,0),new Point(4,0),new Point(Width,Height-4),new Point(Width,Height),new Point(Width-4,Height),new Point(0,4)},new byte[]{0,1,1,1,1,1}));

这篇关于借鉴控件顶部的面板中(C#的WinForms)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆