作者:朱金灿
来源:clever101的专栏
问题现象描述
最近实现在一个MFC单文档程序上动态创建菜单栏和工具栏,代码如下:
static void DelRedundantMenu(HMENU hMenu)
{
// 首先删除多余的菜单项
int Menucount = GetMenuItemCount(hMenu);
for (int i = Menucount - 1; i > -1; i--)
{
::DeleteMenu(hMenu, i, MF_BYPOSITION);
}
}
BOOL CMainFrame::CreateMenuBar()
{
// 删除默认的菜单
CMenu* pMenu = GetMenu();
if (NULL != pMenu)
{
DelRedundantMenu(pMenu->GetSafeHmenu());
}
CMenu PopupMenu;
PopupMenu.CreatePopupMenu();
PopupMenu.AppendMenu(MF_STRING, 1024, "&New");
PopupMenu.AppendMenu(MF_STRING, 1025, "&Open");
PopupMenu.AppendMenu(MF_STRING, 1026, "&Close");
PopupMenu.AppendMenu(MF_STRING, 1027, "E&xit");
pMenu->AppendMenu(MF_POPUP, (UINT)PopupMenu.m_hMenu, "&File"); //关键!
PopupMenu.Detach();
return TRUE;
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CreateMenuBar();
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC))
{
TRACE0("未能创建工具栏\n");
return -1; // 未能创建
}
TCHAR dir[MAX_PATH], fname[MAX_PATH];
GetModuleFileName((HMODULE)theApp.m_hInstance, dir, MAX_PATH);
TCHAR *p1 = _tcsrchr(dir, _T('\\'));
*p1 = 0;
CImage img;
_stprintf_s(fname, MAX_PATH, _T("%s\\apple_64px.png"), dir);
img.Load(fname);
CImageList imglist;
imglist.Create(img.GetWidth(), img.GetHeight(), ILC_COLOR32, 16, 16);
ImageList_Add(imglist.GetSafeHandle(), (HBITMAP)img, NULL);
_stprintf_s(fname, MAX_PATH, _T("%s\\heart_64px.png"), dir);
img.Destroy();
img.Load(fname);
ImageList_Add(imglist.GetSafeHandle(), (HBITMAP)img, NULL);
_stprintf_s(fname, MAX_PATH, _T("%s\\windows_xp_64px.png"), dir);
img.Destroy();
img.Load(fname);
ImageList_Add(imglist.GetSafeHandle(), (HBITMAP)img, NULL);
HIMAGELIST hImgs = imglist.Detach();
SIZE sizeButton, sizeImage;
sizeButton.cx = img.GetWidth() + 7;
sizeButton.cy = img.GetHeight() + 6;
sizeImage.cx = img.GetWidth();
sizeImage.cy = img.GetHeight();
m_wndToolBar.SetSizes(sizeButton, sizeImage);
m_wndToolBar.SendMessage(TB_SETIMAGELIST, 0, (LPARAM)hImgs);
int i = 0;
TBBUTTON buttons[3];
buttons[i].iBitmap = 0;
buttons[i].idCommand = ID_APP_ABOUT;
buttons[i].fsState = TBSTATE_ENABLED;
buttons[i].fsStyle = BTNS_BUTTON;
buttons[i].dwData = 0;
buttons[i].iString = 0;
i++;
buttons[i].iBitmap = 1;
buttons[i].idCommand = ID_FILE_OPEN;
buttons[i].fsState = TBSTATE_ENABLED;
buttons[i].fsStyle = BTNS_BUTTON;
buttons[i].dwData = 0;
buttons[i].iString = 0;
i++;
buttons[i].iBitmap = 2;
buttons[i].idCommand = ID_FILE_SAVE;
buttons[i].fsState = TBSTATE_ENABLED;
buttons[i].fsStyle = BTNS_BUTTON;
buttons[i].dwData = 0;
buttons[i].iString = 0;
i++;
m_wndToolBar.SendMessage(TB_ADDBUTTONS, i, (LPARAM)buttons);
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("未能创建状态栏\n");
return -1; // 未能创建
}
// TODO: 如果不需要工具栏可停靠,则删除这三行
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
结果的效果图如下:
可以看到工具栏的背景是黑色的。
原因分析
我仔细研究了一下代码,发现代码并无问题。那么问题出现在什么地方呢?请教了一位朋友后,他告诉我老版本的comctrl32.dll不支持32位真彩色图像的ImageList,我的程序可能是链接了老版本的comctrl32.dll。
解决方案
按照朋友给的建议,要修改的话应该是强制链接新版本的comctrl32.dll,具体是在工程的stdafx.h添加如下代码:
#if defined _M_IX86
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif