692 lines
16 KiB
C++
692 lines
16 KiB
C++
//+---------------------------------------------------------------------
|
|
//
|
|
// File: border.cxx
|
|
//
|
|
// Contents: Border Object Class
|
|
//
|
|
// Classes: OLEBorder
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
#include "headers.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
BOOL OLEBorder::fInit = FALSE;
|
|
HCURSOR OLEBorder::ahc[5] = { NULL, NULL, NULL, NULL, NULL };
|
|
int OLEBorder::iPartMap[14] = {
|
|
ICURS_STD, // 0 NOWHERE
|
|
ICURS_STD, // 1 TOP
|
|
ICURS_STD, // 2 RIGHT
|
|
ICURS_STD, // 3 BOTTOM
|
|
ICURS_STD, // 4 LEFT
|
|
ICURS_NESW, // 5 TOPRIGHT
|
|
ICURS_NWSE, // 6 BOTTOMRIGHT
|
|
ICURS_NESW, // 7 BOTTOMLEFT
|
|
ICURS_NWSE, // 8 TOPLEFT
|
|
ICURS_NS, // 9 TOPHAND
|
|
ICURS_WE, //10 RIGHTHAND
|
|
ICURS_NS, //11 BOTTOMHAND
|
|
ICURS_WE, //12 LEFTHAND
|
|
ICURS_STD //13 INSIDE
|
|
};
|
|
|
|
HCURSOR
|
|
OLEBorder::MapPartToCursor(USHORT usPart)
|
|
{
|
|
if (usPart > MAX_OBPART)
|
|
usPart = 0;
|
|
return ahc[iPartMap[usPart]];
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::InitClass
|
|
//
|
|
//---------------------------------------------------------------
|
|
void
|
|
OLEBorder::InitClass( void )
|
|
{
|
|
_fErased = TRUE;
|
|
_state = 0;
|
|
_sThickness = FBORDER_THICKNESS;
|
|
_sMinHeight = FBORDER_MINHEIGHT;
|
|
_sMinWidth = FBORDER_MINWIDTH;
|
|
if(fInit)
|
|
return;
|
|
|
|
ahc[ICURS_NWSE] = LoadCursor( NULL, IDC_SIZENWSE );
|
|
ahc[ICURS_NESW] = LoadCursor( NULL, IDC_SIZENESW );
|
|
ahc[ICURS_NS] = LoadCursor( NULL, IDC_SIZENS );
|
|
ahc[ICURS_WE] = LoadCursor( NULL, IDC_SIZEWE );
|
|
ahc[ICURS_STD] = LoadCursor( NULL, IDC_SIZEALL );
|
|
fInit = TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::OLEBorder
|
|
//
|
|
//---------------------------------------------------------------
|
|
OLEBorder::OLEBorder( void )
|
|
{
|
|
rect.top = 0;
|
|
rect.left = 0;
|
|
rect.bottom = 0;
|
|
rect.right = 0;
|
|
InitClass();
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::OLEBorder
|
|
//
|
|
//---------------------------------------------------------------
|
|
OLEBorder::OLEBorder( RECT& r )
|
|
{
|
|
rect = r;
|
|
InitClass();
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::~OLEBorder
|
|
//
|
|
//---------------------------------------------------------------
|
|
OLEBorder::~OLEBorder( void )
|
|
{
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::SetState
|
|
//
|
|
//---------------------------------------------------------------
|
|
USHORT
|
|
OLEBorder::SetState( HDC hdc, HWND hwnd, USHORT usBorderState )
|
|
{
|
|
if (_state ^ usBorderState)
|
|
{
|
|
if (hdc != NULL)
|
|
{
|
|
_state |= OBSTYLE_RESERVED;
|
|
Draw(hdc,hwnd);
|
|
}
|
|
}
|
|
_state = usBorderState & (~OBSTYLE_RESERVED);
|
|
if (hdc != NULL)
|
|
Draw(hdc,hwnd);
|
|
|
|
return _state;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::Erase
|
|
//
|
|
//---------------------------------------------------------------
|
|
void
|
|
OLEBorder::Erase(HWND hwnd)
|
|
{
|
|
RECT r;
|
|
if (hwnd != NULL && !_fErased)
|
|
{
|
|
_fErased = TRUE;
|
|
if(_state & OBSTYLE_DIAGONAL_FILL)
|
|
{
|
|
GetBorderRect(r,BP_INSIDE);
|
|
InvalidateRect(hwnd,&r,TRUE);
|
|
}
|
|
else
|
|
{
|
|
for(int i = BP_TOP; i <= BP_LEFT; i++)
|
|
{
|
|
GetBorderRect(r,i);
|
|
InvalidateRect(hwnd,&r,TRUE);
|
|
}
|
|
}
|
|
}
|
|
_state = _state & OBSTYLE_INSIDE;
|
|
}
|
|
|
|
void
|
|
OLEBorder::GetInsideBorder( RECT& rDest, int iEdge )
|
|
{
|
|
int sHalf = _sThickness >> 1;
|
|
int sMid;
|
|
|
|
switch(iEdge)
|
|
{
|
|
case BP_TOP:
|
|
case BP_BOTTOM:
|
|
rDest.left = rect.left;
|
|
rDest.right = rect.right;
|
|
if (iEdge == BP_TOP)
|
|
{
|
|
rDest.top = rect.top;
|
|
rDest.bottom = rect.top + _sThickness;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.bottom - _sThickness;
|
|
rDest.bottom = rect.bottom;
|
|
}
|
|
break;
|
|
|
|
case BP_RIGHT:
|
|
case BP_LEFT:
|
|
rDest.top = rect.top;
|
|
rDest.bottom = rect.bottom;
|
|
if (iEdge == BP_RIGHT)
|
|
{
|
|
rDest.left = rect.right - _sThickness;
|
|
rDest.right = rect.right;
|
|
}
|
|
else
|
|
{
|
|
rDest.left = rect.left;
|
|
rDest.right = rect.left + _sThickness;
|
|
}
|
|
break;
|
|
|
|
case BP_TOPRIGHT:
|
|
case BP_BOTTOMRIGHT:
|
|
rDest.left = rect.right - _sThickness;
|
|
rDest.right = rect.right;
|
|
if (iEdge == BP_TOPRIGHT)
|
|
{
|
|
rDest.top = rect.top;
|
|
rDest.bottom = rect.top + _sThickness;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.bottom - _sThickness;
|
|
rDest.bottom = rect.bottom;
|
|
}
|
|
break;
|
|
|
|
case BP_BOTTOMLEFT:
|
|
case BP_TOPLEFT:
|
|
rDest.left = rect.left;
|
|
rDest.right = rect.left + _sThickness;
|
|
if (iEdge == BP_BOTTOMLEFT)
|
|
{
|
|
rDest.top = rect.bottom - _sThickness;
|
|
rDest.bottom = rect.bottom;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.top;
|
|
rDest.bottom = rect.top + _sThickness;
|
|
}
|
|
break;
|
|
|
|
case BP_TOPHAND:
|
|
case BP_BOTTOMHAND:
|
|
sMid = rect.left + ((rect.right - rect.left) >> 1);
|
|
rDest.left = sMid - sHalf;
|
|
rDest.right = sMid + sHalf;
|
|
if (iEdge == BP_TOPHAND)
|
|
{
|
|
rDest.top = rect.top;
|
|
rDest.bottom = rect.top + _sThickness;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.bottom - _sThickness;
|
|
rDest.bottom = rect.bottom;
|
|
}
|
|
break;
|
|
|
|
case BP_RIGHTHAND:
|
|
case BP_LEFTHAND:
|
|
sMid = rect.top + ((rect.bottom - rect.top) >> 1);
|
|
rDest.top = sMid - sHalf;
|
|
rDest.bottom = sMid + sHalf;
|
|
if (iEdge == BP_LEFTHAND)
|
|
{
|
|
rDest.left = rect.left;
|
|
rDest.right = rect.left + _sThickness;
|
|
}
|
|
else
|
|
{
|
|
rDest.left = rect.right - _sThickness;
|
|
rDest.right = rect.right;
|
|
}
|
|
break;
|
|
|
|
case BP_INSIDE:
|
|
default:
|
|
rDest = rect;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
OLEBorder::GetOutsideBorder( RECT& rDest, int iEdge )
|
|
{
|
|
int sHalf = _sThickness >> 1;
|
|
int sMid;
|
|
|
|
switch(iEdge)
|
|
{
|
|
case BP_TOP:
|
|
case BP_BOTTOM:
|
|
rDest.left = rect.left - _sThickness;
|
|
rDest.right = rect.right + _sThickness;
|
|
if (iEdge == BP_TOP)
|
|
{
|
|
rDest.top = rect.top - _sThickness;
|
|
rDest.bottom = rect.top + 1;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.bottom;
|
|
rDest.bottom = rect.bottom + _sThickness;
|
|
}
|
|
break;
|
|
|
|
case BP_RIGHT:
|
|
case BP_LEFT:
|
|
rDest.top = rect.top - _sThickness;
|
|
rDest.bottom = rect.bottom + _sThickness;
|
|
if (iEdge == BP_RIGHT)
|
|
{
|
|
rDest.left = rect.right;
|
|
rDest.right = rect.right + _sThickness;
|
|
}
|
|
else
|
|
{
|
|
rDest.left = rect.left - _sThickness;
|
|
rDest.right = rect.left + 1;
|
|
}
|
|
break;
|
|
|
|
case BP_TOPRIGHT:
|
|
case BP_BOTTOMRIGHT:
|
|
rDest.left = rect.right;
|
|
rDest.right = rect.right + _sThickness;
|
|
if (iEdge == BP_TOPRIGHT)
|
|
{
|
|
rDest.top = rect.top - _sThickness;
|
|
rDest.bottom = rect.top + 1;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.bottom;
|
|
rDest.bottom = rect.bottom + _sThickness;
|
|
}
|
|
break;
|
|
|
|
case BP_BOTTOMLEFT:
|
|
case BP_TOPLEFT:
|
|
rDest.left = rect.left - _sThickness;
|
|
rDest.right = rect.left + 1;
|
|
if (iEdge == BP_BOTTOMLEFT)
|
|
{
|
|
rDest.top = rect.bottom;
|
|
rDest.bottom = rect.bottom + _sThickness;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.top - _sThickness;
|
|
rDest.bottom = rect.top + 1;
|
|
}
|
|
break;
|
|
|
|
case BP_TOPHAND:
|
|
case BP_BOTTOMHAND:
|
|
sMid = rect.left + ((rect.right - rect.left) >> 1);
|
|
rDest.left = sMid - sHalf;
|
|
rDest.right = sMid + sHalf;
|
|
if (iEdge == BP_TOPHAND)
|
|
{
|
|
rDest.top = rect.top - _sThickness;
|
|
rDest.bottom = rect.top + 1;
|
|
}
|
|
else
|
|
{
|
|
rDest.top = rect.bottom;
|
|
rDest.bottom = rect.bottom + _sThickness;
|
|
}
|
|
break;
|
|
|
|
case BP_RIGHTHAND:
|
|
case BP_LEFTHAND:
|
|
sMid = rect.top + ((rect.bottom - rect.top) >> 1);
|
|
rDest.top = sMid - sHalf;
|
|
rDest.bottom = sMid + sHalf;
|
|
if (iEdge == BP_LEFTHAND)
|
|
{
|
|
rDest.left = rect.left - _sThickness;
|
|
rDest.right = rect.left + 1;
|
|
}
|
|
else
|
|
{
|
|
rDest.left = rect.right;
|
|
rDest.right = rect.right + _sThickness;
|
|
}
|
|
break;
|
|
|
|
case BP_INSIDE:
|
|
default: //inactive border
|
|
rDest.left = rect.left - 1;
|
|
rDest.right = rect.right + 1;
|
|
rDest.top = rect.top - 1;
|
|
rDest.bottom = rect.bottom + 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::GetBorderRect
|
|
//
|
|
//---------------------------------------------------------------
|
|
void
|
|
OLEBorder::GetBorderRect( RECT& rDest, int iEdge )
|
|
{
|
|
if(_state & OBSTYLE_INSIDE)
|
|
GetInsideBorder(rDest,iEdge);
|
|
else
|
|
GetOutsideBorder(rDest,iEdge);
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::SwitchCoords
|
|
//
|
|
//---------------------------------------------------------------
|
|
void
|
|
OLEBorder::SwitchCoords( HWND hwndFrom, HWND hwndTo )
|
|
{
|
|
MapWindowPoints(hwndFrom, hwndTo, (LPPOINT)&rect, 2);
|
|
MapWindowPoints(hwndFrom, hwndTo, &_pt, 1);
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::Draw
|
|
//
|
|
//---------------------------------------------------------------
|
|
void
|
|
OLEBorder::Draw( HDC hdc, HWND hwnd )
|
|
{
|
|
if(hdc == NULL || (_state & ~OBSTYLE_INSIDE) == 0)
|
|
{
|
|
return; //nothing to do!
|
|
}
|
|
|
|
RECT r;
|
|
//
|
|
// the following should be rewritten so any border style
|
|
// can be drawn in XOR mode...
|
|
//
|
|
if (_state & OBSTYLE_XOR)
|
|
{
|
|
if (_state & OBSTYLE_THICK)
|
|
{
|
|
PatBlt(hdc, rect.left - 1, rect.top - 1,
|
|
rect.right - rect.left + 2, 3, PATINVERT);
|
|
|
|
PatBlt(hdc, rect.left - 1, rect.bottom - 2,
|
|
rect.right - rect.left + 2, 3, PATINVERT);
|
|
|
|
PatBlt(hdc, rect.left - 1, rect.top + 2,
|
|
3, rect.bottom - rect.top - 4, PATINVERT);
|
|
|
|
PatBlt(hdc, rect.right - 2, rect.top + 2,
|
|
3, rect.bottom - rect.top - 4, PATINVERT);
|
|
}
|
|
else
|
|
DrawFocusRect(hdc,&rect);
|
|
return;
|
|
}
|
|
|
|
HBRUSH hbrBlack = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
|
HBRUSH hbr;
|
|
COLORREF clrref;
|
|
int i;
|
|
|
|
if (_state & OBSTYLE_RESERVED)
|
|
{
|
|
Erase(hwnd);
|
|
return;
|
|
}
|
|
|
|
if (_state & OBSTYLE_ACTIVE)
|
|
{
|
|
clrref = GetSysColor(COLOR_ACTIVECAPTION);
|
|
}
|
|
else
|
|
{
|
|
clrref = GetSysColor(COLOR_WINDOWFRAME);
|
|
}
|
|
|
|
if ((_state & OBSTYLE_TYPEMASK) == OBSTYLE_DIAGONAL_FILL)
|
|
{
|
|
hbr = CreateHatchBrush(HS_DIAGCROSS,clrref);
|
|
GetBorderRect(r,BP_INSIDE);
|
|
FillRect(hdc,&r,hbr);
|
|
DeleteObject(hbr);
|
|
}
|
|
else if ((_state & OBSTYLE_TYPEMASK) == OBSTYLE_SOLID_PEN)
|
|
{
|
|
GetBorderRect(r,BP_INSIDE);
|
|
FrameRect(hdc,&r,hbrBlack);
|
|
}
|
|
|
|
if (_state & OBSTYLE_THICK)
|
|
{
|
|
if (_state & OBSTYLE_INSIDE)
|
|
InflateRect(&r,-1,-1);
|
|
else
|
|
InflateRect(&r,1,1);
|
|
FrameRect(hdc,&rect,hbrBlack);
|
|
}
|
|
|
|
if (_state & OBSTYLE_HANDLED)
|
|
{
|
|
for (i = BP_TOPRIGHT; i <= BP_TOPLEFT; i++)
|
|
{
|
|
GetBorderRect(r,i);
|
|
FillRect(hdc,&r,hbrBlack);
|
|
}
|
|
for (i = BP_TOPHAND; i <= BP_LEFTHAND; i++)
|
|
{
|
|
GetBorderRect(r,i);
|
|
FillRect(hdc,&r,hbrBlack);
|
|
}
|
|
}
|
|
_fErased = FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::QueryHit
|
|
//
|
|
//---------------------------------------------------------------
|
|
USHORT
|
|
OLEBorder::QueryHit( POINT point )
|
|
{
|
|
RECT r = rect;
|
|
USHORT usWhere = BP_NOWHERE;
|
|
|
|
if ((_state & OBSTYLE_INSIDE) == 0)
|
|
InflateRect(&r,_sThickness,_sThickness);
|
|
if (PtInRect(&r,point))
|
|
{
|
|
usWhere = BP_INSIDE;
|
|
//
|
|
//test against the real inside to optimize this case...
|
|
//
|
|
InflateRect(&r,-_sThickness,-_sThickness);
|
|
|
|
//
|
|
// PtInRect counts the top and left borders as being inside, so
|
|
// we must account for this.
|
|
//
|
|
r.left++;
|
|
r.top++;
|
|
if (!PtInRect(&r,point))
|
|
{
|
|
//
|
|
//Search for the "handle" that was hit...
|
|
//
|
|
USHORT i;
|
|
for (i = BP_LEFTHAND; i >= BP_TOP; i--)
|
|
{
|
|
GetBorderRect(r,i);
|
|
if (PtInRect(&r,point))
|
|
{
|
|
usWhere = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(usWhere);
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::QueryMoveCursor
|
|
//
|
|
//---------------------------------------------------------------
|
|
HCURSOR
|
|
OLEBorder::QueryMoveCursor( POINT ptCurrent, BOOL fMustMove )
|
|
{
|
|
//
|
|
//Stash part-hit info so we can do the right thing durring
|
|
//upcomming move/size operation
|
|
//
|
|
if (fMustMove)
|
|
{
|
|
_usPart = BP_INSIDE;
|
|
}
|
|
else
|
|
{
|
|
_usPart = QueryHit(ptCurrent);
|
|
}
|
|
return MapPartToCursor(_usPart);
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::BeginMove
|
|
//
|
|
//---------------------------------------------------------------
|
|
HCURSOR
|
|
OLEBorder::BeginMove( HDC hdc, HWND hwnd, POINT ptStart,
|
|
BOOL fMustMove )
|
|
{
|
|
if(_state == 0 )
|
|
_state = OBSTYLE_SOLID_PEN;
|
|
SetState( hdc, hwnd, _state | OBSTYLE_XOR | OBSTYLE_THICK);
|
|
_pt = ptStart;
|
|
return QueryMoveCursor(ptStart,fMustMove);
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::UpdateMove
|
|
//
|
|
//---------------------------------------------------------------
|
|
RECT&
|
|
OLEBorder::UpdateMove( HDC hdc, HWND hwnd, POINT ptCurrent, BOOL fNewRegion )
|
|
{
|
|
if ((ptCurrent.x == _pt.x) && (ptCurrent.y == _pt.y))
|
|
return rect;
|
|
|
|
RECT rTemp = rect;
|
|
Draw(hdc,hwnd);
|
|
if (fNewRegion)
|
|
{
|
|
rTemp.left = min(_pt.x,ptCurrent.x);
|
|
rTemp.top = min(_pt.y,ptCurrent.y);
|
|
rTemp.right = max(_pt.x,ptCurrent.x);
|
|
rTemp.bottom = max(_pt.y,ptCurrent.y);
|
|
}
|
|
else
|
|
{
|
|
int xDelta = ptCurrent.x - _pt.x;
|
|
int yDelta = ptCurrent.y - _pt.y;
|
|
switch (_usPart)
|
|
{
|
|
case BP_INSIDE:
|
|
case BP_TOP:
|
|
case BP_BOTTOM:
|
|
case BP_RIGHT:
|
|
case BP_LEFT:
|
|
default:
|
|
OffsetRect(&rTemp,xDelta,yDelta);
|
|
break;
|
|
|
|
case BP_TOPRIGHT:
|
|
rTemp.right += xDelta;
|
|
rTemp.top += yDelta;
|
|
break;
|
|
|
|
case BP_BOTTOMRIGHT:
|
|
rTemp.right += xDelta;
|
|
rTemp.bottom += yDelta;
|
|
break;
|
|
|
|
case BP_BOTTOMLEFT:
|
|
rTemp.bottom += yDelta;
|
|
rTemp.left += xDelta;
|
|
break;
|
|
|
|
case BP_TOPLEFT:
|
|
rTemp.top += yDelta;
|
|
rTemp.left += xDelta;
|
|
break;
|
|
|
|
case BP_TOPHAND:
|
|
rTemp.top += yDelta;
|
|
break;
|
|
|
|
case BP_BOTTOMHAND:
|
|
rTemp.bottom += yDelta;
|
|
break;
|
|
|
|
case BP_RIGHTHAND:
|
|
rTemp.right += xDelta;
|
|
break;
|
|
|
|
case BP_LEFTHAND:
|
|
rTemp.left += xDelta;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
//clip resize to repect minimum height & width specification
|
|
//
|
|
if((rTemp.right - rTemp.left >= _sMinWidth) &&
|
|
(rTemp.bottom - rTemp.top >= _sMinHeight))
|
|
{
|
|
rect = rTemp;
|
|
if (!fNewRegion)
|
|
{
|
|
_pt = ptCurrent;
|
|
}
|
|
}
|
|
|
|
Draw(hdc,hwnd);
|
|
|
|
return rect;
|
|
}
|
|
|
|
//+---------------------------------------------------------------
|
|
//
|
|
// Member: OLEBorder::EndMove
|
|
//
|
|
//---------------------------------------------------------------
|
|
RECT&
|
|
OLEBorder::EndMove( HDC hdc, HWND hwnd, POINT ptCurrent, USHORT usBorderState )
|
|
{
|
|
SetState( hdc, hwnd, usBorderState );
|
|
return rect;
|
|
}
|