前回の「【Visual Studio探検記】「Hello World!巡り」-ウィンドウズ編(C#)総則」でC#のウィンドウズプログラミングには色々とプラットフォームが分かれているので、一応それらの概観を確認しました。

 

今回は旧い(Win95~のGDIとWinXP~のGDI+)グラフィックを使う、Win32 APIに近いWinFormsで「HelloWorld4」を作ってみましょう。

 

【全体イメージ】

 

これは既に作ったHelloWorld4の画面ですが、ソリューションエクスプローラーを見ると大分当事者(ファイル等)が多いので、ズームしてみます。

 

 

依存関係」はこのアプリケーションがよって立つプラットフォームのシステムやDLLなどが表示されます。(これをユーザーがいじることはまずありません。)尚、「依存関係」-「フレームワーク」を見ると、このプログラムは.NETCore上で走るようです。(「アナライザー」がコード自動生成やファイル管理、「フレームワーク」がプラットフォームなのかな、という感じを受けますね。)

 

Form1.cs」というのがこのプロジェクトの中核なのですが、「Form1(Form1()はコンストラクター、OnPaint()はイベント処理メソッドですね)と「Form1.Designers.cs(「してその実体は」UI設定処理で、リソーススクリプトForm1.resxもその手下のようです)からなります。

 

Program.cs」はエントリーポイントのMain()メソッドを持ち、コンソールプログラムではユーザープログラムの中核だったのですが、どうなってしまったのでしょうか?

 

では、エディターで開かれるファイルを見てみましょう。

 

(1) Form1.cs(ユーザーが処理を書き込む「プログラム本体」部分)

 

 

今回私が書き込んだ部分は緑色のコメント部分です。内容はC++のときと同じく、WM_PAINTメッセージの際のシステムの処理(OnPaintメソッド処理-"base.OnPaint(e)")の後に、Form1ウィンドウのクライアントエリア(ウィンドウの内枠部分)を求め、StringFormatクラスインスタンス sf を(画面の中央に表示をするよう)初期化し、文字列とフォントを設定してGraphicsクラスのDrawStringメソッドで"Hello World!"と描画します。

 

(2) Form1.cs [デザイン](これはForm1というクラスのUIをWYSWYGで設計し、XAMLで記述する部分)

 

 

コントロールやメニュー等は何も使わないのでこのままです。以下(↓)のXAMLファイルでも設定はすべてシステムの既定値です。

 

(3) Form1.Designers.cs(これはForm1クラスの一部で、Form1.resxというリソースの取り込みを含めてUIを規定する部分)

 

 

最初にSystem.ComponentModel.IContainerのインスタンスcomponents(実際はポインター)を初期化し、Form1のDisposeメソッドをオーバーライド()して(リソースがある場合<components != null>の)components.Dispose()メソッドを追加してから、componentsを生成(new)、Form1の初期設定を行っています。

:C++からの用語で、(異なる引数や戻り値の)同じ名前の関数やメソッドを作れるfeature(特長?)です。

 

<Form1.resx - ご参考(これがXAMLというマークアップ言語です)>

<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- 
    Microsoft ResX Schema 
        Version 2.0
    The primary goals of this format is to allow a simple XML format 
    that is mostly human readable. The generation and parsing of the 
    various data types are done through the TypeConverter classes 
    associated with the data types.
    
    Example:
    
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
                
    There are any number of "resheader" rows that contain simple 
    name/value pairs.
    
    Each data row contains a name, and value. The row also contains a 
    type or mimetype. Type corresponds to a .NET class that support 
    text/value conversion through the TypeConverter architecture. 
    Classes that don't support this are serialized and stored with the 
    mimetype set.
    
    The mimetype is used for serialized objects, and tells the 
    ResXResourceReader how to depersist the object. This is currently not 
    extensible. For a given mimetype the value must be set accordingly:
    
    Note - application/x-microsoft.net.object.binary.base64 is the format 
    that the ResXResourceWriter will generate, however the reader can 
    read any of the formats listed below.
    
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array 
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
</root>

 

(4) Program.cs(これがForm1のエントリーポイント<Main()>で、初期化と実行を行う部分)

 

 

お馴染みの"[STAThread] static void Main()"()というエントリーポイントメソッドがあり、アプリケーションの初期化と実行を行います。

: シングルスレッド アパートメント (Single-Threaded Apartment) 

 

いかがだったでしょうか?私的にはまだまだC++で書いたWIndowsプログラム(HellowWorld3)との相関が理解し得る範囲ではありますが、Visual Studio側で多くの処理を裏方の黒子がやっているので、「ユーザーは自分がやることが少なくなっている反面、(自動生成コードと自動処理が多く)プログラム全体で何がどうなっているのかがわからない」というジレンマが生じる、とも言えそうです。

 

いずれにしても、

 

これをビルドして実行すると、

 

 

こんな風になります。尚、「OnPaintイベント処理時点のクライアントエリアの中央に文字列を書き込むので、ウィンドウサイズを変更すると真ん中にならない」プログラムとなってしまいました。これを常に真ん中に持ってくるには「クライアント領域サイズをクラスメンバーとし、OnPaintメソッドにある描画位置処理を、ReSizeイベントOnSizeChanged(EventArgs e)メソッドをオーバーライドしたメソッドへ移動」してください。(面倒くさくてやりませんでした。テヘッ)

        .

        .

        .

        .

わかったよ、分かったから。

【変更版ーVisual Studioにやらせると厄介なので、変更は手作業で行いました。】

namespace HelloWorld4
{
    public partial class Form1 : Form
    {

        //解説:クラスメンバー変数(フィールド)
        int width = 0;
        int height = 0;

        //解説:コンストラクター
        public Form1()
        {
            InitializeComponent();
            width = this.ClientSize.Width;
            height = this.ClientSize.Height;
        }


        //解説:Paintイベントで描画します。
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            //解説:クライアントエリアの幅と高さを取得
            RectangleF rec = new RectangleF(0, 0, width, height);
            //解説:StringFormatインスタンスの設定
            StringFormat sf = new StringFormat
            {
                Alignment = StringAlignment.Center,    
// 水平方向中央
                LineAlignment = StringAlignment.Center  // 垂直方向中央
            };
 
          //解説:表示文字列
            string str = "Hello World!";
            //解説:描画用フォントとブラシの作成(usingを使い、Dispose()メソッドを省略)
            using (Font font = new Font("Meiryo", 20, FontStyle.Bold))
            using (Brush brush = new SolidBrush(Color.DarkBlue))
            {
               
//解説:文字列を描画する
                e.Graphics.DrawString(str, font, brush, rec, sf);
            }
        }


        //解説:SizeChangedイベントで描画します。
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            //解説:クライアントエリアの幅と高さを取得
            width = this.ClientSize.Width;
            height = this.ClientSize.Height;
            this.Refresh();    
//解説:強制的にクライアント領域を無効化、再描画します。(Win32API のinvalidaterect(hWnd, NULL, false);相当)
        }
    }
}

 

防衛費を前倒しでGDPの2%とするそうな。

 

主義や価値観を別とし、(米国大統領は同世代の商売人だから)過去の「(日米貿易不均衡是正策の一環として)付き合いで、断れずに使いもしないものを買わざるを得なかった」だけであれば、単に「無駄な歳出」だけで済むのですが、第三番目の「カネ」がついて、第二番目の「モノ」を(実際に"when in need"に本気で使うつもりで)購入したならば、どうしてもそれを(技術的、整備的、実践的に)使う「ヒト」がいなければどうにもなりません。これはあらゆる

 

マネージメント

 

の世界に共通する原理です。

 

人が要る

 

とうのは、単に「員数を合わせる」という意味では不十分で、教育、訓練双方が不可欠です。特に現在の状況下では深刻な

 

Achilles Tendon

 

となります。そんな赤子でもわかることを現政権や国民が分からないはずがない。にも拘わらず、

 

誰もが他人事のようなそぶりで、

誰も、何も言わない、沈黙の不気味さ

 

それが気になります。

 

死にかけの私のためではなく、(まだ使えそうな)子供たち、(逃げられない)孫たちのことを思うと。

 

前回は、C++でWindows SDKベースのプログラムで「WM_PAINTイベント割り込みで、ウィンドウのクライアントエリアの中央にグラフィックで文字列出力を行う」プロジェクト(HelloWorld3)を作りました。

 

今回はC#を使って同じようなものを作るのですが、C#にはプログラミングプラットフォームがWinFormsWFPの二つがあり()、初心者やC#をよく知らない人は当惑してしまいます。(事実、5年前の私も「???」でした。)

:更にWinFormsでは「Windowsフォームアプリ」と「Windowsフォームアプリケーション(.NET Framework)」、WPFでは「WPFアプリケーション」と「WPFアプリ(.NET Framework)」と更に選択肢がありますが、「何がどう違い、どういう場合に選ぶべきか」が全く分かりません。その為ご本家の説明を求めても、

 

 

ここから長々と「(専門用語の)寿限無寿限無...」を読まなければならないと思うと、心が折れます。

 

そうだっ!Copilot君にまとめさせよう!」ということで質問すると、ズラズラと長い説明が返ってきたので、(誤解を招く)危険を承知で私が短く纏めると以下の通りかと考えます。(2 x 2 = 4通り)

 

1.WinForms 対 WFP

 

要すれば、従来(Windows 95以降のGDIやXP以降のGDI+)のグラフィックを直接GPUを操作できるDirect X 技術に置き換え、クロスプラットフォームが可能となるようにディスプレー縦横比が変わってもキチンと表示できるようなUIを導入し、その開発にプログラミング用マークアップ言語(XAML)を使うようになった為、グラフィックデザイナーやコーダー等それぞれの領域のプロの分業がより効率的になった、とでもいえましょうか?(飽くまで私見ですが...)

 

2..NET 対 .NET Framework(これはCopilot君任せ)

(1) .NET(.NET 5 以降)版

  • 「Windows フォームアプリ」
  • 「WPF アプリケーション」

特徴

  • 新しい .NET(.NET 5+)ランタイム を使用
  • クロスプラットフォームではないが、.NET の最新機能・最適化を利用可能
  • 将来性があり、Microsoft の主流ライン
  • ただし 古い .NET Framework 専用 API やライブラリは使えない場合がある

(2) .NET Framework 版

  • 「Windows フォームアプリケーション(.NET Framework)」
  • 「WPF アプリ(.NET Framework)」

特徴

  • .NET Framework 4.x を使用
  • Windows 専用、レガシー資産との互換性が高い
  • 古い API、COM、Win32、既存 DLL との連携が容易
  • ただし 開発は保守モード(新機能はほぼ追加されない)

いかがでしょうか?少しは「分かった」感がでてきましたでしょうか?

 

しかし、

 

いくら理屈をこねても仕方がないので、「説明なしにズラズラとメニューを並べるVisual Studioのテンプレートの大体の概観が得られた(かな?)」所で、次回からは「現場、現物、現実」の現主義的に実際にVisual Studioにテンプレートを作らせて、それを見てゆきましょう。

 

さてさて、前回で「『Hello World!巡り』-コンソール編」をC++、C#共に終了しましたので、今回からデスクトップテンプレートを使って旅を続けていきたいと思います。

 

先ずはC++から。

 

 

選択したのは「Windows デスクトップウィザード」というやつです。「次へ」ボタンを押して進むと、

 

はて?

 

 

成程。「Windows Desktopで使えるプログラムだから、ウィンドウアプリのみならず、コマンドプロンプト(いわゆる「DOS窓」)で使えるコンソールアプリや.DLL、.LIBも含む」という意味ね。(

:だったら「コンソールアプリを作る入口がダブっているということ?それとも違いがあるの?」という突っ込みができそうです。最初にVisual Studioを使った5年前と全く違うのは私にはCopilotというAIのお供(友?)がいること。彼に聞くと、次の通りとのこと。(矢張りここにもユーザーの知らない黒子達がいっぱいいました。)

 

とはいえ、私は「デスクトップアプリケーション(.exe)(Win32 API)」を選択して進みます。

 

【全体イメージ】

 

小さくて見難いですが、今度はソースファイル(HelloWorld3.cpp)にびっしりコードが書き込まれているのがわかるでしょう。また一見でそれがWindows SDK)ベースのコードであることがわかります。

Windows SDK(Windows Software Development Kit )とはC/C++言語でWin32 APIを使ってプログラミングをするためのヘッダーファイル等が一式セットになったものです。MFC(Microsoft Foundation Class)等を使っていないのでWindowsがウィンドウプログラムをどのように動かしているのか等、基礎的な構造や仕組みを学べます。至極端折って言えば、ウィンドウプログラムはマウスクリックやキー入力、ウィンドウのサイズ変更等という「入力イベント」の割り込みに対し、対応する「関数(メソッド)」を都度処理するプログラムであり、プログラムの起動も"WinMain"というエントリーポイント関数になります。

 

コンソールプログラムと大きく異なるのは関連ファイルの多さです。↑のイメージの左上にある「ソリューションエクスプローラー」の拡大版を載せます。

 

 

御覧のようにヘッダーファイルが4本、リソースファイルとしてリソーススクリプト(.rc)とアイコンファイルが二つあります。(「外部依存関係」はWin32 APIがズラズラと並び膨大です。)

 

(1)framework.h

HelloWorld3のプログラム(ウィンドウズプログラミング)用のSKDとC++ファイブラリーのヘッダーファイルがまとめられていました。

 

// header.h : 標準のシステム インクルード ファイルのインクルード ファイル、
// またはプロジェクト専用のインクルード ファイル
//

#pragma once

#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
            // Windows ヘッダーからほとんど使用されていない部分を除外する
// Windows ヘッダー ファイル
#include <windows.h>
// C ランタイム ヘッダー ファイル
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

 

(2)HelloWorld3.h

単に以下(3)のファイルを読み込む為だけのものでした。(複雑なもプログラムではもっと他のヘッダー等が追加されるのかもしれません。)

 

#pragma once

#include "resource.h"

 

(3)Resource.h

これはWin32リソースにID番号を設定するものです。(BCCSkeltonでは"Res(プロジェクト名).h"となる奴)

尚、プリプロセッサー(if~endif)についてはインデントがされていないので、色で対応を示しておきます。

 

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ で生成されたインクルード ファイルです。
// 次で使用: HelloWorld3.rc

#define IDS_APP_TITLE            103

#define IDR_MAINFRAME            128
#define IDD_HELLOWORLD3_DIALOG    102
#define IDD_ABOUTBOX            103
#define IDM_ABOUT                104
#define IDM_EXIT                105
#define IDI_HELLOWORLD3            107
#define IDI_SMALL                108
#define IDC_HELLOWORLD3            109
#define IDC_MYICON                2

#ifndef IDC_STATIC
#define IDC_STATIC                -1

#endif
// 新しいオブジェクトの次の既定値
//

#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NO_MFC                    130
#define _APS_NEXT_RESOURCE_VALUE    129
#define _APS_NEXT_COMMAND_VALUE        32771
#define _APS_NEXT_CONTROL_VALUE        1000
#define _APS_NEXT_SYMED_VALUE        110

#endif
#endif
 

(4)targetver.h

良く分かりませんが、Windows SDKの「(利用できるもののうち、最も新しい)最適化されたバージョンを選択する」為のヘッダーファイルのようです。

 

#pragma once

// SDKDDKVer.h をインクルードすると、利用できる最も高いレベルの Windows プラットフォームが定義されます。
// 以前の Windows プラットフォーム用にアプリケーションをビルドする場合は、WinSDKVer.h をインクルードし、
// サポートしたいプラットフォームに _WIN32_WINNT マクロを設定してから SDKDDKVer.h をインクルードします。

#include <SDKDDKVer.h>
 

(5)HelloWorld3.ico、small.ico

二つとも同じデザインの自動生成されたアイコンファイルで次の(6)HelloWOrld.rcから参照されます。

 

(6)HelloWorld3.rc

自動生成されたリソーススクリプトファイルです。

 

//Microsoft Visual C++ で生成されたリソース スクリプトです。
//

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE リソースから生成されました。
//

#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
LANGUAGE 17, 1

/////////////////////////////////////////////////////////////////////////////
//
// アイコン
//

// アプリケーション アイコンをすべてのシステム上で維持するために、最も小さい
// ID 値のアイコンが最初に配置されます。


IDI_HELLOWORLD3       ICON         "HelloWorld3.ico"
IDI_SMALL               ICON         "small.ico"


/////////////////////////////////////////////////////////////////////////////
//
// メニュー
//

IDC_HELLOWORLD3 MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "終了する(&X)",                IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...",           IDM_ABOUT
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// アクセラレータ
//

IDC_HELLOWORLD3 ACCELERATORS
BEGIN
    "?",            IDM_ABOUT,              ASCII,  ALT
    "/",            IDM_ABOUT,              ASCII,  ALT
END


/////////////////////////////////////////////////////////////////////////////
//
// ダイアログ
//

IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報 HelloWorld3"
FONT 9, "MS UI Gothic"
BEGIN
    ICON            IDI_HELLOWORLD3,IDC_STATIC,14,14,21,20
    LTEXT           "HelloWorld3, バージョン 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
    LTEXT           "Copyright (c) 2025",IDC_STATIC,42,26,114,8
    DEFPUSHBUTTON   "OK",IDOK,113,41,50,14,WS_GROUP
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 163
        TOPMARGIN, 7
        BOTTOMMARGIN, 55
    END
END

#endif    // APSTUDIO_INVOKED

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\0"
END

3 TEXTINCLUDE
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

/////////////////////////////////////////////////////////////////////////////
//
// 文字列テーブル
//

STRINGTABLE
BEGIN
   IDC_HELLOWORLD3   "HELLOWORLD3"
   IDS_APP_TITLE       "HelloWorld3"
END

#endif
/////////////////////////////////////////////////////////////////////////////

#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE リソースから生成されました。
//
/////////////////////////////////////////////////////////////////////////////

#endif    // not APSTUDIO_INVOKED
 

(7)HelloWorld3.cpp

そして最後に自動生成された(ユーザー用の)プログラム「本体」です。ウィンドウにグラフィックで文字出力を行うために、WM_PAINTイベント割り込みでクライアントエリアの中央に文字列を書いています。

 

// HelloWorld3.cpp : アプリケーションのエントリ ポイントを定義します。
//

#include "framework.h"
#include "HelloWorld3.h"

#define MAX_LOADSTRING 100


// グローバル変数:
HINSTANCE hInst;                                // 現在のインターフェイス
WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーのテキスト
WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名

// このコード モジュールに含まれる関数の宣言を転送します:(解説:「転送」が意味不明ですが、所謂「プロトタイプ宣言」です。)
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);


//解説:ウィンドウプログラムのエントリ^ポイント関数です。'w'がついているのはユニコード対応であることを示しています。
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);


    // TODO: ここにコードを挿入してください。

    // グローバル文字列を初期化する
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_HELLOWORLD3, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance); 
  //解説:これはこのウィンドウをOSに登録しています。

    // アプリケーション初期化の実行:( 解説:ウィンドウの生成と表示を行っています。)
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }


    //解説:アクセラレーションテーブルを読み込んでいます。
    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HELLOWORLD3));

    MSG msg;
    // メイン メッセージ ループ:(解説:このループが続く限り、ウィンドウが開いています。メッセージWM_CLOSEが呼ばれるとウィンドウを閉じ、続いてWM_DESTROYでウィンドウが廃棄されます。)
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}


//
//  関数: MyRegisterClass()
//
//  目的: ウィンドウ クラスを登録します。
//

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLOWORLD3));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_HELLOWORLD3);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    return RegisterClassExW(&wcex);
}


//
//   関数: InitInstance(HINSTANCE, int)
//
//   目的: インスタンス ハンドルを保存して、メイン ウィンドウを作成します
//
//   コメント:
//
//        この関数で、グローバル変数でインスタンス ハンドルを保存し、
//        メイン プログラム ウィンドウを作成および表示します。
//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance;
// グローバル変数にインスタンス ハンドルを格納する
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
   if (!hWnd)
   {
      return FALSE;
   }
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);
   return TRUE;
}


//
//  関数: WndProc(HWND, UINT, WPARAM, LPARAM)
//   解説:所謂ウィンドウコールバック関数で↑にあったメッセージループと対になっています。
//  目的: メイン ウィンドウのメッセージを処理します。
//
//  WM_COMMAND  - アプリケーション メニューの処理
//  WM_PAINT    - メイン ウィンドウを描画する
//  WM_DESTROY  - 中止メッセージを表示して戻る
//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);

            // 選択されたメニューの解析:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

            // TODO: HDC を使用する描画コードをここに追加してください...
 

            //解説:文字列の描画部分だけは私が書きました。Win32APIでよく使われる文字列描画関数は
            //BOOL TextOut(HDC hdc, int x座標, int y座標, LPC(W)STR 文字列ポインター, int 文字列長);
            //ですが、
            //int DrawText(HDC hdc, LPC(W)TSTR 文字列ポインター, int 文字列長, LPRECT 文字列描画RECT構造体へのポインター, UINT 書式設定);
            //も使いやすいと思われます。

            TCHAR str[] = TEXT("Hello World!");
            RECT rec;
            GetClientRect(hWnd, &rec);

            DrawText(hdc, str, -1, &rec, DT_CENTER | DT_SINGLELINE  | DT_VCENTER);
           
EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


// バージョン情報ボックスのメッセージ ハンドラーです。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;
    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;

}

 

いかがだったでしょうか?Windows SDKを使ってプログラミングすると、C/C++文法とWin32 APIだけを使ったプログラミングになるため、何をしているのかが分かりやすい反面、細かいところまでコーディングしなければならないので、コード量が増えることがお判りいただけたかと存じます。その意味で大部分が自動生成されるVisual Studioはありがたいのですが、

 

「どこに何を書くの?」

 

ということがわからない段階では結構ハードルが高いのではないか、と愚考します。

 

いずれにせよ、これをビルドして実行すると、こういう成果物が現れます。(自動生成リソースはアイコン、メニューとバージョンダイアログです。)

 

次はC#でやってみましょう。

 

新PCを迎えたために、旧PCをVisual Studio専用機にして【Visual Studdio探検記】を始めたら、案の定大作になりそうなので、ここで一息、また食べ物の話を入れましょう。

 

昨日(2025年12月20日)のお昼、突然「スパゲッティをアラビアータソースで食べたいっ!」と思い立ちました。

 

しかし、スパだけだと栄養の偏りがあるので、野菜とソーセージの薄切りを入れたチキンコンソメスープ、サラダを用意するのみならず、スパゲッティもアーリオオーリオ(Aglio Olio)にひき肉と野菜を入れて炒め、それに市販のアラビアータソースを絡めた結果、

 

見た目が「ナポリタン」

 

に見えるスパゲッティアラビアータになりました。これでいいのか?

 

これでいいのだっ!

 

「Hello World!巡り」-コンソール編(C++)をやったので、当然C#編も続けてやりましょう。

 

ここでプログラミング言語としてのC#についてご存じでない方のために簡単に説明すると、

 

(1)一番初めは、「1972年にAT&Tベル研究所のデニス・リッチーが主体となって開発した汎用プログラミング言語 (wiki)」として「C」言語が開発されました。これはアッセンブラーのような速いネイティブコード(機械語)をコンパイルする柔軟性のある言語でしたが、その美点の表裏のような結果として(保護メモリーに直接アクセスしたり、キャストなどによってかなり悪いこともできる)低級言語(細かい処理までできるということは、それだけ書かなければならない処理が多くてコード量が増える)であった為、

 

(2)Cを高級言語化した「クラス」を利用できるオブジェクト指向言語("C with Classes")の開発が1979年から開始され、1983年には「Cを(進化を彷彿させる)インクリメント(++)させた言語」という意味で"C++"という名称となり、1985年に商用版がリリースされました。(wiki

 

(3)更に(旧BorlandのTurbo Pascalや、当時WYSWYGで頭抜けていたDelphiを開発したアンダース・ヘルスバーグを筆頭として多数のDelphi開発陣が参加し、)Windowsの.NET Framework上で動作することを前提としてマイクロソフトが開発したのがC#C++を進化させてインクリメントした言語、"C++++"→"C#"という意味らしいで、Javaに似た構文、C++に比べて扱いやすくプログラムの記述量も少なく、2016年6月からはクロスプラットフォームな.NETランタイム上で動作します。(wiki

 

ただし、

 

「高級」になった分、またプラットフォームが.NET Framework→.NET_Core→.NETへ進化する過程、更に(旧いWin32APIベースの)WinFormsから(XAMLによるUI定義やDirect3Dを活用したグラフィック等の新技術を反映した)WPFの導入等により、ライブラリーやソリューション/プロジェクト管理が複雑化した印象が拭えません。

 

例えば

 

C++HelloWorld1では、ソリューションのフォールダーの下には64bitの実行ファイルが入る「x64」、プロジェクトの「HelloWorld1」のフォールダーがあり、「HelloWorld1」の下にはソースファイルや管理ファイルの下にまた「x64」があって、その中に「Debug」と「Release」という実行ファイルのフォールダーが並ぶだけでした。(その下にもゴチャゴチャあるのですが省略)

 

所が

 

これがC#HelloWorld2になると、「x64」のフォールダーがなくなり、管理用の「.vs隠しフォールダーが作られ、その下に管理フォールダーとファイルが入ります。またプロジェクトフォールダー(HelloWorld2)の下にはソースファイルと管理ファイルの他に「bin」(実行ファイル関連)、「obj」(実行ファイル作成用のリンクファイル関連-実行ファイルを含む)、「properties」(実行ファイルの属性情報等)が入るという、系統建てられてはいてもだいぶ複雑な感じになっています。

 

【全体イメージ】

 

Visual Studioの画面レイアウトはC++のHelloWorld1と変わりませんが、ソリューションエクスプローラーとソースコードは大きく異なります。

 

先ず、Visual Studioが「ここにプログラムをかけ」というファイル(ユーザープログラム本体)Program.cs(↑のエディターの部分)になります。しかし、ソリューションエクスプローラーで中身が見れるファイルだけでも、

 

【プログラム部分

(1)Assembly.cs

プロジェクトの「Properties」として、開発するアセンブリ(Assembly-の属性情報(Win32時代のリソースの一種であったVERSION情報等)がプログラムの一部としてビルドされます。

:「Assemblyが何か」はご本家の説明では分かり辛いと思いますが、.NET環境における「展開、バージョン管理、再利用、アクティブ化スコープ、およびセキュリティアクセス許可」情報が組み込まれ、仮体した実行ファイル(*.exe、*.dll等)とお考え下さい。

 

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


// アセンブリに関する一般的な情報は、次の方法で制御されます。
// 制御されます。アセンブリに関連付けられている情報を変更するには、
// これらの属性値を変更します。

[assembly: AssemblyTitle("HelloWorld2")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HelloWorld2")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]


// ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから
// 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、
// その型の ComVisible 属性を true に設定します。

[assembly: ComVisible(false)]

// このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります
[assembly: Guid("6e3229e4-d7f3-42f9-b4b5-fe1b707d5d27")]

// アセンブリのバージョン情報は次の 4 つの値で構成されています:
//
//      メジャー バージョン
//      マイナー バージョン
//      ビルド番号
//      リビジョン
//

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

 

(2)App.config

このC#はWinFormsで作られますが、アプリケーション(プログラム)の基盤情報(エンコーディングや.NETのプラットフォーム種別)にかかわるXAMLファイルになります。

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
</configuration>

 

(3)Program.cs

ここで初めてユーザープログラムが現れます。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelloWorld2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(">>> HelloWorld2 <<<");
 //解説:これは私が書きました。
            Console.WriteLine("Hello World!");  //解説:これは私が書きました。
            Console.Read();                     //解説:これは私が書きました。(コンソールプログラムを終わらせない為)
        }
    }
}

 

C#のコンソールプログラムも"Hello World!"のビルトインコードがあるかと思ったのですが、ありませんでしたね。

 

これを「ビルド」-「ソリューションのビルド」、「デバッグ」-「デバッグの開始」(または「デバッグなしで開始」)で実行すると、

 

 

となります。

 

お判りでしょうか?

単に"Hello World!"という文字列をコンソールに表示するだけでも、Visual Studioという裏方組織は「ユーザーに知られることなく、様々な役割を、様々な黒子(「闇の実行部隊」)が支えている、ということを。

 

ps. 単なる"Hello World!"のプログラム紹介をここまで書くだけで疲れてしまいましたが、まだまだ冒険の旅は続きます。今度はいよいよウィンドウプログラムになります。

 

さて、前回書いたように、本格的に冒険の旅へ出かける前に小手調べとして

 

Hello World!

 

を出力する定番プログラムを試してみることにしました。

 

1.C++プログラム

先ずはC++で「コンソールアプリ」テンプレートでコンソール出力プログラムを作ってみます。(

:「空のプロジェクト」でもよかったのですが、Visual Studioのプロジェクトテンプレートには予めプロジェクト管理ギミックが仕掛けられていると思うので、それも見たいと思い、「コンソールアプリ」にしました。

 

すると自動生成された(ユーザーのプログラミング用)テンプレートは「まんま、Hello World」になっていたので、二行だけ追加しました。

 

【全体イメージ】

 

小さくてみにくいのですが()、フルスクリーンのVisual Strudioの中に、

 

(1)最も左に隠れているのが「ツールボックス

(2)次に上部にタブ付きのエディター(これは本体の一部のようです)、その下部に「出力」と「エラー一覧」(↑のイメージではタブにまとまってますが、各独立画面、独立2画面にすることも可能。)

(3)右に「ソリューションエクスプローラー」(そのタブとして「プロパティマネージャー」「リソースビュー」と「Git変更」があります)、さらにその下部に「プロパティウィンドウ」があります。

(4)これらはいったん閉じて、再度開くときにはメニューの「表示」-「ソリューションエクスプローラー」、「Git変更」、「プロパティウィンドウ」および「その他のウィンドウ」-「リソースビュー」、「プロパティマネージャー」から呼び出せます。

:というよりも、Visual StudioというIDEを画面一杯に広げても、テンコ盛りの機能ですべて埋め尽くされてしまうからです。

 

ソリューション(開発対象の親分)エクスプローラーの中を見てください。まずプロジェクト親分の手下の若頭みたいなもの、今回はHelloWorld01)があり、プロジェクトには「参照」「外部依存関係」「ソースファイル」「ヘッダーファイル」「リソースファイル(実行部隊の協力先と舎弟ですね)が続きます。プログラムはiostreamというヘッダーファイルを読んでいますが、参照ヘッダーファイルフォールダーは空です。(おそらくユーザーのヘッダーファイルを対象とするのでしょう。)外部依存関係はシステムやC++ライブラリー(今回はiostream)の関数がずらっと並びます。ソースファイルには自動生成ファイルが入り、リソースファイルには何も入っていません。

 

【プログラム部分ソースファイル-HelloWorld01.cpp

// HelloWorld1.cpp : このファイルには 'main' 関数が含まれています。プログラム実行の開始と終了がそこで行われます。
//


#include <iostream>

int main()
{
    std::cout << ">>> HelloWorld1 <<<" << std::endl;   //解説:これは私が書きました
    std::cout << "Hello World!\n";
    std::cin.get();   //解説:exeプログラムを実行するとすぐに消えるので、これは私が書きました
}

// プログラムの実行: Ctrl + F5 または [デバッグ] > [デバッグなしで開始] メニュー
// プログラムのデバッグ: F5 または [デバッグ] > [デバッグの開始] メニュー

// 作業を開始するためのヒント: 
//    1. ソリューション エクスプローラー ウィンドウを使用してファイルを追加/管理します 
//   2. チーム エクスプローラー ウィンドウを使用してソース管理に接続します
//   3. 出力ウィンドウを使用して、ビルド出力とその他のメッセージを表示します
//   4. エラー一覧ウィンドウを使用してエラーを表示します
//   5. [プロジェクト] > [新しい項目の追加] と移動して新しいコード ファイルを作成するか、[プロジェクト] > [既存の項目の追加] と移動して既存のコード ファイルをプロジェクトに追加します
//   6. 後ほどこのプロジェクトを再び開く場合、[ファイル] > [開く] > [プロジェクト] と移動して .sln ファイルを選択します

(二行だけ追加しましたが)後はメニューの「ビルド」ー「ソリューションのビルド」()を行い、「出力」と「エラー一覧」で正常にビルドできたことを確認して、「デバッグ」-「デバッグの開始(または「デバッグなしで開始」)」を選択すると、

:ソリューションのビルドを行うと、その傘下のすべてのプロジェクトがビルドされる、ということです。個別にプロジェクトをビルドすることもできます。

 

 

と表示されます。

 

「あー、簡単なんだ。」

 

と思われる方は3点ご注意を。

 

."Hello World!"プログラムは世にC言語を知らしめるためにカーニハンとリッチーが考え出した陰謀であり、現実のプログラミングはそんなに簡単なものではない、ということと、

 

.何しろVisual Studioは、

 

複数のスタッフが共同、協働してプロジェクト、そしてソリューションを完成させて行くことを想定した「プロの環境」なので、実際のプログラミングのみならず、管理機能がテンコ盛りであり、「何がどこにあるのか」を完璧に理解するまでは結構大変である

 

ということは覚えていてほしいと思います。

 

.従って、この原稿を書くためにVisual Studioで表示できるウィンドウやプロパティページを探すだけで、私の「旅の相棒Copilot君にもうお世話になっている始末です。

 

旅はまだまだ続くのであった...

 

ps. 今回C#までやろうかと思いましたが、長くなったので次回。

 

さて、前回装備を確認し、冒険の旅へと出発しました。

 

しかしっ、

 

どんなRPGでも一足飛びに先まで進もうとすると強い敵にやられてお陀仏になってしまいますので、先ずは「出発地周辺(車のナビのようですが)」で経験値を稼ぐことが必要です。

 

C、C++やC#というC調プログラミング言語の出発点

 

といえば、やっぱり

 

Hello World!

 

しかないですよね?

 

ということで、最初は私の選択したプログラミング言語、「C++とC#」のテンプレートでこのメッセージを出力してみましょう。テンプレートは72もありますが、この二つの言語で使えそうなのは、

 

1.コンソール(昔ながらのDOS風の文字列出力です。)

2.シンプルなウィンドウ(「デスクトップ」という呼び方をされているようです。)

 

の二つを取り上げて、C++とC#でプロジェクトを作ってみましょう。題して「Hello World!巡り」です。

 

【予告編】

<コンソール版>

 

 

<デスクトップ版>

 

さーて、HelloWorld!5景。どれが何でしょうか?

 

さて、新たな冒険の旅が開始され、Visaul Studioも正常にダウンロード、インストールされました。(

【Visual Studio探検記】インストールしなければ何も始まらない

 

新たな冒険の旅の出発前に、装備を点検する必要があります。

 

ということで、Visual Studioを立ち上げましょう。

 

【オープニング画面】

 

【開始する】

 

Visual Studioを起動すると、オープニング画面に続き「開始する」というダイアログが開き、左側に既作成のソリューションやプロジェクト)がリストされ、右側に「新しいプロジェクトの作成」、「プロジェクトやソリューションを開く」、「folderを開く」、「リポジトリーのクローン」という選択肢が表示されます

:初めての方には耳慣れない言葉(その説明も「コンテナ」etcと日常の言葉ではありません)ですが、ドラマなどに出てくる反社組織に準えれば「最終的に完成する仕事(「ワシは日本をすべてシマにしちょるけん!」)」という指定暴力団がソリューション、その系列の手下となる構成員組織が「プロジェクト」で「具体的な最終仕事の完成の為の下仕事(「(敵対する組織の)親分のタマとっちゃる」、「(薬とか風俗とかetcで)シノギをする」とか、etcの具体的業務)」を請け負い、指定暴力団の傘下にはいっている、というアナロジーで如何?

 

何もVisual Projectで作っていない段階なので、「新しいプロジェクトの作成」を選択するとそのダイアログが表示されます。

 

【新しいプロジェクトの作成】

 

ここで先ず、(私が選択した)C++とC#は良いとして、それ以外に(選択した覚えのない)VB、F#やその他も含み(私が最も恐れ、嫌う)

 

72のテンプレート(そんなにいらんがな...)

 

が右側にリストされます。その内容も(自分で選んだC++とかC#とかの)プログラミング言語は良いとして、ワークロード)、プラットフォーム(大体「プログラムが動作するOS」と「PCとかスマホとかのハード」と理解しておれば困らないでしょう)等を含め、「クラスライブラリ」「ワーカーサービス」「テストプロジェクト」「NUnit」「ATL」etcやたらカタカナ、英文省略語が多く初心者方には非常に分かり辛いものになっています。

:「Visual Studioで特定のプログラミング言語やプラットフォームに必要なツールや機能をまとめたセット」だそうです。

 

要らないものは排除したり、消去したいと思うのですが、webに書かれたVisual Studio 2022用の方法ではうまくいきません。下手にいじくっておかしくなるのも心外なので、仕方なくこのまま付き合うとしましょう。(尚、その際は↑のイメージの赤枠で囲った)「テンプレートの検索」や「言語(ドロップダウンリスト)」により絞り込みをかけることをお勧めします。

 

要すればこの困惑、当惑は「大都市の一流レストランへ行き、分厚いメニューとワインリストが渡されて、中身は全く知らない、読めない、分からない料理名、酒名で満ち溢れている状態」で、

 

早くなんかオーダーしろ、というプレッシャー

 

がかけられている時に感じるものと類似していることに気付かされるでしょう。

 

5年前はアセアセ、セッセとGoogleでインターネット上の情報を漁って自分で調べましたが、5年後の今は

 

ねぇ、Copilotぉ、ここんとこ分かんない。教せーて!

 

といえば懇切丁寧に教えてくれる時代になったというところだけが違うのです。

 

MicrosoftのCopilotが英雄の仲間になりました(♩~♪~♬~♫~)

┐(´∀`)┌ヤレヤレ

 

やっと始まったこのシリーズ、続けるにはタイトル通り「インストールしなければ何も始まらない」。

 

ということで、

 

今回はVisual Studio 2026のダウンロードとインストールをやりましょう。

 

1.Visual Studio 2026のダウンロード

前回もリンクを載せていましたが、最新のVisual Studio 2026はここからダウンロードします。(個人の方のプライベート使用であれば、フリーダウンロードのCommunity版を選んでください。)

 

 

2.Visual Studio 2026のインストール

とりあえずポチっとすると、本体ではなく

 

 

インストーラー(VIsual Studio Setup.exe)」というものがダウンロードされます。

ここでも迷わず起動しましょう。すると、

 

 

が出ますので構わず「続行」してください。

 

さて、次が鬼門です。

 

 

ユーザーが欲しい「ワークロード」を選択し、既定のコンポーネントにアラカルトを加えるか「個別のコンポーネント」で選択し、使用する言語()に対応する「言語パック」、そして最後に「インストールの場所」も選択できます。

:既定は「OSと同じ言語(日本語)」ですが、英語や欧州圏、アジア圏の適用を考えるなら言語パックをダウンロード、インストールできます。

 

がっ、

 

初めて「プログラミングをしてみよう」と考えた初心者は、「ASP.NETとWeb開発」、「AzureとAIの開発」を読んだあたりで、

 

???なんのこっちゃ???

 

となるか、

 

^^^ビビってしまう^^^

 

のではないでしょうか?次の「Python開発」あたりで、

 

あっ、聞いたことがあるっ!

 

位で、Windowsの主流となった「.NET」も

 

それってプログラミング言語?

 

となったり、「マルチプラットフォーム開発」「デスクトップ開発」もまだ用語に馴染みがないのではないでしょうか?

 

折角プログラミングに興味を持ったのに、門前で怖がらせて引き返したり、挫折感を味わう初心者の方がいないでしょうか?心配です。

 

かくいう(すでに初心者ではない)私もこの「プログラミング環境インストール用タブ選択」を前にして

 

ウ~ン

 

と唸り、結局「C調老人」として

 

 

C#用に(右の詳細でC#関連のみを選び).NETデスクトップ開発」と「C++、Cによるデスクトップ開発」のみをインストールすることにしました。

 

さーて、どうなったでしょうか?