Visual Studio は、Microsoft によって開発された統合開発環境 (IDE) であり、C++、C#、VB.NET、Python、JavaScript などの複数のプログラミング言語をサポートしています。デスクトップ アプリケーション、Web サイト、クラウド サービス、モバイル アプリケーションの開発に適しています。
Visual Studio は Windows オペレーティング システムをサポートし、Visual Studio for Mac は macOS 用に設計されています。
[*.cs] indent_style = space indent_size = 43. ファイルが保存されると、フォーマットは自動的に次のルールに従います。
コマンド ライン ツールを使用して、コンピューターにインストールされている .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]
使用したいバージョンが表示されない場合は、まだインストールされていないことを意味します。
dotnet注文このオプションが表示されない場合は、Windows の [スタート] メニューを使用して「Developer Command Prompt for VS」を検索して開くこともできます。
Ctrl + `dotnetSDKの確認や操作を行うコマンドシステムを使用する;
クラス プログラム {
静的 void Main() {
文字列名 = "世界";
Console.WriteLine($"こんにちは、{名前}!");
}
}
(x, y) => x + yvar q = list.Where(x => x > 10);await Task.Delay(1000);CS8618 は、コンストラクターの最後で、Null不可のプロパティは初期化されていないため、C# コンパイラは、次の可能性があることを警告します。null。
パブリック クラス 製品 {
パブリック文字列名 { get;セット; } // 警告 CS8618
}
public class Product {
public string Name { get; set; }
public Product(string name) {
Name = name;
}
}
public class Product {
public string Name { get; set; } = string.Empty;
}
public class Product {
public string? Name { get; set; }
}
→ 該当するものName合理的に許されるnull状況。
required修飾子 (C# 11 以降でサポート)パブリック クラス 製品 {
public 必須文字列 Name { get;セット; }
}
// 呼び出し元を初期化する必要があります
var p = 新しい製品 { Name = "携帯電話" }; // わかりました
null:使用コンストラクタまたはrequired。null:に変更string?。string.Empty)。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);
F2:固定小数点形式、小数点以下2桁F6:固定小数点形式、小数点以下6桁F{桁}C++/CLIでは、gcnew System::String(stdStr.c_str())意思std::string(いつものANSI / UTF-8エンコード) を .NET に直接System::String、そしてSystem::String期待はUTF-16。
もしstdStrASCII 以外の文字(中国語など)が含まれる場合、文字化けが発生します。
marshal_as(提案)名前空間は引用符で囲む必要があります。
#include
名前空間 msclr::interop を使用します。
std::string stdStr = "中国語テスト";
System::String^ netStr = marshal_as<System::String^>(stdStr);
✅ この方法は、UTF-8 / ANSI を .NET Unicode に正しく自動的に変換できます。
---#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());
---
std::wstringC++ 側で元々ワイド文字列を使用している場合は、それを直接使用します。
std::wstring wstr = L"中国語テスト";
System::String^ netStr = gcnew System::String(wstr.c_str());
---
std::stringソースは UTF-8 (最近のシステムでは一般的) → 使用しますmarshal_asまたはcodecvt。gcnew String(stdStr.c_str())文字列が純粋な英語でない限り。.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 (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++ では、次のように使用できます。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を返します。
}
Directory::GetFiles指定されたディレクトリ内のすべてのアーカイブ パスを取得するメソッド。File::GetLastWriteTime各ファイルの最終変更時刻を取得するメソッド。try-catchこのブロックは、存在しないディレクトリやアクセスできないディレクトリなどの潜在的な例外をキャッチします。System.Reflectionこれは、メタデータを検査および操作するためのツールを提供する .NET Framework の名前空間であり、開発者が実行時に型、メソッド、プロパティなどを動的に検査し、オブジェクトを動的に作成および操作できるようにします。
Assembly: 読み込まれたアセンブリを表し、アセンブリの読み込み、探索、および反映のためのメソッドを提供します。Type: カテゴリ、構造、インターフェースなどを含む型を表し、型情報を取得する機能を提供します。MethodInfo: メソッド情報を表し、開発者がメソッドのプロパティを調べて動的に呼び出すことができるようにします。PropertyInfo: 属性情報を表し、属性メタデータへのアクセスを提供します。FieldInfo: フィールド情報を表し、次のタイプのフィールドにアクセスするために使用できます。以下は用途です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。
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を返します。
}
System.Management.dll参照。ManagementException。ManagementObjectManagementObjectSearcherManagementBaseObjectnet stop winmgmt winmgmt /resetrepository net start winmgmt
Get-WmiObject Win32_NetworkAdapterConfiguration方法 2: WMI テスト ツール (wbemtest)
wbemtestroot\cimv2そして接続しますSELECT * FROM Win32_NetworkAdapterConfigurationDISM /Online /Cleanup-Image /RestoreHealth修復システムイメージ.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 言語のリファレンスとしてシームレスに使用できます。
HtmlAgilityPack。以下は、ローカル 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を返します。
}
技術ポイントの解説
- C++/CLI:C++ コードが .NET Framework (CLR) と相互運用できるようにします。これは、HAP などの C# ライブラリを使用するための基礎です。
- Html Agility Pack:強力な機能を提供しますXPathサポート。
doc->Load(filePath): ローカル HTML ファイルを HAP の DOM 構造に読み込みます。
SelectSingleNode("//table"): XPath 式を使用してファイル内の最初のものを選択します<table>要素。
SelectNodes(".//tr"): 現在のノードを選択します (<table>)以下すべて<tr>要素。
SelectNodes("td | th"):選択<tr>すべてノードの下にあります<td>または<th>要素。
cell->InnerText: セルの内容のプレーンテキストを取得すると、HTML タグが自動的に削除されます。
gcnewそして^:これは、(CLR ガベージ コレクション メカニズムによって管理される) .NET オブジェクトを作成および管理するために C++/CLI によって使用される構文です。
.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();
実行とテスト
- サーバーを実行します。プロジェクトディレクトリで実行
dotnet run。
- テストエンドポイント:通常、サーバーはデフォルトで次のように設定されます
http://localhost:5000またはhttps://localhost:7000走る。
- ブラウザまたはPostmanなどのツールを使用してアクセスします
/api/hello (GET)。
- アクセス
/swagger定義されたすべての API エンドポイントをテストするための Swagger UI を表示するパス。
技術的なポイント
- WebApplication.CreateBuilder(args):これが ASP.NET Core 起動の開始点です。アプリケーションのサービスとミドルウェアを構成するためのホストとビルダーを作成します。
- app.Services.AddSwaggerGen():サポートするサービスに登録するSwagger/OpenAPIファイルを作成し、API テストとファイル生成を大幅に簡素化します。
- ミドルウェア:
app.UseSwagger()、app.UseHttpsRedirection()など、これらのコンポーネントはリクエスト処理パイプラインを順番に構成します。すべてのリクエストはこれらのミドルウェアを経由して流れます。
- app.MapGet / app.MapPost:これは、ルーティングおよび処理ロジックを定義するために Minimal API で使用されるコア メソッドです。これらは、HTTP 動詞を特定の URL パスと Lambda ハンドラー関数にバインドします。
- 自動モデルバインド:存在する
app.MapPostこの例では、クライアントが JSON データを送信すると、ASP.NET Core がそれを C# に自動的に変換 (逆シリアル化) します。Product記録。
Chromebook で .NET プログラムを実行する方法
1. Chromebook の Linux サポートを使用して .NET を実行する
最新の Chromebook のほとんどは、Crostini プロジェクトを通じて Linux アプリケーションの実行をサポートしています。
- Linux 機能を有効にします。
- 入力
[設定] > [詳細] > [開発者] > [Linux を有効にする (ベータ)]。
- .NET SDKをインストールします。
- Linux ターミナルを開いて次に従いますマイクロソフト公式サイトインストール手順。
- 例えば:
sudo apt update
sudo apt install -y dotnet-sdk-7.0
- ターミナルで .NET アプリケーションをコンパイルして実行します。
2. クラウド開発環境を利用する
クラウド プラットフォームを使用すると、ソフトウェアをローカルにインストールしなくても、Chromebook で .NET プログラムを実行できます。
- 推奨されるオプション:
3. Docker コンテナを使用して .NET を実行する
Chromebook はアプリケーションを実行するためのコンテナの使用をサポートしており、Docker を通じて .NET 環境を開始できます。
- Linux 環境に Docker をインストールします。
- .NET コンテナー イメージをダウンロードします。
docker pull mcr.microsoft.com/dotnet/runtime:7.0
- コンテナ内で .NET プログラムを実行します。
4. クロスプラットフォームサポートを使用する
.NET 6 以降、アプリケーションは Linux を含む複数のプラットフォームで実行できるようになりました。アプリをクロスプラットフォーム形式にコンパイルし、Chromebook にデプロイします。
- 任意のマシンでアプリケーションをコンパイルします。
dotnet publish -c Release -r linux-x64 --self-contained
- コンパイルされたアーカイブを Chromebook に転送し、付属のランタイムを使用して実行します。
注意事項
- 有効性:.NET アプリケーションは、ローエンドの Chromebook では遅くなる可能性があります。
- 依存関係:Windows 固有の API に依存するアプリケーションは、正しく機能しない可能性があります。
- モデルのサポート:Chromebook が Linux または仮想化機能をサポートしていることを確認してください。
.NET UIプログラミング
主要技術
- Windows Forms (WinForms): シンプルで学習しやすい初期の UI フレームワークで、中小規模のデスクトップ アプリケーションに適しています。
- WPF (Windows Presentation Foundation): データ バインディング、スタイル、アニメーション、XAML 構文をサポートしており、大規模なデスクトップ アプリケーションに適しています。
- UWP (Universal Windows Platform): Windows 10/11 プラットフォーム向けに設計されており、PC、タブレット、Xbox、その他のデバイスで実行できます。
- MAUI (.NET Multi-platform App UI): クロスプラットフォーム (Windows、Android、iOS、macOS) UI 開発をサポートしており、Xamarin.Forms の進化版です。
- Blazor (Web UI): C# を使用して、ブラウザー (WebAssembly) またはサーバー側で実行できるフロントエンド Web 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」と表示します
よくあるエラーと解決策
- あいまいな呼び出し: 2 つの文字列だけが渡されると、コンパイラがオーバーロードされたバージョンを混乱させることがあります。明示的に追加することをお勧めします。
MessageBoxButtons::OK。
- スレッドの問題: MessageBox はデフォルトで応答 (モーダル) を強制され、現在の UI スレッドをブロックします。画面のフリーズを避けるために、必ずメイン UI でスレッド呼び出しを実行してください。
- 名前空間の競合:同時使用の場合
using namespace System;そしてusing namespace System::Windows::Forms;、おそらく他のものとMessageBox定義が競合するため、フルネームを使用することをお勧めしますSystem::Windows::Forms::MessageBox::Show(...)。
.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 での開発は非常に簡単であり、保守が困難です。
よくある落とし穴
- リソースの解放: C++/CLI では GC はありますが、Form クラスの場合は使用することをお勧めします
delete ibox;または、スコープの終了後にリソースが正しく解放されることを確認してください。
- スレッドの安全性: すべての UI コントロール操作 (カスタム ダイアログ ボックスの表示を含む) は、STA (Single Thread Apartment)実行スレッド (通常はメイン UI 実行スレッド) で実行します。
- 強制応答 (モーダル):使用
ShowDialog()それよりもShow()これにより、ユーザーはメイン ウィンドウを操作する前に入力ウィンドウを閉じる必要があり、直接情報を取得できるようになります。DialogResult。
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+
ビットマップに対応するファイルまたはストリームは存在しません
ソースがビットマップの有効期間中有効であることを確認する
デバッグ手順
赤十字の問題は頻繁には発生しないため、次の順序で進めることをお勧めします。
-
OnPaint 例外のインターセプト: PictureBox を継承、オーバーライド
OnPaint、
try/catch を使用して例外をキャッチし、それらを出力します。Debug.WriteLine、
キャプチャ後に実行this.Image = null執拗な赤十字を避けてください。
-
例外メッセージを確認する: Visual Studio の [出力] ウィンドウのメッセージを確認します。
根本原因を見つけるには、上記のエラー メッセージの表を確認してください。
-
ビットマップのライフサイクルの追跡: Dispose Bitmap に割り当てられるたびに、
記録する
Environment.StackTrace、誰がどの時点でリソースをリリースしたかを調べます。
-
まだ使用中のビットマップの破棄を防止する: 廃棄する前に確認してください
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 オブジェクトの主要なプロパティ
HWnd: メッセージを受信するウィンドウのハンドル。
Msg: メッセージのID。
WParam: 追加メッセージ情報 (ワードパラメータ)。
LParam: 追加メッセージ情報 (長いパラメータ)。
注意事項
- 上書きする
WndProcまたは、コードを変更するときは、既存の動作に影響を与えないように注意してください。
- もし
Message座標やIDは固定ではないので、条件判定を加えて必要な情報を絞り込むことも検討できます。
- [Windows メッセージ] を確認してください
ドキュメント](https://learn.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues) を参照して、メッセージ ID の目的を理解してください。
.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他のメッセージを処理するメソッド。
注意事項
WmCloseこのメソッドは上書きをシミュレートするだけですが、実際にはメッセージをインターセプトして処理します。
- 電話
Form::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 アクション
整理整頓に重点を置く
InvokeRequired継承のみに使用可能Controlオブジェクト (PictureBox など)。
- もし
trueこれは、現在の実行スレッドが UI 実行スレッドではないため、UI 実行スレッドを使用する必要があることを意味します。Invoke。
- 使用
Tuple複数のパラメータをカプセル化し、静的プロキシ関数に渡して処理します。
- 使用
try-catch例外をキャッチすると、プログラムのクラッシュが回避されます。
プログラムのクラッシュを避けるために、pPictureBox->Image = b を保護します。
考えられるクラッシュの原因
- 非 UI スレッドから UI コントロールにアクセスしようとしました
- 画像オブジェクト b が nullptr であるか、解放されています
- 前のイメージがリリースされなかったため、GDI リソースが枯渇しました
イメージを安全にセットアップするための推奨プラクティス
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->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);
}
}
}
追加情報
gcnew MethodInvoker(...)正当な委任である必要があります。C++11 ラムダ ([=]() など) 構文はサポートされていません。
- パラメータを渡すには、次を使用できます
BeginInvokeマッチObject^配列して解析します。
- 以前のイメージを解放することは、GDI リソースの不足を避けるための重要な手順です。
Blazor を使用して統一言語フロントエンド開発環境を確立する
ブレーザーとは何ですか?
Blazor は、Microsoft が発表したフロントエンド フレームワークで、開発者が C# および Razor 構文を使用して対話型 Web アプリケーションを作成できるようにします。 C# コードは、JavaScript を使用せずにブラウザーで実行できます。
開発者のメリット
- 使い慣れた C# および .NET テクノロジ スタックをフルエンド開発に使用する
- 共有バックエンドおよびフロントエンド ライブラリとビジネス ロジック
- 学習曲線を短縮し、開発効率を向上させます
ブレザーモード
- Blazor Server:SignalR を使用してサーバーへの接続を維持し、サーバーが UI ロジックを処理します
- Blazor WebAssembly:C# プログラム コードを WebAssembly にコンパイルし、ブラウザ側で実行します。
.NETとの統合
Blazor は ASP.NET Core をシームレスに統合し、既存の .NET アプリケーションと組み合わせることができ、依存関係の挿入、ルーティング、コンポーネント アーキテクチャ、およびその他の機能をサポートします。
導入方法
- スタンドアロンの静的 Web サイトとして展開可能
- または、ASP.NET Core プロジェクトに統合して公開します
- Azure、GitHub Pages、Docker、その他の環境をサポート
まとめ
Blazor は、主なテクノロジが .NET である開発者向けに、Node.js の統合 JavaScript 言語に対応するソリューションを提供します。これにより、フロント エンドとバック エンドの両方で C# を使用できるようになり、より一貫した開発エクスペリエンスが実現されます。
.NET MAUI を使用してクロスプラットフォーム アプリケーションを構築する
.NET MAUI とは何ですか?
.NET MAUI (Multi-platform App UI) は、Microsoft によって開始されたクロスプラットフォーム アプリケーション フレームワークです。 C# と XAML を使用してコードを作成し、それを Windows、Android、iOS、さらには macOS に展開できます。
開発者のメリット
- C# を統合してフロントエンドと UI を開発
- ビジネスロジック、データモデル、サービスを共有する
- マルチプラットフォームのメンテナンスおよび開発プロセスを簡素化
サポートされているプラットフォーム
- デスクトップ:Windows(WinUI)、macOS(MacCatalyst)
- アクション:Android、iOS
- Web (Blazor を使用):Blazor と組み合わせてハイブリッド Web アプリを構築可能
Blazor ハイブリッド モード
.NET MAUI の Blazor ハイブリッド モードを使用すると、ネイティブ アプリケーションに Web UI を埋め込むことができ、開発者はネイティブ API にアクセスしながら、Razor コンポーネントを使用してクロスプラットフォーム ユーザー インターフェイスを開発できます。
統合と展開
- .NET 7 / .NET 8 と完全に統合されており、Visual Studio を使用して強力な設計およびデバッグ ツールを提供します
- Microsoft Store、Google Playに展開するか、インストールファイルを直接公開します
- DevOps と CI/CD プロセスの統合をサポート
まとめ
.NET MAUI は、現在最も完全な .NET クロスプラットフォーム ソリューションです。 Blazor と組み合わせることで、Web、デスクトップ、モバイル プラットフォーム向けの統合アプリケーション開発を実現し、.NET 開発者に言語とテクノロジの点で一貫したフルエンドのエクスペリエンスを提供できます。
ASP.NET Core と .NET MAUI の比較
位置
- ASP.NET Core: クロスプラットフォームのサーバーサイド Web アプリケーションおよび API の開発用。
- .NET MAUI: クロスプラットフォームのクライアント アプリケーション (デスクトップおよびモバイル デバイス) の開発に使用されます。
サポートプラットフォーム
- ASP.NET Core: Windows、Linux、macOS上のサーバー環境、WebページまたはAPIとして出力します。
- .NET MAUI: Android、iOS、Windows、macOS、ネイティブ GUI アプリケーションの構築用。
開発言語
- 両方を使用するC#.NET プラットフォームを使用します。
UIとインタラクション
- ASP.NET Core: ブラウザーのレンダリングに依存して、Razor Pages、MVC、Blazor などを通じて HTML/CSS/JS を出力します。
- .NET MAUI: XAML または C# を使用してクロスプラットフォームのネイティブ UI を構築し、モバイル デバイスまたはデスクトップに直接レンダリングします。
該当するシナリオ
- ASP.NET Core: エンタープライズ レベルの Web システム、バックエンド API、およびクラウド アプリケーション。
- .NET MAUI: クロスプラットフォーム アプリ、モバイル アプリケーション、デスクトップ アプリケーション。
統合
.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} 回クリックしました";
}
}
実行方法
- Visual Studio でターゲット プラットフォーム (Windows/Android/iOS) を選択します
- 「実行」をクリックすると、クロスプラットフォーム UI が表示されます。
まとめ
この簡単な例は、.NET MAUI のクロスプラットフォーム機能を示しています。開発者は、XAML および C# コードを 1 回記述するだけで、複数のプラットフォームで同時に実行できます。
Visual Studio で .NET MAUI プロジェクトを作成する
ステップ 1: 必要なツールをインストールする
- ダウンロードしてインストールするVisual Studio 2022 17.3以降またはVisual Studio 2022 for Mac
- インストール時に「」を選択してください。.NET MAUI (マルチプラットフォーム アプリケーション UI 開発)ワークロード
ステップ 2: 新しい MAUI プロジェクトを作成する
- Visual Studioを開く
- 「新しいプロジェクトの作成」をクリックします
- 検索して選択します。.NET MAUI App"テンプレート
- 「次へ」をクリックし、プロジェクト名と場所を入力します。
- 「作成」をクリックしてプロジェクトの初期化を完了します
ステップ 3: プロジェクトの構造を理解する
MainPage.xaml: UIインターフェイスの定義(XAMLを使用)
MainPage.xaml.cs: バックエンド コード (C#) がイベントを処理します
MauiProgram.cs: アプリケーションの起動とサービスの登録ポイント
Platformsフォルダー: 各プラットフォームのネイティブ設定 (Android、iOS、Windows、MacCatalyst)
ステップ 4: アプリケーションを実行する
- Visual Studio ツールバーでプラットフォーム ターゲット (Windows、Android エミュレータなど) を選択します。
- 「実行」ボタンをクリックすると、対応するプラットフォームでアプリケーションが起動します。
追加情報
- Android アプリケーションの開発には Android SDK とエミュレータのインストールが必要です
- iOS には Mac と Xcode への接続が必要です
まとめ
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} 回クリックしました";
}
}
コンポーネントの説明
- <ContentPage>:MAUI は、画面やウィンドウと同様に、ページの基本タイプを表します。
- <VerticalStackLayout>:コンテナーは、中の要素が上から下に順番に配置されるように垂直に積み重ねます。設定可能
Spacing(間隔)とPadding(内側の距離)。
- <Label>:静的テキストを表示するコントロール。ここでは大きな文字サイズと中央揃えを設定します。
- <Button>:ボタンのコントロール、設定
x:NameC# バックエンドによるアクセスの場合、Clickedこの属性は、クリック イベントの処理方法を指定します。
C# コードの説明
InitializeComponent(): XAML で定義された UI 構造を初期化します。
OnCounterClicked: クリックイベントの処理メソッドで、ボタンがクリックされるたびにボタンのテキストを更新します。
counterBtn.Text: XAML で指定された名前を通じてボタンのプロパティを制御します。
結果の効果
実行後、画面中央にウェルカムメッセージとボタンが表示されます。ボタンをクリックするたびに、ボタン上のテキストが「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() を返します。
}
}
機能説明
- public static MauiApp CreateMauiApp(): これはアプリケーション全体のエントリ メソッドの 1 つであり、実行可能ファイルをアセンブルして返す役割を果たします。
MauiApp例。
- MauiApp.CreateBuilder(): アプリケーションのビルダー (Builder) を確立します。これは、アプリケーションの基本的な動作とサービスを設定するために使用されます。
- UseMauiApp<App>(): アプリケーションのメイン カテゴリを指定します (通常は
App.xaml.csアプリ カテゴリ)、これはアプリケーションのルート コンポーネントになります。
- ConfigureFonts():フォントファイルを登録して、アプリケーションで利用できるようにします。左側がエンティティファイル名、右側がプロキシ名です。 XAML または C# は、プロキシ名を介してフォントを使用できます。
- #if DEBUG ... #endif: デバッグを容易にするために、デバッグ モードに新しいデバッグ出力レコーダー (ロガー) が追加されました。
- builder.Build(): 上記の設定に基づいて、最終的なアプリケーション インスタンスを生成します。
一般的な拡張子
- 登録サービス (DI):
builder.Services.AddSingleton<MainPage>();
これにより、依存関係注入を使用して、たとえば App クラスで MainPage をロードできるようになります。serviceProvider.GetService<MainPage>()。
- ViewModel または他のクラスを登録する:
builder.Services.AddTransient<MyViewModel>();
builder.Services.AddSingleton<IMyService, MyService>();
要約する
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 つのシナリオに分類できます。
- 純粋な C++ アプリケーション:g++ でコンパイルされ、Ubuntu 上で直接実行されます。
- .NET Managed C++ (C++/CLI):.NET 6 以降でサポートされる Core 用の C# または C++/CLI 用に再設計する必要があります (Windows のみでサポート)。
- ハイブリッドアプリケーション:主に 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
注意事項
- C++/CLI は Windows のみをサポートしており、Ubuntu では直接実行できません。
- クロスプラットフォームの相互運用性が必要な場合は、P/Invoke (C# が C++ を呼び出す) を使用することをお勧めします。
- Linuxの使用
.soWindows で使用される関数ライブラリ.dll。
- ライブラリのパスが含まれていることを確認してください
LD_LIBRARY_PATH。
要約する
.NET C++ プログラムを Ubuntu にデプロイする実現可能な方法は通常、次のとおりです。C# + C++ ネイティブ ライブラリ” 構造。元のプログラムが C++/CLI に依存している場合は、クロスプラットフォーム .NET をサポートするように再設計する必要があります。最も推奨される方法は、Docker で .NET 8 + ネイティブ C++ モジュールを使用して、安定性、移植性、一貫性のあるデプロイメント プロセスを実現することです。
email: [email protected]