タブのオーナードローでちらつきを解消する方法

このQ&Aのポイント
  • WindowsSDKを使って画面を作成している際に、タブをオーナードローしているとちらつきが発生します。WM_DRAWITEMメッセージでタブの描画を行っているが、転送処理によりちらつきが目立つため困っています。
  • WM_ERASEBKGNDでreturnすることでちらつきを解消できますが、背景色で塗りつぶされなくなります。タブが表示される箇所にウィンドウを上に置くと問題が発生します。
  • WM_DRAWITEMが頻繁に呼び出されているため、ちらつきが生じていると考えられます。解消方法をご教授いただきたいです。
回答を見る
  • ベストアンサー

タブをオーナードローすると、ちらついてしまいます

質問させていただきます。 WindowsSDKを用いて、画面を作成しています。 MFCは使用していません。 タブを使っていますが、タブは作成時にTCS_OWNERDRAWFIXEDを指定しています。 WM_DRAWITEMメッセージが来たら、タブを描画していますが どうしてもちらつきが目立ってしまいます。 WM_DRAWITEMでの処理は、初めにタブの裏画面に描画し 最後にタブに通知された、DRAWITEMSTRUCTのhDCに裏画面の内容をBitBltで転送しています。 メイン画面もダブルバッファリングを行っておりますが、メイン画面はちらついていません。 タブ側で、WM_ERASEBKGNDで何もせずreturnすると、ちらつきはなくなりますが 背景色で塗りつぶされなくなるため、タブが表示される箇所にウィンドウを上に置いたりすると そこが残ってしまいます。 WM_DRAWITEMが頻繁によばれているため、これはちらついているのでしょうか? 解消方法に頭を悩ませております。 どうぞご教授の程お願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>DRAWITEMSTRUCTのrcItemですが、きちんと、渡されたleft,top,right,bottomに収めて描画はしております。 そうすると…チラ付きはやはりWM_ERASEBKGNDが関係していることになる…でしょうね。 WM_DRAWITEMの前に毎回WM_ERASEBKGNDが来る…ということはないかと思われますが、その辺りはどうなんでしょう? Spy++などで確認できるかと思われますが…。 再描画に1回だけ…であれば、WM_ERASEBKGNDの時にタブ以外の場所を裏画面から描画することで回避できませんかね。 タブ部分はWM_DRAWITEMで描画しますし。

その他の回答 (1)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

オーナードローはやったことありませんが… DRAWITEMSTRUCT構造体のrcItemメンバの範囲を超えて描き換えしていたりはしないですか?

mmo_mmo_rag
質問者

補足

ご回答有難うございます。 DRAWITEMSTRUCTのrcItemですが、きちんと、渡されたleft,top,right,bottomに収めて描画はしております。

関連するQ&A

  • WinAPIで画像を更新し続けるには

    本を見ながら、WindowsSDKを使ってビットマップを描画する 所まではできたのですが、動かそうとすると上手くいきません。 ソースを簡略かして載せますと、以下のようにしています。 case WM_KEYDOWN: x++; // static MyDrawBitMap( hWnd, x, 10 ); ------------------------------------------------ void MyDrawBitMap( HWND hWnd, int x, int y ) { hdc = BeginPaint(hWnd, &ps); BitBlt( hdc, x, y, bitmap.bmWidth, bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); このように書いてますが、ボタンを押しても画面に変化が出ません。 PAINTSTRUCTは再描画が必要な情報に関する構造体だとは解っていま すが、特に変更の必要の無い画像も再描画したい場合の処理はどうす れば良いのでしょうか?よろしくお願いします。

  • GDI+について

    いつもお世話になっております。 今回教えていただきたいことは、GDI+についてです。 今まで GDI と OpenGL を組み合わせてプログラミングをしていましたが、GDIでは自前でアンチエリアス処理をしなければならないなど面倒な部分が多く困っていました。 そこで GDI+ を使用して楽にプログラミングしようと考えて色々とプログラムをしてみたのですが、ここにきて壁にぶち当たりましたので、先人の方にご教授していただきたいのです。 《 GDI でプログラムしていた時 》 (1)画像バッファを作成しておく  //ディスクトップのDCを取得  HDC hdcTmp = GetDC( GetDesktopWindow() );  //ビットマップのハンドルと、作成したバッファの先頭アドレスを取得  hBitmap = CreateDIBSection( hdcTmp, &bmi, DIB_RGB_COLORS, (void**)&buffer, 0, 0 );  //HBITMAPにHDCを結び付ける  hdc = CreateCompatibleDC( hdcTmp );     //DIBSection用メモリデバイスコンテキスト作成  hOldHandle = SelectObject( hdc, hBitmap );       //画像バッファ(m_hBitmap)をメモリデバイスコンテキストに選択 (GDIでも描画出来るようにするため) (2)画像バッファ上にGDIで描画する  hdcに対してGDIの関数を使用して描画 (3)BitBlt()でウィンドウに転送する  WM_PAINTのメッセージのときだけウィンドウに対して転送 上記(1)(2)(3)のようにして描画を行っていました。 ■したいこと(1)■ 今したい事は 上記(1)で作成したGDI の画像バッファのhdcを使ってGDI+関数で描画したいのです。 そうするといままで使っていたGDIの知識を生かして両方使えます。 ■したいこと(2)■ したいこと(1)がもし出来ないのであればGDI+での画像バッファがつくれるかどうか、その画像バッファのデバイスコンテキスト は取得できるのかどうか教えていただきたいと思います 情報不足かもしれませんが、ご教授よろしくお願いいたします。

  • ドローソフトのダブルバッファリングプログラム

    現在、MFCを使ったドローソフトを作成しています。 仕様はキャンバス上にい色々な部品をマウスで配置するといったものです。 画面描画の際の画面チラつき防止にダブルバッファリングという手法があり 裏画面でキャンバスの背景と部品を作成し、表画面に転送するものがある事を知りました。 そこで質問なのですが マウスで一つの部品を選択し移動する場合、背景はどのように描画すべきなのでしょか? もしも、キャンバス上に部品がたくさん有る場合、毎回、全てを描画し直していたら処理が 遅くなってしまいます。 選択した部品だけ再描画する効率的な方法をご存知の方がいました教えて下さい。 どうぞ宜しくお願い致します。

  • c++ ダブルバッファリング、以下のコードでできず

    こんばんわ。visual studio express 2013でC++を勉強している者です。 ダブルバッファリングをしたいのですが、チラつきが改善しません。 どう書けばダブルバッファリングを実現できるのか、ご教授ください。 以下は私が書いたコードの一部です。よろしくお願いします。 (要は、hdc_mem1のビットマップを、hdc_mem0(白紙のビットマップ)に読み込み、hdc_mem0のみを画面に表示しようとしています。 いずれは用意したすべての種類のビットマップをhdc_mem0に読み込み、hdc_mem0のみ画面に表示させることによってチラつきを抑えようと考えています) case WM_CREATE:  hdc = GetDC(hWnd);  hBmp0 = LoadBitmap(hInst, TEXT("MYBMP0"));  GetObject(hBmp0, (int)sizeof(BITMAP), &bmp_info0);  hdc_mem0 = CreateCompatibleDC(hdc);  SelectObject(hdc_mem0, hBmp0);  hBmp1 = LoadBitmap(hInst, TEXT("MYBMP1"));  GetObject(hBmp1, (int)sizeof(BITMAP), &bmp_info1);  hdc_mem1 = CreateCompatibleDC(hdc);  SelectObject(hdc_mem1, hBmp1);  DeleteObject(hBmp0);  DeleteObject(hBmp1);  ReleaseDC(hWnd, hdc);  break; case WM_PAINT:  hdc = BeginPaint(hWnd, &ps);  BitBlt(hdc_mem0, 0, 0, bmp_info1.bmWidth, bmp_info1.bmHeight, hdc_mem1, 0, 0, SRCCOPY);  BitBlt(hdc, 0, 0, bmp_info0.bmWidth, bmp_info0.bmHeight, hdc_mem0, 0, 0, SRCCOPY);  EndPaint(hWnd, &ps);  break; case WM_DESTROY:  DeleteDC(hdc_mem0);  DeleteDC(hdc_mem1);  PostQuitMessage(0);  break;

  • ダブルバッファの作り方

    画面に描画するBCC5.5 のCプログラムがあります。画面がちらつくので、ダブルバッファにしたいのですが、具体的に、どの関数を呼んで実装したらよいのかわかりません。WEB検索をしますと結構情報がヒットしますが、解決に至ってませんので、よろしくお願いします。 具体的にやったことは、現在動いているプログラムの case WM_PAINT:  hdc=BeginPaint(hWnd,&ps);  paint(hdc); // 自作の描画プログラム本体  ReleaseDC(hWnd,hdc);  EndPaint(hWnd,&ps);  break; の部分を、「画面サイズのビットマップイメージhBitmapをつくり、そこにpaint関数で描き込み、最終画面を一気に出力する」というつもりで以下のプログラムに書き換えたのですが、表示すらしなくなってしまいました。何が悪いのかお教えください。 case WM_PAINT:  GetClientRect(hWnd,&rt);   h = (int)rt.bottom;   w = (int)rt.right;  hBuffer = CreateCompatibleDC(NULL);  hBitmap = CreateCompatibleBitmap(hBuffer, w, h);  SelectObject(hBuffer, hBitmap);  paint(hBuffer);  hdc=BeginPaint(hWnd,&ps);   BitBlt(hdc, 0,0,w,h, hBuffer,0,0, SRCCOPY);  ReleaseDC(hWnd,hdc);  EndPaint(hWnd,&ps);  DeleteDC(hBuffer);  DeleteObject(hBitmap);  break;

  • Windowsプログラミング 画面描画 ちらつき

    SetDIBitsToDevice関数を使って画面に描画をした後、LineTo関数やEllipse関数を使って その画面上に線や丸を表示させる処理をしているのですが、描画処理を一度にできていないためか ちらつきが発生してしまいます。 調べてみるとビットマップのマルチバッファリングなどが解決策にあるのですが、 私は一次元配列で画素値を格納していてビットマップに情報は保持していないため よく解決策で使われているBITBLTが使えない状態です。 裏画面に描画しておいて、最終的に描画は一度だけにするという考えは分かるんですが、 これをSetDIBitsToDevice関数を用いてちらつきが発生しないようにできるんでしょうか? プログラムとしては画像の上に線と円をひたすら描画していくようなイメージをしています。 アドバイスお願いします! case WM_PAINT: hDC=BeginPaint(hParent,&ps); SetDIBitsToDevice( ps.hdc, 0, 0,// コピー先x,y座標 pimg -> bih.biWidth,// DIBの幅 pimg -> bih.biHeight,// DIBの高さ 0, 0,// DIBの座標 0,// 走査線 pimg -> bih.biHeight,/ 走査線数 pimg -> lpBmpData, (BITMAPINFO *)&( pimg -> bih),// BITMAPINFOにキャスト DIB_RGB_COLORS ); for(int i=0; i<number-1; i++){ if(i==0){  hPen1 = CreatePen(PS_SOLID, 1, RGB(255,0,0));  electObject(hDC,hPen1);  MoveToEx(hDC,Xs,Ys,NULL);  Ellipse(hDC,Xs-2,Ys-2,Xs+2,Ys+2); }else{  LineTo(hDC,Xe,Ye);  Ellipse(hDC,Xs-2,Ys-2,Xs+2,Ys+2); } }

  • マウスの反応

    C言語とWIN32APIでプログラミングしています。 いつも多くの方にお世話になっています。 ■ボタンの上にマウスカーソルが来た時、ボタンが反応する様な事を考えています。 ■Web画面でよくあるロ-ルオーバーの様な事です。 上記の様な事を思い、下記の様に記載しました(概略)。 ところが、クリックには反応しますが オンマウスには反応しません。 ■質問 ・マウスカーソルがボタンに乗った時、反応するには何が必要ですか? case WM_DRAWITEM: if(wp==ID_BTN_0) { DrawText(DrawItem->hDC,str,-1,&DrawItem->rcItem,DT_CENTER); ******************************************************** //オンマウスで色を反転する.....目的 if((DrawItem->itemAction) & (ODA_FOCUS)){ InvertRect(DrawItem->hDC,(LPRECT)&DrawItem->rcItem); } ******************************************************** if((DrawItem->itemState) & (ODS_SELECTED)){ DrawEdge(DrawItem->hDC,(LPRECT)&DrawItem->rcItem,EDGE_SUNKEN,BF_RECT); }else{ DrawEdge(DrawItem->hDC,(LPRECT)&DrawItem->rcItem, EDGE_RAISED,BF_RECT); } } break;

  • GDIからDirectXへの移行

    描画速度を向上させるため、DirectXを使いたいと思っているのですが、裏画面を作成して、線を引いて、文字を書いて、画面に転送するだけの簡単なCでのサンプルはどこかにないでしょうか? サイトや本を探しても、3Dや複雑なサンプルばっかりで、Hello Worldのような超簡単なサンプルを探しています。 今は、CreateCompatibleBitmapで裏画面を作成して、GDIで描画して、BitBltで画面に転送しています。

  • WM_PAINTとBitBlt

    レベルはWindowsプログラミングを始めて1月半、それ以前にプログラミング経験はありません。 環境は、VC++6.0 WindowsXP SP2です。 WINAPIしか使えません(MFCは分かりません)。 宜しくお願い致します。 定期的に図形を動かすプログラムを副スレッドを用いて作りました。 副スレッドにはSleep(5msスリープ)を入れてあり、スレッドの最後にInvalidateRectを実行し、WM_PAINTを発行して再描画させているのですが、動作は所望な通りなものの、画面がちらついてしまいます。 所持している参考書を読むと、図形を動かす処理を直接ディスプレイに出すのではなく、メモリDCに一度出力し、その後BitBltでディスプレイに出力すればよい(ダブルバッファのことらしい?)、と書いてありました。 また、あるサイトには、WM_PAINTが実行されるとOnEraseBkgndが走るからちらつくとも書いてあり、何だか良く分かりません。 (別のサイトにはOnPaintが走るとか、OnPaintBackgroundが走ると書いてあり、何が本当なのか???) 自分の知りたいことは以下の通りです。 1)WM_PAINTで画面の再描画を行うと画面が何故チラつくのですか? また、ちらつかない様にする方法はあるのでしょうか? 2)BitBltを用いるとチラつかないのは何故でしょうか? 3)参考までにですが、メモリDCでBitBltで転送、以外に画面をチラつかせずに画面を更新させる方法はあるでしょうか? 色々サイトを探してみてのですが、断片的にしか書いておらず、結局自分が所望する回答は得られませんでした。 初心者レベルなので、分かりやすく説明して頂けると大変嬉しいです。 以上、宜しくお願い致します。

  • Windowのちらつき防止

    WEB検索をしますと結構情報がヒットしますが、 解決に至ってませんので、よろしくお願いします。 Win32アプリケーションです。 WM_PAINTのタイミングでWindowに文字を描画してますが、 背景の塗りつぶしが原因でちらつきます。 WM_ERASEBKGNDメッセージをつぶせない仕様ですので、 よく用いられる方法で、ビットマップによるダブルバッファリングを行ったところ、 ちらつきが抑えられましたが、極端に遅くなってしまいました。 質問1 ビットマップに描画して画面に転送するという動作は どうしたら早くできるでしょうか? 質問2 どんな方法でも結構ですので、画面のちらつきを抑える方法はないでしょうか? どんなささいなことでもかまいませんので お願いします。 不足している情報がありましたら、ご指摘ください。 補足させていただきます。 こちらの掲示版はなにか返答がなければ、もう本人は何もできませんので。

専門家に質問してみよう