modern full framework for bunifu bootstrap academy c# winforms user-interface

c# - framework - telerik ui for winforms full



¿Cómo mostrar una superposición de "carga" en formularios de Windows mientras el formulario está cargando sus controles(o actualizándolos)? (6)

Estoy buscando una manera efectiva de notificar al usuario que un formulario determinado está cargando (o actualizando) su IU y tardará unos segundos.

Esto puede ocurrir en la carga inicial o en la actualización. Dado que es muy intensivo y que modifica los controles de la interfaz de usuario, esto debe hacerse en el subproceso de la interfaz de usuario y, por lo tanto, bloquear al usuario.

Cambiar el cursor no es suficiente, quiero obtener un efecto similar al de las páginas ajax, con toda el área superpuesta por un panel semi transparente con un engranaje animado en el centro.

¿Ya has hecho algo así? ¿O conoces sitios web interesantes que debería consultar?

Muchas gracias


Eche un vistazo a esta publicación con una gran respuesta que imita el estilo Ajax en WinForms

Javascript como la ventana modal para WinForms.
Javascript como la ventana modal para WinForms

Aquí hay un formulario personalizado que hará lo que quieras ... modifica a tu gusto:

public partial class ModalLoadingUI : Form { #region Constants private readonly Color BackgroundFadeColor = Color.FromArgb(50, Color.Black); #endregion #region Constructors public ModalLoadingUI() { InitializeComponent(); } #endregion #region Properties /// <summary> /// Gets or Sets the main form that will be used as a background canvas for the loading form. /// </summary> public Form BackgroundForm { get; set; } /// <summary> /// Gets or Sets the text to displayed as the progress text. /// </summary> public string Title { get { return label1.Text; } set { label1.Text = value; } } /// <summary> /// Gets or Sets the value of the progress bar. /// </summary> public int? Progress { get { if (progressBar1.Style == ProgressBarStyle.Marquee) { return null; } else { return progressBar1.Value; } } set { if (value == null) { progressBar1.Style = ProgressBarStyle.Marquee; progressBar1.Value = 100; label2.Visible = false; } else { progressBar1.Style = ProgressBarStyle.Continuous; progressBar1.Value = value.Value; label2.Text = string.Format("{0}%", value); label2.Visible = true; } } } /// <summary> /// Gets or Sets a value to indicate if the background form should be faded out. /// </summary> public bool UseFadedBackground { get; set; } /// <summary> /// Gets or Sets a value to indicate if the splash box is to be displayed. /// </summary> public bool UseSplashBox { get { return picShadow.Visible; } set { if (value == true) { picShadow.Visible = true; panel1.Visible = true; } else { picShadow.Visible = false; panel1.Visible = false; } } } #endregion #region Base Events private void ModalLoadingUI_Load(object sender, EventArgs e) { if (this.BackgroundForm != null) { this.Location = this.BackgroundForm.Location; } } private void ModalLoadingUI_VisibleChanged(object sender, EventArgs e) { if (this.Visible == true) { if (this.BackgroundForm != null) { this.Location = this.BackgroundForm.Location; } } if (System.Diagnostics.Debugger.IsAttached == true) { this.TopMost = false; } else { this.TopMost = true; } } private void ModalLoadingUI_Shown(object sender, EventArgs e) { } #endregion #region Public Methods /// <summary> /// Paints the background form as the background of this form, if one is defined. /// </summary> public void CaptureBackgroundForm() { if (this.InvokeRequired) { this.BeginInvoke(new MethodInvoker(CaptureBackgroundForm)); return; } if (this.BackgroundForm == null) { return; } var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmpScreenshot); try { // COPY BACKGROUND int x = this.BackgroundForm.Left; int y = this.BackgroundForm.Top; var size = this.BackgroundForm.Size; g.CopyFromScreen(x, y, 0, 0, size, CopyPixelOperation.SourceCopy); // FADE IF DESIRED if (this.UseFadedBackground == true) { var rect = new Rectangle(0, 0, size.Width, size.Height); g.FillRectangle(new SolidBrush(BackgroundFadeColor), rect); } // PAINT SPLASH BOX SHADOW IF DESIRED if(this.UseSplashBox == true) { PaintPanelShadow(g); } } catch (Exception e) { g.Clear(Color.White); } this.BackgroundImage = bmpScreenshot; } /// <summary> /// Paints a shadow around the panel, if one is defined. /// </summary> /// <param name="g">The graphics object to paint into</param> private void PaintPanelShadow(Graphics g) { var shadowImage = picShadow.Image; var x = panel1.Left + (panel1.Width / 2) - (shadowImage.Width / 2); var y = panel1.Top + (panel1.Height / 2) - (shadowImage.Height / 2); g.DrawImage(shadowImage, x, y, shadowImage.Width, shadowImage.Height); } #endregion }


Mi solución recomendada es establecer la opacidad de las formas en casi invisible, por ejemplo, 0.01 antes de inicializar los componentes. A continuación, cree un formulario con el mismo tamaño y posición y coloque una barra de progreso, o marquee en este formulario. Después de la inicialización del formulario principal, establezca la opacidad al máximo y elimine la forma del marco.


Puede crear un panel transparente subclasificando SWFPanel y anulando la propiedad CreateParams:

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

Sobrescriba OnPaint para agregar una superposición semitransparente:

protected override void OnPaint(PaintEventArgs e) { e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(128, 0,0,0)), this.ClientRectangle); }

Establezca este panel en el Dock.Fill en su formulario sobre los otros controles. Escóndelo cuando finalice la carga.


Puede deshabilitar todos los controles en el formulario configurando la propiedad Habilitado en Falso y luego cambiándolo a Verdadero después de que el proceso haya finalizado.

Además, puede tener una etiqueta oculta que dice "Cargando" que se muestra antes de deshabilitar el formulario y ocultarlo cuando lo vuelva a habilitar.

Finalmente, sugiero que divida el proceso en dos partes. Una parte que realiza el trabajo sin modificar los controles que puede ejecutar en un subproceso de trabajo y la parte que cambia la interfaz gráfica de usuario que funciona en el subproceso de interfaz de usuario después de que se realiza el subproceso de trabajo. De esta manera, no bloqueará toda la aplicación, lo que hará que los cambios en Gui sean más fáciles de hacer.


Tenga en cuenta que Winforms no permite que los controles secundarios sean realmente transparentes. Como otros han publicado, una ventana transparente separada es posible, pero difícil de manejar.

Manera barata

  • arrastre todos los controles a un panel y conviértalo en el tamaño de la ventana (cambio fácil)
  • Al operar: oculta ese panel. Utilice los paneles .DrawToBitmap method para establecer la imagen de fondo del formulario.
  • muestra la barra de progreso, trabaja con ''doevents'', ocúltalo.
  • Imagen de fondo clara, volver a mostrar el panel.

Una mejor manera:

Clase de progreso - Consumidor

Te daré un Usercontrol que escribí y he usado en muchos programas diferentes que hacen exactamente lo que quieres. Aquí hay un ejemplo trivial para el consumidor, puede pegar en el código de un formulario (sí, solo hace un montón de nuevos botones sin ninguna razón):

Public Class Form1 Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed End ''''// use a flag if you would like a more graceful way to handle this. End Sub WithEvents ucProgress As New Progress ''''// just doing it this way so I don''''//t have to paste designer code. Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown Controls.Clear() Controls.Add(ucProgress) Me.ucProgress.pb.Visible = False ucProgress.StartProgress() Try ucProgress.Message = "Starting up..." Application.DoEvents() Me.ucProgress.pb.Visible = True Me.ucProgress.pb.Maximum = 21 Me.ucProgress.pb.Value = 0 For i As Integer = 0 To 20 Dim btn As New Button btn.Top = +i * 3 btn.Left = i * 8 btn.Text = CStr(i) btn.Enabled = False ''''// ONLY HAVE TO DO FOR CTLS RIGHT ON MAIN FORM ucProgress.EnabledStates.Add(btn, True) ''''// ONLY HAVE TO DO FOR CTLS RIGHT ON MAIN FORM Controls.Add(btn) btn.BringToFront() System.Threading.Thread.Sleep(200) Application.DoEvents() ucProgress.pb.Value += 1 ucProgress.Message = "Processing item# " & i.ToString If Me.ucProgress.Cancel Then MsgBox("Cancelled - not all loaded.") Me.ucProgress.Cancel = False Exit For End If Next Catch ex As Exception MsgBox(ex.ToString, , "Error loading something") Finally ucProgress.EndProgress() End Try End Sub End Class

Clase de progreso - Definición

Y aquí está la clase. El código de "diseñador" se pega en línea, puede dejarlo allí. La clase desactiva los controles cuando se ejecuta, por lo que todo lo que puede hacer es cancelar. Se ejecuta en el hilo de la interfaz gráfica de usuario. Puede deshabilitar la opción de cancelar. En el consumidor hay un ejemplo de cómo tratar con los controles recién agregados para que no se muestren habilitados, sino que se habiliten cuando finalice el progreso.

Option Explicit On Option Strict On Public Class Progress Inherits System.Windows.Forms.UserControl #Region "Code for the Designer.vb class" Sub New() InitializeComponent() End Sub ''''//Form overrides dispose to clean up the component list. <System.Diagnostics.DebuggerNonUserCode()> _ Protected Overrides Sub Dispose(ByVal disposing As Boolean) If disposing AndAlso components IsNot Nothing Then components.Dispose() End If MyBase.Dispose(disposing) End Sub ''''//Required by the Windows Form Designer Private components As System.ComponentModel.IContainer ''''//NOTE: The following procedure is required by the Windows Form Designer ''''//It can be modified using the Windows Form Designer. ''''//Do not modify it using the code editor. <System.Diagnostics.DebuggerStepThrough()> _ Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container Me.btnCancel = New System.Windows.Forms.Button Me.lblPlaceholder = New System.Windows.Forms.Label Me.pb = New System.Windows.Forms.ProgressBar Me.SuspendLayout() ''''// ''''//btnCancel ''''// Me.btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Top Me.btnCancel.Location = New System.Drawing.Point(73, 33) Me.btnCancel.Name = "btnCancel" Me.btnCancel.Size = New System.Drawing.Size(91, 21) Me.btnCancel.TabIndex = 0 Me.btnCancel.Text = "Cancel" Me.btnCancel.UseVisualStyleBackColor = True ''''// ''''// ''''//lblPlaceholder ''''// Me.lblPlaceholder.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) Me.lblPlaceholder.BackColor = System.Drawing.Color.Transparent Me.lblPlaceholder.Font = New System.Drawing.Font("Arial Narrow", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.lblPlaceholder.Location = New System.Drawing.Point(12, 3) Me.lblPlaceholder.Name = "lblPlaceholder" Me.lblPlaceholder.Size = New System.Drawing.Size(221, 29) Me.lblPlaceholder.TabIndex = 1 Me.lblPlaceholder.Text = "Placeholder label for text drawing" Me.lblPlaceholder.Visible = False ''''// ''''//pb ''''// Me.pb.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _ Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) Me.pb.Location = New System.Drawing.Point(6, 60) Me.pb.Name = "pb" Me.pb.Size = New System.Drawing.Size(225, 10) Me.pb.Style = System.Windows.Forms.ProgressBarStyle.Continuous Me.pb.TabIndex = 2 ''''// ''''//ucProgress ''''// Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.BackColor = System.Drawing.Color.LightSteelBlue Me.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle Me.Controls.Add(Me.pb) Me.Controls.Add(Me.lblPlaceholder) Me.Controls.Add(Me.btnCancel) Me.Name = "ucProgress" Me.Size = New System.Drawing.Size(236, 77) Me.ResumeLayout(False) End Sub Friend WithEvents btnCancel As System.Windows.Forms.Button Friend WithEvents lblPlaceholder As System.Windows.Forms.Label Public WithEvents pb As System.Windows.Forms.ProgressBar #End Region Dim _mymessage As String Public Event WorkerPart() Public Cancel As Boolean Public EnabledStates As New Dictionary(Of Control, Boolean) Dim oldfocus As Control Dim OldMinBox As Boolean Public Sub StartProgress() Cancel = False Me.Parent = Me.ParentForm oldfocus = Me.ParentForm.ActiveControl Parent_SizeChanged(Nothing, Nothing) AddHandler Me.ParentForm.SizeChanged, AddressOf Parent_SizeChanged Me.Visible = True Me.Enabled = True Me.btnCancel.Focus() EnabledStates.Clear() For Each ctl As Control In Me.Parent.Controls If ctl IsNot Me Then EnabledStates.Add(ctl, ctl.Enabled) ctl.Enabled = False End If Next Me.BringToFront() Me.pb.Value = 0 OldMinBox = Me.ParentForm.MinimizeBox Me.ParentForm.MinimizeBox = True End Sub Public Sub EndProgress() RemoveHandler Me.ParentForm.SizeChanged, AddressOf Parent_SizeChanged For Each ctl As Control In Me.Parent.Controls If ctl IsNot Me And EnabledStates.ContainsKey(ctl) Then ctl.Enabled = EnabledStates(ctl) End If Next If oldfocus IsNot Nothing Then oldfocus.Focus() End If Me.ParentForm.MinimizeBox = OldMinBox Me.Visible = False End Sub Public Property Message() As String Get Return _mymessage End Get Set(ByVal value As String) _mymessage = value Dim g As Graphics = Me.CreateGraphics() DrawString(g) g.Dispose() ''''//lblMessage.Text = value Application.DoEvents() End Set End Property Private Sub DrawString(ByVal g As Graphics) ''''//g.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixel Dim rct As New Rectangle(Me.lblPlaceholder.Left, Me.lblPlaceholder.Top, _ Me.lblPlaceholder.Width, Me.lblPlaceholder.Height) g.SetClip(rct) Dim b As New SolidBrush(Me.BackColor) If Me.BackgroundImage Is Nothing Then g.FillRectangle(b, rct) Else g.DrawImage(Me.BackgroundImage, 0, 0) End If ''''// With lblPlaceholder g.DrawString(_mymessage, .Font, Brushes.DarkBlue, .Left, _ .Top + CInt(IIf(InStr(_mymessage, vbCrLf) <> 0, 0, .Height / 4))) End With End Sub Private Sub frmProgress_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint DrawString(e.Graphics) End Sub Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click Cancel = True End Sub Private Sub Parent_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Me.Left = (Me.Parent.Width - Me.Width) / 2 Me.Top = (Me.Parent.Height - Me.Height) / 2 End Sub End Class

¡Buena suerte!