Comment afficher une superposition "chargement" sur les formulaires windows pendant que le formulaire est en train de charger ses commandes (ou de les mettre à jour)?

je suis à la recherche d'un moyen efficace pour notifier à l'utilisateur qu'un formulaire donné est en train de charger (ou de mettre à jour) il est UI et cela prendra quelques secondes.

cela peut se produire à la charge initiale ou à la mise à jour. Comme c'est très intensif et modifiant les contrôles de l'interface utilisateur, cela doit être fait sur le thread de l'interface utilisateur, ce qui bloque l'utilisateur.

changer le curseur n'est pas suffisant, je veux obtenir un effet similaire que sur les pages ajax, avec toute la zone qui est recouvert d'un panneau semi-transparent avec un engrenage animé au centre.

avez-vous déjà fait quelque chose comme ça? Ou connaissez-vous des sites intéressants que je devrais consulter?

Merci beaucoup

18
demandé sur Community 2010-09-16 10:36:57

6 réponses

jetez un oeil à ce post avec une grande réponse qui imite le style Ajax sur WinForms

Javascript comme fenêtre modale pour WinForms.

Javascript Comme Fenêtre Modale pour WinForms

voici un formulaire personnalisé qui fera ce que vous voulez... modifier à votre goût:

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
}
11
répondu Michel Triana 2017-05-23 12:08:40

vous pouvez créer un panneau transparent en sous-classant le Panneau S. W. F. et en outrepassant la propriété CreateParams:

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

outrepasser l'OnPaint pour ajouter un recouvrement semi-transparent:

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

mettez ce panneau sur le quai.Remplir un formulaire sur les autres contrôles. Cachez-le à la fin du chargement.

4
répondu Johann Blais 2010-09-16 06:59:50

notez que Winforms ne permet pas aux commandes enfants d'être réellement transparentes. Comme d'autres ont posté une fenêtre transparente séparée est possible - mais salissant à gérer.

pas Cher

  • faites glisser toutes les commandes dans un panneau et faites-le de la taille de la fenêtre (changement facile)
  • en fonctionnement: Masquer ce panneau. Utilisez les panneaux .Méthode de DrawToBitmap pour définir l'image de fond de forme.
  • afficher barre de progression, travaillez avec "doevents", cachez-le.
  • image de fond claire, panneau de rediffusion.

Une Meilleure façon:

Les Progrès De La Classe Des Consommateurs

je vais vous donner un Usercontrol j'ai écrit et utilisé dans de nombreux programmes différents qui fait exactement ce que vous voulez. Voici un exemple de consommateur trivial, vous pouvez coller dans le code d'un formulaire (oui, il fait juste un tas de nouveaux boutons pour aucune raison):

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

Les Progrès De La Classe - Définition

et voici la classe. Le créateur de code est collé en ligne, vous pouvez le laisser là. La classe désactive les contrôles lors de l'exécution de sorte que vous pouvez faire est de l'annuler. Il fonctionne sur le fil GUI. Vous pouvez désactiver l'option annuler. Le consommateur est un exemple de traiter avec de nouveaux contrôles supplémentaires afin qu'ils ne se présentent pas activé, mais activé lorsque la progression est plus.

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

bonne chance!

4
répondu FastAl 2010-09-21 19:11:13

vous pouvez désactiver tous les contrôles sur le formulaire en définissant la propriété Enabled à False puis en la changeant de nouveau à True après le processus est fait.

en outre, vous pouvez avoir une étiquette cachée qui dit" Chargement " que vous affichez avant de désactiver le formulaire et de se cacher lors de sa réactivation.

enfin, je suggère que vous divisiez le processus en deux parties. Une partie qui fait le travail sans modifier les commandes que vous pouvez exécuter sur un travailleur le fil et la partie qui change l'interface graphique qui le fait fonctionner sur le fil graphique après que le fil ouvrier est fait. De cette façon, vous ne bloquerez pas toute l'application, rendant les modifications à L'interface graphique plus faciles à faire.

3
répondu Rune Grimstad 2010-09-16 06:44:39

ma solution recommandée est de régler l'opacité des formes à presque invisible say 0,01 avant d'initialiser les composants. Ensuite, créez un formulaire avec la même taille et la position et une barre de progression, ou de sélection sur ce formulaire.. Après l'initialisation de la forme principale, définissez son opacité à remplir et disposez de la forme marquee.

1
répondu Andrew Hanlon 2010-09-20 08:59:43

utilisez une barre de progression de style marquee ou blocks.

http://msdn.microsoft.com/en-us/library/system.windows.forms.progressbar.aspx

0
répondu Mamta D 2010-09-16 06:39:58