本主题中的示例创建两个菜单,每个菜单包含几个位图菜单项。对于每个菜单,应用程序在主窗口的菜单栏中添加相应的菜单名称。
第一个菜单包含显示三种图表类型的菜单项:饼图,线条和条形图。这些菜单项的位图被定义为资源,并使用LoadBitmap功能加载。与此菜单相关联是菜单栏上的“图表”菜单名称。
第二个菜单包含显示CreatePen功能中使用的五种线条样式的菜单项:PS_SOLID,PS_DASH,PS_DOT,PS_DASHDOT和PS_DASHDOTDOT。该应用程序使用GDI绘图功能在运行时创建这些菜单项的位图。与此菜单相关联的是菜单栏上的“线条”菜单名称。
在应用程序的窗口过程中定义了两个位图句柄的静态数组。一个数组包含用于图表菜单的三个位图的句柄。另一个包含用于“线”菜单的五个位图的句柄。处理WM_CREATE消息时,窗口过程将加载图表位图,创建行位图,然后添加相应的菜单项。处理WM_DESTROY消息时,窗口过程将删除所有位图。
以下是应用程序头文件的相关部分。
//菜单项标识符
#define IDM_LINE 2
#define IDM_BAR 3
// Line-type flags
#define IDM_SOLID 4
#define IDM_DASH 5
#define IDM_DASHDOT 6
#define IDM_DASHDOTDOT 7
//图表和线菜单上的项目数
#define C_LINES 5
#define C_CHARTS 3
//位图资源标识符
#define IDB_PIE 1
#define IDB_LINE 2
#define IDB_BAR 3
//行位图的尺寸
#define CX_LINEBMP 40
#define CY_LINEBMP 10
以下是窗口过程的相关部分。窗口过程通过调用应用程序定义的LoadChartBitmaps,CreateLineBitmaps和AddBitmapMenu函数来执行其大部分初始化,本主题稍后介绍。
LRESULT CALLBACK MainWindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
if(!OnCreate(hwnd))
)
{
static HBITMAP aHbmLines[C_LINES];
static HBITMAP aHbmChart[C_CHARTS];
int i;
开关(uMsg){
case WM_CREATE:
//调用应用程序定义的函数来加载
//图表菜单的位图,并为其创建
//线条菜单。
LoadChartBitmaps(aHbmChart);
CreateLineBitmaps(aHbmLines);
//调用应用程序定义的函数来创建
//包含位图菜单项的菜单。功能
//还向窗口的菜单栏添加菜单名称。
AddBitmapMenu(
hwnd, //菜单栏的所有者窗口
"&Chart", 菜单栏上的菜单名称的文本
IDM_PIE, //菜单上第一个项目的ID
aHbmChart, //数组位图句柄
C_CHARTS //菜单上的项目数量
);
AddBitmapMenu(hwnd,“&行”,IDM_SOLID,
aHbmLines, C_LINES);
break;
case WM_DESTROY:
for (i = 0; i < C_LINES; i++)
DeleteObject(aHbmLines[i]);
for (i = 0; i < C_CHARTS; i++)
DeleteObject(aHbmChart[i]);
PostQuitMessage(0);
break;
.
. //处理其他消息。
.
默认:
return (DefWindowProc(hwnd, uMsg, wParam, lParam));
}
return 0;
}
应用程序定义的LoadChartBitmaps函数通过调用LoadBitmap函数加载图表菜单的位图资源,如下所示。
VOID WINAPI LoadChartBitmaps(HBITMAP * paHbm)
{
paHbm[0] = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_PIE));
paHbm[1] = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_LINE));
paHbm[2] = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_BAR));
}
应用程序定义的CreateLineBitmaps函数通过使用GDI绘图函数为Lines菜单创建位图。该函数创建与桌面窗口的DC具有相同属性的内存设备上下文(DC)。对于每个线型,函数创建一个位图,将其选择到存储器DC中,然后进行绘制。
VOID WINAPI CreateLineBitmaps(HBITMAP * paHbm)
{
HWND hwndDesktop = GetDesktopWindow();
HDC hdcDesktop = GetDC(hwndDesktop);
HDC hdcMem = CreateCompatibleDC(hdcDesktop);
COLORREF clrMenu = GetSysColor(COLOR_MENU);
HBRUSH hbrOld;
HPEN hpenOld;
HBITMAP hbmOld;
int fnDrawMode;
int i;
//使用菜单背景颜色创建一个画笔,
//并将其选择到内存DC中。
hbrOld = SelectObject(hdcMem, CreateSolidBrush(clrMenu));
//创建位图。选择每一个进入存储器
// DC被创建并绘制。
for (i = 0; i < C_LINES; i++) {
//创建位图并将其选择到DC中。
paHbm[i] = CreateCompatibleBitmap(hdcDesktop,
CX_LINEBMP, CY_LINEBMP);
hbmOld = SelectObject(hdcMem, paHbm[i]);
//使用画笔填写背景。
PatBlt(hdcMem, 0, 0, CX_LINEBMP, CY_LINEBMP, PATCOPY);
//创建笔并将其选入DC。
hpenOld = SelectObject(hdcMem,
CreatePen(PS_SOLID + i, 1, RGB(0, 0, 0)));
//画线保留背景颜色
//笔为白色,请使用R2_MASKPEN绘图模式。
fnDrawMode = SetROP2(hdcMem, R2_MASKPEN);
MoveToEx(hdcMem, 0, CY_LINEBMP / 2, NULL);
LineTo(hdcMem, CX_LINEBMP, CY_LINEBMP / 2);
SetROP2(hdcMem, fnDrawMode);
//删除笔,然后选择旧的笔和位图。
DeleteObject(SelectObject(hdcMem, hpenOld));
SelectObject(hdcMem, hbmOld);
}
//删除画笔并选择原始画笔。
DeleteObject(SelectObject(hdcMem, hbrOld));
//删除内存DC并释放桌面DC。
DeleteDC(hdcMem);
ReleaseDC(hwndDesktop, hdcDesktop);
}
应用程序定义的AddBitmapMenu函数创建一个菜单,并向其中添加指定数量的位图菜单项。然后在指定的窗口的菜单栏中添加相应的菜单名称。
VOID WINAPI AddBitmapMenu(
HWND hwnd, //拥有菜单栏的窗口
LPSTR lpszText, 菜单栏上的菜单名称的文本
UINT uID, //第一个位图菜单项的ID
HBITMAP *paHbm, //菜单项的位图
int cItems) //号码位图菜单项
{
HMENU hmenuBar = GetMenu(hwnd);
HMENU hmenuPopup = CreatePopupMenu();
MENUITEMINFO mii;
int i;
//将位图菜单项添加到菜单中。
for (i = 0; i < cItems; i++) {
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_DATA;
mii.fType = MFT_BITMAP;
mii.wID = uID + i;
mii.dwTypeData = (LPSTR) (paHbm[i]);
InsertMenuItem(hmenuPopup, i, TRUE, &mii);
}
//向菜单栏添加菜单名称。
mii.fMask = MIIM_TYPE | MIIM_DATA | MIIM_SUBMENU;
mii.fType = MFT_STRING;
mii.hSubMenu = hmenuPopup;
mii.dwTypeData = lpszText;
InsertMenuItem(hmenuBar,
GetMenuItemCount(hmenuBar), TRUE, &mii);
}