0

我有一个 WinForms 应用程序,它每秒增加一次计时器并更新标签的文本。第二个计时器每 20 毫秒递增一次,以查找最近的鼠标移动并将当前坐标写入另一个标签。

当程序收到 Alt+F4 时,我实例化“MessageBoxQueryClose”,要求用户关闭或恢复操作。在显示 MessageBox 之前,我想停止每秒一次的计时器触发,并且在用户说“请继续”之后重新启用它。

这是我观察到一些“奇怪”行为的地方:当 MessageBox 打开并且鼠标移动时,每秒一次的计时器再次触发。

表格代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Globalization;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool _altF4Pressed = false;

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Alt && e.KeyCode == Keys.F4)
                _altF4Pressed = true;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // show the MessageBox asking the user if the programm should really exit
            MessageBoxQueryClose msgBoxQC = new MessageBoxQueryClose();
            msgBoxQC.QueryClose(ref _altF4Pressed, ref timer2, ref e);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 20;
            timer1.Enabled = true;

            timer2.Interval = 1000;
            timer2.Enabled = true;
        }


        bool toggle = false;

        private void timer2_Tick(object sender, EventArgs e)
        {
            if (toggle)
                label1.Text = "tick";
            else
                label1.Text = "tack";

            toggle = !toggle;
        }


        Point oldPos, newPos;

        private void timer1_Tick(object sender, EventArgs e)
        {
            newPos = Cursor.Position;
            label2.Text = Convert.ToString(newPos.X + ", " + newPos.Y);

            CompareCursorPosition();

            oldPos = newPos; 
        }

        private void CompareCursorPosition()
        {
            if (oldPos != newPos)
                Display_ResetFallback();
        }

        private void Display_ResetFallback()
        {
            timer2.Stop();
            timer2.Start();
        }
    }
}

MessageBoxQueryClose 的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace WindowsFormsApplication1
{
    class MessageBoxQueryClose
    {
        public void QueryClose(ref bool _altF4Pressed, ref Timer timer, ref FormClosingEventArgs e) 
        {
            if (_altF4Pressed)
            {
                // first, disable timer2 to stop Form1.label1 from being updated 
                timer.Enabled = false;

                if (e.CloseReason == CloseReason.UserClosing)
                {
                    DialogResult res;

                    res = MessageBox.Show("Close program ?", "timers",
                                MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);


                    if (res == DialogResult.Yes)
                    {
                        return;
                    }

                    // if program execution shall continue, re-enable timer2
                    timer.Enabled = true;
                }
                e.Cancel = true;
                _altF4Pressed = false;
            }
        }
    }
}

我直觉我的问题是关于计时器和线程,但我最近才开始使用 .Net,所以任何见解都值得赞赏。

兄弟,克里斯

4

2 回答 2

3

您的timer1_Tick事件调用了 CompareCursorPosition(),它调用了 Display_ResetFallback(),它又开始timer2了。

timer2因此,您在 QueryClose() 中停止,但随后timer1_Tick事件触发,timer2再次启动。

您可以修改 Display_ResetFallback() 以确保您的计时器仅在当前运行时才重新启动:

if (timer2.Enabled)
{
    timer2.Stop();
    timer2.Start();
}

作为旁注,我可能会完全摆脱 MessageBoxQueryClose 类,并相应地修改您的FormClosing事件:

if (e.CloseReason == CloseReason.UserClosing)
{
    timer2.Stop();

    if (MessageBox.Show("Close program ?", "timers", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
    {
        e.Cancel = true;
        timer2.Start();
    }
}
于 2013-06-15T13:27:01.680 回答
0

你可以试试这个...

        timer1.Stop();
        label1.Text = timer1.Enabled == false ?"timer disabled":"timer enabled";
        if (MessageBox.Show("Close program ?", "timers",
              MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.OK)
        {
            //do stuff here if you want
        }
        timer1.Start();
        label1.Text = timer1.Enabled == false ? "timer disabled" : "timer enabled";

只需将那些标签文本供您检查。这个编辑你不需要类

编辑:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool _altF4Pressed = false;

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Alt && e.KeyCode == Keys.F4)
                _altF4Pressed = true;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //show the MessageBox asking the user if the programm should really exit
            //MessageBoxQueryClose msgBoxQC = new MessageBoxQueryClose();
            //msgBoxQC.QueryClose(ref _altF4Pressed, ref timer2, ref e);

            if (_altF4Pressed)
            {
                this.timer2.Stop();
                if (MessageBox.Show("Close program ?", "timers",
                                MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
                {
                    e.Cancel = true;
                    this.timer2.Start();
                }

            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 20;
            timer1.Enabled = true;

            timer2.Interval = 1000;
            timer2.Enabled = true;
        }


        bool toggle = false;

        private void timer2_Tick(object sender, EventArgs e)
        {
            if (toggle)
                label1.Text = "tick";
            else
                label1.Text = "tack";

            toggle = !toggle;
        }


        //Point oldPos, newPos;

        private void timer1_Tick(object sender, EventArgs e)
        {

            label2.Text = MousePosition.X.ToString() + " , " + MousePosition.Y.ToString();
        }

        //private void CompareCursorPosition()
        //{
        //    if (oldPos != newPos)
        //        Display_ResetFallback();
        //}

        //private void Display_ResetFallback()
        //{
        //    timer2.Stop();
        //    timer2.Start();
        //}
    }

只需将我的第一篇文章放在你的代码中......它为我停止,不需要额外的类,删除了 2 个点和 2 个方法(Display_ResetFallback 和 CompareCursorPosition),但你可以使用它们(2 个点变量)如果你想在 timer1 里面做你的检查。

于 2013-06-15T13:31:36.307 回答