开发者

Events being sent to disabled control

I have a problem that I'd like some advice on. I have a button in my GUI that starts a complicated setup sequence (to connect to a analogue to digital converter and start logging data from an echo sounder). Once it is finished setting up, the button changes from START to STOP and has the expected behaviour. What I was experiencing is that during the long operation, if the user clicked on the button again (even though it was disabled) the event would still be sent to the button once it was reenabled. The only way I've found to make this work properly is to call Application.DoEvents() before enabling the button again. All I really want to do is swallow up the events destined for my button, so DoEvents() seems a bit heavy handed. Since people seem to be unanimously against calling DoEvents() I'm hoping that the bright minds here can help me come up with an alternative solution. Note I haven't tried my demo code but it follows my real code closely, excepting the really long methods.

  1. Is there an alternative way to accomplish this?
  2. Is it safe(ish) to call DoEvents() from the completion portion of the background worker?

    public class Form1 : Form {

    BackgroundWorker worker;
    Button startButton;
    bool state;
    
    public Form1() {
        state = false;
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(StartSequence);
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ToggleButton);
        startButton = new Button();
        startButton.Text = "START";
        startButton.Click += new System.EventHandler(StartClicked);
        this.Controls.Add(startButton);
    }
    
    private void StartClicked( object sender, EventArgs e ) {
        startButton.Enabled = false;
        worker.RunWorkerAsync( !state );
    }
    
    private void StartSequence( object sender, DoWorkEventArgs e ) {
        bool onState = (bool) e.Argument;
        if ( onState ) {
            RunR开发者_运维技巧eallyLongStartupSequence();
        }
        else {
            RunReallyLongStopSequence();
        }
        state = onState;
    }
    
    private void ToggleButton( object sender, RunWorkerCompletedEventArgs e ) {
        startButton.Text = state ? "STOP" : "START";
    
        // THIS IS WHAT I AM WORRIED ABOUT!
        Application.DoEvents();
        startButton.Enabled = true;
    }
    

    }


Application.DoEvents() isn't heavy-handed, and I don't think programmers are unanimously opposed to DoEvents in all cases. DoEvents has a bad reputation because it has traditionally been used as a magical hack fix for badly-written code. In your case, it is the proper and normal way to deal with your situation.

In Windows, the situation you describe (where clicks on disabled buttons are applied when the buttons are re-enabled) is actually normal, expected behavior for a control. However, this does not mean that it is always desirable behavior from a programmer's standpoint, and if you have users that are prone to clicking away on disabled buttons, then the simplest way is to use DoEvents, which is nothing more than a method telling the form to go ahead and process any events it has queued up. Use it proudly!


First of all, I do not find DoEvents() bad at all, especially when it comes to gui, you can't imagine how many times it has helped me , and if you create things like progress bars, it is pretty much mandatory if you want to see it update, all I'm saying is that I don't really get why it is considered a bad command. On the topic though, what I usually do in such situations is not disable the control at all I use something similar to the following

public Class myForm :Form
{
    private bool _working = false;

    public myForm()
    {
        _working = true;
        //code here
        this.btnDoStuff.Click += new System.EventHandler(DoStuffClick);

        _working = false;
    }

    private void DoStuffClick(object sender, EventArgs e) 
    {
        if (_working) return;
        _working = true;
        DoStuff();
        _working = false;
    }

    private void DoStuff()
    {
        //your code goes here
    }
}

I find that the above helps me when it comes to allowing the user to do only one thing at a time, and if I want to be able to allow the user to do multiple stuff( for example while the command executes , to be able to press other buttons) I usually put the DoStuff() code to execute in a different thread

In case you were wandering, the reason I use an extra method (DoStuff()) to perform the actions, is that sometimes I need to execute code form other methods in one method, and if the _working flag is set to true, I can't call DoStuffClick(null , new EventArgs()) as it will not do anything

I hope I helped

p.s. yes I know it's been two years, but I only joined stackoverflow the other day (:

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜