Can't seem to make double-buffered painting with multiple monitors
I'm trying to remake my Windows screensaver written with C++ and WinAPIs to work on multiple monitors. I found this article that gives the basics. But when I implement it in my own code, I get a weird result. Take a look at this code:
Painting always works on a primary monitor. But when I paint to the secondary monitor, I can only paint directly to its DC. When I use double-buffering technique (with DIRECT_PAINT pre-processor directive commented out) I only get a black screen on a secondary monitor when it should've been red.
I'm attaching two screenshots here.
First one with direct painting that works:
and then the one that doesn't, with double-buffering technique:
Re: Can't seem to make double-buffered painting with multiple monitors
I haven't done any Windows programming in a long time so my memory isn't the best these days...
Anyway, BitBlt uses logical coordinates so doesn't that mean that you have to set up mapmode and so on before calling it?
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.
- Brian W. Kernighan
Re: Can't seem to make double-buffered painting with multiple monitors
Originally Posted by ahmd
Why would it work then without a double buffer?
Without it you don't call BitBlt to finalize the painting
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.
- Brian W. Kernighan
Re: Can't seem to make double-buffered painting with multiple monitors
Originally Posted by Igor Vartanov
[code]
These highlighted must just match in their top left
They do match. If you check above the left-top of RECT is set to 0,0.
As for setting mapmode, I'm not really sure what you mean. Can you give a code example of what should I add? It might be it, because I don't think there's anything else I can do with this sample. It seems right.
Re: Can't seem to make double-buffered painting with multiple monitors
SetMapMode sets how to translate between logical and device coordinates (SetWindowOrg and SetViewPortOrg might also be good to checkup).
As I said it's been a long time since I did any Windows programming (except console quickies) but I did browse MSDN a bit and it seems like what you're doing should work. As far as I remember though this type of code easily ended up being a pain in the ... as suddenly SetWindowOrg, SetViewportOrg and SetMapMode had to be involved.
Try calling SetMapMode http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx with MM_TEXT before calling BitBlt. Also try removing the text from your output. It might a little red dot somewhere indicating that pixel scaling occur.
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.
- Brian W. Kernighan
Re: Can't seem to make double-buffered painting with multiple monitors
Originally Posted by ahmd
They do match. If you check above the left-top of RECT is set to 0,0.
Oh sorry, you're right, my bad.
As for setting mapmode, I'm not really sure what you mean. Can you give a code example of what should I add? It might be it, because I don't think there's anything else I can do with this sample. It seems right.
The map mode by default is MM_TEXT. Considering that BitBlt works fine for your primary monitor, the problem is somewhere else. Need to play with your code a bit. It's a pity you did not provide a compilable project.
Last edited by Igor Vartanov; September 21st, 2012 at 01:25 AM.
Re: Can't seem to make double-buffered painting with multiple monitors
Igor, sorry, I wanted to make a sample project but it seems to be quite a pain in the butt with screensavers.
cilu, much appreciated! There's no way in heck I would think of doing that. Any idea how exactly it makes it work (by doing it completely opposite to what I've been taught to do in WM_PAINT)?
Re: Can't seem to make double-buffered painting with multiple monitors
I guess it's because BeginPaint() clips what's outside the update region, while GetDC(NULL) returns the DC of the entire screen. In your case the update region is not the entire screen.
Re: Can't seem to make double-buffered painting with multiple monitors
One follow-up question. While trying to find a solution I did the following: I started using the initial virtual screen DC (received from WM_PAINT) to render each monitor. In this case I needed to know the size of the monitor (for which I used mi.rcMonitor) and also the offset from the virtual screen's anchor point, which I was able to obtain by calling GetDCOrgEx(hMonitorDC, &pnt), were hMonitorDC is the DC passed into the MyPaintEnumProc() enum proc. I illustrated it with a diagram attached.
The question I have, even though this approach (with using only one DC for the whole virtual screen) seems to work as well, am I doing something that shouldn't be done?
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.