【转载】CMenu自绘---钩子---去除边框
使用默认的CMenu菜单类或者继承CMenu实现的菜单扩展类,在显示的时候最外层都会有边框出现,或者说是具有3D外观(菜单阴影不算),当改变菜单背景色或者需要加个边框线时就会看上去很不美观。看过很多菜单的自定义实现类,一般可以有两种方式来实现外框的移除。
第一种方法就是:自定义窗口,完全模拟菜单的实现,自给自足,倒是能够完全满足开发需要,不过实现的复杂让人头痛,此处略过不提。
下面介绍第二种比较简单直接的方法:安装钩子,在菜单创建时就改变其窗口属性。其实菜单应该也算是一个窗口类,不过实在是无从得知到底在哪创建的窗口,所以下下钩子,过程倒是明了许多。
实现如下:
先在cpp前面申明一下:
static HHOOK g_hook=NULL; // 全局钩子
static LRESULT WINAPI CallWndProc(int, WPARAM, LPARAM); // 安装的钩子的窗口过程
static LRESULT WINAPI MenuWndProc(HWND, UINT, WPARAM, LPARAM); // 用来处理菜单的窗口过程
然后是钩子的实现:
/
// 如果需要去除菜单的外部边框,需要通过安装钩子,设置外框属性并改变菜单大小
WNDPROC oldWndProc = NULL; // 用来保存被替换的窗口过程
LRESULT WINAPI CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam;
while (code == HC_ACTION)
{
HWND hWnd = pStruct->hwnd;
// 捕捉创建消息WM_CREATE,后面筛选为是否是菜单的创建
if ( pStruct->message != WM_CREATE)
break;
TCHAR sClassName[10];
int Count = ::GetClassName(hWnd, sClassName, sizeof(sClassName)/sizeof(sClassName[0]));
// 检查是否菜单窗口,#32768为菜单类名
if ( Count != 6 || _tcscmp(sClassName, _T("#32768")) != 0 )
break;
WNDPROC lastWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
if (lastWndProc != MenuWndProc)
{
// 替换菜单窗口过程
SetWindowLong(hWnd, GWL_WNDPROC, (long)MenuWndProc);
// 保留原有的窗口过程
oldWndProc = lastWndProc;
}
break;
}
return CallNextHookEx((HHOOK)WH_CALLWNDPROC, code, wParam, lParam);
}
// 处理菜单的窗口过程
LRESULT WINAPI MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult;
switch (message)
{
case WM_CREATE:
{
// 首先要去掉菜单窗口的一些扩展风格
// 包括:WS_BORDER、WS_EX_DLGMODALFRAME、WS_EX_WINDOWEDGE
lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);
DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
DWORD dwNewStyle = (dwStyle & ~WS_BORDER);
::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
DWORD dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
DWORD dwNewExStyle = (dwExStyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE));
::SetWindowLong(hWnd, GWL_EXSTYLE, dwNewExStyle);
return lResult;
}
case WM_PRINT: // 此处阻止非客户区地绘制
return CallWindowProc( oldWndProc, hWnd, WM_PRINTCLIENT, wParam, lParam);
case WM_WINDOWPOSCHANGING:
{
// 最后,由于我们在MeasureItem里指定了菜单大小,而系统会自动替菜单加边框,
// 因此必须去掉此部分额外地尺寸,将菜单大小改小
LPWINDOWPOS lpPos = (LPWINDOWPOS)lParam;
lpPos->cx -= 2*GetSystemMetrics(SM_CXBORDER)+4;
lpPos->cy -= 2*GetSystemMetrics(SM_CYBORDER)+4;
lResult = CallWindowProc(oldWndProc, hWnd, message, wParam, lParam);
return 0;
}
case WM_GETICON:
return 0;
default:
return CallWindowProc( oldWndProc, hWnd, message, wParam, lParam);
}
}
/
最后是调用:
下钩子需要调用SetWindowsHookEx,参数包括主窗口的实例句柄theApp.m_hInstance,可以在调用时作为参数传入,同时也设一个参数作为是否安装钩子的标识,以便在退出时判断是否需要卸载钩子(UnhookWindowsHookEx(g_hook))。示例如下:
void CSkinMenu::RemoveMenuBorder(HINSTANCE hInst, BOOL bRemove /* = TRUE */)
{
m_bRemoveBorder = bRemove; // 标识
// 需要移除边框时,要安装钩子
if (m_bRemoveBorder)
{
DWORD id = ::GetCurrentThreadId(); // 获取当前线程的ID
g_hook = SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,hInst,id);
}
}
这样子,就搞定菜单的边框了,最后要记得,如果安装了钩子,需要卸载掉。
转载于:https://www.cnblogs.com/doudongchun/p/3699700.html
【转载】CMenu自绘---钩子---去除边框相关推荐
- java设置窗体居中与去除边框以及jframe设置背景色
java设置窗体居中的代码如下: public void setWindowCenter(JFrame frame){int windowWidth = frame.getWidth(); //获得窗 ...
- IE7下动态创建Iframe时,去除边框
IE7下动态创建Iframe时,去除边框 2008-09-24 12:04 大家都知道,只要设置Iframe的属性:frameborder="0",Iframe就不显示边框,但是当 ...
- iframe去除边框
iframe去除边框 <iframe name="file_frame" src="UploadFile.jsp" frameborder=no bor ...
- ggplot2画图——点图想要描边但是又需要去除边框
在用ggplot2作点图时,点的颜色默认是由color参数控制的.如下所示: library(ggplot2) ggplot(iris,aes(x=Sepal.Length,y=Sepal.Width ...
- iview Input组件聚焦时会出现边框(去除边框CSS)
去除边框CSS .ivu-input:focus{outline:none;border:none;box-shadow: 0 0 0 2px transparent; }
- WPF去除边框的方法
WPF中,设置AllowsTransparency=true去除边框的方法比较简单,这里不做详细说明.下面主要演示AllowsTransparency=false的时候去除边框的方法. 1.去网上下载 ...
- Vue el-card去除边框——记录一种询问度娘之外的方法
简单介绍下el-card如何把去除边框: #card{background:transparent;position:fixed;background-size:100% 100%;left: 20% ...
- iframe 去除边框 去除滚动条 设置背景透明
iframe去除 边框 和 滚动条其实完全不需要css控制 iframe 标签给我提供了几个很不错的属性设置 src :这个不用说 就是嵌套界面的地址 frameborder :是否需要边框 0不需要 ...
- textarea 去除边框
textarea 去除边框 textarea{ width: 100%; height: 100%; border: ...
最新文章
- 防止sql注入攻击的方法总结
- 34 linux监控平台
- 从任务到可视化,如何理解LSTM网络中的神经元 By 机器之心2017年7月03日 14:29 对人类而言,转写是一件相对容易并且可解释的任务,所以它比较适合用来解释神经网络做了哪些事情,以及神经网
- VTK:非结构化网格之ClipUnstructuredGridWithPlane2
- JS-Object 对象的相关方法
- android 微信支付,body为中文字符,签名错误
- php json获取get请求,PHP简单的Curl的Get请求和Curl的Post请求和file_get_contents的Get请求获取接口JSON数据...
- ARP协议详解,ARP协议执行原理、ARP协议如何根据IP地址寻找Mac地址?
- Libiconv裁剪
- VBA中 各种数据类型的使用(自定义数据类型Type,数组,数据字典)、读写文件
- Ubuntu18.04 32位下载
- 【脑图制作】万彩脑图大师教程 | 修改主题样式
- android 扫描wifi列表重复,Android Settings 出现重复的WIFI SSID,多个相同的WIFI SSID
- MySQL高级篇——锁的概述与案例应用
- 开题报告:基于java多用户商城平台系统 毕业设计论文开题报告模板
- 【多线程与高并发】从一则招聘信息进入多线程的世界
- “PaaS+云管”双剑合璧,BoCloud博云的进阶之路
- 《弗洛伊德及其后继者》学习笔记(part2)--自我心理学
- android app内部打开word pdf .doc类型文件的两种方式
- 李峋同款爱心代码(附源码,前端代码,python代码)