|
|
#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; }
|