/// <summary> /// DBのタグを更新します /// </summary> /// <param name=""></param> /// <param name=""></param> /// <returns></returns> private bool UpdateTag(IList <int> idList, IList <string> selectedTagList) { //DBのタグを更新します using (var connection = _db.GetConnection()) { //トランザクション開始 var transaction = connection.BeginTransaction(); try { foreach (var id in idList) { //タグを全て削除します TagDataDao.Delete(connection, id); //タグを追加します foreach (var tag in selectedTagList) { TagDataDao.Insert(connection, tag, id); } } //コミット transaction.Commit(); return(true); } catch (Exception ex) { //ロールバック transaction.Rollback(); MsgBoxUtils.ShowErrorMsgBox("更新に失敗しました。\n" + ex.Message); return(false); } } }
/// <summary> /// グリッドの手入力後に発生するイベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void grid_CellEndEdit(object sender, DataGridViewCellEventArgs e) { var id = _grid[0, e.RowIndex].Value.ToString(); //ID var newValue = _grid[e.ColumnIndex, e.RowIndex].Value?.ToString(); //入力値 if (newValue == null) { newValue = ""; } FileData oldFileData; using (var connection = _db.GetConnection()) { oldFileData = FileDataDao.GetData(connection, id); if (oldFileData == null) { MsgBoxUtils.ShowErrorMsgBox("このデータは削除されています。"); return; } //タグを取得します oldFileData._tags = TagDataDao.GetTags(connection, StringUtils.ToInt(id)); } //カラムオブジェクトに値の変更を通知します(カラム側ではファイル名の変更などを行う) var newFileData = ((IFileListColumnForFileInfo)_grid.Columns[e.ColumnIndex]).ValueChanged(oldFileData, newValue); if (newFileData == null) { newFileData = oldFileData; } //行の更新します SetRowData(e.RowIndex, newFileData); }
} //プラグインのタイトルを返します /// <summary> /// プラグインが終了できるかどうか /// </summary> /// <returns>true:終了できる false:終了できない</returns> public bool CanClosePlugin() { if (txtMain.Modified) { //テキストに変更がある場合、保存の確認を行います var result = MsgBoxUtils.ShowMsgBoxToConfirmSaving(); if (result == DialogResult.Yes) { //ファイルを保存します SaveFile(); } if (result == DialogResult.No) { //保存せずに、変更なしの状態にします txtMain.Modified = false; } if (result == DialogResult.Cancel) { //終了できないことを返します return(false); } } return(true); }
/****************************************************************************** * * プラグイン用イベントハンドラー * ******************************************************************************/ /// <summary> /// ファイル情報選択中イベント /// </summary> /// <param name="param"></param> /// <param name="sender"></param> public void PluginEvent_FileInfoSelecting(EventParam param, object sender) { //データが変更されている場合は、確認メッセージを表示します if (_editor.Modified) { var dialogResult = MsgBoxUtils.ShowMsgBoxToConfirmSaving(); if (dialogResult == DialogResult.Yes) { //「はい」の場合、保存します _editor.SaveData(); } if (dialogResult == DialogResult.No) { //「いいえ」の場合、何もせずに処理を続けます } if (dialogResult == DialogResult.Cancel) { //「キャンセル」の場合、処理を抜けます return; } } //ファイル情報を表示します var id = ((FileInfoSelectingEventParam)param).ID; _editor.LoadData(id); }
private void Menu_Load(object sender, EventArgs e) { Am = new AssetsManager(); if (File.Exists("classdata.tpk")) { try { Am.LoadClassPackage("classdata.tpk"); if (Am.classPackage.valid) { return; } MsgBoxUtils.ShowErrorDialog("Invalid classdata.tpk file."); } catch (Exception ex) { MsgBoxUtils.ShowErrorDialog("Can't load classdata.tpk:\n" + ex); } } else { MsgBoxUtils.ShowErrorDialog("Missing classdata.tpk by exe.\n" + "Please make sure it exists."); } Close(); Environment.Exit(1); }
private void AskSaveChanges() { if (!Modified) { return; } var choice = MsgBoxUtils.ShowInfoDialog("Would you like to save the changes?"); switch (choice) { case DialogResult.Yes: { var sfd = new SaveFileDialog { Title = @"Save bundle file", Filter = @"All types (*.*)|*.*|Bundle file (*.unity3d)|*.unity3d" }; if (sfd.ShowDialog() != DialogResult.OK) { return; } SaveBundle(sfd.FileName); break; } case DialogResult.No: CloseAllFiles(); break; } }
private void SaveFiles(bool overwrite = false) { var newAssetsList = Workspace.NewAssets.Values.ToList(); if (FromBundle) { ModifiedFiles = WriteFilesToMemory(newAssetsList); Workspace.Modified = false; ClearModified(); } else { if (overwrite) { var choice = MsgBoxUtils.ShowWarningDialog("This action will overwrite the file.\n" + "Are you sure you want to continue?"); if (choice != DialogResult.Yes) { return; } } WriteFiles(newAssetsList, overwrite); Workspace.Modified = false; ClearModified(); } }
/// <summary> /// DBにタグを追加します /// </summary> /// <param name=""></param> /// <param name=""></param> /// <returns></returns> private bool AddTag(IList <int> idList, IList <string> selectedTagList) { //DBにタグを追加します using (var connection = _db.GetConnection()) { //トランザクション開始 var transaction = connection.BeginTransaction(); try { //選択中のIDのデータに対して、選択されたタグを追加します foreach (var id in idList) { TagDataDao.AddTags(connection, id, selectedTagList); } //コミット transaction.Commit(); return(true); } catch (Exception ex) { //ロールバック transaction.Rollback(); MsgBoxUtils.ShowErrorMsgBox("更新に失敗しました。\n" + ex.Message); return(false); } } }
private void btnLoad_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog { Title = @"Open texture", Filter = @"PNG file (*.png)|*.png|TGA file (*.tga)|*.tga|All types (*.*)|*.*" }; if (ofd.ShowDialog() != DialogResult.OK) { return; } try { using var image = Image.Load <Rgba32>(ofd.FileName); tex.m_Width = image.Width; tex.m_Height = image.Height; image.Mutate(i => i.Flip(FlipMode.Vertical)); imgBytes = image.TryGetSinglePixelSpan(out var pixelSpan) ? MemoryMarshal.AsBytes(pixelSpan).ToArray() : null; if (imgBytes == null) { MsgBoxUtils.ShowErrorDialog(this, "Failed to parse current texture."); } } catch (Exception ex) { MsgBoxUtils.ShowErrorDialog(this, "Something went wrong when importing the texture:\n" + ex); } }
/// <summary> /// グリッドのキーダウンイベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void grid_KeyDown(object sender, KeyEventArgs e) { //CTRL + エンターキーの場合は、ネイティブな方法でファイルを開きます if (e.Control && e.KeyCode == Keys.Enter) { //選択されているセルがある行のパスを取得します var path = GetSelectedPath(); if (path == null) { return; } if (FileUtils.Exists(path) == false) { MsgBoxUtils.ShowErrorMsgBox(path + "が見つかりません。"); return; } //ネイティブな方法でファイルを開きます Process.Start(path); //キー操作を処理済みにします e.Handled = true; return; } //エンターキーが押された場合は、フォルダorファイル選択イベントを発生させます if (e.KeyCode == Keys.Enter) { //選択されているセルがある行のパスを取得します var path = GetSelectedPath(); if (path == null) { return; } //フォルダまたはファイル選択イベントを発生させます RaiseSelectedEvent(path); //キー操作を処理済みにします e.Handled = true; return; } //DELETEキーが押された場合は、管理データを削除します if (e.KeyCode == Keys.Delete) { //現在選択中のIDリストを取得します var idList = GetSelectedIDList(); if (idList.Count == 0) { return; } //管理データを削除します DeleteData(idList); } }
private bool FailIfNothingSelected() { switch (GetSelectedCount()) { case 0: MsgBoxUtils.ShowErrorDialog("No item selected."); return(true); default: return(false); } }
private void btnOK_Click(object sender, EventArgs e) { FileID = cboxFileID.SelectedIndex; if (long.TryParse(boxPathID.Text, out var pathId)) { PathID = pathId; } else { MsgBoxUtils.ShowErrorDialog("Path ID is invalid!"); } }
private void btnOK_Click(object sender, EventArgs e) { if (BundleInst == null) { return; } AssetBundleCompressionType compType; if (rbtnLZ4.Checked) { compType = AssetBundleCompressionType.LZ4; } else if (rbtnLZMA.Checked) { compType = AssetBundleCompressionType.LZMA; } else { MsgBoxUtils.ShowErrorDialog("You didn't choose any compression method!\n" + "Please go back and select it.\n"); DialogResult = DialogResult.None; return; } try { var bw = new BackgroundWorker(); bw.DoWork += delegate { var sfd = new SaveFileDialog { FileName = BundleInst.name + ".packed", Filter = @"All types (*.*)|*.*" }; if (sfd.ShowDialog() != DialogResult.OK) { return; } CompressBundle(BundleInst, sfd.FileName, compType); }; bw.RunWorkerCompleted += delegate { MsgBoxUtils.ShowInfoDialog("The bundle file has been successfully packed!", MessageBoxButtons.OK); Compressed = true; }; bw.RunWorkerAsync(); } catch (Exception ex) { MsgBoxUtils.ShowErrorDialog("Something went wrong when packing the bundle:\n" + ex); } }
private void btnInfo_Click(object sender, EventArgs e) { if (BundleInst == null || cboxBundleContents.SelectedItem == null) { return; } var index = cboxBundleContents.SelectedIndex; var dirInf = BundleHelper.GetDirInfo(BundleInst.file, index); var bunAssetName = dirInf.name; //When we make a modification to an assets file in the bundle, //we replace the assets file in the manager. This way, all we //have to do is not reload from the bundle if our assets file //has been modified MemoryStream assetStream; if (!ModifiedFiles.ContainsKey(bunAssetName)) { var assetData = BundleHelper.LoadAssetDataFromBundle(BundleInst.file, index); assetStream = new MemoryStream(assetData); } else { //unused if the file already exists assetStream = null; } //warning: does not update if you import an assets file onto //a file that wasn't originally an assets file var isAssetsFile = BundleInst.file.IsAssetsFile(BundleInst.file.reader, dirInf); if (isAssetsFile) { var assetMemPath = Path.Combine(BundleInst.path, bunAssetName); var fileInst = Am.LoadAssetsFile(assetStream, assetMemPath, true); if (!LoadOrAskCldb(fileInst)) { return; } var info = new AssetsViewer(Am, fileInst, true); info.Closing += AssetsViewerClosing; info.Show(); } else { MsgBoxUtils.ShowErrorDialog("This doesn't seem to be a valid assets file."); } }
/// <summary> /// 管理データを削除します /// </summary> private void DeleteData(IList <int> idList) { //セルが選択されていない場合は、処理を抜けます if (_grid.SelectedCells.Count == 0) { return; } var result = MessageBox.Show("管理データを削除してもよろしいですか?\nファイルは削除されません。", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { var deleteIDList = new List <int>(); //グリッドから行を削除するためのIDリスト //「はい」の場合、管理データを削除します using (var connection = _db.GetConnection()) { //トランザクション開始 var transaction = connection.BeginTransaction(); try { foreach (var id in idList) { //管理データを削除します FileDB.DeleteData(connection, id); //削除用IDリストにIDを追加します deleteIDList.Add(id); } //コミット transaction.Commit(); } catch (Exception ex) { //ロールバック transaction.Rollback(); MsgBoxUtils.ShowErrorMsgBox("削除に失敗しました。\n" + ex.Message); } } //一覧を更新します foreach (var id in deleteIDList) { //指定したIDの行を取得します int row = GetRowIndex(id); //行を削除します _grid.Rows.RemoveAt(row); } } }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { if (Modified) { AskSaveChanges(); } var ofd = new OpenFileDialog { Title = @"Open assets or bundle file", Filter = @"All types (*.*)|*.*|Unity content (*.unity3d;*.assets)|*.unity3d;*.assets|Bundle file (*.unity3d)|*.unity3d|Assets file (*.assets)|*.assets" }; if (ofd.ShowDialog() != DialogResult.OK) { return; } var selectedFile = ofd.FileName; var fileType = AssetsBundleDetector.DetectFileType(selectedFile); CloseAllFiles(); switch (fileType) { case DetectedFileType.AssetsFile: { var fileInst = Am.LoadAssetsFile(selectedFile, true); if (!LoadOrAskCldb(fileInst)) { return; } new AssetsViewer(Am, fileInst).ShowDialog(); break; } case DetectedFileType.BundleFile: LoadBundle(selectedFile); break; default: MsgBoxUtils.ShowErrorDialog("Unable to read the file!\n" + "Invalid file or unknown (unsupported) version."); break; } }
private void RemoveAssetItems() { var choice = MsgBoxUtils.ShowWarningDialog("Are you sure you want to remove the selected asset(s)?\n" + "This will break any reference to this/these."); if (choice != DialogResult.Yes) { return; } foreach (ListViewItem listItem in assetList.SelectedItems) { var item = Workspace.LoadedAssets[listItem.Index]; Workspace.AddReplacer(AssetModifier.CreateAssetRemover(item)); assetList.Items.Remove(listItem); Workspace.LoadedAssets.Remove(item); } }
private List <AssetTypeValueField> GetSelectedFields() { try { var fields = new List <AssetTypeValueField>(); foreach (var cont in GetSelectedAssets()) { fields.Add(Workspace.GetBaseField(cont)); } return(fields); } catch { MsgBoxUtils.ShowErrorDialog("Unable to process the asset data!\n" + "This might be due to an incompatible type database."); return(null); } }
public void WriteFiles(List <AssetsReplacer> replacers, bool overwrite = false) { var lastFileId = replacers.Max(r => r.GetFileID()); for (var fileId = 0; fileId <= lastFileId; fileId++) { var id = fileId; var sortedAssetsList = replacers.Where(r => r.GetFileID() == id).ToList(); // sort the list of replacers by fileID var fileInst = Workspace.LoadedFiles[fileId]; if (overwrite) { var path = fileInst.path; var tempPath = Path.Combine(Path.GetTempPath(), fileInst.name); using var fs = File.OpenWrite(tempPath); using var writer = new AssetsFileWriter(fs); fileInst.file.Write(writer, 0, sortedAssetsList, 0); Am.UnloadAssetsFile(path); fs.Close(); File.Replace(tempPath, path, path + ".backup"); Workspace.LoadedFiles[fileId] = Am.LoadAssetsFile(path, false); } else { var sfd = new SaveFileDialog { Title = @"Save as...", Filter = @"All types (*.*)|*.*|Assets file (*.assets)|*.assets", FileName = fileInst.name }; if (sfd.ShowDialog() != DialogResult.OK) { continue; } if (fileInst.path == sfd.FileName) { MsgBoxUtils.ShowErrorDialog("If you want to overwrite files go to \"File->Save\" instead of \"File->Save as...\"!"); return; } using var fs = File.OpenWrite(sfd.FileName); using var writer = new AssetsFileWriter(fs); fileInst.file.Write(writer, 0, sortedAssetsList, 0); } } }
private void AskSaveChanges() { if (!Workspace.Modified) { return; } var choice = MsgBoxUtils.ShowInfoDialog("Would you like to save the changes?"); switch (choice) { case DialogResult.Yes: SaveFiles(); break; case DialogResult.No: CloseFiles(); break; } }
//初期処理を行います public bool Initialize(PluginCreateParam param) { //指定されたファイルがある場合は、ファイルを開きます if (FileUtils.Exists(param.Path)) { //指定されたパスの先頭の1行を読み込みます var lines = TextFileUtils.ReadTopLines(param.Path, Encoding.UTF8, 1); try { var path = lines[0].Trim(); //OSで指定されている方法でファイルを開きます Process.Start(path); } catch (Exception ex) { MsgBoxUtils.ShowErrorMsgBox(ex.Message); } } //false を返してプラグインを破棄させます return(false); }
private void btnOK_Click(object sender, EventArgs e) { if (rbtnTXT.Checked) { dumpType = DumpType.TXT; } else if (rbtnXML.Checked) { dumpType = DumpType.XML; } else if (rbtnJSON.Checked) { dumpType = DumpType.TXT; // todo } else { MsgBoxUtils.ShowErrorDialog("You didn't choose any dump type!\n" + "Please go back and select it.\n"); DialogResult = DialogResult.None; } }
private void btnViewData_Click(object sender, EventArgs e) { if (FailIfNothingSelected()) { return; } var baseFields = GetSelectedFields(); if (baseFields == null) { return; } var cldb = Workspace.Am.classFile; foreach (var baseField in baseFields) { var cldbType = AssetHelper.FindAssetClassByName(cldb, baseField.GetFieldType()); if (cldbType != null) { if (HasAnyField(cldbType)) { continue; } MsgBoxUtils.ShowErrorDialog("This asset has no data to view."); } else { MsgBoxUtils.ShowErrorDialog("Unknown asset format."); } baseFields.Remove(baseField); } if (baseFields.Count == 0) { return; } foreach (var baseField in baseFields) { new AssetData(Workspace, baseField).Show(); } }
/// <summary> /// グリッドのダブルクリックイベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void grid_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex == -1) { return; //ヘッダーダブルクリックは無視する } //選択されているパスを取得します var path = GetSelectedPath(); if (path == null) { return; } if (FileUtils.Exists(path) == false) { MsgBoxUtils.ShowErrorMsgBox(path + "が見つかりません。"); return; } //フォルダまたはファイル選択イベントを発生させます RaiseSelectedEvent(path); }
/// <summary> /// 評価を一括更新します /// </summary> private bool UpdateValue(IList <int> idList) { using (var connection = _db.GetConnection()) { //トランザクション開始 var transaction = connection.BeginTransaction(); try { foreach (var id in idList) { //評価を更新します FileDataDao.UpdateField(connection, id, "value", _value.ToString()); } //コミット transaction.Commit(); return(true); } catch (Exception ex) { //ロールバック transaction.Rollback(); MsgBoxUtils.ShowErrorMsgBox("更新に失敗しました。\n" + ex.Message); return(false); } } }
private void btnOK_Click(object sender, EventArgs e) { var cldb = Workspace.Am.classFile; var fileInst = Workspace.LoadedFiles[cboxFileID.SelectedIndex]; AssetTypeTemplateField templateField; var fileId = cboxFileID.SelectedIndex; if (!long.TryParse(boxPathID.Text, out var pathId)) { MsgBoxUtils.ShowErrorDialog("Path ID is invalid!"); return; } var type = boxTypeNameOrID.Text; int typeId; var createBlankAsset = chboxCreateBlankAssets.Checked; if (fileInst.file.typeTree.hasTypeTree) { if (!TryParseTypeTree(fileInst, ref type, createBlankAsset, out templateField, out typeId)) { if (!TryParseClassDatabase(ref type, createBlankAsset, out templateField, out typeId)) { MsgBoxUtils.ShowErrorDialog("Class type is invalid!"); return; } //has typetree but had to lookup to cldb //we need to add a new typetree entry because this is //probably not a type that existed in this bundle fileInst.file.typeTree.unity5Types.Add(C2T5.Cldb2TypeTree(cldb, typeId)); } } else { if (!TryParseClassDatabase(ref type, createBlankAsset, out templateField, out typeId)) { MsgBoxUtils.ShowErrorDialog("Class type is invalid!"); return; } } var monoSelected = cboxTypePreset.SelectedIndex == 1; ushort monoId; if (typeId != 0x72 || !monoSelected) { monoId = ushort.MaxValue; } else { if (!ushort.TryParse(boxMonoID.Text, out monoId)) { MsgBoxUtils.ShowErrorDialog("Mono ID is invalid!"); return; } } if (!int.TryParse(boxCount.Text, out var count)) { MsgBoxUtils.ShowErrorDialog("The count of assets being created is invalid!"); return; } byte[] assetBytes; if (createBlankAsset) { var baseField = ValueBuilder.DefaultValueFieldFromTemplate(templateField); assetBytes = baseField.WriteToByteArray(); } else { assetBytes = Array.Empty <byte>(); } for (var i = 0; i < count; i++) { var item = new AssetItem { Type = type, TypeID = (uint)typeId, FileID = fileId, PathID = pathId + i, Size = assetBytes.Length, Modified = "*", MonoID = monoId }; Items.Add(item); Workspace.AddReplacer(AssetModifier.CreateAssetReplacer(item, assetBytes), new MemoryStream(assetBytes)); } DialogResult = DialogResult.OK; }
private void btnOK_Click(object sender, EventArgs e) { if (BundleInst == null) { return; } AssetBundleDecompressionType decompType; if (rbtnFile.Checked) { decompType = AssetBundleDecompressionType.File; } else if (rbtnMemory.Checked) { decompType = AssetBundleDecompressionType.Memory; } else { MsgBoxUtils.ShowErrorDialog("You didn't choose any decompression type!\n" + "Please go back and select it.\n"); DialogResult = DialogResult.None; return; } try { Bw = new BackgroundWorker(); if (BundleInst.file.IsBundleDataCompressed()) { switch ((int)decompType) { // Decompress to File case 0: { var sfd = new SaveFileDialog { FileName = BundleInst.name + ".unpacked", Filter = @"All types (*.*)|*.*" }; if (sfd.ShowDialog() != DialogResult.OK) { return; } Bw.DoWork += delegate { DecompressToFile(sfd.FileName); }; break; } // Decompress to Memory case 1: Bw.DoWork += delegate { DecompressToMemory(); }; break; } } else { Bw.DoWork += delegate { DecompressToMemory(); }; } Bw.RunWorkerCompleted += delegate { MsgBoxUtils.ShowInfoDialog("The bundle file has been successfully unpacked!", MessageBoxButtons.OK); //Decompressed = true; }; Bw.RunWorkerAsync(); } catch (Exception ex) { MsgBoxUtils.ShowErrorDialog("Something went wrong when unpacking the bundle:\n" + ex); } }
/// <summary> /// ポップアップメニューを設定します /// </summary> private void SetPopupMenuItem() { //フォルダを開く _grid.ContextMenuStrip = new ContextMenuStrip(); { var menu = new ToolStripMenuItem("フォルダを開く"); menu.Click += (sender, e) => { //選択されているセルがある行のパスを取得します var path = GetSelectedPath(); if (path == null) { return; } var dirPath = Path.GetDirectoryName(path); if (Directory.Exists(dirPath) == false) { MsgBoxUtils.ShowErrorMsgBox(path + "が見つかりません。"); return; } //ネイティブな方法でフォルダを開きます Process.Start(dirPath); }; _grid.ContextMenuStrip.Items.Add(menu); } //ファイルを開く { var menu = new ToolStripMenuItem("ファイルを開く"); menu.Click += (sender, e) => { //選択されているセルがある行のパスを取得します var path = GetSelectedPath(); if (path == null) { return; } if (FileUtils.Exists(path) == false) { MsgBoxUtils.ShowErrorMsgBox(path + "が見つかりません。"); return; } //フォルダまたはファイル選択イベントを発生させます RaiseSelectedEvent(path); }; _grid.ContextMenuStrip.Items.Add(menu); } //ネイティブな方法でファイルを開く { var menu = new ToolStripMenuItem("ネイティブな方法でファイルを開く"); menu.Click += (sender, e) => { //選択されているセルがある行のパスを取得します var path = GetSelectedPath(); if (path == null) { return; } if (FileUtils.Exists(path) == false) { MsgBoxUtils.ShowErrorMsgBox(path + "が見つかりません。"); return; } //ネイティブな方法でフォルダを開きます Process.Start(path); }; _grid.ContextMenuStrip.Items.Add(menu); } //管理データの削除 { var menu = new ToolStripMenuItem("管理データの削除"); menu.Click += (sender, e) => { //現在選択中のIDリストを取得します var idList = GetSelectedIDList(); if (idList.Count == 0) { return; } //管理データを削除します DeleteData(idList); }; _grid.ContextMenuStrip.Items.Add(menu); } //評価 { var menu = new ToolStripMenuItem { Text = "評価" }; _grid.ContextMenuStrip.Items.Add(menu); //評価(0 - 10)ごとにメニューを作成します for (int value = 0; value <= 10; value++) { menu.DropDownItems.Add(new UpdateValueMenu(this, _db, _grid, _colIndexes.Value, value)); } } //タグ { var menu = new ToolStripMenuItem("タグ"); _grid.ContextMenuStrip.Items.Add(menu); menu.DropDownItems.Add(new AddTagMenu(this, _db, _grid, _colIndexes.Tag)); //タグ追加 menu.DropDownItems.Add(new UpdateTagMenu(this, _db, _grid, _colIndexes.Tag)); //タグ更新 menu.DropDownItems.Add(new DeleteTagMenu(this, _db, _grid, _colIndexes.Tag)); //タグ削除 } }