WTL 7.0 CMDICommandBarCtr 错误及修复





4.00/5 (1投票)
2002年5月14日
1分钟阅读

53922
WTL 7.0 CMDICommandBarCtr 小修复
引言
下载 WTL 7.0 后,我发现 Microsoft 已经实现了完整的 MDI 支持。但我在这个实现中发现了两个小问题。首先,命令栏上的 MDI 子窗口图标在最大化时看起来很糟糕。其次,如果应用程序有几种类型的子窗口,并且激活的 MDI 子窗口被最大化,如果你尝试切换到不同类型(即具有不同图标)的子窗口,命令栏上显示的图标仍然相同。
修复方案
修复这些小错误非常简单:我稍微修改了模板中的 OnAllHookMessages
函数(原始代码第 3396 行,文件 atlctrlw.h)。第一个问题发生的原因是,当命令栏发送 WM_GETICON
消息时,子窗口返回 NULL
(标准的 CMDIChildWindowImpl
就是这样做的),代码中会使用 WNDCLASSEX
的 hIcon
成员,而经过插值后的大图标看起来很丑。实际上应该使用 hIconSm
成员,从 WNDCLASSEX
中获取小图标。解决第二个问题也很简单:只需检查新的图标句柄是否等于旧的图标句柄,如果不相等,就强制命令栏重新绘制自身。以下是代码:
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;
}
历史
- 2002年5月14日:初始版本
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。