Click to See Complete Forum and Search --> : GD+ drawing problem


Alberto_Canabal
November 24th, 2005, 09:25 AM
Hi.
I have developed a VC++ app that uses GDI+.
When drawing my components (almost all of them created by me), and passing another window over them, they do not paint correctly (for example, text appears by half, or lines appear cut).

I thought it was an "invalidate" problem (calling invalidate when i didn't have to), so i intercepted windows's message to the forms, and called invalidate(true) when movement was detected...this worked OK, but the problem now are CPU ussage leaks (up to 70%) when moving forms...

Any idea of what i'm doing wrong?

Thanks

Marc G
November 24th, 2005, 09:34 AM
Where are you drawing your components?
All drawing should be done in response to a WM_PAINT message.

Alberto_Canabal
November 24th, 2005, 10:33 AM
Drawing is done in response to WM_PAINT...

Alberto_Canabal
November 25th, 2005, 06:34 AM
Another thing that happens in my app. is that i can´t catch WM_MOVING, WM_MOVE or their sizing counterparts...doesn´t this turn any lights on?

Alberto_Canabal
November 25th, 2005, 06:35 AM
Soryy, forgot to say: I catch movement via a series of messages

Marc G
November 25th, 2005, 07:40 AM
I don't know what the problem is.
Can you post your WM_PAINT code and the code in your WM_MOUSEMOVE etc handlers?

Alberto_Canabal
November 25th, 2005, 08:16 AM
Sorry, can´t post any code (politics...), but, in pseudo code, my onDraw function is:

void MyViewClass::OnDraw(CDC* pDC)
{
pDC->SetBkColor(....);

CMemDC mDC(pDC);
Graphics graphics(mDC->m_hDC);

graphics.SetInterpolationMode(...);
graphics.SetSmoothingMode(...);
graphics.SetCompositingQuality(...);

CRect rcClipBox;
pDC->GetClipBox(&rcClipBox);
//Draws all components in the clipbox...
PaintAllComponents(rcClipBox);
}


Could it be a matter of drawing speed? (sincerely hope not...)

Marc G
November 25th, 2005, 12:59 PM
Can't help you any further :(
Anyone else also experiencing this problem?

Alberto_Canabal
November 25th, 2005, 01:52 PM
Only one more thing:
I´ve tried inflating the CDC´s clipping area: no luck. Ditto with the graphics clipping area, or any area i´ve encountered 10 blocks away from home, hoping it would be that. But just maybe i´m doing it wrong...


//To inflate the CDC* clipping area...
CRect rectBox;
pDC->GetClipBox(&rectBox);
rectBox.InflateRect(100, 100);
CRgn* pRgn = new CRgn();
pRgn->CreateRectRgnIndirect(rectBox);
pDC->SelectClipRgn(pRgn);
//.........
graphics.SetClip(FRect(rectBox));


If you hear of someone killing a computer, it´s me.

Thanks.

gstercken
November 26th, 2005, 10:36 PM
Only one more thing:
I´ve tried inflating the CDC´s clipping area: no luck. Generally, messing around with the clipping region is not required - there must be something else fundamentally wrong with the way you are drawing your window contents. Unfortunately, the pseudo-code you posted doesn't provide any helpful hints for solving your problem. If you can't post actual code for "political" reasons, try to create a simple, new project which draws something to a view using GDI+ and which reproduces the problem and post it here.

Alberto_Canabal
November 29th, 2005, 09:42 AM
I solved the drawing problem (was an issue with the call that made double-buffering), but the CPU usage is still huge. Could it be a matter of GDI+?

Marc G
November 29th, 2005, 10:40 AM
What is huge? How much %?

To speed it up you might want to keep an offscreen buffer with your drawing. That way you can simply blit the offscreen buffer back to the screen when it needs to be repainted. Then you only need to update=redraw the offscreen buffer when something really needs to change: for example: and object moved.

Alberto_Canabal
December 1st, 2005, 07:45 AM
Let's see...
To start monitoring things, i wrote another simple GDI+ app., which draws a static rectangle and marks a variable area with a grid. The app. doesn't use double buffering (for the sake of simplicity)...

Here is my whole OnPaint method:


//Get the invalid rectangle...
CRect rect;
GetUpdateRect(&rect);

CPaintDC dc(this);
Graphics graphics(dc.m_hDC);

//Clear the background...
graphics.Clear(Color::Black);

Color colorCross = Color::Red;
HatchBrush oBrushCross(HatchStyleCross, colorCross,
Color(0,0,0,0));

Pen oPenCross(colorCross, 0.0);

RectF oRect(
rect.TopLeft().x + 50,
rect.TopLeft().y + 50,
rect.Width() - 50,
rect.Height() - 50);

//Paint the area with a grid...
graphics.FillRectangle(&oBrushCross, oRect);
graphics.DrawRectangle(&oPenCross, oRect);

Color color = Color::Yellow;
HatchBrush oBrush(HatchStyleBackwardDiagonal, color,
Color(0,0,0,0));
Pen oPen(color, 0.0);

//Draw a static rectangle
RectF ooRect(100, 100, 200, 200);
graphics.FillRectangle(&oBrush, ooRect);
graphics.DrawRectangle(&oPen, ooRect);


Results:
When hovering another window over the dialog...
- CPU usage reaches nearly 70% (i'm working on a pretty good computer)
- Drawing is horrible...it leaves "garbage", or doesn't repaint the variable area ok...i've also added double buffering, and the problem is not solved...

Thanks!

gstercken
December 1st, 2005, 11:06 AM
To start monitoring things, i wrote another simple GDI+ app., which draws a static rectangle and marks a variable area with a grid. The app. doesn't use double buffering (for the sake of simplicity)...

Here is my whole OnPaint method:


//Get the invalid rectangle...
CRect rect;
GetUpdateRect(&rect);

...

RectF oRect(
rect.TopLeft().x + 50,
rect.TopLeft().y + 50,
rect.Width() - 50,
rect.Height() - 50);

Results:
When hovering another window over the dialog...
- CPU usage reaches nearly 70% (i'm working on a pretty good computer)
- Drawing is horrible...it leaves "garbage", or doesn't repaint the variable area ok...i've also added double buffering, and the problem is not solved...Well, why are you using the invalid rect as a base for the objects you are drawing? The invalid rect will change with every WM_PAINT message - as you drag another window over your window, the invalid area changes all the time, and the sizes of your drawn objects will change constantly.
You should rather use the client area of your Window (GetClientRect).

Alberto_Canabal
December 1st, 2005, 01:06 PM
The idea on using the invalid area is to see what GDI+ is doing, and compare it with my expectations...
In this case, it draws a sort of lines where it doesn't have to, or draws incomplete figures (the grid is not show entirely)...
Try the code, simply putting a window over the image and minimizing it...i expected a grid well drawn, but...nope.

gstercken
December 1st, 2005, 04:11 PM
The idea on using the invalid area is to see what GDI+ is doing, and compare it with my expectations...
In this case, it draws a sort of lines where it doesn't have to, or draws incomplete figures (the grid is not show entirely)...
Try the code, simply putting a window over the image and minimizing it...i expected a grid well drawn, but...nope.As said above: When using GetUpdateRect() for determining your drawing bounds, you will never get a "grid well drawn", but only useless junk. The reason is that the rectangle returned by GetUpdateRect() will vary with every WM_PAINT message - it's not the rectangle which describes your drawing area, but the enclosing rectangle of the invalid region at that moment. Have you tried using GetClientRect() instead?
The purpose of GetUpdateRect() is to supply additional information about the rectangle enclosing the invalid region for optimization purposes (for example, you could have some strategy which excludes objects from costly rendering if they don't intersect with the invalid region).
So please use GetClientRect() instead, and report whether you are experiencing the same problems.

Alberto_Canabal
December 2nd, 2005, 09:09 AM
That does almost what I want it to...when i do something like:

graphics.DrawRectangle(pen, rect);
graphics.FillRectangle(brush, rect); //rect is the same...

painting is OK (but huge CPU usage...)...but if i do:

graphics.FillRectangle(brush, rect); //rect is the same...
graphics.DrawRectangle(pen, rect);

sometimes the painting doesn't show complete...

I know it has little to do with the subject, but perhaps some of you experienced this kind of problem...