椭圆作为菜单中的选中图标

ellipse as checked icon in a menu

我正在为 window 创建一个上下文菜单,我想在子菜单中填充椭圆,每个椭圆用不同的颜色代替文本 - 这个子菜单负责选择颜色.我不知道该怎么做...有人知道任何具体的例子吗?我在 MSDN 页面上阅读了有关所有者绘制的菜单项的信息,但是没有关于此特定任务的示例 - 所以,我不知道该怎么做。后来我尝试更改菜单项的已选中图标 - 但结果是我的 Dev-C++(在 Windows 7 下)既不知道 SetDCBrushColor 也不知道 DC_BRUSH,而且我仍然不知道如何更改已选中图标而不从文件加载图像。然后我在程序的开头添加了以下几行:

#define _WIN32_IE 0x0600
#define WINVER  0x0700
#define _WIN32_WINNT 0x0700

然后编译器不会抗议,但是,当我尝试以下代码以及我选择的任何颜色时,图标总是黑色的:

HWND hwnd = GetDesktopWindow();
HDC hdc = GetDC( hwnd );
HDC hdcMem = CreateCompatibleDC( hdc );
SIZE size = { GetSystemMetrics( SM_CXMENUCHECK ), GetSystemMetrics( SM_CYMENUCHECK ) };
HBITMAP bitmap = CreateCompatibleBitmap( hdcMem, size.cx, size.cy );
HBITMAP bitmapOld = (HBITMAP) SelectObject( hdcMem, bitmap );
PatBlt( hdcMem, 0, 0, size.cx, size.cy, WHITENESS );
HBRUSH brushOld = (HBRUSH) SelectObject( hdcMem, GetStockObject( NULL_BRUSH ) );
Ellipse( hdcMem, 0, 0, size.cx, size.cy);
SetDCBrushColor( hdcMem, RGB(0,0,255) );
SelectObject( hdcMem, GetStockObject( DC_BRUSH ) );
Ellipse( hdcMem, 2, 2, size.cx-2, size.cy-2 );
SelectObject( hdcMem, brushOld );
SelectObject( hdcMem, bitmapOld );
DeleteDC( hdcMem );
ReleaseDC( hwnd, hdc );
SetMenuItemBitmaps( mnu_t, (30*M_MENU_T+25), MF_BYCOMMAND, bitmap, bitmap);// mnu_t and M_MENU_T are my variables

谁能帮帮我?

问题在这里:

HBITMAP bitmap = CreateCompatibleBitmap( hdcMem, size.cx, size.cy );

这是一个非常自然而合理的陈述,但它并没有达到大多数人的预期。这是一个常见的错误,可能需要很长时间才能找出问题的根源。我自己不止一次犯过这个错误,我知道这一点。

CreateCompatibleBitmap 创建与指定设备上下文 (DC) 兼容的位图。好吧,它确实——有点——但实际上更微妙的是:它创建了一个新的位图,该位图与选择到指定 DC 中的 位图 兼容。

当使用 CreateCompatibleDC 创建内存 DC 时,新 DC 会获得一个默认位图,该位图的宽度为 1 像素,高度为 1 像素,颜色深度为 1 位。这根本不直观,因为您要求 DC 与屏幕 DC 兼容,并且屏幕(几乎可以肯定)具有超过 1 位的色深。

因此,当您调用 CreateCompatibleBitmap 时,您会得到一个指定大小的新位图,每个像素使用 1 位。你可以画它,如果星星对齐,你会看到你画的粗略轮廓。但是如果星星没有对齐,你最终会得到所有像素都是单一颜色的。

当您将每像素 1 位的位图 blit 到另一个 DC 时,将使用当前的文本前景色和背景色。由于前景文本颜色通常为黑色,因此您最终得到的是一个黑色矩形,几乎不知道哪里出错了。

解决方法是在调用CreateCompatibleBitmap时指定屏幕或windowDC而不是内存DC。这将创建一个与屏幕使用的位图具有相同颜色深度的新位图,这非常有用。