#if SELFTEST
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace TIASshot {
public partial class Form1 {
/// <summary>
/// ヘッドレス(非表示)セルフテスト用コンストラクタの目印型(SELFTEST 限定).
/// </summary>
internal sealed class SelfTestHeadless {
internal static readonly SelfTestHeadless Instance = new SelfTestHeadless();
private SelfTestHeadless() { }
}
// ヘッドレスモードか(ShowError をモーダル表示せず記録に切り替える)
private bool _selfTestHeadless = false;
// ヘッドレスモードで ShowError に渡されたメッセージ(最後の 1 件)
private string _selfTestLastError = null;
/// <summary>
/// ヘッドレス(非表示)セルフテスト用コンストラクタ(SELFTEST 限定).
/// InitializeComponent は IC Imaging Control(カメラ SDK)のコントロールを生成するため呼ばず,
/// プレビュー・校正・撮影の経路(ShowImage / MainRefreshTimer_Tick / ShowMessage / EnableShots /
/// GetDataName 等)が参照するコントロールだけを生成する.
/// 本モニタの再描画タイマーの設定は Form1_Load と同じ値で行う(Form1_Load はカメラ接続を含むため呼ばない).
/// </summary>
internal Form1(SelfTestHeadless marker) {
_selfTestHeadless = true;
picPreview = new PictureBox();
picDisplay = new PictureBox { Size = new Size(449, 610), SizeMode = PictureBoxSizeMode.Zoom };
txtMessage = new TextBox();
txtDataName = new TextBox { Text = "selftest" };
txtNumMultiShots = new TextBox { Text = "1" };
txtMultiShotsInterval = new TextBox { Text = "0" };
txtDeviceName = new TextBox();
txtSerialNo = new TextBox();
txtSaveFolder = new TextBox();
txtConvElemNum = new TextBox();
btnShotOne = new Button();
btnShotMulti = new Button();
btnLightSW = new Button();
btnOpenDataFolder = new Button();
Controls.AddRange(new Control[] {
picPreview, picDisplay, txtMessage, txtDataName, txtNumMultiShots, txtMultiShotsInterval,
txtDeviceName, txtSerialNo, txtSaveFolder, txtConvElemNum,
btnShotOne, btnShotMulti, btnLightSW, btnOpenDataFolder,
});
ShowInTaskbar = false;
Text = $"{APP_NAME} [SELFTEST]";
_mainRefreshTimer.Interval = MainRefreshIntervalMs;
_mainRefreshTimer.Tick += MainRefreshTimer_Tick;
}
/// <summary>
/// ウィンドウハンドルを生成し(表示はしない),本モニタの再描画タイマーを開始する.
/// ハンドルが無いと InvokeRequired が常に false となり,ワーカースレッドからの
/// ShowMessage / EnableShots が UI スレッドへマーシャリングされない(実運用と異なる経路になる)ため必ず呼ぶ.
/// </summary>
/// <param name="previewMonitor">副モニタ(null 可)</param>
internal void SelfTestStart(PreviewMonitor previewMonitor) {
CreateHandle();
_previewMonitor = previewMonitor;
EnableShots(false);
_mainRefreshTimer.Start();
}
/// <summary>本モニタ(picDisplay)に現在表示中の画像</summary>
internal Image SelfTestDisplayedImage => picDisplay.Image;
/// <summary>ステータス表示(txtMessage)の現在値</summary>
internal string SelfTestMessage => txtMessage.Text;
/// <summary>ヘッドレスモードで ShowError に渡された最後のメッセージ(無ければ null)</summary>
internal string SelfTestLastError => _selfTestLastError;
/// <summary>撮影ボタンが有効か</summary>
internal bool SelfTestShotsEnabled => btnShotOne.Enabled && btnShotMulti.Enabled;
/// <summary>ShowError のヘッドレス版(モーダルダイアログを出すと無人実行が止まるため記録のみ行う)</summary>
private void SelfTestRecordError(string msg) {
Debug.WriteLine($"[SELFTEST] ShowError: {msg}");
_selfTestLastError = msg;
}
/// <summary>
/// タイマー停止と表示用 Bitmap の解放(FormClosing の代わり.Dispose の前に UI スレッドで呼ぶ).
/// </summary>
internal void SelfTestShutdown() {
_mainRefreshTimer.Stop();
_mainRefreshTimer.Dispose();
var shown = picDisplay.Image;
picDisplay.Image = null;
shown?.Dispose();
Bitmap pending;
lock (_dispBufLock) {
pending = _dispBuf;
_dispBuf = null;
_isUpdateBuf = false;
}
pending?.Dispose();
}
}
}
#endif