Click here to Skip to main content
11,478,174 members (72,530 online)
Rate this: bad
Please Sign up or sign in to vote.
See more: C++ C GDI GDI+
I tried the following code but I am getting nothing but black rectangles where my drawing images should be (using GDI+) on my 2nd monitor. Has anyone heard of this issue? Any drawing I do (bitmap or text) on the second monitor renders as a black rectangle. Thanks!

LRESULT WINAPI ScreenSaverProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)  
   static UINT         uTimer;   // timer identifier

   // Handles screen saver messages  
      // <snip>
      case WM_PAINT:   //  Sent when the system or another application makes a request to paint a portion of an application's window (e.g., UpdateWindow/RedrawWindow)
         PAINTSTRUCT lpPaint = {0};
         HDC hdc = BeginPaint(hwnd, &lpPaint );
            EnumDisplayMonitors(hdc, NULL, MonitorNumProcPaint, 0);  // For every monitor attached, call the passed in function
         EndPaint(hwnd, &lpPaint);
         return true;
      // <snip>
BOOL CALLBACK MonitorNumProcPaint(HMONITOR hMonitor, HDC hdc, LPRECT lprcMonitor, LPARAM data)
   // If the coordinates of the top left corner are 0,0, then we're rendering on the primary monitor, otherwise we're not.
   if (lprcMonitor->left == 0 && lprcMonitor->top == 0)
      return (PaintPrimaryDisplay(hMonitor, hdc, lprcMonitor, data));
      return (PaintNonPrimaryDisplay(hMonitor, hdc, lprcMonitor, data));
bool PaintNonPrimaryDisplay(HMONITOR hMonitor, HDC hdc, LPRECT lprcMonitor, LPARAM data)
   Gdiplus::Graphics * pGraphics = Gdiplus::Graphics::FromHDC(hdc);
   if (gpBitmapMotivation2)
      pGraphics->DrawImage(gpBitmapMotivation2, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top);
   int sizeX = (int) ceil( (lprcMonitor->right - lprcMonitor->left) * SS_SCREEN_PERCENTAGE);
   int sizeY = (int) ceil( (lprcMonitor->bottom- lprcMonitor->top)  * SS_SCREEN_PERCENTAGE);
   DrawMyText(lprcMonitor, sizeX, sizeY, pGraphics, "MyText"); // This custom function sets up the font, etc and renders the text.

   BitBlt(hdc, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top, hdc, lprcMonitor->left, lprcMonitor->top, SRCCOPY);
   return true;
Posted 14-Sep-11 12:30pm
Edited 14-Sep-11 16:13pm
Rate this: bad
Please Sign up or sign in to vote.

Solution 1

the HWND you get passed is maximised over all monitors ...

you're probably better off creating a child window per monitor during the WM_CREATE call if you want separate draw images
Rate this: bad
Please Sign up or sign in to vote.

Solution 2

Hi barneyman,
If you mean the HWND when entering the ScreenSaverProc, then I'm not sure what your saying. MonitorNumProcPaint should be called for every monitor I have, and its params include LPRECT lprcMonitor which is the location and size of the particular monitor the function was called for.

So if I draw a rectangle at lprcMonitor->left, that will be the left side of whatever monitor I'm on. And I've verified this by adding and subtracting numbers to that value, and the black rectangle moves left or right. The black rectangle on my 2nd monitor is definately due to my callback of PaintNonPrimaryDisplay. if I remove that call then the 2nd monitor says the same.. nothing via the screensaver gets painted to it.

I do want to draw seperate images. One set for the Primary Monitor and then different images for each monitor thereafter. But no matter what I do the rendering is a black rectangle. Its like the canvas is being set but nothing renders on it. I've tried playing with coordinates to see if my drawing coordinates were off but they seem OK.

I appreciate any assistance anyone can give, thanks!
Rate this: bad
Please Sign up or sign in to vote.

Solution 3

I resolved this a while ago. The way I was trying to use the lprcMonitor, but ended up using the dwData to fix it, as commented below:

gHdc = BeginPaint(hwnd, &gPaintStruct);   // Get Device Context handle from canvas
   // For every monitor attached, call the passed in function
   EnumDisplayMonitors(gHdc, NULL, MonitorNumProcPaint, (LPARAM)&gHdc); 
EndPaint(hwnd, &gPaintStruct);            // Painting is done

BOOL PaintNonPrimaryDisplay(HMONITOR hMonitor, LPRECT lprcMonitor, LPARAM dwData)
   HDC *pdc = (HDC*)dwData;

   // Create an "off screen" DC (double buffer) to avoid flickering
   HDC hdcMem = CreateCompatibleDC(*pdc);
   HBITMAP hbmMem = CreateCompatibleBitmap(*pdc, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top);
   HGDIOBJ hOld = SelectObject(hdcMem, hbmMem);
   // Paint everything into the double buffer
   Gdiplus::Graphics  *gpGraphics = Gdiplus::Graphics::FromHDC(hdcMem);
   if (gpGraphics == NULL)
      return false;
   if (gpBitmapMotivations[1])
      gpGraphics->DrawImage(gpBitmapMotivations[1], 0, 0, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top);
   DrawOverlay(0, 0, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top, gpGraphics);
   // Transfer the "off screen" (double buffer) DC (Device Context) to the screen
   // BitBlt Specs:
   BitBlt(*pdc, lprcMonitor->left, lprcMonitor->top, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top, hdcMem, 0, 0, SRCCOPY);
   // Free the "off screen" DC
   delete gpGraphics;
   SelectObject(hdcMem, hOld);
   return TRUE;
Roland4269 at 11-May-12 10:45am
This works, but is incompatible with the LANDesk 9 Mirror Driver. Severe flickering occurs because the mirror driver utilizes a virtual monitor and anything that's on the primary mon will be dupe'd on top, causing flickering (overriding your paints).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 229
1 F-ES Sitecore 170
2 Sascha Lefèvre 160
3 Frankie-C 120
4 OriginalGriff 95
0 Sergey Alexandrovich Kryukov 7,675
1 OriginalGriff 7,321
2 Sascha Lefèvre 3,034
3 Maciej Los 2,491
4 Richard Deeming 2,325

Advertise | Privacy | Mobile
Web01 | 2.8.150520.1 | Last Updated 12 Apr 2012
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100