Windows XPとvc++で画面に文字を出力させるプログラムを作っているのですが、実行
画面に出力した文字が画面の大きさを変えたり、画面を移動させたりすると画面が白く
なってしまいます。再描写が上手くいかないので、教えていただけないでしょうか。
環境をもう少し書いて下さい。
MFCなのかSDKなのか?
基本的には、OnDrawで再描画するといったところでしょうが
Windowsの描画の基本は、OSからのWM_PAINTメッセージに対応して
自分のウインドウ内の全描画を行うことです。
各ウインドウはこのタイミングでその時点に描画しなければならない全ての描画を
いつでも再現できるように実装しなくてはなりません。
WM_PAINTメッセージは再描画必要な場合にOSから送られるウインドウメッセージです。
この事から、Windowsのプログラミングでは、WM_PAINTメッセージに
対応する処理から全ての描画できるようにプログラム設計を行います。
Win32APIで作成している場合なら上記の通りなのでコードを入れる所は解ると思います。
ボタンを押したタイミングで描画を行いたい場合は、描画に必要な情報を設定しておいて
Invalidate等の関数でウインドウを無効化してOSからWM_PAINTメッセージを送らせるか、
ボタンを押した時の処理からもWM_PAINTの処理からも呼べるような描画関数を別に作成して
おいて両方から呼ぶようにしておく必要があります。
MFCを使っている場合は、Document-Viewアークテクチャを使用していれば、
OnDraw内に全ての描画処理が集約されるようにし、使っていなければ、OnPaint内に
集約されるように設計します。
この辺はWindowsの描画処理の根幹になる部分なのできちんと勉強される事をお勧めします。
ごめんなさい、脱字がありますね。
日本語が若干変ですが、
その辺は読み取ってください。(^^;
読めないほど変ではないと思いますので。
すいません。MFCでDocument-Viewアークテクチャを使っているのですが、OnDraw内でど
のようにプログラムすれば、よいのでしょうか?教えてください!
というか、OnDrawにどう書いているのですか?
1. 描画データをDocに置く
2. View::OnDrawでGetDocument()し、そいつから描画データを貰って描く。
手元に一冊は参考書を置いておかれた方が良いと思います。
質問内容が漠然としてますし、
今の質問の内容では、本を読んで基本的な部分は勉強してくださいとしか言えないです。
OnDrawのコードの書き方については、MFCのプログラミングに一般的な本であれば、
詳しく書いていると思います。
まずは基礎知識の収集を書籍等でされる事をお勧めします。
因みに質問されている内容をここで詳しく説明しだしたら
とてもじゃありませんが、このスペースには収まりきれないです。
訂正。
誤)
MFCのプログラミングに一般的な本であれば、
正)
MFCのプログラミングに関する一般的な本であれば、
勉強不足ですいませんでした。
取り敢えず、現状の描画をどのように何処に書いているのかを
ソースで提示して、それをOnDraw内でどのように実装すれば良いかと言う話なら
内容がある程度限定されるので何とかなるかもしれません。
コード量があまりに大量だと掲示板上に載り切らないかもしれせんが、
取り敢えず、考えて見られてはどうでしょうか?
LRESULT CMFC_DEMOView::OnWTPacket(WPARAM wSerial, LPARAM hCtx)
{
PACKET pkt;
WTPacket( (HCTX)hCtx, wSerial, &pkt );
CSingleLock lock( pWTMutex, TRUE );
CDC *pDC = GetDC();
RECT window_rect;
GetWindowRect( &window_rect );
POINT size;
POINT zahyo;
size.x = window_rect.right - window_rect.left;
size.y = window_rect.bottom - window_rect.top;
if( csr.x >= 0 ) {
CRgn r;
r.CreateRectRgn( csr.x - 2, csr.y - 2, csr.x + 2, csr.y + 2 );
pDC->InvertRgn( &r );
}
csr.x = (size.x * pkt.pkX) / lc.lcInExtX;
csr.y = size.y - (size.y * pkt.pkY) / lc.lcInExtY;
if( pkt.pkButtons ) {
CMFC_DEMODoc *pDoc = GetDocument();
list<point> * lst = pDoc->GetLst();
if( prev_pkButtons ) {
list<point>::iterator i = lst->end();
i--;
zahyo.x = size.x / 9;
zahyo.y = size.y / 6;
if(abs(i->x)<=zahyo.x && abs(i->y)<=zahyo.y){
pDC->TextOut(abs(i->x),abs(i->y),や);}
pev_pkButtons = pkt.pkButtons;
CRgn r;
r.CreateRectRgn( csr.x - 2, csr.y - 2, csr.x + 2, csr.y + 2 );
pDC->InvertRgn( &r );
ReleaseDC( pDC );
return TRUE;
}
このOnWTPacketで実行した画面を移動させたり、サイズを変えると白紙になってしまう
ので、実行画面をサイズ変更などしても実行画面がその大きさに合わせてそのまま表示
できるようにしたいのですが・・・お願いします。
まず、処理の切り分けが必要です。
純粋に描画の部分の処理とそのための情報収集部分を分けます。
収集した情報は、Documentクラスに保持させるとかしないと
収集した情報を再描画で使えなくなりますから、考慮が必要です。
単に描画用のパラメータ程度の話であれば、Viewクラスのメンバー変数に
保持する事になると思います。
描画に関する部分をViewクラスのOnDrawに持って行きます。
OnDrawはCDCのポインタを引数でもらうのでGetDCは必要ありません。
ReleaseDCも当然しなくて良いです。
GetDocumentもOnDrawの中で出来るはずなので問題ないですね。
この辺はCView::OnDrawをHELPとかMSDNとかで調べてみてください。
説明があると思います。
OnWTPacketでは、描画に必要な情報の収集と保存を行い、
InvalidateRect等で更新したい範囲を無効化します。
これでOSがWM_PAINTを送ってくるはずなのでOnDrawの描画処理が走って描画されます。
他のウインドウが重なっている状態から表に出てくるとかウインドウの操作で
再描画が必要な場合はOSが勝手にWM_PAINTを送ってきますので
どのタイミングで送ってこられるかはわかりませんので
どのタイミングでWM_PAINTが来ても再描画が出来るように
描画に必要な情報は常に保持しておくことが必要です。
また、状況によって画面上の描画内容が変わるような場合は、
今がどの状態なのかを保持しておいて状況に合わせて描画内容を
切り替えるようにしておく必要があります。
ウインドウのサイズが変わった場合にそれに合わせて描画したいのであれば、
描画のたびにクライアント領域のサイズを取得してそれを元に描画座標を相対的に
計算すれば、良いと思います。
補足
リサイズの話ですが、OnSizeでクライアントサイズをメンバー変数に保持するようにして
OnDrawではそれを参照するだけにした方がすっきりするかもしれませんね。
返事遅くなりました。
解決できました、ありがとうございました!