Click here to Skip to main content
15,886,422 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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!

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

   // Handles screen saver messages  
   switch(message)  
   { 
      // <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));
   else
      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
Updated 14-Sep-11 15:13pm
v2

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
 
Share this answer
 
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!
 
Share this answer
 
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:

C++
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;
//From http://www.realtimesoft.com/multimon/forum/messages.asp?Topic=3760&tmpl=UltraMon)

   // 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: http://msdn.microsoft.com/en-us/library/dd183370(v=VS.85).aspx
   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);
   DeleteObject(hbmMem);
   DeleteDC(hdcMem);

   return TRUE;
}
 
Share this answer
 
v2
Comments
Roland4269 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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900