音声ファイルから動画ファイルを生成する(21)

公開:2013-12-31 07:14
更新:2020-02-15 04:37
カテゴリ:windows api,音声動画出力プログラム,windows,c++,audio

どう作ろうか

自前でコントロールのラッパーを作っていくことにはしたものの、さてどう作っていくかである。親ウィンドウを生成して子ウィンドウとしてコントロールを生成し、OSのダイアログ・システムは利用しない(といってもファイルダイアログとかデフォルトのものは使うけれども)方向で進めるのだが、コントロールとC++クラスの構成とか実装方法とかについてうだうだ考えているところである。

通常であれば、ベースとなるウィンドウラッパークラスを作り、基本的なAPIやメッセージ処理をメンバ関数化してそれを派生してつくるのが普通かなと思う。しかしそれではクラスが肥大気味というか冗長というか、必要以上に大きくなってしまう。というのもラップするのはコントロールの描画だけにしてその他のメッセージ処理はデフォルトで行うつもりだからだ。つまりWM_PAINTなどの描画系メッセージだけをフックすればよいと考えているので、ベースクラスはウィンドウを意識した構成にする必要はなく、簡素なものでよくなる。

描画カスタマイズをするにはいくつか方法がある。サブクラス/オーナードロー/カスタムドローという3つの方法である。今回は描画処理をすべて横取りして、Direct2D/3Dで描画するつもりなのでサブクラスでいいかなと思っている。

クラスとウィンドウの結びつきはサンクで行おうと考えている。生成は基本的にはヒープに作り、生成用の専用関数を作りクラスのコンストラクタは専用関数以外からnewできないようにprivate化する。インスタンスの生成以降に何か行う必要がある場合に備えておくために。

子コントロールを一から生成していくのでフック機構は不要となりそうだ。せっかく作ったけど今後何かの役にたつだろう。きっと。

サブクラス化の方法

コントロールとC++の結びつきはサンクを使い、WM_NCCREATE時にサブクラス化する。自前のウィンドウのときは、ウィンドウクラスのウィンドウプロシージャにサンクを仕込んでいた。そのためCreateWindowEXを呼び出した時点でサンクを呼び出すことができた。しかしこの設計はまずいな。ウィンドウが一個だけならいいのだが、2個以上生成する場合は問題があるな。

それはさておき、サブクラス化の場合はCreateWindowExしたあと、WM_NCCREATE時にSetWindowSubclassする。その際thisポインタをどう引き渡すかである。CreateWindowEx関数のlpParamにthisポインタをセットすればWM_NCCREATEメッセージのCREATESTRUCT構造体のlpCreateParamsで参照することができる。これをさらにSetWindowSubclassのdwRefDataに渡せばよい。そうするとサンク関数は普通の関数でよくなる。dwRefDataをthisにキャストしてメンバ関数を呼び出すだけなので、Xybakを使ってアセンブラでパラメータ変換しなくてもよくなるので。そのかわりパラメータをウィンドウに引き渡すことができなくなるが、それは引き渡すクラスのメンバにパラメータを追加すれば代替できるだろう。

CreateWindowEx呼び出し時のWM_CREATEメッセージコールバックが同期か非同期か

CreateWindowEx呼び出し時のWM_CREATEメッセージコールバックって同期か非同期かちょっと悩んだが、やっぱり同期だよね。なぜならWM_CREATEメッセージの戻り値によってCreateWindowEx関数の戻り値が変わるから。非同期だとインスタンス生成時に考慮しなくてはいけないことが増えそうなので、ちょっと考えてしまった。

子コントロールのメッセージ処理方法

子コントロールのメッセージは通知メッセージで親ウィンドウのウィンドウプロシージャに送られ処理する。このため親ウィンドウのウィンドウプロシージャが複雑なものになりがちである。なので子コントロールのメッセージについては親ウィンドウを経由せず、そのメッセージに関連するオブジェクトへ直接送信するのが理想である。それをどのように行うか今思案中である。頭の中ではデリゲートとかboost::signalとかのイメージがあるのだけれどもデリゲートはC++/CXだしboost::signalはコンパイルが重くなるし汎用的すぎるしなんだかなーと思っている。普通にインターフェースでよいように思うが。