円でエンエンエン
パパママ地獄編
雪山に消えた一匹のワンワン の巻
ワンワンでーす
とりあえずいろいろやってパパママのアイデアをまとめた。SynthEditというソフトがあってそういう感じにしてみたいと思う。
http://www.aaa-int.or.jp/jfactory/projects/SynthEdit/
で、あーでもなくこうでもなくやってみたら、まあVISIOっぽい画面が完成した。
フォーカスしてると赤くなったりして、無駄にてがこんでいる。
四角がドラッグなどで動くが、ちらつきが気になったのでインターネットに言われるがままビユーで
this->InvalidateRect(NULL,FALSE);
したら、残像拳が三倍も、いや六倍近く残るようになった。(ちらつきはなくなったが)。そんで、メモリDCなどを使うなどの記述もあったが完全に私の頭はクリアされていて、空いた場所にはワンワンや、おかあさんと一緒、しましまのしまじろうののぶゆきおにいさん(通称ノブ)などが入っていた。うれしくなっちゃうナー、ワン。
ワンワンでーす
残像拳数十倍の図
この残像拳を消したいとせつに願うが、そもそもビユーとは何か、誰も教えてくれない。本場USAから出版されているチャオチェン先生作の「ヴィジアルCと(とっても)MFC」をひもといてみると。こんな図が書いてある。
・・・・・。
「物を覚えるにはまず人をおちょくるような立場でものを考えよ」とは確か先代の言葉だったが。それはここでも当てはめることができよう。そして、ここで、かなり昔に円でエンエンエンの連載中に、仕事で調べたからという理由で掲載されたビットマップとDC完全攻略マップがあったはずだ。
まったく何も思い出せない。
おぼろげながらDC(デヴァイスコンテキスト)という言葉は覚えていて、ウインドウがあったり、DIB・DDBがなんとなくあったりしているうちにビューだよ、ビュー。
ビュービュー。とりあえずチャオチェン師匠の文章でもひっぱってみるか。
In virtually all applications involving a View, it is used for displaying purposes. You can draw the display images, or you can write the display images. They all rely on their respective functions. We will begin by looking at how drawing in a View is done.
かと思ったら個別のという意味のようだ。覚えておこう。チャオチェン師が言うところでは、万物は必ずViewにつながるとのことだ。
Associated with a CView class is the CDC class, or Device Context, which CView manages. When you generate an SDI application, the device context is inherently constructed for us, which is why the OnDraw() function has an incoming parameter of “CDC* pDC” a pointer to the device context.
実際CView の継承関係を見てみよう。
ようするにウインドウクラス(CWnd)のことを言ってるんだナ。MSDNには
Within the Microsoft Foundation Class Library,
further classes are derived from CWnd to
provide specific window types. Many of these classes, including CFrameWnd,
CMDIFrameWnd,
CMDIChildWnd,
CView,
and CDialog,
are designed for further derivation. The control classes derived from CWnd, such as CButton,
can be used directly or can be used for further derivation of classes.
For more information on using CWnd,
see Frame
Window Topics and Window
Object Topics in Visual C++
Programmer's Guide.
でーとーんで
Most drawing in a framework
application occurs in the view, whose OnDraw
member function is called whenever the window’s contents must be drawn. If your
window is a child of the view, you might delegate some of the view’s drawing to
your child window by having OnDraw
call one of your window’s member functions.
In any case, you will need a device
context for drawing. You can use the stock pen, brush, and other graphic
objects contained in the device context associated with your window. Or you can
modify these objects to get the drawing effects you need. With your device
context set up as you like, call member functions of class CDC
(device-context class) to draw lines, shapes, and text; to use colors; and to
work with a coordinate system.
でとーんで
When a view becomes invalid, Windows sends it a WM_PAINT
message. The view's OnPaint
handler function responds to the message by creating a device-context object of
class CPaintDC
and calls your view's OnDraw
member
function. You do not normally have to write an overriding OnPaint
handler function.
A device
context is a Windows data structure that contains information about the
drawing attributes of a device such as a display or a printer. All drawing
calls are made through a device-context object. For drawing on the screen, OnDraw
is passed a CPaintDC
object. For drawing on a printer, it is passed a CDC
object set up for the current printer.
フムフム つまりこうか
だんだん思い出してきたよ。PainterってのがGDIのことなんだろう。しくみは大分思い出してきたよ。
ちらつきとはどういうことかフリッカー、そうだ、フリッカーだ。ソウルフリッカー!
http://www.codeproject.com/gdi/flickerfree.asp?df=100&forumid=55&exp=0&select=822717
Flicker Free Drawing In MFCという記事があった。
ここにあるサンプルではフリッカーモードオンとオフが試せるので、効果が絶大なのがわかる。は、はやくそのほうほうをおしえてくれ。
読んでいくとカプセル化されているのでOnDrawで使ってるCDCをCmemDCにすれば良いようだ。以下の手順を踏めばよい。
あっというまになおった。
ほんとにぴたりとなおった。
つまりこうしたわけだな
一体なんでちらつかなくなるのか?実際俺も思い出しながらデバコンメモリーを使うという方法は実践したがちらつきを抑えることはできなかった(嗚咽をもらす)。つーか、なんか書いてあったかもしれないが、めんどうくさいのではしょったのでよけいにちらつきがひどくなった。
ということはOnEraseBkgnd(pDC);をCViewに返さないというのが大事なことのようだ。それではOnEraseBkgndはそこで何をやっているのか。
http://techtips.belution.com/ja/vc/0003/
なるほど、定説だ。しかしいまいちそれぞれのタイミングが良くわからん。
からトレースしてみたぃ。が、MFCでトレースするのがめんどうくさいようなので以下を参照にする。
http://homepage3.nifty.com/ysflight/mfcconsole/mfcconsolej.html
発生の順番はこうだ
InvalidateRect(trueの場合)
OnEraseBkgnd
OnDraw
UpdateWindow
OnMouseMove
InvalidateRect(falseの場合)
OnDraw
UpdateWindow
OnMouseMove
OnEraseBkgndあんまり関係ねえじゃねえか。
やっぱりデバコン
チャウシェスクー(終わり)
this->CreateCompatibleDC(pDC);
pDC->LPtoDP(&m_rect);
this->m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
this->m_oldBitmap =
this->SelectObject(&m_bitmap);
this->SetMapMode(pDC->GetMapMode());
this->SetWindowExt(pDC->GetWindowExt());
this->SetViewportExt(pDC->GetViewportExt());
pDC->DPtoLP(&m_rect);
this->SetWindowOrg(m_rect.left, m_rect.top);
this->FillSolidRect(m_rect, pDC->GetBkColor());
てなかんじだよと。なぜか完全を誇っていたデバコン図にCreateCompatibleBitmapが入っていなかった。図の一番右に書き加えるべきだった。あとはそんなに疑問に残るようなことはやってないと思う。FillSolidRectの速度が速いからちらつきがなくなるのかね。