ページ 11

再描画について

Posted: 2009年12月12日(土) 17:48
by たこやき
ウィンドウの雛形に
case WM_PAINT:{
PAINTSTRUCT ps;
char cbuf[100];
HDC hdc = BeginPaint( hWnd, &ps );
wsprintf( cbuf, _T("Hello window"));
TextOut(hdc,0,100,cbuf,sizeof(cbuf));
SetWindowText( hWnd, cbuf );
EndPaint( hWnd, &ps );
break;
}

を付けて実行したのですが、サイズを大きくしたり小さくしたりするとちらつきが見られるのですが、どうしたらこのちらつきをなくすことが出来るんでしょうか?

Re:再描画について

Posted: 2009年12月13日(日) 05:05
by Dixq (管理人)
質問する際は名前を統一して下さいますようお願いします。

Re:再描画について

Posted: 2009年12月13日(日) 05:59
by たこやき
すみません。気をつけます。

Re:再描画について

Posted: 2009年12月13日(日) 08:55
by KEYONN_
サイズとは何のサイズの事でしょうか?
今、私もWindowsプログラミングを勉強しています。
力になれれば良いのですが…。

Re:再描画について

Posted: 2009年12月13日(日) 13:02
by たこやき
回答ありがとうございます。サイズとは、ウインドウ自体のサイズのことです。

Re:再描画について

Posted: 2009年12月13日(日) 20:00
by softya
多少のチラツキは避けられません。
ある程度抑える方法としては事前に作っておいた裏画面(バッファ)で描画して、表画面に転送する方法が一般的です。
参考↓
http://oshiete1.goo.ne.jp/qa4093552.html

それと2点気になったので修正しました。
1.UNICODEとマルチバイト文字の扱いの混在が気になったので統一。
2.TextOutの引数が間違っていたので修正。
TCHAR tcbuf[100];
        HDC hdc = BeginPaint( hWnd, &ps );
        _stprintf( tcbuf, _T("Hello window"));
        TextOut(hdc,0,100,tcbuf,_tcslen(tcbuf)); ←バッファ長では無く文字列長を渡してください。
            SetWindowText( hWnd, tcbuf );
        EndPaint( hWnd, &ps );

Re:再描画について

Posted: 2009年12月13日(日) 20:22
by たこやき
そうなんですか。その方法でやっていみたいと思います。
まだ実験はしてないですが。ようはstatic HDC hdc;を前のバッファにすればいいのですね。
回答ありがとうございました!

Re:再描画について

Posted: 2009年12月13日(日) 23:07
by たこやき
参考にしたサイトを参考にしてやってみましたが、ちらつきが軽減しません。
やり方が間違っているのでしょうか?
ソースを見てください。
case WM_PAINT:{
PAINTSTRUCT ps;
TCHAR tbuf[100];
RECT r;
HRGN hRgn;
hdc = BeginPaint( hWnd, &ps );
GetClientRect(hWnd,&r);
wsprintf( tbuf, _T("on WM_PAINT%d"),t);
TextOut(hdc,0,100,tbuf,::_tcslen(tbuf));
SetWindowText( hWnd, tbuf );
hdc2=hdc;
[pre]        EndPaint( hWnd, &ps );
SetTimer(hWnd,NULL,1,NULL);
break;
}
case WM_TIMER:
PAINTSTRUCT ps;
wchar_t cbuf[100];
RECT r;
HRGN hRgn;
hdc = GetDC( hWnd);
GetClientRect(hWnd,&r);
wsprintf( cbuf, _T("on WM_PAINT%d"),t);
TextOut(hdc,0,100,cbuf,sizeof(cbuf));
ReleaseDC( hWnd, hdc);
t++;
InvalidateRect(hWnd,NULL,FALSE);
break;
です。

Re:再描画について

Posted: 2009年12月13日(日) 23:31
by たこやき
このソースでいらないものがあると思いますが。それは無視してください。

Re:再描画について

Posted: 2009年12月13日(日) 23:46
by たこやき
ソース間違えました。
HDC hdc,hdc;
case WM_PAINT:{
PAINTSTRUCT ps;
TCHAR tbuf[100];
hdc = BeginPaint( hWnd, &ps );
wsprintf( tbuf, _T("on WM_PAINT%d"),t);
TextOut(hdc,0,100,tbuf,::_tcslen(tbuf));
SetWindowText( hWnd, tbuf );
EndPaint( hWnd, &ps );
SetTimer(hWnd,NULL,1,NULL);
break;
}
case WM_TIMER:
PAINTSTRUCT ps;
TCHAR tbuf[100];
RECT r;
HRGN hRgn;
hdc2 = GetDC( hWnd);
           GetClientRect(hWnd,&r);
wsprintf( tbuf, _T("on WM_PAINT%d"),t);
TextOut(hdc2,0,100,tbuf,::_tcslen(tbuf));
ReleaseDC( hWnd, hdc2);
  t++;
InvalidateRect(hWnd,NULL,FALSE);
break;
です。

Re:再描画について

Posted: 2009年12月14日(月) 00:34
by softya
本当にちゃんと読みました?
参考にリンクした情報と全然違うのですが・・・。
リンクの更にリンク先の情報までちゃんと読んでくださいね。
http://oshiete1.goo.ne.jp/qa3052870.html

問題点。
1.常駐のメモリDCが無い。
2.WM_PAINTでBitBltでメモリDCから転送していない。つまり何も変わっていない。

Re:再描画について

Posted: 2009年12月14日(月) 01:38
by たこやき
回答ありがとうございます。あ、気づきませんでした。そのサイトで作ってみましたが,
create関数がないのですが、代わりの関数はないのでしょうか?一応探してみてはいるの
ですがみつからなので・・・

Re:再描画について

Posted: 2009年12月14日(月) 10:07
by softya
createと言う関数は知らないので、オリジナル関数じゃないかと思われます。それに小文字で始まるWindowsAPIは見たことありません。
フォントはCreateFont()関数を使ってください。

Re:再描画について

Posted: 2009年12月14日(月) 11:15
by たこやき
回答ありがとうございます。TextOutの方は再描画されたのですが、ボタンのほうがチカチカし始めました、どうしたらチカチカをとめるころができるのでしょうか?

Re:再描画について

Posted: 2009年12月14日(月) 11:17
by たこやき
ボタンの定義はこれです。
CreateWindow( _T("BUTTON"), _T("何もしない"),BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE ,50, 50, 300,50,
 hWnd, (HMENU)999, hInstance, NULL );

Re:再描画について

Posted: 2009年12月14日(月) 12:25
by softya
ボタンのチカチカを止めることは基本的に無理です。
別ウィンドウとして描画されていますので、どうしてもチカチカしてしまいます。
色々なテクニックでチカチカを抑えることは出来ないことは無いですが、どれも裏技っぽい方法になってしまうのでどうかなと・・・。
それ以前にWindowsAPIの他の知識を深めてもらわないと説明も出来ないので色々とまず基本的なことを勉強してください。

Re:再描画について

Posted: 2009年12月14日(月) 14:23
by たこやき
そうなんですか。裏技ですか。。。回答有難うございました。

Re:再描画について

Posted: 2009年12月15日(火) 01:44
by たこやき
最後の質問なのでが、WM_TIMERにInvalidateRect(hWnd,NULL,FALSE);を入れて、
WM_PAINTにSetTime()をいれた場合、無限ループになるのでしょうか?また無限ループならどういう風
にかけば無限ループにならないのでしょうか?

Re:再描画について

Posted: 2009年12月15日(火) 02:06
by softya
>最後の質問なのでが、WM_TIMERにInvalidateRect(hWnd,NULL,FALSE);を入れて、
>WM_PAINTにSetTime()をいれた場合、無限ループになるのでしょうか?また無限ループならどういう風
>にかけば無限ループにならないのでしょうか?

私が無限ループと表現したのは、WM_PAINTにInvalidateRect()を入れてしまうとWindowsの処理出来る範囲での最短時間で再描画されてしまうからです。これは描画リソースの無駄遣いですので無限ループと表現しました。
描画負荷のかかるWM_PAINTを呼び出すのは出来るだけ少なくするべきですので、都合の良い出来るだけ長い時間をSetTimerに設定してください。そうすれば描画負荷は最小限になります。1つのアプリがリソースを独占する事はWindowsプログラミングとして出来るだけ避けるべき重要な事柄です。
ちなみにWM_PAINTの度にSetTimer()をしてはいけません。SetTimer()は一回呼び出すだけでタイムアウト時間周期でWM_TIMERメッセージが毎回発生します。

そうそう、TextOutによるボタンのチラツキを抑える事はTextOutするウィンドウを子ウィンドウにしてInvalidateRect()で子ウィンドウだけ再描画すれば抑えられますよ。

Re:再描画について

Posted: 2009年12月15日(火) 03:06
by たこやき
ソースをいじくりましたが、出来ません。
もうしわけないのですが具体的におしえてください。

Re:再描画について

Posted: 2009年12月15日(火) 03:15
by たこやき
できれば例など出していただけると助かります。

Re:再描画について

Posted: 2009年12月15日(火) 10:04
by たいちう
> できれば例など出していただけると助かります。

> ボタンのほうがチカチカし始めました

再現できる簡潔なプロジェクトをupしてくれたら手伝えるかも。
どんなボタンか分からないのに1から例を作るのは私は御免。
(ボタンがどこにあるのかとか、どこに描画しているのとか)

Re:再描画について

Posted: 2009年12月15日(火) 12:00
by たこやき
はい。わかりました。プロジェクトは入りきらなっかったのでソースだけupします.

Re:再描画について

Posted: 2009年12月15日(火) 12:29
by たいちう
再現しました。
多分一番ラクにごまかす方法。
case WM_TIMER: {
    TCHAR tbuf[100];
    SelectObject( hMemDC, hFont );
    int len = wsprintf( tbuf, _T("on  x=%d "),t);
    TextOut(hMemDC,0,100,tbuf,len); // ここは既にsoftyaさんが指摘している
    t++;
    RECT rect;
    SetRect(&rect, 0, 100, 200, 150);
    InvalidateRect(hWnd,&rect,FALSE);
    break;
}
正攻法としては、ダイアログリソースを使うとか、
WM_ERASEBKGROUNDを殺して、ボタンの部分以外をクリッピングして
自分で背景を描画するとかかな。
もちろんsoftyaさんの案の子ウィンドウを使う方法の他にという意味で。

Re:再描画について

Posted: 2009年12月15日(火) 12:57
by softya
とりあえずstaticコントロールに文字を表示しただけの物です。
TextOutも使っていません。

こんな風にも出来るよって参考にしてください。

それとSetTimerの周期を1msにしてもOSのタスク・ディスパッチ周期が早くありませんので、0.001秒の周期ではWM_TIMERメッセージは発行されません。10msでも厳しいと思いますが一応10msにしてあります。

Re:再描画について

Posted: 2009年12月15日(火) 13:36
by たこやき
回答ありがとうございます。結局TextOutではチカチカうぃとめることは出来ないということなのでしょうか?

Re:再描画について

Posted: 2009年12月15日(火) 13:38
by たこやき
チカチカ止まっていました。回答ありがとうございます。

Re:再描画について

Posted: 2009年12月15日(火) 13:41
by たこやき
すみません。やっぱり出来ませんんでした。

Re:再描画について

Posted: 2009年12月15日(火) 14:14
by softya
>すみません。やっぱり出来ませんんでした。

意味がわかりません。
何ができなったんでしょうか?

ちなみにTextOut()を止めてもチラツキは完全には無くなりません。
ある程度抑えることが出来るだけです。

Re:再描画について

Posted: 2009年12月15日(火) 14:23
by たこやき
TextOutでボタンのチカチカをとめることは出来なかったと言うことです。
TextOutではチカチカをとめることは出来ないということなのでしょうか?

Re:再描画について

Posted: 2009年12月15日(火) 15:33
by たこやき
チカチカとることができました。タイチウさんありがとうございます。
ただ、TextOut()が2つあった場合どうすればよいのでしょうか。
自分でも考えてみたいとおもいます。

Re:再描画について

Posted: 2009年12月15日(火) 16:32
by たこやき
原点に戻ってしまいました。ボタンとかのチカチカは消えたのですが、今度はウィンドウのサイズを変更したらまたチカチカするようになりました。助けてください。。。

Re:再描画について

Posted: 2009年12月15日(火) 17:20
by softya
TextOutを子ウィンドウにだけ対応したもの。
どの程度のチカチカを避けたかが分かりませんが、このぐらいが限界です。
今回は、staticコントロールをサブクラス化して専用のウィンドウプロシージャで描画しています。

>ただ、TextOut()が2つあった場合どうすればよいのでしょうか。
この方式なら、どうとでもなります。

Re:再描画について

Posted: 2009年12月15日(火) 19:56
by たこやき
わかりました。回答ありがとうございました!!