📄 tabbarwnd.cpp
字号:
#include "stdafx.h"
#include "TabBars.h"
#include "ShellTools.h"
#include "TabBarWnd.h"
#include "TabManagerWnd.h"
#include "DevStudioWnd.h"
#include "Commands.h"
#include "DSWindow.h"
#include "DS_MDIWnd.h"
#include "DSAddin.h"
#include "BCMenu.h"
#include "Globals.h"
#include "ShellContextMenu.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define ID_TAB 1000
//#define MENU_WIDTH (14 + 8) // width for menu button
//#define MENU_HEIGHT (14 + 8) // height for menu button
#define GRIPPER_SIZE 6 // short side
// flags for popup menus
#define TPM_FLAGS (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD)
CTabBarsWnd *pGlobalTabs = NULL;
/////////////////////////////////////////////////////////////////////////////
// CTabBarsWnd
CTabBarsWnd::CTabBarsWnd(CCommands* pCommands) : m_RectGripper(0, 0, 0, 0), m_iLockUpdates(0)
{
m_pCommands = pCommands;
m_pApplication = pCommands->GetApplicationObject();
m_uTimerID = 0;
m_pFont = NULL;
}
CTabBarsWnd::~CTabBarsWnd()
{
POSITION p = m_TabData.GetStartPosition();
tabdata_t *pData;
HWND key;
while (p)
{
m_TabData.GetNextAssoc(p, key, pData);
delete pData;
}
if(m_pFont != NULL)
{
m_pFont->DeleteObject();
delete m_pFont;
}
DestroyWindow();
}
BEGIN_MESSAGE_MAP(CTabBarsWnd, CWnd)
//{{AFX_MSG_MAP(CTabBarsWnd)
ON_WM_CREATE()
ON_WM_WINDOWPOSCHANGED()
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_DRAWITEM()
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_NOTIFY(TCN_SELCHANGE, ID_TAB, OnSelchangeTabCtrl)
ON_NOTIFY(NM_RCLICK,ID_TAB, OnRClickTabCtrl)
ON_NOTIFY(TTN_NEEDTEXT, 0, OnToolTipTabCtrl)
ON_WM_MEASUREITEM()
ON_MESSAGE(MSG_TABCTRL_2_TABBARWND,OnDbClickTabCtrl)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTabBarsWnd message handlers
int CTabBarsWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
m_TabImages.Create(16, 16, ILC_COLOR8|ILC_MASK, 10, 5);
DWORD dwSty = WS_CHILD|WS_VISIBLE|TCS_TOOLTIPS|TCS_SINGLELINE|TCS_FORCELABELLEFT|TCS_BUTTONS|TCS_FLATBUTTONS|TCS_RAGGEDRIGHT|TCS_FOCUSNEVER;
if(cfg_iOrientation == soBottom)
dwSty |= TCS_BOTTOM;
SetRedraw(FALSE);
m_TabCtrl.Create(dwSty, CRect(0,0,1,1), this, ID_TAB);
DWORD dwExStyle= m_TabCtrl.GetExtendedStyle();
m_TabCtrl.SetExtendedStyle(dwExStyle | TCS_EX_FLATSEPARATORS);
// use a font smaller than default
CFont *pFont = new CFont();
pFont->CreatePointFont(80,_T("MS Sans Serif"));
SetTabFont(pFont);
m_TabCtrl.SetPadding(CSize(2,2));
m_TabCtrl.SetFont(pFont, TRUE);
UpdateTabs();
SetRedraw(TRUE);
RedrawWindow();
m_TabCtrl.SetImageList(&m_TabImages);
m_uTimerID = SetTimer(TABBAR_WINDOW_TIMERID,10000L,NULL);//for auto save
return 0;
}
void CTabBarsWnd::OnDestroy()
{
CWnd::OnDestroy();
}
void CTabBarsWnd::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
CWnd::OnWindowPosChanged(lpwndpos);
if (pGlobalActiveDSWindow->GetSaferHwnd())
{
static CWnd *MDIAreaWnd = NULL;
if (!MDIAreaWnd)
{
MDIAreaWnd = pGlobalActiveDSWindow->GetParent();
ASSERT(MDIAreaWnd);
}
SetWindowPos(MDIAreaWnd->GetWindow(GW_HWNDPREV), 0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE);
}
if ((lpwndpos->flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) == (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
return;
CRect r, r2, r3;
GetClientRect(r);
g_pDevStudioWnd->GetClientRect(r2);
GetWindowRect(r3);
g_pDevStudioWnd->ScreenToClient(r3);
if (r3.left != 0)
{
r.left++;
}
if (r3.right != r2.right)
{
r.right--;
}
// using global var's isn't great software eng. - but it works :)
if (pGlobalActiveManager->GetSafeHwnd())
{
r.DeflateRect(pGlobalActiveManager->GetBorder());
}
r.left += GRIPPER_SIZE;
if(cfg_iOrientation == soTop)
{
r.top += 1;
}
else
{
r.bottom -= 1;
}
m_TabCtrl.MoveWindow(r);
m_TabCtrl.ShowWindow(m_TabCtrl.GetItemCount()? SW_SHOW : SW_HIDE);
m_RectGripper = CRect(r.left - GRIPPER_SIZE, r.top, r.left, r.bottom);
}
// The following event handler is called when the user presses on a tab.
// The tab's corresponding window is activated.
// See FindDSWindow() for DevStudio window enumeration techniques.
void CTabBarsWnd::OnSelchangeTabCtrl(NMHDR* pNMHDR, LRESULT* pResult)
{
CComQIPtr<IGenericWindow, &IID_IGenericWindow> pWindow;
if (FindDSWindow(m_TabCtrl.GetCurSel(), pWindow))
{
ActivateWindow(pWindow);
}
}
// the following event handler is called when the user right-clicks on a tab.
void CTabBarsWnd::OnRClickTabCtrl(NMHDR* pNMHDR, LRESULT* pResult)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CComPtr<IDispatch> pDisp;
CComQIPtr<IGenericWindow, &IID_IGenericWindow> pWindow;//
CComQIPtr<IGenericDocument, &IID_IGenericDocument> pDoc;
BCMenu menu;
BCMenu * pPopup;
POINT point;
TCHITTESTINFO hti;
int iTab;
hti.pt = CPoint(GetMessagePos());
m_TabCtrl.ScreenToClient(&hti.pt);
iTab = m_TabCtrl.HitTest(&hti);
if (iTab < 0)
return;
if(!FindDSWindow(iTab, pWindow))
return;
VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
if (LoadPopupMenu(IDR_POPUP, menu, pPopup))
{
CComBSTR bStr;
CString cStr, cFullPath;
DsSaveStatus iSaved;
bool bIsTextWindow, bHasDoc;
int i;
typedef struct
{
UINT cmd; //command code
bool bDocWindowsOnly; //just effectively in document windows
bool bActiveWindowsOnly;//just effectively in generic windows
} cmnd_t;
// special commands which I want it show in menu
static cmnd_t commands[] =
{
{IDC_HEADERFLIP, true, false},
{IDC_SAVE, true, false},
{IDC_PROPERTIES, false, true},
{IDC_OPENASTEXT, true, false},
{IDC_ROATTR, true, false}
};
GetCursorPos(&point);
pWindow->get_Type(&bStr);
cStr = bStr;
bIsTextWindow = bool(cStr == "Text");
bHasDoc = GetDocumentObject(pWindow, pDoc);
if (bHasDoc)
{
pDoc->get_FullName(&bStr);
cFullPath = bStr;
}
else
{
cFullPath.Empty();
}
if (bIsTextWindow)
{
pPopup->EnableMenuItem(IDC_OPENASTEXT, MF_GRAYED | MF_BYCOMMAND);
}
CShellContextMenu scm(::GetActiveWindow(), cFullPath);
const int iShellContextPos = 2;//pPopup->GetMenuItemCount() - 3;
pPopup->ModifyODMenu(NULL, "Shell", IDB_SHELLCONTEXT);
if ((cfg_bNoShellContext && !(GetKeyState(cfg_iShellKey) & 0x8000)) || !bHasDoc)
{
pPopup->EnableMenuItem(iShellContextPos,
MF_GRAYED | MF_BYPOSITION);
}
else
{
scm.SetMenu((BCMenu *)pPopup->GetSubMenu(iShellContextPos),pPopup);
}
::SetMenuDefaultItem(pPopup->m_hMenu, 0, TRUE);
for (i = 0; i < countof(commands); i++)
{
if (!bHasDoc && commands[i].bDocWindowsOnly)
{
pPopup->EnableMenuItem(commands[i].cmd,MF_GRAYED | MF_BYCOMMAND);
}
}
int iCmd;
if (GetKeyState(cfg_iShellKey) & 0x8000)
{
iCmd = pPopup->GetSubMenu(iShellContextPos)->TrackPopupMenu(TPM_FLAGS, point.x, point.y, this);
}
else
{
iCmd = pPopup->TrackPopupMenu(TPM_FLAGS, point.x, point.y, this);
}
if (scm.IsMenuCommand(iCmd))
{
scm.InvokeCommand(iCmd);
}
else
{
for (i = 0; i < countof(commands); i++)
{
if (iCmd == (int)commands[i].cmd)
{
if (commands[i].bActiveWindowsOnly)
{
VARIANT_BOOL vb;
pWindow->get_Active(&vb);
if (vb == VARIANT_TRUE)
{
pWindow->put_Active(VARIANT_FALSE);
}
pWindow->put_Active(VARIANT_TRUE);
}
break;
}
}
HWND hWnd, hWndNext, hWndExcept = NULL;
switch (iCmd)
{
case IDC_SELECT:
ActivateWindow(pWindow);
break;
case IDC_CLOSE:
{
CloseDSWindow(pWindow);
/*
VARIANT_BOOL vb;
// bStr <- name of window to close
// (used later to retrieve window handle)
pWindow->get_Caption(&bStr);
// are we closing the active window?
pWindow->get_Active(&vb);
if (vb == VARIANT_FALSE)
{
// not closing the active window, so save the active
// window in pWindow
m_pApplication->get_ActiveWindow(&pDisp);
pWindow = pDisp;
pDisp = NULL;
m_iLockUpdates++;
// force an event:
pWindow->put_Active(VARIANT_FALSE);
}
::SendMessage(GetHWND(bStr), WM_CLOSE, 0, 0);//now close it!
// need to reactivate the previously active window?
if (vb == VARIANT_FALSE)
{
// get HWND of previously active window
HWND hWnd = GetHWND(pWindow);
::PostMessage(::GetParent(hWnd), WM_MDIACTIVATE,(WPARAM)hWnd, 0);
}
*/
break;
}
case IDC_CLOSEALLEXCEPT:
hWndExcept = GetHWND(pWindow);
hWnd = ::GetTopWindow(pGlobalMDIManager->m_hWnd);
while (hWnd)
{
hWndNext = ::GetNextWindow(hWnd, GW_HWNDNEXT);
if (hWnd != hWndExcept)
::PostMessage(hWnd, WM_CLOSE, 0, 0);
hWnd = hWndNext;
}
ActivateWindow(pWindow,FALSE);
ActivateWindow(pWindow);
break;
case IDC_CLOSEALL:
// doesn't use ExecuteCommand("WindowCloseAll")
// (see above)
hWnd = ::GetTopWindow(pGlobalMDIManager->m_hWnd);
while (hWnd)
{
hWndNext = ::GetNextWindow(hWnd, GW_HWNDNEXT);
::PostMessage(hWnd, WM_CLOSE, 0, 0);
hWnd = hWndNext;
}
break;
case IDC_SAVE:
{
CComVariant varPrompt = true, v = lpszNull;
pDoc->Save(v, varPrompt, &iSaved);
break;
}
case IDC_SAVEALL:
{
bStr = _T("FileSaveAll");
m_pApplication->ExecuteCommand(bStr);
break;
}
// BUG BUG: SaveAs doesn't work at all through
// IApplication->ExecuteCommand(). You can see this clearly
// by using the sample "command window" add-in that comes
// with VC.
/* case IDC_SAVEAS:
{
bStr = _T("FileSaveAs");
m_pApplication->ExecuteCommand(bStr);
break;
}
*/
case IDC_PROPERTIES:
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -