Help us understand the problem. What is going on with this article?

Visual Studio 2017 Visual C++ による VC++/CLI GUI の開発

More than 1 year has passed since last update.

はじめに

VC++/CLI は .NET CLR 上で動作するものですが、GUI も開発できます。しかし、VC++ で GUI を作る人はほとんどいなかったのか、すでにオワコン状態です。以前は確かもっと厚くサポートされていたと思いますが、現在ではオマケのような感じです。

さらに、Visual Studio 2017 での開発においても、何かと問題があるように見えます。例えば、

  • 一部のコントロールがちゃんと動作しない。(少なくとも C# や VB.NET と動作が異なる)
  • ウィンドウプロシージャを手動で書いてやる必要がある。
  • フォームのデザイン画面を最初に開いたとき必ずエラーになる。。
  • プロジェクトのプロパティを手動で修正する必要がある。

ということで、複雑な GUI を作るのにはお勧めできませんが、処理結果をコンソール画面でなくウィンドウに表示したいという程度なら使えそうです。

プロジェクトの作成

Visual C++ の「新しいプロジェクト」には 「Windows Forms アプリケーション」のような選択肢はありません。次のように「空のプロジェクト」を選択します。

VCProj_Empty.png
Fig.1 「新しいプロジェクト」ダイアログ

空のプロジェクトが作成されたら、そのプロジェクトを選択し、コンテキストメニューの「追加」-「新しい項目」から Fig.2 のように 「UI」-「Windows フォーム」を選んで OK ボタンをクリックします。

GUI_MyForm.png
Fig.2 「新しい項目の追加」ダイアログ

デフォルトでは MyForm.cpp と MyForm.h というファイルがプロジェクトに追加されます。このうち、MyForm.h が GUI に関連するので、これを開いてみると Fig.3 のようなエラー画面が表示されてしまいます。

GUI_DesignError.png
Fig.3 フォーム表示のエラー画面

これは一度、ビルドを行えば解消されますが、Fig.4 のようなエラーが表示されます。これは「空のプロジェクト」にフォームを追加しただけなので、main 関数が未定義になっているためです。

GUI_EntryPointError.png
Fig.4 ビルドエラー

MyForm.cpp をコード表示して、次のように main 関数を追加します。あるいは Main.cpp のようなソースを追加してそこに記述しても構いません。ここで、名前空間は各自のプロジェクトに合わせて修正が必要です。

Code.1 MyForm.cpp の修正例

#include <Windows.h>
#include "MyForm.h"

using namespace GUI2;

int main()
{
    MSG msg;

    Console::WriteLine(L"Starting ..");

    // フォームを構築して表示する。
    MyForm ^myForm = gcnew MyForm();
    myForm->Show();
    Console::WriteLine(L"MyForm has shown ..");

    // ウィンドウメッセージをディスパッチ
    while (GetMessage(&msg, 0, 0, 0))
        DispatchMessage(&msg);

    Console::WriteLine(L"MyForm destroyed.");
    return 0;
}

ビルドしてみると、Fig.5 のようなリンカーエラーが大量に出ます。これは、プロジェクトのプロパティでリンカー設定を修正すると解消できます。

GUI_LinkError.png
Fig.5 リンカーのエラー

Fig.6 のようにリンカーの入力に Windows のシステム DLL をリンクするように指示します。

GUI_LinkProp.png
Fig.6 プロジェクトのプロパティの設定

これで実行してみると、Fig.7 のような画面が表示されるはずです。

GUI_MyFormShown.png
Fig.7 フォームの表示

サンプル

Fig.7 の画面でフォームの閉じるボタン (x) をクリックしてもアプリケーションは終了しません。

アプリケーションを終了させるには、PostQuitMessage API 関数を実行すればいいので、FormClosed ハンドラでこの関数を呼び出すようにします。

変更が必要なのはヘッダーファイルだけです。FormClosed イベントハンドラを追加して、そこで PostQuitMessage を呼び出しています。(Code.2 の下の方)

Code.2 MyForm.h

#pragma once

namespace GUI2 {

    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>
    /// MyForm の概要
    /// </summary>
    public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
            //
            //TODO: ここにコンストラクター コードを追加します
            //
        }

    protected:
        /// <summary>
        /// 使用中のリソースをすべてクリーンアップします。
        /// </summary>
        ~MyForm()
        {
            if (components)
            {
                delete components;
            }
        }
    private: System::Windows::Forms::Button^  button1;

    private:
        /// <summary>
        /// 必要なデザイナー変数です。
        /// </summary>
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        /// <summary>
        /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディターで変更しないでください。
        /// </summary>
        void InitializeComponent(void)
        {
            this->components = gcnew System::ComponentModel::Container();
            this->Size = System::Drawing::Size(300,300);
            this->Text = L"MyForm";
            this->Padding = System::Windows::Forms::Padding(0);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->FormClosed += gcnew System::Windows::Forms::FormClosedEventHandler(this, &MyForm::MyForm_FormClosed);
        }
#pragma endregion
    // FormClosed
    private: System::Void MyForm_FormClosed(System::Object^  sender, System::Windows::Forms::FormClosedEventArgs^  e) {
        PostQuitMessage(0);
    }
    };
}

-

tadnakam
電通大出身。 趣味でプログラミングをやってます。
https://makandat.wordpress.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした