PDA

View Full Version : About CS_OWNDC



Meu
05-23-2005, 06:31 AM
Hello,

I read an article about how not to get the DC every time seeking more performance, just initialize it one time and then release it at the end.
This is good but really what bothers me that it said I must specify CS_OWNDC as a class style, I do not understand the reason!?
Why I just make a static variable of type HDC and then get the DC at the WM_CREATE and release it at WM_DESTROY and just that - I tried it and it works!.

Thanks,
Mustafa ELBanna

Ehsan Kamrani
05-23-2005, 07:08 AM
Originally posted by Meu:
Why I just make a static variable of type HDC and then get the DC at the WM_CREATE and release it at WM_DESTROY and just that - I tried it and it works!.
The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. The window procedure of the new window receives this message after the window is created, but before the window becomes visible. So in WM_CREATE, you can declare the DC, specify it's pixel format ,etc.The WM_CREATE is sent before the CreateWindowEx or CreateWindow function returns.

The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window procedure of the window being destroyed after the window is removed from the screen.So in WM_DESTROY, you can release the DC, destroy the HDC, etc.

So you are correct.
-Ehsan-

Meu
05-23-2005, 07:16 AM
Hello,
First: Thanks for replying.
Second: So I do not have to specify CS_OWNDC as a class style, Right?
But please read this article: http://www.starstonesoftware.com/OpenGL/whyyou.htm
Thanks,
Mustafa ELBanna

Ehsan Kamrani
05-23-2005, 07:20 AM
You have many options. it was an option. If that article has said that it does work, you can use from that manner as well.
-Ehsan-

Ehsan Kamrani
05-23-2005, 08:48 AM
Whoop! :eek: Your question is about the CS_OWNDC. excuse me. I haven't slept for more than 24 hours and i'm so tired--And i shouldn't response to the questions when i'm sleepy.
As i said before, you can declare the DC, and then in your WM_CREATE, set the pixel formats, create the RC, etc.
Also in your WM_CLOSE or WM_DESTROY, you can release the DC, destroy the RC, etc.
But CS_OWNDC is another thing.it Allocates a *unique device context* for *each window* in the class.You should create a window class and then use from one of the CS_* symbolic constants as the style parameter.This is a standard manner and works correctly. So you don't need to use from another manner.

Meu
05-23-2005, 12:54 PM
Hello,
No the article say if I want reserve my DC along the lifetime of the application, I must use CS_OWNDC??.
I know it is better way for sake of memory and the common DCs are limited by thier specification.
But all I ask about is what I am doing is totally wrong or just bad??
Thanks,
Mustafa ELBanna

Meu
05-23-2005, 01:01 PM
Hello,
Sorry I forgot to say that if the DC is being allocated all the time, So I did not have to release this DC any where in my window procedure.And evenwhen I receive WM_DESTROY for my window I will not even release the DC because will do this implicitly*!!??
(*I do not is this true or not, I just tell for sake of asking??)
Thanks,
Mustafa ELBanna

Ehsan Kamrani
05-23-2005, 01:35 PM
In this link:
http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=2;t=018651
Move to the source code and take a look at the functions *killGLWindow* and *CreateGLWindow*.

You should explicitly detach the current rendering context from the thread , destroy it and release the DC.
The best reference is MSDN:
----------------------
Creating a Rendering Context and Making It Current
The following code sample shows how to create an OpenGL rendering context in response to a WM_CREATE message. Notice that you set up the pixel format before creating the rendering context. Also notice that in this scenario the device context is not released locally; you release it when the window is closed, after making the rendering context not current. For more information, see Deleting a Rendering Context. Finally, notice that you can use local variables for the device context and rendering context handles, because with the wglGetCurrentContext and wglGetCurrentDC functions you can obtain handles to those contexts as needed.

// a window has been created, but is not yet visible
case WM_CREATE:
{
// local variables
HDC hdc ;
HGLRC hglrc ;

// obtain a device context for the window
hdc = GetDC(hWnd);

// set an appropriate pixel format
myPixelFormatSetupFunction(hdc);

// if we can create a rendering context ...
if (hglrc = wglCreateContext( hdc ) ) {

// try to make it the thread's current rendering context
bHaveCurrentRC = wglMakeCurrent(hdc, hglrc) ;

}

// perform miscellaneous other WM_CREATE chores ...

}
break ;

Deleting a Rendering Context
The following code sample shows how to delete an OpenGL rendering context when an OpenGL window is closed. It is a continuation of the scenario used in Creating a Rendering Context and Making It Current.

// a window is about to be destroyed
case WM_DESTROY:
{
// local variables
HGLRC hglrc;
HDC hdc ;

// if the thread has a current rendering context ...
if(hglrc = wglGetCurrentContext()) {

// obtain its associated device context
hdc = wglGetCurrentDC() ;

// make the rendering context not current
wglMakeCurrent(NULL, NULL) ;

// release the device context
ReleaseDC (hwnd, hdc) ;

// delete the rendering context
wglDeleteContext(hglrc);

}
-----------------------------
If you have any problems with your own code, that NeHe code works correctly and you only need to change the DrawGLScene() and initGL() functions.

-Ehsan

mikael_aronsson
05-24-2005, 01:13 AM
Hi !

The idea with CS_OWNDC is that when you have set the CS_OWNDC flag the context will not be deleted when you call ReleaseDC(), this means that you can keep your old code that allocates and release the DC but Windows will keep the DC in memory so those function will execute much faster.

When you create new code you can of course just allocate the DC when you create the window and then keep it around yourself, that makes no difference.

Mikael

Meu
05-24-2005, 01:28 AM
Hello,

Thanks for replying. So if I used CS_OWNDC I will not need any call for ReleaseDC even if in the destruction time of the window because it the job of the OS to destroy the window with the private DC of the window.

Thanks,
Mustafa ELBanna

Ehsan Kamrani
05-24-2005, 05:28 AM
I said you, you should release the DC's. I should explain it with more details:
An application performing numerous drawing operations in the client area of its window must use a private display device context. To create this type of device context, the application must specify the CS_OWNDC constant for the style member of the WNDCLASS structure when registering the window class. After registering the window class, the application obtains a handle identifying a private display device context by calling the GetDC function.

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.

Although the CS_OWNDC style is convenient, use it carefully, because each device context uses a significant portion of 64K GDI heap

If you were programming for 16-bit Windows, you were told to avoid the use of your own DCís because the system could only support a few. This is not true on Windows NT. Use the creation style CS_OWNDC as much as you can when you call the RegisterClass function. This avoids repeated calling of the relatively expensive GetDC and ReleaseDC functions every time you have to draw. It also preserves the selected objects in your own DC in between calls, eliminating the need to select them again after each call to GetDC.

OK.As you read, each device context uses a significant portion of 64K GDI heap. SO WHEN YOU WANT TO DESTROY A WINDOW, YOU *SHOULD* RELEASE THE DC OF EACH WINDOW.

There's no another exception.As you have seen my previous reply, Microsoft say that you should get the current DC-The DC of the specified window- and release it--And windows doesn't like to know anything about them. All the programs, when are finished, should release their DC's.

-Ehsan-

mikael_aronsson
05-24-2005, 10:06 PM
No, you do not need to free a DC created with CS_OWNDC, ReleaseDC does nothing in that case, the documentation for ReleaseDC is pretty clear about this:

"The ReleaseDC function releases a device context (DC), freeing it for use by other applications. The effect of the ReleaseDC function depends on the type of DC. It frees only common and window DCs. It has no effect on class or private DCs"

So ReleaseDC does nothing with a CS_OWNDC and GetDC will just return the allocated DC instead of creating a new one each time, this is where you get the speed improvmement, when the window is destroyed the DC is also release by windows.

Mikael

Ehsan Kamrani
05-24-2005, 11:50 PM
Hi Mikael,
So why we use from the ReleaseDC in this case? see the NeHe articles as an example. So in this case, ReleaseDC cannot release the window's DC?--And why they have written it? :confused:
NeHe has witten a code for ReleaseDC:
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}
I never have received an error for ReleaseDC.In this case, the window class is using from the CS_OWNDC costant.
-Ehsan-

Meu
05-25-2005, 03:10 AM
I read that ReleaseDC and Just for compatibility with an old code. It does not do any thing with a DC with style of CS_OWNDC and it does not generate errors in the same time.
Thanks,
Mustafa ELBanna