C#で、指定した2つのアプリを交互にアクティブにするツールを作成したので公開します。
ツールについて
本ツールについて簡単に説明します。
まず、以下がツールの実行イメージです。

簡単に使い方を説明します。
1.「アプリケーション情報取得」ボタンをクリック
切り替える事が出来るアプリの一覧を取得します。
2.リストから切り替えるアプリを選択
本ツール(Form1)が自動で選択されるので、もう1つのアプリを選択します。
本ツール以外を選択しても構いません。
3.「待機中」ボタンをクリック
ボタンが「実行中」に変われば、処理が開始されており、
切り替え間隔(秒)ごとにアクティブウィンドウが切り替わります。
4.切り替えの停止
「実行中」ボタンをクリックすると、切り替えが停止します。
停止処理ですが、停止後に1回切り替えが行われる場合があります。
これは、停止処理が次回以降のループを処理しないようにしているだけで、
直ちに処理を停止するような作りになっていないためです。
ソースコード
以下が、本ツールのソースコードです。
.NET Framework 4.8 環境で実装しました。
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SwitchWindows
{
public partial class Form1 : Form
{
// user32.dllからSetForegroundWindowをインポート
[DllImport("user32.dll")]
public static extern IntPtr SetForegroundWindow(IntPtr hWnd);
private Process process1 = null;
private Process process2 = null;
private CancellationTokenSource cancellationTokenSource;
private bool isRunning = false;
public Form1()
{
InitializeComponent();
}
// プロセスの一覧を取得
private void btnGetApplication_Click(object sender, EventArgs e)
{
// メインウィンドウのタイトルが空でないプロセスの一覧を取得
List<Process> processes = Process.GetProcesses()
.Where(p => !string.IsNullOrEmpty(p.MainWindowTitle))
.OrderBy(p => p.MainWindowTitle)
.ToList();
cbxApp1.Items.Clear();
cbxApp2.Items.Clear();
// リストボックスにウィンドウタイトルを表示
foreach (Process process in processes)
{
cbxApp1.Items.Add(process.MainWindowTitle);
cbxApp2.Items.Add(process.MainWindowTitle);
}
// 本アプリのプロセス情報を初期値として設定
cbxApp1.SelectedIndex = cbxApp1.Items.IndexOf(this.Text);
}
// 選択されたアプリのアクティブウィンドウを交互に切り替える
private void btnSwitchWindows_Click(object sender, EventArgs e)
{
// 実行中か待機中かの状態をトグルする
if (isRunning)
{
// キャンセルリクエストを送信して、スレッドを停止する
cancellationTokenSource?.Cancel();
// 待機中に切り替え
btnSwitchWindows.Text = "待機中";
btnSwitchWindows.BackColor = System.Drawing.Color.LightGray;
isRunning = false;
}
else
{
if (cbxApp1.SelectedItem != null && cbxApp2.SelectedItem != null)
{
string selectedTitle1 = cbxApp1.SelectedItem.ToString();
string selectedTitle2 = cbxApp2.SelectedItem.ToString();
process1 = Process.GetProcesses().FirstOrDefault(p => p.MainWindowTitle == selectedTitle1);
process2 = Process.GetProcesses().FirstOrDefault(p => p.MainWindowTitle == selectedTitle2);
if (process1 != null && process2 != null)
{
// キャンセルトークンソースを生成
cancellationTokenSource = new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
// 新しいスレッドでウィンドウ切り替えを開始
Task.Run(() => SwitchWindowsAlternately(token));
// 実行中に切り替え
btnSwitchWindows.Text = "実行中";
btnSwitchWindows.BackColor = System.Drawing.Color.Red;
isRunning = true;
}
else
{
MessageBox.Show("選択されたアプリケーションが見つかりません。");
}
}
else
{
MessageBox.Show("両方のアプリケーションを選択してください。");
}
}
}
// 交互にウィンドウを切り替える
private void SwitchWindowsAlternately(CancellationToken token)
{
int interval = int.Parse(tbxInterval.Text) * 1000;
// 指定した間隔ごとに交互にウィンドウを切り替える
while (!token.IsCancellationRequested)
{
// process1のウィンドウをアクティブにする
if (process1 != null && !process1.HasExited)
{
SetForegroundWindow(process1.MainWindowHandle);
}
Thread.Sleep(interval);
// process2のウィンドウをアクティブにする
if (process2 != null && !process2.HasExited)
{
SetForegroundWindow(process2.MainWindowHandle);
}
Thread.Sleep(interval);
}
}
}
}
ソースコード(デザイン)
こちらは、フォームアプリのデザインコードです。
namespace SwitchWindows
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.btnGetApplication = new System.Windows.Forms.Button();
this.btnSwitchWindows = new System.Windows.Forms.Button();
this.cbxApp1 = new System.Windows.Forms.ComboBox();
this.cbxApp2 = new System.Windows.Forms.ComboBox();
this.tbxInterval = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// btnGetApplication
//
this.btnGetApplication.Location = new System.Drawing.Point(12, 12);
this.btnGetApplication.Name = "btnGetApplication";
this.btnGetApplication.Size = new System.Drawing.Size(183, 19);
this.btnGetApplication.TabIndex = 0;
this.btnGetApplication.Text = "アプリケーション情報取得";
this.btnGetApplication.UseVisualStyleBackColor = true;
this.btnGetApplication.Click += new System.EventHandler(this.btnGetApplication_Click);
//
// btnSwitchWindows
//
this.btnSwitchWindows.Location = new System.Drawing.Point(227, 12);
this.btnSwitchWindows.Name = "btnSwitchWindows";
this.btnSwitchWindows.Size = new System.Drawing.Size(135, 56);
this.btnSwitchWindows.TabIndex = 1;
this.btnSwitchWindows.Text = "待機中";
this.btnSwitchWindows.UseVisualStyleBackColor = true;
this.btnSwitchWindows.Click += new System.EventHandler(this.btnSwitchWindows_Click);
//
// cbxApp1
//
this.cbxApp1.FormattingEnabled = true;
this.cbxApp1.Location = new System.Drawing.Point(14, 83);
this.cbxApp1.Name = "cbxApp1";
this.cbxApp1.Size = new System.Drawing.Size(348, 20);
this.cbxApp1.TabIndex = 4;
//
// cbxApp2
//
this.cbxApp2.FormattingEnabled = true;
this.cbxApp2.Location = new System.Drawing.Point(14, 120);
this.cbxApp2.Name = "cbxApp2";
this.cbxApp2.Size = new System.Drawing.Size(348, 20);
this.cbxApp2.TabIndex = 5;
//
// tbxInterval
//
this.tbxInterval.Location = new System.Drawing.Point(118, 49);
this.tbxInterval.Name = "tbxInterval";
this.tbxInterval.Size = new System.Drawing.Size(77, 19);
this.tbxInterval.TabIndex = 6;
this.tbxInterval.Text = "10";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 53);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(100, 12);
this.label1.TabIndex = 7;
this.label1.Text = "切り替え間隔(秒):";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(378, 153);
this.Controls.Add(this.label1);
this.Controls.Add(this.tbxInterval);
this.Controls.Add(this.cbxApp2);
this.Controls.Add(this.cbxApp1);
this.Controls.Add(this.btnSwitchWindows);
this.Controls.Add(this.btnGetApplication);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btnGetApplication;
private System.Windows.Forms.Button btnSwitchWindows;
private System.Windows.Forms.ComboBox cbxApp1;
private System.Windows.Forms.ComboBox cbxApp2;
private System.Windows.Forms.TextBox tbxInterval;
private System.Windows.Forms.Label label1;
}
}
リンク
コメント