c# - tutorial - windows forms descargar
Dibujando sobre los controles dentro de un panel(C#WinForms) (10)
¿Qué le parece esta solución # 1 (Obtenga el escritorio DC y Draw en la pantalla):
- Obtenga el DC de escritorio y el objeto de gráficos para ese DC [Graphics.fromHDC (...)]
- Establezca la propiedad Clip del objeto Graphics resultante para que sea la región actualmente visible de su formulario. (No he investigado aún cómo encontrar la región visible de un formulario)
- Haz tu renderizado de gráficos
Sé que esta pregunta fue hecha más de una vez, pero hasta ahora no he podido encontrar una buena solución.
Tengo un panel con otro control sobre él.
Quiero trazar una línea sobre él y encima de todos los controles en el panel
Encontré 3 tipos de soluciones (ninguna funcionó como yo quería):
Obtenga el escritorio DC y Draw en la pantalla.
Esto se basará en otras aplicaciones si se superponen al formulario.Anulando los "CreateParams" del panel:
=
protected override CreateParams CreateParams {
get {
CreateParams cp;
cp = base.CreateParams;
cp.Style &= ~0x04000000; //WS_CLIPSIBLINGS
cp.Style &= ~0x02000000; //WS_CLIPCHILDREN
return cp;
}
}
// NOTA También he intentado deshabilitar WS_CLIPSIBLINGS
y luego dibujando la línea OnPaint (). Pero ... Como OnPaint del panel se llama antes que OnPaint de los controles en él, el dibujo de los controles en el interior simplemente pinta en la parte superior de la línea.
He visto a alguien sugerir usar un filtro de mensajes para escuchar los mensajes de WM_PAINT, y usar un temporizador, pero no creo que esta solución sea "buena práctica" o efectiva.
Qué harías ? ¿Decidió que los controles internos habían terminado de dibujarse después de X ms y configuró el temporizador en X ms?
Esta captura de pantalla muestra el panel con WS_CLIPSIBLINGS y WS_CLIPCHILDREN desactivados.
La línea Azul está pintada en el Panel OnPaint, y simplemente está pintada por los cuadros de texto y la etiqueta.
La línea roja está pintada en la parte superior solo porque no está pintada desde el panel OnPaint (en realidad está pintada como resultado del clic de un botón).
3º: crear una capa transparente y dibujar en la parte superior de esa capa.
Creé un control transparente usando:
protected override CreateParams CreateParams {
get {
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
El problema sigue siendo poner el control transparente encima del Panel y todos sus controles.
Intenté llevarlo al frente usando: "BringToFront ()", pero no pareció ayudar.
Lo puse en el controlador OnPaint () del control de línea.
¿Debería intentar ponerlo en otro lugar?
- Esto también crea problemas con tener otro control en la parte superior del panel. (captando los clics del mouse, etc.)
¡Cualquier ayuda sería muy apreciada!
** EDITAR: La línea negra es una muestra de lo que estaba tratando de hacer. (utilizó pintura de ventanas para pintar)
Creo que la mejor manera es heredar el control del que desea trazar una línea. Reemplace el método OnPaint, llame a base.Paint () desde adentro, luego dibuje la línea usando la misma instancia gráfica. Al mismo tiempo, también puede tener un parámetro específico en el que se dibujará la línea, para que pueda controlar la línea directamente desde su formulario principal.
El código original debe ser:
protected override CreateParams CreateParams
{
get
{
CreateParams cp;
cp = base.CreateParams;
cp.Style &= 0x7DFFFFFF; //WS_CLIPCHILDREN
return cp;
}
}
Esto funciona !!
Haga un nuevo LineControl: Control de esta manera:
luego llame a BringToFront () después de InitializeComponent
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.simpleLine1.BringToFront();
}
}
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;
public class SimpleLine : Control
{
private Control parentHooked;
private List<Control> controlsHooked;
public enum LineType
{
Horizontal,
Vertical,
ForwardsDiagonal,
BackwardsDiagonal
}
public event EventHandler AppearanceChanged;
private LineType appearance;
public virtual LineType Appearance
{
get
{
return appearance;
}
set
{
if (appearance != value)
{
this.SuspendLayout();
switch (appearance)
{
case LineType.Horizontal:
if (value == LineType.Vertical)
{
this.Height = this.Width;
}
break;
case LineType.Vertical:
if (value == LineType.Horizontal)
{
this.Width = this.Height;
}
break;
}
this.ResumeLayout(false);
appearance = value;
this.PerformLayout();
this.Invalidate();
}
}
}
protected virtual void OnAppearanceChanged(EventArgs e)
{
if (AppearanceChanged != null) AppearanceChanged(this, e);
}
public event EventHandler LineColorChanged;
private Color lineColor;
public virtual Color LineColor
{
get
{
return lineColor;
}
set
{
if (lineColor != value)
{
lineColor = value;
this.Invalidate();
}
}
}
protected virtual void OnLineColorChanged(EventArgs e)
{
if (LineColorChanged != null) LineColorChanged(this, e);
}
public event EventHandler LineWidthChanged;
private float lineWidth;
public virtual float LineWidth
{
get
{
return lineWidth;
}
set
{
if (lineWidth != value)
{
if (0 >= value)
{
lineWidth = 1;
}
lineWidth = value;
this.PerformLayout();
}
}
}
protected virtual void OnLineWidthChanged(EventArgs e)
{
if (LineWidthChanged != null) LineWidthChanged(this, e);
}
public SimpleLine()
{
base.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Selectable, false);
base.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
base.BackColor = Color.Transparent;
InitializeComponent();
appearance = LineType.Vertical;
LineColor = Color.Black;
LineWidth = 1;
controlsHooked = new List<Control>();
this.ParentChanged += new EventHandler(OnSimpleLineParentChanged);
}
private void RemoveControl(Control control)
{
if (controlsHooked.Contains(control))
{
control.Paint -= new PaintEventHandler(OnControlPaint);
if (control is TextboxX)
{
TextboxX text = (TextboxX)control;
text.DoingAPaint -= new EventHandler(text_DoingAPaint);
}
controlsHooked.Remove(control);
}
}
void text_DoingAPaint(object sender, EventArgs e)
{
this.Invalidate();
}
private void AddControl(Control control)
{
if (!controlsHooked.Contains(control))
{
control.Paint += new PaintEventHandler(OnControlPaint);
if (control is TextboxX)
{
TextboxX text = (TextboxX)control;
text.DoingAPaint += new EventHandler(text_DoingAPaint);
}
controlsHooked.Add(control);
}
}
private void OnSimpleLineParentChanged(object sender, EventArgs e)
{
UnhookParent();
if (Parent != null)
{
foreach (Control c in Parent.Controls)
{
AddControl(c);
}
Parent.ControlAdded += new ControlEventHandler(OnParentControlAdded);
Parent.ControlRemoved += new ControlEventHandler(OnParentControlRemoved);
parentHooked = this.Parent;
}
}
private void UnhookParent()
{
if (parentHooked != null)
{
foreach (Control c in parentHooked.Controls)
{
RemoveControl(c);
}
parentHooked.ControlAdded -= new ControlEventHandler(OnParentControlAdded);
parentHooked.ControlRemoved -= new ControlEventHandler(OnParentControlRemoved);
parentHooked = null;
}
}
private void OnParentControlRemoved(object sender, ControlEventArgs e)
{
RemoveControl(e.Control);
}
private void OnControlPaint(object sender, PaintEventArgs e)
{
int indexa =Parent.Controls.IndexOf(this) , indexb = Parent.Controls.IndexOf((Control)sender);
//if above invalidate on paint
if(indexa < indexb)
{
Invalidate();
}
}
private void OnParentControlAdded(object sender, ControlEventArgs e)
{
AddControl(e.Control);
}
private System.ComponentModel.IContainer components = null;
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20; // Turn on WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnLayout(LayoutEventArgs levent)
{
switch (this.Appearance)
{
case LineType.Horizontal:
this.Height = (int)LineWidth;
this.Invalidate();
break;
case LineType.Vertical:
this.Width = (int)LineWidth;
this.Invalidate();
break;
}
base.OnLayout(levent);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
//disable background paint
}
protected override void OnPaint(PaintEventArgs pe)
{
switch (Appearance)
{
case LineType.Horizontal:
DrawHorizontalLine(pe);
break;
case LineType.Vertical:
DrawVerticalLine(pe);
break;
case LineType.ForwardsDiagonal:
DrawFDiagonalLine(pe);
break;
case LineType.BackwardsDiagonal:
DrawBDiagonalLine(pe);
break;
}
}
private void DrawFDiagonalLine(PaintEventArgs pe)
{
using (Pen p = new Pen(this.LineColor, this.LineWidth))
{
pe.Graphics.DrawLine(p, this.ClientRectangle.X, this.ClientRectangle.Bottom,
this.ClientRectangle.Right, this.ClientRectangle.Y);
}
}
private void DrawBDiagonalLine(PaintEventArgs pe)
{
using (Pen p = new Pen(this.LineColor, this.LineWidth))
{
pe.Graphics.DrawLine(p, this.ClientRectangle.X, this.ClientRectangle.Y,
this.ClientRectangle.Right, this.ClientRectangle.Bottom);
}
}
private void DrawHorizontalLine(PaintEventArgs pe)
{
int y = this.ClientRectangle.Height / 2;
using (Pen p = new Pen(this.LineColor, this.LineWidth))
{
pe.Graphics.DrawLine(p, this.ClientRectangle.X, y,
this.ClientRectangle.Width, y);
}
}
private void DrawVerticalLine(PaintEventArgs pe)
{
int x = this.ClientRectangle.Width / 2;
using (Pen p = new Pen(this.LineColor, this.LineWidth))
{
pe.Graphics.DrawLine(p,x, this.ClientRectangle.Y,
x, this.ClientRectangle.Height);
}
}
}
Editar: Añadido soporte diagonal
He agregado algo de soporte para los controles que se vuelven a pintar cuando obtienen el foco.
los cuadros de texto y los cuadros combinados no funcionarán, ya que necesitarás hacer los tuyos propios y enlazar los comandos paintish de la siguiente manera:
public class TextboxX : TextBox
{
public event EventHandler DoingAPaint;
protected override void WndProc(ref Message m)
{
switch ((int)m.Msg)
{
case (int)NativeMethods.WindowMessages.WM_PAINT:
case (int)NativeMethods.WindowMessages.WM_ERASEBKGND:
case (int)NativeMethods.WindowMessages.WM_NCPAINT:
case 8465: //not sure what this is WM_COMMAND?
if(DoingAPaint!=null)DoingAPaint(this,EventArgs.Empty);
break;
}
base.WndProc(ref m);
}
}
No está probado y estoy seguro de que puedes mejorarlo
La única solución simple en la que puedo pensar es crear controladores de eventos Paint para cada control sobre el que quieras pintar. Luego coordine el dibujo de líneas entre estos manejadores. Esta no es la solución más conveniente, sin embargo, esto le dará la capacidad de pintar encima de los controles.
El botón Asumir es un control secundario del panel:
panel.Paint += new PaintEventHandler(panel_Paint);
button.Paint += new PaintEventHandler(button_Paint);
protected void panel_Paint(object sender, PaintEventArgs e)
{
//draw the full line which will then be partially obscured by child controls
}
protected void button_Paint(object sender, PaintEventArgs e)
{
//draw the obscured line portions on the button
}
Resulta que esto es mucho más fácil de lo que pensaba. Gracias por no aceptar ninguna de mis otras respuestas. Aquí está el proceso de dos pasos para crear una Fline ( línea de pérdida, lo siento, es tarde):
texto alternativo http://www.freeimagehosting.net/uploads/1fd1206890.jpg
Paso 1 : Agregue un UserControl a su proyecto y asígnele el nombre "Fline". Agregue lo siguiente a las instrucciones de uso:
using System.Drawing.Drawing2D;
Paso 2 : agregue lo siguiente al evento de cambio de tamaño de Fline:
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);
Compila, y luego arrastra una Fline en tu formulario o panel. Importante: el BackColor predeterminado es el mismo que el del formulario, por lo tanto, cambie BackColor de la Fline a Rojo o algo obvio (en el diseñador). Una peculiaridad extraña sobre esto es que cuando lo arrastra en el diseñador, se muestra como un bloque sólido hasta que lo libera, no es un gran problema.
Este control puede aparecer delante o detrás de cualquier otro control. Si configura Enabled en false, seguirá siendo visible, pero no interferirá con los eventos del mouse en los controles que se encuentran debajo.
Querrá mejorar esto para sus propósitos, por supuesto, pero esto muestra el principio básico. Puedes usar la misma técnica para crear un control de cualquier forma que quieras (mi prueba inicial de esto hizo un triángulo).
Actualización : esto también hace un buen trazador de líneas denso y denso. Simplemente coloque esto en el evento Resize de su UserControl:
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}));
Si desea que la línea sea simplemente una línea horizontal o vertical simple, coloque otro panel (deshabilitado para que no capte ningún evento del mouse) en el panel principal, establezca su altura (o ancho) en 3 o 4 píxeles (o lo que quieras), y llevarlo al frente. Si necesita cambiar dónde está la línea durante el tiempo de ejecución, puede mover el panel y hacer que sea visible e invisible. Así es como se ve:
texto alternativo http://www.freeimagehosting.net/uploads/832018002a.jpg
Incluso puede hacer clic en cualquier lugar que desee, y las líneas no interfieren en absoluto. La línea se dibuja sobre cualquier tipo de control (aunque la parte desplegable de un ComboBox o un DatePicker todavía se muestra por encima de la línea, lo que de todos modos es bueno). La línea azul es exactamente la misma cosa pero enviada a atrás.
Si, esto se puede hacer. El problema es que el panel y los controles son todos ventanas separadas (en el sentido API) y, por lo tanto, todas las superficies de dibujo separadas. No hay una sola superficie de dibujo para obtener este efecto (que no sea la superficie de la pantalla de nivel superior, y se considera de mala educación dibujar todo eso).
El truco ( toser) es trazar la línea en el panel debajo de los controles, y también dibujarlo en cada uno de los controles, lo que resulta en esto (que persistirá incluso al hacer clic en los botones y mover el mouse alrededor )
texto alternativo http://www.freeimagehosting.net/uploads/2dce0ba7ab.gif
Cree un proyecto de winforms (que debería venir con Form1 por defecto). Agregue un panel (llamado "panel1") y dos botones ("botón1" y "botón2") en el panel como se muestra. Agregue este código en el constructor del formulario:
panel1.Paint += PaintPanelOrButton;
button1.Paint += PaintPanelOrButton;
button2.Paint += PaintPanelOrButton;
y luego agregue este método al código del formulario:
private void PaintPanelOrButton(object sender, PaintEventArgs e)
{
// center the line endpoints on each button
Point pt1 = new Point(button1.Left + (button1.Width / 2),
button1.Top + (button1.Height / 2));
Point pt2 = new Point(button2.Left + (button2.Width / 2),
button2.Top + (button2.Height / 2));
if (sender is Button)
{
// offset line so it''s drawn over the button where
// the line on the panel is drawn
Button btn = (Button)sender;
pt1.X -= btn.Left;
pt1.Y -= btn.Top;
pt2.X -= btn.Left;
pt2.Y -= btn.Top;
}
e.Graphics.DrawLine(new Pen(Color.Red, 4.0F), pt1, pt2);
}
Algo así debe dibujarse en el evento Paint de cada control para que la línea persista. Es fácil dibujar directamente los controles en .NET, pero cualquier cosa que dibuje se borrará cuando alguien haga clic en el botón o mueva el mouse sobre él (a menos que se vuelva a dibujar perpetuamente en los eventos de Paint, como aquí).
Tenga en cuenta que para que esto funcione, cualquier control dibujado debe tener un evento Paint. Estoy seguro de que tendrá que modificar esta muestra para lograr lo que necesita. Si se le ocurre una buena función generalizada para esto, publíquelo.
Actualización: este método no funcionará para las barras de desplazamiento, cuadros de texto, cuadros combinados, listas de vista, o básicamente cualquier cosa con un elemento de tipo cuadro de texto como parte de él (y no porque solo compensa los botones en el ejemplo anterior; simplemente no puede dibujar al principio de un cuadro de texto, al menos no de su evento Paint, al menos no si eres yo). Espero que eso no sea un problema.
Un panel de formularios de Windows es un contenedor para controles. Si desea dibujar algo encima de otros controles dentro de un panel, entonces lo que necesita es otro control (en la parte superior del orden z).
Afortunadamente, puede crear controles de formularios de Windows que tengan bordes no rectangulares. Mire esta técnica: http://msdn.microsoft.com/en-us/library/aa289517(VS.71).aspx
Para dibujar algo en la pantalla, use un control de etiqueta y desactive AutoSize. A continuación, conéctelo al evento Paint y configure Tamaño y Propiedades de región.
Aquí hay una muestra de código:
private void label1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Drawing2D.GraphicsPath myGraphicsPath = new System.Drawing.Drawing2D.GraphicsPath();
myGraphicsPath.AddEllipse(new Rectangle(0, 0, 125, 125));
myGraphicsPath.AddEllipse(new Rectangle(75, 75, 20, 20));
myGraphicsPath.AddEllipse(new Rectangle(120, 0, 125, 125));
myGraphicsPath.AddEllipse(new Rectangle(145, 75, 20, 20));
//Change the button''s background color so that it is easy
//to see.
label1.BackColor = Color.ForestGreen;
label1.Size = new System.Drawing.Size(256, 256);
label1.Region = new Region(myGraphicsPath);
}
EDITAR Encontré una manera de deshacerme del problema de la pintura recursiva que tenía. Entonces, ahora, para mí, esto se ve muy, muy, muy cerca de lo que quieres lograr.
Esto es lo que podría hacer. Utiliza el enfoque n. ° 3 delineado en la pregunta original. El código es algo extenso porque están involucradas tres clases:
- Una clase privada llamada DecorationCanvas. Esto se deriva de Panel y usa WS_EX_TRANSPARENT para proporcionar un lienzo transparente para dibujar nuestras cosas
- La clase del panel en sí, lo llamé DecoratedPanel, deriva del Panel
- Una clase de diseñador llamada DecoratedPanelDesigner para el panel, para asegurarse de que ZOrder se pueda conservar durante el tiempo de Diseño.
El enfoque básico es:
- En el constructor de DecoratedPanel, crea una instancia de DecorationCanvas y agrégala a la colección DecoratedPanel Controls.
- Anule OnControlAdded y OnControlRemoved, para enganchar / desenganchar automáticamente eventos de pintura para controles secundarios, y para asegurarse de que DecorationCanvas permanezca en la parte superior de ZOrder.
- Siempre que un control contenido pinta, invalida el rectángulo DecorativeCanvas correspondiente.
- Anule OnResize y OnSizeChanged para asegurarse de que DecorationCanvas tenga el mismo tamaño que DecoratedPanel. (Traté de lograr esto usando la propiedad Anchor, pero falló de alguna manera).
- Proporcione un método interno para restablecer DecorationCanvas ZOrder desde DecoratedPanelDesigner.
Funciona bien en mi sistema (VS2010 / .net4 / Windows XP SP3). Aquí está el código:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace WindowsFormsApplication3
{
[Designer("WindowsFormsApplication3.DecoratedPanelDesigner")]
public class DecoratedPanel : Panel
{
#region decorationcanvas
// this is an internal transparent panel.
// This is our canvas we''ll draw the lines on ...
private class DecorationCanvas : Panel
{
public DecorationCanvas()
{
// don''t paint the background
SetStyle(ControlStyles.Opaque, true);
}
protected override CreateParams CreateParams
{
get
{
// use transparency
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
}
#endregion
private DecorationCanvas _decorationCanvas;
public DecoratedPanel()
{
// add our DecorationCanvas to our panel control
_decorationCanvas = new DecorationCanvas();
_decorationCanvas.Name = "myInternalOverlayPanel";
_decorationCanvas.Size = ClientSize;
_decorationCanvas.Location = new Point(0, 0);
// this prevents the DecorationCanvas to catch clicks and the like
_decorationCanvas.Enabled = false;
_decorationCanvas.Paint += new PaintEventHandler(decoration_Paint);
Controls.Add(_decorationCanvas);
}
protected override void Dispose(bool disposing)
{
if (disposing && _decorationCanvas != null)
{
// be a good citizen and clean up after yourself
_decorationCanvas.Paint -= new PaintEventHandler(decoration_Paint);
Controls.Remove(_decorationCanvas);
_decorationCanvas = null;
}
base.Dispose(disposing);
}
void decoration_Paint(object sender, PaintEventArgs e)
{
// --- PAINT HERE ---
e.Graphics.DrawLine(Pens.Red, 0, 0, ClientSize.Width, ClientSize.Height);
}
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
if (IsInDesignMode)
return;
// Hook paint event and make sure we stay on top
if (!_decorationCanvas.Equals(e.Control))
e.Control.Paint += new PaintEventHandler(containedControl_Paint);
ResetDecorationZOrder();
}
protected override void OnControlRemoved(ControlEventArgs e)
{
base.OnControlRemoved(e);
if (IsInDesignMode)
return;
// Unhook paint event
if (!_decorationCanvas.Equals(e.Control))
e.Control.Paint -= new PaintEventHandler(containedControl_Paint);
}
/// <summary>
/// If contained controls are updated, invalidate the corresponding DecorationCanvas area
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void containedControl_Paint(object sender, PaintEventArgs e)
{
Control c = sender as Control;
if (c == null)
return;
_decorationCanvas.Invalidate(new Rectangle(c.Left, c.Top, c.Width, c.Height));
}
protected override void OnResize(EventArgs eventargs)
{
base.OnResize(eventargs);
// make sure we''re covering the panel control
_decorationCanvas.Size = ClientSize;
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
// make sure we''re covering the panel control
_decorationCanvas.Size = ClientSize;
}
/// <summary>
/// This is marked internal because it gets called from the designer
/// to make sure our DecorationCanvas stays on top of the ZOrder.
/// </summary>
internal void ResetDecorationZOrder()
{
if (Controls.GetChildIndex(_decorationCanvas) != 0)
Controls.SetChildIndex(_decorationCanvas, 0);
}
private bool IsInDesignMode
{
get
{
return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime;
}
}
}
/// <summary>
/// Unfortunately, the default designer of the standard panel is not a public class
/// So we''ll have to build a new designer out of another one. Since Panel inherits from
/// ScrollableControl, let''s try a ScrollableControlDesigner ...
/// </summary>
public class DecoratedPanelDesigner : ScrollableControlDesigner
{
private IComponentChangeService _changeService;
public override void Initialize(IComponent component)
{
base.Initialize(component);
// Acquire a reference to IComponentChangeService.
this._changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
// Hook the IComponentChangeService event
if (this._changeService != null)
this._changeService.ComponentChanged += new ComponentChangedEventHandler(_changeService_ComponentChanged);
}
/// <summary>
/// Try and handle ZOrder changes at design time
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _changeService_ComponentChanged(object sender, ComponentChangedEventArgs e)
{
Control changedControl = e.Component as Control;
if (changedControl == null)
return;
DecoratedPanel panelPaint = Control as DecoratedPanel;
if (panelPaint == null)
return;
// if the ZOrder of controls contained within our panel changes, the
// changed control is our control
if (Control.Equals(panelPaint))
panelPaint.ResetDecorationZOrder();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this._changeService != null)
{
// Unhook the event handler
this._changeService.ComponentChanged -= new ComponentChangedEventHandler(_changeService_ComponentChanged);
this._changeService = null;
}
}
base.Dispose(disposing);
}
/// <summary>
/// If the panel has BorderStyle.None, a dashed border needs to be drawn around it
/// </summary>
/// <param name="pe"></param>
protected override void OnPaintAdornments(PaintEventArgs pe)
{
base.OnPaintAdornments(pe);
Panel panel = Control as Panel;
if (panel == null)
return;
if (panel.BorderStyle == BorderStyle.None)
{
using (Pen p = new Pen(SystemColors.ControlDark))
{
p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
pe.Graphics.DrawRectangle(p, 0, 0, Control.Width - 1, Control.Height - 1);
}
}
}
}
}
Déjame saber lo que piensas ...