DC understanding

This forum has been great to learn faster when my Petzold book and online searches fail to help with certain understanding of concepts and what goes on behind the scenes in Windows Programming. So, thanks for all the responses. It is getting easier.

So, I have a little app that is working quite well. I only use 1 main window, so I have a global variable 'hwnd_main' handle that I use. I also use 'hdc_main' as a global DC when printing text to the window. So, I don't use the return value from BeginPaint, when I print. I use global 'hdc_main' for all prints. When I print using TextOut, it works great.

In messing around, I noticed that when I create another DC using 'hwnd_main', it gives me another DC pointer and I can't use that one to print. Probably, because 'hdc_main' is never actually released. But, where is the 2nd DC for 'hwnd_main' pointing to? I actually tried releasing 'hdc_main', and using a new DC for printing and it still doesn't work. Why not?

Sutton

I also use 'hdc_main' as a global DC when printing text to the window


How (which function) and where (which function) are you getting this global Device Context?
In WinMain (so I do this only once), I do:

hwnd_main = CreateWindow(...);
hdc_main = Get_DC(hwnd_main);

Both of these are globals.

If I do another hdc_main2 = Get_DC(hwnd_main), I would expect to have a 2nd DC to print to the same main window. I know it's not needed, but it doesn't work. So, where is that 2nd DC pointing to? It's just a curiosity question mainly.
OK. I figured out the problem, but don't know what is going on behind the scenes to cause the problem.

The problem is I was calling BeginPaint multiple times, getting a DC for hwnd_main several times (with different variables). The resulting hdc pointers would not print to the main window, but the original hdc_main still worked. If I changed the BeginPaint to GetDC, then those DC pointers worked.

I'm sure it had to do with multiple BeginPaints. But, not sure what the compiler was doing in the case of it not working. Not sure what multiple BeginPaints do behind the scenes to mess things up that GetDC does not.
Last edited on
What I don't understand Sutton, and the basis for my question, is why you are doing these very, very, very non-standard things? You certainly didn't see Charles Petzold using GetDC() in WinMain() to get a device context for use in a WM_PAINT handler. I mention that simply because I seem to recall your mentioning that you were using Petzold's book to help you get started. Please forgive me if I'm wrong. Maybe I got you mixed up with somebody else.

Also, using global variables in Win32 SDK Api code is simply unnecessary. I see it all the time, and I have to admit that when I do look at code and notice it it sets an alarm bell off in my head somewhere that I may be looking at code that's not so good, or perhaps a beginner who is just getting started. Guess I'm a snob for thinking that way, but I'm just being truthful. Fact is, I started out that way too, and nasty people like me in various forums set my head right about it, and I rectified the error of my ways.

Let me be specific. Why would you make your HWND for your main program window a global? Every time a message fires, whether it be from some user's interaction with your program, or a call from the operating system to inform your program of some event, your Window Procedure will be called, and the 1st parameter of the call will be the HWND of the window in your program to which the message applies. So you'll always have the needed HWND. And if you create other procedures in your application which you call from within your Window Procedure, you can easily pass the HWND passed to your Window Procedure to your other procedure called from there through a function parameter. In more advanced usages, the Win Api makes available various other means to 'persist' variables so as to avoid globals, such as storage within the WNDCLASS::cbWndExtra bytes (the amount of storage there is user configurable), or the GetProp()/SetProp() functions. You could look into that.

And I won't even get into the issue of Object Oriented Programming's principal of attaching data to objects to which they are related. Globals are basically the antithesis of this. They are just 'hanging out' there - seemingly not attached to anything, being subject to being modified by anything and at any time.

In terms of your obtaining HDCs the way you are, it doesn't sound good to me. Sounds to me like memory leak city. Years ago - I'm talking like 20 years ago, Microsoft realized most coders couldn't write Api SDK code without leaking memory and resources all over the place. That's why they created .NET and garbage collected languages - to protect coders and their operating systems from themselves. The best rule to follow when drawing in a Window is to do all painting in WM_PAINT handler code, use BeginPaint()/EndPaint() to deal with a local stack based HDC and PAINTSTRUCT, and refrain from EVER using an HDC obtained from GetDC() to draw outside of WM_PAINT handler code. Actually, I'm pretty sure Petzold said about the same thing in his books, and I recall no code of his that differed in any way from what I just described.

It's natural for coders to wish to be creative, and I commend you for that. But I think there are certain parts of Win32 Api code where I wouldn't stray from the path too much, and WM_PAINT handler code is one of those places.

Just trying to be helpful here. I don't want to offend you any.
Last edited on
Nah. I'm way past getting offended by any forum post. I just keep asking questions, until I get an answer that helps me.

Yes. My question was very, very non-standard. I've been designing and programming embedded systems for 30+ years, and I've always wanted/needed to know exactly how compilers and code operates to make subsequent designs better. Last month, I had some free time and I always wanted to dip my hands in Windows Programming. So, I got Petzold's book and set out to create a simple, one window application and start learning. With Windows, there is a lot of behind the scenes stuff that 'just happens' that I've never had to deal with before.

With my code, I basically copied a lot of Petzold's examples and then said 'I wonder what happens when I do this'. That's my nature of learning what works, doesn't work, how to design next time, how not to design, etc. It's all a preference and might not fit everyone. So, I noticed that both BeginPaint and GetDC return a handle, so I experimented with each one and so my question. All my painting is done under the WM_PAINT handler code, but I noticed in just playing around that there are differences between the 2 functions that cause certain things not to work right. That's what I mean by 'behind the scenes' stuff that I can't quite figure out.

As far as globals, that's always been a debated subject ever since I started programming way back in college. My take is they are OK in moderation, but you better know the ramifications of using them, because they can bite you. I use them fairly sparingly, depending on what I am doing, because in projects, I like to encapsule functionality for the most part. There is no right answer, but most people, in my experience, prefer using them as little as possible.

For this code, I was just playing around as I wasn't doing any real project design. Just experimenting with different scenarios and I made a few global (HWND and HDC, which you didn't like). Later on, if I try and design an actual project, I will go back to my encapsulation. Petzold does that pretty well.

Last edited on
Registered users can post here. Sign in or register to post.