From af7e438cfe8ce85e1da234318ed1584e89d952cc Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Fri, 29 Jun 2012 05:38:03 +0000 Subject: only add some plugins and protocols, not adapted See please maybe not all need us git-svn-id: http://svn.miranda-ng.org/main/trunk@678 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SmartAutoReplier/wtl/atlsplit.h | 917 ++++++++++++++++++++++++++++++++ 1 file changed, 917 insertions(+) create mode 100644 plugins/SmartAutoReplier/wtl/atlsplit.h (limited to 'plugins/SmartAutoReplier/wtl/atlsplit.h') diff --git a/plugins/SmartAutoReplier/wtl/atlsplit.h b/plugins/SmartAutoReplier/wtl/atlsplit.h new file mode 100644 index 0000000000..f94fa099e9 --- /dev/null +++ b/plugins/SmartAutoReplier/wtl/atlsplit.h @@ -0,0 +1,917 @@ +// Windows Template Library - WTL version 8.1 +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// This file is a part of the Windows Template Library. +// The use and distribution terms for this software are covered by the +// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php) +// which can be found in the file CPL.TXT at the root of this distribution. +// By using this software in any fashion, you are agreeing to be bound by +// the terms of this license. You must not remove this notice, or +// any other, from this software. + +#ifndef __ATLSPLIT_H__ +#define __ATLSPLIT_H__ + +#pragma once + +#ifndef __ATLAPP_H__ + #error atlsplit.h requires atlapp.h to be included first +#endif + +#ifndef __ATLWIN_H__ + #error atlsplit.h requires atlwin.h to be included first +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Classes in this file: +// +// CSplitterImpl +// CSplitterWindowImpl +// CSplitterWindowT + + +namespace WTL +{ + +/////////////////////////////////////////////////////////////////////////////// +// CSplitterImpl - Provides splitter support to any window + +// Splitter panes constants +#define SPLIT_PANE_LEFT 0 +#define SPLIT_PANE_RIGHT 1 +#define SPLIT_PANE_TOP SPLIT_PANE_LEFT +#define SPLIT_PANE_BOTTOM SPLIT_PANE_RIGHT +#define SPLIT_PANE_NONE -1 + +// Splitter extended styles +#define SPLIT_PROPORTIONAL 0x00000001 +#define SPLIT_NONINTERACTIVE 0x00000002 +#define SPLIT_RIGHTALIGNED 0x00000004 +#define SPLIT_BOTTOMALIGNED SPLIT_RIGHTALIGNED +#define SPLIT_GRADIENTBAR 0x00000008 +#define SPLIT_FIXEDBARSIZE 0x00000010 + +// Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are +// mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL + + +template +class CSplitterImpl +{ +public: + enum { m_nPanesCount = 2, m_nPropMax = 10000 }; + + HWND m_hWndPane[m_nPanesCount]; + RECT m_rcSplitter; + int m_xySplitterPos; + int m_nDefActivePane; + int m_cxySplitBar; // splitter bar width/height + static HCURSOR m_hCursor; + int m_cxyMin; // minimum pane size + int m_cxyBarEdge; // splitter bar edge + bool m_bFullDrag; + int m_cxyDragOffset; + int m_nProportionalPos; + bool m_bUpdateProportionalPos; + DWORD m_dwExtendedStyle; // splitter specific extended styles + int m_nSinglePane; // single pane mode + +// Constructor + CSplitterImpl() : + m_xySplitterPos(-1), m_nDefActivePane(SPLIT_PANE_NONE), + m_cxySplitBar(4), m_cxyMin(0), m_cxyBarEdge(0), m_bFullDrag(true), + m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true), + m_dwExtendedStyle(SPLIT_PROPORTIONAL), + m_nSinglePane(SPLIT_PANE_NONE) + { + m_hWndPane[SPLIT_PANE_LEFT] = NULL; + m_hWndPane[SPLIT_PANE_RIGHT] = NULL; + + ::SetRectEmpty(&m_rcSplitter); + + if(m_hCursor == NULL) + { + CStaticDataInitCriticalSectionLock lock; + if(FAILED(lock.Lock())) + { + ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CSplitterImpl::CSplitterImpl.\n")); + ATLASSERT(FALSE); + return; + } + + if(m_hCursor == NULL) + m_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE : IDC_SIZENS); + + lock.Unlock(); + } + } + +// Attributes + void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true) + { + if(lpRect == NULL) + { + T* pT = static_cast(this); + pT->GetClientRect(&m_rcSplitter); + } + else + { + m_rcSplitter = *lpRect; + } + + if(IsProportional()) + UpdateProportionalPos(); + else if(IsRightAligned()) + UpdateRightAlignPos(); + + if(bUpdate) + UpdateSplitterLayout(); + } + + void GetSplitterRect(LPRECT lpRect) const + { + ATLASSERT(lpRect != NULL); + *lpRect = m_rcSplitter; + } + + bool SetSplitterPos(int xyPos = -1, bool bUpdate = true) + { + if(xyPos == -1) // -1 == middle + { + if(t_bVertical) + xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2; + else + xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2; + } + + // Adjust if out of valid range + int cxyMax = 0; + if(t_bVertical) + cxyMax = m_rcSplitter.right - m_rcSplitter.left; + else + cxyMax = m_rcSplitter.bottom - m_rcSplitter.top; + + if(xyPos < m_cxyMin + m_cxyBarEdge) + xyPos = m_cxyMin; + else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin)) + xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin; + + // Set new position and update if requested + bool bRet = (m_xySplitterPos != xyPos); + m_xySplitterPos = xyPos; + + if(m_bUpdateProportionalPos) + { + if(IsProportional()) + StoreProportionalPos(); + else if(IsRightAligned()) + StoreRightAlignPos(); + } + else + { + m_bUpdateProportionalPos = true; + } + + if(bUpdate && bRet) + UpdateSplitterLayout(); + + return bRet; + } + + void SetSplitterPosPct(int nPct, bool bUpdate = true) + { + ATLASSERT(nPct >= 0 && nPct <= 100); + + m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100); + UpdateProportionalPos(); + + if(bUpdate) + UpdateSplitterLayout(); + } + + int GetSplitterPos() const + { + return m_xySplitterPos; + } + + bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE); + if(!(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT || nPane == SPLIT_PANE_NONE)) + return false; + + if(nPane != SPLIT_PANE_NONE) + { + if(!::IsWindowVisible(m_hWndPane[nPane])) + ::ShowWindow(m_hWndPane[nPane], SW_SHOW); + int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT; + ::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE); + if(m_nDefActivePane != nPane) + m_nDefActivePane = nPane; + } + else if(m_nSinglePane != SPLIT_PANE_NONE) + { + int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT; + ::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW); + } + + m_nSinglePane = nPane; + UpdateSplitterLayout(); + return true; + } + + int GetSinglePaneMode() const + { + return m_nSinglePane; + } + + DWORD GetSplitterExtendedStyle() const + { + return m_dwExtendedStyle; + } + + DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0) + { + DWORD dwPrevStyle = m_dwExtendedStyle; + if(dwMask == 0) + m_dwExtendedStyle = dwExtendedStyle; + else + m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask); +#ifdef _DEBUG + if(IsProportional() && IsRightAligned()) + ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n")); +#endif // _DEBUG + return dwPrevStyle; + } + +// Splitter operations + void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true) + { + m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop; + m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom; + ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]); + if(bUpdate) + UpdateSplitterLayout(); + } + + bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + m_hWndPane[nPane] = hWnd; + ATLASSERT(m_hWndPane[SPLIT_PANE_LEFT] == NULL || m_hWndPane[SPLIT_PANE_RIGHT] == NULL || m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]); + if(bUpdate) + UpdateSplitterLayout(); + return true; + } + + HWND GetSplitterPane(int nPane) const + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + return m_hWndPane[nPane]; + } + + bool SetActivePane(int nPane) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + if(m_nSinglePane != SPLIT_PANE_NONE && nPane != m_nSinglePane) + return false; + ::SetFocus(m_hWndPane[nPane]); + m_nDefActivePane = nPane; + return true; + } + + int GetActivePane() const + { + int nRet = SPLIT_PANE_NONE; + HWND hWndFocus = ::GetFocus(); + if(hWndFocus != NULL) + { + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(hWndFocus == m_hWndPane[nPane] || ::IsChild(m_hWndPane[nPane], hWndFocus)) + { + nRet = nPane; + break; + } + } + } + return nRet; + } + + bool ActivateNextPane(bool bNext = true) + { + int nPane = m_nSinglePane; + if(nPane == SPLIT_PANE_NONE) + { + switch(GetActivePane()) + { + case SPLIT_PANE_LEFT: + nPane = SPLIT_PANE_RIGHT; + break; + case SPLIT_PANE_RIGHT: + nPane = SPLIT_PANE_LEFT; + break; + default: + nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT; + break; + } + } + return SetActivePane(nPane); + } + + bool SetDefaultActivePane(int nPane) + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + + if(nPane != SPLIT_PANE_LEFT && nPane != SPLIT_PANE_RIGHT) + return false; + m_nDefActivePane = nPane; + return true; + } + + bool SetDefaultActivePane(HWND hWnd) + { + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(hWnd == m_hWndPane[nPane]) + { + m_nDefActivePane = nPane; + return true; + } + } + return false; // not found + } + + int GetDefaultActivePane() const + { + return m_nDefActivePane; + } + + void DrawSplitter(CDCHandle dc) + { + ATLASSERT(dc.m_hDC != NULL); + if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) + return; + + T* pT = static_cast(this); + if(m_nSinglePane == SPLIT_PANE_NONE) + { + pT->DrawSplitterBar(dc); + + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(m_hWndPane[nPane] == NULL) + pT->DrawSplitterPane(dc, nPane); + } + } + else + { + if(m_hWndPane[m_nSinglePane] == NULL) + pT->DrawSplitterPane(dc, m_nSinglePane); + } + } + +// Overrideables + void DrawSplitterBar(CDCHandle dc) + { + RECT rect = { 0 }; + if(GetSplitterBarRect(&rect)) + { + dc.FillRect(&rect, COLOR_3DFACE); + +#if (!defined(_WIN32_WCE) || (_WIN32_WCE >= 420)) + if((m_dwExtendedStyle & SPLIT_GRADIENTBAR) != 0) + { + RECT rect2 = rect; + if(t_bVertical) + rect2.left = (rect.left + rect.right) / 2 - 1; + else + rect2.top = (rect.top + rect.bottom) / 2 - 1; + + dc.GradientFillRect(rect2, ::GetSysColor(COLOR_3DFACE), ::GetSysColor(COLOR_3DSHADOW), t_bVertical); + } +#endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 420) + + // draw 3D edge if needed + T* pT = static_cast(this); + if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0) + dc.DrawEdge(&rect, EDGE_RAISED, t_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM)); + } + } + + // called only if pane is empty + void DrawSplitterPane(CDCHandle dc, int nPane) + { + RECT rect = { 0 }; + if(GetSplitterPaneRect(nPane, &rect)) + { + T* pT = static_cast(this); + if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0) + dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); + dc.FillRect(&rect, COLOR_APPWORKSPACE); + } + } + +// Message map and handlers + BEGIN_MSG_MAP(CSplitterImpl) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_PAINT, OnPaint) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) +#endif // !_WIN32_WCE + if(IsInteractive()) + { + MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick) + MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) + } + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) +#ifndef _WIN32_WCE + MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) +#endif // !_WIN32_WCE + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) + END_MSG_MAP() + + LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + T* pT = static_cast(this); + pT->GetSystemSettings(false); + + bHandled = FALSE; + return 1; + } + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + // try setting position if not set + if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) + pT->SetSplitterPos(); + // do painting + CPaintDC dc(pT->m_hWnd); + pT->DrawSplitter(dc.m_hDC); + return 0; + } + + LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + if((HWND)wParam == pT->m_hWnd && LOWORD(lParam) == HTCLIENT) + { + DWORD dwPos = ::GetMessagePos(); + POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; + pT->ScreenToClient(&ptPos); + if(IsOverSplitterBar(ptPos.x, ptPos.y)) + return 1; + } + + bHandled = FALSE; + return 0; + } + + LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + T* pT = static_cast(this); + int xPos = GET_X_LPARAM(lParam); + int yPos = GET_Y_LPARAM(lParam); + if((wParam & MK_LBUTTON) && ::GetCapture() == pT->m_hWnd) + { + int xyNewSplitPos = 0; + if(t_bVertical) + xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset; + else + xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset; + + if(xyNewSplitPos == -1) // avoid -1, that means middle + xyNewSplitPos = -2; + + if(m_xySplitterPos != xyNewSplitPos) + { + if(m_bFullDrag) + { + if(pT->SetSplitterPos(xyNewSplitPos, true)) + pT->UpdateWindow(); + } + else + { + DrawGhostBar(); + pT->SetSplitterPos(xyNewSplitPos, false); + DrawGhostBar(); + } + } + } + else // not dragging, just set cursor + { + if(IsOverSplitterBar(xPos, yPos)) + ::SetCursor(m_hCursor); + bHandled = FALSE; + } + + return 0; + } + + LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) + { + int xPos = GET_X_LPARAM(lParam); + int yPos = GET_Y_LPARAM(lParam); + if(IsOverSplitterBar(xPos, yPos)) + { + T* pT = static_cast(this); + pT->SetCapture(); + ::SetCursor(m_hCursor); + if(!m_bFullDrag) + DrawGhostBar(); + if(t_bVertical) + m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos; + else + m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos; + } + bHandled = FALSE; + return 1; + } + + LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) + { + ::ReleaseCapture(); + bHandled = FALSE; + return 1; + } + + LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->SetSplitterPos(); // middle + return 0; + } + + LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + if(!m_bFullDrag) + { + DrawGhostBar(); + UpdateSplitterLayout(); + T* pT = static_cast(this); + pT->UpdateWindow(); + } + return 0; + } + + LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled) + { + if(m_nSinglePane == SPLIT_PANE_NONE) + { + if(m_nDefActivePane == SPLIT_PANE_LEFT || m_nDefActivePane == SPLIT_PANE_RIGHT) + ::SetFocus(m_hWndPane[m_nDefActivePane]); + } + else + { + ::SetFocus(m_hWndPane[m_nSinglePane]); + } + bHandled = FALSE; + return 1; + } + +#ifndef _WIN32_WCE + LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam); + if(lRet == MA_ACTIVATE || lRet == MA_ACTIVATEANDEAT) + { + DWORD dwPos = ::GetMessagePos(); + POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) }; + pT->ScreenToClient(&pt); + RECT rcPane = { 0 }; + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(GetSplitterPaneRect(nPane, &rcPane) && ::PtInRect(&rcPane, pt)) + { + m_nDefActivePane = nPane; + break; + } + } + } + return lRet; + } +#endif // !_WIN32_WCE + + LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + T* pT = static_cast(this); + pT->GetSystemSettings(true); + + return 0; + } + +// Implementation - internal helpers + void UpdateSplitterLayout() + { + if(m_nSinglePane == SPLIT_PANE_NONE && m_xySplitterPos == -1) + return; + + T* pT = static_cast(this); + RECT rect = { 0 }; + if(m_nSinglePane == SPLIT_PANE_NONE) + { + if(GetSplitterBarRect(&rect)) + pT->InvalidateRect(&rect); + + for(int nPane = 0; nPane < m_nPanesCount; nPane++) + { + if(GetSplitterPaneRect(nPane, &rect)) + { + if(m_hWndPane[nPane] != NULL) + ::SetWindowPos(m_hWndPane[nPane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + else + pT->InvalidateRect(&rect); + } + } + } + else + { + if(GetSplitterPaneRect(m_nSinglePane, &rect)) + { + if(m_hWndPane[m_nSinglePane] != NULL) + ::SetWindowPos(m_hWndPane[m_nSinglePane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + else + pT->InvalidateRect(&rect); + } + } + } + + bool GetSplitterBarRect(LPRECT lpRect) const + { + ATLASSERT(lpRect != NULL); + if(m_nSinglePane != SPLIT_PANE_NONE || m_xySplitterPos == -1) + return false; + + if(t_bVertical) + { + lpRect->left = m_rcSplitter.left + m_xySplitterPos; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + lpRect->bottom = m_rcSplitter.bottom; + } + else + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top + m_xySplitterPos; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + } + + return true; + } + + bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const + { + ATLASSERT(nPane == SPLIT_PANE_LEFT || nPane == SPLIT_PANE_RIGHT); + ATLASSERT(lpRect != NULL); + bool bRet = true; + if(m_nSinglePane != SPLIT_PANE_NONE) + { + if(nPane == m_nSinglePane) + *lpRect = m_rcSplitter; + else + bRet = false; + } + else if(nPane == SPLIT_PANE_LEFT) + { + if(t_bVertical) + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.left + m_xySplitterPos; + lpRect->bottom = m_rcSplitter.bottom; + } + else + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.top + m_xySplitterPos; + } + } + else if(nPane == SPLIT_PANE_RIGHT) + { + if(t_bVertical) + { + lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + lpRect->top = m_rcSplitter.top; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.bottom; + } + else + { + lpRect->left = m_rcSplitter.left; + lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge; + lpRect->right = m_rcSplitter.right; + lpRect->bottom = m_rcSplitter.bottom; + } + } + else + { + bRet = false; + } + return bRet; + } + + bool IsOverSplitterRect(int x, int y) const + { + // -1 == don't check + return ((x == -1 || (x >= m_rcSplitter.left && x <= m_rcSplitter.right)) && + (y == -1 || (y >= m_rcSplitter.top && y <= m_rcSplitter.bottom))); + } + + bool IsOverSplitterBar(int x, int y) const + { + if(m_nSinglePane != SPLIT_PANE_NONE) + return false; + if(m_xySplitterPos == -1 || !IsOverSplitterRect(x, y)) + return false; + int xy = t_bVertical ? x : y; + int xyOff = t_bVertical ? m_rcSplitter.left : m_rcSplitter.top; + return ((xy >= (xyOff + m_xySplitterPos)) && (xy < xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge)); + } + + void DrawGhostBar() + { + RECT rect = { 0 }; + if(GetSplitterBarRect(&rect)) + { + // convert client to window coordinates + T* pT = static_cast(this); + RECT rcWnd = { 0 }; + pT->GetWindowRect(&rcWnd); + ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcWnd, 2); + ::OffsetRect(&rect, -rcWnd.left, -rcWnd.top); + + // invert the brush pattern (looks just like frame window sizing) + CWindowDC dc(pT->m_hWnd); + CBrush brush = CDCHandle::GetHalftoneBrush(); + if(brush.m_hBrush != NULL) + { + CBrushHandle brushOld = dc.SelectBrush(brush); + dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT); + dc.SelectBrush(brushOld); + } + } + } + + void GetSystemSettings(bool bUpdate) + { + if((m_dwExtendedStyle & SPLIT_FIXEDBARSIZE) == 0) + { +#ifndef _WIN32_WCE + m_cxySplitBar = ::GetSystemMetrics(t_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME); +#else // CE specific + m_cxySplitBar = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); +#endif // _WIN32_WCE + } + + T* pT = static_cast(this); + if((pT->GetExStyle() & WS_EX_CLIENTEDGE)) + { + m_cxyBarEdge = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); + m_cxyMin = 0; + } + else + { + m_cxyBarEdge = 0; + m_cxyMin = 2 * ::GetSystemMetrics(t_bVertical ? SM_CXEDGE : SM_CYEDGE); + } + +#ifndef _WIN32_WCE + ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0); +#endif // !_WIN32_WCE + + if(bUpdate) + UpdateSplitterLayout(); + } + + bool IsProportional() const + { + return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0); + } + + void StoreProportionalPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal); + else + m_nProportionalPos = 0; + ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreProportionalPos - %i\n"), m_nProportionalPos); + } + + void UpdateProportionalPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + { + int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax); + m_bUpdateProportionalPos = false; + T* pT = static_cast(this); + pT->SetSplitterPos(xyNewPos, false); + } + } + + bool IsRightAligned() const + { + return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0); + } + + void StoreRightAlignPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + m_nProportionalPos = cxyTotal - m_xySplitterPos; + else + m_nProportionalPos = 0; + ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreRightAlignPos - %i\n"), m_nProportionalPos); + } + + void UpdateRightAlignPos() + { + int cxyTotal = t_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge); + if(cxyTotal > 0) + { + m_bUpdateProportionalPos = false; + T* pT = static_cast(this); + pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false); + } + } + + bool IsInteractive() const + { + return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0); + } +}; + +template HCURSOR CSplitterImpl< T, t_bVertical>::m_hCursor = NULL; + + +/////////////////////////////////////////////////////////////////////////////// +// CSplitterWindowImpl - Implements a splitter window + +template +class ATL_NO_VTABLE CSplitterWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T , t_bVertical > +{ +public: + DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, COLOR_WINDOW) + + typedef CSplitterImpl< T , t_bVertical > _baseClass; + + BEGIN_MSG_MAP(CSplitterWindowImpl) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) + MESSAGE_HANDLER(WM_SIZE, OnSize) + CHAIN_MSG_MAP(_baseClass) + FORWARD_NOTIFICATIONS() + END_MSG_MAP() + + LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) + { + // handled, no background painting needed + return 1; + } + + LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) + { + if(wParam != SIZE_MINIMIZED) + SetSplitterRect(); + + bHandled = FALSE; + return 1; + } +}; + + +/////////////////////////////////////////////////////////////////////////////// +// CSplitterWindow - Implements a splitter window to be used as is + +template +class CSplitterWindowT : public CSplitterWindowImpl, t_bVertical> +{ +public: + DECLARE_WND_CLASS_EX(_T("WTL_SplitterWindow"), CS_DBLCLKS, COLOR_WINDOW) +}; + +typedef CSplitterWindowT CSplitterWindow; +typedef CSplitterWindowT CHorSplitterWindow; + +}; // namespace WTL + +#endif // __ATLSPLIT_H__ -- cgit v1.2.3