tag propiedad net .net winforms user-interface
Aquí está mi demo muy hecha en 20 minutos

.net - propiedad - net core 3 release date



.NET Windows Forms Control transparente (6)

¿Puedes hacer esto en .NET / C #?

Sí, ciertamente puedes, pero requiere un poco de esfuerzo. Yo recomendaría el siguiente enfoque. Cree un formulario de nivel superior que no tenga un borde o un área de barra de título y luego asegúrese de que no dibuja ningún fondo de área de cliente configurando TransparencyKey y BackColor en el mismo valor. Entonces ahora tienes una ventana que no dibuja nada ...

public class DarkenArea : Form { public DarkenArea() { FormBorderStyle = FormBorderStyle.None; SizeGripStyle = SizeGripStyle.Hide; StartPosition = FormStartPosition.Manual; MaximizeBox = false; MinimizeBox = false; ShowInTaskbar = false; BackColor = Color.Magenta; TransparencyKey = Color.Magenta; Opacity = 0.5f; } }

Cree y coloque esta ventana DarkenArea sobre el área del cliente de su formulario. Entonces necesita poder mostrar la ventana sin que tome el foco y necesitará invocar la plataforma de la siguiente manera para mostrar sin que se active ...

public void ShowWithoutActivate() { // Show the window without activating it (i.e. do not take focus) PlatformInvoke.ShowWindow(this.Handle, (short)SW_SHOWNOACTIVATE); }

Debe hacer que dibuje algo, pero excluya el dibujo en el área del control que desea que permanezca resaltado. Así que anule el controlador OnPaint y dibuje en negro / azul o lo que quiera, pero excluyendo el área que desea que permanezca brillante ...

protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // Do your painting here be exclude the area you want to be brighter }

Por último, debe sobrescribir el WndProc para evitar que el mouse interactúe con la ventana si el usuario intenta algo tan loco como hacer clic en el área oscurecida. Algo como esto...

protected override void WndProc(ref Message m) { if (m.Msg == (int)WM_NCHITTEST) m.Result = (IntPtr)HTTRANSPARENT; else base.WndProc(ref m); }

Eso debería ser suficiente para obtener el efecto deseado. Cuando esté listo para invertir el efecto, deseche la instancia de DarkenArea y continúe.

Quiero simular una técnica de interfaz de usuario estilo Lightbox ''Web 2.0'' en una aplicación de Windows Forms . Es decir, llamar la atención sobre el control de primer plano al "atenuar" el resto del contenido en el área del cliente de una ventana.

La solución obvia es crear un control que sea simplemente un rectángulo parcialmente transparente que pueda acoplarse al área del cliente de una ventana y llevarse al frente del Z-Order. Tiene que actuar como un dolor sucio de vidrio a través del cual aún se pueden ver los otros controles (y por lo tanto continuar pintando ellos mismos). es posible?

He tenido una buena ronda de búsqueda e intenté algunas técnicas, pero hasta ahora no he tenido éxito. Si no es posible, ¿cuál sería otra forma de hacerlo?

Consulte: http://www.useit.com/alertbox/application-design.html (en la sección Lightbox para obtener una captura de pantalla para ilustrar lo que quiero decir).


Cada forma tiene una propiedad de "Opacidad". Establézcalo al 50% (o 0.5 del código) por lo que será medio transparente. Elimine los bordes y muéstrelos al máximo antes del formulario en el que desea enfocar. Puede cambiar BackColor del formulario o incluso establecer una imagen de fondo para diferentes efectos.


El gran rectángulo de regulación es bueno.

Otra forma de hacerlo sería:

Tira tu propia base La clase de formulario dice una clase MyLightboxAwareForm que escucharía un LightboxEvent de un LightboxManager . Luego MyLightboxAwareForm que todos sus formularios hereden de MyLightboxAwareForm .

Al llamar al método Show en cualquier Lightbox , el LightboxManager transmitiría un evento LightboxShown a todas MyLightboxAwareForm instancias de MyLightboxAwareForm y las haría atenuarse.

Esto tiene la ventaja de que la funcionalidad normal de las formas de Win32 continuará funcionando, como el destello de la barra de tareas del formulario al hacer clic en uno de sus diálogos modales o la gestión de los eventos mouseover / mousedown aún funcionaría normalmente, etc.

Y si quieres el estilo de atenuación rectangular, podrías poner la lógica en MyLightboxAwareForm


Esta es una idea genial. Probablemente la use, así que gracias. De todos modos, mi solución es realmente simple ... abra una nueva forma opaca al 50% sobre la actual y luego dibuje una imagen de fondo para esa forma con un rectángulo que coincida con los límites del control que desea resaltar rellenado con el color del clave de transparencia

En mi muestra aproximada, llamé a este formulario ''LBform'' y la carne de esto es esta:

public Rectangle ControlBounds { get; set; } private void LBform_Load(object sender, EventArgs e) { Bitmap background = new Bitmap(this.Width, this.Height); Graphics g = Graphics.FromImage(background); g.FillRectangle(Brushes.Fuchsia, this.ControlBounds); g.Flush(); this.BackgroundImage = background; this.Invalidate(); }

Color.Fuchia es la TransparencyKey para esta forma semiopaca, por lo que podrás ver a través del rectángulo dibujado e interactuar con cualquier cosa dentro de sus límites en la forma principal.

En el proyecto experimental que preparé para probar esto, utilicé un UserControl añadido dinámicamente al formulario, pero con la misma facilidad podría usar un control que ya está en el formulario. En la forma principal (la que estás ocultando) pongo el código relevante en un clic del botón:

private void button1_Click(object sender, EventArgs e) { // setup user control: UserControl1 uc1 = new UserControl1(); uc1.Left = (this.Width - uc1.Width) / 2; uc1.Top = (this.Height - uc1.Height) / 2; this.Controls.Add(uc1); uc1.BringToFront(); // load the lightbox form: LBform lbform = new LBform(); lbform.SetBounds(this.Left + 8, this.Top + 30, this.ClientRectangle.Width, this.ClientRectangle.Height); lbform.ControlBounds = uc1.Bounds; lbform.Owner = this; lbform.Show(); }

Cosas realmente básicas que puede hacer a su manera si lo desea, pero solo agrega el control de usuario, luego establece el formulario de la luz sobre el formulario principal y establece la propiedad de los límites para mostrar la transparencia completa en el lugar correcto. Cosas como la forma de arrastrar y cerrar el formulario lightbox y UserControl no se manejan en mi muestra rápida. Ah, y no te olvides de disponer de la instancia de Graphics. Lo dejé también (es tarde, estoy cansado).

Aquí está mi demo muy hecha en 20 minutos


Los formularios en sí tienen la propiedad Opacity que sería perfecta, pero no creo que la mayoría de los controles individuales sí lo hagan. Tendrás que dibujar el propietario.


Otra solución que no implica el uso de un nuevo formulario:

  • hacer una foto de su contenedor (formulario / panel / lo que sea),
  • cambiar su opacidad,
  • mostrarlo en el fondo de un nuevo panel.
  • Llena tu contenedor con ese panel.

Y ahora el código ...

Digamos que tengo un UserControl llamado Frame al cual querré aplicar mi efecto lightbox:

public partial class Frame : UserControl { private Panel shadow = new Panel(); private static float LIGHTBOX_OPACITY = 0.3f; public Frame() { InitializeComponent(); shadow.Dock = DockStyle.Fill; } public void ShowLightbox() { Bitmap bmp = new Bitmap(this.Width, this.Height); this.pnlContainer.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height)); shadow.BackgroundImage = SetImgOpacity(bmp, LIGHTBOX_OPACITY ); this.Controls.Add(shadow); shadow.BringToFront(); } // http://www.geekpedia.com/code110_Set-Image-Opacity-Using-Csharp.html private Image SetImgOpacity(Image imgPic, float imgOpac) { Bitmap bmpPic = new Bitmap(imgPic.Width, imgPic.Height); Graphics gfxPic = Graphics.FromImage(bmpPic); ColorMatrix cmxPic = new ColorMatrix(); cmxPic.Matrix33 = imgOpac; ImageAttributes iaPic = new ImageAttributes(); iaPic.SetColorMatrix(cmxPic, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); gfxPic.DrawImage(imgPic, new Rectangle(0, 0, bmpPic.Width, bmpPic.Height), 0, 0, imgPic.Width, imgPic.Height, GraphicsUnit.Pixel, iaPic); gfxPic.Dispose(); return bmpPic; } }

Las ventajas de usar esta técnica son:

  • No tendrá que manejar todos los eventos del mouse
  • No tendrá que administrar múltiples formularios para comunicarse con los elementos del lightbox
  • Sin anulación de WndProc
  • Te sentirás genial porque serás el único que no use formularios para lograr este efecto.

Los inconvenientes son principalmente que esta técnica es mucho más lenta porque debe procesar una imagen completa para corregir cada punto de píxel con ColorMatrix.