📄 flattabctrl.h
字号:
pt.x = rc.right - rc.left;
pt.y = 0;
chevron.ClientToScreen(&pt);
mnu.TrackPopupMenu(TPM_RIGHTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, m_hWnd);
return 0;
}
LRESULT onSelectWindow(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
CMenuItemInfo mi;
mi.fMask = MIIM_DATA;
mnu.GetMenuItemInfo(wID, FALSE, &mi);
HWND hWnd = GetParent();
if(hWnd) {
SendMessage(hWnd, FTM_SELECTED, (WPARAM)mi.dwItemData, 0);
}
return 0;
}
private:
class TabInfo {
public:
typedef vector<TabInfo*> List;
typedef typename List::iterator ListIter;
enum { MAX_LENGTH = 20 };
TabInfo(HWND aWnd, COLORREF c) : hWnd(aWnd), len(0), xpos(0), row(0), dirty(false) {
pen.CreatePen(PS_SOLID, 1, c);
memset(&size, 0, sizeof(size));
memset(&boldSize, 0, sizeof(boldSize));
name[0] = 0;
update();
}
HWND hWnd;
CPen pen;
TCHAR name[MAX_LENGTH];
size_t len;
SIZE size;
SIZE boldSize;
int xpos;
int row;
bool dirty;
bool update() {
TCHAR name2[MAX_LENGTH];
len = (size_t)::GetWindowTextLength(hWnd);
if(len >= MAX_LENGTH) {
::GetWindowText(hWnd, name2, MAX_LENGTH - 3);
name2[MAX_LENGTH - 4] = _T('.');
name2[MAX_LENGTH - 3] = _T('.');
name2[MAX_LENGTH - 2] = _T('.');
name2[MAX_LENGTH - 1] = 0;
len = MAX_LENGTH - 1;
} else {
::GetWindowText(hWnd, name2, MAX_LENGTH);
}
if(_tcscmp(name, name2) == 0) {
return false;
}
_tcscpy(name, name2);
CDC dc(::GetDC(hWnd));
HFONT f = dc.SelectFont(WinUtil::font);
dc.GetTextExtent(name, len, &size);
dc.SelectFont(WinUtil::boldFont);
dc.GetTextExtent(name, len, &boldSize);
dc.SelectFont(f);
::ReleaseDC(hWnd, dc);
return true;
}
bool updateText(LPCTSTR text) {
len = _tcslen(text);
if(len >= MAX_LENGTH) {
::_tcsncpy(name, text, MAX_LENGTH - 3);
name[MAX_LENGTH - 4] = '.';
name[MAX_LENGTH - 3] = '.';
name[MAX_LENGTH - 2] = '.';
name[MAX_LENGTH - 1] = 0;
len = MAX_LENGTH - 1;
} else {
_tcscpy(name, text);
}
CDC dc(::GetDC(hWnd));
HFONT f = dc.SelectFont(WinUtil::font);
dc.GetTextExtent(name, len, &size);
dc.SelectFont(WinUtil::boldFont);
dc.GetTextExtent(name, len, &boldSize);
dc.SelectFont(f);
::ReleaseDC(hWnd, dc);
return true;
}
int getWidth() {
return (dirty ? boldSize.cx : size.cx) + FT_EXTRA_SPACE;
}
};
void moveTabs(TabInfo* aTab, bool after){
if(moving == NULL)
return;
TabInfo::ListIter i, j;
//remove the tab we're moving
for(j = tabs.begin(); j != tabs.end(); ++j){
if((*j) == moving){
tabs.erase(j);
break;
}
}
//find the tab we're going to insert before or after
for(i = tabs.begin(); i != tabs.end(); ++i){
if((*i) == aTab){
if(after)
++i;
break;
}
}
tabs.insert(i, moving);
moving = NULL;
calcRows(false);
Invalidate();
}
HWND closing;
CButton chevron;
CMenu mnu;
int rows;
int height;
TabInfo* active;
TabInfo* moving;
typename TabInfo::List tabs;
CPen black;
typedef list<HWND> WindowList;
typedef WindowList::iterator WindowIter;
WindowList viewOrder;
WindowIter nextTab;
bool inTab;
TabInfo* getTabInfo(HWND aWnd) {
for(TabInfo::ListIter i = tabs.begin(); i != tabs.end(); ++i) {
if((*i)->hWnd == aWnd)
return *i;
}
return NULL;
}
/**
* Draws a tab
* @return The width of the tab
*/
void drawTab(CDC& dc, TabInfo* tab, int pos, int row, bool aActive = false) {
int ypos = (getRows() - row - 1) * getTabHeight();
HPEN oldpen = dc.SelectPen(black);
POINT p[4];
dc.BeginPath();
dc.MoveTo(pos, ypos);
p[0].x = pos + tab->getWidth() + getFill();
p[0].y = ypos;
p[1].x = pos + tab->getWidth();
p[1].y = ypos + getTabHeight();
p[2].x = pos + getFill();
p[2].y = ypos + getTabHeight();
p[3].x = pos;
p[3].y = ypos;
dc.PolylineTo(p, 4);
dc.CloseFigure();
dc.EndPath();
HBRUSH oldbrush = dc.SelectBrush(GetSysColorBrush(aActive ? COLOR_WINDOW : COLOR_BTNFACE));
dc.FillPath();
dc.MoveTo(p[1].x + 1, p[1].y);
dc.LineTo(p[0].x + 1, p[0].y);
dc.MoveTo(p[2]);
dc.LineTo(p[3]);
if(!active || (tab->row != (rows - 1)) )
dc.LineTo(p[0]);
dc.SelectPen(tab->pen);
dc.MoveTo(p[1]);
dc.LineTo(p[0]);
dc.MoveTo(p[1]);
dc.LineTo(p[2]);
dc.SelectPen(oldpen);
dc.SelectBrush(oldbrush);
dc.SetBkMode(TRANSPARENT);
if(tab->dirty) {
HFONT f = dc.SelectFont(WinUtil::boldFont);
dc.TextOut(pos + getFill() / 2 + FT_EXTRA_SPACE / 2, ypos + 1, tab->name, tab->len);
dc.SelectFont(f);
} else {
dc.TextOut(pos + getFill() / 2 + FT_EXTRA_SPACE / 2, ypos + 1, tab->name, tab->len);
}
}
};
class FlatTabCtrl : public FlatTabCtrlImpl<FlatTabCtrl> {
public:
DECLARE_FRAME_WND_CLASS_EX(GetWndClassName(), IDR_QUEUE, 0, COLOR_3DFACE);
};
template <class T, int C = RGB(128, 128, 128), class TBase = CMDIWindow, class TWinTraits = CMDIChildWinTraits>
class ATL_NO_VTABLE MDITabChildWindowImpl : public CMDIChildWindowImpl<T, TBase, TWinTraits> {
public:
MDITabChildWindowImpl() : created(false) { }
FlatTabCtrl* getTab() { return WinUtil::tabCtrl; }
virtual void OnFinalMessage(HWND /*hWnd*/) { delete this; }
typedef MDITabChildWindowImpl<T, C, TBase, TWinTraits> thisClass;
typedef CMDIChildWindowImpl<T, TBase, TWinTraits> baseClass;
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_CLOSE, onClose)
MESSAGE_HANDLER(WM_SYSCOMMAND, onSysCommand)
MESSAGE_HANDLER(WM_FORWARDMSG, onForwardMsg)
MESSAGE_HANDLER(WM_CREATE, onCreate)
MESSAGE_HANDLER(WM_MDIACTIVATE, onMDIActivate)
MESSAGE_HANDLER(WM_DESTROY, onDestroy)
MESSAGE_HANDLER(WM_SETTEXT, onSetText)
MESSAGE_HANDLER(WM_REALLY_CLOSE, onReallyClose)
MESSAGE_HANDLER(WM_NOTIFYFORMAT, onNotifyFormat)
CHAIN_MSG_MAP(baseClass)
END_MSG_MAP()
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
{
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
if(nMenuID != 0)
#if (_ATL_VER >= 0x0700)
m_hMenu = ::LoadMenu(ATL::_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
#else //!(_ATL_VER >= 0x0700)
m_hMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
#endif //!(_ATL_VER >= 0x0700)
if(m_hMenu == NULL)
m_hMenu = WinUtil::mainMenu;
dwStyle = T::GetWndStyle(dwStyle);
dwExStyle = T::GetWndExStyle(dwExStyle);
dwExStyle |= WS_EX_MDICHILD; // force this one
m_pfnSuperWindowProc = ::DefMDIChildProc;
m_hWndMDIClient = hWndParent;
ATLASSERT(::IsWindow(m_hWndMDIClient));
if(rect.m_lpRect == NULL)
rect.m_lpRect = &TBase::rcDefault;
// If the currently active MDI child is maximized, we want to create this one maximized too
ATL::CWindow wndParent = hWndParent;
BOOL bMaximized = FALSE;
if(MDIGetActive(&bMaximized) == NULL)
bMaximized = BOOLSETTING(MDI_MAXIMIZED);
if(bMaximized)
wndParent.SetRedraw(FALSE);
HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam);
if(bMaximized)
{
// Maximize and redraw everything
if(hWnd != NULL)
MDIMaximize(hWnd);
wndParent.SetRedraw(TRUE);
wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
::SetFocus(GetMDIFrame()); // focus will be set back to this window
}
else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus()))
{
::SetFocus(hWnd);
}
return hWnd;
}
LRESULT onNotifyFormat(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
#ifdef _UNICODE
return NFR_UNICODE;
#else
return NFR_ANSI;
#endif
}
// All MDI windows must have this in wtl it seems to handle ctrl-tab and so on...
LRESULT onForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) {
return baseClass::PreTranslateMessage((LPMSG)lParam);
}
LRESULT onSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) {
if(wParam == SC_NEXTWINDOW) {
HWND next = getTab()->getNext();
if(next != NULL) {
MDIActivate(next);
return 0;
}
} else if(wParam == SC_PREVWINDOW) {
HWND next = getTab()->getPrev();
if(next != NULL) {
MDIActivate(next);
return 0;
}
}
bHandled = FALSE;
return 0;
}
LRESULT onCreate(UINT /* uMsg */, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
bHandled = FALSE;
dcassert(getTab());
getTab()->addTab(m_hWnd, C);
created = true;
return 0;
}
LRESULT onMDIActivate(UINT /*uMsg*/, WPARAM /*wParam */, LPARAM lParam, BOOL& bHandled) {
dcassert(getTab());
if((m_hWnd == (HWND)lParam))
getTab()->setActive(m_hWnd);
bHandled = FALSE;
return 1;
}
LRESULT onDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
bHandled = FALSE;
dcassert(getTab());
getTab()->removeTab(m_hWnd);
if(m_hMenu == WinUtil::mainMenu)
m_hMenu = NULL;
BOOL bMaximized = FALSE;
if(::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized) != NULL)
SettingsManager::getInstance()->set(SettingsManager::MDI_MAXIMIZED, (bMaximized>0));
return 0;
}
LRESULT onReallyClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) {
MDIDestroy(m_hWnd);
return 0;
}
LRESULT onClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled */) {
PostMessage(WM_REALLY_CLOSE);
return 0;
}
LRESULT onSetText(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
bHandled = FALSE;
dcassert(getTab());
if(created) {
getTab()->updateText(m_hWnd, (LPCTSTR)lParam);
}
return 0;
}
LRESULT onKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
if(wParam == VK_CONTROL && LOWORD(lParam) == 1) {
getTab()->startSwitch();
}
bHandled = FALSE;
return 0;
}
LRESULT onKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) {
if(wParam == VK_CONTROL) {
getTab()->endSwitch();
}
bHandled = FALSE;
return 0;
}
void setDirty() {
dcassert(getTab());
getTab()->setDirty(m_hWnd);
}
void setTabColor(COLORREF color) {
dcassert(getTab());
getTab()->setColor(m_hWnd, color);
}
private:
bool created;
};
#endif // !defined(FLAT_TAB_CTRL_H)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -