C++でWindowsFormを作りたかったが、VisualStudio2013に、昔あったような「Windowsフォームアプリケーション」が存在しない。
http://takacity.blog.fc2.com/blog-entry-85.html
によると「C++ Windows Forms」が新しいプロジェクトのオンラインにあるとのことだが、2017/6/15時点のVisualStudio2013には見つからず。
http://takacity.blog.fc2.com/blog-entry-84.html
を参考にさせていただき、進めてみる。
「新しいプロジェクト」から、「Visual C++」の「CLR」の「空のCLRプロジェクト」を選択する。名前は「ImageAnalysisModule」と付けておく。
右のプロジェクト名を右クリックし、「追加」の「新しい項目」をクリックする。
VisualC++のUIの「Windowsフォーム」を選択する。
名前は「TopForm.h」としておく。
フォームができて、TopForm.cpp、TopForm.hができて、左側のTopForm.hデザインが開いている。
ソリューションのビルドを行うと、「error LNK1561:エントリーポイントを定義しなければなりません。」エラー。
TopForm.cppを開くと、#include "FopForm.h"しか書かれていないので、http://takacity.blog.fc2.com/blog-entry-84.html、http://y-okamoto-psy1949.la.coocan.jp/booksetc/introvcpp/vs2012FormApp/ を参考に、埋める。
[STAThreadAttribute]を書く理由は、https://dobon.net/vb/dotnet/form/stathread.html が詳しい。
#include "TopForm.h"
using namespace ImageAnaylysisModule;
[STAThreadAttribute]
int main(){
TopForm ^tm = gcnew TopForm();
tm->ShowDialog();
return 0;
}
ビルドが通った。デバッグ開始。
コマンドプロンプトの上にFormが表示される。Formを×で閉じると両方消えた。
コマンドプロンプトを消すには、プロジェクトを右クリックしてプロパティを選択し、「構成プロパティ」の「リンカー」の「システム」の、「サブシステム」を、デフォルトは空っぽなのを、「Windows (/SUBSYSTEM:WINDOWS)」を選択し、「構成プロパティ」の「リンカー」の「詳細設定」の、「エントリポイント」を、デフォルトは空っぽなのを、<編集>を選択し、「main」と入力する。
「適用」ボタンを押し、再度ビルド、デバッグ開始すると、コマンドプロンプトが出なくなる。(http://takacity.blog.fc2.com/blog-entry-84.html、http://y-okamoto-psy1949.la.coocan.jp/booksetc/introvcpp/vs2012FormApp/)
Formにメニューを追加してみる。(参考:https://dobon.net/vb/dotnet/control/menustrip.html)
左のバーから「ツールボックス」をクリックし、「全般」内の「MenuStrip」を、TopForm.hにドラッグ&ドロップする。左上のあたり。
クリックすると入力可能になるので、「ファイル(&F)」と入力する。表示は「ファイル(F)」になる。(Fはショートカットキー。)その下に「開く(&O)...」を入力する。参考URLによると、ダイアログボックスが開く場合にはピリオド3つつけるお作法があるとのこと。
ショートカットキーを画面に表示する場合、「開く」を右クリックしてプロパティを開いて、ShortcutKeyプロパティを変更する。デフォルトは「NONE」なので、Ctrlにチェック入れて、キーはOを選ぶ。「開く(O)...」の右隣りにCtrl+Oと追加される。
進捗状況を表示するステータスバーを作ってみる。(参考:https://dobon.net/vb/dotnet/control/sbprogresspanel.html)
同様に左のバーから「ツールボックス」をクリックし、「全般」内の「statusStrip」を、TopForm.hにドラッグ&ドロップする。▼をクリックし、ProgresBarを選択する。ProgressBarの形になる。
全体的なレイアウト画面を作る。TableLayoutPanelで作ってみることにする。(参考:https://dobon.net/vb/dotnet/control/tlbeginning.html)
左のバーから「ツールボックス」をクリックし、「全般」内の「TableLayoutPanel」を、TopForm.hの中にドラッグ&ドロップする。
デフォルトで2*2なので、列を追加してみる。右下のプロパティに「列の追加」があるのでクリックする。即座に列が追加される。
TableLayoutPanelの右下にListBoxを追加する。(ドラッグ&ドロップしたファイル名を次々表示する場所)
ToolTipを追加する。右向き▼をクリックし、DockをTopから左中央に変更する。ToolTipが横長から縦長に変更された。
ビルド、デバッグするとシンプルにこんな感じ。
上中央にラベルを置く。(今開いているファイル名を表示する)
次にドラッグ&ドロップしたファイル名をListBoxに追加、Labelにファイル名フルパスを記載してみる。(参考:https://dobon.net/vb/dotnet/control/droppedfile.html)
TopFormをクリックし、プロパティの「AllowDrop」がデフォルトで「False」になっているので、「True」に変更する。
イベントボタン(プロパティにある黒い雷みたいなアイコン)をクリックする。
「ドラッグアンドドロップ内」、DragEnter(コントロールのクライアント領域内に、マウスポインターでアイテムをドラッグしたときに発生します)をダブルクリックする。
TopForm.hに行が追加される。
#pragma endregion
private: System::Void TopForm_DragEnter(System::Object^ sender, System::Windows::Forms::DragEventArgs^ e) {
}
};
https://support.microsoft.com/ja-jp/help/815667/how-to-provide-file-drag-and-drop-functionality-in-a-visual-c-net-application-or-in-a-visual-c-2005-application に従い、コードを追加する。
#pragma endregion
private: System::Void TopForm_DragEnter(System::Object^ sender, System::Windows::Forms::DragEventArgs^ e) {
if (e->Data->GetDataPresent(DataFormats::FileDrop)){
e->Effect = DragDropEffects::All;
}
else {
e->Effect = DragDropEffects::None;
}
}
};
TopForm.h[デザイン]に戻り、次はlistBox1のプロパティを開き、イベントボタン(黒い雷)をクリックし、DragDropをダブルクリックする。
コードが自動生成される。
private: System::Void listBox1_DragDrop(System::Object^ sender, System::Windows::Forms::DragEventArgs^ e) {
}
コードを追加する。
String *fileDropList[] = (String *[]) e->Data->GetData(DataFormats::FileDrop, false); ←この書き方ではエラーが出て動かなかった(https://support.microsoft.com/ja-jp/help/815667/how-to-provide-file-drag-and-drop-functionality-in-a-visual-c-net-application-or-in-a-visual-c-2005-application を参考にしたが古い。)
http://blog.goo.ne.jp/uiweo8864/e/b49e5e8eb6992a1cbf6f3d199218912f もコンパイル通らず。
array^ strDropFile = (array<String^>^)e->Data->GetData( ::DataFormats::FileDrop, false );(http://www.program-lab.jp/blog/progmemo/archives/2006/04/dragdrop.html)のarray方法もコンパイル通らず。
結局、https://www.daniweb.com/programming/software-development/threads/341685/drag-and-drop の書き方がエラーが出なかった。
array<String^> ^fileDropList = (array<String^>^) e->Data->GetData(DataFormats::FileDrop);
ただ、これではドラッグ&ドロップしても反応が無く、
http://www.program-lab.jp/blog/progmemo/archives/2006/04/dragdrop.html を参考に、以下の1行を追加すると、無事に表示されるようになった。
http://www.program-lab.jp/blog/progmemo/archives/2006/04/dragdrop.html を参考に、以下の1行を追加すると、無事に表示されるようになった。
this->DragEnter += gcnew System::Windows::Forms::DragEventHandler(this, &TopForm::TopForm_DragEnter); ←これは自動で入っていた
this->DragDrop += gcnew System::Windows::Forms::DragEventHandler(this, &TopForm::listBox1_DragDrop); ←これが自動で入っていなかった
this->DragDrop += gcnew System::Windows::Forms::DragEventHandler(this, &TopForm::listBox1_DragDrop); ←これが自動で入っていなかった
出力は、以下でメッセージボックスにフルパス、
for (int i = 0; i < fileDropList->Length; i++){
MessageBox::Show(fileDropList[i], "test", MessageBoxButtons::OK, MessageBoxIcon::Information);
}
以下で、リストボックスにフルパス。
listBox1->Items->Add(fileDropList[0]);
以下で、ラベルにフルパス。
label1->Text = fileDropList[0];
以下、ここまでの全コード。(TopForm.h)
#pragma once
#include <array>
namespace ImageAnaylysisModule {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// TopForm の概要
/// </summary>
public ref class TopForm : public System::Windows::Forms::Form
{
public:
TopForm(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクター コードを追加します
//
}
protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~TopForm()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::MenuStrip^ menuStrip1;
protected:
private: System::Windows::Forms::ToolStripMenuItem^ ファイルFToolStripMenuItem;
private: System::Windows::Forms::ToolStripMenuItem^ 開くOToolStripMenuItem;
private: System::Windows::Forms::StatusStrip^ statusStrip1;
private: System::Windows::Forms::ToolStripProgressBar^ toolStripProgressBar1;
private: System::Windows::Forms::TableLayoutPanel^ tableLayoutPanel1;
private: System::Windows::Forms::ListBox^ listBox1;
private: System::Windows::Forms::ToolStrip^ toolStrip1;
private: System::Windows::Forms::Label^ label1;
protected:
private:
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());
this->ファイルFToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
this->開くOToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
this->statusStrip1 = (gcnew System::Windows::Forms::StatusStrip());
this->toolStripProgressBar1 = (gcnew System::Windows::Forms::ToolStripProgressBar());
this->tableLayoutPanel1 = (gcnew System::Windows::Forms::TableLayoutPanel());
this->listBox1 = (gcnew System::Windows::Forms::ListBox());
this->label1 = (gcnew System::Windows::Forms::Label());
this->toolStrip1 = (gcnew System::Windows::Forms::ToolStrip());
this->menuStrip1->SuspendLayout();
this->statusStrip1->SuspendLayout();
this->tableLayoutPanel1->SuspendLayout();
this->SuspendLayout();
//
// menuStrip1
//
this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) { this->ファイルFToolStripMenuItem });
this->menuStrip1->Location = System::Drawing::Point(0, 0);
this->menuStrip1->Name = L"menuStrip1";
this->menuStrip1->Size = System::Drawing::Size(503, 26);
this->menuStrip1->TabIndex = 0;
this->menuStrip1->Text = L"menuStrip1";
//
// ファイルFToolStripMenuItem
//
this->ファイルFToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) { this->開くOToolStripMenuItem });
this->ファイルFToolStripMenuItem->Name = L"ファイルFToolStripMenuItem";
this->ファイルFToolStripMenuItem->Size = System::Drawing::Size(85, 22);
this->ファイルFToolStripMenuItem->Text = L"ファイル(&F)";
//
// 開くOToolStripMenuItem
//
this->開くOToolStripMenuItem->Name = L"開くOToolStripMenuItem";
this->開くOToolStripMenuItem->ShortcutKeys = static_cast<System::Windows::Forms::Keys>((System::Windows::Forms::Keys::Control | System::Windows::Forms::Keys::O));
this->開くOToolStripMenuItem->Size = System::Drawing::Size(179, 22);
this->開くOToolStripMenuItem->Text = L"開く(&O)...";
//
// statusStrip1
//
this->statusStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) { this->toolStripProgressBar1 });
this->statusStrip1->Location = System::Drawing::Point(0, 240);
this->statusStrip1->Name = L"statusStrip1";
this->statusStrip1->Size = System::Drawing::Size(503, 22);
this->statusStrip1->TabIndex = 1;
this->statusStrip1->Text = L"statusStrip1";
//
// toolStripProgressBar1
//
this->toolStripProgressBar1->Name = L"toolStripProgressBar1";
this->toolStripProgressBar1->Size = System::Drawing::Size(100, 16);
//
// tableLayoutPanel1
//
this->tableLayoutPanel1->ColumnCount = 3;
this->tableLayoutPanel1->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Percent,
8.051948F)));
this->tableLayoutPanel1->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Percent,
91.94805F)));
this->tableLayoutPanel1->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute,
94)));
this->tableLayoutPanel1->Controls->Add(this->listBox1, 2, 1);
this->tableLayoutPanel1->Controls->Add(this->label1, 1, 0);
this->tableLayoutPanel1->Location = System::Drawing::Point(29, 29);
this->tableLayoutPanel1->Name = L"tableLayoutPanel1";
this->tableLayoutPanel1->RowCount = 2;
this->tableLayoutPanel1->RowStyles->Add((gcnew System::Windows::Forms::RowStyle(System::Windows::Forms::SizeType::Percent, 13.46154F)));
this->tableLayoutPanel1->RowStyles->Add((gcnew System::Windows::Forms::RowStyle(System::Windows::Forms::SizeType::Percent, 86.53846F)));
this->tableLayoutPanel1->Size = System::Drawing::Size(462, 208);
this->tableLayoutPanel1->TabIndex = 2;
//
// listBox1
//
this->listBox1->FormattingEnabled = true;
this->listBox1->ItemHeight = 12;
this->listBox1->Location = System::Drawing::Point(370, 31);
this->listBox1->Name = L"listBox1";
this->listBox1->Size = System::Drawing::Size(88, 88);
this->listBox1->TabIndex = 0;
this->listBox1->DragDrop += gcnew System::Windows::Forms::DragEventHandler(this, &TopForm::listBox1_DragDrop);
//
// label1
//
this->label1->AutoSize = true;
this->label1->Location = System::Drawing::Point(32, 0);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(35, 12);
this->label1->TabIndex = 1;
this->label1->Text = L"label1";
//
// toolStrip1
//
this->toolStrip1->Dock = System::Windows::Forms::DockStyle::Left;
this->toolStrip1->Location = System::Drawing::Point(0, 26);
this->toolStrip1->Name = L"toolStrip1";
this->toolStrip1->Size = System::Drawing::Size(26, 214);
this->toolStrip1->TabIndex = 3;
this->toolStrip1->Text = L"toolStrip1";
//
// TopForm
//
this->AllowDrop = true;
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(503, 262);
this->Controls->Add(this->toolStrip1);
this->Controls->Add(this->tableLayoutPanel1);
this->Controls->Add(this->statusStrip1);
this->Controls->Add(this->menuStrip1);
this->MainMenuStrip = this->menuStrip1;
this->Name = L"TopForm";
this->Text = L"TopForm";
this->DragEnter += gcnew System::Windows::Forms::DragEventHandler(this, &TopForm::TopForm_DragEnter);
this->DragDrop += gcnew System::Windows::Forms::DragEventHandler(this, &TopForm::listBox1_DragDrop);
this->menuStrip1->ResumeLayout(false);
this->menuStrip1->PerformLayout();
this->statusStrip1->ResumeLayout(false);
this->statusStrip1->PerformLayout();
this->tableLayoutPanel1->ResumeLayout(false);
this->tableLayoutPanel1->PerformLayout();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void TopForm_DragEnter(System::Object^ sender, System::Windows::Forms::DragEventArgs^ e) {
if (e->Data->GetDataPresent(DataFormats::FileDrop)){
e->Effect = DragDropEffects::All;
// e->Effect = DragDropEffects::Move;
}
else {
e->Effect = DragDropEffects::None;
}
}
private: System::Void listBox1_DragDrop(System::Object^ sender, System::Windows::Forms::DragEventArgs^ e) {
array<String^> ^fileDropList = (array<String^>^) e->Data->GetData(DataFormats::FileDrop);
if (!fileDropList)
return;
// for (int i = 0; i < fileDropList->Length; i++){
// MessageBox::Show(fileDropList[i], "test", MessageBoxButtons::OK, MessageBoxIcon::Information);
// }
listBox1->Items->Add(fileDropList[0]);
label1->Text = fileDropList[0];
//String *fileDropList[] = (String *[]) e->Data->GetData(DataFormats::FileDrop, false);
//listBox1->Items->Add(fileDropList[0]);
}
};
}