windows-nt/Source/XPSP1/NT/multimedia/media/sndrec32/o2base/ipborder.cxx
2020-09-26 16:20:57 +08:00

436 lines
12 KiB
C++

//+---------------------------------------------------------------------
//
// File: ipborder.cxx
//
// Classes: InPlaceBorder
//
// Notes: Use of this class limits windows to the use
// of the non-client region for UIAtive borders
// only: Standard (non-control window) scroll bars
// are specifically NOT supported.
//
// History: 14-May-93 CliffG Created.
//
//------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
#define IPB_GRABFACTOR 3
#define SetWF(hwnd,wf) SetWindowLongPtr(hwnd, GWL_STYLE, \
GetWindowLongPtr(hwnd,GWL_STYLE) | (wf))
#define ClrWF(hwnd,wf) SetWindowLongPtr(hwnd, GWL_STYLE, \
GetWindowLongPtr(hwnd,GWL_STYLE) &~(wf))
#define TestWF(hwnd,wf) (GetWindowLongPtr(hwnd,GWL_STYLE) & (wf))
WORD InPlaceBorder::_cUsage = 0;
HBRUSH InPlaceBorder::_hbrActiveCaption;
HBRUSH InPlaceBorder::_hbrInActiveCaption;
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::DrawFrame
//
//---------------------------------------------------------------
void
InPlaceBorder::DrawFrame(HWND hwnd)
{
if(!_fUIActive)
return;
HDC hdc = GetWindowDC(hwnd);
if (!hdc)
return;
HBRUSH hbr;
if(_fParentActive)
hbr = _hbrActiveCaption;
else
hbr = _hbrInActiveCaption;
if (hbr)
{
RECT rcWhole;
GetWindowRect(hwnd, &rcWhole);
OffsetRect(&rcWhole, -rcWhole.left, -rcWhole.top);
RECT rc;
//Top
rc = rcWhole;
rc.bottom = rc.top + _cyFrame;
FillRect(hdc, &rc, hbr);
//Left
rc = rcWhole;
rc.right = rc.left + _cxFrame;
FillRect(hdc, &rc, hbr);
//Bottom
rc = rcWhole;
rc.top = rc.bottom - _cyFrame;
FillRect(hdc, &rc, hbr);
//Right
rc = rcWhole;
rc.left = rc.right - _cxFrame;
FillRect(hdc, &rc, hbr);
if(TestWF(hwnd, WS_THICKFRAME)) //Resizable window?
{
//
//Draw grab handles at 4 corners of the border...
//
hbr = (HBRUSH)GetStockObject( BLACK_BRUSH );
//TopLeft
rc = rcWhole;
rc.right = rc.left + _cxFrame;
rc.bottom = rc.top + _cyFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
rc.bottom = rc.top + _cyFrame;
rc.right = rc.left + _cxFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
//TopRight
rc.right = rcWhole.right;
rc.left = rc.right - _cxFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
rc.left = rc.right - _cxFrame;
rc.bottom = rc.top + _cyFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
//BottomLeft
rc = rcWhole;
rc.top = rc.bottom - _cyFrame * IPB_GRABFACTOR;
rc.right = rc.left + _cxFrame;
FillRect(hdc, &rc, hbr);
rc.top = rc.bottom - _cyFrame;
rc.right = rc.left + _cxFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
//BottomRight
rc.right = rcWhole.right;
rc.left = rc.right - _cxFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
rc.right = rcWhole.right;
rc.left = rc.right - _cxFrame;
rc.top = rc.bottom - _cyFrame * IPB_GRABFACTOR;
FillRect(hdc, &rc, hbr);
}
}
ReleaseDC(hwnd, hdc);
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::HitTest
//
//---------------------------------------------------------------
LONG
InPlaceBorder::HitTest(HWND hwnd, int x, int y)
{
POINT pt = { x, y };
RECT rcClient;
GetWindowRect(hwnd, &rcClient);
CalcClientRect(hwnd, &rcClient);
if (PtInRect(&rcClient, pt))
return HTCLIENT;
// We're somewhere on the window frame.
if (y >= rcClient.bottom)
{
if (x <= rcClient.left + _cxFrame * IPB_GRABFACTOR)
return HTBOTTOMLEFT;
if (x >= rcClient.right - _cxFrame * IPB_GRABFACTOR)
return HTBOTTOMRIGHT;
return HTBOTTOM;
}
else if (y <= rcClient.top)
{
if (x <= rcClient.left + _cxFrame * IPB_GRABFACTOR)
return(HTTOPLEFT);
if (x >= rcClient.right - _cxFrame * IPB_GRABFACTOR)
return(HTTOPRIGHT);
return HTTOP;
}
else if (x <= rcClient.left)
{
if (y <= rcClient.top + _cyFrame * IPB_GRABFACTOR)
return HTTOPLEFT;
if (y >= rcClient.bottom - _cyFrame * IPB_GRABFACTOR)
return HTBOTTOMLEFT;
return HTLEFT;
}
else
{
if (y <= rcClient.top + _cyFrame * IPB_GRABFACTOR)
return HTTOPRIGHT;
if (y >= rcClient.bottom - _cyFrame * IPB_GRABFACTOR)
return HTBOTTOMRIGHT;
return HTRIGHT;
}
return HTNOWHERE;
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::DefWindowProc
//
//---------------------------------------------------------------
LRESULT
InPlaceBorder::DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = 0L;
//REVIEW code assumes an SDI app...
if(_hwnd == NULL)
return ::DefWindowProc(hwnd,msg,wParam,lParam);
switch (msg)
{
case WM_WINDOWPOSCHANGED:
if(_pSite != NULL && _cResizing == 0 && _fUIActive)
{
++_cResizing;
RECT rc;
GetChildWindowRect(hwnd, &rc);
InflateRect(&rc,-_cxFrame,-_cyFrame);
_pSite->OnPosRectChange(&rc);
_cResizing--;
}
break;
case WM_NCCALCSIZE: // lParam == LPRECT of window rect
//
//Turn off the WS_THICKFRAME style bit during
//default processing so we keep ownership of visualization...
//
if (TestWF(hwnd, WS_THICKFRAME))
{
ClrWF(hwnd, WS_THICKFRAME);
lRet = ::DefWindowProc(hwnd, msg, wParam,lParam);
SetWF(hwnd, WS_THICKFRAME);
}
CalcClientRect(hwnd, (LPRECT)lParam);
return lRet;
case WM_NCHITTEST: // lParam is POINT in screen cords
return HitTest(hwnd, LOWORD(lParam), HIWORD(lParam));
case WM_NCPAINT:
DrawFrame(hwnd);
return 0L;
case WM_NCLBUTTONDOWN:
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCRBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCMBUTTONDBLCLK:
case WM_NCACTIVATE: // wParam == active state
case WM_NCCREATE: // Sent before WM_CREATE
case WM_NCDESTROY: // Sent before WM_DESTROY
break;
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::InPlaceBorder
//
//---------------------------------------------------------------
InPlaceBorder::InPlaceBorder(void)
{
_fParentActive = TRUE;
_fUIActive = FALSE;
_hwnd = NULL;
_pSite = NULL;
_cResizing = 0;
_cxFrame = _cyFrame = IPBORDER_THICKNESS;
if(_cUsage++ == 0)
{
// the following could fail and we would be hosed...
_hbrActiveCaption = CreateHatchBrush(HS_BDIAGONAL,
GetSysColor(COLOR_ACTIVECAPTION));
_hbrInActiveCaption = CreateHatchBrush(HS_BDIAGONAL,
GetSysColor(COLOR_WINDOWFRAME));
}
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::~InPlaceBorder
//
//---------------------------------------------------------------
InPlaceBorder::~InPlaceBorder(void)
{
if(--_cUsage == 0)
{
DeleteObject(_hbrActiveCaption);
_hbrActiveCaption = NULL;
DeleteObject(_hbrInActiveCaption);
_hbrInActiveCaption = NULL;
}
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::SetState
//
//Change the border state: reflected in the nonclient window border
//---------------------------------------------------------------
void
InPlaceBorder::SetUIActive(BOOL fUIActive)
{
if(_hwnd == NULL)
return;
if(_fUIActive != fUIActive)
{
RECT rcClient;
GetChildWindowRect(_hwnd, &rcClient);
int cx = rcClient.right - rcClient.left;
int cy = rcClient.bottom - rcClient.top;
int x = rcClient.left;
int y = rcClient.top;
BOOL fResize = FALSE;
if (fUIActive)
{
fResize = TRUE;
cx += _cxFrame * 2;
cy += _cyFrame * 2;
x -= _cxFrame;
y -= _cyFrame;
}
else if (_fUIActive)
{
fResize = TRUE;
cx -= _cxFrame * 2;
cy -= _cyFrame * 2;
x += _cxFrame;
y += _cyFrame;
}
if (fResize)
{
//
//Set our state member up so CalcClientRect generates correct values,
//then move the window (keeping client area same size and position)
//
_fUIActive = fUIActive;
++_cResizing;
SetWindowPos( _hwnd, NULL, x, y, cx, cy, SWP_FRAMECHANGED |
SWP_NOACTIVATE | SWP_NOZORDER);
RedrawFrame();
_cResizing--;
}
else
{
InvalidateFrame();
}
}
_fUIActive = fUIActive;
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::SetSize
//
//---------------------------------------------------------------
void
InPlaceBorder::SetSize(HWND hwnd, RECT& rc)
{
int cx = rc.right - rc.left;
int cy = rc.bottom - rc.top;
int x = rc.left;
int y = rc.top;
if(_fUIActive)
{
cx += _cxFrame * 2;
cy += _cyFrame * 2;
x -= _cxFrame;
y -= _cyFrame;
}
++_cResizing;
MoveWindow(hwnd, x, y, cx, cy, TRUE);
_cResizing--;
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::Erase
//
// Force border state to non-UIActive, managing the coresponding
// change in border appearance
//
//---------------------------------------------------------------
void
InPlaceBorder::Erase(void)
{
if(_hwnd == NULL)
return;
SetUIActive(FALSE);
_fParentActive = TRUE;
InvalidateFrame();
RedrawFrame();
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::SetBorderSize
//
//---------------------------------------------------------------
void
InPlaceBorder::SetBorderSize( int cx, int cy )
{
if(cx < 0)
cx = 0;
if(cy < 0)
cy = 0;
_cxFrame = cx;
_cyFrame = cy;
InvalidateFrame();
RedrawFrame();
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::GetBorderSize
//
//---------------------------------------------------------------
void
InPlaceBorder::GetBorderSize( LPINT pcx, LPINT pcy )
{
*pcx = _cxFrame;
*pcy = _cyFrame;
}
//+---------------------------------------------------------------
//
// Member: InPlaceBorder::Attach
//
//---------------------------------------------------------------
void
InPlaceBorder::Attach(HWND hwnd, BOOL fUIActive)
{
if((_hwnd = hwnd) != NULL)
{
SetUIActive(fUIActive);
InvalidateFrame(); //force first-time NCCALC
}
}
void
InPlaceBorder::Bind(LPOLEINPLACESITE pSite, HWND hwnd, BOOL fUIActive)
{
_pSite = NULL;
if((_hwnd = hwnd) != NULL && (_pSite = pSite) != NULL)
{
SetUIActive(fUIActive);
InvalidateFrame(); //force first-time NCCALC
}
}