1 秒に 1 回タイマーをインクリメントし、ラベルのテキストを更新する WinForms アプリがあります。2 番目のタイマーは 20 ミリ秒ごとに 1 回インクリメントして、最近のマウスの動きを探し、現在の座標を別のラベルに書き込みます。
プログラムが Alt+F4 を受け取ると、「MessageBoxQueryClose」をインスタンス化し、ユーザーが操作を閉じるか再開するよう求められます。MessageBox が表示される前に、1 秒ごとのタイマーの起動を停止し、ユーザーが「続行してください」と言った後に再び有効にしたいと思います。
ここで、いくつかの「奇妙な」動作を観察しました。MessageBox が開いていて、マウスが移動しているときに、1 秒ごとのタイマーが再び起動します。
フォームのコード:
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 を使い始めたばかりなので、洞察をいただければ幸いです。
br、クリス