PowerShellでタスク管理ツールを作成
PowerShellでWindowsフォームを作ることができることがわかったので、下記のようなタスク管理ツールを作ってみた。データはフォルダとフォルダ内にあるTask.xmlで保持するようにしてみた。
frm010_000_Project.ps1にすべての処理を記載してあり、ファイルの分割などは行っていない。ただどうしてもアセンブリ読み込みの関係で単一ファイルにすることができなかった。
下記のアセンブリ読み込みを実行しないとFormの継承をすることができなく、スクリプト上で指定をしていてもスクリプトを開く前に実行をしておかないと読み込みができずエラーが発生する。※Classの読み込みがスクリプト上のAdd-Typeよりも先に実行されるためだと思うが・・・。スクリプト上でClassをインスタンス化して処理をしている可能性があるので、当然といえば当然の気もする・・・・。
<事前実行する必要のあるアセンブリ読み込みコマンド>
Add-Type -AssemblyName System.Windows.Forms;
Add-Type -AssemblyName System.Drawing;
そのため、Main.ps1を実行すると、アセンブリ読み込みを行った後に同階層にある「frm010_000_Project.ps1」を読み込んで、インスタンス化するような形で作成している。
このツールのいいところはインストール不要であり、フリーソフトなどのファイルをダウンロードすることができない環境でもコピペすれば使えること。
問題は、まだタスクの検索機能や削除機能、終了したタスクをアーカイブする処理を作っていないこと・・・。
試してはいないが、Tree階層をフォルダ階層で表していて、1タスク1フォルダで、データは各フォルダに配置されているTask.xmlにそれぞれ管理しているので共通フォルダに「Main.ps1」「frm010_000_Project.ps1」「Data」フォルダを配置することで複数人で利用できるはず。試していないけど。
ソースコード
Main.ps1
-------
Add-Type -AssemblyName System.Drawing;
Add-Type -AssemblyName System.Windows.Forms;
$CurrentDir = Split-Path $MyInvocation.MyCommand.path;
$ScriptName = $MyInvocation.MyCommand.path;
$Basename = $MyInvocation.MyCommand.Name;
# 読み込むファイル
$MenuFile = $CurrentDir + "\frm010_000_Project.ps1";
.$MenuFile;
[Application]::EnableVisualStyles();
$form = [frm010_000_Projet]::new();
$form.fstrCurrentPath = $CurrentDir;
$form.StartPosition="CenterScreen"; # 列挙体は文字列で指定する必要がある
$form.ShowDialog();
frm010_000_Project.ps1
-------
using namespace System.Windows.Forms;
using namespace System.Drawing;
#デバッグ する際にはターミナルで流しておく必要がある。Classの継承を行っており、Class定義がスクリプトの中で一番最初に読み込まれる(?)ためエラーが出る。先に別ファイルやターミナルで実行することで回避
Add-Type -AssemblyName System.Windows.Forms;
Add-Type -AssemblyName System.Drawing;
# [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
# [void][reflection.assembly]::LoadWithPartialName("System.Drawing")
$CurrentDir = Split-Path $MyInvocation.MyCommand.path;
$ScriptName = $MyInvocation.MyCommand.path;
$Basename = $MyInvocation.MyCommand.Name;
# ------------------------------------------------------------------------------------------------------------
# メイン画面を作成
# ------------------------------------------------------------------------------------------------------------
# Formクラスを継承して新しいクラスを作成する
Class frm010_000_Projet :System.Windows.Forms.Form{
[string]$fstrCurrentPath; # インスタンス後に設定される。$MyInvocation.MyCommandはスクリプト内で定義されており、ウォッチ式は見れるがクラスの中では取得できない。
[System.Collections.Generic.Dictionary[string,TreeNode]]$fdicNodes;
[System.Collections.Generic.Dictionary[string,TreeNode]]$fdicNodesById;
[System.Data.DataSet]$fdsCurrentData ;
[string]$DATA_FILE_NAME = "Task.xml";
[string]$DATA_TABLE_NAME_CONTENT = "ContentsData";
[string]$DATA_TABLE_NAME_HISTORY = "HistoryData";
[string]$COLNAME_CONTENTS_TITLE = "Title";
[string]$COLNAME_CONTENTS_LIMITDAY = "LimitDay";
[string]$COLNAME_CONTENTS_LIMITALERTDAYCOUNT = "LimitAlertDayCount";
[string]$COLNAME_CONTENTS_STATUS = "Status";
[string]$COLNAME_CONTENTS_COLORLABEL = "ColorLabel";
[string]$COLNAME_CONTENTS_MEMBER = "Member";
[string]$COLNAME_CONTENTS_CLASS = "Class";
[string]$COLNAME_CONTENTS_CREATEIONDATETIME = "CreateDateTime";
[string]$COLNAME_CONTENTS_CONTENTS = "Contents";
[string]$COLNAME_CONTENTS_NOTE = "Note";
[string]$COLNAME_HISTORY_PATTERN = "Pattern";
[string]$COLNAME_HISTORY_CONTROL = "Control";
[string]$COLNAME_HISTORY_CREATEIONDATETIME = "CreateDateTime";
[string]$COLNAME_HISTORY_USERNAME = "UserName";
[string]$COLNAME_HISTORY_HISTORYCONTENTS = "HistoryContents";
[string]$DGV_COLNAME_TRKDATETIME = "colTrkDateTime";
[string]$DGV_COLNAME_KBN = "colKbn";
[string]$DGV_COLNAME_CONTROL = "colControl";
[string]$DGV_COLNAME_HOSTNAME = "colHostName";
[string]$DGV_COLNAME_CONTENTS = "colContents";
[string]$DGV_ALIGN_MIDDLECENTER = "MiddleCenter";
[string]$DGV_ALIGN_MIDDLELEFT = "MiddleLeft";
[string]$DGV_ALIGN_MIDDLERIGHT = "MiddleRight";
[string]$STATUS_TODO = "作業前";
[string]$STATUS_DOING = "作業中";
[string]$STATUS_DONE = "作業完了";
[string]$PATTERN_AUTO = "自動";
[string]$PATTERN_CHANGELOG = "変更";
[string]$PATTERN_COMMENT = "コメント";
[string]$LABELCOLOR_RED = "赤";
[string]$LABELCOLOR_PINK = "桃";
[string]$LABELCOLOR_PURPLE = "紫";
[string]$LABELCOLOR_ORANGE = "橙";
[string]$LABELCOLOR_YELLOW = "黄";
[string]$LABELCOLOR_GREEN = "緑";
[string]$LABELCOLOR_LIGHTBLUE = "水";
[string]$LABELCOLOR_BLUE = "青";
# ↓↓↓↓↓ Design Start
# 色:https://www.lab-nemoto.jp/www/leaflet_edu/else/ColorMaker.html
# ▼タイトル
$lblTitle=[Label]@{
Location = [Point]::new(5,5);
Size=[Size]::new(80,20);
Text = “タイトル”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtTitle=[TextBox]@{
Location = [Point]::new(88,5);
Size=[Size]::new(20,20);
Anchor="Top,Left,Right";
Text = “”;
}
# ▼期限
$lblLimit=[Label]@{
Location = [Point]::new(5,30);
Size=[Size]::new(80,20);
Text = “期限”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtLimit=[TextBox]@{
Location = [Point]::new(88,30);
Size=[Size]::new(90,30);
Anchor="Top,Left";
Text = “”;
}
# ▼期限通知カウント
$txtAlertDayCount=[TextBox]@{
Location = [Point]::new(180,30);
Size=[Size]::new(20,30);
Anchor="Top,Left";
TextAlign = [System.Windows.Forms.HorizontalAlignment]::Right;
MaxLength = 1;
Text = “”;
}
$lblAlertDayCount=[Label]@{
Location = [Point]::new(202,32);
Size=[Size]::new(85,20);
Text = “日前に通知”;
Anchor="Top,Left";
BorderStyle="None";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
# ▼進捗状況
$lblStatus=[Label]@{
Location = [Point]::new(290,30);
Size=[Size]::new(75,20);
Text = “進捗状況”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$cboStatus=[ComboBox]@{
Location = [Point]::new(368,30);
Size=[Size]::new(90,20);
DropDownStyle = "DropDownList";
}
# ▼色
$lblColorLabel=[Label]@{
Location = [Point]::new(465,30);
Size=[Size]::new(50,20);
Text = “色”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$cboColorLabel=[ComboBox]@{
Location = [Point]::new(517,30);
Size=[Size]::new(45,20);
DropDownStyle = "DropDownList";
}
$lblStickyNote=[Label]@{
Location = [Point]::new(565,30);
Size=[Size]::new(20,20);
Text = “”;
#BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
# ▼担当
$lblMember=[Label]@{
Location = [Point]::new(5,55);
Size=[Size]::new(80,20);
Text = “担当”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtMember=[TextBox]@{
Location = [Point]::new(88,55);
Size=[Size]::new(115,30);
Anchor="Top,Left";
Text = “”;
}
# ▼分類
$lblClass=[Label]@{
Location = [Point]::new(212,55);
Size=[Size]::new(60,20);
Text = “分類”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtClass=[TextBox]@{
Location = [Point]::new(275,55);
Size=[Size]::new(90,30);
Anchor="Top,Left";
Text = “”;
}
# ▼登録日時
$lblCreateDateTime=[Label]@{
Location = [Point]::new(367,55);
Size=[Size]::new(65,20);
Text = “登録日時”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtCreateDateTime=[TextBox]@{
Location = [Point]::new(435,55);
Size=[Size]::new(165,30);
Anchor="Top,Left";
Text = “”;
ReadOnly = $True
}
# ▼コンテンツ
$lblContents=[Label]@{
Location = [Point]::new(5,80);
Size=[Size]::new(80,20);
Text = “内容”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtContents=[TextBox]@{
Location = [Point]::new(88,80);
Size=[Size]::new(20,105);
Anchor="Top,Left,Right";
Text = “”;
WordWrap = $False;
ScrollBars = "Both";
Multiline = $True;
}
# ▼備考
$lblNote=[Label]@{
Location = [Point]::new(5,190);
Size=[Size]::new(80,20);
Text = “備考”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtNote=[TextBox]@{
Location = [Point]::new(88,190);
Size=[Size]::new(20,65);
Anchor="Top,Left,Right";
Text = “”;
WordWrap = $False;
ScrollBars = "Both";
Multiline = $True;
}
# ▼メインとなるテーブルレイアウトパネル
$tlpMainLayout=[TableLayoutPanel]@{
ColumnCount = 1;
RowCount=2;
Dock= "Fill";
}
# ▼変更履歴を表示するかどうかのチェックボックス
$chkShowHistory=[CheckBox]@{
Location = [Point]::new(5,2);
Size=[Size]::new(140,20);
Anchor="Top,Left";
Text = "変更履歴を表示"
Checked=$false;
}
# ▼変更履歴及びコメント一覧
$dgv = [DataGridView]@{
Location = [Point]::new(5,23);
Size=[Size]::new(140,20);
Anchor="Top,Left,Right,Bottom";
AutoGenerateColumns=$false;
AllowUserToAddRows=$False;
AllowUserToDeleteRows=$False;
ReadOnly=$True;
}
# ▼履歴内容
$lblHistoryContents=[Label]@{
Location = [Point]::new(5,5);
Size=[Size]::new(270,20);
Text = “履歴内容”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtHistoryContents=[TextBox]@{
Location = [Point]::new(5,28);
Size=[Size]::new(270,15);
Anchor="Top,Bottom,Left";
Text = “”;
WordWrap = $False;
ScrollBars = "Both";
ReadOnly=$true;
Multiline = $True;
}
# ▼コメント
$lblComments=[Label]@{
Location = [Point]::new(278,5);
Size=[Size]::new(270,20);
Text = “追加コメント”;
BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
Anchor="Top,Left";
BorderStyle="FixedSingle";
TextAlign = "MiddleLeft";
AutoSize = $False;
}
$txtComments=[TextBox]@{
Location = [Point]::new(278,28);
Size=[Size]::new(270,15);
Anchor="Top,Bottom,Left";
Text = "";
WordWrap = $False;
ScrollBars = "Both";
Multiline = $True;
}
# ▼追加ボタン
$btnAddComment=[Button]@{
Location = [Point]::new(553,100);
Size=[Size]::new(50,25);
BackColor = "Silver";
Anchor="Top,Left";
Text = "追加";
}
# ▼登録内容と履歴内容の区切り(TreeViewとその右側の区切り)
$SpContainVertical=[SplitContainer]@{
Dock="Fill";
Orientation = "Vertical";
BorderStyle = "FixedSingle"
}
# ▼登録内容と履歴内容の区切り(タスク内容と履歴内容の水平区切り)
$SpContainTask=[SplitContainer]@{
Dock="Fill";
Orientation = "Horizontal";
BorderStyle = "FixedSingle";
# Initializeでコントロールの追加をしてからでないとうまく反映できないためコメントアウト
# SplitterDistance = 50;
}
$SpContainHorizontal=[SplitContainer]@{
Dock="Fill";
Orientation = "Horizontal";
BorderStyle = "FixedSingle";
}
# ▼TreeView
$tvTasks = [TreeView]@{
Dock="Fill";
AllowDrop = $True;
HideSelection = $False; # フォーカスを失ってもノードの選択状態を維持する
}
# ▼メニューバー
$menuFormMain = [MenuStrip]@{
}
# ↑↑↑↑↑ Design End
# ↓↓↓↓↓ Method
# コンストラクタ
frm010_000_Projet(){
$this.Initialize();
# Load_Events
$frm_Load = {
$this.RefreshTreeViewNodes();
$this.SpContainTask.SplitterDistance = 260;
$this.SpContainHorizontal.SplitterDistance = 150;
}
$this.add_Load($frm_Load);
}
# ------------------------------------------------------------------------------------------------------------
# 初期化処理
# ------------------------------------------------------------------------------------------------------------
Initialize() {
$this.Text = "Task"
$this.Size = [Size]::new(950, 670);
$this.Font = New-Object Drawing.Font("MS Gothic",10) ;
$this.dgv.Font = New-Object Drawing.Font("MS Gothic",9) ;
$this.chkShowHistory.Font = New-Object Drawing.Font("MS Gothic",9) ;
#$this.Font = New-Object Drawing.Font("BIZ UDGothic",10) ;
#$this.dgv.Font = New-Object Drawing.Font("BIZ UDGothic",9) ;
#$this.chkShowHistory.Font = New-Object Drawing.Font("BIZ UDGothic",9) ;
$this.BackColor = [System.Drawing.Color]::FromArgb(232, 241, 255);
$this.fdicNodes = [System.Collections.Generic.Dictionary[String, PSObject]]::new();
$this.fdicNodesById = [System.Collections.Generic.Dictionary[String, PSObject]]::new();
# コントロールを追加
# レイアウトロジックを停止する
$this.SuspendLayout()
# Menuを追加する
$this.MenuControlInit()
# 各種パネルを追加する
# TableLayoutPanelを主に配置し、SplitContainerパネルを配置していく
$this.Controls.Add($this.tlpMainLayout)
$this.tlpMainLayout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle("Absolute",70)));
$this.tlpMainLayout.CellBorderStyle = "Single";
$this.tlpMainLayout.Controls.Add($this.SpContainVertical,0,1);
$this.SpContainVertical.Panel2.Controls.Add($this.SpContainTask);
$this.SpContainTask.Panel2.Controls.Add($this.SpContainHorizontal);
# 画面右側のタスクの登録項目を配置していく
$this.SpContainTask.Panel1.Controls.Add($this.lblTitle);
$this.SpContainTask.Panel1.Controls.Add($this.txtTitle);
$this.SpContainTask.Panel1.Controls.Add($this.lblLimit);
$this.SpContainTask.Panel1.Controls.Add($this.txtLimit);
$this.SpContainTask.Panel1.Controls.Add($this.txtAlertDayCount);
$this.SpContainTask.Panel1.Controls.Add($this.lblAlertDayCount);
$this.SpContainTask.Panel1.Controls.Add($this.lblStatus);
$this.SpContainTask.Panel1.Controls.Add($this.cboStatus);
$this.SpContainTask.Panel1.Controls.Add($this.lblColorLabel);
$this.SpContainTask.Panel1.Controls.Add($this.cboColorLabel);
$this.SpContainTask.Panel1.Controls.Add($this.lblStickyNote);
$this.SpContainTask.Panel1.Controls.Add($this.lblMember);
$this.SpContainTask.Panel1.Controls.Add($this.txtMember);
$this.SpContainTask.Panel1.Controls.Add($this.lblClass);
$this.SpContainTask.Panel1.Controls.Add($this.txtClass);
$this.SpContainTask.Panel1.Controls.Add($this.lblCreateDateTime);
$this.SpContainTask.Panel1.Controls.Add($this.txtCreateDateTime);
$this.SpContainTask.Panel1.Controls.Add($this.lblContents);
$this.SpContainTask.Panel1.Controls.Add($this.txtContents);
$this.SpContainTask.Panel1.Controls.Add($this.lblNote);
$this.SpContainTask.Panel1.Controls.Add($this.txtNote);
# 履歴一覧を表示する
$this.SpContainHorizontal.Panel1.Controls.Add($this.dgv);
$this.SpContainHorizontal.Panel1.Controls.Add($this.chkShowHistory);
# 履歴コメントを表示する
$this.SpContainHorizontal.Panel2.Controls.Add($this.lblHistoryContents);
$this.SpContainHorizontal.Panel2.Controls.Add($this.txtHistoryContents);
$this.SpContainHorizontal.Panel2.Controls.Add($this.lblComments);
$this.SpContainHorizontal.Panel2.Controls.Add($this.txtComments);
$this.SpContainHorizontal.Panel2.Controls.Add($this.btnAddComment);
$this.SpContainVertical.Panel1.Controls.Add($this.tvTasks);
# コンボボックスの選択肢を生成
# 進捗状況コンボボックス
$this.cboStatus.Items.Clear();
$this.cboStatus.Items.Add($this.STATUS_TODO);
$this.cboStatus.Items.Add($this.STATUS_DOING);
$this.cboStatus.Items.Add($this.STATUS_DONE);
# 色コンボボックス
$this.cboColorLabel.Items.Clear();
$this.cboColorLabel.Items.Add("");
$this.cboColorLabel.Items.Add($this.LABELCOLOR_RED);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_PINK);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_PURPLE);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_ORANGE);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_YELLOW);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_GREEN);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_LIGHTBLUE);
$this.cboColorLabel.Items.Add($this.LABELCOLOR_BLUE);
$cboColorLabel_Leave={
$sender = $args[0];
$e = $args[1];
$sender.FindForm().SetStickyNoteColor($sender);
}
$this.cboColorLabel.add_Leave($cboColorLabel_Leave);
# ■ 各種イベントを追加
# タイトル
$txtTitle_Leave={
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
$form.tvTasks.SelectedNode.Text = $form.txtTitle.Text;
$form.SaveFile($form.tvTasks.SelectedNode.Tag);
}
$this.txtTitle.add_Leave($txtTitle_Leave);
# 期限
$txtLimitDay_Leave={
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
$sender.Text = $form.GetDateTryConvertFromString($sender.Text);
}
$this.txtLimit.add_Leave($txtLimitDay_Leave);
# 期限通知日数
$txtAlertDayCount_Leave = {
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
if ([double]::TryParse($sender.Text,[ref]$null) -ne $true){
$sender.Text = "";
[System.Windows.Forms.MessageBox]::Show("数値で入力してください", "エラー");
$sender.Focus();
} elseif ($sender.Text.Length -ne 1) {
$sender.Text = "";
[System.Windows.Forms.MessageBox]::Show("1桁で入力してください", "エラー");
$sender.Focus();
}
}
$this.txtAlertDayCount.add_Leave($txtAlertDayCount_Leave);
# 処理状況
$cboStatus_Leave={
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
$form._SetTreeNodeStyle($form.tvTasks.SelectedNode,$form.cboStatus.Text,$form.txtLimit.Text,$form.txtAlertDayCount.Text,$form.cboColorLabel.Text);
$form.SaveFile($form.tvTasks.SelectedNode.Tag);
}
$this.cboStatus.add_Leave($cboStatus_Leave);
# 履歴表示
$chkShowHistory_CheckedChange={
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
$form.dgv.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
foreach($dgvRow in $form.dgv.Rows){
if ($dgvRow.Cells[$form.DGV_COLNAME_KBN].Value -eq $form.PATTERN_CHANGELOG) {$dgvRow.Visible=$form.chkShowHistory.Checked;}
}
}
$this.chkShowHistory.add_CheckedChanged($chkShowHistory_CheckedChange);
# 履歴一覧
$dgv_CurrentCellChanged = {
$sender = $args[0];
$e = $args[1];
$form =$sender.FindForm();
if ( $form.dgv -eq $null) { return;}
if ( $form.dgv.CurrentRow -eq $null) { return;}
$form.txtHistoryContents.Text = $form.dgv.CurrentRow.Cells[$form.DGV_COLNAME_CONTENTS].Value;
}
$this.dgv.add_CurrentCellChanged($dgv_CurrentCellChanged);
# ■TreeView関連
# 選択変更前に画面上の内容を保存する
$TreeView_BeforeSelect ={
$sender = $args[0];
$e = $args[1];
$CurrentSelectedNode = $sender.SelectedNode;
if ($CurrentSelectedNode -ne $null){
$thisForm = $sender.FindForm();
$thisForm.SaveFile($CurrentSelectedNode.Tag);
$CurrentSelectedNode.Text = $thisForm.GetTaskTitle($CurrentSelectedNode.Tag);
}
};
$this.tvTasks.add_BeforeSelect($TreeView_BeforeSelect);
# 選択された内容を画面上に表示する
$TreeView_AfterSelect={
$sender = $args[0];
$e = $args[1];
$sender.FindForm().SetDataFromFile($e.Node.Tag)
};
$this.tvTasks.add_AfterSelect($TreeView_AfterSelect);
# TreeViewのDragDrop処理
$TreeView_ItemDrag = {
$sender = $args[0];
$e = $args[1];
[TreeView]$tv = $sender;
$tv.SelectedNode = $e.Item;
$tv.Focus();
# ノードのドラッグを開始する
$dde = $tv.DoDragDrop($e.Item , [System.Windows.Forms.DragDropEffects]::All);
};
$TreeView_DragOver = {
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
#ドラッグされているデータがTreeNodeか調べる
if ($e.Data.GetDataPresent([TreeNode])){
$e.Effect = [DragDropEffects]::Move;
} else {
# TreeNodeでなければ受け入れない
$e.Effect = [DragDropEffects]::None;
}
# マウス下のNodeを選択する
if ($e.Effect -ne [DragDropEffects]::None)
{
[TreeView] $tv = $sender;
# マウスのあるNodeを取得する
[TreeNode] $target = $tv.GetNodeAt($tv.PointToClient([Point]::new($e.X, $e.Y)));
#ドラッグされているNodeを取得する
[TreeNode] $source =$e.Data.GetData([TreeNode]);
#マウス下のNodeがドロップ先として適切か調べる
if (($target -ne $Null) -And ($target -ne $source) -And ($form.IsChildNode($source, $target) -ne $True))
{
if ( $target.IsSelected -eq $false) {
$tv.SelectedNode = $target;
}
}
else {
$e.Effect = [DragDropEffects]::None;
}
}
};
$TreeView_DragDrop = {
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
if ($e.Data.GetDataPresent([TreeNode])){
$e.Effect = [DragDropEffects]::Move;
[TreeView] $tv = $sender;
# ドロップされたデータ(TreeNode)を取得
[TreeNode] $source = $e.Data.GetData([TreeNode]);
# ドロップ先のTreeNodeを取得する
[TreeNode] $target = $tv.GetNodeAt($tv.PointToClient([Point]::new($e.X, $e.Y)));
# マウス下のNodeがドロップ先として適切か調べる
if (($target -ne $Null) -And ($target -ne $source) -And ($form.IsChildNode($source, $target) -ne $True))
{
$dicInfoSource = New-Object System.IO.DirectoryInfo($source.Tag);
$dicInfoTarget = New-Object System.IO.DirectoryInfo($target.Tag);
$strChangeLog = "";
$strChangeLog += $form.GetTaskTitle($dicInfoSource.Parent.FullName) + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $form.GetTaskTitle($dicInfoTarget.FullName) + "`r`n";
$tv.SelectedNode = $source;
$form.OpenFile($dicInfoSource.Tag)
$strPathFrom = $dicInfoSource.FullName;
$strPathTo = $dicInfoTarget.FullName;
$strId_To = $form.GetIdFromPath($strPathTo);
# フォルダを移動
Move-Item $strPathFrom $strPathTo
# 移動した履歴を登録する
$form._AddHistory("フォルダ移動" + "`r`n" + $strChangeLog,$false);
# TreeViewを再構築
$form.RefreshTreeViewNodes();
$target = $form.fdicNodesById[$strId_To];
$target.Expand();
# 追加されたNodeを選択
$tv.SelectedNode = $target;
} else {$e.Effect = [DragDropEffects]::None;}
} else {
# TreeNodeでなければ受け入れない
$e.Effect = [DragDropEffects]::None;
}
}
$this.tvTasks.add_ItemDrag($TreeView_ItemDrag);
$this.tvTasks.add_DragOver($TreeView_DragOver);
$this.tvTasks.add_DragDrop($TreeView_DragDrop);
# コメント追加ボタン
$btnAddComment_Click = {
$sender = $args[0];
$e = $args[1];
$form = $sender.FindForm();
$form._AddHistory($form.txtComments.Text,$False);
}
$this.btnAddComment.add_Click($btnAddComment_Click);
# 画面上のキー押下処理
$this.KeyPreview=$True;
$KeyDownEvent={
$sender = $args[0];
$e = $args[1];
$this.RunFunctionKeyDownEvents($sender,$e);
}
$this.add_KeyDown($KeyDownEvent);
# DataGridViewを設定
$this.DataGridViewInit();
# レイアウトを再開
$this.ResumeLayout();
}
# ------------------------------------------------------------------------------------------------------------
# Function Key 押下時イベント
# ------------------------------------------------------------------------------------------------------------
RunFunctionKeyDownEvents([object] $sender, [KeyEventArgs] $e){
$PushKeyCode= $e.KeyCode;
$selectedTask = $this.tvTasks.SelectedNode;
if (( $e.Control -eq $true) -And ( $e.KeyCode -eq ([System.Windows.Forms.Keys]::S)) ) {
# 上書き保存し、Treeを再描画
$this.SaveFile($selectedTask.Tag);
$this.RefreshTreeViewNodes();
}
If ( $PushKeyCode -eq "F1" ) {
#[System.Windows.Forms.MessageBox]::Show("押されたキーは:${PushKeyCode}です", "結果")
# 下のレベルにタスクを追加
if ($selectedTask -eq $null){ $this.AddTaskNode($this.GetDataFolderPath(), $false);}
else {$this.AddTaskNode($selectedTask.Tag, $false);}
} ElseIf ($PushKeyCode -eq "F2" ){
# 同じレベルにタスクを追加
if ($selectedTask -eq $null){ $this.AddTaskNode($this.GetDataFolderPath(), $false);}
else {$this.AddTaskNode($selectedTask.Tag, $true);}
} ElseIf ($PushKeyCode -eq "F3" ){
# タスクを上へ移動
if ($selectedTask -ne $null){ $this.MoveTask($selectedTask, $true);}
} ElseIf ($PushKeyCode -eq "F4" ){
# タスクを下へ移動
if ($selectedTask -ne $null){ $this.MoveTask($selectedTask, $false);}
} ElseIf ($PushKeyCode -eq "F5" ){
# 再描画
$this.RefreshTreeViewNodes();
} ElseIf ($PushKeyCode -eq "F6" ){
#$this.btnF06.PerformClick();
} ElseIf ($PushKeyCode -eq "F7" ){
#$this.btnF07.PerformClick();
} ElseIf ($PushKeyCode -eq "F8" ){
#$this.btnF08.PerformClick();
} ElseIf ($PushKeyCode -eq "F9" ){
#$this.btnF09.PerformClick();
} ElseIf ($PushKeyCode -eq "F10" ){
# [System.Windows.Forms.MessageBox]::Show("押されたキーは:${PushKeyCode}です", "結果")
#$this.btnF10.PerformClick();
} ElseIf ($PushKeyCode -eq "F11" ){
#$this.btnF11.PerformClick();
} ElseIf ($PushKeyCode -eq "F12" ){
#$this.btnF12.PerformClick();
}
}
# ------------------------------------------------------------------------------------------------------------
# 渡された日付をyyyy/MM/dd形式に変換する
# 変換できない場合は空白を返す
# https://teratail.com/questions/118618
# ------------------------------------------------------------------------------------------------------------
[string]GetDateTryConvertFromString([string]$userInputDate){
# 対応する入力パターン
[string[]]$dateFormats = @(
'yyyy/MM/dd'
'yyyy/m/d'
'yy/m/d'
'yyyyMMdd'
)
# 適当な値で初期化
[datetime]$parsedDate = [datetime]::MinValue
# 変換して $parsedDate へ。失敗したら $parseSuccess が $false。
[bool]$parseSuccess = [datetime]::TryParseExact(
$userInputDate,
$dateFormats,
[Globalization.DateTimeFormatInfo]::CurrentInfo,
[Globalization.DateTimeStyles]::AllowWhiteSpaces,
[ref]$parsedDate
)
if ($parseSuccess) {
#Write-Host ('Parse success. input = {0}' -f $userInputDate)
return $parsedDate.ToShortDateString();
} else {
#Write-Host ('Parse fail. input = {0}' -f $userInputDate)
return "";
}
return "";
}
# ------------------------------------------------------------------------------------------------------------
# カラーコンボボックスの色に応じてラベルの色を変更する
# ------------------------------------------------------------------------------------------------------------
SetStickyNoteColor([ComboBox]$cbo){
$form = $cbo.FindForm();
$form.lblStickyNote.BackColor = $form._GetColor($cbo.Text);
$selectedNode = $form.tvTasks.SelectedNode;
if($selectedNode -ne $null) {$selectedNode.BackColor =$form.lblStickyNote.BackColor; }
}
# ------------------------------------------------------------------------------------------------------------
# 区分に応じて色のColorインスタンスを取得する
# ------------------------------------------------------------------------------------------------------------
[Color]_GetColor([string]$strColor) {
if ($strColor -eq $this.LABELCOLOR_RED) {
return [System.Drawing.Color]::FromArgb(248, 91, 89);
} elseif ($strColor -eq $this.LABELCOLOR_PINK) {
return [System.Drawing.Color]::FromArgb(255 ,189 , 255);
} elseif ($strColor -eq $this.LABELCOLOR_PURPLE) {
return [System.Drawing.Color]::FromArgb(198,133,255);
} elseif ($strColor -eq $this.LABELCOLOR_ORANGE) {
return [System.Drawing.Color]::FromArgb(255,176,104);
} elseif ($strColor -eq $this.LABELCOLOR_YELLOW) {
return [System.Drawing.Color]::FromArgb(248, 255, 89);;
} elseif ($strColor -eq $this.LABELCOLOR_LIGHTBLUE) {
return [System.Drawing.Color]::FromArgb(32,241,234);
} elseif ($strColor -eq $this.LABELCOLOR_BLUE) {
return [System.Drawing.Color]::FromArgb(124, 124, 255);;
} elseif ($strColor -eq $this.LABELCOLOR_GREEN) {
return [System.Drawing.Color]::FromArgb(167, 255, 156);
}
return [System.Drawing.Color]::FromArgb(255, 255, 255);
}
# ------------------------------------------------------------------------------------------------------------
# Nodeの内容をフォーム変数に格納しておく
# 連想配列に格納しておくことで、参照型であるClassを名前ですぐにインスタンスを取得し、高速にアクセスできる
# ------------------------------------------------------------------------------------------------------------
SetSystemKeyValues([string] $strFullPath,[TreeNode]$tnTgtNode){
$this.fdicNodes.Add($strFullPath,$tnTgtNode);
$this.fdicNodesById.Add($strFullPath.Substring($strFullPath.length- 17,17),$tnTgtNode);
}
# ------------------------------------------------------------------------------------------------------------
# パスからタスクのIDを取得する(yyyyMMddHHmmssがID)
# ------------------------------------------------------------------------------------------------------------
[string] GetIdFromPath([string]$strFolderPath){
return $strFolderPath.Substring($strFolderPath.Length - 17,17);
}
# ------------------------------------------------------------------------------------------------------------
# あるTreeNodeが別のTreeNodeの子ノードか調べる
# 引数1:親ノードか調べるTreeNode
# 引数2:子ノードか調べるTreeNode
# 戻り値:子ノードの時はTrue
# ------------------------------------------------------------------------------------------------------------
[bool] IsChildNode([TreeNode] $parentNode, [TreeNode] $childNode)
{
if ($childNode.Parent -eq $parentNode) {
return $true;
} elseif ($childNode.Parent -ne $Null) {
return $this.IsChildNode($parentNode, $childNode.Parent);
} else {
return $false;
}
}
# ------------------------------------------------------------------------------------------------------------
# DataGridViewの初期設定を実施
# ------------------------------------------------------------------------------------------------------------
DataGridViewInit(){
$this.dgv.Columns.Clear();
$dc = $this.GetDataGridColumnText($this.DGV_COLNAME_TRKDATETIME,"登録日時",120,$this.DGV_ALIGN_MIDDLECENTER,$this.COLNAME_HISTORY_CREATEIONDATETIME);
$this.dgv.Columns.Add($dc)
$dc = $this.GetDataGridColumnText($this.DGV_COLNAME_KBN,"区分",50,$this.DGV_ALIGN_MIDDLECENTER,$this.COLNAME_HISTORY_PATTERN);
$this.dgv.Columns.Add($dc)
$dc = $this.GetDataGridColumnText($this.DGV_COLNAME_CONTROL,"コントロール",70,$this.DGV_ALIGN_MIDDLECENTER,$this.COLNAME_HISTORY_CONTROL);
$this.dgv.Columns.Add($dc)
$dc = $this.GetDataGridColumnText($this.DGV_COLNAME_HOSTNAME,"PC名",80,$this.DGV_ALIGN_MIDDLECENTER,$this.COLNAME_HISTORY_USERNAME);
$this.dgv.Columns.Add($dc)
$dc = $this.GetDataGridColumnText($this.DGV_COLNAME_CONTENTS,"内容",280,$this.DGV_ALIGN_MIDDLELEFT,$this.COLNAME_HISTORY_HISTORYCONTENTS);
$this.dgv.Columns.Add($dc)
# $dt = New-Object System.Data.DataTable;
# $dt.Columns.Add("strInsDateTime",[string])
# $dt.Columns.Add("strKbn",[string])
# $dt.Columns.Add("strHostName",[string])
# $dt.Columns.Add("strContents",[string])
# $dr = $dt.NewRow();
# $dr["strInsDateTime"] ="2023/12/16 12:10:05";
# $dr["strKbn"] ="自動";
# $dr["strHostName"] = (Get-ChildItem Env:\USERNAME).Value;
# $dr["strContents"] ="データ更新" ;
# $dt.Rows.Add($dr);
$this.dgv.DataSource = $null;
}
# ------------------------------------------------------------------------------------------------------------
# DataGridViewのColumnを取得する
# ------------------------------------------------------------------------------------------------------------
[DataGridViewTextBoxColumn]GetDataGridColumnText([string] $strName,[string]$strHeaderText,[int]$intWidth,[string]$strCellTextAligment,[string]$strDataPropName) {
$dc = New-Object DataGridViewTextBoxColumn ;
$dc.Name = $strName;
$dc.HeaderText = $strHeaderText;
$dc.Width = $intWidth;
$dc.DefaultCellStyle.Alignment = $strCellTextAligment;
$dc.HeaderCell.Style.Alignment = "MiddleCenter";
$dc.ReadOnly=$True;
$dc.AutoSizeMode = "NotSet" # 処理速度向上
$dc.SortMode = "NotSortable"; # 並び替えを行わないようにすることでヘッダのテキストを中央寄せにできる
$dc.DataPropertyName = $strDataPropName;
return $dc;
}
# ------------------------------------------------------------------------------------------------------------
# Menuコントロール設定処理
# ------------------------------------------------------------------------------------------------------------
MenuControlInit(){
$this.menuFormMain.SuspendLayout()
#「ファイル(&F)」メニュー項目を作成する
$fileMenuItem = New-Object ToolStripMenuItem;
$fileMenuItem.Text = "ファイル(&F)";
$this.menuFormMain.Items.Add($fileMenuItem);
#「上書き保存(&S)」メニュー項目を作成する
$saveMenuItem = New-Object ToolStripMenuItem;
$saveMenuItem.Text = "上書き保存(&S)";
$fileMenuItem.DropDownItems.Add($saveMenuItem);
# セパレータ
$sepa = New-Object ToolStripSeparator;
$fileMenuItem.DropDownItems.Add($sepa);
#「終了(&X)」メニュー項目を作成する
$closeMenuItem = New-Object ToolStripMenuItem;
$closeMenuItem.Text = "終了(&X)";
$fileMenuItem.DropDownItems.Add($closeMenuItem);
#「ファイル(&F)」メニュー項目を作成する
$operateMenuItem = New-Object ToolStripMenuItem;
$operateMenuItem.Text = "操作(&E)";
$this.menuFormMain.Items.Add($operateMenuItem);
#「再描画(&R)」メニュー項目を作成する
$refreshMenuItem = New-Object ToolStripMenuItem;
$refreshMenuItem.Text = "再描画(&R)";
$refreshMenuItem_Click_RefreshTreeView={
$sender = $args[0];
$e = $args[1];
$form = $sender.OwnerItem.Owner.FindForm();
$form.RefreshTreeViewNodes();
}
$refreshMenuItem.add_Click($refreshMenuItem_Click_RefreshTreeView);
$operateMenuItem.DropDownItems.Add($refreshMenuItem);
# セパレータ
$sepa = New-Object ToolStripSeparator;
$operateMenuItem.DropDownItems.Add($sepa);
#「下のレベルに追加(&A)」メニュー項目を作成する
$addMenuItem = New-Object ToolStripMenuItem;
$addMenuItem.Text = "下のレベルに追加(F1)(&A)";
$addMenuItem_Click_AddNode_Under={
$sender = $args[0];
$e = $args[1];
$form = $sender.OwnerItem.Owner.FindForm();
$selectedTask = $form.tvTasks.SelectedNode;
if ($selectedTask -eq $null){ $form.AddTaskNode($form.GetDataFolderPath(), $false);}
else {$form.AddTaskNode($selectedTask.Tag, $false);}
$form.ClearInit();
}
$addMenuItem.add_Click($addMenuItem_Click_AddNode_Under);
$operateMenuItem.DropDownItems.Add($addMenuItem);
#「同じレベルに追加(&M)」メニュー項目を作成する
$addSameMenuItem = New-Object ToolStripMenuItem;
$addSameMenuItem.Text = "同じレベルに追加(F2)(&M)";
$addSameMenuItem_Click_AddNode_Same={
$sender = $args[0];
$e = $args[1];
$form = $sender.OwnerItem.Owner.FindForm();
$selectedTask = $form.tvTasks.SelectedNode;
if ($selectedTask -eq $null){
# Nodeが一つもない場合は必ず下のレベルに追加にする
$form.AddTaskNode($form.GetDataFolderPath(), $false);
}
else {$form.AddTaskNode($selectedTask.Tag, $true);}
$form.ClearInit();
}
$addSameMenuItem.add_Click($addSameMenuItem_Click_AddNode_Same);
$operateMenuItem.DropDownItems.Add($addSameMenuItem);
#「削除(&D)」メニュー項目を作成する
$deleteMenuItem = New-Object ToolStripMenuItem;
$deleteMenuItem.Text = "削除(&D)";
$operateMenuItem.DropDownItems.Add($deleteMenuItem);
# セパレータ
$sepa = New-Object ToolStripSeparator;
$operateMenuItem.DropDownItems.Add($sepa);
#「上へ(&U)」メニュー項目を作成する
$upMenuItem = New-Object ToolStripMenuItem;
$upMenuItem.Text = "タスクを上へ(F3)(&U)";
$upMenuItem_Click_MoveUp={
$sender = $args[0];
$e = $args[1];
$form = $sender.OwnerItem.Owner.FindForm();
$selectedTask = $form.tvTasks.SelectedNode;
if ($selectedTask -eq $null){
#[System.Windows.Forms.MessageBox]::Show("未選択です", "結果")
return;
}
else {
$form.MoveTask($selectedTask,$True);
}
#$form.ClearInit();
}
$upMenuItem.add_Click($upMenuItem_Click_MoveUp);
$operateMenuItem.DropDownItems.Add($upMenuItem);
#「下へ(&U)」メニュー項目を作成する
$downMenuItem = New-Object ToolStripMenuItem;
$downMenuItem.Text = "タスクを下へ(F4)(&D)";
$upMenuItem_Click_MoveDown={
$sender = $args[0];
$e = $args[1];
$form = $sender.OwnerItem.Owner.FindForm();
$selectedTask = $form.tvTasks.SelectedNode;
if ($selectedTask -eq $null){
#[System.Windows.Forms.MessageBox]::Show("未選択です", "結果")
return;
}
else {
$form.MoveTask($selectedTask,$False);
}
#$form.ClearInit();
}
$downMenuItem.add_Click($upMenuItem_Click_MoveDown);
$operateMenuItem.DropDownItems.Add($downMenuItem);
# フォームにMenuStripを追加する
$this.Controls.Add($this.menuFormMain);
# フォームのメインメニューとする
$this.MainMenuStrip = $this.menuFormMain;
# レイアウトロジックを再開する
$this.menuFormMain.ResumeLayout($false);
$this.menuFormMain.PerformLayout();
}
# ------------------------------------------------------------------------------------------------------------
# 選択されているNodeの下の階層にフォルダを追加したうえで、TreeViewのNodeに追加する
# ------------------------------------------------------------------------------------------------------------
RefreshTreeViewNodes() {
# 展開状態を覚えておく
$strSelectedNode = "";
$selectedNode = $this.tvTasks.SelectedNode;
if ($selectedNode -ne $null) {$strSelectedNode = $selectedNode.Tag.Substring($selectedNode.Tag.length-17,17)};
$lstExpandNodes = New-Object 'System.Collections.Generic.List[string]';
foreach ($key in $this.fdicNodes.Keys) {
[TreeNode] $node = $this.fdicNodes[$key];
if ($node.IsExpanded -eq $true) {
$lstExpandNodes.Add($key.Substring($key.length-17,17));
}
}
# クリア処理
$this.SuspendLayout();
$this.tvTasks.SuspendLayout();
$this.tvTasks.Nodes.Clear();
$this.fdicNodes.Clear();
$this.fdicNodesById.Clear();
# フォルダパスをすべて取得し、並び替えを行う
$directrys = [System.IO.Directory]::GetDirectories($this.GetDataFolderPath(), "*", [System.IO.SearchOption]::AllDirectories);
$directrys = $directrys | Sort-Object
$parentNode = New-Object TreeNode;
foreach ($path in $directrys){
$dicInfo = New-Object System.IO.DirectoryInfo($path);
$dicParentInfo = New-Object System.IO.DirectoryInfo($dicInfo.Parent.FullName);
$node = New-Object TreeNode;
# TreeNodeの値やフォントを設定する
[System.Data.DataRow]$dr = $this.GetTaskDataRow($dicInfo.FullName)
# タイトル
if ($dr[$this.COLNAME_CONTENTS_TITLE] -eq "") { $node.Text= "[No Title]";}
else { $node.Text= $dr[$this.COLNAME_CONTENTS_TITLE]; }
# 進捗状態に合わせてフォントを変更
# 背景などのフォントスタイル設定のテスト
$this._SetTreeNodeStyle($node,$dr[$this.COLNAME_CONTENTS_STATUS],$dr[$this.COLNAME_CONTENTS_LIMITDAY],$dr[$this.COLNAME_CONTENTS_LIMITALERTDAYCOUNT],$dr[$this.COLNAME_CONTENTS_COLORLABEL])
# Nodeのタグ値にキーとなるパスを設定する
$node.Tag = $path;
# フォーム変数に覚えている全Nodeリストに追加する(忘れないようにすること)
$this.SetSystemKeyValues($path.ToString(),$node);
# タスクを追加する
if ($dicParentInfo.FullName -eq $this.GetDataFolderPath() ){
$this.tvTasks.Nodes.Add($node);
} else {
# 既に追加されているものから探してくる
$parentNode = $this.fdicNodes[$dicParentInfo.FullName];
$parentNode.Nodes.Add($node);
}
}
# 事前に保存している内容で設定する(展開状況と選択ノードを元に戻す)
foreach ($strId in $lstExpandNodes) {
[TreeNode] $node = $this.fdicNodesById[$strId];
$node.Expand();
}
if ($strSelectedNode -ne "")
{
$this.tvTasks.SelectedNode = $this.fdicNodesById[$strSelectedNode];
};
# 描画を開始
$this.tvTasks.ResumeLayout();
$this.ResumeLayout();
}
# ------------------------------------------------------------------------------------------------------------
# Nodeのスタイルを設定する
# ------------------------------------------------------------------------------------------------------------
_SetTreeNodeStyle([TreeNode]$node,[string] $strStatus,[string] $strLimitDay,[string] $strAlertDayCount,[string] $strColorPattern) {
# 初期化
$node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Regular) ;
$node.ForeColor = "Black";
# 状態によってフォントを変更する
if ($strStatus -eq $this.STATUS_DONE) {
$node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Strikeout) ;
} elseif ($strStatus -eq $this.STATUS_DOING) {
$node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Italic) ;
$node.ForeColor = "Blue";
}
$strLimitDay = $this.GetDateTryConvertFromString($strLimitDay);
if (($strLimitDay -ne "") -And ($strStatus -ne $this.STATUS_DONE)) {
[datetime]$parsedDate = [datetime]::Parse($strLimitDay);
$intConvertCount = 0;
if ([double]::TryParse($strAlertDayCount,[ref]$intConvertCount) -eq $true){
$parsedDate.AddDays($intConvertCount);
}
[datetime]$now = [datetime]::Now;
if ($parsedDate.ToShortDateString() -le $now.ToShortDateString()) {
$node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Bold) ;
$node.ForeColor = "Red";
}
}
# ノードの背景色を設定
if($strColorPattern -ne "") {$node.BackColor = $this._GetColor($strColorPattern); }
}
# ------------------------------------------------------------------------------------------------------------
# 履歴を追加する
# ------------------------------------------------------------------------------------------------------------
_AddHistory([string]$strContents,[bool]$blnAutoHistory) {
if ($this.fdsCurrentData -eq $null) {return;}
if ($this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_CONTENT] -eq $null) {return;}
if ($blnAutoHistory -eq $True) {
[string]$strChangeLog = "";
$dt = $this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_CONTENT];
# タイトル
if ($this.txtTitle.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_TITLE]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_TITLE] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtTitle.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"タイトル",$strChangeLog);
};
# 期限
if ($this.txtLimit.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_LIMITDAY]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_LIMITDAY] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtLimit.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"期限",$strChangeLog);
};
# 期限前通知
if ($this.txtAlertDayCount.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_LIMITALERTDAYCOUNT]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_LIMITALERTDAYCOUNT] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtAlertDayCount.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"期限前通知",$strChangeLog);
};
# 進捗状況
if ($this.cboStatus.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_STATUS]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_STATUS] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.cboStatus.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"進捗状況",$strChangeLog);
};
# カラーラベル
if ($this.cboColorLabel.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_COLORLABEL]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_COLORLABEL] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.cboColorLabel.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"進捗状況",$strChangeLog);
};
# カラーラベル
if ($this.txtMember.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_MEMBER]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_MEMBER] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtMember.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"担当",$strChangeLog);
};
# 分類
if ($this.txtClass.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_CLASS]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_CLASS] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtClass.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"分類",$strChangeLog);
};
# 内容
if ($this.txtContents.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_CONTENTS]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_CONTENTS] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtContents.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"内容",$strChangeLog);
};
# 備考
if ($this.txtNote.Text -ne $dt.Rows[0][$this.COLNAME_CONTENTS_NOTE]){
$strChangeLog = "";
$strChangeLog += $dt.Rows[0][$this.COLNAME_CONTENTS_NOTE] + "`r`n";
$strChangeLog += "↓↓↓↓↓↓`r`n";
$strChangeLog += $this.txtNote.Text + "`r`n";
$this._AddRow_Hisotory($this.PATTERN_CHANGELOG,"分類",$strChangeLog);
};
} else {
if ($strContents -ne "") {
$this._AddRow_Hisotory($this.PATTERN_COMMENT,"コメント",$this.txtComments.Text);
} else {
$this._AddRow_Hisotory($this.PATTERN_AUTO,"",$strContents);
}
}
}
# ------------------------------------------------------------------------------------------------------------
# 履歴一覧に値を追加する
# ------------------------------------------------------------------------------------------------------------
_AddRow_Hisotory([string]$strPattern,[string]$strControl,[string]$strHistoryContents){
$dr = $this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_HISTORY].NewRow();
$dr[$this.COLNAME_HISTORY_PATTERN] = $strPattern;
$dr[$this.COLNAME_HISTORY_CONTROL] = $strControl;
$dr[$this.COLNAME_HISTORY_CREATEIONDATETIME] = Get-Date -Format "yyyy/MM/dd HH:mm:ss";
$dr[$this.COLNAME_HISTORY_USERNAME] = (Get-ChildItem Env:\USERNAME).Value;
$dr[$this.COLNAME_HISTORY_HISTORYCONTENTS] = $strHistoryContents;
$this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_HISTORY].Rows.Add($dr);
}
# ------------------------------------------------------------------------------------------------------------
# 選択されているNodeの下の階層にフォルダを追加したうえで、TreeViewのNodeに追加する
# RefreshTreeViewNodesを使うとTreeViewのNodeがすべて再構築されるので、選択状態が消える
# 毎回最新を取得して選択状態を取得したほうが安全か・・・?
# ------------------------------------------------------------------------------------------------------------
AddTaskNode([string] $strFolderPath,[bool] $blnSameLevel) {
$strNow = Get-Date -Format "yyyyMMddhhmmssfff";
$dicInfo = New-Object System.IO.DirectoryInfo($strFolderPath);
if ($blnSameLevel -eq $true) {
$dicInfo = $dicInfo.Parent;
}
$strFolderNo = "0000" + ($dicInfo.GetDirectories().Count + 1) ;
$strFolderNo = $strFolderNo.Substring($strFolderNo.Length - 4 ,4);
$strNewFolderPath = $dicInfo.FullName + "\" + $strFolderNo + "_" + $strNow ;
New-Item $strNewFolderPath -ItemType Directory;
# Nodeを追加する
$dicInfo = New-Object System.IO.DirectoryInfo($strNewFolderPath);
$node = New-Object TreeNode;
#$node.Text= $this.GetTaskTitle($dicInfo.FullName);
$node.Tag = $dicInfo.FullName;
# 全Nodeリストに追加する(忘れないようにすること)
$this.SetSystemKeyValues($dicInfo.FullName,$node);
# $this.fdicNodes.Add($dicInfo.FullName,$node);
# $this.fdicNodesById.Add($dicInfo.FullName.Substring($dicInfo.FullName.length-14,14),$node);
# 既に追加されているものから探してくる
if ($dicInfo.Parent.FullName -eq $this.GetDataFolderPath() ){
$this.tvTasks.Nodes.Add($node);
} else {
# 既に追加されているものから探してくる
$parentNode = $this.fdicNodes[$dicInfo.Parent.FullName];
$parentNode.Expand();
$parentNode.Nodes.Add($node);
}
# 画面を初期化する
$this.ClearInit();
# ファイルを保存する
$this.SaveFile($dicInfo.FullName);
# TreeViewのNodeを再構築する
$this.RefreshTreeViewNodes();
# 追加したNodeを選択状態にすることで現在選択されているNodeの内容が保存される
$this.tvTasks.SelectedNode = $this.fdicNodesById[$node.Tag.Substring($node.Tag.Length - 17,17)];
# すぐに入力できるようにフォーカスを設定
$this.txtTitle.Focus();
}
# ------------------------------------------------------------------------------------------------------------
# タスクを移動する
# ------------------------------------------------------------------------------------------------------------
MoveTask([TreeNode]$selectedTask,[bool]$blnMoveUp) {
$tnParent = $selectedTask.Parent;
if ($tnParent -eq $null){return;}
if ($tnParent.Nodes -eq $null){return;}
$index = $tnParent.Nodes.IndexOf($selectedTask);
$insertIdx = 0;
if ($blnMoveUp) {
$insertIdx = $index - 1;
if ($insertIdx -lt 0 ) {
[System.Windows.Forms.MessageBox]::Show("これ以上上に行けません", "エラー");
return;
}
} else {
$insertIdx = $index + 1;
if ($insertIdx -gt $tnParent.Nodes.Count - 1 )
{
[System.Windows.Forms.MessageBox]::Show("これ以上下に行けません", "エラー");
return;
}
}
$selectedTask.Remove();
$tnParent.Nodes.Insert($insertIdx, $selectedTask);
$this.tvTasks.SelectedNode = $selectedTask;
for ($i = 0; $i -lt $tnParent.Nodes.Count; $i++) {
$dicInfo = New-Object System.IO.DirectoryInfo($tnParent.Nodes[$i].Tag);
$strNo = ("0000" + ( $i + 1 ));
$strNo = $strNo.Substring($strNo.Length - 4 , 4 );
$strNewFolderName = $strNo + "_" + $dicInfo.Name.Substring($dicInfo.Name.Length - 17 , 17);
# フォルダをリネーム(番号が変わる場合のみ)
if ($dicInfo.Name -ne $strNewFolderName) {
Rename-Item $dicInfo.FullName $strNewFolderName
}
}
# TreeViewを再構築する
$this.RefreshTreeViewNodes()
}
# ------------------------------------------------------------------------------------------------------------
# ファイルを開いてタスクのタイトルを取得する
# ------------------------------------------------------------------------------------------------------------
[string]GetTaskTitle([string]$strDicPath) {
if ($this.OpenFile($strDicPath) -eq $true ){
$dt = $this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_CONTENT];
if ($dt.Rows[0][$this.COLNAME_CONTENTS_TITLE] -eq "") { return "[No Title]" } # Titleが空白の場合にTreeView上で選択できなくなるため
else {return $dt.Rows[0][$this.COLNAME_CONTENTS_TITLE];}
} else {
return "[Not Exists Task.xml]" + $strDicPath;
}
}
# ------------------------------------------------------------------------------------------------------------
# ファイルを開いてタスクのデータを返す
# ------------------------------------------------------------------------------------------------------------
[System.Data.DataRow]GetTaskDataRow([string]$strDicPath) {
if ($this.OpenFile($strDicPath) -eq $true ){
$dt = $this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_CONTENT];
return $dt.Rows[0];
} else {
return $null;
}
}
# ------------------------------------------------------------------------------------------------------------
# ファイルを開いて画面に値を設定する
# ------------------------------------------------------------------------------------------------------------
SetDataFromFile([string]$strDicPath){
$this.ClearInit();
if ($this.OpenFile($strDicPath) -eq $true ){
$dt = $this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_CONTENT];
$this.txtTitle.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_TITLE];
$this.txtLimit.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_LIMITDAY];
$this.txtAlertDayCount.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_LIMITALERTDAYCOUNT];
$this.cboStatus.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_STATUS];
$this.cboColorLabel.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_COLORLABEL];
$this.lblStickyNote.BackColor = $this._GetColor($this.cboColorLabel.Text);
$this.txtMember.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_MEMBER];
$this.txtClass.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_CLASS];
$this.txtCreateDateTime.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_CREATEIONDATETIME];
$this.txtContents.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_CONTENTS];
$this.txtNote.Text = $dt.Rows[0][$this.COLNAME_CONTENTS_NOTE];
}
}
# ------------------------------------------------------------------------------------------------------------
# 画面上の値をクリアする
# ------------------------------------------------------------------------------------------------------------
ClearInit(){
$this.txtTitle.Text = "";
$this.txtLimit.Text = "";
$this.txtAlertDayCount.Text = "3";
$this.cboStatus.Text = "作業前";
$this.cboColorLabel.Text = "";
$this.txtMember.Text = "";
$this.txtClass.Text = "";
$this.txtCreateDateTime.Text = "";
$this.txtContents.Text = "";
$this.txtNote.Text = "";
$this.DataGridViewInit();
}
# ------------------------------------------------------------------------------------------------------------
# ファイルの内容を開く
# ------------------------------------------------------------------------------------------------------------
[bool]OpenFile([string]$strDicPath) {
$strFilePath = $strDicPath + "\" + $this.DATA_FILE_NAME;
if ((Test-Path $strFilePath) -eq $true) {
$ds = New-Object System.Data.DataSet;
$ds.ReadXml($strFilePath);
$this.fdsCurrentData = $ds;
if ($this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_HISTORY] -eq $null) {return $false;}
$this.dgv.DataSource = $this.fdsCurrentData.Tables[$this.DATA_TABLE_NAME_HISTORY];
$this.dgv.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
foreach($dgvRow in $this.dgv.Rows){
if ($dgvRow.Cells[$this.DGV_COLNAME_KBN].Value -eq $this.PATTERN_CHANGELOG) {$dgvRow.Visible=$this.chkShowHistory.Checked;}
if ($dgvRow.Cells[$this.DGV_COLNAME_KBN].Value -eq $this.PATTERN_COMMENT)
{
foreach ($cell in $dgvRow.Cells){
$cell.Style.ForeColor = "Blue";
}
}
}
return $true;
} else {
return $false;
}
}
# ------------------------------------------------------------------------------------------------------------
# 画面上の値をファイルに保存する
# ------------------------------------------------------------------------------------------------------------
SaveFile([string]$strDicPath) {
$dicInfo = New-Object System.IO.DirectoryInfo($strDicPath);
# 変更履歴を追加
$this._AddHistory("",$true);
$ds = New-Object System.Data.DataSet;
$ds.DataSetName = "TaskDate";
# コンテンツテーブル作成
$dtContents = New-Object System.Data.DataTable;
$dtContents.TableName = $this.DATA_TABLE_NAME_CONTENT;
$dtContents.Columns.Add($this.COLNAME_CONTENTS_TITLE,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_LIMITDAY,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_LIMITALERTDAYCOUNT,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_STATUS,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_COLORLABEL,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_MEMBER,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_CLASS,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_CREATEIONDATETIME,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_CONTENTS,[string]);
$dtContents.Columns.Add($this.COLNAME_CONTENTS_NOTE,[string]);
# データを登録
$strDateTime = $strDicPath.Substring($strDicPath.Length - 17,17);
$strDateTime = $strDateTime.Substring(0,4) + "/" + $strDateTime.Substring(4,2) + "/" + $strDateTime.Substring(6,2) + " " + $strDateTime.Substring(8,2) + ":" + $strDateTime.Substring(10,2) + ":" + $strDateTime.Substring(12,2) + ":" + $strDateTime.Substring(14,3)
$dr = $dtContents.NewRow();
$dr[$this.COLNAME_CONTENTS_TITLE]=$this.txtTitle.Text;
$dr[$this.COLNAME_CONTENTS_LIMITDAY]=$this.txtLimit.Text;
$dr[$this.COLNAME_CONTENTS_LIMITALERTDAYCOUNT]=$this.txtAlertDayCount.Text;
$dr[$this.COLNAME_CONTENTS_STATUS]=$this.cboStatus.Text;
$dr[$this.COLNAME_CONTENTS_COLORLABEL]=$this.cboColorLabel.Text;
$dr[$this.COLNAME_CONTENTS_MEMBER]=$this.txtMember.Text;
$dr[$this.COLNAME_CONTENTS_CLASS]=$this.txtClass.Text;
$dr[$this.COLNAME_CONTENTS_CREATEIONDATETIME]=$strDateTime;
$dr[$this.COLNAME_CONTENTS_CONTENTS]=$this.txtContents.Text;
$dr[$this.COLNAME_CONTENTS_NOTE]=$this.txtNote.Text;
$dtContents.Rows.Add($dr);
$ds.Tables.Add($dtContents);
# 履歴テーブル作成
$dtHistorys = New-Object System.Data.DataTable;
$dtHistorys.TableName = $this.DATA_TABLE_NAME_HISTORY;
$dtHistorys.Columns.Add($this.COLNAME_HISTORY_CREATEIONDATETIME,[string]);
$dtHistorys.Columns.Add($this.COLNAME_HISTORY_CONTROL,[string]);
$dtHistorys.Columns.Add($this.COLNAME_HISTORY_PATTERN,[string]);
$dtHistorys.Columns.Add($this.COLNAME_HISTORY_USERNAME,[string]);
$dtHistorys.Columns.Add($this.COLNAME_HISTORY_HISTORYCONTENTS,[string]);
$dt_dgv = $this.dgv.DataSource;
foreach ($dr_dgv in $dt_dgv.Rows) {
$dr = $dtHistorys.NewRow();
$dr[$this.COLNAME_HISTORY_PATTERN]=$dr_dgv[$this.COLNAME_HISTORY_PATTERN];
$dr[$this.COLNAME_HISTORY_CREATEIONDATETIME]=$dr_dgv[$this.COLNAME_HISTORY_CREATEIONDATETIME];
$dr[$this.COLNAME_HISTORY_CONTROL]=$dr_dgv[$this.COLNAME_HISTORY_CONTROL];
$dr[$this.COLNAME_HISTORY_USERNAME]=$dr_dgv[$this.COLNAME_HISTORY_USERNAME];
$dr[$this.COLNAME_HISTORY_HISTORYCONTENTS]=$dr_dgv[$this.COLNAME_HISTORY_HISTORYCONTENTS];
$dtHistorys.Rows.Add($dr);
}
# 新規追加の場合は、新規登録された履歴を登録。履歴が0件だとエラーが発生する
if ($dtHistorys.Rows.Count -eq 0 ) {
$dr = $dtHistorys.NewRow();
$dr[$this.COLNAME_HISTORY_PATTERN]=$this.PATTERN_AUTO;
$dr[$this.COLNAME_HISTORY_CREATEIONDATETIME] = Get-Date -Format "yyyy/MM/dd HH:mm:ss";
$dr[$this.COLNAME_HISTORY_CONTROL]="-";
$dr[$this.COLNAME_HISTORY_USERNAME] = (Get-ChildItem Env:\USERNAME).Value;
$dr[$this.COLNAME_HISTORY_HISTORYCONTENTS]="新規作成";
$dtHistorys.Rows.Add($dr);
}
$ds.Tables.Add($dtHistorys);
$ds.WriteXml($dicInfo.FullName + "\" + $this.DATA_FILE_NAME);
# 保存したファイルを再度開くことでfdsの内容を変更する
$this.OpenFile($dicInfo.FullName)
}
# ------------------------------------------------------------------------------------------------------------
# データを保存しているフォルダを取得する
# ------------------------------------------------------------------------------------------------------------
[string] GetDataFolderPath(){
return ($this.fstrCurrentPath + "\Data");
}
}
# 呼び出し用のMain.ps1は別途作成する必要がある
# Debug用 デバッグする際にはコメントアウトを削除し、VisualStudioCodeなどでF5。事前に「Add-Type -AssemblyName System.Windows.Forms;」「Add-Type -AssemblyName System.Windows.Forms;」の実行が必要
# [Application]::EnableVisualStyles();
# $form = [frm010_000_Projet]::new();
# $form.fstrCurrentPath = $CurrentDir; # インスタンス化してから、スクリプト上で設定しないと、クラスの中ではMyInvocationが取得できない。
# $form.StartPosition="CenterScreen"; # 列挙体は文字列で指定する必要がある
# $form.ShowDialog();