📄 ftab.cpp
字号:
pParent -> SendMessage (WM_NOTIFY, nm.idFrom, (LPARAM) & nm);
}
delete m_editBox;
m_editBox = NULL;
DefEditBoxProc = NULL;
UserPressedEnterOnTheEditBox = false;
}
}
//////////////////
// Handle right mouse click: Notify parent, of course
//
void CFolderTabCtrl::OnRButtonDown(UINT nFlags, CPoint pt)
{
int iTab = HitTest(pt);
if (iTab >= 0)
{
SelectItem (iTab);
}
// Create the pop-up menu items.
HMENU hmenu = CreatePopupMenu ();
AppendMenu (hmenu, MF_ENABLED | MF_STRING, ID_EDIT_ADDSHEET, "Add");
AppendMenu (hmenu, MF_ENABLED | MF_STRING, ID_EDIT_DELETESHEET, "Delete");
AppendMenu (hmenu, MF_ENABLED | MF_STRING, ID_EDIT_RENAMESHEET, "Rename");
AppendMenu (hmenu, MF_SEPARATOR, NULL, "");
AppendMenu (hmenu, MF_ENABLED | MF_STRING, ID_EDIT_SHEETS, "Properties...");
// display menu next to the selected tab
ClientToScreen ( & pt);
TrackPopupMenuEx (hmenu, TPM_RIGHTBUTTON, pt.x, pt.y, m_hWnd, NULL);
// cleanup
DestroyMenu (hmenu);
}
//////////////////
// Find which tab is under mouse, -1 if none
//
int CFolderTabCtrl::HitTest(CPoint pt)
{
CRect rc;
GetClientRect(&rc);
rc.left += m_cxButtons;
if (rc.PtInRect(pt))
{
int xOrigin = m_cxButtons - GetTab(m_iFirstTab)->GetRect().left;
pt.x -= xOrigin;
int n = GetItemCount();
for (int i=0; i<n; i++)
{
if (GetTab(i)->HitTest(pt))
return i;
}
}
return -1;
}
//////////////////
// Select ith tab. Returns index selected
//
int CFolderTabCtrl::SelectItem(int iTab)
{
int count = GetItemCount();
if (iTab<0 || iTab>=count)
return -1; // bad
if (iTab == m_iCurItem)
return iTab; // already selected
if (m_iCurItem < count)
InvalidateTab(m_iCurItem); // invalidate old tab (repaint)
m_iCurItem = iTab; // set new selected tab
InvalidateTab(m_iCurItem); // repaint new tab
return m_iCurItem;
}
//////////////////
/// Invalidate a tab: invaldate its rect
//
void CFolderTabCtrl::InvalidateTab(int iTab, BOOL bErase)
{
CRect rc = GetTab(iTab)->GetRect();
CFolderTab * tab = GetTab (m_iFirstTab);
int xOrigin = 0;
if (tab)
xOrigin = m_cxButtons - tab -> GetRect().left;
else
xOrigin = m_cxButtons;
rc += CPoint(xOrigin,0);
InvalidateRect(rc, bErase);
}
BOOL CFolderTabCtrl::Load(UINT nIDRes)
{
CString s;
if (!s.LoadString(nIDRes))
return FALSE;
CString sTab;
for (int i=0; AfxExtractSubString(sTab, s, i); i++) {
AddItem(sTab);
}
return TRUE;
}
int CFolderTabCtrl::AddItem(LPCTSTR lpszText)
{
m_lsTabs.AddTail(new CFolderTab(lpszText));
RecomputeLayout();
return m_lsTabs.GetCount() - 1;
}
BOOL CFolderTabCtrl::RemoveItem(int iPos)
{
POSITION pos = m_lsTabs.FindIndex(iPos);
if (pos)
{
CFolderTab* pTab = (CFolderTab*)m_lsTabs.GetAt(pos);
m_lsTabs.RemoveAt(pos);
delete pTab;
}
RecomputeLayout();
return pos!=NULL;
}
CFolderTab* CFolderTabCtrl::GetTab(int iPos)
{
POSITION pos = m_lsTabs.FindIndex(iPos);
return pos ? static_cast<CFolderTab*>(m_lsTabs.GetAt(pos)) : NULL;
}
void CFolderTabCtrl::RecomputeLayout()
{
CClientDC dc(this);
int x = 0;
int n = GetItemCount();
CFolderTab* pTab = NULL;
for (int i=0; i<n; i++)
{
pTab = GetTab(i);
CFont* pOldFont = NULL;
// use the bigger of the two fonts for all extents since the
// Selected font is bigger than the Normal font - elsewhise
// some of the displayed selected tab characters are cut
// if (i == m_iCurItem)
pOldFont = dc.SelectObject(&m_fontSelected);
// else
// pOldFont = dc.SelectObject(&m_fontNormal);
if (pTab)
x += pTab->ComputeRgn(dc, x) - CXOFFSET;
dc.SelectObject(pOldFont);
}
m_cxDesired = m_cxButtons;
if (pTab)
{
CRect rc = pTab->GetRect();
m_cxDesired += rc.right;
}
}
int CFolderTabCtrl::OnCreate(LPCREATESTRUCT lpcs)
{
if (CWnd::OnCreate(lpcs)!=0)
return -1;
if (m_dwFtabStyle & FTS_BUTTONS)
{
CRect rc;
// for (int i=FTBPREV; i<=FTBNEXT; i++)
for (int i = FTBFIRST; i <= FTBLAST; i++)
{
VERIFY (m_wndButton[i-1].Create (NULL,
WS_VISIBLE | WS_CHILD | BS_OWNERDRAW,rc,this,i));
}
m_cxButtons = FTS_NUMBUTTONS * CXBUTTON;
}
return 0;
}
void CFolderTabCtrl::OnSize(UINT nType, int cx, int cy)
{
if (m_wndButton[0].m_hWnd)
{
int w = cy;
CRect rc(0,0,w,cy);
// for (int i = FTBPREV; i<=FTBNEXT; i++)
for (int i = FTBFIRST; i <= FTBLAST; i++)
{
m_wndButton[i-1].MoveWindow(&rc);
rc += CPoint(w,0);
}
UpdateButtons();
}
}
void CFolderTabCtrl::UpdateButtons()
{
for (int i = FTBFIRST; i <= FTBLAST; i++)
{
m_wndButton [i - 1].EnableWindow (TRUE);
}
}
void CFolderTabCtrl::OnFirstTab()
{
m_iFirstTab = 0;
Invalidate();
UpdateButtons();
}
void CFolderTabCtrl::OnNextTab()
{
if (m_iFirstTab < m_lsTabs.GetCount() - 1)
{
m_iFirstTab++;
Invalidate();
UpdateButtons();
}
}
void CFolderTabCtrl::OnPrevTab()
{
if (m_iFirstTab > 0)
{
m_iFirstTab--;
Invalidate();
UpdateButtons();
}
}
void CFolderTabCtrl::OnLastTab()
{
m_iFirstTab = m_lsTabs.GetCount() - 1;
Invalidate();
UpdateButtons();
}
void CFolderTabCtrl::OnEditProperties()
{
NMFOLDERTAB nm;
nm.hwndFrom = m_hWnd;
nm.idFrom = GetDlgCtrlID();
nm.code = FTN_EDITSHEETS;
nm.iItem = m_iCurItem;
CWnd* pParent = GetParent();
pParent->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
}
void CFolderTabCtrl::OnEditAddSheet()
{
NMFOLDERTAB nm;
nm.hwndFrom = m_hWnd;
nm.idFrom = GetDlgCtrlID();
nm.code = FTN_ADDSHEET;
nm.iItem = m_iCurItem;
CWnd* pParent = GetParent();
// note that the parent will need to call the AddItem method
// in order to complete this user event
pParent->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
}
void CFolderTabCtrl::OnEditDeleteSheet()
{
NMFOLDERTAB nm;
nm.hwndFrom = m_hWnd;
nm.idFrom = GetDlgCtrlID();
nm.code = FTN_DELETESHEET;
nm.iItem = m_iCurItem;
CWnd* pParent = GetParent();
// note that the parent will need to call the RemoveItem method
// in order to complete this user event
pParent->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
}
void CFolderTabCtrl::OnEditRenameSheet()
{
// get the position for the proposed edit box
CRect rc = GetTab (m_iCurItem) -> GetRect ();
// make the edit box smaller than the tab trapezoid
rc.top++;
rc.left += m_cxButtons + CXOFFSET + CXMARGIN;
rc.right += m_cxButtons - CXOFFSET - CXMARGIN;
rc.bottom--;
// now throw up the transparent edit control
if ( ! m_editBox)
{
m_editBox = new CEdit;
m_editBox -> Create ( WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
rc, this, EditBoxId );
CFolderTab * tab = GetTab (m_iCurItem);
m_editBox -> SetWindowText ( tab -> GetText () );
m_editBox -> SetFocus ();
// the limit on the length of the tab names is 40 characters minus 1
m_editBox -> SetLimitText (40 - 1);
int len = strlen (tab -> GetText ());
// move the cursor to the end of the text without selecting anything
m_editBox -> SetSel (len, len);
HWND EditWnd = m_editBox -> GetSafeHwnd ();
DefEditBoxProc = (WNDPROC) GetWindowLong (EditWnd, GWL_WNDPROC);
SetWindowLong (EditWnd, GWL_WNDPROC, (long) MyEditBoxProc);
UserPressedEnterOnTheEditBox = false;
EditBoxHandle = EditWnd;
}
}
////////////////////////////////////////////////////////////////
// CFolderButton
//
IMPLEMENT_DYNAMIC(CFolderButton, CButton)
BEGIN_MESSAGE_MAP(CFolderButton, CButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_TIMER()
END_MESSAGE_MAP()
void CFolderButton::DrawItem(LPDRAWITEMSTRUCT lpDis)
{
DRAWITEMSTRUCT& dis = *lpDis;
CDC& dc = *CDC::FromHandle(dis.hDC);
CRect rc;
GetClientRect(&rc);
dc.FillSolidRect(&rc,GetSysColor(COLOR_3DFACE));
BOOL bDown = dis.itemState & ODS_SELECTED;
if (bDown) {
rc += CPoint(1,1);
}
CPen pen(PS_SOLID,1,
dis.itemState & ODS_DISABLED ? GetSysColor(COLOR_3DSHADOW) : RGB(0,0,0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.MoveTo(rc.TopLeft());
dc.LineTo(rc.right,rc.top);
CRect rc2=rc;
for (int i=0; i<2; i++)
{
dc.Draw3dRect(&rc2,
GetSysColor(bDown ? COLOR_3DFACE : COLOR_3DHIGHLIGHT),
GetSysColor(COLOR_3DSHADOW));
rc2.right--;
rc2.bottom--;
}
// this number needs to be odd so that will get 1 pixel at the end
// Paul had it set to 7 - Excel appears to have 9
int arrowHeight = 9;
// this number appears to be (arrowHeight / 2 + 1)
// Paul had this set to 4 - Excel appears to have 5
int arrowWidth = 5;
int cyMargin = (rc.Height() - arrowHeight) / 2;
int cxMargin = (rc.Width() - arrowWidth) / 2;
// draw the arrows (left or right depending on button)
int x = 0;
int incr = 0;
switch (dis.CtlID)
{
case FTBFIRST:
x = rc.right - cxMargin - 1;
incr = -1;
break;
case FTBPREV:
x = rc.right - cxMargin - 2;
incr = -1;
break;
case FTBNEXT:
x = rc.left + cxMargin;
incr = 1;
break;
case FTBLAST:
x = rc.left + cxMargin - 1;
incr = 1;
break;
}
int y = rc.top + cyMargin;
int h = arrowHeight;
for (int j = 0; j < arrowWidth; j++)
{
dc.MoveTo (x, y);
dc.LineTo (x, y + h);
h -= 2;
x += incr;
y++;
}
// draw the vertical line for the first and last buttons
if (dis.CtlID == FTBFIRST)
{
// the vertical line is before the arrow
x--;
y = rc.top + cyMargin;
dc.MoveTo (x, y);
dc.LineTo (x, y + arrowHeight);
}
if (dis.CtlID == FTBLAST)
{
// the vertical line is after the arrow
x++;
y = rc.top + cyMargin;
dc.MoveTo (x, y);
dc.LineTo (x, y + arrowHeight);
}
dc.SelectObject(pOldPen);
}
void CFolderButton::OnLButtonDown(UINT nFlags, CPoint pt)
{
Default();
SetTimer(1,500,NULL);
m_iState = 0;
}
void CFolderButton::OnLButtonUp(UINT nFlags, CPoint pt)
{
KillTimer(1);
Default();
}
void CFolderButton::OnLButtonDblClk(UINT nFlags, CPoint pt)
{
SendMessage(WM_LBUTTONDOWN,nFlags,MAKELONG(pt.x,pt.y));
}
void CFolderButton::OnTimer(UINT nIDEvent)
{
if (IsWindowEnabled())
{
if (m_iState++ == 0)
{
KillTimer(1);
SetTimer(1,150,NULL);
}
GetParent()->SendMessage(WM_COMMAND, GetDlgCtrlID());
}
else
{
KillTimer(1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -