c00*_*0fd 5 c++ windows winapi mfc contextmenu
我只是想在我的上下文菜单中添加小颜色样本(通过TrackPopupMenu API 显示.)这是我想要实现的Photoshop版本:
据我所知,默认菜单不支持它.顺便说一句,上面的样本(没有颜色样本)是通过这样做生成的:
MENUITEMINFO mii = {0};
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING;
mii.fType = MFT_STRING;
mii.wID = ID_1_MARKER_01 + m;
mii.dwTypeData = L"Marker";
mii.cch = TSIZEOF(L"Marker");
mii.fState = m == 1 ? MFS_CHECKED : MFS_ENABLED;
if(m == 2)
mii.fState |= MFS_GRAYED;
VERIFY(::InsertMenuItem(hMenu, ID_1_BEFORE, FALSE, &mii));
Run Code Online (Sandbox Code Playgroud)
所以我发现我需要使用MFT_OWNERDRAW
样式自己绘制菜单项,但这就是问题的开始.
我更改了代码以显示我的菜单:
MENUITEMINFO mii = {0};
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.fType = MFT_OWNERDRAW;
mii.wID = ID_1_MARKER_01 + m;
mii.dwItemData = MARKER_ID_01 + m;
mii.fState = m == 1 ? MFS_CHECKED : MFS_ENABLED;
if(m == 2)
mii.fState |= MFS_GRAYED;
VERIFY(::InsertMenuItem(hMenu, ID_1_BEFORE, FALSE, &mii));
Run Code Online (Sandbox Code Playgroud)
然后我需要覆盖WM_MEASUREITEM
和WM_DRAWITEM
消息.但是,当我使用下面将要显示的代码执行此操作时,这是我得到的:
所以请耐心等待.关于这个话题,我有几个问题:
1)在处理WM_MEASUREITEM
如何既DC
没有HWND
提供文本也不提供菜单的情况下我应该如何知道文本的大小?换句话说,如果我这样做,菜单的大小是错误的:
#define TSIZEOF(f) ((sizeof(f) - sizeof(TCHAR)) / sizeof(TCHAR))
//hwnd = HWND supplied in WM_MEASUREITEM notification
HDC hDC = ::GetDC(hwnd);
HGDIOBJ hOldFont = ::SelectObject(hDC, ::SendMessage(hwnd, WM_GETFONT, 0, 0));
SIZE szTxt = {0};
::GetTextExtentPoint32(hDC,
L"Marker",
TSIZEOF(L"Marker"),
&szTxt);
//lpmis = MEASUREITEMSTRUCT*
lpmis->itemWidth = szTxt.cx;
lpmis->itemHeight = szTxt.cy;
::SelectObject(hDC, hOldFont);
::ReleaseDC(hwnd, hDC);
Run Code Online (Sandbox Code Playgroud)
2)然后在处理时WM_DRAWITEM
如何知道偏移量以开始在左侧绘制文本?如果我这样做,我的菜单就没有向右偏移(正如你从上面的截图中看到的那样):
int nCheckW = ::GetSystemMetrics(SM_CXMENUCHECK);
//lpdis = DRAWITEMSTRUCT*
::ExtTextOut(lpdis->hDC,
lpdis->rcItem.left + nCheckW,
lpdis->rcItem.top,
ETO_OPAQUE,
&lpdis->rcItem,
L"Marker",
TSIZEOF(L"Marker"),
NULL);
Run Code Online (Sandbox Code Playgroud)
3)最后如何在菜单项的左侧绘制默认复选框?
虽然我不使用颜色样本,并且严格使用 MFC,但我确实在派生菜单项上渲染位图。您应该能够根据您的需要调整以下内容。
\n\n在测量项目文本时,我使用桌面dc。
\n\nCClientDC dc(CWnd::GetDesktopWindow());\nSIZE size;\n\nGetTextExtentPoint32(dc.m_hDC, buff, buff.GetLength(), &size );\nlpMeasureItemStruct->itemWidth = size.cx+12;\nlpMeasureItemStruct->itemHeight = size.cy+8;\n
Run Code Online (Sandbox Code Playgroud)\n\n通过实验进行一些微小的调整,我想出了我需要的尺寸。
\n\n为了渲染实际的位图和文本,我检查主题是否处于活动状态,并以两种不同的方式之一渲染菜单项。作为主题菜单项或标准菜单项。为了渲染文本,我从通过 LPDRAWITEMSTRUCT 传递的矩形开始。然后,我在渲染文本之前进行以下调整。
\n\n// adjust if non-themed.\nif (!IsThemeActive())\n rectt.left+= m_bmWidth+4;\nelse\n rectt.left+= BITMAP_ADJUSTMENT;\n
Run Code Online (Sandbox Code Playgroud)\n\n通过反复试验,我发现将 BITMAP_ADJUSTMENT 设置为 30 对我来说很有效。然后,根据项目的说明(禁用、选择),进一步调整rectt 。
\n\n// draw disabled text.\nif (disabled)\n {\n // draw selected text.\n if (selected)\n {\n pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));\n pDC->DrawText(text, &rectt, format);\n }\n else\n {\n offset = rectt;\n offset.left+= 1;\n offset.right+=1;\n offset.top+= 1;\n offset.bottom+= 1;\n pDC->SetTextColor(::GetSysColor(COLOR_BTNHILIGHT));\n pDC->DrawText(text, &offset, format);\n pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));\n pDC->DrawText(text, &rectt, format);\n }\n }\nelse\n // draw normal text.\n pDC->DrawText(text, &rectt, format);\n
Run Code Online (Sandbox Code Playgroud)\n\n最后,为了呈现复选标记,我使用预定义的位图创建图像列表(我可能已从 Microsoft dll 中提取了它)。同样,位图根据项目的状态进行渲染。
\n\n // draw non-disabled bitmap.\n if (!disabled)\n {\n bmp.GetBitmap(&bm);\n m_bmWidth = bm.bmWidth;\n imgList.Create(bm.bmWidth, bm.bmWidth, ILC_COLOR24|ILC_MASK, 1, 1);\n imgList.Add(&bmp, COLOR_BITMAP_BACKGROUND);\n\n if (checked)\n {\n if (!selected)\n imgList.DrawEx(pDC, 0, CPoint(4,rect.top+4), CSize(bm.bmWidth, bm.bmWidth), COLOR_NOT_SELECTED, 0, ILD_NORMAL);\n else\n imgList.DrawEx(pDC, 0, CPoint(4,rect.top+4), CSize(bm.bmWidth, bm.bmWidth), 0, COLOR_SELECTED, ILD_SELECTED);\n }\n else\n imgList.DrawEx(pDC, 0, CPoint(4,rect.top+4), CSize(bm.bmWidth, bm.bmWidth), 0, 0, ILD_TRANSPARENT);\n }\n else\n // draw a disabled bitmap.\n AfxDrawGrayBitmap(pDC, 4, rect.top+4, bmp, ::GetSysColor(COLOR_3DFACE));\n
Run Code Online (Sandbox Code Playgroud)\n\n大多数渲染是通过在每次尝试后调整矩形对象的迭代方法来完成的。
\n 归档时间: |
|
查看次数: |
1087 次 |
最近记录: |