// ATLSheetTabWindow.cpp: implementation of the CSheetTabWindow class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "../include/ATLSheetTabWindow.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BEGIN_MSG_MAP_CPP(CSheetTabWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
//MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUP)
//MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
if(WM_HSCROLL==uMsg){
FORWARD_NOTIFICATIONS()
}
ALT_MSG_MAP(1) // Scroll
END_MSG_MAP()
CSheetTabWindow::CSheetTabWindow() :m_hCursor(NULL)//, m_cxyDragOffset(0)
,nSplitScale_(MakeDefSplitPos()),bShowTab_(TRUE)
//m_bMinimumScrollBarMode(false), m_nMaxFlatTabControlWidth(300)
//m_nScrollMinRange(0), m_nScrollMaxRange(0), m_nPageSize(0)
{
if(m_hCursor == NULL)
{
::EnterCriticalSection(&_Module.m_csStaticDataInit);
if(m_hCursor == NULL)
m_hCursor = ::LoadCursor(NULL, IDC_SIZEWE);
::LeaveCriticalSection(&_Module.m_csStaticDataInit);
}
}
bool CSheetTabWindow::_Init()
{
// Setup Static control
SetFont((HFONT)::SendMessage(GetParent(), WM_GETFONT, 0, 0));
ModifyStyle(WS_BORDER, ES_LEFT);
// Create Scroll bar
RECT rc = { 0, 0, 0, 0 };
m_wndScroll.Create(this, 1, m_hWnd, &rc, NULL, WS_CHILD | WS_VISIBLE);
ATLASSERT(m_wndScroll.IsWindow());
m_wndScroll.SetFont((HFONT)::SendMessage(GetParent(), WM_GETFONT, 0, 0));
m_wndScroll.SetWindowPos(HWND_TOP, &rc, SWP_NOMOVE | SWP_NOSIZE);
// Create Flat Tab Control
if (!m_wndFlatTab.Create(*this, rc, NULL, WS_VISIBLE | WS_CHILD | FTS_HASARROWS | FTS_BOTTOM | TCS_TOOLTIPS,
0, IDC_FLATTAB))
{
DWORD dErrorCode = GetLastError();
// Find out why check the Win32 Error codes in MSDN
return false;
}
ATLASSERT(m_wndFlatTab.IsWindow());
m_wndFlatTab.SetFont((HFONT)::SendMessage(GetParent(), WM_GETFONT, 0, 0));
m_wndFlatTab.SetWindowPos(HWND_TOP, &rc, SWP_NOMOVE | SWP_NOSIZE);
return true;
}
void CSheetTabWindow::UpdateControlLayout(WORD cx, WORD cy, bool bMouseMove)
{
if(!cx||!cy)
return;
// first time set the sheet control to atleast three qurters
// if (m_fCurTabWidthPercent == 0)
// {
//MakeDefSplitPos(cx);
// // m_fCurTabWidthPercent = (cx / 5) * 3;
// }
// else
/*
{
// Need to make sure that atleast a minimum scrollbar exist
if (cx-nSplitPos-SPLITTER_BAR_WIDTH < MINIMUM_SCROLLBAR)
{
nSplitPos = cx-MINIMUM_SCROLLBAR;
m_fCurTabWidthPercent=SplitPosToPercent(cx,nSplitPos);
//m_bMinimumScrollBarMode = true;
}
else
{
if (m_bMinimumScrollBarMode && !bMouseMove)
{
if (nSplitPos+SPLITTER_BAR_WIDTH+MINIMUM_SCROLLBAR < cx){
nSplitPos = cx-MINIMUM_SCROLLBAR;
m_fCurTabWidthPercent=SplitPosToPercent(cx,nSplitPos);
}
// Lets check the status again
if (cx > m_nMaxFlatTabControlWidth && cx > m_wndFlatTab.GetVisibleTabWidth()+100)
m_bMinimumScrollBarMode = false;
}
}
}
*/
// Now lets move the windows
if (m_wndFlatTab.m_hWnd)
{
int nSplitPos=MulDiv(LOWORD(nSplitScale_),cx,HIWORD(nSplitScale_));
RestrictSplitPos(cx,nSplitPos);
MAKELONG(nSplitPos,cx);
const int height=::GetSystemMetrics(SM_CXHSCROLL);
const int xScroll=bShowTab_?nSplitPos+SPLITTER_BAR_WIDTH:0;
const int cxScroll=cx-xScroll;
if(!bShowTab_)
nSplitPos=0;
HDWP hDWP=::BeginDeferWindowPos(2);
::DeferWindowPos(hDWP,m_wndFlatTab,NULL,0,0,nSplitPos,height,SWP_NOZORDER|SWP_NOMOVE);//.MoveWindow(0, 0, nSplitPos, ::GetSystemMetrics(SM_CXHSCROLL));
::DeferWindowPos(hDWP,m_wndScroll,NULL,xScroll, 0,cxScroll, height,SWP_NOZORDER);//.MoveWindow(nSplitPos+SPLITTER_BAR_WIDTH, 0,cx-nSplitPos-SPLITTER_BAR_WIDTH, ::GetSystemMetrics(SM_CXHSCROLL));
::EndDeferWindowPos(hDWP);
}
}
bool CSheetTabWindow::RestrictSplitPos(int cxClient,int& nSplitPos)const
{
if(nSplitPos<=1){
nSplitPos=1;
return true;
}else if(nSplitPos>cxClient-MINIMUM_SCROLLBAR){
nSplitPos=cxClient-MINIMUM_SCROLLBAR;
return true;
}
return false;
}
LRESULT CSheetTabWindow::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
WORD cx = LOWORD(lParam);
WORD cy = HIWORD(lParam);
if (cx == 0)
return 0;
if (wParam != SIZE_MINIMIZED)
{
// Need to size the Sheet Control and Scroll bar
RECT rcSplit;
GetSplitterBarRect(&rcSplit);
UpdateControlLayout(cx, cy);
RECT rcSplitNew;
GetSplitterBarRect(&rcSplitNew);
rcSplit.left=min(rcSplit.left-1,rcSplitNew.left-1);
rcSplit.right=max(rcSplit.right+1,rcSplitNew.right+1);
m_wndFlatTab.InvalidateRect(&rcSplit);
InvalidateRect(&rcSplit);
m_wndFlatTab.UpdateWindow();
//#ifdef _DEBUG
// RECT rcN;
// GetSplitterBarRect(&rcN);
// CString str;
// str.Format(_T("oldSplit(X1=%d,x2=%d),newSplit(x1=%d,x2=%d)"),rcSplit.left,rcSplit.right,rcN.left,rcN.right);
// GetTopWindow().SetWindowText(str);
//#endif
UpdateWindow();
}
return 0;
}
LRESULT CSheetTabWindow::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT(::IsWindow(m_hWnd));
NMHDR* pNMHDR = (NMHDR*)lParam;
LRESULT lResult = 0;
// handle messages from the flat tab control itself
if (IDC_FLATTAB ==(UINT)wParam)
{
pNMHDR->hwndFrom=m_hWnd;
// Allow the parent to process the same event
::SendMessage(GetParent(), uMsg, wParam, lParam);
}
return lResult;
}
LRESULT CSheetTabWindow::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
if(IsOverSplitterBar(xPos, yPos))
::SetCursor(m_hCursor);
bHandled = FALSE;
return 0;
}
LRESULT CSheetTabWindow::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))
{
TrackDragSplit(xPos);
//SetCapture();
//::SetCursor(m_hCursor);
//CRect rc;GetClientRect(&rc);
//m_cxyDragOffset = xPos - GetSplitPos(rc.Width());//m_fCurTabWidthPercent;
}
bHandled = FALSE;
return 0;
}
void CSheetTabWindow::TrackDragSplit(int xCursorPos)
{
SetCapture();
CRect rc;
GetClientRect(&rc);
const int cxClient=rc.Width();
const int cyClient=rc.Height();
int nSplitPos=GetSplitPos();
const int xDragOffset=xCursorPos-nSplitPos;
MSG msg;
while((::GetCapture()==m_hWnd)&&(GetMessage(&msg, NULL, 0, 0))){
switch(msg.message)
{
case WM_MOUSEMOVE:
{
const int nOldSplitPos=nSplitPos;
int x = GET_X_LPARAM(msg.lParam);
nSplitPos=x-xDragOffset;
RestrictSplitPos(cxClient,nSplitPos);
nSplitScale_=MAKELONG(nSplitPos,cxClient);
UpdateControlLayout(cxClient,cyClient, true);
RECT rcInvalidate;
rcInvalidate.left=min(nOldSplitPos,nSplitPos)-10;
rcInvalidate.top=0;
rcInvalidate.bottom=cyClient;
rcInvalidate.right=max(nOldSplitPos,nSplitPos)+(SPLITTER_BAR_WIDTH*2);
InvalidateRect(&rcInvalidate);
m_wndFlatTab.InvalidateRect(&rcInvalidate);
m_wndFlatTab.UpdateWindow();
UpdateWindow();
}break;
case WM_LBUTTONUP:
{
ReleaseCapture();
}break;
}
}
ReleaseCapture();
}
//CSheetTabWindow::CSheetTabWindow()
//{
//
//}
//
//CSheetTabWindow::~CSheetTabWindow()
//{
//
//}