views:

160

answers:

2

If I have a window that spans both monitors on a multimonitor system, I can't seem to erase (paint black) the entire window. Instead, only the primary window is drawn black. The secondary remains the original white color. Has anyone seen this behavior?

wxwidgets:

wxClientDC dc(this); 
Erase(dc); 

void SpriteWindowFrame::Erase(wxDC& dc) 
{ 
    dc.SetBackground(*wxBLACK_BRUSH); 
    dc.SetBrush(*wxBLACK_BRUSH); 
    dc.Clear(); 
   //wxLogDebug("Erase called. Rect is %i, %i w:%i, h:%i", GetPosition().x, GetPosition().y, GetSize().GetWidth(), GetSize().GetHeight()); 
 } 

Inside dc.Clear() function, there is this code

wxwidgets:

void wxDC::Clear() 
{ 
WXMICROWIN_CHECK_HDC 

RECT rect; 
if ( m_canvas ) 
{ 
    GetClientRect((HWND) m_canvas->GetHWND(), &rect); 
} 
else 
{ 
    // No, I think we should simply ignore this if printing on e.g. 
    // a printer DC. 
    // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") ); 
    if (!m_selectedBitmap.Ok()) 
        return; 

    rect.left = -m_deviceOriginX; rect.top = -m_deviceOriginY; 
    rect.right = m_selectedBitmap.GetWidth()-m_deviceOriginX; 
    rect.bottom = m_selectedBitmap.GetHeight()-m_deviceOriginY; 
} 

#ifndef __WXWINCE__ 
(void) ::SetMapMode(GetHdc(), MM_TEXT); 
#endif 

DWORD colour = ::GetBkColor(GetHdc()); 
HBRUSH brush = ::CreateSolidBrush(colour); 
::FillRect(GetHdc(), &rect, brush); 
::DeleteObject(brush); 

#ifndef __WXWINCE__ 
int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX, 
    height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY; 

::SetMapMode(GetHdc(), MM_ANISOTROPIC); 

::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL); 
::SetWindowExtEx(GetHdc(), width, height, NULL); 
::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL); 
::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL); 
#endif 

}

Using the debugger, I checked what GetClientRect returned and sure enough it returns a rectange with location 0 and width/height of the combined two monitors so it's right. Maybe fillrect function is not capable of drawing to two displays?

+1  A: 

Can you trace into the constructor of the wxClientDC?

wxClientDC dc(this);

A lot depends on what type of DC wx has given you. The windows API to retrieve a window DC is hdc = GetDC(hwnd), and, on multimonitor systems, it retrieves a handle to a 'mirror driver' DC, thats meant to reflect calls to all the underlying display device DCs that the monitor spans.

The only possible reason I can think of for this behaviour is wx is somehow retrieving a display DC rather than a window DC.

Chris Becke
A: 

I'm sure Chris is correct, that the "overlapping window" case is handled somewhere for you. But where?

Rendering with windows GDI and "display contexts" such as you mention is very primitive and prone to all sorts of problems. GDI is one of poorest interfaces ever seen, poor even for Microsoft. Since most "window" programs work OK on multiple monitors, think of animating things in a "window" - and how that "window" makes its way to the "display" is best left a mystery.

Maybe DC is fundamentally not multi-monitor capable. Look for anything that allows multiple DCs to be treated uniformly. Rending graphics onto a grid of paper sheets would be like a tiled "printer DC". A video wall would be a tiled "display DC" and you would be happy with a 2-monitor hack, i.e. "multimon dc" echoes to "owning" display and "another one" if a window spans both.

If you want to do "real" animation on windows, you will need to move to DirectX. It is also a lot to learn, but much more capable: scene graphs, textures, video, alpha channels, ...

reechard