マイクロソフトが開発



Visual Studio

開発環境の紹介

Visual Studio は、Microsoft によって開発された統合開発環境 (IDE) であり、C++、C#、VB.NET、Python、JavaScript などの複数のプログラミング言語をサポートしています。デスクトップ アプリケーション、Web サイト、クラウド サービス、モバイル アプリケーションの開発に適しています。

主な機能

バージョンの違い

プラットフォームのサポート

Visual Studio は Windows オペレーティング システムをサポートし、Visual Studio for Mac は macOS 用に設計されています。

一般的な用途



Visual Studio の構文の書式設定

1. コードを自動的にフォーマットする

Visual Studio には、さまざまなプログラミング言語に適したコードをすばやくフォーマットするためのショートカット キーが用意されています。 - ファイル全体をフォーマットするには、ショートカット キー「Ctrl + K、Ctrl + D」を使用します。 - ショートカット キー「Ctrl + K、Ctrl + F」を使用して、選択したコード ブロックをフォーマットします。

2.自動フォーマットを有効にする

Visual Studio は、ファイルを保存する際の自動コード形式をサポートしています。 1. **[ツール] > [オプション]** をクリックします。 2. **テキスト エディター > [言語] > コーディング スタイル > 一般** に移動します。 3. **ファイル保存時にコードを再フォーマット** にチェックを入れます。

3. 書式設定を変更する

1. **[ツール] > [オプション]** を開きます。 2. **テキスト エディター > [言語] > コーディング スタイル > 書式設定** に移動します。 3. ここでは、インデント、括弧のスタイル、空白行などの詳細な書式設定を調整できます。

4.コーディングスタイルプロファイルを使用する

Visual Studio は、チームのコーディング スタイルを統一するためのコーディング スタイル構成ファイル (.editorconfig) をサポートしています。 1. プロジェクトのルート ディレクトリに新しい `.editorconfig` ファイルを作成します。 2. 次のような形式ルールを定義します。
   [*.cs]
   indent_style = space
   indent_size = 4
   
3. ファイルが保存されると、フォーマットは自動的に次のルールに従います。

5. 拡張ツールをインストールする

組み込みの書式設定機能がニーズを満たさない場合は、拡張ツールをインストールできます。 - **Extension Manager** で **CodeMaid** や **ReSharper** などのツールを検索してインストールします。 - これらのツールは、より多くのコードのフォーマットおよびリファクタリングのオプションを提供します。

6. フォーマットの問題を迅速に修正する

フォーマットの問題が発生した場合は、クイックフィックスを使用できます。 - 問題のあるコードを右クリックし、**クイック アクションとリファクタリング**を選択します。 - **ファイルのフォーマット**または**選択範囲のフォーマット**を選択します。

7. まとめ

- ショートカット キーを使用して、コードをすばやくフォーマットします。 - ファイル保存時の自動フォーマットを有効にします。 - コードスタイルを統一するには `.editorconfig` を使用します。 - 拡張ツールをインストールしてフォーマット機能を向上させます。 ・クイック修正機能を活用してコードの可読性を向上させます。

.NET SDKのバージョン

インストールされている .NET SDK を確認する

コマンド ライン ツールを使用して、コンピューターにインストールされている .NET SDK のバージョンを確認できます。

dotnet --list-sdks

次のような結果が表示された場合は、インストールされている SDK のバージョンを示します。

8.0.100 [C:\Program Files\dotnet\sdk]
9.0.100-preview.3.24172.9 [C:\Program Files\dotnet\sdk]

使用したいバージョンが表示されない場合は、まだインストールされていないことを意味します。

.NET SDKをダウンロードしてインストールする

  1. に行く.NET公式ダウンロードページ
  2. 対応するバージョン (.NET 9 など) とオペレーティング システム プラットフォーム (Windows、macOS、Linux) を選択します。
  3. インストーラーをダウンロードして実行する

Visual Studio でコマンド プロンプト文字を有効にする

  1. Visual Studioを開く
  2. メニュー列のクリック:ツール >コマンドライン >開発者コマンド プロンプトの文字
  3. 開発環境のパスが設定された状態でコマンド プロンプト ウィンドウが開き、これを直接使用できます。dotnet注文

このオプションが表示されない場合は、Windows の [スタート] メニューを使用して「Developer Command Prompt for VS」を検索して開くこともできます。

Visual Studio の組み込みターミナルを使用する (2022 年以降にサポートされます)

  1. Visual Studio で次をクリックします。見る >ターミナルまたはショートカットキーを使用するCtrl + `
  2. 端末の種類を選択します (例: PowerShell または CMD)
  3. 直接入力可能dotnetSDKの確認や操作を行うコマンド


C#言語

言語機能

基本的な例

システムを使用する;

クラス プログラム {
    静的 void Main() {
        文字列名 = "世界";
        Console.WriteLine($"こんにちは、{名前}!");
    }
}

一般的な応用分野

先進的な機能



CS8618 Null 不可が初期化されていません

警告内容

CS8618 は、コンストラクターの最後で、Null不可のプロパティは初期化されていないため、C# コンパイラは、次の可能性があることを警告します。null

質問例

パブリック クラス 製品 {
    パブリック文字列名 { get;セット; } // 警告 CS8618
}

解決

方法 1: コンストラクターで値を割り当てる (推奨)

public class Product {
    public string Name { get; set; }

    public Product(string name) {
        Name = name;
    }
}

方法 2: 属性にデフォルト値を与える

public class Product {
    public string Name { get; set; } = string.Empty;
}

方法 3: Null を許可する

public class Product {
    public string? Name { get; set; }
}

→ 該当するものName合理的に許されるnull状況。

方法 4: 使用するrequired修飾子 (C# 11 以降でサポート)

パブリック クラス 製品 {
    public 必須文字列 Name { get;セット; }
}

// 呼び出し元を初期化する必要があります
var p = 新しい製品 { Name = "携帯電話" }; // わかりました

提案



.NETプログラム

科学的表記法を避けるために浮動小数点数を文字列に変換します

問題文

C++/CLI で使用する場合、floatそしてSystem::Stringたとえば次のように合計します。

System::String^ tmpStr = "Value: " + someFloat;
いつsomeFloat非常に大きいまたは非常に小さい場合、科学表記法 (例: 1.23E+05) で自動的に表示される場合があります。

解決

利用可能System::String::FormatまたはToStringフォーマット文字列を使用して小数点以下の桁数を指定し、科学表記法を使用しないでください。

サンプルプログラム

名前空間システムを使用します。

浮動小数点値 = 123456.789f;

// 方法 1: String::Format
String^ tmpStr1 = String::Format("値: {0:F2}", 値); // F2は小数点以下2桁を表します
Console::WriteLine(tmpStr1);

// 方法 2: ToString の一致形式
String^ tmpStr2 = "値: " + value.ToString("F2");
Console::WriteLine(tmpStr2);

//方法 3: 桁数を増やす
String^ tmpStr3 = "値: " + value.ToString("F6");
Console::WriteLine(tmpStr3);

コードのフォーマット命令



.NET および std str のトランスコーディングで文字化けが発生する

理由

C++/CLIでは、gcnew System::String(stdStr.c_str())意思std::string(いつものANSI / UTF-8エンコード) を .NET に直接System::String、そしてSystem::String期待はUTF-16
もしstdStrASCII 以外の文字(中国語など)が含まれる場合、文字化けが発生します。

解決策 1: 使用するmarshal_as(提案)

名前空間は引用符で囲む必要があります。

#include 
名前空間 msclr::interop を使用します。

std::string stdStr = "中国語テスト";
System::String^ netStr = marshal_as<System::String^>(stdStr);

✅ この方法は、UTF-8 / ANSI を .NET Unicode に正しく自動的に変換できます。

---

解決策 2: std::string が UTF-8 であることが確実な場合は、手動で変換できます

#include 
#include <ロケール>

std::string utf8Str = u8"中国語テスト";
std::wstring WideStr = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>{}.from_bytes(utf8Str);
System::String^ netStr = gcnew System::String(wideStr.c_str());
---

解決策 3: ソースが次の場合std::wstring

C++ 側で元々ワイド文字列を使用している場合は、それを直接使用します。

std::wstring wstr = L"中国語テスト";
System::String^ netStr = gcnew System::String(wstr.c_str());
---

提案



.NET List

基本的な紹介

.NET (C++/CLI、C#、VB.NET などの言語) では、List<T>は一般的なコレクション カテゴリです。 あらゆるタイプのデータ (T) を保存でき、動的なサイズ変更機能を提供します。 それはに属しますSystem::Collections::Generic名前空間。

宣言と初期化

// 名前空間をインポートする
名前空間システムを使用します。
名前空間 System::Collections::Generic を使用します。

int main()
{
    // int を格納するリストを宣言します
    List<int>^ 数値 = gcnew List<int>();

    //初期化中に要素を直接追加します
    List<String^>^ names = gcnew List<String^>({ "アリス", "ボブ", "チャーリー" });
}

要素の追加、削除、アクセス

List<int>^ nums = gcnew List<int>();

// 新しい要素を追加
nums->Add(10);
数値->加算(20);
数値->追加(30);

//指定位置に挿入
nums->挿入(1, 15); // インデックス 1 に 15 を挿入します

//指定された値を削除
nums->削除(20);

//指定されたインデックスを削除します
nums->RemoveAt(0);

// 要素を取得する
int 値 = nums[1]; // インデックス 1 の要素を取得します

// が含まれているかどうかを確認します
if (数値->次を含む(30))
    Console::WriteLine("見つかった 30");

// すべての要素をクリア
nums->Clear();

トラバースリスト

// for ループ
for (int i = 0; i Count; i++)
{
    Console::WriteLine("{0} 番目の要素: {1}", i, nums[i]);
}

// ループごとに
それぞれ (int n in nums)
{
    コンソール::WriteLine(n);
}

共通のプロパティとメソッド

プロパティ/メソッド説明する
Count現在の要素数
Capacity内部容量 (自動的に拡張可能)
Add(item)要素を追加する
AddRange(collection)別のコレクションのすべての要素を結合する
Insert(index, item)指定した位置に要素を挿入
Remove(item)指定された値を削除します (最初に一致した値が見つかりました)
RemoveAt(index)指定されたインデックスにある要素を削除します
Clear()すべての要素を削除する
Contains(item)指定した値が含まれているか確認する
IndexOf(item)要素のインデックスを返します (要素が存在しない場合は -1)
Sort()要素の並べ替え (比較可能なタイプの場合)
Reverse()要素の順序を逆にする

出力例

10
15
30


.NET Dictionary

基本的な紹介

.NET (C++/CLI、C#、VB.NET などの言語) では、Dictionary<TKey, TValue>一般的なコレクションです。 「キーと値のペア」を保存するために使用されます。各キーは一意である必要があり、値は反復可能である必要があります。 それはに属しますSystem::Collections::Generic名前空間。

宣言と初期化

// 名前空間をインポートする
名前空間システムを使用します。
名前空間 System::Collections::Generic を使用します。

int main()
{
    // キーを int、値を String としてディクショナリを作成します
    Dictionary<int, String^>^ users = gcnew Dictionary<int, String^>();

    // 直接初期化
    users->Add(1, "アリス");
    ユーザー ->追加(2, "ボブ");
    users->Add(3, "チャーリー");

    0を返します。
}

要素の追加、変更、削除、およびアクセス

Dictionary<String^, int>^ 年齢 = gcnew Dictionary<String^, int>();

// 新しい要素を追加
年齢->Add("トム", 25);
年齢->Add("ジェリー", 30);

//値を変更します(インデクサー経由)
年齢["トム"] = 26;

// 追加または変更 (キーが存在しない場合は自動的に追加されます)
年齢["スパイク"] = 40;

// 要素を削除
年齢->削除(「ジェリー」);

//要素にアクセスする
if (年齢->ContainsKey("トム"))
{
    Console::WriteLine("トムの年齢は {0}"、年齢["トム"]);
}

// 値の取得を試みます (例外を回避します)
年齢;
if (年齢->TryGetValue("スパイク", 年齢))
{
    Console::WriteLine("スパイクの年齢は {0}", 年齢);
}

トラバース辞書

Dictionary<int, String^>^ users = gcnew Dictionary<int, String^>();
users->Add(1, "アリス");
ユーザー ->追加(2, "ボブ");
users->Add(3, "チャーリー");

// KeyValuePair ループを使用する
それぞれ (ユーザーの KeyValuePair エントリ)
{
    Console::WriteLine("キー = {0}、値 = {1}"、entry.Key、entry.Value);
}

//キーのみを取得する
それぞれ (ユーザーの int キー -> キー)
{
    Console::WriteLine("キー: {0}", key);
}

//値のみを取得する
それぞれ (ユーザー内の文字列 ^ 名前 -> 値)
{
    Console::WriteLine("名前: {0}", 名前);
}

共通のプロパティとメソッド

プロパティ/メソッド説明する
Add(key, value)新しいキーと値のペアのセットを追加します
Remove(key)指定されたキーとそれに対応する値を削除します
Clear()すべてのプロジェクトをクリアする
ContainsKey(key)指定されたキーが存在するかどうかを確認する
ContainsValue(value)指定された値が存在するかどうかを確認する
TryGetValue(key, out value)例外をスローせずに安全に値を取得します
Count辞書内の現在の要素数
Keysすべてのキーのコレクションを返します
Valuesすべての値のコレクションを返します

出力例

キー = 1、値 = アリス
キー = 2、値 = ボブ
キー = 3、値 = チャーリー
トムの年齢は26歳です
スパイクの年齢は40歳


.NET C++を使用してディレクトリ内の最新のファイルを取得する

導入

.NET C++ では、次のように使用できます。System::IOネームスペースは、ファイルとディレクトリを操作するための機能を提供します。 ディレクトリ内の最新のファイルを取得するには、すべてのファイル情報を読み取り、最終変更日を比較します。

サンプルコード

以下は、指定されたディレクトリ内の最新のファイルを取得する方法を示す完全な例です。

#include "stdafx.h"
#include 
#include 
#include 

名前空間システムを使用します。
名前空間 System::IO を使用します。
名前空間cliextを使用します。

int main()
{
    試してみる
    {
        //ディレクトリパスを指定
        String^ directoryPath = "C:\\Your\\Directory\\Path";

        // ディレクトリが存在するかどうかを確認する
        if (!Directory::Exists(ディレクトリパス))
        {
            Console::WriteLine("ディレクトリが存在しません: {0}", directoryPath);
            -1 を返します。
        }

        // ディレクトリ内のすべてのファイルを取得します
        配列^ ファイル = ディレクトリ::GetFiles(ディレクトリパス);

        // ディレクトリ内にファイルが無い場合
        if (ファイル->長さ == 0)
        {
            Console::WriteLine("ディレクトリにファイルがありません。");
            0を返します。
        }

        // 最新のファイルを検索します
        文字列^最新ファイル = nullptr;
        DateTime 最新時間 = DateTime::MinValue;

        それぞれ (ファイル内の文字列 ^ ファイル)
        {
            // ファイルの最終変更時刻を取得します
            DateTime lastWriteTime = File::GetLastWriteTime(file);

            // 時間を比較し、最新のファイル情報を更新します
            if (最後の書き込み時間 > 最新の時間)
            {
                最新時間 = 最終書き込み時間;
                最新ファイル = ファイル;
            }
        }

        // 最新のファイル情報を出力する
        Console::WriteLine("最新のファイル: {0}", 最新ファイル);
        Console::WriteLine("最終更新時刻: {0}", 最新時刻);
    }
    catch (例外 ^ 例)
    {
        Console::WriteLine("エラーが発生しました: {0}", ex->Message);
    }

    0を返します。
}

コードの説明

アプリケーションシナリオ

注意事項



.NET: System.Reflection

1. System.Reflection とは何ですか?

System.Reflectionこれは、メタデータを検査および操作するためのツールを提供する .NET Framework の名前空間であり、開発者が実行時に型、メソッド、プロパティなどを動的に検査し、オブジェクトを動的に作成および操作できるようにします。

2. System.Reflection の目的

3. 共通の System.Reflection カテゴリ

4. 使用例

以下は用途ですSystem.Reflection型やメソッドを動的にチェックしてメソッドを呼び出す方法を示すサンプルプログラムです。

// 簡単なサンプルクラスを定義する
パブリック クラス SampleClass {
    パブリック文字列 SayHello(文字列名) {
        return $"こんにちは、{name}!";
    }
}

// リフレクションを使用してメソッドを動的に呼び出す
システムを使用する;
System.Reflection を使用します。

クラス プログラム {
    静的 void Main() {
        //SampleClassクラスのインスタンスを作成する
        タイプサンプルタイプ = typeof(SampleClass);
        オブジェクトサンプルインスタンス = Activator.CreateInstance(サンプルタイプ);

        // SayHello メソッド情報を取得する
        MethodInfo メソッド情報 =sampleType.GetMethod("SayHello");

        // SayHello メソッドを動的に呼び出す
        object result = methodInfo.Invoke(sampleInstance, new object[] { "World" });
        Console.WriteLine(結果); // 出力: Hello, World!
    }
}

上の例では、Activator.CreateInstanceカテゴリのインスタンスを作成して使用しますMethodInfo.Invokeメソッドを呼び出すSayHello

5. 一般的なアプリケーションシナリオ



System::Management::ManagementClass

使用

System::Management::ManagementClassWindows Management Instrumentation (WMI) の操作を提供する .NET Framework のクラスの 1 つです。これにより、開発者はハードウェア、オペレーティング システム、ネットワーク設定などのシステム情報を読み取り、操作、管理できます。

名前空間

System::Management位置していますSystem.Management.dllこの関数を使用する前に、名前空間に参照を追加する必要があります。

一般的な用途

簡単な例

// C++/CLIの記述方法
名前空間システムを使用します。
名前空間 System::Management を使用します。

int main() {
    {を試してください
        ManagementClass^ mc = gcnew ManagementClass("Win32_OperatingSystem");
        for each (ManagementObject^ mo in mc->GetInstances()) {
            Console::WriteLine("OS名: {0}", mo["キャプション"]);
        }
    }
    catch (例外^ ex) {
        Console::WriteLine("エラー: {0}", ex->Message);
    }
    0を返します。
}

一般的なエラーとトラブルシューティング

関連カテゴリー



Win32_NetworkAdapterConfiguration の無効なクラス エラーを修正

エラーコードの説明

エラー コード `0x80041010` は、`System::Management::ManagementClass("Win32_NetworkAdapterConfiguration")` を使用するときに発生します。これは、WMI がクラスを見つけられないことを示します。これは通常、次のことを意味します。

解決策のステップ

Windows 10/11 用の WMI リポジトリを再作成するための完全な修正は次のとおりです。
net stop winmgmt
winmgmt /resetrepository
net start winmgmt

説明する

修理後の確認

次のいずれかの方法を使用して、修復が成功したかどうかを確認できます。方法 1: PowerShell クエリ
Get-WmiObject Win32_NetworkAdapterConfiguration
方法 2: WMI テスト ツール (wbemtest)
  1. Win + Rを押してEnterwbemtest
  2. 「接続」をクリックして入力しますroot\cimv2そして接続します
  3. 「クエリ」をクリックして入力しますSELECT * FROM Win32_NetworkAdapterConfiguration

追加の提案



.NET C++ は HTML テーブルを読み取ります

概要

.NET C++ (より一般的には C++/CLI) プロジェクトでは、ファイル内の HTML テーブルの読み取りと解析には通常、外部 HTML 解析ライブラリを使用する必要があります。これは、標準の .NET フレームワークと C++ 自体には強力な HTML DOM 解析機能が組み込まれていないためです。一般的で効率的なオプションは、C# または別の .NET 言語でライブラリを使用し、それを C++/CLI で参照することです。

C++/CLI プロジェクトの場合、最も実用的で推奨されるアプローチは、次の方法を使用することです。Html Agility Pack(HAP)、非常に人気のある .NET HTML パーサー。 HAP は C# で書かれていますが、C++/CLI を含むあらゆる .NET 言語のリファレンスとしてシームレスに使用できます。

HTML Agility Pack を使用する手順

  1. C++/CLI プロジェクトを作成します。プロジェクトが C++/CLI プロジェクトであることを確認してください (例: CLR コンソール アプリケーションまたは Windows フォーム アプリ)。
  2. HTML アジリティ パックを入手:
  3. プログラム コードの実装 (C++/CLI):

コード例

以下は、ローカル HTML ファイルを読み取り、その中の最初のテーブルを解析する方法を示す C++/CLI コード スニペットです (<table>) コンテンツ:

# を使用します;
#using 
#<HtmlAgilityPack.dll> を使用します。 // 参照が含まれていることを確認してください

名前空間システムを使用します。
名前空間 System::IO を使用します。
名前空間 HtmlAgilityPack を使用します。

void ParseHtmlTable(String^ filePath)
{
    // ファイルが存在するかどうかを確認します
    if (!File::Exists(filePath))
    {
        Console::WriteLine("エラー: ファイルが存在しません。");
        戻る;
    }

    // 1. HTML ファイルを読み込みます
    HtmlDocument^ doc = gcnew HtmlDocument();
    試してみる
    {
        //ファイルからHTMLをロード
        doc->Load(ファイルパス);
    }
    catch (例外 ^ 例)
    {
        Console::WriteLine("ファイルのロード中にエラーが発生しました: " + ex->Message);
        戻る;
    }

    // 2. 最初の <table> を選択します。ノード
    HtmlNode^ table = doc->DocumentNode->SelectSingleNode("//table");

    if (テーブル != nullptr)
    {
        Console::WriteLine("HTML テーブルを見つけて解析を開始します...");

        // 3. すべてを選択 <tr> (テーブル列) ノード
        HtmlNodeCollection^ rows = table->SelectNodes(".//tr");

        if (行数 != nullptr)
        {
            それぞれ (HtmlNode^ 行の行)
            {
                // 4. <td> を選択します。または  (セル) ノード
                // | を使用します。演算子で <td> を選択します。または 
                HtmlNodeCollection^ セル = row->SelectNodes("td | th");

                if (セル != nullptr)
                {
                    文字列^ rowData = "";
                    それぞれ (セル内の HtmlNode^ セル)
                    {
                        // セルの内部テキストを取得し、先頭と末尾の空白を削除します
                        rowData += cell->InnerText->Trim() + "\t";
                    }
                    Console::WriteLine(rowData);
                }
            }
        }
        それ以外の場合
        {
            Console::WriteLine("<tr> タグがテーブルに見つかりません。");
        }
    }
    それ以外の場合
    {
        Console::WriteLine("<table> タグがファイル内に見つかりません。");
    }
}

int main(配列^ args)
{
    // 「your_html_file.html」を実際のファイル パスに置き換えてください
    String^ htmlFilePath = "C:\\path\\to\\your_html_file.html";
    ParseHtmlTable(htmlFilePath);
    0を返します。
}

技術ポイントの解説



.NET C++ HTTP API サーバー

HttpListener クラスの使用

HttpListenerクラスを使用すると、C++/CLI アプリケーションでシンプルな自己ホスト型 HTTP サーバーを作成できます。

プロジェクトの要件と設定

Visual Studio で C++/CLI プロジェクト (CLR コンソール アプリケーションなど) を作成し、それが参照されていることを確認します。System.dll

コード例

以下が使用されますHttpListener単純な API サーバーを作成し、GET リクエストを処理するための C++/CLI コード。

# を使用します;

名前空間システムを使用します。
名前空間 System::Net を使用します。
名前空間 System::Threading::Tasks を使用します。
名前空間 System::Text を使用します。

// 受信した HTTP リクエストを処理する関数
void HandleRequest(HttpListenerContext^ context)
{
    HttpListenerRequest^ request = context->Request;
    HttpListenerResponse^ 応答 = context->Response;

    //デフォルトの応答設定
    応答->ContentType = "アプリケーション/json; charset=utf-8";
    文字列^ 応答文字列 = "";
    応答->ステータスコード = 200; // デフォルトでOK

    // 要求されたパスとメソッドを確認します
    String^ url = request->RawUrl->ToLower();
    
    if (url == "/api/status" && request->HttpMethod == "GET")
    {
        // GET /api/status リクエストを処理します
        responseString = "{\"ステータス\": \"サーバー実行中\", \"言語\": \"C++/CLI\"}";
    }
    それ以外の場合
    {
        // 他の未定義リクエストを処理します
        応答->ステータスコード = 404; // 見つかりません
        responseString = "{\"error\": \"404 Not Found\", \"path\": \"" + URL + "\"}";
    }

    // 文字列応答をバイトに変換し、出力ストリームに書き込みます
    array<Byte>^buffer = Encoding::UTF8->GetBytes(responseString);
    応答->ContentLength64 = バッファ->長さ;
    
    試してみる
    {
        応答->出力ストリーム->書き込み(バッファー、0、バッファー->長さ);
        応答->OutputStream->Close();
    }
    キャッチ (例外^)
    {
        // 書き込みエラーを無視します。通常はクライアントが切断します
    }
}

// HttpListenerを起動する関数
void StartListener(文字列^プレフィックス)
{
    HttpListener^ リスナー = gcnew HttpListener();
    
    試してみる
    {
        リスナー->プレフィックス->追加(プレフィックス);
        リスナー->Start();
        Console::WriteLine("C++/CLI API サーバーが開始されました、リッスン: {0}"、プレフィックス);
    }
    catch (例外 ^ 例)
    {
        Console::WriteLine("HttpListener の起動中にエラーが発生しました。アクセス許可またはアドレスが占有されていないか確認してください。");
        Console::WriteLine("エラー メッセージ: {0}", ex->Message);
        戻る;
    }

    // 非同期ループ、リクエストを受信し続ける
    while (リスナー -> IsListening)
    {
        試してみる
        {
            // 次のリクエストを同期的に待ちます
            HttpListenerContext^ context =listener->GetContext();
            
            // リスニング ループのブロックを避けるために、タスクを使用してリクエストを非同期に処理します
            Task::Factory->StartNew(gcnew Action<HttpListenerContext^>(&HandleRequest), context);
        }
        キャッチ (例外 ^)
        {
            // リスナーが停止すると例外がスローされます
            休憩;
        }
    }
    
    if (リスナー->IsListening)
    {
        リスナー->Close();
    }
}

int main(配列^ args)
{
    // 監視用の URL プレフィックスを設定します
    // 注: Windows では、管理者権限、または netsh を使用して URL 名前空間を登録することが必要な場合があります。
    文字列^ listenPrefix = "http://localhost:8080/";
    StartListener(listeningPrefix);
    
    Console::WriteLine("任意のキーを押してサーバーを終了します...");
    コンソール::ReadKey(true);
    
    0を返します。
}

実行権限に関する注意事項

Windows システムでは、コードが管理者権限で実行されていない場合、HttpListener特定のポートをリッスンすると、アクセス拒否例外がスローされる場合があります。次のコマンドを使用して、URL 名前空間を登録して、管理者以外のアカウントがサーバーを実行できるようにすることができます。


netsh http add urlacl url=http://+:8080/ user=Everyone

http://+:8080/コードで使用されている実際のプレフィックスに置き換える必要があります。



ASP.NET Core C# HTTP API サーバー

概要

ASP.NET Core では、HTTP API サーバーを作成するための標準プロジェクト タイプは Web API です。最新の .NET バージョン (.NET 6 以降) を推奨Minimal APIsAPI エンドポイントを迅速かつ軽量に作成します。

最小限の API は、最小限のファイルとコード行を使用して、起動ロジック (Startup) とルーティング定義 (Routing) を 1 つのファイルに結合します。Program.cs真ん中。

プロジェクトのセットアップ (CLI を使用)

新しい Minimal API プロジェクトを作成するには、.NET CLI (コマンド ライン インターフェイス) を使用できます。


dotnet new web -n MinimalApiServer
cd MinimalApiServer

プログラムコード例:Program.cs

以下は最小限の API サーバーのコア ファイルです。Program.cs完全な内容。これは、サーバーの起動、ミドルウェア、および 2 つの API エンドポイント (1 つの GET、1 つの POST) を定義します。

// 1. WebApplication インスタンスを作成します (従来の Startup カテゴリを置き換えます)
var builder = WebApplication.CreateBuilder(args);

// 2. サービスの登録 (サービス構成)
//ここでデータベース接続、検証サービスなどを追加できます。
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); // Swagger/OpenAPI サポートを有効にする

var app = builder.Build();

// 3. HTTP リクエスト パイプラインの構成 (ミドルウェア構成)

// 開発環境で、テスト用に Swagger UI を有効にします
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// HTTPS リダイレクトを有効にする (運用環境に推奨)
// app.UseHttpsRedirection();

// 4. APIエンドポイントを定義する(エンドポイント定義)
// POSTリクエストに使用されるエンティティクラス
パブリック レコード Product(int Id, string Name, 10 進価格);

// GET リクエストのエンドポイント: /api/hello
app.MapGet("/api/hello", () =>
{
    return Results.Ok(new { message = "ASP.NET Core Minimal API からこんにちは!", timestamp = DateTime.Now });
});

// GET リクエスト エンドポイント: /api/products/{id}
app.MapGet("/api/products/{id}", (int id) =>
{
    // データベースから製品をクエリすると仮定します
    if (id == 1)
    {
        return Results.Ok(new Product(1, "ラップトップ", 1200.00m));
    }
    return Results.NotFound(new { error = $"製品 ID {id} が見つかりません" });
});

// POST リクエストのエンドポイント: /api/products
app.MapPost("/api/products", (製品 product) =>
{
    // ASP.NET Core は、JSON リクエスト本文を Product エンティティに自動的に逆シリアル化します。
    Console.WriteLine($"新製品を受け取りました: {product.Name} (ID: {product.Id})");
    
    //実際のアプリケーションではここでデータベースの追加操作を行います。
    //Return 201 作成されたステータスコード
    return Results.Created($"/api/products/{product.Id}", product);
});

// 5. アプリケーションを起動し、HTTP リクエストのリッスンを開始します。
app.Run();

実行とテスト

  1. サーバーを実行します。プロジェクトディレクトリで実行dotnet run
  2. テストエンドポイント:通常、サーバーはデフォルトで次のように設定されますhttp://localhost:5000またはhttps://localhost:7000走る。

技術的なポイント



Chromebook で .NET プログラムを実行する方法

1. Chromebook の Linux サポートを使用して .NET を実行する

最新の Chromebook のほとんどは、Crostini プロジェクトを通じて Linux アプリケーションの実行をサポートしています。

  1. Linux 機能を有効にします。
  2. .NET SDKをインストールします。
  3. ターミナルで .NET アプリケーションをコンパイルして実行します。

2. クラウド開発環境を利用する

クラウド プラットフォームを使用すると、ソフトウェアをローカルにインストールしなくても、Chromebook で .NET プログラムを実行できます。

3. Docker コンテナを使用して .NET を実行する

Chromebook はアプリケーションを実行するためのコンテナの使用をサポートしており、Docker を通じて .NET 環境を開始できます。

  1. Linux 環境に Docker をインストールします。
  2. .NET コンテナー イメージをダウンロードします。
    docker pull mcr.microsoft.com/dotnet/runtime:7.0
  3. コンテナ内で .NET プログラムを実行します。

4. クロスプラットフォームサポートを使用する

.NET 6 以降、アプリケーションは Linux を含む複数のプラットフォームで実行できるようになりました。アプリをクロスプラットフォーム形式にコンパイルし、Chromebook にデプロイします。

  1. 任意のマシンでアプリケーションをコンパイルします。
    dotnet publish -c Release -r linux-x64 --self-contained
  2. コンパイルされたアーカイブを Chromebook に転送し、付属のランタイムを使用して実行します。

注意事項



.NET UIプログラミング

主要技術

単純な WinForms の例

システムを使用する;
System.Windows.Forms を使用します。

パブリック クラス MyForm : フォーム {
    パブリック MyForm() {
        ボタン btn = 新しい Button();
        btn.Text = "クリックしてください";
        btn.Click += (s, e) => MessageBox.Show("ボタンをクリックしました!");
        Controls.Add(btn);
    }

    [STAスレッド]
    静的 void Main() {
        Application.EnableVisualStyles();
        Application.Run(new MyForm());
    }
}

単純な WPF の例 (XAML + C#)

// MainWindow.xaml
<ウィンドウ x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        タイトル="WPF の例" 高さ="200" 幅="300">
    <スタックパネル>
        <Button Content="クリックしてください" Click="Button_Click"/>
    </StackPanel>
</ウィンドウ>

// MainWindow.xaml.cs
private void Button_Click(オブジェクト送信者, RoutedEventArgs e) {
    MessageBox.Show("ボタンをクリックしました!");
}

簡単な MAUI の例

// MainPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             x:Class="MyApp.MainPage">
    <VerticalStackLayout Spacing="25" Padding="30">
        <ボタンテキスト="クリックしてください" Clicked="OnButtonClicked"/>
    </VerticalStackLayout>
</ContentPage>

// MainPage.xaml.cs
private void OnButtonClicked(オブジェクト送信者, EventArgs e) {
    await DisplayAlert("通知", "ボタンをクリックしました!", "OK");
}

UIテクノロジー選択のアドバイス

テクノロジー 使用 プラットフォーム
WinForms デスクトップアプリケーションを迅速に開発する Windows
WPF 複雑なデスクトップ アプリケーション、MVVM パターン Windows
MAUI クロスプラットフォーム アプリケーション Windows、macOS、Android、iOS
Blazor Webフロントエンド開発 クロスプラットフォーム (Web)


.NET は子コントロールを走査してプロパティをバッチで変更します

次の例は、使用方法を示していますControls->GetEnumerator().NET フォーム内のすべての子コントロールを 1 つずつ反復処理し、それらのプロパティをバッチで変更するメソッド。

サンプルコード:

システムを使用する;
System.Drawing を使用します。
System.Windows.Forms を使用します。

パブリック クラス FormExample : フォーム
{
    public FormExample()
    {
        //いくつかのコントロールを初期化します
        ボタン button1 = 新しいボタン { テキスト = "ボタン 1"、場所 = 新しいポイント(10, 10) };
        TextBox textBox1 = 新しい TextBox { 場所 = 新しいポイント(10, 50) };
        
        Controls.Add(button1);
        Controls.Add(textBox1);

        // GetEnumerator() を使用してコントロールのプロパティを走査して変更します
        ModifyControls();
    }

    private void ModifyControls()
    {
        var enumerator = Controls.GetEnumerator();
        
        while (列挙体.MoveNext())
        {
            制御 control = (Control)enumerator.Current;

            // 設定例:すべてのコントロールの背景色を水色に設定
            control.BackColor = Color.LightBlue;
            
            // コントロール項目が TextBox の場合、編集不可にします
            if (コントロールは TextBox)
            {
                control.Enabled = false;
            }
        }
    }
    
    // アプリケーションを起動する
    パブリック静的 void Main()
    {
        Application.Run(new FormExample());
    }
}

説明する

**GetEnumerator()**: `Controls.GetEnumerator()` メソッドを使用してコントロール項目の列挙子を取得し、すべての子コントロールを走査できるようにします。

**条件付き変更**: `while` ループで、背景色を水色に設定するなど、各 `Control` オブジェクトのプロパティを変更し、コントロールの種類に基づいて特定の変更を加えます (たとえば、`TextBox` を編集不可に設定します)。

**使用方法**: この方法は、UI スタイルの調整や特定の状況下での複数のコントロールの無効化など、プロパティをバッチで変更する必要がある場合に非常に効果的です。

実行効果

実行後、すべてのコントロールの背景色が水色に変わり、すべての `TextBox` コントロールが編集不可に設定されます。



.NET MessageBox

1. 基本的な構文と一般的なオーバーロード

C++/CLIでは、MessageBox::Showこれは、ダイアログ ボックスをポップアップするために使用される静的メソッドです。最も完全な呼び出し方法には、メッセージの内容、タイトル、ボタンの種類、アイコン、デフォルトのボタンが含まれます。

名前空間 System::Windows::Forms を使用します。

// 最も単純な表示
MessageBox::Show("操作が完了しました");

// パラメータの完全なバージョン
DialogResult 結果 = MessageBox::Show(
    "このファイルを削除してもよろしいですか?", // メッセージ内容(テキスト)
    "削除の確認", // ウィンドウのタイトル (キャプション)
    MessageBoxButtons::YesNo, // ボタンの組み合わせ
    MessageBoxIcon::Warning, // プロンプト アイコン
    MessageBoxDefaultButton::Button2 // デフォルトのフォーカスは 2 番目のボタンにあります (いいえ)
);

2. 戻り値の処理(DialogResult)

ボタンに「はい/いいえ」や「OK/キャンセル」などの複数のオプションが含まれている場合はチェックする必要があります。DialogResultその後のロジックを決定します。

if (result == DialogResult::Yes) {
    //削除ロジックを実行する
} それ以外の場合は {
    // 操作をキャンセルします
}

3. 共通の列挙値参照

カテゴリ 共通オプション 説明する
MessageBoxButtons OK, OKCancel, YesNo, YesNoCancel ダイアログ ボックスの下に表示されるボタンを定義します。
MessageBoxIcon Information, Warning, Error, Question 左側に表示されるアイコンとシステム効果音を定義します。
DialogResult OK, Cancel, Yes, No Showメソッドの戻り値は、ユーザーがどのキーを押したかを表します。

4. 高度なテクニック: std::string または float を組み合わせる

なぜならMessageBox::Show受信したのは .NETSystem::String^ネイティブ C++ データがある場合は、それを変換する必要があります。

#include <文字列>
#include 

// メッセージボックスに std::string を表示します
std::string cpp_str = "コアエラー";
MessageBox::Show(msclr::interop::marshal_as<System::String^>(cpp_str));

//フロートをフォーマットして表示します
浮動小数点距離 = 1.23456f;
MessageBox::Show("距離は次のとおりです: " + dist.ToString("F2")); // 「距離は 1.23」と表示します

よくあるエラーと解決策



.NET カスタム入力ダイアログ ボックス

1. MessageBox が編集ボックスをサポートしていないのはなぜですか?

System::Windows::Forms::MessageBox「通知」または「警告」を表示し、標準ボタンを介してユーザーの決定を取得するように設計されています。動的に制御項目を挿入する機能はありません。テキストを入力する必要がある場合、標準的なアプローチは次のように継承します。System::Windows::Forms::Formカスタム ダイアログ ボックスを作成します。


2.カスタムInputBoxを実装する

これは、ラベル、テキスト ボックス、および [OK] ボタンを含む、シンプルで再利用可能なカテゴリです。

名前空間システムを使用します。
名前空間 System::Windows::Forms を使用します。
名前空間 System::Drawing を使用します。

パブリック ref クラス CustomInputBox : public Form {
パブリック:
    テキストボックス^ txt入力;
    ボタン^ btnOK;
    ラベル^ lblプロンプト;

    CustomInputBox(文字列^タイトル、文字列^プロンプト) {
        // フォームの基本プロパティを設定します
        this->テキスト = タイトル;
        this->Size = System::Drawing::Size(300, 150);
        this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog;
        this->StartPosition = FormStartPosition::CenterParent;
        this->MaximizeBox = false;
        this->MinimizeBox = false;

        // プロンプトテキスト
        lblPrompt = gcnew Label();
        lblプロンプト->テキスト = プロンプト;
        lblプロンプト->場所 = ポイント(15, 15);
        lblPrompt->Size = System::Drawing::Size(250, 20);

        // 入力ボックス
        txtInput = gcnew TextBox();
        txtInput->Location = ポイント(15, 40);
        txtInput->Size = System::Drawing::Size(250, 20);

        // OKボタン
        btnOK = gcnew Button();
        btnOK->テキスト = "OK";
        btnOK->DialogResult = System::Windows::Forms::DialogResult::OK;
        btnOK->位置 = ポイント(190, 75);
        
        // コントロールを追加します
        this->コントロール->追加(lblプロンプト);
        this->コントロール->追加(txtInput);
        this->コントロール->追加(btnOK);
        
        // デフォルトのボタンを設定します (Enter キーを押すことは、「OK」をクリックすることと同じです)
        this->AcceptButton = btnOK;
    }
};

3. メインプログラムでの呼び出し方法

使用ShowDialog()このメソッドは強制応答モードでウィンドウを開き、戻り値がOK

void OnButtonClick() {
    CustomInputBox^ ibox = gcnew CustomInputBox("システム入力", "ファイル名を入力してください:");
    
    if (ibox->ShowDialog() == System::Windows::Forms::DialogResult::OK) {
        文字列^ userInput = ibox->txtInput->Text;
        
        if (!String::IsNullOrWhiteSpace(userInput)) {
            // ユーザーが入力した文字列を処理します
            MessageBox::Show("入力しました: " + userInput);
        }
    }
}

4. プラン比較

プラン 実装の複雑さ アドバンテージ 欠点がある
カスタムフォーム 真ん中 レイアウトを完全に制御し、検証ロジックを追加する機能 (制限された数など)。 さらにインターフェイス コードを記述する必要があります。
VB Interaction 低い 1行のコードが完成しました。 引用する必要がありますMicrosoft.VisualBasic、スタイルは固定されており、調整することはできません。
Win32 API 高い .NET環境は必要ありません。 C++/CLI での開発は非常に簡単であり、保守が困難です。

よくある落とし穴



PictureBox 赤十字エラー

現象の説明

PictureBox には赤い十字が表示され、OnPaint実行中に例外が発生しました。 ただし、.NET はデフォルトでこの例外を無視し、一般ログや中断ポイントに表示しないため、デバッグが困難になります。

よくある原因

理由 説明する
ビットマップは破棄されました PictureBox はビットマップへの参照を保持しており、解放されたリソースはペイント中にアクセスされます。
ソースストリームが閉じられています ストリームを使用してビットマップを作成し、ストリームを閉じると、ビットマップ データは無効になります。
クロススレッドアクセス バックグラウンド スレッドはビットマップを直接変更または割り当てますが、これは UI スレッドと競合します。
GDI+ リソースの枯渇 大量のビットマップが破棄されないため、GDI+ メモリが不足します

エラーメッセージの比較

例外メッセージ 根本的な原因 ソリューションの方向性
ArgumentException: Parameter is not valid ビットマップが破棄されたか、ストリームが閉じられました ビットマップのディープコピー、ストリームに依存しない
InvalidOperationException: object is in use elsewhere スレッド間で同時に同じビットマップにアクセス ロックを追加するか、UI スレッドに戻って呼び出します
OutOfMemoryException GDI+ リソースが枯渇しているか、画像形式がサポートされていません 古いビットマップを速やかに破棄し、画像ソースを確認してください。
ExternalException: A generic error occurred in GDI+ ビットマップに対応するファイルまたはストリームは存在しません ソースがビットマップの有効期間中有効であることを確認する

デバッグ手順

赤十字の問題は頻繁には発生しないため、次の順序で進めることをお勧めします。

  1. OnPaint 例外のインターセプト: PictureBox を継承、オーバーライドOnPaint、 try/catch を使用して例外をキャッチし、それらを出力します。Debug.WriteLine、 キャプチャ後に実行this.Image = null執拗な赤十字を避けてください。
  2. 例外メッセージを確認する: Visual Studio の [出力] ウィンドウのメッセージを確認します。 根本原因を見つけるには、上記のエラー メッセージの表を確認してください。
  3. ビットマップのライフサイクルの追跡: Dispose Bitmap に割り当てられるたびに、 記録するEnvironment.StackTrace、誰がどの時点でリソースをリリースしたかを調べます。
  4. まだ使用中のビットマップの破棄を防止する: 廃棄する前に確認してください PictureBox がまだビットマップを保持しているかどうか (保持している場合は、最初に)Imagenull に設定してから破棄します。

安全な画像変更モード

すべてのイメージ変更操作は、スレッドの安全性と正しい破棄順序を確保するために、このモードを通じて実行されます。

// C++/CLI
void SafeUpdateImage(Bitmap^ newBmp) {
    if (pictureBox1->InvokeRequired) {
        pictureBox1->Invoke(gcnew アクション<ビットマップ^>(
            this、&YourClass::SafeUpdateImage)、newBmp);
        戻る;
    }
    ビットマップ ^ old = safety_cast<ビットマップ ^>(pictureBox1->Image);
    PictureBox1->画像 = newBmp; // 最初に新しい画像に変更します
    if (old != nullptr) old->Dispose(); // 古い画像を再度破棄します
}

ストリームからビットマップを作成する正しい方法

// エラー: ストリームが閉じられた後はビットマップが無効です
using (var stream = new FileStream(path, FileMode.Open)) {
    pictureBox1.Image = 新しいビットマップ(ストリーム);
}

// 正解: ディープ コピー、ストリームに依存しない
ビットマップがロードされました。
using (var stream = new FileStream(path, FileMode.Open))
using (var tmp = new Bitmap(stream)) {
    ロード済み = 新しいビットマップ(tmp);
}
pictureBox1.Image = ロード済み;

トラブルシューティングのチェックリスト

チェック項目 確認方法
ビットマップが別の場所に配置されているかどうか SafeUpdateImage を通じてイメージを統合して変更し、StackTrace を記録する
ソースストリームが閉じているかどうか 代わりにディープコピーを使用してくださいnew Bitmap(tmp)
スレッドをまたいでアクセスするかどうか 画像を変更するときは InvokeRequired をチェックし、常に UI 実行スレッドに戻って呼び出します。
赤い十字はすぐに表示されますか、それともしばらくしてから表示されますか? すぐに表示される場合は、ソースに問題がある可能性があります。しばらくすると、破棄のタイミングに問題がある可能性があります。


.NET StackTrace でメッセージ m の内容を取得する

問題の背景

次のエラー メッセージがスタック トレースに表示される場合、開発者は確認する必要がある場合があります。Messageオブジェクトの内容:

   at ....MainForm.Dispose(Boolean A_0)
   at System.Windows.Forms.Form.WmClose(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   ...
    

このとき、上書きまたは検出する必要があります。WndProcメソッド内Message m詳細を確認します。

解決

確認または記録するにはいくつかの方法がありますMessageオブジェクトの内容。

1. WndProc メソッドをオーバーライドします。

フォームまたはコントロールのソース コードにアクセスできる場合は、上書きすることをお勧めします。WndProc直接記録または確認する方法Message mコンテンツ。

protected オーバーライド void WndProc(ref Message m)
{
    試してみる
    {
        //メッセージの内容を記録する
        Console.WriteLine($"メッセージの詳細: hWnd={m.HWnd}, Msg={m.Msg}, WParam={m.WParam}, LParam={m.LParam}");
        Base.WndProc(ref m);
    }
    catch (例外例)
    {
        Console.WriteLine($"例外: {ex}");
        投げる; // 元の例外動作を維持する
    }
}
    

このコードは、メッセージを受信するたびに関連情報をログに記録し、開発者がメッセージをさらに分析できるようにします。

2. Dispose メソッドに例外処理を追加する

エラーが発生した場合Disposeメソッド内に例外処理を追加して、関連情報を確認できます。

protected オーバーライド void Dispose(bool 破棄)
{
    試してみる
    {
        もし(処分するなら)
        {
            // リソースを解放する
        }
        Base.Dispose(処分);
    }
    catch (例外例)
    {
        Console.WriteLine($"Dispose の例外: {ex}");
        投げる;
    }
}
    

これにより、リソースを解放するときに重要なエラー情報が無視されなくなります。

3. グローバル例外処理を使用する

エラーが発生した場所を特定できない場合は、グローバル例外処理を使用してスタック トレースと関連情報を記録できます。


AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
    Exception ex = (Exception)args.ExceptionObject;
    Console.WriteLine($"Unhandled Exception: {ex}");
    Environment.Exit(1);
};

    

4. デバッグツールを使用してメッセージを確認します。

Visual Studio を使用してブレークポイントを設定できます。WndProcまたはDispose方法とチェックMessageオブジェクトの内容。

Message オブジェクトの主要なプロパティ

注意事項



.NET C++ での Form.WmClose(Message& m) のオーバーライド

問題の背景

.NET C++/CLI では、WmClose(Message& m)はいSystem.Windows.Forms.Form内部保護方式を直接上書きすることはできません。ただし、オーバーライドすることは可能ですWndProcインターセプトして処理する方法WM_CLOSE同様のオーバーライドを実現するためのメッセージWmClose効果。

完全な例

#include 
#include 

名前空間システムを使用します。
名前空間 System::Windows::Forms を使用します。

パブリック参照クラス CustomForm : パブリック フォーム
{
保護されています:
    // WmClose 動作のオーバーライドをシミュレートします
    void WmClose(Message% m)
    {
        // ここにカスタム WM_CLOSE 動作を追加します
        if (MessageBox::Show("ウィンドウを閉じてもよろしいですか?", "確認", MessageBoxButtons::YesNo) == DialogResult::Yes)
        {
            // 正常なシャットダウンの基本動作の呼び出しを継続します
            this->Form::WndProc(m);
        }
        それ以外の場合
        {
            // ウィンドウが閉じないようにする
            戻る;
        }
    }

    // WndProc をオーバーライドし、WM_CLOSE メッセージをインターセプトして WmClose を呼び出します
    仮想 void WndProc(Message% m) オーバーライド
    {
        const int WM_CLOSE = 0x0010;

        if (m.Msg == WM_CLOSE)
        {
            WmClose(m); // カスタムの WmClose メソッドを呼び出します
        }
        それ以外の場合
        {
            // 他のメッセージを処理する
            フォーム::WndProc(m);
        }
    }
};

[STAスレッド]
int main(配列^ args)
{
    Application::EnableVisualStyles();
    Application::SetCompatibilityTextRenderingDefault(false);

    CustomForm^ form = gcnew CustomForm();
    form->Text = "WmClose 動作の例をオーバーライド";
    アプリケーション::実行(フォーム);

    0を返します。
}
    

コードの説明

1.WmCloseメソッド

上書きをシミュレートするWmCloseここでウィンドウを閉じる動作をカスタマイズする方法。確認ダイアログ ボックスを使用して、ウィンドウを閉じるかどうかをユーザーに尋ねます。

2. WndProc をオーバーライドする

上書きするWndProc傍受する方法WM_CLOSEメッセージを送信し、カスタムに委任しますWmClose方法。

3. 他のメッセージの処理を続行します

傍受なしでWM_CLOSE基底クラスを呼び出す場合WndProc他のメッセージを処理するメソッド。

注意事項



System::Windows::Forms::Control::InvokeRequired

使用説明書

InvokeRequiredはいSystem::Windows::Forms::Controlこの属性は、現在の実行スレッドがコントロール項目が属する UI 実行スレッドであるかどうかを判断するために使用されます。バックグラウンド スレッドから UI コントロールにアクセスする場合は、次を使用する必要があります。Invoke操作を UI スレッドにマーシャリングして戻します。

完全な例: PictureBox 画像の設定

名前空間システムを使用します。
名前空間 System::Windows::Forms を使用します。
名前空間 System::Drawing を使用します。

ref クラス ImageHelper {
パブリック:
    static void SetImageSafe(PictureBox^ pPictureBox, Bitmap^ b) {
        if (pPictureBox == nullptr)
            戻る;

        if (pPictureBox->InvokeRequired) {
            // MethodInvoker を使用して同じ関数を呼び出しますが、UI スレッドで実行します
            pPictureBox->Invoke(
                gcnew MethodInvoker(gcnew アクション(ImageHelper::InvokeCallback), 
                gcnew Tuple(pPictureBox、b))
            );
        } それ以外の場合は {
            適用画像(pPictureBox, b);
        }
    }

プライベート:
    // マーシャリングされた関数プロキシ
    static void InvokeCallback(Object^ state) {
        タプル^ args = static_cast^>(状態);
        applyImage(args->Item1, args->Item2);
    }

    // 設定イメージロジックの実際の実行
    static void applyImage(PictureBox^ pPictureBox, Bitmap^ b) {
        {を試してください
            if (b != nullptr) {
                if (pPictureBox->画像 != nullptr)
                    pPictureBox->画像を削除します。
                pPictureBox->画像 = b;
            }
        }
        catch (System::Exception^ ex) {
            Console::WriteLine("画像の設定に失敗しました: " + ex->Message);
        }
    }
};

整理整頓に重点を置く



プログラムのクラッシュを避けるために、pPictureBox->Image = b を保護します。

考えられるクラッシュの原因

イメージを安全にセットアップするための推奨プラクティス


using namespace System;
using namespace System::Windows::Forms;
using namespace System::Drawing;

void SetImageSafe(PictureBox^ pPictureBox, Bitmap^ b) {
    if (pPictureBox->InvokeRequired) {
        pPictureBox->Invoke(gcnew MethodInvoker(
            gcnew EventHandler(nullptr, &SetImageInvoker)
        ), gcnew array{ pPictureBox, b });
    } それ以外の場合は {
        SetImageInternal(pPictureBox, b);
    }
}

void SetImageInvoker(Object^ 送信者, EventArgs^ e) {
    // このバージョンが使用されない場合は、無視して完全なリファレンスとして保持できます。
}

void SetImageInternal(PictureBox^ pPictureBox, Bitmap^ b) {
    {を試してください
        if (b != nullptr) {
            if (pPictureBox->画像 != nullptr)
                pPictureBox->画像を削除します。

            pPictureBox->画像 = b;
        }
    }
    catch (System::Exception^ ex) {
        Console::WriteLine("画像の設定に失敗しました: " + ex->Message);
    }
}

簡易版(匿名委任を推奨)

`pPictureBox->Image = b;` を手早く保護したいだけであれば、次の記述方法がより直接的で効果的です。
名前空間システムを使用します。
名前空間 System::Windows::Forms を使用します。
名前空間 System::Drawing を使用します。

void SafeAssignImage(PictureBox^ pPictureBox, Bitmap^ b) {
    if (pPictureBox->InvokeRequired) {
        pPictureBox->Invoke(gcnew MethodInvoker(gcnew delegate {
            {を試してください
                if (b != nullptr) {
                    if (pPictureBox->画像 != nullptr)
                        pPictureBox->画像を削除します。
                    pPictureBox->画像 = b;
                }
            } catch (System::Exception^ ex) {
                Console::WriteLine("画像の設定に失敗しました: " + ex->Message);
            }
        }));
    } それ以外の場合は {
        {を試してください
            if (b != nullptr) {
                if (pPictureBox->画像 != nullptr)
                    pPictureBox->画像を削除します。
                pPictureBox->画像 = b;
            }
        } catch (System::Exception^ ex) {
            Console::WriteLine("画像の設定に失敗しました: " + ex->Message);
        }
    }
}

追加情報



Blazor を使用して統一言語フロントエンド開発環境を確立する

ブレーザーとは何ですか?

Blazor は、Microsoft が発表したフロントエンド フレームワークで、開発者が C# および Razor 構文を使用して対話型 Web アプリケーションを作成できるようにします。 C# コードは、JavaScript を使用せずにブラウザーで実行できます。

開発者のメリット

ブレザーモード

.NETとの統合

Blazor は ASP.NET Core をシームレスに統合し、既存の .NET アプリケーションと組み合わせることができ、依存関係の挿入、ルーティング、コンポーネント アーキテクチャ、およびその他の機能をサポートします。

導入方法

まとめ

Blazor は、主なテクノロジが .NET である開発者向けに、Node.js の統合 JavaScript 言語に対応するソリューションを提供します。これにより、フロント エンドとバック エンドの両方で C# を使用できるようになり、より一貫した開発エクスペリエンスが実現されます。



.NET MAUI を使用してクロスプラットフォーム アプリケーションを構築する

.NET MAUI とは何ですか?

.NET MAUI (Multi-platform App UI) は、Microsoft によって開始されたクロスプラットフォーム アプリケーション フレームワークです。 C# と XAML を使用してコードを作成し、それを Windows、Android、iOS、さらには macOS に展開できます。

開発者のメリット

サポートされているプラ​​ットフォーム

Blazor ハイブリッド モード

.NET MAUI の Blazor ハイブリッド モードを使用すると、ネイティブ アプリケーションに Web UI を埋め込むことができ、開発者はネイティブ API にアクセスしながら、Razor コンポーネントを使用してクロスプラットフォーム ユーザー インターフェイスを開発できます。

統合と展開

まとめ

.NET MAUI は、現在最も完全な .NET クロスプラットフォーム ソリューションです。 Blazor と組み合わせることで、Web、デスクトップ、モバイル プラットフォーム向けの統合アプリケーション開発を実現し、.NET 開発者に言語とテクノロジの点で一貫したフルエンドのエクスペリエンスを提供できます。



ASP.NET Core と .NET MAUI の比較

位置

サポートプラットフォーム

開発言語

UIとインタラクション

該当するシナリオ

統合

.NET MAUI は、API 呼び出しを通じて ASP.NET Core によって作成されたバックエンド サービスと統合して、完全な「フロントエンド アプリ + バックエンド API」アーキテクチャを形成できます。

要約する

ASP.NET Core は「バックエンド サービス」と「Web アプリケーション」の問題を解決しますが、.NET MAUI は「クライアント側のクロスプラットフォーム アプリ」に焦点を当てています。この 2 つは相互に排他的ではありませんが、完全なソリューションを形成するために一緒に使用されることがよくあります。



簡単な .NET MAUI アプリケーションの例

基本的な .NET MAUI アプリケーションを構築する

以下は、.NET MAUI を使用して構築されたクロスプラットフォーム アプリケーションの例です。このアプリケーションは、クリックするとテキスト数を更新するボタンを画面上に表示します。

メインファイル: MainPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiApp.MainPage">

    <VerticalStackLayout Spacing="25" Padding="30">
        <ラベル x:Name="カウンターラベル"
               Text="まだボタンをクリックしていません"
               フォントサイズ = "24"
               horizontaloptions="Center" />

        <ボタンテキスト="クリックしてください"
                クリック済み =「オンカウンタークリック済み」
                horizontaloptions="Center" />
    </VerticalStackLayout>
</ContentPage>

バックエンド コード: MainPage.xaml.cs

名前空間MauiApp;

パブリック部分クラス MainPage : ContentPage
{
    int カウント = 0;

    パブリック MainPage()
    {
        InitializeComponent();
    }

    private void OnCounterClicked(オブジェクト送信者, EventArgs e)
    {
        カウント++;
        counterLabel.Text = $"{count} 回クリックしました";
    }
}

実行方法

まとめ

この簡単な例は、.NET MAUI のクロスプラットフォーム機能を示しています。開発者は、XAML および C# コードを 1 回記述するだけで、複数のプラットフォームで同時に実行できます。



Visual Studio で .NET MAUI プロジェクトを作成する

ステップ 1: 必要なツールをインストールする

ステップ 2: 新しい MAUI プロジェクトを作成する

  1. Visual Studioを開く
  2. 「新しいプロジェクトの作成」をクリックします
  3. 検索して選択します。.NET MAUI App"テンプレート
  4. 「次へ」をクリックし、プロジェクト名と場所を入力します。
  5. 「作成」をクリックしてプロジェクトの初期化を完了します

ステップ 3: プロジェクトの構造を理解する

ステップ 4: アプリケーションを実行する

追加情報

まとめ

Visual Studio を使用して .NET MAUI プロジェクトを作成するのに必要な手順はわずかで、1 セットのコードを同時に複数のプラットフォームにデプロイできるため、最新の C# フルエンド開発者にとって理想的な選択肢となります。



MainPage.xaml の例と説明

例: MainPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyMauiApp.MainPage">

    <VerticalStackLayout Spacing="25" Padding="30"
                         垂直オプション="中央">

        <ラベル
            Text=".NET MAUI へようこそ!"
            SemanticProperties.HeadingLevel="レベル1"
            フォントサイズ = "32"
            horizontaloptions="Center" />

        <ボタン
            x:名前="カウンターボタン"
            テキスト=「クリックしてください!」
            クリック済み =「オンカウンタークリック済み」
            horizontaloptions="Center" />

    </VerticalStackLayout>

</ContentPage>

対応するMainPage.xaml.cs

システムを使用する;
名前空間 MyMauiApp;

パブリック部分クラス MainPage : ContentPage
{
    int カウント = 0;

    パブリック MainPage()
    {
        InitializeComponent();
    }

    private void OnCounterClicked(オブジェクト送信者, EventArgs e)
    {
        カウント++;
        counterBtn.Text = $"{count} 回クリックしました";
    }
}

コンポーネントの説明

C# コードの説明

結果の効果

実行後、画面中央にウェルカムメッセージとボタンが表示されます。ボタンをクリックするたびに、ボタン上のテキストが「X 回クリックしました」に更新されます。



MauiProgram.cs の例と説明

例: MauiProgram.cs

using Microsoft.Extensions.Logging;

namespace MyMauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        
        builder
            .UseMauiApp() //アプリケーションのエントリポイントを指定します
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans- Regular.ttf", "OpenSans Regular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

#if デバッグ
        builder.Logging.AddDebug();
#endif

        builder.Build() を返します。
    }
}

機能説明

一般的な拡張子

要約する

MauiProgram.csASP.NET Core と同じようにStartup.csまたはProgram.csは、アプリケーションの起動とサービスの登録のためのメインの設定センターです。大規模な MAUI アプリケーションを開発する場合、このファイルを拡張して DI、ロギング、コンポーネント設定などを追加することが非常に一般的です。



.NET C++ プログラムを Ubuntu にデプロイする

序文

Ubuntu システムへの .NET C++ (C++/CLI または .NET ベースの C++ アプリケーション) のデプロイメントは、プロジェクトの種類に応じて個別に処理する必要があります。純粋な C++/CLI (.NET Framework に依存) を使用する場合、Linux 上で直接実行することはできないため、次を使用する必要があります。.NET 6/7/8 のクロスプラットフォーム テクノロジ(C++/CLR → C#、または .NET 相互運用性のある C++/ネイティブの使用など)。

導入の概要

アプリケーションの性質に応じて、展開は 3 つのシナリオに分類できます。

  1. 純粋な C++ アプリケーション:g++ でコンパイルされ、Ubuntu 上で直接実行されます。
  2. .NET Managed C++ (C++/CLI):.NET 6 以降でサポートされる Core 用の C# または C++/CLI 用に再設計する必要があります (Windows のみでサポート)。
  3. ハイブリッドアプリケーション:主に C#、C++ は、動的関数ライブラリ (.so) の形式でパフォーマンス モジュールを提供します。

環境のインストール

.NET SDK と必要なツールを Ubuntu にインストールします。

sudo apt update
sudo apt install -y dotnet-sdk-8.0
sudo apt install -y build-essential

(バージョンに応じて置き換え可能dotnet-sdk-8.0のためにdotnet-sdk-7.0または他のバージョン)

プロジェクトの作成

.NET C# をメイン プログラムとして使用し、C++ ライブラリを呼び出す場合:

# メインアプリケーションを作成する
dotnet 新しいコンソール -n MyApp
cdMyApp

# ネイティブ関数ライブラリを作成する
mkdir ネイティブ
CDネイティブ
ナノ追加.cpp

add.cpp の例:

extern "C" int add(int a, int b) {
    return a + b;
}

共有関数ライブラリとしてコンパイルします。

g++ -fPIC -shared -o libadd.so add.cpp

C# (.NET) での C++ ライブラリの呼び出し

Program.cs参加してください:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("libadd.so", EntryPoint="add")]
    public static extern int Add(int a, int b);

    static void Main()
    {
        Console.WriteLine("3 + 5 = " + Add(3, 5));
    }
}

実行とテスト

プロジェクトのルート ディレクトリに戻り、次を実行します。

dotnet run

出力結果が次の場合3 + 5 = 8、展開が成功したことを示します。

リリース展開バージョン

プログラムは、独立して実行可能な展開ファイルにパッケージ化できます。

dotnet publish -c Release -r linux-x64 --self-contained true

生成された実行可能ファイルは次の場所にあります。bin/Release/net8.0/linux-x64/publish/

Dockerコンテナのデプロイメント(オプション)

アプリケーションは Docker を使用してコンテナ化され、任意の Ubuntu システム上で実行できます。

# Dockerfile の例
mcr.microsoft.com/dotnet/runtime:8.0 から
WORKDIR/アプリ
コピー ./発行 .
コピー ./native/libadd.so /usr/lib/
エントリーポイント ["./MyApp"]

コンテナを構築して実行します。

docker build -t myapp .
docker run --rm myapp

注意事項

要約する

.NET C++ プログラムを Ubuntu にデプロイする実現可能な方法は通常、次のとおりです。C# + C++ ネイティブ ライブラリ” 構造。元のプログラムが C++/CLI に依存している場合は、クロスプラットフォーム .NET をサポートするように再設計する必要があります。最も推奨される方法は、Docker で .NET 8 + ネイティブ C++ モジュールを使用して、安定性、移植性、一貫性のあるデプロイメント プロセスを実現することです。




email: [email protected]
T:0000
資訊與搜尋 | 回dev首頁
email: Yan Sa [email protected] Line: 阿央
電話: 02-27566655 ,03-5924828
阿央
泱泱科技
捷昱科技泱泱企業