Fullscreen With GDI

Im writing a program in which I want to take over the full screen.  Not so much as to clear the desktop, but at least be able to write to any portion of it outside the confines of a client window.

Id like to be able to do this without the use of Directx or other APIs due to incompatiblities with the NT platform, which will be used as well as 95/98.

I once downloaded a single executable from the net in which a cool cartoon character danced across the desktop.  It was awesome.  I dont think I had any DirectX drivers installed (I could be wrong), so I was wondering if this is possible to do with some sort of Windows Device Context, using GDI calls, etc.

Thanks for any help out there,
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

You can always write to any portion of the display.  You can get a DC for the display using


The problem is that you will be writting over other windows. If you then want to remove or move what you've written you will have a problem, as you need to restore what was originally there before you drew there.

One way around this is the save the image in that portion of the display before you draw there, then restore the image later.  That is pretty easy to do, but may lead to display glitches.  If the window you are drawing in changes its display during this time, you wil end up restoring its old image, not what should be there currently.

For that reason, this whole approach tends to be a bad idea (but it is easy, so it may be worth considering, it just depends on your circumstances.)

A more difficult but safer approach is to use a transparent window.  That is, create a window with the WS_EX_TRANSPARENT style.  This windows will allow the window below it to show through in the areas you don't paint in.  It will allow you to perform an animation on top of other windows, but when your animation moves or ends, the windows below will be restored automatically.

Let me know if you have any questions.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dmaroffAuthor Commented:
Ok, the CreateDC() did work and I see what you mean by writing to the desktop where It can disrupt other windows, besides that however, In order to make animation, I need to use a timer.  To use a timer I need an HWND to have the timer point to.  How can I make the desktop (which is now my client window)the HWND for which my WndProc() processes messages?  Can you show me a sample WinMain() perhaps?  

Also I did try the Transparent option for window type and all it did was remove the system menus.  The title bar still remained.  Do I need to 'OR' it with some other option to get just a blank client area?

Thanks so much for your help.

>>  How can I make the desktop
>> (which is now my client
>> window)the HWND for which my
>> WndProc() processes messages
You can't.  That window belongs to a different process.  The OS to be exact.

You can create your own window (as usuall, write a window procedur, register a class for it and then create an window with the class) and use this window when you create the time with SetTimer().  However you can just make this a hidden window, so it is not visible.

>> Also I did try the Transparent option for
>> window type and all it did was remove the
>> system menus.
The window is transparent, except where it draws things "in itself"  So if you create a window with a caption, it will draw the caption, it won't be transparent there.  So you probably don't want a caption.  You probably don't want a border (frame), you probably don't want a background brush etc...
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

dmaroffAuthor Commented:
Adjusted points to 150
dmaroffAuthor Commented:
Ok thanks.  One more question if you dont mind.  I want to reduce animation flicker from my program.  Im using InvalidateRect() and passing in the RECT values of the bitmap so it only gets redrawn, not the whole client area.  Then I call UpdateWindow() so Windows will next process a WM_PAINT message.  Inside WM_PAINT, Im using BeginPaint() to get a device context.  However my problem is that the RECT structure inside the PAINTSTRUCT which is passed to BeginPaint() doesn't reflect the values I passed to InvalidateRect().

In other words, if I pass a 10,10,10,10, to InvalidateRect().  BeginPaint() should set the values of the PAINTSTRUCT to 10,10,10,10, so that only that area gets drawn.  However after the function call, all I get is 0,0,0,0, and the flicker doesn't get any better.  So Im assuming its redrawing the entire client area.  Do you know why this is?  Am I using these GDI calls correctly?

Thanks for your all help,
>> However my problem is that
>> the RECT structure inside the
>> PAINTSTRUCT which is passed
>> to BeginPaint() doesn't reflect the values I
>> passed to InvalidateRect().
They may not match at times.  windows "collects" invalid regions for the window.  When WM_PAINT occurs the rectangle to be painted is the largest rectangle that encompasses all the invalid regions.  So if other things are also invalidating the window (like other windows moving in front of it or other areas in the window being changed) you may see this.

>> if I pass a 10,10,10,10, to InvalidateRect().
That rectangle does not have any area.  It probably won't even generate an invalid region. if it does, It might generate an invaliid---uh, incorrect--invalid region. i.e. it is possible that it invalidatign the whole window because the rectangle you specify is incorrect.  Although I sort of doubt it.

Note that cooredinates go between pixels. 0,0,1,1 is a 1 pixel rectangle. the 0 top edge goes above the first (0th) pixel.  The 0 left edge goes to the left of the first pixel.  The 1 right edge goes to the left of the 2nd pixel, that is to the right of the first pixel.  The 1 botom edge goes above the 2nd pixel, in other words below the first pixel.  so you see 0,0,1,1, surrounds 1 pixel.  10,10,10,10 surrounds none.  10,10,11,11, surrounds 1 pixel, the 11th pixel from the top and 11th from the left.

>> after the function call, all I
>> get is 0,0,0,0,
That is no area too.  i.e you specified no area and you got no arrea.

>> the flicker doesn't get any better
Depending on how you are drawing, your only option to reduce flicker might  be to use an "offscreen"  (memory) bitmap.  This is usually needed when your drawing must be done in multiple steps.  i.e if you use several drawing operations to create a single frame of the animation.  Like if the animation consitst of a ball bouncing inside a box, you have to draw the ball (circle) in a seperate step from the box (rectangle), so this would usually require offscreen drawing to prevent flashing.
dmaroffAuthor Commented:
I understand. Im going to use the double-buffering idea, Im just curious as to how I would use InvalidateRect() if I needed it?  How would I get it to work? Also, what do you mean when you say regions?

BTW - Your right, I meant to say 10,10,20,20.  10,10,10,10 is a result of lack of sleep.

>> Im just curious as to how I would use
>> InvalidateRect() if I needed it?
It sounds like you are using it correctly.  Just specify a rectangle that contains the array to be redrawn, expressed in client coordinates.

>> what do you mean when you say
>> regions?
A region is a shape that is not necessarily retangular.  Windows allows the invalid "shape" to be a region, not necessarily a rectangle.  The InvalidateRgn() function allows you to invalidate a region.  however, rectangles tend to be much easier for the OS to work with, so it is ioften better for use InvalidateRect() with a rectangle  that encompasses an entire region rather than useing InvalidRgn() with a comparibly smaller area than the rectangle.
Sure, I can create transparent windows, etc, or draw on the desktop, but what I want to do is create a single full screen window, which (to begin with) draws a black rectangle over everything, start bar included. ShowWindow with SW_MAXIMIZE, etc don't cover the start bar IIRC.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.