惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - vibration

ATL3.0组件注册bug的解决方法 奇怪的引用错误及解决方法 OLE2T在VS2003中转换中文失败的问题及解决方法 AppBar的WTL实现 招聘C++和C#开发工程师 ATL组件中文路径注册问题(转载) 关于C++模板的连接问题 - vibration - 博客园 用窗口消息解决COM接口的多线程访问问题 用全局接口表实现COM接口在不同线程中的传递 MyMSN支持自定义内容了 自画菜单的WM_MEASUREITEM只会发送一次 悼念皮皮 上了点照片 一个测试记忆力的小游戏 老板该如何向核心员工许诺 ActiveScript SkinX界面换肤框架更新 反射获取定制Attribute Skin技术实现框架(完)
标题栏按钮的WTL实现
vibration · 2005-09-20 · via 博客园 - vibration

起因

上次完成了CAppBar的代码后,就一直想在标题栏的关闭按钮前面加一个按钮,来控制自动隐藏的设置。在标题栏上加按钮并不算特别麻烦,主要是控制WM_NCPAINT,把想要的效果画上去。当然,原理不复杂,要实现的好却不容易。上网搜了一下,有一些简单的例子用来讲述原理,没有找到比较好的实现,更谈不上可复用的代码了,那么只好自己实现了。

原理

首选必须明白原理,想在标题栏上创建CButton这样窗口按钮的努力是徒劳的。标题栏属于Non-Client区域,不能在其上创建子窗口,唯一的方法就是响应WM_NCPAINT消息,通过Window DC画上去,当然,还需要处理一些其他的鼠标消息以得到按钮的效果。这样,实现的思路就和CAppBar差不多了,再创建一个模板类,于是,CCaptionButton<T>就诞生了。 先看看效果

按钮图片

因为是画上去的按钮,我们需要准备一些按钮图片。一个按钮至少需要3个图片来表示3个状态:

  • 正常状态
  • 按下状态
  • 鼠标停留状态

另外,如果需要下面两种额外状态,就需要一共提供5个按钮图片

  • Checked状态
  • Disabled状态

我们通过一个ImageList来组织这些按钮图片。一幅象下面这样的图片资源可以产生一个按钮需要的ImageList,当然也可以通过其他方式实现。

当添加一个标题栏按钮时,我们需要这些按钮图片,参数的类型是HIMAGELIST

添加标题栏按钮

我们需要支持多个标题栏按钮,因此在CCaptionButton类中,通过一个vector来维护所有按钮的信息。具体实现不多说了,就讲怎么使用吧,添加按钮的方法就是:

 int AddButton(UINT uID, int cx, int cy, HIMAGELIST himl, LPCTSTR lpszHint=NULL);

其中,uID是按钮的ID,当按钮被点击时,会有一个WM_COMMAND消息发送给窗口,uID为参数。因此,处理标题栏按钮点击的方法和处理普通按钮完全相同。cx和cy定义了按钮的宽度和高度,这个尺寸必须和按钮图片相符。himl则包含了3-5幅图片,表示按钮不同状态下的样子。最后,lpszHint是按钮的tooltip提示文字。

控制按钮位置

加入的按钮显示在标题栏的什么地方呢?自动控制按钮的位置似乎是一个可重用的类应该完成的任务。在类的实现中,我尝试自动计算标题栏上的空白区域,让我们添加的标题栏按钮靠窗口右边已有按钮排列。然而,我发现,由于存在许多不同的窗口样式,如是否有最小化按钮,是否有问号按钮,是否窄标题栏(即ToolWindow),自动计算很容易产生错误。不如让继承类来决定如何排放按钮位置。因此,提供了下面这个函数供继承类重载:

 POINT GetButtonPos(int index);

CCaptionButton为这个函数提供了一个默认的实现,但是,这个实现比较简单,只有在窗口为ToolWindow,并且没有任何系统按钮的情况下才能正常显示。通过重载GetButtonPos函数,实际上我们得到了比自动计算强的多的功能,即我们可以在任意位置显示按钮,甚至可以控制按钮水平或者垂直排列,就象例子程序中看到的那样。

使用方法

总结一下使用方法

  • 把CCaptionButton作为一个父类继承
  • 使用CHAIN_MSG_MAP把消息传递到CCaptionButton类
  • 调用AddButton函数添加一个或多个按钮
  • 重载GetButtonPos函数提供每个按钮的显示位置
  • 处理标题栏按钮产生的Command消息
  • 可以调用CheckButton改变按钮的Check状态
  • 可以调用EnableButton改变按钮的Enable状态

示例程序

示例程序中使用了5个标题按钮,并配合使用了CAppBar类,以实现桌面停靠的功能。5个标题按钮的排列使用了普通方式和垂直排列的方式,通过继承GetButtonPos函数实现。其中图钉按钮控制AppBar窗口的自动隐藏设置;其他4个按钮使窗口停靠到桌面的一边;并且把停靠到底部的按钮设置成Disabled,可以看到不同的效果

下载示例程序