Hey all,

Here's my question:
why would I ever *not* use a private DC for a window? It's so much less coding to worry about... I don't have to keep calling GetDC and ReleaseDC, etc. My Windows API warns me that a private DC is not a good idea because it consumes (a whopping) 800 bytes. I feel that I'm missing something. Does this 800 bytes come from somewhere that 800 bytes would hurt? Or does it matter?

--Chorus
Posted on 2002-04-16 21:56:30 by chorus
A window already has its own DC, it needs it because it is visible. So the first question I would ask you is just what are ya gonna do with another DC?

Huh?


;-)
Posted on 2002-04-16 22:20:44 by Ernie
Usually, (from my experiences), you would use the primary DC only when windows says to your program its time to rePAINT the window again. Being a friendly OS, it gives you a chance to add any other stuff you would like on your window in the WM_PAINT handler.

However, to draw directly to this DC alot, consumes time, and can cause 'flickering' on the window (as its being drawn in real time). So often a second private DC is used to pre-draw the needed images, and bltblt (copy) the image from the private to the main. THis is reasonably fast, so the flicker is then taken care of.

This is called backbuffering.

As well, Text operations in most cases can be drawn directly on to the primary DC....

Hope this helps..
:alright:
NaN
Posted on 2002-04-17 00:50:48 by NaN
Ernie, you're a bit wrong. Read the PlatformSDK:

If no device-context style is explicitly given, the system assumes each window uses a device context retrieved from a pool of contexts maintained by the system. In such cases, each window must retrieve and initialize the device context before painting and free it after painting.


Now, assuming the original question is about CS_OWNDC, this
also answers the question. With CS_OWNDC, you can retrieve the
DC once, and keep using this handle value on every repaint. Without
this style, you have to retrieve the handle every time you need it,
as it can theoretically change. However, most windows only need
a hdc in WM_PAINT, where you're supposed to call BeginPaint/EndPaint,
and since BeginPaint returns a HDC... well, I guess you should only
use CS_OWNDC if you have a reason to :).
Posted on 2002-04-17 07:23:16 by f0dder
here's an additional statement, adding some small hints to f0dders answer:

There are three types of DCs for video displays:

* Class
* Common
* Private

Class Device Contexts

Class device contexts are supported strictly for compatibility with 16-bit versions of Windows. When writing your application, avoid using the class device context; use a private device context instead.

Common Device Contexts

Common device contexts are display DCs maintained in a special cache by the system. Common device contexts are used in applications that perform infrequent drawing operations. Before the system returns the DC handle, it initializes the common device context with default objects, attributes, and modes. Any drawing operations performed by the application use these defaults unless one of the GDI functions is called to select a new object, change the attributes of an existing object, or select a new mode.

Because only a limited number of common device contexts exist, an application should release them after it has finished drawing. When the application releases a common device context, any changes to the default data are lost.

Private Device Contexts

Private device contexts are display DCs that, unlike common device contexts, retain any changes to the default data?even after an application releases them. Private device contexts are used in applications that perform numerous drawing operations such as computer-aided design (CAD) applications, desktop-publishing applications, drawing and painting applications, and so on. Private device contexts are not part of the system cache and therefore need not be released after use. The system automatically removes a private device context after the last window of that class has been destroyed.
Posted on 2002-04-17 07:32:54 by beaster
Thanks beaster.
Oh, and why shouldn't you use class DCs? Here's why, straight out
of PlatformSDK :)

Allocates one device context to be shared by all windows in the class. Because window classes are process specific, it is possible for multiple threads of an application to create a window of the same class. It is also possible for the threads to attempt to use the device context simultaneously. When this happens , the system allows only one thread to successfully finish its drawing operation.

So, if you have multithreaded updates, or run more than one program
that uses the class, you risk getting thread blocking, which degrades
performance.
Posted on 2002-04-17 07:39:46 by f0dder
Thanks everybody.

NaN, I am familiar with backbuffering: I use it in a small game demo I wrote. But outside of heavy graphic applications, is backbuffering useful? The application I am working on right now is a mini-word processor you could say. It does a lot of painting, but mostly text operations. Furthermore, there's the possibility of the screen size changing (possibly frequently). Backbuffering is pretty static, unless you 1) keep creating Memory DCs with DIB Sections or 2) Just allocate a really big DIB section and only use the portions of it that you need. Any other options?

f0dder, my original question was concerning CS_OWNDC as you pointed out. You mentioned that BeginPaint returns a DC. Is there a "default DC" that BeginPaint uses, or does it create one everytime. Or does it depend if CS_OWNDC is present or not? Also, I have to wonder why I need to call BeginPaint at all. From what I've read in the API, it's more like calling several functions (such as ValidateRect, GetDC, WM_ERASEBKGND etc.). If I know for instance that I want the whole client area invalidated every call, can I skip the BeginPaint/EndPaint? I have drawn to the client without using BeginPaint and it doesn't seem to make a difference. For example, I have tied graphics refreshing to a timer before and simply paint to the DC.

What I was getting at originally was this: Is there some kind of penalty to using CS_OWNDC, or is there a benefit to not using it (same thing I guess...)? This is for a document style application which is predominantly text and borders and coloured rectangles.

Oh, and I have no intention of using Class DCs...

Thanks again

--Chorus
Posted on 2002-04-17 17:50:44 by chorus
As already written, BeginPaint will return a new HDC every time
(well, it *can* do that), with some default values. If you use CS_OWNDC,
you'll have your own (static) DC per window (which will retain objects
selected in it). I don't know how much difference this will make for
a text editor, I guess you should just try it out :). I wouldn't use it
if it doesn't give much improvement, as each DC takes a chunk of
the GDI heap, which is quite limited on 9x (64k says PlatformSDK).

Yes, you can paint to a DC whenever you want. BeginPaint should only
be called in respont to WM_PAINT - and I think it's a pretty good idea
to call it in there, I've had some weird problems a few times when I didn't.

Doublebuffering... if you got flicker, do it. Otherwise don't bother.
If you do it, you gotta handle offscreen bitmap resizing in WM_SIZE.
It would probably be smart to do resizes in increments, like multiple
of 64 - I can imagine destroying/creating bitmap on 1-pixel differences
would be wasteful.

Oh, and don't sendmessage(WM_ERASEBKGND) yourself, use RedrawWindow
and set the RDW_ERASE flag. Also never send WM_PAINT yourself :).
Posted on 2002-04-17 18:03:50 by f0dder

What I was getting at originally was this: Is there some kind of penalty to using CS_OWNDC, or is there a benefit to not using it (same thing I guess...)? This is for a document style application which is predominantly text and borders and coloured rectangles.


The only drawback of which I am aware of becomes apparent when you have multiple controls of the same class as changing some property of the DC will affect all of the controls which access it. Sometimes this is a good thing.

If for instance I was coding a custom button for some purpose and I applied to the DC a new font, it would apply to both which I think would be an unfortunate side effect in that case.
Posted on 2002-04-18 16:58:13 by Graebel
Graebel, wouldn't that be if you used a class DC? CS_OWNDC should
allocated a DC per *window*, and thus the problem you describe
shouldn't happen? At least that's how I understand the MS documentation.
Posted on 2002-04-18 17:08:40 by f0dder

Class Device Contexts

Class device contexts are supported strictly for compatibility with previous versions of Windows. When writing a Win32-based application, avoid using the class device context. Use a private device context instead.



An application creates a private device context by first specifying the CS_OWNDC window-class style when it initializes the style member of the WNDCLASS structure and calls the RegisterClass function. (For more information about window classes, see Window Classes.) After creating a window with the CS_OWNDC style, an application can call the GetDC, GetDCEx, or BeginPaint function once to obtain a handle identifying a private device context. The application can continue using this handle (and the associated device context) until it deletes the window created with this class. Any changes to graphic objects and their attributes, or graphic modes are retained by Windows until the window is deleted.


As far as I can make out, it sounds like the same thing but under a different name. Apples / Oranges?
Posted on 2002-04-18 17:19:20 by Graebel
If you look at the description of the CS_OWNDC bit, PlatformSDK
has the following to say:

Allocates a unique device context for each window in the class.


And a little later:

To avoid retrieving a device context each time it needs to paint inside a window, an application can specify the CS_OWNDC style for the window class. This class style directs the system to create a private device context ? that is, to allocate a unique device context for each window in the class. The application need only retrieve the context once and then use it for all subsequent painting.
Posted on 2002-04-18 17:24:17 by f0dder
Yeah, seems I was miss-reading the manual some. So easy to do with something written from M$.

Heres another:


Employing CS_OWNDC was once discouraged because it required some memory overhead; nowadays it can improve performance in some graphics-intensive Windows NT applications. Even if you use CS_OWNDC, you should still release the device context handle before exiting the window procedure.


So maybe thats it. Used to be bad, not anymore =)
Posted on 2002-04-18 17:35:53 by Graebel