本主题包含一个示例,显示如何模拟菜单中的复选框。该示例包含一个字符菜单,其项目允许用户设置当前字体的粗体,斜体和下划线属性。当字体属性有效时,相应菜单项旁边的复选框中会显示一个复选标记;否则,项目旁边将显示一个空的复选框。
该示例用两个位图替换了默认的复选标记位图:带有复选框的位图和带有空框的位图。当项目的检查标记属性设置为MF_CHECKED时,勾选的复选框位图显示在粗体,斜体或下划线菜单项旁边。当复选标记属性设置为MF_UNCHECKED时,将显示未选中或空的复选框位图。
Windows提供了一个预定义的位图,其中包含用于复选框和单选按钮的图像。示例将检查和空复选框隔离,将它们复制到两个单独的位图,然后将其用作“字符”菜单中项目的已选中和未检查的位图。
要检索系统定义的复选框位图的句柄,该示例调用LoadBitmap函数,将【的hInstance】参数指定为NULL,将OBM_CHECKBOXES指定为【lpBitmapName】参数。因为位图中的图像大小相同,所以示例可以通过将位图的宽度和高度除以其行和列中的图像数来隔离它们。
资源定义文件的以下部分显示如何定义“字符”菜单中的菜单项。请注意,最初没有字体属性有效,因此将常规项目的复选标记属性设置为检查,默认情况下,其余项目的复选标记属性设置为未选中。
#include“men3.h”
主菜单菜单
BEGIN
POPUP“&字符”
BEGIN
MENUITEM“& Regular”,IDM_REGULAR,CHECKED
MENUITEM SEPARATOR
MENUITEM“& Bold”,IDM_BOLD
MENUITEM“&斜体”,IDM_ITALIC
MENUITEM“&下划线”,IDM_ULINE
END
END
以下是应用程序头文件的相关内容。
//菜单项标识符
#define IDM_REGULAR 0x1
#define IDM_BOLD 0x2
#define IDM_ITALIC 0x4
#define IDM_ULINE 0x8
//检查标记
#define CHECK 1
#define UNCHECK 2
//字体属性掩码
#define ATTRIBMASK 0xe
//函数原型
LRESULT APIENTRY MainWndProc(HWND, UINT, WPARAM, LPARAM);
HBITMAP GetMyCheckBitmaps(UINT);
BYTE CheckOrUncheckMenuItem(BYTE, HMENU);
以下示例显示了创建复选标记位图的窗口过程的部分;设置粗体,斜体和下划线菜单项的复选标记属性;并销毁复选标记位图。
LRESULT APIENTRY MainWndProc(hwndMain,uMsg,wParam,lParam)en
HWND hwndMain;
UINT uMsg;
WPARAM wParam;
LPARAM lParam;
{
static HBITMAP hbmpCheck; //检查位图的句柄
static HBITMAP hbmpUncheck; //处理未检查的位图
static HMENU hmenu; //主菜单的句柄
BYTE fbFontAttrib; // font-attribute flags
开关(uMsg){
case WM_CREATE:
//调用应用程序定义的GetMyCheckBitmaps
//函数获取预定义的检查和
//未勾选的复选框位图。
hbmpCheck = GetMyCheckBitmaps(CHECK);
hbmpUncheck = GetMyCheckBitmaps(UNCHECK);
//设置菜单的选中和未选中的位图
//项目。
hmenu = GetMenu(hwndMain);
SetMenuItemBitmaps(hmenu,IDM_BOLD,MF_BYCOMMAND,
hbmpUncheck, hbmpCheck);
SetMenuItemBitmaps(hmenu,IDM_ITALIC,MF_BYCOMMAND,
hbmpUncheck, hbmpCheck);
SetMenuItemBitmaps(hmenu,IDM_ULINE,MF_BYCOMMAND,
hbmpUncheck, hbmpCheck);
return 0;
case WM_COMMAND:
开关(LOWORD(wParam)){
//处理菜单命令。
case IDM_REGULAR:
case IDM_BOLD:
case IDM_ITALIC:
case IDM_ULINE:
// CheckOrUncheckMenuItem是一个应用程序 -
//定义函数设置菜单项
//检查标记并返回用户选择
//字体属性。
fbFontAttrib = CheckOrUncheckMenuItem(
(BYTE) LOWORD(wParam), hmenu);
.
. //设置字体属性。
.
return 0;
.
. //处理其他命令消息。
.
默认:
break;
}
break;
.
. //处理其他窗口消息
.
case WM_DESTROY:
//销毁已检查和未检查的位图。
DeleteObject(hbmpCheck);
DeleteObject(hbmpUncheck);
PostQuitMessage(0);
break;
默认:
return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}
return NULL;
}
HBITMAP GetMyCheckBitmaps(fuCheck)
UINT fuCheck; //检查或UNCHECK标志
{
COLORREF crBackground; // 背景颜色
HBRUSH hbrBackground; //背景画刷
HBRUSH hbrTargetOld; //原始背景画笔
HDC hdcSource; //源设备上下文
HDC hdcTarget; //目标设备上下文
HBITMAP hbmpCheckboxes; //处理复选框位图
BITMAP bmCheckbox; //位图数据结构
HBITMAP hbmpSourceOld; //原始源位图的句柄
HBITMAP hbmpTargetOld; //原始目标位图的句柄
HBITMAP hbmpCheck; //复选标记位图的句柄
RECT rc; //用于复选框位图的矩形
DWORD dwCheckXY; //检查标记位图的尺寸
WORD wBitmapX; //检查标记位图的宽度
WORD wBitmapY; //检查标记位图的高度
//获取菜单背景颜色并创建一个实心的画笔
//用那种颜色
crBackground = GetSysColor(COLOR_MENU);
hbrBackground = CreateSolidBrush(crBackground);
//为源创建内存设备上下文
//目标位图。
hdcSource = CreateCompatibleDC((HDC) NULL);
hdcTarget = CreateCompatibleDC(hdcSource);
//获取Windows默认复选标记位图的大小
//创建相同大小的兼容位图。
dwCheckXY = GetMenuCheckMarkDimensions();
wBitmapX = LOWORD(dwCheckXY);
wBitmapY = LOWORD(dwCheckXY);
hbmpCheck = CreateCompatibleBitmap(hdcSource, wBitmapX,
wBitmapY);
//在目标DC中选择背景画笔和位图。
hbrTargetOld = SelectObject(hdcTarget, hbrBackground);
hbmpTargetOld = SelectObject(hdcTarget, hbmpCheck);
//使用所选画笔初始化背景颜色
//目标设备上下文中的位图。
PatBlt(hdcTarget, 0, 0, wBitmapX, wBitmapY, PATCOPY);
//加载预定义的复选框位图并选择它
//进入源DC。
hbmpCheckboxes = LoadBitmap((HINSTANCE) NULL,
(LPTSTR) OBM_CHECKBOXES);
hbmpSourceOld = SelectObject(hdcSource, hbmpCheckboxes);
//填写BITMAP结构信息
//复选框位图,然后找到左上角
//未勾选的复选框或勾选的复选框。
GetObject(hbmpCheckboxes, sizeof(BITMAP), &bmCheckbox);
if (fuCheck == UNCHECK) {
rc.left = 0;
rc.right = (bmCheckbox.bmWidth / 4);
}
else {
rc.left = (bmCheckbox.bmWidth / 4);
rc.right = (bmCheckbox.bmWidth / 4) * 2;
}
rc.top = 0;
rc.bottom = (bmCheckbox.bmHeight / 3);
//将适当的位图复制到目标DC中。如果
//复选框位图大于默认的复选标记
//位图,使用StretchBlt使其适合;否则,只是
//复制它
if(((rc.right - rc.left)>(int)wBitmapX)||
((rc.bottom - rc.top)>(int)wBitmapY))
StretchBlt(hdcTarget,0,0,wBitmapX,wBitmapY,
hdcSource,rc.left,rc.top,rc.right - rc.left,
rc.bottom - rc.top, SRCCOPY);
其他
BitBlt(hdcTarget,0,0,rc.right - rc.left,
rc.bottom - rc.top,
hdcSource, rc.left, rc.top, SRCCOPY);
//选择旧的源和目标位图
//源和目标DC,然后删除DC和
//背景画笔。
SelectObject(hdcSource, hbmpSourceOld);
SelectObject(hdcTarget, hbrTargetOld);
hbmpCheck = SelectObject(hdcTarget, hbmpTargetOld);
DeleteObject(hbrBackground);
DeleteObject(hdcSource);
DeleteObject(hdcTarget);
//返回新的复选标记位图的句柄。
return hbmpCheck;
}
BYTE CheckOrUncheckMenuItem(bMenuItemID,hmenu)
BYTE bMenuItemID;
HMENU hmenu;
{
DWORD fdwMenu;
static BYTE fbAttributes;
switch(bMenuItemID){
case IDM_REGULAR:
//每当选择常规菜单项时,添加一个
//勾选标记,然后从中删除复选标记
//任何字体属性菜单项。
CheckMenuItem(hmenu,IDM_REGULAR,MF_BYCOMMAND |
MF_CHECKED);
if(fbAttributes & ATTRIBMASK){
CheckMenuItem(hmenu,IDM_BOLD,MF_BYCOMMAND |
MF_UNCHECKED);
CheckMenuItem(hmenu,IDM_ITALIC,MF_BYCOMMAND |
MF_UNCHECKED);
CheckMenuItem(hmenu,IDM_ULINE,MF_BYCOMMAND |
MF_UNCHECKED);
}
fbAttributes = IDM_REGULAR;
return fbAttributes;
case IDM_BOLD:
case IDM_ITALIC:
case IDM_ULINE:
//切换所选菜单项的复选标记
//适当地设置字体属性标志。
fdwMenu = GetMenuState(hmenu, (UINT) bMenuItemID,
MF_BYCOMMAND);
if(!(fdwMenu & MF_CHECKED)){
CheckMenuItem(hmenu,(UINT)bMenuItemID,
MF_BYCOMMAND | MF_CHECKED);
fbAttributes |= bMenuItemID;
} else {
CheckMenuItem(hmenu,(UINT)bMenuItemID,
MF_BYCOMMAND | MF_UNCHECKED);
fbAttributes ^= bMenuItemID;
}
//如果当前选择了任何字体属性,
//从常规菜单项中删除复选标记;
//如果没有选择属性,请添加一个复选标记
//到常规菜单项。
if(fbAttributes & ATTRIBMASK){
CheckMenuItem(hmenu,IDM_REGULAR,
MF_BYCOMMAND | MF_UNCHECKED);
fbAttributes &= (BYTE) ~IDM_REGULAR;
} else {
CheckMenuItem(hmenu,IDM_REGULAR,
MF_BYCOMMAND | MF_CHECKED);
fbAttributes = IDM_REGULAR;
}
return fbAttributes;
}
}