描画した線の消去方法

[戻る]
コロ 2009/10/06(火) 22:13:58
開発環境 Windows XP Visual C++6.0  SDIです。

早速質問させてください。

画像処理ソフトを作成していて、描画した線(多角形)をマウスでドラッグした時の動作
に関する質問です。

表示した画像(DIB画像)に多角形を描画して、多角形をマウスでドラッグして移動する
(移動の軌跡を表示したい)方法についての質問です。

画像表示はOnDraw内でDIB画像をStretchDIBits()で転送後に多角形を描画しています。
(質問の最後に記載)

OnMouseMove内でInvalidate(FALSE)で再描画すれば所望の動作はするのですが、ドラッ
グ中の処理負荷が半端じゃないです。

四角形の場合はDrawDragRect()という便利な関数があるのですが、多角形の移動で
DrawDragRectと同様の機能を自分で実装するにはどうすればよいでしょうか?

描画の方法として下記方法があることは理解できているのですがうまくいきません。
@描画したい領域のみ更新するようにInvalidateRect()を使用
 →多角形が大きい場合はこの方法では効果がない
AXORのラスターオペレーション(pDC->SetROP2(R2_XORPEN))を使い、
WM_MOUSEMOVEの中で前回分を消す。 今回分を描く
 →消した線が黒になってしまう。どうやって使用したらいいの??


//OnDrawでの描画はDIB画像を表示した後に、多角形を表示という構成です。
void xxxView::OnDraw(CDC* pDC){

    
    //DIB画像(Jpeg画像やBitMap等)を表示
    StretchDIBits(パラメータは省略)

    //多角形を表示
    pDC->Polyline(lpPoints, nCount );
}


過去ログの↓は読みましたが、解決できませんでした。

http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200304/03040059.txt

アドバイスをお願いいたします。

コロ 2009/10/06(火) 22:30:44
開発環境 Windows XP 
Visual Studio6.0  MFC SDIです。

仲澤@失業者 2009/10/07(水) 09:54:32
まず、
OnDraw()内でStretchDIBits()をやっていたのでは時間がかかるでしょうね。
OnDraw()内では裏バッファDCから表のDCに対してBitBlt()だけを行うように
変更しましょう。これでかなり早くなります。
裏バッファへの更新処理は現在OnDraw()内でやっていることをやればよいわけです。
OnSize()での裏バッファサイズ変更処理も必要です。

次に、
多角形描画ですが、このような処理をラバーバンド描画と呼ぶ場合もあります。
最近のCPU GPUは早いので通常通りの描画(@)で間に合ってしまう場合がほとんど
ですが、昔のCAD等はAのXOR描画を使っていました。Aのコツは、XORで同じ
描画を2回行うと元に戻るという性質を使っています。線を消すには
 1.線をXORで描画する。この線をA線ととする(この線は見える)
 2.マウス移動されたら
 3.A線をXORで再度描画(この段階でA線は消える)
 4.A線の座標を変更する。
 1.に戻る
を繰り返します。

仲澤@失業者 2009/10/07(水) 10:23:13
ついでだから裏DCの作り方(笑)。
class UraDC : public CDC{ public:
    CBitmap   m_bitmap;    // 選択しているBitmap
    CBitmap * m_OldBitmap;    // 旧ビットマップ
    UraDC(){
        OldBitmap = NULL;
    }
    void Creat_or_ReSize( CWnd * OwnerWnd, const CRect& rc){
        Destroy_Me();
        CDC *OwnerDC = OwnerWnd->GetDC();
        CreateCompatibleDC( OwnerDC);
        m_bitmap.CreateCompatibleBitmap( OwnerDC, rc.Width(), rc.Height());
        m_OldBitmap = SelectObject( &m_bitmap);
    }
    void    Destroy_Me(){
        SelectObject( m_OldBitmap);
        m_bitmap.DeleteObject();
        DeleteDC();      
    }
};
てな感じ、ソラで書いたので仕組みの説明だけってことでご勘弁。

コロ 2009/10/07(水) 18:52:02
>仲澤@失業者様
アドバイスありがとうございます。
StretchDIBitsが時間がかかる関数とは知りませんでした。
さっそく裏DCを作成してBitBltを用いる方法に変更してみます。

でき次第報告させて頂きますが、取り急ぎご御礼まで。

コロ 2009/10/08(木) 22:37:02
[[解決]]
裏DCを作成してBitBltを用いる方法にして、必要領域のみ再描画でCPU負荷が大幅に低減
でいました。

StretchDIBitsとBitBltでは処理負荷がだいぶ違うことが実感できました。

>仲澤@失業者様

アドバイスありがとうございました。

古いスレッドには追加発言できません。