CMenu如何绘制:非客户区

凌乱哥 2018-12-10 07:33:27
项目中有个功能菜单一开始是这样的:

有线条和灰色边框,产品部觉得影响整体风格,要求去掉。所以找资料,参考了这篇文章去掉了边框,效果如下:


问题来了:
边框虽然是没了,但是上下级菜单的区域没有重叠区,导致选择语言很难操作。
结合代码对比了之前的效果,发现是去掉边框的时候把非客户区去掉了,菜单的尺寸减小了,导致菜单无法重叠在一起。
所以问问大神,为了解决这个问题,有2个思路,看哪个实现更简单:
1.让下级菜单弹出的时候往上级菜单靠紧一点
2.非客户区不删除,采用自绘非客户区来代替,也就是代码这里该如何修改:

case WM_PRINT: // 此处阻止非客户区地绘制
return CallWindowProc( oldWndProc, hWnd, WM_PRINTCLIENT, wParam, lParam);
//这里如何不return,而转向自绘非客户区

...全文
394 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
猪猪加大码力 2019-05-27
  • 打赏
  • 举报
回复
棒棒的,学到了,感谢感谢
凌乱哥 2018-12-17
  • 打赏
  • 举报
回复
static int g_cxMenu = 0; static int g_xMenu = 0; static bool g_bSubMenu = false;
凌乱哥 2018-12-17
  • 打赏
  • 举报
回复
最终代码: case WM_WINDOWPOSCHANGING: { // 最后,由于我们在MeasureItem里指定了菜单大小,而系统会自动替菜单加边框, // 因此必须去掉此部分额外地尺寸,将菜单大小改小 bool bAdjust = false; LPWINDOWPOS lpPos = (LPWINDOWPOS)lParam; if (lpPos->flags & SWP_NOSIZE) { if (g_bSubMenu && lpPos->x) { if (lpPos->x < g_xMenu) lpPos->x += 10; else if (lpPos->x > g_xMenu) lpPos->x -= 6; g_bSubMenu = false; bAdjust = true; } } if (g_cxMenu && (lpPos->cx) && (lpPos->cx < g_cxMenu)){ g_bSubMenu = true; } else { if (false == bAdjust) { if (lpPos->cx) g_cxMenu = lpPos->cx; if (lpPos->x) g_xMenu = lpPos->x; } } lpPos->cx -= 2 * GetSystemMetrics(SM_CXBORDER) + 4; lpPos->cy -= 2 * GetSystemMetrics(SM_CYBORDER) + 4; lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam); return 0; }
worldy 2018-12-12
  • 打赏
  • 举报
回复
引用 8 楼 凌乱哥 的回复:
问题解决,添加了标红的代码,让上下级菜单重叠了6个像素:

case WM_WINDOWPOSCHANGING:
{
// 最后,由于我们在MeasureItem里指定了菜单大小,而系统会自动替菜单加边框,
// 因此必须去掉此部分额外地尺寸,将菜单大小改小
LPWINDOWPOS lpPos = (LPWINDOWPOS)lParam;

if (lpPos->flags & SWP_NOSIZE){
if (lpPos->x)
lpPos->x -= 6;
}

lpPos->cx -= 2 * GetSystemMetrics(SM_CXBORDER) + 4;
lpPos->cy -= 2 * GetSystemMetrics(SM_CYBORDER) + 4;
lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);
return 0;
}

效果图:
凌乱哥 2018-12-12
  • 打赏
  • 举报
回复
问题解决,添加了标红的代码,让上下级菜单重叠了6个像素: case WM_WINDOWPOSCHANGING: { // 最后,由于我们在MeasureItem里指定了菜单大小,而系统会自动替菜单加边框, // 因此必须去掉此部分额外地尺寸,将菜单大小改小 LPWINDOWPOS lpPos = (LPWINDOWPOS)lParam; if (lpPos->flags & SWP_NOSIZE){ if (lpPos->x) lpPos->x -= 6; } lpPos->cx -= 2 * GetSystemMetrics(SM_CXBORDER) + 4; lpPos->cy -= 2 * GetSystemMetrics(SM_CYBORDER) + 4; lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam); return 0; } 效果图:
凌乱哥 2018-12-12
  • 打赏
  • 举报
回复
引用 5 楼 worldy 的回复:
在子菜单弹出后,能不能马上使用SetFocus之类的命令将焦点转到子菜单上?
不行,CMenu的父类是CObject,没有SetFocus接口
class CMenu : public CObject
凌乱哥 2018-12-11
  • 打赏
  • 举报
回复
引用 1 楼 zgl7903 的回复:
参考下高版本的 CMFCMenu 基于 CWnd 实现的, 想怎么绘制都可以
是CMFCPopupMenu吗
凌乱哥 2018-12-11
  • 打赏
  • 举报
回复
引用 2 楼 worldy 的回复:
没有明白为什么没有非客户区会造成语言选择困难?当弹出下级菜单后,光标设置到语言选择菜单上,不可以吗?
你仔细看修改前后的对比图,因为修改后上下级菜单之间是刚好分开的,没有之前那样的重叠部分,如图:
worldy 2018-12-11
  • 打赏
  • 举报
回复
没有明白为什么没有非客户区会造成语言选择困难?当弹出下级菜单后,光标设置到语言选择菜单上,不可以吗?
worldy 2018-12-11
  • 打赏
  • 举报
回复
在子菜单弹出后,能不能马上使用SetFocus之类的命令将焦点转到子菜单上?
zgl7903 2018-12-10
  • 打赏
  • 举报
回复
参考下高版本的 CMFCMenu 基于 CWnd 实现的, 想怎么绘制都可以

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧