System menu fix for floating toolbar

Environment: ****** –>

Default system menu for standard MFC toolbar has maximize/minimize/restore ability. I didn’t like the
way the Maximized toolbar looked. Ben Summers and
Sushil Saxena already submited some ways to fix
MFC bars, however, I found another one:

MFC removes SC_SIZE from toolbar frame each time when it appears.


BOOL CMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
{

CMenu* pSysMenu = GetSystemMenu(FALSE);
pSysMenu->DeleteMenu(SC_SIZE, MF_BYCOMMAND);

}

The solution is a class derived from CMiniDockFrame with his own Create(…)


BOOL CFixedMiniFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
{
// set m_bInRecalcLayout to avoid flashing during creation
// RecalcLayout will be called once something is docked
m_bInRecalcLayout = TRUE;

DWORD dwStyle = WS_POPUP|WS_CAPTION|WS_SYSMENU|MFS_MOVEFRAME|
MFS_4THICKFRAME|MFS_SYNCACTIVE|MFS_BLOCKSYSMENU|
FWS_SNAPTOBARS;

if (dwBarStyle & CBRS_SIZE_DYNAMIC)
dwStyle &= ~MFS_MOVEFRAME;

DWORD dwExStyle = 0;
#ifdef _MAC
if (dwBarStyle & CBRS_SIZE_DYNAMIC)
dwExStyle |= WS_EX_FORCESIZEBOX;
else
dwStyle &= ~(MFS_MOVEFRAME|MFS_4THICKFRAME);
#endif

if (!CMiniFrameWnd::CreateEx(dwExStyle,
NULL, &afxChNil, dwStyle, rectDefault, pParent))
{
m_bInRecalcLayout = FALSE;
return FALSE;
}
dwStyle = dwBarStyle & (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) ?
CBRS_ALIGN_LEFT : CBRS_ALIGN_TOP;
dwStyle |= dwBarStyle & CBRS_FLOAT_MULTI;

CMenu* pSysMenu = GetSystemMenu(FALSE);

pSysMenu->DeleteMenu(SC_SIZE, MF_BYCOMMAND);
pSysMenu->DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND);
pSysMenu->DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND);

CString str;
if (str.LoadString(AFX_IDS_HIDE))
pSysMenu->ModifyMenu(SC_CLOSE,
MF_BYCOMMAND|MF_STRING|MF_ENABLED, SC_CLOSE, str);
// convert SC_RESTORE to ToggleDocking();
if (str.LoadString(AFX_IDS_DOCK))
pSysMenu->ModifyMenu(SC_RESTORE,
MF_BYCOMMAND|MF_STRING|MF_ENABLED, SC_RESTORE, str);

// must initially create with parent frame as parent
if (!m_wndDockBar.Create(pParent, WS_CHILD | WS_VISIBLE | dwStyle,
AFX_IDW_DOCKBAR_FLOAT))
{
m_bInRecalcLayout = FALSE;
return FALSE;
}

// set parent to CMiniDockFrameWnd
m_wndDockBar.SetParent(this);
m_bInRecalcLayout = FALSE;

return TRUE;
}

Then I add code to handle SC_RESTORE. This is not
necessary, but why not?


BEGIN_MESSAGE_MAP(CFixedMiniFrameWnd, CMiniDockFrameWnd)
//{{AFX_MSG_MAP(CFixedMiniFrameWnd)
ON_WM_SYSCOMMAND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFixedMiniFrameWnd message handlers

void CFixedMiniFrameWnd::OnSysCommand(UINT nID, LPARAM)
{
switch (nID & 0xFFF0)
{
case SC_RESTORE:
OnNcLButtonDblClk( HTCAPTION, CPoint(0,0));
return;
}
Default();
}

Of course, MainFrame must know our new class


int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);

// Use our own class for miniframes
m_pFloatingFrameClass = RUNTIME_CLASS(CFixedMiniFrameWnd);


}

Download demo project – 17KB

Download demo only – 8KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read