ペイントソフトを作っているのですが…

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
KEYONN_

ペイントソフトを作っているのですが…

#1

投稿記事 by KEYONN_ » 15年前

WIN32APIの応用として、ペイントソフトを作っています。しかし、問題が発生してしまいました。
長時間、描画命令を繰り返すと、ウィンドウが変に描画されてしまいます。
どういう風に変かというと、説明しずらいのですが、メニューだけが消えたり、
ウィンドウが消えたりします。なので、デバッグしているのですが、
デバッグしても、原因が分からないのです。なにしろ、本格的なウィンドウズアプリケーションを
C言語(C++)で作ったのは初めてですので…。

ソースを載せますね。

原因が分かる方はどうかアドバイスをください。宜しくお願いします。

環境は、VC++6.0でWindowsXPです。 画像

YuO

Re:ペイントソフトを作っているのですが…

#2

投稿記事 by YuO » 15年前

コードは見ていないですが,症状だけを見るとGDIリソースをリークさせているのではないかと思います。
例えば,CreatePenでペンを作ったあと,不要になったら,
ペンがどのDCにも選択されていない状態にしてDeleteObjectする必要があります。

タスクマネージャのプロセスタブで,列としてGDIオブジェクトを表示させておいた場合に,
対象プロセスのGDIオブジェクトの数が増加していくのであれば,間違いなくGDIリソースのリークです。

KEYONN_

Re:ペイントソフトを作っているのですが…

#3

投稿記事 by KEYONN_ » 15年前

GDIというか、CreateDIBSectionで32ビットのDIBを作成して、そこのバッファ(LPDWORD lpPixel)に
書き込んでいます。
なので、DIBSectionなので、GDIでも自前描画クラスでもピクセルバッファに書き込めるのですが、
あえて、自前描画クラスで書き込んでいます。
クラスは、下のような感じです。
//描画用クラス
class CDraw{
private:
    int width;
    int height;
    
    struct BufStr buff[MAXSIZE]; /* シード登録用バッファ */
    struct BufStr *sIdx, *eIdx;  /* buffの先頭・末尾ポインタ */
public:
    int OldPointX;
    int OldPointY;
    int DrawMode;
    int DrawCount;
public:
    CDraw()
    {
        //(コンストラクタ)特に無し
    }
    CDraw(int xwidth,int yheight)
    {
        width=xwidth;
        height=yheight;
    }
    ~CDraw()
    {
        //(デストラクタ)特に無し
    }
    int GetPoint(int x,int y)
    {
        if(x<0 || x>width) return 0;
        if(y<0 || y>height) return 0;
        if(y==0) y=1;
        int p=lpPixel[x+(480-y)*width];
        int a,r,g,b;
        a = (p>>24&0xFF);
        r = ((p>>16)&0xFF);
        g = ((p>>8)&0xFF);
        b = (p&0xFF);
        int Col2 = (b<<16) | (g<<8) | r | 0xff000000;
        return Col2;
    }
    void DrawPixel(int x,int y,int Col)
    {
        int a,r,g,b;
        a = (Col>>24&0xFF);
        r = ((Col>>16)&0xFF);
        g = ((Col>>8)&0xFF);
        b = (Col&0xFF);

        int Col2 = (b<<16) | (g<<8) | r | 0xff000000;
        if(x<0 || x>width) return;
        if(y<0 || y>height) return;
        if(y==0) y=1;
        lpPixel[x + (480-y) * width] = Col2;
        
        
    }
    void ColorDivide(int Col,int *r,int *g,int *b)
    {
        *r=((Col>>16)&0xFF);
        *g=((Col>>8)&0xFF);
        *b=(Col&0xFF);
    }
    void DrawRect(int x0,int y0,int x1,int y1,int Col)
    {
        int i,j;//矩形を描画するメンバ関数

        for(i=x0;i<x1;i++)
        {
            for(j=y0;j<y1;j++)
            {
                DrawPixel(i,j,Col);
            }
        }
        
    }
    void DrawLine(int x0,int y0,int x1,int y1,int Col)
    {
        int i;//線を描画するメンバ関数

        int dx = ( x1 > x0 ) ? x1 - x0 : x0 - x1;
        int dy = ( y1 > y0 ) ? y1 - y0 : y0 - y1;
        int sx = ( x1 > x0 ) ? 1 : -1;
        int sy = ( y1 > y0 ) ? 1 : -1;

        /* 傾きが1以下の場合 */
        if( dx >= dy )
        {
            int E = -dx;
            for( i = 0 ; i <= dx ; i++ ) 
            {
                DrawPixel(x0,y0,Col);
                x0 += sx;
                E += 2 * dy;
                if( E >= 0 )
                {
                    y0 += sy;
                    E -= 2 * dx;
                }
            }
        /* 傾きが1より大きい場合 */
        } else 
        {
            int E = -dy;
            for( i = 0 ; i <= dy ; i++ ) 
            {
                DrawPixel(x0,y0,Col);
                y0 += sy;
                E += 2 * dx;
                if( E >= 0 )
                {
                    x0 += sx;
                    E -= 2 * dy;
                }
            }
        }
        
    }
void DrawCircle(int mx,int my,int r,int Col)
{
    int sx=mx-r;
    int sy=my-r;
    int dx=mx+r;
    int dy=my+r;

    int x,y;

    for(y=sy;y<=dy;y++)
    {
        for(x=sx;x<=dx;x++)
        {
            //円の範囲内?
            if( (x-mx)*(x-mx)+(y-my)*(y-my)<=r*r)
            {
                DrawPixel(x,y,Col);
            }
        }
    }
}
};

SGGK

Re:ペイントソフトを作っているのですが…

#4

投稿記事 by SGGK » 15年前

ぱっと見ただけだけど、
・WndProc の WM_TIMER
・MyDlgProc の WM_PAINT
でリソースリークが発生してる。

後、WM_TIMER ではきちんとIDをチェックした方が良いよ。
SetTimer() をするのは自分だけでは無く、システムも必要に応じて SetTimer() してくるから。

KEYONN_

Re:ペイントソフトを作っているのですが…

#5

投稿記事 by KEYONN_ » 15年前

YuOさんへ
SGGKさんへ

ありがとうございました。おかげでメモリリークはなくなりました。
ご協力ありがとうございました。

しかし、これから、また新しい関数を作ると、メモリリークする機会が出てくると
思います。なので、注意したいです。

解決ボタンを忘れてました。すみません。 画像

閉鎖

“C言語何でも質問掲示板” へ戻る