April 30, 2024, 03:12:02 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


How to use OnPaint( )

Started by Parker, November 03, 2006, 04:51:47 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Parker

Whenever I resize the window I get duplicates of some of the graphics on the right - how do I get rid of these in OnPaint?

It seems OnPaint isn't being called when it is resized. Any way to solve that?

Ionic Wind Support Team

Depends on your code and what you're drawing.

Aurora has two methods of GDI drawing.  The first is by specifying AWS_AUTODRAW which creates an offscreen bitmap and remembers everything that is drawn into the window, eliminating the need to use the standard GDI method of erasing the background and drawing the foreground in response to OnPaint.

If you're not using an autodrawn window then Windows will invalidate your window whenever it is resized larger, provided you return FALSE in the OnSize and OnSizing handlers.  When a window is invalidated the OS sends a number of WM_PAINT messages, which causes your OnPaint handler to be called.

The default background color is set using SetWindowColor, you can draw your own background by overriding OnEraseBkgnd and returning TRUE to indicate that you handled the message and no other action should be taken.

Paul.
Ionic Wind Support Team

Parker

I don't really want autodraw because that would make drawing really akward.

There are two problems. They are demonstrated by the following screenshots.

This is the program as it is supposed to look (and how it does look when it first starts).


This is what happens when I shrink the class diagram window.


This is what happens when I expand the class diagram window.


It returns to normal when something covers up the window. I draw the background rectangle in OnEraseBkgnd, and the caption (and eventually the rest) in OnPaint.
DiagramWindow::OnPaint( )
{
RECT rc = GetClientRect( );
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
DrawMode( TRANSPARENT );

// "Caption"
DrawRect( 0, 0, width, 30, 0, 0xDDDDBB );
FrontPen( 0xFF0000 );
SetFont( "Courier New", 8, 100, SFITALIC );
WriteText( 5, 8, "Class" );

FrontPen( 0 );
SetFont( "Courier New", 10, 100 );
// 75 for Interface, 47 for Class, 54 for Struct
WriteText( 47, 8, "MyClass" );

// Draw "X" button
SetFont( "Verdana", 8, 1000 );
DrawRect( width - 18, 7, 14, 15, 0, 0x0000F0 );
WriteText( width - 15, 8, "X" );

return true;
}

DiagramWindow::OnEraseBkgnd( )
{
RECT rc = GetClientRect( );
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
DrawMode( TRANSPARENT );

DrawRect( 0, 0, width, height, 0, 0xFFF5F5 );
return true;
}


Any information on how to fix these problems would be appreciated.

Ionic Wind Support Team

And your OnSize/OnSizing handlers?  Windows is doing exactly what it is supposed to do based on your screen shots.  In the second shot of a downsizing of the rectangle you won't automatically get OnPaint messages since nothing in the windows is invalidated, you have to call InvalidateRect yourself to force the OnPaint message.

In the third shot of upsizing the window the, invalidated area is the region that is uncovered on the right/bottom.  Windows sends an OnPaint with those areas marked as invalid and does not automatically invalidate the inner rectangle.  Again that is your program responsibility to tell Windows that that rectangle (the inner one) needs to be redrawn by using the InvalidateRect API function. 

Isn't GDI programming fun ;).   

Quote
I don't really want autodraw because that would make drawing really akward.

No it wouldn't but that is your choice.  No matter what you're either going to be invalidating in response to OnSize or you're going to be drawing. 

Paul.





Ionic Wind Support Team

Parker

Adding InvalidateRect calls to OnSize and OnSizing solves those problems. It flickers, but that's okay for now.

Thanks
Parker

Ionic Wind Support Team

If your drawing the entire foreground of the rectangle in OnPaint, which it appears you are,  then you can use FALSE for the last parameter of InvalidateRect, which prevents OnEraseBkgnd from being called and reduces flicker.  In other words there is no reason to paint twice when the background is not showing through.

Ionic Wind Support Team

Parker

Thanks. It's still there, but it's barely noticeable :D

Ionic Wind Support Team

Beyond not drawing the background it gets more complicated to reduce flicker in Windows.  To completely remove flicker you have to cache any GDI drawing to an off-screen bitmap, much like the AWS_AUTODRAW method does, and then use the BitBlt function to transfer the bitmap all at once to the rectangle.

There are other techniques depending on what you're doing.  Scrolling is usually a flicker fest unless you use ScrollWindowEx and only invalidate the uncovered portion of your document, image, whatever.

If you ever get into those areas we are here to help.
Ionic Wind Support Team