358 lines
13 KiB
C++
358 lines
13 KiB
C++
|
|
||
|
#include "stdafx.h"
|
||
|
#include "global.h"
|
||
|
#include "pbrush.h"
|
||
|
#include "sprite.h"
|
||
|
#include "tracker.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "memtrace.h"
|
||
|
|
||
|
// FUTURE: Make these static to CTracker!
|
||
|
CBitmap NEAR g_bmapDragHandle; // Handle for the drag handle bitmap.
|
||
|
CBitmap NEAR g_bmapDragHandle2; // Handle for hollow drag handle bitmap.
|
||
|
|
||
|
|
||
|
// These are the bitmaps arrays used for tracker borders and the dotted
|
||
|
// drag rectangles.
|
||
|
//
|
||
|
static unsigned short bmapHorizBorder[] =
|
||
|
{ 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0 };
|
||
|
|
||
|
static unsigned short bmapVertBorder [] =
|
||
|
{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA };
|
||
|
|
||
|
static CBrush NEAR brushHorizBorder;
|
||
|
static CBrush NEAR brushVertBorder;
|
||
|
static CBitmap NEAR bitmapHorizBorder;
|
||
|
static CBitmap NEAR bitmapVertBorder;
|
||
|
|
||
|
static HCURSOR hcurArrow = NULL; // System "Select Arrow" cursor.
|
||
|
static HCURSOR hcurMove = NULL; // System "Move" cursor.
|
||
|
static HCURSOR hcurSizeNESW = NULL; // System sizing "NESW" cursor.
|
||
|
static HCURSOR hcurSizeNS = NULL; // System sizing "NS" cursor.
|
||
|
static HCURSOR hcurSizeNWSE = NULL; // System sizing "NWSE" cursor.
|
||
|
static HCURSOR hcurSizeWE = NULL; // System sizing "WE" cursor.
|
||
|
static HCURSOR hcurDragTool;
|
||
|
|
||
|
|
||
|
// This array of hCursors is used to map tracker states (see the definition
|
||
|
// of CTracker in editor.hxx) to the appropriate mouse cursor bitmaps.
|
||
|
//
|
||
|
static HCURSOR* mapTrackerStateToPHCursor[] =
|
||
|
{
|
||
|
&hcurArrow, // nil
|
||
|
&hcurArrow, // predrag
|
||
|
&hcurMove, // moving
|
||
|
&hcurSizeNS, // resizingTop
|
||
|
&hcurSizeWE, // resizingLeft
|
||
|
&hcurSizeWE, // resizingRight
|
||
|
&hcurSizeNS, // resizingBottom
|
||
|
&hcurSizeNWSE, // resizingTopLeft
|
||
|
&hcurSizeNESW, // resizingTopRight
|
||
|
&hcurSizeNESW, // resizingBottomLeft
|
||
|
&hcurSizeNWSE, // resizingBottomRight
|
||
|
};
|
||
|
|
||
|
|
||
|
HCURSOR HCursorFromTrackerState( int m )
|
||
|
{
|
||
|
ASSERT(m >= 0 &&
|
||
|
m < sizeof (mapTrackerStateToPHCursor) / sizeof (HCURSOR*));
|
||
|
return (*(mapTrackerStateToPHCursor[m]));
|
||
|
}
|
||
|
|
||
|
|
||
|
/* RVUV2
|
||
|
*
|
||
|
* This code needs to be called, just once, before we begin to use
|
||
|
* trackers. In lieu of a standard initialization function into which
|
||
|
* I can put this code, I am using a moduleInit variable as a kludge.
|
||
|
*/
|
||
|
|
||
|
BOOL moduleInit = FALSE; /** RVUV2 temporary! **/
|
||
|
|
||
|
BOOL InitTrackers()
|
||
|
{
|
||
|
/*
|
||
|
* Initialize the brushes and bitmaps needed to do repaints
|
||
|
*/
|
||
|
|
||
|
if (! bitmapHorizBorder.CreateBitmap( 8, 8, 1, 1, (LPSTR)bmapHorizBorder )
|
||
|
|| ! bitmapVertBorder.CreateBitmap ( 8, 8, 1, 1, (LPSTR)bmapVertBorder )
|
||
|
|| ! brushHorizBorder.CreatePatternBrush( &bitmapHorizBorder )
|
||
|
|| ! brushVertBorder.CreatePatternBrush ( &bitmapVertBorder )
|
||
|
|| ! g_bmapDragHandle.LoadBitmap ( IDBM_DRAGHANDLE )
|
||
|
|| ! g_bmapDragHandle2.LoadBitmap( IDBM_DRAGHANDLE2 ))
|
||
|
{
|
||
|
// Future: Failure here should cause error in opening dialog resource!
|
||
|
theApp.SetMemoryEmergency( FALSE );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
hcurArrow = theApp.LoadStandardCursor( IDC_ARROW );
|
||
|
hcurMove = theApp.LoadCursor( IDCUR_MOVE );
|
||
|
hcurSizeNESW = theApp.LoadCursor( IDCUR_SIZENESW );
|
||
|
hcurSizeNS = theApp.LoadCursor( IDCUR_SIZENS );
|
||
|
hcurSizeNWSE = theApp.LoadCursor( IDCUR_SIZENWSE );
|
||
|
hcurSizeWE = theApp.LoadCursor( IDCUR_SIZEWE );
|
||
|
|
||
|
hcurDragTool = ::LoadCursor( AfxGetInstanceHandle(),
|
||
|
MAKEINTRESOURCE( IDC_DRAGTOOL ));
|
||
|
|
||
|
moduleInit = TRUE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
|
||
|
void CTracker::CleanUpTracker()
|
||
|
{
|
||
|
brushHorizBorder.DeleteObject();
|
||
|
brushVertBorder.DeleteObject();
|
||
|
|
||
|
bitmapHorizBorder.DeleteObject();
|
||
|
bitmapVertBorder.DeleteObject();
|
||
|
|
||
|
g_bmapDragHandle.DeleteObject();
|
||
|
g_bmapDragHandle2.DeleteObject();
|
||
|
}
|
||
|
|
||
|
/***************************************************************************/
|
||
|
// NOTE: The rect passed in here is the inner-most rect of the tracker!
|
||
|
|
||
|
CTracker::STATE CTracker::HitTest( const CRect& rc,
|
||
|
CPoint pt,
|
||
|
STATE defaultState )
|
||
|
{
|
||
|
/*
|
||
|
* Compute position of edge (non-corner) handles
|
||
|
*/
|
||
|
int xMid = ((rc.right + rc.left) / 2) - (HANDLE_SIZE / 2);
|
||
|
int yMid = ((rc.top + rc.bottom) / 2) - (HANDLE_SIZE / 2);
|
||
|
|
||
|
/*
|
||
|
* Now we do the actual hit-testing for each resizing handle
|
||
|
*/
|
||
|
if ((pt.x < rc.left) && (pt.x > rc.left - HANDLE_SIZE))
|
||
|
{
|
||
|
if ((pt.y < rc.top) && (pt.y > rc.top - HANDLE_SIZE))
|
||
|
return(resizingTopLeft);
|
||
|
else
|
||
|
if ((pt.y >= rc.bottom) && (pt.y < rc.bottom + HANDLE_SIZE))
|
||
|
return(resizingBottomLeft);
|
||
|
else
|
||
|
if ( (pt.y >= yMid) && (pt.y < yMid + HANDLE_SIZE) )
|
||
|
return(resizingLeft);
|
||
|
}
|
||
|
else
|
||
|
if ((pt.x >= rc.right) && (pt.x < rc.right + HANDLE_SIZE))
|
||
|
{
|
||
|
if ((pt.y < rc.top) && (pt.y > rc.top - HANDLE_SIZE))
|
||
|
return(resizingTopRight);
|
||
|
else
|
||
|
if ((pt.y >= rc.bottom) && (pt.y < rc.bottom + HANDLE_SIZE))
|
||
|
return(resizingBottomRight);
|
||
|
else
|
||
|
if ((pt.y >= yMid) && (pt.y < yMid + HANDLE_SIZE))
|
||
|
return(resizingRight);
|
||
|
}
|
||
|
else
|
||
|
if ( (pt.x >= xMid) && (pt.x < xMid + HANDLE_SIZE) )
|
||
|
{
|
||
|
if ((pt.y < rc.top) && (pt.y > rc.top - HANDLE_SIZE))
|
||
|
return(resizingTop);
|
||
|
else
|
||
|
if ((pt.y >= rc.bottom) && (pt.y < rc.bottom + HANDLE_SIZE))
|
||
|
return(resizingBottom);
|
||
|
}
|
||
|
|
||
|
return (defaultState);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
void CTracker::DrawBorder( CDC* dc, const CRect& trackerRect, EDGES edges )
|
||
|
{
|
||
|
if (! moduleInit)
|
||
|
InitTrackers(); // RVUV2
|
||
|
|
||
|
// Some precalculation for drawing the fuzzy borders
|
||
|
int width = trackerRect.Width();
|
||
|
int height = trackerRect.Height();
|
||
|
int borderWidth = HANDLE_SIZE;
|
||
|
int xLength = width - HANDLE_SIZE * 2;
|
||
|
int xHeight = height - HANDLE_SIZE * 2;
|
||
|
int xRight = trackerRect.left + width - HANDLE_SIZE;
|
||
|
int yBottom = trackerRect.top + height - HANDLE_SIZE;
|
||
|
int iOffset = 1;
|
||
|
|
||
|
// Draw the fuzzy borders. Note that we have different bitmaps for
|
||
|
// the vertical and horizontal borders.
|
||
|
COLORREF windowColor = GetSysColor( COLOR_WINDOW );
|
||
|
COLORREF highlightColor = GetSysColor( COLOR_HIGHLIGHT );
|
||
|
|
||
|
dc->SetTextColor( windowColor ); // colors reversed to adjust for
|
||
|
dc->SetBkColor ( highlightColor ); // patblt's reversed world view.
|
||
|
|
||
|
CBrush* oldBrush = dc->SelectObject( &brushHorizBorder );
|
||
|
|
||
|
if (! (edges & top))
|
||
|
{
|
||
|
dc->SelectObject( GetSysBrush( COLOR_APPWORKSPACE ) );
|
||
|
iOffset = 0;
|
||
|
}
|
||
|
|
||
|
dc->PatBlt( trackerRect.left + HANDLE_SIZE, trackerRect.top + iOffset, xLength, borderWidth - 2 * iOffset, PATCOPY );
|
||
|
dc->PatBlt( trackerRect.left + HANDLE_SIZE, yBottom + iOffset, xLength, borderWidth - 2 * iOffset, PATCOPY );
|
||
|
|
||
|
iOffset = 1;
|
||
|
|
||
|
// dc->SelectObject( &brushVertBorder );
|
||
|
|
||
|
if (! (edges & left))
|
||
|
{
|
||
|
dc->SelectObject( GetSysBrush( COLOR_APPWORKSPACE ) );
|
||
|
iOffset = 0;
|
||
|
}
|
||
|
|
||
|
dc->PatBlt( xRight + iOffset, trackerRect.top + HANDLE_SIZE, borderWidth - 2 * iOffset, xHeight, PATCOPY );
|
||
|
dc->PatBlt( trackerRect.left + iOffset, trackerRect.top + HANDLE_SIZE, borderWidth - 2 * iOffset, xHeight, PATCOPY );
|
||
|
|
||
|
dc->SelectObject( oldBrush ); // clean up
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
void CTracker::DrawHandles( CDC* dc, const CRect& rect, EDGES edges )
|
||
|
{
|
||
|
/*
|
||
|
* Some precalculation for tracker handles. The bitmaps are colored,
|
||
|
* but the function that loads them adds the windowColor and
|
||
|
* selectionColor.
|
||
|
*/
|
||
|
int x = rect.left + rect.Width() - HANDLE_SIZE;
|
||
|
int y = rect.top + rect.Height() - HANDLE_SIZE;
|
||
|
int xMid = rect.left + (((rect.Width() + 1) / 2) - (HANDLE_SIZE / 2));
|
||
|
int yMid = rect.top + (((rect.Height() + 1) / 2) - (HANDLE_SIZE / 2));
|
||
|
|
||
|
BOOL bTopLeft = (edges & top ) && (edges & left );
|
||
|
BOOL bTopRight = (edges & top ) && (edges & right);
|
||
|
BOOL bBottomLeft = (edges & bottom) && (edges & left );
|
||
|
BOOL bBottomRight = (edges & bottom) && (edges & right);
|
||
|
/*
|
||
|
* Choose a solid resizing handle if this is the currently selected
|
||
|
* control, otherwise choose a hollow tracker handle.
|
||
|
*/
|
||
|
CDC tempDC;
|
||
|
|
||
|
if (!tempDC.CreateCompatibleDC(dc))
|
||
|
{
|
||
|
theApp.SetGdiEmergency();
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
* Draw the eight resizing handles.
|
||
|
*/
|
||
|
dc->SetTextColor( GetSysColor( COLOR_HIGHLIGHT ) );
|
||
|
dc->SetBkColor ( GetSysColor( COLOR_WINDOW ) );
|
||
|
|
||
|
for (int i = 0; i < 2; i += 1)
|
||
|
{
|
||
|
CBitmap* pOldBitmap = tempDC.SelectObject( i? &g_bmapDragHandle2
|
||
|
: &g_bmapDragHandle );
|
||
|
if (bTopLeft)
|
||
|
dc->BitBlt(rect.left, rect.top, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (edges & top)
|
||
|
dc->BitBlt(xMid, rect.top, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (bTopRight)
|
||
|
dc->BitBlt(x, rect.top, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (edges & right)
|
||
|
dc->BitBlt(x, yMid, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (bBottomRight)
|
||
|
dc->BitBlt(x, y, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (edges & bottom)
|
||
|
dc->BitBlt(xMid, y, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (bBottomLeft)
|
||
|
dc->BitBlt(rect.left, y, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
if (edges & left)
|
||
|
dc->BitBlt(rect.left, yMid, HANDLE_SIZE, HANDLE_SIZE,
|
||
|
&tempDC, 0, 0, SRCCOPY);
|
||
|
|
||
|
edges = (EDGES)~(int)edges;
|
||
|
bTopLeft = !bTopLeft;
|
||
|
bTopRight = !bTopRight;
|
||
|
bBottomLeft = !bBottomLeft;
|
||
|
bBottomRight = !bBottomRight;
|
||
|
|
||
|
tempDC.SelectObject(pOldBitmap);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
void CTracker::DrawBorderRgn( CDC* pdc, const CRect& trackerRect, CRgn *pcRgnPoly)
|
||
|
{
|
||
|
int ixOffset, iyOffset;
|
||
|
|
||
|
if (! moduleInit)
|
||
|
{
|
||
|
InitTrackers(); // RVUV2
|
||
|
}
|
||
|
|
||
|
COLORREF windowColor = GetSysColor( COLOR_WINDOW );
|
||
|
COLORREF highlightColor = GetSysColor( COLOR_HIGHLIGHT );
|
||
|
|
||
|
pdc->SetTextColor( windowColor ); // colors reversed to adjust for
|
||
|
pdc->SetBkColor ( highlightColor ); // patblt's reversed world view.
|
||
|
|
||
|
ixOffset = trackerRect.left + CTracker::HANDLE_SIZE + 1;
|
||
|
iyOffset = trackerRect.top + CTracker::HANDLE_SIZE + 1;
|
||
|
|
||
|
// offset bitmap in the imgwnd from selection boundary
|
||
|
if (pcRgnPoly != NULL
|
||
|
&& pcRgnPoly->GetSafeHandle() != NULL)
|
||
|
{
|
||
|
pcRgnPoly->OffsetRgn( ixOffset, iyOffset );
|
||
|
|
||
|
pdc->FrameRgn( pcRgnPoly, &brushVertBorder, 1, 1 );
|
||
|
|
||
|
pcRgnPoly->OffsetRgn( -ixOffset, -iyOffset );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
void CTracker::DrawHandlesRgn( CDC* dc, const CRect& rect, EDGES edges, CRgn *pcRgnPoly)
|
||
|
{
|
||
|
/*
|
||
|
* Some precalculation for tracker handles. The bitmaps are colored,
|
||
|
* but the function that loads them adds the windowColor and
|
||
|
* selectionColor.
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
CTracker::STATE CTracker::HitTestRgn( const CRect& rc, CPoint pt,
|
||
|
STATE defaultState, CRgn *pcRgnPoly)
|
||
|
{
|
||
|
// if (pcRgnPoly->PtInRegion(pt) != FALSE)
|
||
|
|
||
|
return (defaultState);
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|