You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
395 lines
8.8 KiB
395 lines
8.8 KiB
#include "precomp.h"
|
|
#include "splitbar2.h"
|
|
#include "resource.h"
|
|
|
|
/* static */ int CSplitBar2::ms_dxpSplitBar = 0; // width of a standard split bar window // GetSystemMetrics(SM_CXSIZEFRAME);
|
|
|
|
/* static */ void CSplitBar2::_UpdateSplitBar(void)
|
|
{
|
|
ms_dxpSplitBar = GetSystemMetrics(SM_CXSIZEFRAME);
|
|
}
|
|
|
|
/* C S P L I T B A R */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: CSplitBar2
|
|
|
|
-------------------------------------------------------------------------*/
|
|
CSplitBar2::CSplitBar2(void)
|
|
: m_hwndBuddy (NULL)
|
|
, m_hwndParent(NULL)
|
|
, m_pfnAdjust(NULL)
|
|
, m_Context(NULL)
|
|
, m_hdcDrag(NULL)
|
|
, m_fCaptured(FALSE)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::CSplitBar2);
|
|
|
|
_UpdateSplitBar();
|
|
|
|
DBGEXIT(CSplitBar2::CSplitBar2);
|
|
}
|
|
|
|
|
|
CSplitBar2::~CSplitBar2()
|
|
{
|
|
DBGENTRY(CSplitBar2::~CSplitBar2);
|
|
|
|
if( ::IsWindow( m_hWnd ) )
|
|
{
|
|
DestroyWindow();
|
|
}
|
|
|
|
DBGEXIT(CSplitBar2::~CSplitBar2);
|
|
}
|
|
|
|
|
|
|
|
HRESULT CSplitBar2::Create(HWND hwndBuddy, PFN_ADJUST pfnAdjust, LPARAM Context)
|
|
{
|
|
DBGENTRY(CSplitBar2::Create);
|
|
HRESULT hr = S_OK;
|
|
|
|
if( hwndBuddy && pfnAdjust )
|
|
{
|
|
m_hwndBuddy = hwndBuddy;
|
|
m_hwndParent = ::GetParent(hwndBuddy);
|
|
m_pfnAdjust = pfnAdjust;
|
|
m_Context = Context;
|
|
|
|
RECT rc;
|
|
SetRect( &rc, 0, 0, ms_dxpSplitBar, 0 );
|
|
|
|
if( !CWindowImpl<CSplitBar2>::Create( m_hwndParent, rc ) )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
}
|
|
|
|
DBGEXIT_HR(CSplitBar2::Create,hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
LRESULT CSplitBar2::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
|
|
|
|
DBGENTRY(CSplitBar2::OnLButtonDown);
|
|
|
|
POINT pt;
|
|
pt.x = LOWORD(lParam);
|
|
pt.y = HIWORD(lParam);
|
|
|
|
_TrackDrag(pt);
|
|
|
|
DBGEXIT(CSplitBar2::OnLButtonDown);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
/* C O N S T R A I N D R A G P O I N T */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: _ConstrainDragPoint
|
|
|
|
-------------------------------------------------------------------------*/
|
|
int CSplitBar2::_ConstrainDragPoint(short x)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::_ConstrainDragPoint);
|
|
|
|
|
|
// Factor out the drag offset (to make calculations easier)
|
|
int dx = x - m_dxDragOffset;
|
|
|
|
// Don't allow the panes to go below their minimum size
|
|
if (dx < m_dxMin)
|
|
{
|
|
dx = m_dxMin;
|
|
}
|
|
else if (dx > m_dxMax)
|
|
{
|
|
dx = m_dxMax;
|
|
}
|
|
|
|
|
|
DBGEXIT(CSplitBar2::_ConstrainDragPoint);
|
|
|
|
// Factor the drag offset back in
|
|
return (m_dxDragOffset + dx);
|
|
}
|
|
|
|
|
|
/* D R A W B A R */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: _DrawBar
|
|
|
|
-------------------------------------------------------------------------*/
|
|
void CSplitBar2::_DrawBar(void)
|
|
{
|
|
DBGENTRY(CSplitBar2::_DrawBar);
|
|
|
|
RECT rc;
|
|
|
|
RECT ClientRect;
|
|
GetClientRect( &ClientRect );
|
|
|
|
// Rectangle is a larger to make it easier to see.
|
|
rc.top = ClientRect.top;
|
|
rc.bottom = ClientRect.bottom;
|
|
rc.left = m_xCurr - (m_dxDragOffset + 1); //ClientRect.left +
|
|
rc.right = rc.left + ms_dxpSplitBar + 1;
|
|
::MapWindowPoints(m_hwndParent, GetDesktopWindow(), (POINT *) &rc, 2);
|
|
|
|
::InvertRect(m_hdcDrag, &rc);
|
|
|
|
DBGEXIT(CSplitBar2::_DrawBar);
|
|
}
|
|
|
|
|
|
/* F I N I T D R A G L O O P */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: FInitDragLoop
|
|
|
|
Initialize the mouse down drag loop.
|
|
Return FALSE if there was a problem.
|
|
-------------------------------------------------------------------------*/
|
|
BOOL CSplitBar2::FInitDragLoop(POINT pt)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::FInitDragLoop);
|
|
|
|
if (NULL != ::GetCapture())
|
|
{
|
|
ERROR_OUT(("InitDragLoop: Unable to capture"));
|
|
return FALSE;
|
|
}
|
|
|
|
// handle pending WM_PAINT messages
|
|
MSG msg;
|
|
while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
|
|
{
|
|
if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
|
|
return FALSE;
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
HWND hwndDesktop = GetDesktopWindow();
|
|
DWORD dwFlags = ::LockWindowUpdate(hwndDesktop) ? DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE : DCX_WINDOW|DCX_CACHE;
|
|
|
|
ASSERT(m_hdcDrag == NULL);
|
|
m_hdcDrag = ::GetDCEx(hwndDesktop, NULL, dwFlags);
|
|
ASSERT(m_hdcDrag != NULL);
|
|
|
|
ASSERT(!m_fCaptured);
|
|
SetCapture();
|
|
ASSERT(m_hWnd == GetCapture());
|
|
m_fCaptured = TRUE;
|
|
|
|
m_dxDragOffset = pt.x;
|
|
m_xCurr = pt.x;
|
|
_DrawBar();
|
|
|
|
RECT rc;
|
|
// determine the drag extent
|
|
::GetClientRect(m_hwndBuddy, &rc);
|
|
::MapWindowPoints(m_hwndBuddy, m_hwndParent, (POINT *) &rc, 1);
|
|
m_dxMin = rc.left + (32 + (3*2));
|
|
|
|
::GetClientRect( ::GetParent( m_hwndParent ) , &rc);
|
|
m_dxMax = RectWidth(rc) - (ms_dxpSplitBar + 176);
|
|
|
|
if (m_dxMax < m_dxMin)
|
|
m_dxMax = m_dxMin;
|
|
|
|
TRACE_OUT(("captured mouse at (%d,%d) (min=%d, max=%d)", pt.x, pt.y, m_dxMin, m_dxMax));
|
|
|
|
DBGEXIT(CSplitBar2::FInitDragLoop);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* O N D R A G M O V E */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: OnDragMove
|
|
|
|
-------------------------------------------------------------------------*/
|
|
void CSplitBar2::OnDragMove(POINT pt)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::OnDragMove);
|
|
|
|
ASSERT(m_fCaptured);
|
|
|
|
::ScreenToClient(m_hwndParent, &pt);
|
|
int x = _ConstrainDragPoint((short)pt.x);
|
|
if (x != m_xCurr)
|
|
{
|
|
_DrawBar();
|
|
m_xCurr = x;
|
|
_DrawBar();
|
|
}
|
|
|
|
DBGEXIT(CSplitBar2::OnDragMove);
|
|
}
|
|
|
|
|
|
/* O N D R A G E N D */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: OnDragEnd
|
|
|
|
-------------------------------------------------------------------------*/
|
|
void CSplitBar2::OnDragEnd(POINT pt)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::OnDragEnd);
|
|
|
|
CancelDragLoop();
|
|
|
|
RECT ClientRect;
|
|
GetClientRect( &ClientRect );
|
|
|
|
::ScreenToClient(m_hwndParent, &pt);
|
|
int x = _ConstrainDragPoint((short)pt.x);
|
|
if (0 != x)
|
|
{
|
|
// Call the adjustment function
|
|
if(m_pfnAdjust)
|
|
{
|
|
m_pfnAdjust(x - (ClientRect.left + m_dxDragOffset), m_Context);
|
|
}
|
|
|
|
// ForceWindowResize();
|
|
}
|
|
|
|
DBGEXIT(CSplitBar2::OnDragEnd);
|
|
}
|
|
|
|
|
|
/* C A N C E L D R A G L O O P */
|
|
/*-------------------------------------------------------------------------
|
|
%%Function: CancelDragLoop
|
|
|
|
-------------------------------------------------------------------------*/
|
|
void CSplitBar2::CancelDragLoop(void)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::CancelDragLoop);
|
|
|
|
if (m_fCaptured)
|
|
{
|
|
TRACE_OUT(("Canceling drag loop..."));
|
|
|
|
// Release the capture
|
|
ReleaseCapture();
|
|
m_fCaptured = FALSE;
|
|
|
|
// Erase the bar
|
|
_DrawBar();
|
|
|
|
// unlock window updates
|
|
LockWindowUpdate(NULL);
|
|
if (m_hdcDrag != NULL)
|
|
{
|
|
::ReleaseDC(GetDesktopWindow(), m_hdcDrag);
|
|
m_hdcDrag = NULL;
|
|
}
|
|
}
|
|
|
|
DBGEXIT(CSplitBar2::CancelDragLoop);
|
|
}
|
|
|
|
|
|
void CSplitBar2::_TrackDrag(POINT pt)
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::_TrackDrag);
|
|
|
|
// set capture to the window which received this message
|
|
if (FInitDragLoop(pt))
|
|
{
|
|
// get messages until capture lost or cancelled/accepted
|
|
while (GetCapture() == m_hWnd)
|
|
{
|
|
MSG msg;
|
|
if (!::GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
PostQuitMessage(msg.wParam);
|
|
break;
|
|
}
|
|
|
|
if (WM_MOUSEMOVE == msg.message)
|
|
{
|
|
OnDragMove(msg.pt);
|
|
continue;
|
|
}
|
|
|
|
if (WM_LBUTTONUP == msg.message)
|
|
{
|
|
OnDragEnd(msg.pt);
|
|
break;
|
|
}
|
|
|
|
if ((WM_KEYDOWN == msg.message) ||
|
|
(WM_RBUTTONDOWN == msg.message))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// dispatch all other messages
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
CancelDragLoop();
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("Unable to Initialize drag loop?"));
|
|
}
|
|
|
|
DBGEXIT(CSplitBar2::_TrackDrag);
|
|
}
|
|
|
|
|
|
|
|
/* static */ CWndClassInfo& CSplitBar2::GetWndClassInfo()
|
|
{
|
|
|
|
DBGENTRY(CSplitBar2::GetWndClassInfo);
|
|
|
|
static CWndClassInfo wc =
|
|
{
|
|
{
|
|
sizeof(WNDCLASSEX), // cbSize
|
|
NULL, // style
|
|
StartWindowProc, // WndProc
|
|
0, // cbClsExtra
|
|
0, // cbWndExtra
|
|
0, // hInstance
|
|
0, // hIcon
|
|
NULL, // hCursor
|
|
reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1), // hBackground
|
|
0, // lpszMenuName
|
|
_T("ConfSplitBarClass2"), // lpszClassName
|
|
0 // hIconSm
|
|
},
|
|
NULL,
|
|
NULL,
|
|
MAKEINTRESOURCE(IDC_SPLITV), // hCursor,
|
|
FALSE,
|
|
0,
|
|
_T("")
|
|
};
|
|
|
|
DBGEXIT(CSplitBar2::GetWndClassInfo);
|
|
|
|
return wc;
|
|
}
|