質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

2回答

5614閲覧

Visual C++による.NETプログラム開発

nartoc

総合スコア12

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

0クリップ

投稿2016/12/22 15:23

C++
Visual C++で.NETのプログラムを開発しています。C++ではヘッダー部と実装部を.hファイルと.cppファイルに分けることが一般的とされていますが、Visual Studioで定義したフォームやコントロールは"フォーム名.h"ファイル内にコードが実装され、そのファイルの外からコントロールをアクセスする方法が分からない(できない?)ので、"フォーム名.h"ファイル内に、フォーム(およびフォーム内のコントロール)の処理を実装しています。C++のマナーに従い.cppファイル内にコントロールの処理を実装する方法があれば教えてください。

エラーメッセージ

###該当のソースコード

ここにご自身が実行したソースコードを書いてください

###試したこと
課題に対してアプローチしたことを記載してください

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Visual Studioが自動で作成するC++/CLIのコードは、単にヘッダーにインラインでコードを書いているだけであって、全く同じことがC++でもできます。

Visual Studioで定義したフォームやコントロールは"フォーム名.h"ファイル内にコードが実装され、そのファイルの外からコントロールをアクセスする方法が分からない(できない?)ので、

ヘッダーをインクルードすればいいだけだと思うのですが。例えば、MyFormのコードの中でMyUserControlを使いたいなら、MyForm.hの最初の方(namespace ~の前あたり)で#include "MyUserControl.h"と書けば使えるようになります。
そういう話ではないのですか?


サンプルコード
フォーム側

public ref class MyForm : public System::Windows::Forms::Form { public: MyForm(void) { InitializeComponent(); // staticメンバにthisポインタを格納。 // ※複数のインスタンスを作らないことが前提 spThis = this; } public: System::Windows::Forms::PictureBox^ pictureBox1; // ↑ デザイナーでModifiresプロパティを変更するとここが書き換わる public: // グローバル関数からアクセスできるようにstaticメンバ変数でthisポインタを保持 static MyForm^ spThis; : : };

呼び出し側

#include "MyForm.h" using namespace プロジェクト名; void MyAppFunction() { auto g = MyForm::spThis->pictureBox1->CreateGraphics(); : : }

投稿2016/12/22 16:08

編集2016/12/26 04:30
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nartoc

2016/12/23 01:09

回答ありがとうございます。 フォーム定義の.hファイルをincludeしていますが、フォームのコントロールが参照できません。例えば Graphics^ g = pictureBox1->CreateGraphics(); というコードは(pictureBox1は.hファイルに定義されているpictureBox).hファイル内に記述すると正常にコンパイルできますが、.cppファイル(.hファイルinclude)に記述すると、 C2065 'pictureBox1':undeclared identifier となります。
catsforepaw

2016/12/23 01:19

状況がよく判りません。単にpictureBox1を参照する場所のスコープが違うということも考えられます。 可能であれば、どういうファイル構成でどのようにコードを記述したらコンパイルエラーになるのか、具体的に提示していただいたほうが回答しやすくなると思います。
KoichiSugiyama

2016/12/23 04:23

質問者から同様のコメントをいただきましたので、こちらにコメントをつけさせていただきます。 cppファイルに記述する場合(From1のコントロールの場合) Graphics^ g = Form1::pictureBox1->CreateGraphics(); でダメでしょうか?
KoichiSugiyama

2016/12/23 04:29

追加です。自クラスのオブジェクトの場合、 Graphics^ g = this->pictureBox1->CreateGraphics(); で。
nartoc

2016/12/25 00:12

自クラス内ならthis->なしでアクセスできるので問題ありません。自クラス外からアクセスする場合pictureBox1だけではエラーになるので、回答いただいたように Graphics^ g =Form1::pictureBox1->CreateGraphics(); としてみましたが、 C2227 'left of ->CreateGraphics' must point to class/struct/unions/generic type エラーとなりビルドできません。
catsforepaw

2016/12/25 01:14

エラー箇所を1行だけ抜き出して見せられてもエラーの原因は判りません。文脈が判る程度に範囲を広げて.hと.cpp両方を提示してください。 おそらく、スコープや、関連の実装方法に関する理解が浅いために混乱しているのだと思われます。C++が.hと.cppに分けるのはC言語から引き継いだ仕様ですが、それはコンパイラーの都合であり、OOPとは何の関係もありません。エラーの原因もコードの書き方の問題であり、.hと.cppに分けたこととは無関係です。 お節介かもしれませんが、.NETアプリを作るのなら、C++ではなくC#を使うことをおすすめします。.NET関連でC++を対象とした解説は非常に少ないです。MSDNのサイトでも.NETクラスライブラリーのサンプルコードにC++がなかったりすることもありますから。
nartoc

2016/12/25 14:11

VSでフォームおよびフォーム内コントロールを定義すると「フォーム名,h」ファイルが作られ、その中に次のようなコードが生成されます。 namespace プロジェクト名 {    ... public ref class フォーム名 : public System::Windows::Forms::Form { public: フォーム名(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// </summary> ~フォーム名() { if (components) { delete components; } } ... private: System::Windows::Forms::PictureBox^ pictureBox1; ... private: /// <summary> /// Required designer variable. /// </summary> System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> void InitializeComponent(void) { ... this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox()); ... // // pictureBox1 // this->pictureBox1->Location = System::Drawing::Point(190, 27); this->pictureBox1->Name = L"pictureBox1"; ... } #pragma endregion (アプリケーションコードはここに記述) } 「フォーム名,h」ファイルが作られるとき、同時に「フォーム名,cpp」ファイルも作られます。このファイル内に次のようなコードを記述すると、前の質問のようなエラーになり、ビルドできません。 (各種#include) ... #include "フォーム名.h" ... (各種 using) ... using namespace フォーム名; //************************************************** //* アプリケーション処理 //************************************************** アプリケーション関数() { ... Graphics^ g =フォーム名::pictureBox1->CreateGraphics(); ・・・ return ; } ----------------- おっしゃる通り、.NETプログラム開発にはC#がいいと思いC#の勉強を始めていたのですが、OpenCVを使った画像処理ソフトを開発する必要に迫られ、OpenCVはC#をサポートしないので、サポートする言語(C++,Python,Java,C。Cは今後サポートされない)の中からC++を選び、勉強のやり直しを始めたところです。OpenCVはオープンソースで機能豊富な画像処理ライブラリですが、GUI機能はほとんどサポートしていないので、その部分は.NETで実現しようとしています。 いまの問題は、アプリケーションコードを「フォーム名」クラスの中にメンバー関数として記述すれば解決すると思いますが、そうすると.hと.cppの使い分けもさることながら、せっかくフォーム(とフォーム名コントロール)をクラス(カプセル)化し情報隠蔽を図っているはずなのに、その中に入り込まないとクラスメンバーにアクセスできないということであり、何かおかしいなと疑問を感じている次第です。
catsforepaw

2016/12/26 04:21

やはりスコープの違いでアクセスできないだけのようですね。 `アプリケーション関数`はグローバル関数のようなので、`フォーム名`オブジェクトのthisポインタをグローバル変数かpublicなstaticメンバ変数として格納しておき、それを介してアクセスしないといけません。さらには、`pictureBox1`はprivateで外部からは直接参照できないので、フォームデザイナーで`pictureBox1`を選択し、プロパティの`Modifires`をPrivateからPublicに変更しておいてください(あまりお勧めはできませんが、とりあえずの処置です)。 それと、`using namespace`で指定するのはフォーム名ではなくプロジェクト名です。ウィザードでプロジェクトを作成すると、プロジェクト名が名前空間名になるはずです。 サンプルコードを回答の方に書いておきます。
catsforepaw

2016/12/26 04:54

> OpenCVはC#をサポートしないので、サポートする言語(C++,Python,Java,C。Cは今後サポートされない)の中からC++を選び、勉強のやり直しを始めたところです。 .NETは異なる言語間での呼び出しも容易にできます。GUI部分はC#で作成し、OpenCVを使うような画像処理部分はC++/CLIでクラスライブラリーとして作成し、C#でそれを呼び出すようにします。 あるいは、C#はC/C++で作ったDLLを直接呼び出すこともできるので、GUI部分はC#で作成し、画像処理部分はC/C++で作成する、ということもよくやります。`DllImport`をキーワードに検索すればいろいろ出てきますよ。 言語によって得意分野が違うので、それぞれの特性を生かして言語を使い分けるということも重要です。 > せっかくフォーム(とフォーム名コントロール)をクラス(カプセル)化し情報隠蔽を図っているはずなのに、その中に入り込まないとクラスメンバーにアクセスできないということであり、何かおかしいなと疑問を感じている次第です。 それについては、この件の問題ではなく設計・実装の方法論ですね。C++でも然るべき設計・実装をすれば高いレベルでの情報隠蔽は実現できますし、ほかのどのような言語でも設計・実装がまずければおかしなことになります。
nartoc

2016/12/26 14:07

「あまりお勧めできない、とりあえずの処置」でうまくいきました。ありがとうございました。 以前C#とC++の組み合わせも検討し、「OpenCV3ではじめるWindowsアプリ開発」(林良二著、工学社」を買って勉強したのですが、そもそもWindowsのことをよく知らないので、書いてあることがよく分からず、サンプルコードをそのまま(のつもり)打ち込んでみても動かないのであきらめました。一段落したらもう一度チャレンジしてみます。 ユーザフォーム(およびフォーム内コントロール)をフォームクラス外からアクセスするためには、クラス内にパブリックなアクセス関数がなければ、コントロール自体をパブリックにせざるを得ないと思いますが、マイクロソフトはどんな使い方(使われ方)を想定しているのでしょうか?
catsforepaw

2016/12/26 14:28

コードの体裁を考えないのであればメンバ変数をpublicにしてしまえば誰でもアクセスできますが、「隠蔽」の目的は果たせないので「あまりお勧めできない、とりあえずの処置」としました。 > ユーザフォーム(およびフォーム内コントロール)をフォームクラス外からアクセスするためには、クラス内にパブリックなアクセス関数がなければ、コントロール自体をパブリックにせざるを得ないと思いますが、 そんなことはありません。アクセサ(いわゆるgetter/setter)を作ったり、特定の操作を行うための専用のメソッドを作ったり(例えば、PictureBoxに対して画像をセットする、指定した色で塗りつぶす、などといった操作をするメンバ関数の作成)、様々な手法が考えられます。
guest

0

ソリューションエクスプローラに表示される「ソースファイル」フォルダで、右クリック→追加→新しい項目と操作して表示されるダイアログからcppファイルをプロジェクトに追加できます。
あとは、通常のc++の作法通り、ヘッダから実装部分をcppファイルに移して書くだけです。

開発環境任せでソースを作ると、VB.NETやC#に合わせた形でヘッダファイルのみに全てコードが書かれてしまいますので、hファイルとcppファイルに分けたければ残念ながら手作業でcppファイルに追加してやる必要があります。

C++に関しては、CLRだけのみならず、MFCやWin32、コンソールアプリなどいろいろなタイプのプロジェクトに対応する必要があるので、自動整形の機能に限界があるのはやむを得ないと思います。

投稿2016/12/22 15:50

KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nartoc

2016/12/23 00:53

回答ありがとうございます。 VSで新しいフォームを作成すると"フォーム名.h”ファイルと同時に"フォーム名.cpp"という空ファイルができるので、基本的にはここに処理を記述するようにしています。ところがTextBoxなりpictureBoxなりの画面のコントロールを参照しようとするとこれらは"フォーム名.h”の中で”フォーム名"クラスのコンポーネントとして定義されており、"フォーム名.cpp"の中から参照できません。仕方なくコントロールを参照するコードは"フォーム名.h”内に("フォーム名クラスのメンバー関数として)記述していますが、対話処理プログラムの場合はほとんどのコードをここに記述せざるを得なくなり、.ヘッダと実装の分離というC++のガイドラインを守れません。 フォームとコントロールの定義部分も実装と考えて.cpp側に移せばいいのでしょうか? そうすると.hには何も残らなくなりますが?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問