WTL 7.0 CMDICommandBarCtr Bug and Fix





4.00/5 (1 vote)
May 14, 2002
1 min read

53393
WTL 7.0 CMDICommandBarCtr small fixes
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 the application has few types of children 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 the 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 /*wParam*/,
LPARAM /*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; //declare variable to
// indicate whether we need redraw or not
m_bChildMaximized = (hWndChild != NULL && bMaximized);
if(m_bChildMaximized)
{
if(m_hWndChildMaximized != hWndChild)
{
CWindow wnd = m_hWndChildMaximized = hWndChild;
HICON hOldIcon = m_hIconChildMaximized;
//save old icon value
m_hIconChildMaximized = wnd.GetIcon(FALSE);
if(m_hIconChildMaximized == NULL)
// no icon set with WM_SETICON, get the class one
{
TCHAR szClass[200];
::GetClassName(wnd, szClass,
sizeof(szClass) / sizeof(TCHAR));
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
// try process local class first
BOOL bRet = ::GetClassInfoEx(
_Module.GetModuleInstance(), szClass, &wc);
if(!bRet) // try global class
bRet = ::GetClassInfoEx(NULL, szClass, &wc);
//if small icon is not NULL, use it, else use big icon
m_hIconChildMaximized = bRet ?
(wc.hIconSm ? wc.hIconSm : wc.hIcon) : NULL;
}
//if we need to set new icon, we need to redraw command bar
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
// assuming we are in a rebar, change our size to
// accommodate new state
// we hope that if we are not in a rebar, nCount will be 0
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 //!(_WIN32_IE >= 0x0500)
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 //!(_WIN32_IE >= 0x0500)
}
/*// force size change and redraw everything
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);*/
//now we need to redraw
bNeedRedraw = true;
}
if(bNeedRedraw)
{
// force size change and redraw everything
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;
}
History
- 14th May, 2002: Initial version
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.