home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
ctltrack.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
10KB
|
349 lines
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#ifdef AFXCTL_CORE2_SEG
#pragma code_seg(AFXCTL_CORE2_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
AFX_STATIC_DATA const int _afxResizeStyle =
CRectTracker::resizeInside | CRectTracker::resizeOutside;
AFX_STATIC void AFXAPI _AfxOffsetTrackerRect(CRect& rect, CWnd* pWnd)
{
DWORD dwStyle = pWnd->GetStyle();
DWORD dwExStyle = pWnd->GetExStyle();
int nBorders = ((dwStyle & WS_BORDER) != 0) +
((dwExStyle & WS_EX_CLIENTEDGE) != 0) * 2;
int dx = -nBorders * GetSystemMetrics(SM_CXBORDER);
int dy = -nBorders * GetSystemMetrics(SM_CYBORDER);
if (dwExStyle & WS_EX_LEFTSCROLLBAR)
dx -= GetSystemMetrics(SM_CXVSCROLL);
rect.OffsetRect(dx - rect.left, dy - rect.top);
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::CreateTracker - Creates tracker for UIActive control
void COleControl::CreateTracker(BOOL bHandles, BOOL bHatching)
{
CreateTracker(bHandles, bHatching, NULL);
}
void COleControl::CreateTracker(BOOL bHandles, BOOL bHatching, LPCRECT prcClip)
{
ASSERT(bHandles || bHatching);
#ifdef _AFXDLL
ASSERT(!m_bOpen);
#endif
ASSERT(m_bUIActive);
ASSERT(m_pRectTracker == NULL);
UINT nStyle = 0;
if (bHandles)
nStyle |= CRectTracker::resizeOutside;
if (bHatching)
nStyle |= CRectTracker::hatchedBorder;
ASSERT(nStyle != 0);
TRY
{
// Create the tracker.
CRect rectTmp = m_rcPos;
_AfxOffsetTrackerRect(rectTmp, this);
m_pRectTracker = new CControlRectTracker(rectTmp, nStyle);
// Reset the window sizes, reflecting the tracker
if (prcClip != NULL)
m_pRectTracker->m_rectClip = *prcClip;
else
prcClip = m_rcPos;
OnSetObjectRects(m_rcPos, prcClip);
}
CATCH (CException, e)
{
// If anything went wrong, just continue without the tracker.
if (m_pRectTracker != NULL)
{
delete m_pRectTracker;
m_pRectTracker = NULL;
}
}
END_CATCH
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::DestroyTracker - destroys tracker when control UIDeactivates
void COleControl::DestroyTracker()
{
#ifdef _AFXDLL
ASSERT(!m_bOpen);
#endif
ASSERT(m_bUIActive);
if (m_pRectTracker == NULL)
return;
// Destroy the tracker.
CRect rectClip = m_pRectTracker->m_rectClip;
delete m_pRectTracker;
m_pRectTracker = NULL;
// Reset the position based on no tracker present
OnSetObjectRects(m_rcPos, rectClip);
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::OnNcPaint - handler for WM_NCPAINT message
void COleControl::OnNcPaint()
{
#ifdef _AFXDLL
if (m_bOpen || m_pRectTracker == NULL)
#else
if (m_pRectTracker == NULL)
#endif
{
Default();
return;
}
DWORD dwStyle = GetStyle();
DWORD dwExStyle = GetExStyle();
DWORD dwScrollStyle = dwStyle & (WS_HSCROLL | WS_VSCROLL);
// Paint scrollbars, if any.
if (dwScrollStyle != 0)
Default();
UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
CWindowDC dc(this);
// Convert client coords to window coords, draw tracker, and convert back.
CRect& rectTrack = m_pRectTracker->m_rect;
int dx = rectTrack.left - nHandleSize;
int dy = rectTrack.top - nHandleSize;
rectTrack.OffsetRect(-dx, -dy);
CRect rc = rectTrack;
m_pRectTracker->Draw(&dc);
m_pRectTracker->m_rect.OffsetRect(dx, dy);
// Draw border, if any.
_AfxDrawBorders(&dc, rc, (dwStyle & WS_BORDER),
(dwExStyle & WS_EX_CLIENTEDGE));
if (dwScrollStyle == (WS_HSCROLL | WS_VSCROLL))
{
// Workaround for Windows bug:
// Draw the corner between the scrollbars
int cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
if (dwExStyle & WS_EX_LEFTSCROLLBAR) // Middle East Windows only
rc.right = rc.left + cxVScroll;
else
rc.left = rc.right - cxVScroll;
rc.top = rc.bottom - GetSystemMetrics(SM_CYVSCROLL);
CBrush brushGUI(GetSysColor(COLOR_3DFACE));
dc.FillRect(rc, &brushGUI);
}
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::OnNcCalcSize - handler for WM_NCCALCSIZE message
void COleControl::OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS* lpParams)
{
Default();
#ifdef _AFXDLL
if (m_bOpen || m_pRectTracker == NULL)
#else
if (m_pRectTracker == NULL)
#endif
return;
// Adjust client rect to make room for tracker.
UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
::InflateRect(lpParams->rgrc, -(int)nHandleSize, -(int)nHandleSize);
m_pRectTracker->m_rect = m_rcPos;
_AfxOffsetTrackerRect(m_pRectTracker->m_rect, this);
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::OnNcHitTest - handler for WM_NCHITTEST message
UINT COleControl::OnNcHitTest(CPoint point)
{
#ifdef _AFXDLL
if (m_bOpen || m_pRectTracker == NULL ||
#else
if (m_pRectTracker == NULL ||
#endif
!(m_pRectTracker->m_nStyle & _afxResizeStyle))
{
return (UINT)Default();
}
UINT nHitCode = (UINT)Default();
// Check for scrollbar or sizebox hit.
if ((nHitCode == HTHSCROLL) || (nHitCode == HTVSCROLL) ||
(nHitCode == HTSIZE))
{
return nHitCode;
}
// Check for client area hit.
CPoint pointClient(point);
ScreenToClient(&pointClient);
CRect rect;
GetClientRect(rect);
if (rect.PtInRect(pointClient))
return HTCLIENT;
// Check for border hit.
UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
GetWindowRect(rect);
rect.InflateRect(-(int)nHandleSize, -(int)nHandleSize);
if (rect.PtInRect(point))
return HTBORDER;
// If tracker detects a hit, return HTBORDER; otherwise HTNOWHERE.
nHitCode = m_pRectTracker->HitTest(pointClient);
return (nHitCode == CRectTracker::hitNothing) ? HTNOWHERE : HTBORDER;
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::OnNcLButtonDown - handler for WM_NCLBUTTONDOWN message
void COleControl::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
#ifdef _AFXDLL
if (m_bOpen || m_pRectTracker == NULL ||
#else
if (m_pRectTracker == NULL ||
#endif
!(m_pRectTracker->m_nStyle & _afxResizeStyle) ||
(nHitTest == HTHSCROLL) || (nHitTest == HTVSCROLL))
{
Default();
return;
}
ScreenToClient(&point);
// Setup a (semi-)permanent CWnd for the control's parent window
CRect rectBefore = m_pRectTracker->m_rect;
CWnd* pWndClip = CWnd::FromHandle(::GetParent(GetOuterWindow()->m_hWnd));
// Move or resize the tracker.
BOOL bTrack = m_pRectTracker->Track(this, point, FALSE, pWndClip);
if (bTrack)
{
ASSERT(m_pInPlaceSite);
CRect rectAfter = m_pRectTracker->m_rect;
if (rectBefore != rectAfter)
{
// If rectangle changed, adjust the tracker's rectangle and move
// the control.
m_pRectTracker->m_rect.OffsetRect(-m_pRectTracker->m_rect.left,
-m_pRectTracker->m_rect.top);
CWnd* pWndOuter = GetOuterWindow();
CWnd* pWndParent = pWndOuter->GetParent();
CRect rectWindow;
CRect rectParent;
pWndOuter->GetWindowRect(rectWindow);
pWndParent->GetClientRect(rectParent);
pWndParent->ClientToScreen(rectParent);
int nBorderWidth = GetBorderStyle()*GetSystemMetrics( SM_CXBORDER );
int nBorderHeight = GetBorderStyle()*GetSystemMetrics( SM_CYBORDER );
UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
rectAfter.OffsetRect(rectWindow.left - rectParent.left +
nHandleSize + nBorderWidth, rectWindow.top - rectParent.top +
nHandleSize + nBorderHeight);
// Update the control's extents.
SIZEL szlPixels;
SIZEL szlHimetric;
szlPixels.cx = (long)rectAfter.Width();
szlPixels.cy = (long)rectAfter.Height();
_AfxXformSizeInPixelsToHimetric(NULL, &szlPixels, &szlHimetric);
if ((m_cxExtent != szlHimetric.cx) ||
(m_cyExtent != szlHimetric.cy))
{
m_cxExtent = szlHimetric.cx;
m_cyExtent = szlHimetric.cy;
SetModifiedFlag();
}
// Move/resize the control's window.
m_pInPlaceSite->OnPosRectChange(rectAfter);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// COleControl::OnSetCursor - handler for WM_SETCURSOR message
BOOL COleControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT)
{
#ifdef _AFXDLL
if (m_bOpen || m_pRectTracker == NULL ||
#else
if (m_pRectTracker == NULL ||
#endif
!(m_pRectTracker->m_nStyle & _afxResizeStyle))
{
return (BOOL)Default();
}
if ((nHitTest == HTCLIENT) || (nHitTest == HTHSCROLL) ||
(nHitTest == HTVSCROLL) || (nHitTest == HTSIZE))
{
// In client area: use default cursor or arrow.
if (!Default())
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
}
else
{
// In non-client area: use tracker-supplied cursor.
m_pRectTracker->SetCursor(pWnd, HTCLIENT);
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Force any extra compiler-generated code into AFX_INIT_SEG
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif