prgramming archives
コントロールサイズのリサイズ その2 | August 4, 2008 8:27 PM _ prgramming
前の記事で描画時にゴミが残るーとか言ってたわけだけど、
そもそもWM_SIZEを捕まえる必要がないという……
The So-Software Studio のWTL/ATLコンテンツのPart3ダイアログリサイズにリサイズマップを使ったコントロールのリサイズ方法が載ってます。
WTL/ATLはもっぱらここを読んで勉強してるわけだけどちゃんと読もうぜ俺。
悔しいので何でゴミが残らないのかなーと思ってちょっと追ってみた。
CDialogResizeのWM_SIZEハンドラで処理しているらしい。
んで、自分のくんだハンドラとの違いはまず処理始めに
BOOL bVisible = pT->IsWindowVisible();
if(bVisible) pT->SetRedraw(FALSE);
としてやって表示されてたら一時的に再描画を切って、最後に
if(bVisible) pT->SetRedraw(TRUE);
pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
としてやって再描画をオンにして再描画メソッドを投げると。
再描画を切るのはまぁ良いとして多分最後のRedrawWindow()に渡している引数がポイントの模様。
MSDNを見ると
■DW_ERASE
ウィンドウの再描画時に、ウィンドウが WM_ERASEBKGND メッセージを受け取ります。RDW_INVALIDATE フラグも同時に指定しなければなりません。RDW_INVALIDATE フラグを指定しないと、RDW_ERASE フラグは効果がありません。
■RDW_INVALIDATE
lprcUpdate または hrgnUpdate パラメータで指定した領域を無効化します(NULL 以外の値を指定できるのはどちらか一方だけです)。両方とも NULL の場合、クライアント領域全体が無効化されます。
となっていて、自分のはWM_ERASEBKGNDを投げるだけだったので、きちんと消去されていなかったらしい。
一度領域を無効化しないと消されないという解釈でいいのかな。
とまぁそう言うことらしい。
若干もやもやが残るけどこれ以上追求してる余裕もないので分かったつもりになっておく。
コントロールのサブクラス化と多重継承 | August 3, 2008 9:36 PM _ prgramming
/*
立て続けにまたプログラミングの記事。
いや、卒論(テキストの方ね)書くときに見返すことで役立つかなーと。
あとは何処かの誰かが同じようなことで詰まったときに少しでも参考になれば、と。
一応もそもそと絵を描いては居るのだけれど、どうにも身が入らない。
というか絵なんて描いていて良いのだろうかとか煽られる煽られる。
何かもう少しでも多くソース弄ってないと寝るときに不安が押し寄せてきて寝れないとか。
*/
そんなことはさておいて。
表題のことだけどサブクラス化と多重継承の説明は省略。
今回はサブクラス化と多重継承を行ったときに起きた問題と解決。
例えば、CWindowImplテンプレートを継承してサブクラス化する際に、更にCTreeViewCtrlExを継承する場合。
色々な関数が在るわけだけどCTreeViewCtrlEx::の関数を使う時にm_hWndがNULLですよーな意味のエラーががが。
んで、色々追ってみると、CWindow::m_hWndには値が入っていて、CTreeViewCtrlEx::m_hWndはNULLになっている。
CTreeViewCtrlEx::の関数を使うときは当たり前と言えば当たり前なんだけど、CTreeViewCtrlEx::m_hWndが使われる。
なのでCWindow::m_hWndの値をCTreeViewCtrlEx::m_hWndへ突っ込んでみると無事に動作確認!
けど動いたのは良いけどこんな解決の仕方で良いのだろうか。
ただまぁ色々なコントロールをクラス化して別で記述出来るので、分割してクラス当たりの行数を減らしてコーディングしたい人にはお勧め。
ただし何か問題があっても責任は取れな(ry
コントロールサイズのリサイズ | August 3, 2008 2:55 AM _ prgramming
少し引っかかったのでメモ。
WTL/ATLでリサイズするときに捕まえるメッセージはWM_SIZINGではなくWM_SIZE
何故かWM_SIZINGが飛んでこなくて代わりにWM_SIZEが飛んでくると言う。
とりあえずはこれでコントロール含めたリサイズが出来るようになるわけだけど、
素早くリサイズすると描画時にゴミが残る罠が。
どうにか出来ないかなとリサイズ後にWM_ERASEBKGNDとか投げてみたけれど改善されず。
キャッシュ消してリペイントでも駄目となるとどうしたら良いんだ?
ウィンドウ保存位置その3 | August 2, 2008 8:03 PM _ prgramming
WINDOWPLACEMENTのshowCmdにSW_HIDEが保存されないと言う件で、
GetWindowPlacement()についてMSDNを読んだら以下のような記述が。
CWnd が最大表示されている場合は、WINDOWPLACEMENT 構造体の showCmd メンバは SW_SHOWMAXIMIZED になります。ウィンドウが最小化されている場合は、このメンバは SW_SHOWMINIMIZED になります。それ以外は SW_SHOWNORMAL になります。
要は最大化か最小化しか状態を保存できないと言うことらしい。
仕方ないので状態保存用の関数を書き換えることに。
修正前は、
// target : 状態を保存するウィンドウクラスへのポインタ
// nID : ウィンドウのID
void inputState(CWindow* target,int nID){
target->GetWindowPlacement(&wndPlc[nID]);
}
となっていて、WINDOWPLACEMENT構造体の配列に直接値を取得して居たわけだけれど、
GetWindowPlacement()は前述の通り、showCmdにSW_HIDEを保存できないので、以下のように修正。
// inWindplc : 保存するWINDOWPLACEMENT
// nID : ウィンドウのID
void inputState(WINDOWPLACEMENT inWndplc,int nID){
// ウィンドウ状態コピー
wndPlc[nID].flags = inWndplc.flags;
wndPlc[nID].length = inWndplc.length;
wndPlc[nID].ptMaxPosition = inWndplc.ptMaxPosition;
wndPlc[nID].ptMinPosition = inWndplc.ptMinPosition;
wndPlc[nID].rcNormalPosition = inWndplc.rcNormalPosition;
wndPlc[nID].showCmd = inWndplc.showCmd;
}
あとは呼び出し元を、
{
(~略~)
// ウィンドウ状態保存
WINDOWPLACEMENT wndplc;
GetWindowPlacement(&wndplc); //現在の状態を取得
// 表示状態をチェックし代入
if(IsWindowVisible()) wndplc.showCmd = SW_NORMAL;
else wndplc.showCmd = SW_HIDE;
// 状態保存関数呼び出し
pcfm->inputState(wndplc,wndId);
(~略~)
}
と修正。
一応これで無事動作することを確認。
さくさく次に進もう。
ウィンドウ位置保存その2 | August 2, 2008 6:02 PM _ prgramming
前回結局スレッドを使うことも出来なかったのでどうするかと考えたけれど、
やはり何かしらを持たせなければどうにもなりそうに無さそう。
・CMainWindow(ウィンドウクラス)
・CConfigManager(ウィンドウ情報クラス)
・CWndManager(ウィンドウ管理クラス)
があって、
CWndManagerにCMainwindowとCConfigManagerを持たせるところまでは前回通り。
んで、CMainWindowに何かを持たせなければならないという結論に落ち着いたわけだけど、
持たせるのはCConfigManagerにすることに。
/* Frieve Editor という面白い物があったので使ってみる */
■ 前回

■ 今回

ウィンドウクラスでOnDestroyが呼ばれたときに、
WINDOWPLACEMENTをCConfigManagerに渡す
↓
CConfigManagerのデストラクタでファイルに書き出し
で、どうにかウィンドウ位置の保存に成功。
ただ、CConfigManager*を持たせるためにコンストラクタへの引数を増やさなきゃいけないのはなぁ。
出来ればデフォルトコンストラクタで余り意識しないで使えるようにしたかったのだけれど。
もし仮に、CConfigManagerを持たせずにやるとすれば、
所定の状況に於いてメッセージを発行し、
それをCWndManagerで、発行元を参照して処理
という方法が有るのだけれど、CWndManagerはメッセージループを持たないただのクラスなので捕まえることもできず、
かといってそれを実装しちゃうとそれはそれでごちゃごちゃしてて美しくないので却下。
そのうちこの辺りを綺麗に実装する方法を考え直そう。
ウィンドウ位置保存 | July 30, 2008 3:13 PM _ prgramming
管理用のパレットを独立させるから複数のウィンドウ(ダイアログ)が表示されるわけだけど、
大抵のお絵かきツールはウィンドウ情報を保持してる(物によってはパターン保存可能)のを実装しようとして少し詰まったのでメモ。
CWndManager(ウィンドウ管理クラス) → CConfigManager(ウィンドウ情報)
↓ ↓
ウィンドウ群.......
てなクラスで、本当はウィンドウクラス側でメッセージを処理してCConfigManagerに渡せれば良いんだけど、親クラスを持たせるとかの相互依存をあんまりやりたくないのでスレッドで処理することに。
具体的には、
CWndManagerのコンストラクタでスレッド生成
↓
数分置きにウィンドウクラスの情報をチェックしCConfigManagerに渡す
↓
CConfigManagerのデストラクタで状態を外部ファイルへ書き出し
で、スレッドを作るに当たってCreateThreadを使おうとするのだけれどビルドでエラーを吐く。
何でかなーと思ったら、スレッド関数はクラス内で使うときstaticしなければならないらしい。
なるほど。
これってメンバ関数だと実行アドレスが定まらないからって理由?
クラス時のメモリ周りの挙動があんまり分かってないのがこんなにも早く影響するとは。
C++に関しても、もっと勉強を進めないと。
卒論メモとかとか | July 13, 2008 7:23 PM _ prgramming
卒論のメモ用にブログ立てようかと思ったけど面倒なので本家でやっちゃう。
■何を作るのか
乱暴に言うとリアルタイムレタッチツール
丁寧に言うとPhotoshopとかのようにGUIを操作しながらシェーダをはき出せるミドルウェア
ゲーム会社とかには確実にあるはずだけど公開されている物は知らないので……
RenderMonkeyやFX Composerは何だかんだでシェーダ書かないといけないしね。
■ コントロールはWTL/ATL
The So-Software Studio(WTL関連では恐らく最も詳しい)
http://home.att.ne.jp/banana/akatsuki/
Highest Seraphim(MFC用みたいだがWTLにも流用可能)
http://www.alpha-net.ne.jp/users2/uk413/
今のところ
・描画パネル
・エフェクト管理パネル
大学でのプレゼン用に嘘画面を作ってあったりするけれどPhotoshopの画面を一部切り貼りしてるので今は秘密;-P
・オブジェクトパネル
・カメラパネル
・光源パネル
なインターフェースの予定。
■ グラフィックはDirectX
・OpenGLでも良いんだけど、いつか同人ゲー作ってみたいなぁって事でPCに強いDirectXを
Masafumi's LABORATORY
http://www.shader.jp/xoops/html/masafumi/
■ シェーダ言語はHLSL
・なんとなくイメージで。
あとはCgでも良いけど、基本的には呼び出しAPIが違うだけ+DirectXでの実装がHLSLに比べてちょっと面倒らしいので。
shader.jp(言わずもがな)
http://www.shader.jp/xoops/html/
GPU Gems / Free HTML (英語だけど無料公開されたので)
http://http.developer.nvidia.com/GPUGems/gpugems_pref02.html
■ 実装予定
・良くある色補正
・スクリーン補正とかのエフェクトプリセット
・gaussian filterとかフィルタ
・オブジェクトマスク(後述)
・シェーダファイルへのエクスポート
・被写界深度や画角などのカメラエミュレーション
カメラエミュレーションは趣味。多分間に合わない。
■ オブジェクトマスク
・オブジェクトを指定してエフェクトをかけられる
・てかそれくらいはつけないと、このソフトウェアの存在意義があんまり無くなる気がする
取りあえずこんなところ
Σ(・×・)