6月 14

クリックイベントを発生させる

ボタンをマウスやキーボードから押した場合
Click イベントが発生しますが
これをプログラムから【押したことにしたい】場合があります。

あまり良い例ではありませんが、例えば、
文書を保存するSaveボタンを作ったとします。
Saveボタンを押すとClickイベントハンドらが呼び出され、文書を保存しますが
定期的に(10分に1回などにも)Save処理を行いたいとします。
この時、タイマーを利用して10分に1回、Saveボタンを【押したことにしたい】場合

Buttonコントロールの
PerformClick 関数をコールします。

    button1.PerformClick();	// button1コントロールのClickイベントを発生させる
6月 14

テキストの表示位置を設定する

ボタン内のテキスト表示位置を設定する場合は
TextAlign プロパティーの値を変更します。
通常は MiddleCenter です。

通常はプログラムからではなく
デザイン画面からプロパティーで設定することが多いと思います。

button_textalign

上のように、9種類から選択します。
設定を変更すると、デザイン画面にも反映されるので解りやすいです。

もちろん、プログラムから変更することも可能です。
その場合は下記のようになります。

    button1.TextAlign = ContentAlignment.MiddleCenter;  // 中断中央(デフォルト)の場合
    button1.TextAlign = ContentAlignment.TopLeft;       // 左上の場合
6月 14

デフォルトボタン/キャンセルボタンを設定する

フォーム上の
デフォルトボタン(Enterキー/Spaceキーで押されるボタン)
キャンセルボタン(ESCキーで押されるボタン)
を設定するには

フォームの
AcceptButton, CancelButtonプロパティーに
それぞれボタン名を指定します。

【補足】
フォーム上に複数のボタンが存在し、
デフォルトボタン以外のボタンがフォーカスを持つ場合は
フォーカスを持つボタンがデフォルトで押されます。

this.AcceptButton = button1;
this.CancelButton = button2;
6月 14

押されたままの状態にする

ボタンを押すと凹んだような外観になりますが
そのまま凹んだ外観をキープしたい場合は
ボタンコントロールではなく
チェックボックスコントロールを使います。
(チェックボックスの節を参照してください)

チェックボックスの外観を
ボタンのように変更することで
押された際、凹んだままのボタンを実装可能です。

チェックボックスコントロールの
Appearanceプロパティーに列挙体のButtonを設定します。

6月 14

ビットマップなどのイメージ(絵)を張り付ける

ボタンにテキストではなく、イメージを張り付けるには
Imageプロパティーにビットマップファイルなどの
ファイル名を指定します。

なお、イメージの配置位置は
ImageAlignプロパティーに
位置の列挙体を設定することで変更可能です。

イメージのファイル形式は
ビットマップ(.bmp)の他に
アイコン(.ico)や、PNG、JPG、GIFなどがありますので色々試してみてください。

【補足】
デザイン時からイメージを張り付けたい場合は
Imageプロパティーの…ボタンをクリックし、
目的の画像ファイルを選択してください。

また、イメージのみ表示して
ボタン上のテキストが不要な場合は
Textプロパティーの内容を”"としてください。

例:button1.Text = “”;

// ボタンに張り付けるイメージのファイル名を指定します。
// ファイルが存在しない場合は
// System.IO.FileNotFoundException 例外が発生します。
button1.Image = System.Drawing.Image.FromFile(@"c:\unko.bmp");

// 表示位置は中央
button1.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
6月 14

ボタンを有効/無効にする(押せる/押せないようにする)

ボタンに限らずですが
コントロールを有効、無効にする場合は
Enabled プロパティーに true あるいは false を設定します。

true:有効
false:無効

です。
下図では、左のボタンが有効、右のボタンが無効です。

デザイン時にEnabledプロパティーを設定
またはプログラムからEnabledプロパティーを設定します。

button_enable

    private void Form1_Load(object sender, EventArgs e)
    {
        button1.Enabled = true;     // 押せる状態に
        button2.Enabled = false;    // 押せない状態に
    }
6月 14

スレッドの進捗状況を知らせる

BackgroundWorkerを使って実行中の
別スレッドの進捗状況を知らせる方法です。
別節のサンプルに少し手を加えています。

具体的には
ProgressChangedハンドラを追加して進捗の変化を捕捉します。

なお、WorkerReportsProgressプロパティーにtrueを設定して
進捗報告を許可するのを忘れずに

進捗状況の設定は
ReportProgress関数で行います。引数は0~100%

下の例では視覚的に進捗状況がわかるように
ProgressBarコントロールをFormに追加しています。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

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

        private void Form1_Load(object sender, EventArgs e)
        {
            // RunWorkerAsyncが呼び出された時に発生
            backgroundWorker1.DoWork += 
            	new DoWorkEventHandler(backgroundWorker1_DoWork);

            // BackgroundWorkerでの処理が完了した時に発生
            backgroundWorker1.RunWorkerCompleted += 
            	new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

            // 進捗があった時に発生
            backgroundWorker1.ProgressChanged += 
            	new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

            // キャンセルされることを許可
            backgroundWorker1.WorkerSupportsCancellation = true;

            // 進捗報告を許可
            backgroundWorker1.WorkerReportsProgress = true;
        }

        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled)
                MessageBox.Show("処理はキャンセルされました");
            else
                MessageBox.Show("処理完了");
        }

        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                // キャンセルされた?
                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                backgroundWorker1.ReportProgress(i);

                System.Diagnostics.Debug.Write("@");
                Application.DoEvents();
            }

            backgroundWorker1.ReportProgress(100);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // BackgroundWorkerが処理中でなければ
            if (!backgroundWorker1.IsBusy)
            {
                // バックグラウンド処理を開始
                backgroundWorker1.RunWorkerAsync();

                for (int i = 0; i < 100; i++)
                {
                    System.Diagnostics.Debug.Write("_");
                    Application.DoEvents();
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 処理をキャンセルします
            backgroundWorker1.CancelAsync();
        }
    }
}
6月 14

スレッドの処理を途中で停止、キャンセルする

BackgroundWorkerを使って実行中の別スレッドの処理をキャンセルする方法です。
(前節のサンプルにスレッドを停止する2つ目のボタンを追加しています)

まず準備として
BackgroundWorkerのWorkerSupportsCancellationプロパティーにtrueを設定し
このスレッドがキャンセルに対応することを設定します。

実際のキャンセル処理ですが
BackgroundWorkerのCancelAsync関数を任意のタイミングで呼び出します。

後は、DoWorkハンドラ内で定期的にキャンセルされていないか
CancellationPendingプロパティーを監視し、

CancellationPendingにtrueが設定されていれば
DoWorkEventArgs引数のCancelプロパティーにtrueを設定して
処理を中断(return)します。

処理が完了しても中断しても
最後はRunWorkerCompletedハンドラが呼ばれるので
そこでキャンセルによる停止なのか処理が完了したのか
理由を参照します。(e.Cancelled)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

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

        private void Form1_Load(object sender, EventArgs e)
        {
            // RunWorkerAsyncが呼び出された時に発生
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

            // BackgroundWorkerでの処理が完了した時に発生
            backgroundWorker1.RunWorkerCompleted += 
            	new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

            // キャンセルされることを許可
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled)
                MessageBox.Show("処理はキャンセルされました");
            else
                MessageBox.Show("処理完了");
        }

        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 1000; i++)
            {
                // キャンセルされた?
                if (backgroundWorker1.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                System.Diagnostics.Debug.Write("@");
                Application.DoEvents();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // BackgroundWorkerが処理中でなければ
            if (!backgroundWorker1.IsBusy)
            {
                // バックグラウンド処理を開始
                backgroundWorker1.RunWorkerAsync();

                for (int i = 0; i < 1000; i++)
                {
                    System.Diagnostics.Debug.Write("_");
                    Application.DoEvents();
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 処理をキャンセルします
            backgroundWorker1.CancelAsync();
        }
    }
}
6月 14

BackgroundWorkerを使って別スレッドで処理する

BackgroundWorkerを使えば、簡単に別スレッドで処理を実行することができます。

使い方はとても簡単です。
FormにBackgroundWorkerをドラッグ&ドロップで配置し
DoWorkとRunWorkerCompletedのイベントハンドラをそれぞれ追加します。

DoWorkハンドラには
別スレッドで処理したいコードを記述します。

RunWorkerCompletedには
別スレッドでの処理が完了した際のコードを記述します。

例として
FormにButtonとBackgroundWorkerを配置し
ボタンをクリックされたら
Clickイベントハンドラ内で文字をループ表示しつつ
別スレッドでも同様に違い文字をループ表示させてみます。

結果は出力パネルに出力されます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

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

        private void Form1_Load(object sender, EventArgs e)
        {
            // RunWorkerAsyncが呼び出された時に発生
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

            // BackgroundWorkerでの処理が完了した時に発生
            backgroundWorker1.RunWorkerCompleted += 
            	new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
        }

        void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("処理完了");
        }

        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                //System.Threading.Thread.Sleep(10);
                System.Diagnostics.Debug.Write("@");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // BackgroundWorkerが処理中でなければ
            if (!backgroundWorker1.IsBusy)
            {
                // バックグラウンド処理を開始
                backgroundWorker1.RunWorkerAsync();

                for (int i = 0; i < 100; i++)
                {
                    //System.Threading.Thread.Sleep(10);
                    System.Diagnostics.Debug.Write("_");
                }
            }
        }
    }
}

■結果

@@@@@@@@@@@_@@@@@@@@___@@@@@@@@@@____@@@@@@________@@@@@@@@_____@____@@@@@@@(以後省略)