Introduction
After downloading WTL 7.0 I have seen that Microsoft has implemented full MDI
support. But I found two small problems in this implementation. First, the MDI
child window icon looks terrible on command bar (when child window is
maximized). Second, if application has few types of childs and active MDI child
is maximized, if you try to switch to child window of different type (i.e. that
has different icon), the icon displayed on command bar remains the same.
The fix
To fix these small bugs was very simple: I changed a little bit of the
function OnAllHookMessages in the template (original code line
3396, file atlctrlw.h). First problem occurs, because if the child
window returns NULL when command bar sends message
WM_GETICON (and standard CMDIChildWindowImpl does it),
in the code it uses hIcon member of WNDCLASSEX, and
the big icon after interpolation looks ugly. It is actually supposed to use
hIconSm member, to retrieve small icon from
WNDCLASSEX. To solve second problem is also very simple: just to
check, if new icon handle is equal to old, and if not force command bar to
redraw itself. Here is the code:
LRESULT OnAllHookMessages(UINT uMsg, WPARAM ,
LPARAM , BOOL& bHandled)
{
bHandled = FALSE;
if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU)
return 1;
BOOL bMaximized = FALSE;
HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient,
WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
bool bMaxOld = m_bChildMaximized;
bool bNeedRedraw = false;
m_bChildMaximized = (hWndChild != NULL && bMaximized);
if(m_bChildMaximized)
{
if(m_hWndChildMaximized != hWndChild)
{
CWindow wnd = m_hWndChildMaximized = hWndChild;
HICON hOldIcon = m_hIconChildMaximized;
m_hIconChildMaximized = wnd.GetIcon(FALSE);
if(m_hIconChildMaximized == NULL)
{
TCHAR szClass[200];
::GetClassName(wnd, szClass,
sizeof(szClass) / sizeof(TCHAR));
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
BOOL bRet = ::GetClassInfoEx(
_Module.GetModuleInstance(), szClass, &wc);
if(!bRet)
bRet = ::GetClassInfoEx(NULL, szClass, &wc);
m_hIconChildMaximized = bRet ?
(wc.hIconSm ? wc.hIconSm : wc.hIcon) : NULL;
}
bNeedRedraw = (hOldIcon != m_hIconChildMaximized);
}
}
else
{
m_hWndChildMaximized = NULL;
m_hIconChildMaximized = NULL;
}
if(bMaxOld != m_bChildMaximized)
{
#ifdef _CMDBAR_EXTRA_TRACE
ATLTRACE2(atlTraceUI, 0, "MDI CmdBar - All messages "
"hook change: m_bChildMaximized = %s\n",
m_bChildMaximized ? "true" : "false");
#endif
int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT,
0, 0L);
int cxDiff = (m_bChildMaximized ? 1 : -1) *
(m_cxLeft + m_cxRight);
for(int i = 0; i < nCount; i++)
{
#if (_WIN32_IE >= 0x0500)
REBARBANDINFO rbi = { sizeof(REBARBANDINFO),
RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE
| RBBIM_STYLE };
::SendMessage(GetParent(), RB_GETBANDINFO, i,
(LPARAM)&rbi);
if(rbi.hwndChild == m_hWnd)
{
if((rbi.fStyle & RBBS_USECHEVRON) != 0)
{
rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE;
rbi.cxMinChild += cxDiff;
rbi.cxIdeal += cxDiff;
::SendMessage(GetParent(), RB_SETBANDINFO,
i, (LPARAM)&rbi);
}
break;
}
#else
REBARBANDINFO rbi = { sizeof(REBARBANDINFO),
RBBIM_CHILD | RBBIM_CHILDSIZE };
::SendMessage(GetParent(), RB_GETBANDINFO, i,
(LPARAM)&rbi);
if(rbi.hwndChild == m_hWnd)
{
rbi.fMask = RBBIM_CHILDSIZE;
rbi.cxMinChild += cxDiff;
::SendMessage(GetParent(), RB_SETBANDINFO, i,
(LPARAM)&rbi);
break;
}
#endif
}
bNeedRedraw = true;
}
if(bNeedRedraw)
{
RECT rect;
GetWindowRect(&rect);
::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2);
SetRedraw(FALSE);
SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE);
SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
SetRedraw(TRUE);
RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE
| RDW_UPDATENOW);
}
return 1;
}
Conclusion
Sorry for my English :-)