Select to view content in your preferred language

ArcMap threading form with progress bar

3321
6
04-09-2012 01:41 PM
CarlosPiccirillo
Emerging Contributor
Hi everyone,

I've been fighting with this problem for almost a week now and I am no closer to a solution than when I started so I am hoping someone has some ideas for me. I've read LOTS of ESRI documentation as well as lots of forums post asking similar things but no concrete solutions.

I have a form where the user enters a number to search for into an input box. When the user clicks the OK button, the search code runs. The problem is that the search code takes several minutes to complete and I want to give the user some indication that the code is running and not locked up. I've tried to set the MouseCursor to hourglass but it's not consistent for some reason, sometimes the hourglass stays on for the entire search like I want it to do and sometimes it does not.

So, I have added a progress bar to my menu below in the input box and set it's ProgressBarStyle to Marquee. I can turn the progress bar on (visible = true) and it updates once but after that, the bar does not move anymore and the progress bar goes away (visible = false) when the search is done.

WAY back in the AML days, I could display a "please wait" form on top of the search form in a separate thread until the search was over and then get rid of the thread. Trying to do the same here except figured I would get fancier and put the progress bar on the main form instead of opening another form.

I've read some ESRI documents that at times seems to indicate this is not doable but I am not sure. Can someone help me out with some sample code or at least give me a yes or no on whether what I am trying to do is even possible or should I abandon my current code and try something else.

I am programming in C# using ArcGIS 9.3 and Visual Studio 2008 and .NET 3.5

Thanks,
Carlos
0 Kudos
6 Replies
RichWawrzonek
Frequent Contributor
I have found the IMouseCursor to behave strangely so tend to avoid it. I think each time your code calls external methods then you need to call .SetCursor() again.

Have you looked into using IProgressDialog? You can use it with a step progressor bar if you know how many iterations the process will take. If you don't know then hide the step progressor as shown below:
            //CREATE OBJECT TO ALLOW USER TO CANCEL
            ITrackCancel trackCancel = new CancelTrackerClass();
            trackCancel.CancelOnClick = true;
            trackCancel.CancelOnKeyPress = true;

            //CREATE A PROGRESS DIALOG
            IProgressDialogFactory progDialogFact = new ProgressDialogFactoryClass();
            IStepProgressor stepProg = progDialogFact.Create(trackCancel, Handle.ToInt32());
            IProgressDialog2 progDialog = (IProgressDialog2)stepProg;
            progDialog.CancelEnabled = true;
            progDialog.Description = "Querying database...";
            progDialog.Title = "Progress Dialog Title Here";
            progDialog.Animation = esriProgressAnimationTypes.esriProgressGlobe;
            stepProg.Message = "Click below to Cancel...";
            stepProg.Hide();


Don't forget to close the dialog in your Finally block:
progDialog.HideDialog();


This progess dialog will not be embeded in your form but pop up in front. However, I have found it to be the most reliable way to show the user that lengthy background processes are occuring.  For shorter processes where a WinForm remains open you may just want to set the Windows cursor to a wait one.
0 Kudos
CarlosPiccirillo
Emerging Contributor
Rich,

Thanks for your reply. Yes, I have tried using the IProcessDialog and it works fine but I was trying to avoid opening yet another pop-up form. My boss REALLY likes how the progressbar set to marquee looks and wants the fewest pop-ups/forms as possible so I was trying to get it to work that way first and only go with the IProcessDialog as a last resort.

I have never tried setting the Windows cursor to a wait one. Can you show me how to do that?

Thanks for your help and time, I really appreciate it!
Carlos


I have found the IMouseCursor to behave strangely so tend to avoid it. I think each time your code calls external methods then you need to call .SetCursor() again.

Have you looked into using IProgressDialog? You can use it with a step progressor bar if you know how many iterations the process will take. If you don't know then hide the step progressor as shown below:
            //CREATE OBJECT TO ALLOW USER TO CANCEL
            ITrackCancel trackCancel = new CancelTrackerClass();
            trackCancel.CancelOnClick = true;
            trackCancel.CancelOnKeyPress = true;

            //CREATE A PROGRESS DIALOG
            IProgressDialogFactory progDialogFact = new ProgressDialogFactoryClass();
            IStepProgressor stepProg = progDialogFact.Create(trackCancel, Handle.ToInt32());
            IProgressDialog2 progDialog = (IProgressDialog2)stepProg;
            progDialog.CancelEnabled = true;
            progDialog.Description = "Querying database...";
            progDialog.Title = "Progress Dialog Title Here";
            progDialog.Animation = esriProgressAnimationTypes.esriProgressGlobe;
            stepProg.Message = "Click below to Cancel...";
            stepProg.Hide();


Don't forget to close the dialog in your Finally block:
progDialog.HideDialog();


This progess dialog will not be embeded in your form but pop up in front. However, I have found it to be the most reliable way to show the user that lengthy background processes are occuring.  For shorter processes where a WinForm remains open you may just want to set the Windows cursor to a wait one.
0 Kudos
KenBuja
MVP Esteemed Contributor
Here's how I set the Windows Wait Cursor (in VB.NET)

Windows.Forms.Cursor.Current = Windows.Forms.Cursors.WaitCursor


The other thing I've done in some of my forms is to add a StatusStrip. In there, I've placed progress bars and messages to give the user an idea of what's happening as the application goes through its steps.

[ATTACH=CONFIG]13380[/ATTACH][ATTACH=CONFIG]13381[/ATTACH][ATTACH=CONFIG]13382[/ATTACH]
0 Kudos
CarlosPiccirillo
Emerging Contributor
Thanks Ken, the windows cursor seems to be more stable than the IMouseCursor one.

I will give the StatusStrip with a progress bar/message a try. I have never tried that before, do you have some code I could look at?

Thanks!
Carlos
0 Kudos
KenBuja
MVP Esteemed Contributor
Look at MSDN help for the full documentation, but here's an example of how I use it. Here, I have already added the StatusStrip (StatusStrip1) to the form. Unfortunately, this example doesn't do anything with a progress bar, but that can also be added.

'form initialization subroutine

            StatusStrip1.Items.AddRange(New System.Windows.Forms.ToolStripItem() {toolStripStatusLabel1})
            StatusStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow
            StatusStrip1.Location = New System.Drawing.Point(0, 0)
            StatusStrip1.Name = "statusStrip1"
            StatusStrip1.ShowItemToolTips = True
            StatusStrip1.Size = New System.Drawing.Size(292, 22)
            StatusStrip1.Text = "statusStrip1"
            toolStripStatusLabel1.Name = "toolStripStatusLabel1"
            toolStripStatusLabel1.Size = New System.Drawing.Size(109, 17)
            toolStripStatusLabel1.Text = "toolStripStatusLabel1"
            StatusStrip1.Visible = False

'processing code
        Try
            StatusStrip1.Visible = True
            toolStripStatusLabel1.Text = "Starting"
            StatusStrip1.Refresh()

            'more code

            toolStripStatusLabel1.Text = "Processing layer " & pLayer.Name
            StatusStrip1.Refresh()

            'more code

        Catch ex As Exception
            System.Windows.Forms.MessageBox.Show(ex.ToString, "Run")
        Finally
              StatusStrip1.Visible = False 'Make it invisible when finished or in case the process crashes early
        End Try



0 Kudos
CarlosPiccirillo
Emerging Contributor
Thanks Ken, this should help a LOT! 🙂
0 Kudos