#ifndef _TINYSPLITTER_H_ #define _TINYSPLITTER_H_ #ifndef _TINY_WINDOW_H_ #error "_TinySplitter require <_TinyWindow.h>" #endif #define SPLITTER_WIDTH 3 #define DRAW_RAISED_SPLITTER class _TinySplitter : public _TinyWindow { public: virtual BOOL Create(_TinyWindow *pParentWnd=NULL, _TinyWindow *pPan0=NULL,_TinyWindow *pPan1=NULL,bool bVertical=false, const RECT* pRect=NULL){ BOOL bRes=_TinyWindow::Create(_T("_default_TinyWindowClass"),_T(""),WS_VISIBLE|WS_CHILD|WS_CLIPCHILDREN,NULL,pRect,pParentWnd); if(!bRes)return FALSE; m_bVertical = bVertical; m_bDragging = false; SetFirstPan(pPan0); SetSecondPan(pPan1); CenterSplitter(); NotifyReflection(TRUE); return TRUE; } void SetFirstPan(_TinyWindow *pWnd) { m_pPan0 = pWnd; if (m_pPan0 != NULL) { m_pPan0->SetParent(this); m_pPan0->MakeChild(); m_pPan0->NotifyReflection(TRUE); } }; void SetSecondPan(_TinyWindow *pWnd) { m_pPan1 = pWnd; if (m_pPan1) { m_pPan1->SetParent(this); m_pPan1->MakeChild(); m_pPan1->NotifyReflection(TRUE); } }; bool Reshape(int w,int h) { if (m_pPan0 == NULL || m_pPan1 == NULL) return false; const int iHlfSplitterWdh = SPLITTER_WIDTH / 2; SetWindowPos(0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE); if (m_bVertical) { int iEndUpper = ReverseYAxis(m_iSplitterPos) - iHlfSplitterWdh; m_pPan0->Reshape(w, iEndUpper); m_pPan0->SetWindowPos(0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); m_pPan1->Reshape(w, h - (iEndUpper + iHlfSplitterWdh) - 2); m_pPan1->SetWindowPos(0, iEndUpper + iHlfSplitterWdh * 2, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } else { int iEndLeft = m_iSplitterPos - iHlfSplitterWdh; m_pPan0->Reshape(iEndLeft , h); m_pPan0->SetWindowPos(0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); m_pPan1->Reshape(w - (iEndLeft + iHlfSplitterWdh) - 2, h); m_pPan1->SetWindowPos(iEndLeft + iHlfSplitterWdh * 2, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } return true; } bool Reshape() { _TinyRect rc; GetClientRect(&rc); return Reshape(rc.right, rc.bottom); } void CenterSplitter() { if (IsCreated()) { HWND hWndParent = GetParent(m_hWnd); if (IsWindow(hWndParent)) { _TinyRect rc; ::GetClientRect(hWndParent, &rc); m_iSplitterPos = m_bVertical ? rc.bottom / 2 : rc.right / 2; } } } UINT GetSplitterPos() const { return m_iSplitterPos; }; void SetSplitterPos(UINT iPos) { m_iSplitterPos = iPos; }; protected: _BEGIN_MSG_MAP(CSourceEdit) _MESSAGE_HANDLER(WM_PAINT, OnPaint) _MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) _MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave) _MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) _MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) _END_MSG_MAP() void ObtainSplitterRect(_TinyRect &rcOut) { const int iHlfSplitterWdh = SPLITTER_WIDTH / 2; GetClientRect(&rcOut); if (m_bVertical) { rcOut.top = ReverseYAxis(m_iSplitterPos) - iHlfSplitterWdh - 2; rcOut.bottom = ReverseYAxis(m_iSplitterPos) + iHlfSplitterWdh + 2; } else { rcOut.left = m_iSplitterPos - iHlfSplitterWdh; rcOut.right = m_iSplitterPos + iHlfSplitterWdh; } } void EnableMouseTracking() { // Enable hover / leave messages TRACKMOUSEEVENT evt; evt.cbSize = sizeof(TRACKMOUSEEVENT); evt.dwFlags = TME_HOVER | TME_LEAVE; evt.hwndTrack = m_hWnd; evt.dwHoverTime = 1; _TrackMouseEvent(&evt); } LRESULT OnMouseMove(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam) { // To receive the leave message EnableMouseTracking(); HCURSOR hCur = LoadCursor(NULL, m_bVertical ? IDC_SIZENS : IDC_SIZEWE); _TinyAssert(hCur != NULL); SetCursor(hCur); if (m_bDragging) { int xPos = _TINY_SIGNED_LOWORD(lParam); int yPos = _TINY_SIGNED_HIWORD(lParam); m_iSplitterPos = m_bVertical ? ReverseYAxis(yPos) : xPos; MoveSplitterToValidPos(); Reshape(); } return 0; } LRESULT OnMouseLeave(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam) { HCURSOR hCur = LoadCursor(NULL, IDC_ARROW); SetCursor(hCur); return 0; } LRESULT OnLButtonDown(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam) { m_bDragging = true; SetCapture(); return 0; } LRESULT OnLButtonUp(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam) { m_bDragging = false; _TinyVerify(ReleaseCapture()); int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); m_iSplitterPos = m_bVertical ? ReverseYAxis(yPos) : xPos; MoveSplitterToValidPos(); Reshape(); return 0; } LRESULT OnPaint(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam) { _TinyRect rc; PAINTSTRUCT ps; HDC hDC; ::BeginPaint(m_hWnd, &ps); hDC = ::GetDC(m_hWnd); GetClientRect(&rc); ::FillRect(hDC, &rc, GetSysColorBrush(COLOR_BTNFACE)); ObtainSplitterRect(rc); #ifdef DRAW_RAISED_SPLITTER DrawFrameControl(hDC, &rc, DFC_BUTTON, DFCS_BUTTONPUSH); #else DrawFrameControl(hDC, &rc, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED); #endif EndPaint(m_hWnd,&ps); return 0; } void MoveSplitterToValidPos() { return; // TODO _TinyRect rc; GetClientRect(&rc); m_iSplitterPos = __min(__max(m_iSplitterPos, SPLITTER_WIDTH), rc.bottom - SPLITTER_WIDTH); } UINT ReverseYAxis(UINT iY) { _TinyRect rc; _TinyVerify(GetClientRect(&rc)); return rc.bottom - iY; } long m_iSplitterPos; _TinyWindow *m_pPan0; _TinyWindow *m_pPan1; bool m_bVertical; bool m_bDragging; }; #endif