Re: Fixing incorrect clip box on multi-monitor machines
The problem has nothing to do with monitor borders. The line drawing is cut
off as soon as the client coordinates exceed 2560 - even if this coordinate
is somewhere in the middle of a monitor.
And as I said before - it's a single graphic card.
Thanks for your help so far
Robert
PS: I'll not be able to read or write for more than a week, so feel free to
take your time.
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
news:0112d2pa4pn36oc1lbhsjsqni84ro58gtb@4ax.com...
You're right. This is very confusing. It looks very much like driver
problems.
I tested out a piece of multimonitor code recently by swapping my various
monitors around
in odd configurations (it helps that they don't have the same resolution
so I had to deal
with differences where one was taller or wider than the other). In all
cases, in a
two-monitor system, things worked with negative coordinates.
One thing to try: go into the setup and swap your monitors around. Make
the right-hand
monitor have negative coordinates and the left-hand monitor have positive
coordinates
(note this will drive you crazy after a while during testing!) and see if
the problems
follow the monitor or follow the coordinates.
Do you have one multihead graphics card, or more than one card? If you
have more than one
card, are they the same vendor? Just some additional thoughts as to where
confusion might
reign.
I don't really have time to look at the code for a few days. But I might
have time to
send you my multimonitor example code, but again it's only been tested in
a two-monitor
system. Send me email.
joe
On Wed, 2 Aug 2006 10:53:36 +0200, "Robert" <noone@nowhere.com> wrote:
I'm using Visual Studio 6.0 (newest SP) on XP SP2.
You seem to be right: Both MFC and direct API calls show the same
behaviour.
But it's not quite as simple as that - I've tried a few more things, and
the
results confuse me quite a little:
TextOut called directly within the OnPaint event handler will render to
the
3rd monitor (both the MFC and API variant). LineTo and DrawClipRect will
not
do so.
When calling a function from OnPaint (handing over the dc), even TextOut
will no longer render to the 3rd monitor.
When I restrict my form to use only the middle and right monitors, I can
suddenly draw on the rightmost monitor (but of course, then I can't draw
on
the lestmost monitor).
I also have no problems drawing on my leftmost (=negative coordinate)
monitor. I seem to run into trouble only when my client coordinates
exceed
the maximum screen coordinate. However, within other applications this
seems
to work, so I don't really suspect the graphics drivers.
BTW it's a single graphics card which can manager up to four display
monitors. Each monitor is seen by Windows as a single display (when you
go
to display properties / settings).
The application I have is already very trivial. At times it basically
only
had an OnPaint handler with the lines and TextOut drawn (and the latter
one
only for test purposes).
I can post the current code here...(warning: I haven't worked with C /
C++ /
MFC for years, the code might look a bit awkward...)
// clsBackgroundForm.cpp : implementation file
//
#include "stdafx.h"
#include "winuser.h"
#include "WR_MFC_Functions.h"
#include "clsBackgroundForm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////////////////
/
/
// clsBackgroundForm dialog
clsBackgroundForm::clsBackgroundForm(CWnd* pParent /*=NULL*/)
: CDialog(clsBackgroundForm::IDD, pParent)
{
//{{AFX_DATA_INIT(clsBackgroundForm)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void clsBackgroundForm::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(clsBackgroundForm)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(clsBackgroundForm, CDialog)
//{{AFX_MSG_MAP(clsBackgroundForm)
ON_WM_RBUTTONUP()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////
/
/
// clsBackgroundForm message handlers
HDC hMemDC;
HBITMAP hBmp;
HBITMAP hOldBmp;
int x,y,w,h;
int isButtonDown;
CPoint ptStart, ptEnd, ptPrevEnd, ptPrevStart;
CPen myPen;
int isLassoDrawn;
int forceFullRedraw;
void clsBackgroundForm::PaintLines(CPaintDC* dc, CPoint ptFrom, CPoint
ptTo)
{
CRect r;
if (ptStart == ptTo)
{
return;
}
dc->SelectObject(myPen);
int hOldRasterMode = dc->SetROP2(R2_NOT);
// Only test
dc->TextOut(2500, 72, "Hello MFC!");
::TextOut(*dc,2500,372,"Hello API!",10);
dc->MoveTo(ptStart.x,ptStart.y);
dc->LineTo(ptTo.x,ptStart.y);
dc->LineTo(ptTo.x,ptTo.y);
dc->LineTo(ptStart.x,ptTo.y);
dc->LineTo(ptStart.x,ptStart.y);
isLassoDrawn = !isLassoDrawn;
}
void clsBackgroundForm::OnRButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDialog::EndDialog(0);
CDialog::OnRButtonUp(nFlags, point);
}
BOOL clsBackgroundForm::OnInitDialog()
{
CDialog::OnInitDialog();
HDC hScreenDC = ::GetDC(NULL);
x = GetSystemMetrics(SM_XVIRTUALSCREEN);
y = GetSystemMetrics(SM_YVIRTUALSCREEN);
w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
/*
// When I do this, I can draw on the rightmost monitor, but no longer on
the leftmost
x = 0;
w = 2560;
*/
CDialog::MoveWindow(x,y,w,h);
myPen.CreatePen(PS_SOLID | PS_GEOMETRIC,1,RGB(255,0,0));
hMemDC = CreateCompatibleDC(hScreenDC);
hBmp = CreateCompatibleBitmap(hScreenDC,w,h);
static_cast<HBITMAP>(SelectObject(hMemDC,hBmp));
// Capture the screen
BitBlt(hMemDC,0,0,w,h,hScreenDC,x,y,SRCCOPY);
::ReleaseDC(NULL,hScreenDC);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void clsBackgroundForm::OnPaint()
{
CRect r,rPrev;
CRgn rgn;
CPaintDC dc(this); // device context for painting
if ((forceFullRedraw) || (!isButtonDown))
{
// Paste my screen capture on my window
StretchBlt(dc,0,0,w,h,hMemDC,0,0,w,h,SRCCOPY);
isLassoDrawn=0;
}
// Only test
dc.TextOut(2500, 572, "Hello MFC!");
::TextOut(dc,2500,772,"Hello API!",10);
if (isLassoDrawn)
{
PaintLines(&dc, ptPrevStart, ptPrevEnd);
}
ptPrevEnd = ptEnd;
ptPrevStart = ptStart;
PaintLines(&dc, ptStart, ptEnd);
forceFullRedraw=0;
}
BOOL clsBackgroundForm::DestroyWindow()
{
myPen.DeleteObject();
DeleteObject(SelectObject(hMemDC,hOldBmp));
DeleteDC(hMemDC);
return CDialog::DestroyWindow();
}
void clsBackgroundForm::OnLButtonDown(UINT nFlags, CPoint point)
{
CRect r;
GetWindowRect(&r);
InvalidateRect(&r,0);
ptStart = point;
ptEnd = ptStart;
isButtonDown=1;
forceFullRedraw=1;
CDialog::OnLButtonDown(nFlags, point);
}
void clsBackgroundForm::OnLButtonUp(UINT nFlags, CPoint point)
{
ptEnd = point;
isButtonDown=0;
ptStart.x += x;
ptStart.y += y;
ptEnd.x += x;
ptEnd.y += y;
CDialog::OnLButtonUp(nFlags, point);
m_strRange.Format ("%d;%d;%d;%d",ptStart.x, ptStart.y, ptEnd.x,
ptEnd.y);
}
void clsBackgroundForm::OnMouseMove(UINT nFlags, CPoint point)
{
if (isButtonDown)
{
ptEnd = point;
CRect r;
GetWindowRect(&r);
InvalidateRect(&r,0);
}
CDialog::OnMouseMove(nFlags, point);
}
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
news:kt1vc2p07erjjdcio9av6hgtoufeohhio1@4ax.com...
Which version of MFC are you using? And what platform are you using,
e.g., are you using
XP SP2, Server 2003, or something else?
Note that this is most likely *not* MFC that is doing it, because MFC
doesn't create the
clip box; this comes from the operating system. Have you tried
creating a
trivial example
application that demonstrates this?
Just an observation that I've successfully used these techniques to
draw
on my left-hand
monitor, which has negative coordinates. This sounds like it could also
be
a bug in the
device driver for your display screens; you might want to report this
to
the vendor of
your video card(s). Also, make sure you have the latest drivers. If
you
have a single
card that does all three monitors, it is a different question than if
you
have two cards
from either the same or two different vendors. It could be drivers Not
Playing Well With
Others.
joe
On Tue, 1 Aug 2006 17:04:22 +0200, "Robert" <noone@nowhere.com> wrote:
Hello all,
I have a CDialog, which I set to span the whole virtual screen. The
machine
has 3 monitors with 1280x1024 each, and the virtual screen ranges from
(-1280 / 0) to (2560 / 1024) (yes, the first monitor has negative
X-coordinates).
The MFC drawing routines don't seem to like that. I was absolutely
unable
to
draw anything on the third (=rightmost) monitor (TextOut, LineTo).
So I took a look at the ClipBox within OnPaint, and sure enought, it
said
(0/0) - (2560/1024), where it SHOULD've read (0/0) - (3840/1024),
because
that's the size of my window. (Interestingly, 2560 is the maximum
X-Coordinate in screen coordinates, but NOT in client coordinates!).
Then I tried overriding the clipping region using CreateRectRgn and
SelectClipRgn, but MFC either ignores the call, or overrides the
values I
set.
What can I do? Any ideas?
Thanks for any input!
Robert
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm