画像表示位置調整GUI付きの画像描画クラスできたよー

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

画像表示位置調整GUI付きの画像描画クラスできたよー

投稿記事 by MoNoQLoREATOR » 13年前

うおおおおおおおおおおお。
Win32APIと格闘すること8時間。
できましたあああああああ。

88888888888888
(_´Д`)ノ~~オツカレー
(↑自作自演乙!)

え?なんでWin32APIなの?
それはね。次のような脳内会議の末に見出された結論なのだよ。

「座標調整モード」みたいなのを作って、そのモードの間はD&Dで画像表示位置が調整できたらいいなー

『#define なんたらかんたら』で座標調整モードに突入!シンクロ率250%!

描画関数の中で[D&D検出][座標調整][座標情報をファイルに出力]→後で簡単に利用できる→これだ!

でも描画毎にファイル開いて書き換えてファイル閉じて・・・なんてしてたらカクカクするっしょ

じゃあoutputボタンが押されたら出力するようにしよう

それどこに配置するのよ?絶対邪魔にならない場所なんてないでしょ

別ウインドウにボタン作ればいいんじゃね?

君ねえ。それはいい考えだと思うけど、誰がそれ実装するの?MoNoQLoREATORだよ?Win32APIできるの?いくら良い考えでもねえ、実現できないようだったらそれは駄策と同じだよ。君はグリム童話の猫と鈴がどうのこうのっていう話を知らないのかい?

MoNoQLoREATORならできる。

根拠は?

私がMoNoQLoREATORだからだ。

そして、伝説へ・・・・!


・・・・・うん。なんという中二病。
ま、わざと中二病っぽい文章にしたんですけどね。中二病好きだから。
てなわけで完成したクラスがこちら。

graphic.h
► スポイラーを表示
とりあえず主要な部分だけ公開。

fw::eachframe関数(関数オブジェクト)は毎フレーム呼び出すべき関数で、中ではマウス情報の更新、fw::newwin::eachframe()の呼び出しを行うべきです。
fw::bfileはバイナリファイルを扱うクラスです。
fw::eachframe.notcalled()は、fw::eachframe()が一度も呼ばれていなかった場合にtrueを返す関数です。

fw::newwinは以前作ったデバッグ情報表示用の物を流用。だから汎用性がないコードが含まれています(ウインドウプロシージャのSTATIC子ウインドウ用の処理の部分)。

fw::figureクラスは名前通り図形を司るクラスです。
画像がD&Dを受け付ける範囲を指定するために使用しています。

とりあえず大まかなアルゴリズムを説明することが今回の目的なので、詳細が知りたい場合やこの描画管理クラスを利用したい場合はここからfireworksヘッダファイル群をダウンロードしてください。
fireworks.hをインクルードすれば使用可能となります(各ヘッダファイルを個別にインクルードしても利用できません)。
また、WinMain関数が定義されている場所では、fireworks.hを呼び出す前に
#define FW_WIN_MAIN_
を定義する決まりになっています。
座標調整モードにするには
#define FW_GRAPHIC_DRAG_
も合わせて定義してください。
また、fireworksヘッダファイル群を利用する際は
#define FW_WIN_MAIN_
#define FW_ALL_POP_UP_WITH_GRAPHIC_DRAG_
の2つを定義することをおすすめします(1つ目はWinMain関数が定義されているファイルのみでしか定義してはいけません)。
2つ目の定義によって、デバッグ情報出力が全て許可され、座標調整モードもONになります。
リリース時には2つ目の定義をコメントアウトすれば良いでしょう。
もしデバッグはしたいけど座標調整モードは不要だという場合はWITH_GRAPHIC_DRAG_の部分を削ればOKです。


はい。じゃ、説明しようと思ったのだけれど、何を主題とするか。
んー。今回作ったクラスの仕樣について説明した所で、あまり利益はないと思うんですよね。
そんなものは1人1人独自のものを作ればいい。
というわけで、私が苦労したWin32APIの部分を主題として説明を繰り広げていくことにしました。

まず、奴の考え方として、ウインドウプロシージャという関数を柱にして、何をするにしてもコイツにメッセージを送ったりコイツからメッセージを受け取ったりしてやりくりしてゆくというものがあるようです。
そして、私達が一般的にウインドウと呼んでいるものが親ウインドウと名付けられており、その中のパーツ(テキストボックスとかボタンとか)は子ウインドウと名付けられています。
どちらもCreateWindowという関数で作成します。
で、ボタンを作成した場合、ボタンが押されるとウインドウプロシージャにWM_COMMANDというメッセージが送られてくる(関数が実行されて引数にそれが格納されている)そうです。
これはウインドウプロシージャ関数の第2引数に格納されています。
よって、第2引数の値がWM_COMMANDだった場合にボタンが押された際の処理をすれば良いということですね。
ウインドウプロシージャ関数に直接処理を書くと汎用性が失われるので、とりあえずそのラッパークラスの「クリックされたフラグ」をONにしておきます。
あとはこれを毎フレーム確かめて、フラグがONになっていたらフラグをOFFにして「ボタンが押された際の処理」をすれば幸せになれますね。
しかし、ここで問題になってくるのは
どのボタンが押されたのか?
ということですよね。
GetWindowLongPtr(reinterpret_cast(第4引数), GWLP_ID)
とすれば、子ウインドウを作成するときに指定したIDを取得することができるので、どのボタンが押されたのかを特定することができます。
子ウインドウを作成するときに指定するIDは、原則唯一のものを指定します。
(親ウインドウが違えば被っても大丈夫だったような気がしますが、IDとクリックフラグをセットで管理する変数を今回は1つしか用意していないため、唯一にする必要があります。
親ウインドウごとに管理変数を用意する実装は複雑になる上にメリットがないと思われます。
unsigned intで表現できるIDはほとんどのコンパイラで約42億個ですからそうそう枯渇することはないでしょう。)
(ちなみに100番より前のIDは使用されているかもしれないと聞いたので今回は100番以降のIDを指定しています。)

これくらい知っていれば、あとはググったり、普通のC++の知識で書けると思います。

fireworksヘッダファイル群はまだまだ制作中のものです。
現在修正中で使い物にならないものも多々あります。
まあ少なくともこの描画管理クラス関係のものは使い物になりますけれど。
そんな状態でも使いたいという物好きの方がおられましたらどうぞご自由にお使いください。
改造も もちろんOKです。
ここバグってるよとかここはこうした方がいいんじゃないかとか意見があったら気軽に言ってください。
あと質問もお気軽にどうぞ。




う~ん。
これは便利なものができた!他の人にも使ってもらいたい!と思ってこの日記書いたけど、これは相当ハードル高いですねw
自作のものが多過ぎて、もう・・・・ねぇ?
まあいいや。
ここまでお疲れ様でした。

それでは、良いプログラミングライフを!

コメントはまだありません。