Windowsプログラミング

みんな大好きWindowsプログラミングについてのいろいろ

ComptrとDirectXの話

マイクロソフト界隈のプログラミング環境で、度々見かける正体不明の言葉たち。
DirectX関連のコードを書いているとちょいちょい見かけて、知らんうちに使ってるけど正体がよくわかっていない怖いやつ「COMオブジェクト」について

COMオブジェクトって何ぞ?(ていがくねんむけせつめい)

💡まず「COM」ってなに?

COM(コム)は「Component Object Model(コンポーネント オブジェクト モデル)」の略です。
でもそんなカタい言葉、いったん忘れてください。


🍱 COMオブジェクトは「お弁当のおかず」

たとえば「ゲームを作る」としましょう。

それが、「COMオブジェクト」です。


📦 COMオブジェクトは「貸してくれる便利な道具」

みたいな「完成された便利な道具(部品)」を、他の人(Microsoftなど)が作っていて、
それを「COMオブジェクト」として使えるようにしてくれてるんです。


🗣️「共通のルールで話せる友達」

COMオブジェクトにはルールがあります。

だから「知らない人が作ったプログラムの部品」でも、安心して呼び出して使えます。


🧩 まとめ

比喩

意味

おかず(道具)

COMオブジェクト

お弁当箱

自分のアプリ

おかずの受け渡しのルール

COMの決まり(インターフェース)

作ってくれた人

Microsoftや他の開発者


✅ 一言で言うと

「COMオブジェクト」とは、共通のルールで作られた便利な部品のこと。いろんなソフトから呼び出して使える。

もう少し勉強した人向けの説明

🔧 COMオブジェクトとは何か?

✳️ ざっくり一言でいうと:

「異なるプログラミング言語やアプリケーション同士が、共通の仕組みでオブジェクトをやりとりできるようにした技術」
→ それが COM(Component Object Model)
→ COMを通じて使えるインスタンス(機能の塊)が COMオブジェクト


🎯 COMが目指すこと

プログラムの世界には「部品の再利用」や「モジュール化」が大事です。

でも、

これらが言語や仕組みを超えて共通のやり方で連携できるようにしたのがCOMです。


🧱 COMオブジェクトの仕組み(ざっくり)

  1. インターフェース(IUnknownやIDispatch)
    • COMオブジェクトには最低1つ、インターフェースがあります。
    • 利用者はインターフェース越しにしかCOMオブジェクトにアクセスできません。
    • 実装の中身は隠蔽されていて見えません(カプセル化)。
  2. GUID(Globally Unique Identifier)
    • COMオブジェクトやインターフェースには一意のID(GUID)が振られています。
    • これにより、OSや他アプリから動的に識別できます。
  3. 参照カウント(Reference Counting)
    • COMは内部的にAddRef/Releaseを通じてオブジェクトの寿命を管理します(ガベージコレクションはしません)。

✅ よく使われる場面


💡 なぜ今でも使われる?


👨‍🏫 まとめ

項目

内容

目的

言語を超えて再利用できる「共通のオブジェクト化」技術

コア概念

インターフェースベース、参照カウント、GUID

主な用途

DirectX、Office自動化、ActiveX、WinAPI

メリット

再利用性、互換性、Windowsとの親和性

デメリット

実装がやや複雑(CoCreateInstance、IUnknown、HRESULT...)

ComPtrについて

🧩 前提まとめ:DirectXはCOMベース

まず前提として:


❗COMの注意点:メモリ管理が自分持ち

COMオブジェクトは自動で解放されません。
代わりに AddRef()Release()参照カウント管理 を自前で行う必要があります。

ID3D11Device* device = nullptr;
CreateDevice(..., &device);
// 使い終わったら手動で解放
device->Release();

これをうっかり忘れると メモリリーククラッシュ の原因になります。


🛡️ ComPtr とは?(Microsoft::WRL::ComPtr)

ComPtrは、COMオブジェクトをスマートポインタで安全に扱うためのラッパークラスです。

ComPtr<T> を使えば、参照カウントの管理を自動でやってくれます!

🔁 ComPtrがやってくれること:


✅ 使用例(素のポインタ vs ComPtr)

【従来】生ポインタでの DirectX デバイス生成:

ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr;

D3D11CreateDevice(..., &device, &context);
// ...使う
device->Release();
context->Release();

【今どき】ComPtrを使った安全なやり方:

#include <wrl/client.h>
using Microsoft::WRL::ComPtr;

ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;

D3D11CreateDevice(..., device.GetAddressOf(), context.GetAddressOf());
// 解放は自動(RAII)で行われる

GetAddressOf()T** が必要なAPIのために ComPtr の中身のアドレスを渡す関数です。


📌 DirectX × ComPtr:なぜ使うのが当たり前?

👍 メリットまとめ:

ComPtr の利点

解説

自動メモリ管理

Release()

を書かなくていい。例外にも安全

スマートなコード

if (device)

のようにそのままチェックできる

RAIIに沿う

C++のモダンな設計思想とマッチ

安心してAPI連携

GetAddressOf()

で API に渡しやすい


🧠 最後に一言でまとめると…

DirectXはCOMでできている。COMの参照カウント管理は手間がかかる。ComPtrを使えばそれが自動で、ミスも減る。だからプロでも標準的に使われている。


Windowsプログラミングについて

Windowクラス

種類

構造体メンバ

列-A列-B
行-1A-1B-1
行-2A-2B-2
行-3A-3B-3
行-3A-3B-3
行-3A-3B-3
行-3A-3B-3
行-3A-3B-3

このパラメタを変えるとこうなる!

WinMainの引数の意味

CreateWindowExの引数と戻り値

メッセージループとコールバック関数の関係と仕組み

メッセージループ

コールバック

XMVECTORとXMFLOATどっち?問題

XMVECTOR


XMVECTORは、DirectXMathライブラリの中核をなすデータ型です。その特徴は以下の通りです。

XMVECTOR を使うべき場面:

:

C++

#include <DirectXMath.h>

// XMVECTOR同士の加算
XMVECTOR v1 = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
XMVECTOR v2 = XMVectorSet(4.0f, 5.0f, 6.0f, 0.0f);
XMVECTOR vResult = XMVectorAdd(v1, v2);

// 行列とベクトルの乗算
XMMATRIX m = XMMatrixRotationY(XM_PIDIV4);
XMVECTOR transformedVec = XMVector3TransformCoord(v1, m);


XMFLOAT (例: XMFLOAT3, XMFLOAT4)


XMFLOATシリーズのデータ型(XMFLOAT2, XMFLOAT3, XMFLOAT4など)は、C++の通常の構造体として定義されています。

XMFLOAT を使うべき場面:

:

C++

#include <DirectXMath.h>

// 構造体のメンバとして位置を保持
struct GameObject {
    XMFLOAT3 position;
    XMFLOAT4 color;
    // ...
};

GameObject player;
player.position = XMFLOAT3(0.0f, 1.0f, 0.0f);
player.color = XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f);

// XMVECTORの計算結果をXMFLOAT3に格納
XMVECTOR vec = XMVectorSet(10.0f, 20.0f, 30.0f, 0.0f);
XMFLOAT3 resultFloat3;
XMStoreFloat3(&resultFloat3, vec); // ここで変換


変換について


XMVECTORXMFLOATの間は、以下の関数を使って相互に変換できます。


まとめと推奨されるフロー


DirectXプログラミングにおける理想的なデータフローは以下のようになります。

  1. データ格納: オブジェクトの状態(位置、回転、色など)は、クラスや構造体のメンバとして**XMFLOAT**型で保持します。
  2. 計算開始: 計算が必要になったら、**XMLoadFloat関数を使用してXMFLOAT型のデータをXMVECTOR**型にロードします。
  3. 計算実行: **XMVECTOR**型を使って、DirectXMathの関数(XMVectorAdd, XMMatrixMultiplyなど)で高速なSIMD演算を行います。
  4. 計算結果の格納: 計算が終わったら、**XMStoreFloat関数を使用してXMVECTOR型の結果を再びXMFLOAT**型にストアし、永続化します。

ダイアログ

🪟 1. ダイアログってなに?

ダイアログ(ダイアログボックス)は、
ユーザーに何かを聞いたり、設定を入力させたりするための小さなウィンドウです。

例:


🔄 2. モーダル vs モードレス

種類

特徴

モーダル

他のウィンドウを操作できなくなる(完了するまで)

「保存しますか?」などの確認ダイアログ

モードレス

他のウィンドウも同時に操作できる

検索ウィンドウ、ツールパレット

💡 イメージ


📦 3. よく使われる「コントロール(部品)」

🟢 ボタン類

名前

説明

Button(ボタン)

「OK」「キャンセル」など。押すと動作を実行。

CheckBox(チェックボックス)

ON/OFF の選択に使う。複数選択も可能。

RadioButton(ラジオボタン)

選択肢を1つだけ選ぶ(複数ある中で1つ)

🔵 入力系

名前

説明

Edit(エディット)

文字を入力するテキストボックス。

ComboBox(コンボボックス)

リストから選ぶ+入力もできる。

ListBox(リストボックス)

複数行の選択肢から選ぶ。複数選択可もあり。

🟣 表示系・他

名前

説明

Static(スタティック)

文字や画像を表示するだけのラベル。

GroupBox

コントロールをグループ化して囲む枠。

ProgressBar(プログレスバー)

処理の進行度を表示するバー。


🧑‍💻 4. 実際に使うとどうなる?

モーダルダイアログを表示するコード例(Win32 API)

DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);

モードレスダイアログを表示するコード例

CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DialogProc);
ShowWindow(hDlg, SW_SHOW);

📌 5. まとめ

項目

ポイント

ダイアログ

ユーザーに質問や操作を促す小ウィンドウ

モーダル

他の操作をブロックして返事を待つ

モードレス

他の操作もOK、自由に使える

コントロール

ボタン、入力欄、リストなど部品のこと


🧁 もっとわかりやすく例えると…

ダイアログはコンビニのレジ
モーダルは「レジの人が“お会計終わるまで商品戻してね”って止める」状態。
モードレスは「セルフレジ。会計しながら他の人も動ける」状態です。