Q
I have a problem I cannot find the answer for. Please tell me why the MFC toolbars and views (CListView, for example) do not display the 256-color icons and bitmaps I create in my resources. Instead they are all displayed as 16-color icons or bitmaps. Many Windows-based programs including Explorer, Microsoft® Internet Explorer, and others display full-color toolbars and icons. Please help!
Many Readers
有个问题,俺没找到答案。请告诉俺,怎样在俺的工具栏还有“污油”(譬如“李思特污油”中显示256克拉的图标和位图。很多程序,像是IE等都显示了“蛮色”的工具栏和图示,神啊,救救救我吧!
A
Kind of makes you feel like a second-class citizen, doesn't it? All those other apps have pretty multihued buttons, while your toolbars have a crude, color- challenged toy look. Never fear, it's easy to turn up the volume on your toolbar color dial.
Toolbars and list views both store their images in image lists. An image list is just what it sounds like: a list of images. Only the "list" isn't a linked list, it's a long bitmap that holds all the images, one after another. Say you have seven 20×20 icons. The image list holds them as one 140×20 bitmap (7×20 = 140). The bitmap can have as many color planes as you want; but you have to tell the image list how many colors to use when you create it. By default, you get 16. And when MFC loads your toolbar bitmap, it uses an internal function, AfxLoadSysColorBitmap, that presumes 16 colors. To get around MFC, you have to replace the bitmap; to do that, you have to get at the image list.
你是不是觉得有点像二等公民?哈哈,其他的程序都有好看的多彩的按钮,而你的工具栏却长的像是粗糟的,颜色有限的儿童玩具。别担心,提高你工具栏的颜色很容易。
工具栏和列表视图的图片都存在图像链表中。一条图像链表听起来好像:一个图像的列表。但是链表并不是相互连接的列表,它是一个长形的保存所有图片的位图,一个接一个。比如说你有七个20X20 的图标。图像链表就是一个140X20的位图。位图当然像你像的那样有很多颜色;但你得告诉图像链表你生成它的时候用了多少种颜色。默认情况下,你只会得到个16色的。还有当MFC载入你的工具栏位图之时,它用了一个内部的函数AfxLoadSysColorBitmap,并假定了16种颜色。要绕过MFC,你得换掉那个位图;要换掉那个位图,你得在图像链表中得到它。
Figure 5 Pretty Toolbar
I wrote a little app, TBColor, that shows how. TBColor is a plain, normal, ordinary, boring—did I say pedestrian?—MFC application with a pretty toolbar. Figure 5 tells the story. The buttons don't do much: any one you press brings up the About dialog. But how do the buttons get 256 colors? It all happens in CMainFrame::OnCreate (see Figure 6).
我写了一个小应用,TBColor,来显示如何做到这一切。TBColor是一个平常的,正常的,惯常的,无聊的,我说呆板了吗?带着一个漂亮工具栏的MFC应用程序。图五说明了这件事。按钮只会弹出个About对话。但是按钮是如何具有二五六中颜色的呢?故事发生在CMainFrame::OnCreate中(看图六)。
Figure 7 The Bitmap
The first step is to make sure you load your toolbar bitmap using ::LoadImage. This handy multipurpose function can load cursors, icons, and bitmaps. In the case of bitmaps, it will even (if you ask nicely) map certain colors in your bitmap to the current screen colors. For example, TBColor's toolbar bitmap (see Figure 7) uses RGB(192,192,192) for the background; LoadImage with LR_LOADMAP3DCOLORS maps this to whatever the actual 3D face color (GetSysColor(COLOR_3DFACE)) happens to be on your system.
第一步确信你用::LoadImage载入了toobbar。这个便捷的多用途函数能载入图标,鼠标和位图。对于位图来说哦,它甚至能将(如果你细问)当前的你的位图的颜色映射到当前屏幕的颜色。例如,TBColor's 工具栏位图用RGB(192,192,192)作为背景;在你的系统中LoadImage用LR_LOADMAP3DCOLORS把这映射到无论哪种真正的3D界面颜色(GetSysColor(COLOR_3DFACE))。
HBITMAP hbm = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_BITMAP,
0,0, // cx, cy
LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS );
LoadImage returns a handle to the bitmap (HBITMAP), but MFC likes CBitmaps better, so the next thing is to create one and attach your handle to it.
LoadImage返回一个指向那个位图句柄,但MFC更喜欢CBitmaps,因此下一件事就是要生成一个CBitmap对象并把它挂接到你的句柄上。
CBitmap bm;
bm.Attach(hbm);
Now that you have a CBitmap, you can create a new image list from it.
现在有了一个CBitmap,你能够用它产生一个新的图像链表。
m_ilToolBar.Create(20,20,ILC_COLOR8,4,4);
m_ilToolBar.Add(&bm,(CBitmap*)NULL);
m_ilToolBar is a CMainFrame member and ILC_COLOR8 is the magic flag that says: create an 8-bit paletted bitmap—that is, one with 256 colors. You can even create a bitmap with 24-bit color if you like—but keep in mind LR_LOADMAP3DCOLORS only works with paletted bitmaps, a little secret mommy never told you. In any case, once you've made your image list your way, the final step is to serve it to the toolbar.
M_ilToolBar是一个CMainFrame成员,还有ILC_COLOR8是系统的识别标志:那就是产生一个8位的调色板,拥有256中颜色。你也能够生成一个24位的位图如果你喜欢记住LR_LOADMAP3DCOLORS只和调色板位图一起工作,一旦你做完了图像链表,最后的步骤就是让它为工具栏服务。
m_wndToolBar.GetToolBarCtrl().
SetImageList(&m_ilToolBar);
Pretty simple, once you know the voodoo. I never actually tried it, but the same technique should work with list views and rebars and any other control that uses image lists. Now, go forth and unleash your inner Kandinsky!
小case,只要你知道那个魔法。我从未试验过,但这样的技术应该能够运用在列表视图和rebar还有其他的控件上,现在往前冲吧,释放你内心的Kandinsky(好像是个作画的俄罗斯司机)!