在Windows编程中,我们已经习惯了一个窗体从创建到显示并获得焦点。

我们总感觉一个窗体创建出来获得焦点是理所理所当然的。一个窗体仅仅要显示就必须获得焦点。一个新窗体显示时。会收到到WM_SETFOCUS消息。然后旧的窗体会收到WM_KILLFOCUS消息。可能我们并不关心焦点的切换,由于从视觉角度来看,没有不论什么影响,可是键盘类的消息却在焦点变化时不断切换响应窗体。我们都知道,鼠标消息到来时,决定哪个窗体响应的是鼠标的坐标点。指哪里打哪里。键盘消息到来时,是谁来决定这个消息由哪个窗体响应呢?答案就是焦点。焦点是键盘消息的“舞台”,不论什么一个窗体仅仅要登上焦点这个“舞台”,全部的键盘类消息自然会分配到该窗体的窗体过程函数。

只是话又说回来了,在什么情况下的窗体不须要获得焦点呢?我总结了一下。有两种情况:1.提示类窗体,像我们常见的tooltipWindow,酷狗的音乐列表上的提示窗体,还有我们每天都在使用的QQ,把鼠标移到你的头像上,出现的提示信息窗体,当QQ收到消息时,鼠标指到QQ的任务栏图标上时出现的消息列表提示窗体,等等。当然,你有可能会问了,提示窗体和焦点有什么关系,提示窗体获得焦点又如何?事实上表面上影响不是非常大,可是细致想想这是不符合原生的Window控件机制的,WM_MOUSEMOVE消息仅仅是个过客,键盘消息的“舞台”不能受鼠标移动干扰。比方我们打开QQ正在聊天时,或者正在填写一个比較繁琐的表格时。就晃了晃鼠标,光标没了。是不是非常蛋疼?我们还得又一次找到原来的编辑区,点一下刚才输入的位置让光标又一次出现才干继续输入。提示类窗体的创建和销毁往往是由WM_MOUSEMOVE来控制。所以呢这类窗体不能获得焦点。2.菜单窗体,Windows原生菜单是不获取焦点的,可能你还不信,事实上測试一下非常easy就能看出来。用Visual
Studio建一个带有菜单的Win32项目。在窗体过程函数中捕获WM_KILLFOCUS消息。当菜单弹出时,WM_KILLFOCUS是不会响应的。

这里肯定你还会问,菜单的弹出和焦点有毛关系,谁规定了菜单必须是无焦点的?当然没有人规定这些。可是遵循原生的机制绝对是没错的。首先,在自己使用窗体模拟菜单时,焦点的切换是一个非常大的障碍,当然。有人还利用了这个特性,用WM_KILLFOCUS消息来控制菜单的窗体的销毁,这点在仅仅有一级的菜单中还能体现出优势,可是在做级联菜单时,问题又来了。子菜单出来。主菜单就会失去焦点。这无形其中增添了不少麻烦。各级菜单的耦合度变高,维护起来相当复杂。其次,焦点的不断切换会影响美观,我一提这个,肯定还会有不少人产生疑问。这从何说起啊?焦点在菜单上看不见摸不着,怎么能影响外观?之前有人用Duilib写过一个MenuDemo,应该非常多人都在用,效果看起来也不错。可是我个人认为还是有问题。可能大家也不会把这个当成问题。当鼠标在主菜单上滑行时,子菜单会轮流弹出,假设这时碰巧你在这个窗体的某个编辑里开启输入法输完东西时,输入法的工具框还保留当前窗体,因为子菜单的切换显示。会导致输入法的工具框不断闪烁。我个人感觉是影响美观,不知道大家的看法。原因是因为焦点的切换。导致输入法消息的响应窗体不断切换。从而导致其闪烁。

酷我音乐盒应该大家都用过。假设没猜错的话,用的就是Duilib的MenuDemo来实现的菜单。

你能够试一下。切换成中文在搜索框里输入几个字,然后右击弹出菜单,用鼠标在主菜单上滑行。让子菜单轮流弹出,看看那个输入法工具框是不是在不停闪烁。还有酷我音乐盒的全部提示框都是带焦点的。在菜单弹出时。不得不屏蔽某些控件的MouseHover事件,防止提示框的弹出抢走焦点。导致菜单销毁。

我想这应该是因为Duilib眼下不支持无焦点窗体的原因,为了解决问题。Skilla在Duilib的菜单上花了不少时间,因为网上这方面的资料真心太少了。还好最后有了成果,所以还有机会和大家一起分享。

事实上,弄一个无焦点的窗体还是比較简单的。1.在窗体显示时,使用ShowWindow(SW_SHOWNOACTIVE),这样窗体显示时就不会获得焦点了。可是不能点击,点击完还是会获得焦点。 2.在窗体过程中截获WM_MOUSEACTIVATE消息,返回MA_NOACTIVE,这样就完美了,这时在客户区任凭你把鼠标左键右键全点烂了这个窗体也不会获得焦点。可是不能点标题栏,这也无妨,在Duilib中我们的窗体通常是不带原生标题栏的,把标题栏去掉就是了,这时仅仅要你不主动去SetFocus,窗体是永远不会获得焦点的。

假设仅用Win32或者MFC编程,上面两步就够了。但我们还使用了Duilib框架,关于窗体焦点的控制參与的不不过CWindowWnd。CPaintManagerUI也做了大量的::SetFocus操作,假设不做处理窗体还是照样会获得焦点。

这时我们须要对源代码做一下小小的改动。1.给CPaintManagerUI加入一个布尔类型属性bool m_bUnfocusPaintWindow;来区分所绘制窗体是否为无焦点窗体,在构造时初始化为false。并加入Get、Set方法。让外界能訪问到。2.在CPaintManagerUI的cpp文件里查找全部的::SetFocus操作(注意前面的两个点),给全部的::SetFocus操作加上if(!m_bUnfocusPaintWindow)的推断。这时我们仅须要在将m_bUnfocusPaintWindow设置为true就可以防止CPaintManager抢走焦点。这样既不影响原来的功能,又达到了我们想要的效果。3.为了方便使用在CDialogBuilder的cpp文件的219行加上一个推断

else if(_tcscmp(pstrName, _T("unfocus")) == 0)

                    {

                        if(_tcscmp(pstrName,_T("true")))

                        pManager->SetUnfocusPaintWindow(true);

                    }

这样,我们就能够在xml里面设置窗体是否为无焦点窗体了,仅仅需在Window标签上加一个unfocus="true"的属性就能够了。比如

<Window size="400,240"  caption="0,0,0,40"  roundcorner="5,5" unfocus="true">

这仅仅是无焦点窗体在TipWindow上的应用,关于菜单的实现我会尽快写好Demo来和大家一起分享。

假设大家还有什么不明确的地方。或者对我的改动有什么意见或的法的,能够直接留言,或者联系QQ:848861075(Skilla)

轻轻的我走了,正如我轻轻的来——Duilib无焦点窗体的实现的更多相关文章

  1. shell 4注释

    单行注释 每一行加一个#号. #shell #!/bin/sh echo "#" #轻轻的我走了 #正如我轻轻的来 #我挥一挥衣袖 #不带走一片云彩 echo "#&qu ...

  2. UILabel 常见问题总结

    写在前面:笔者在iOS软件开发中发现UILabel控件有些问题反复出现,所以在这里做点总结,方便自己查阅,也能给大家提供相关问题的解决方案. 一:当label里的内容显示满了的时候,能够自动将字体变小 ...

  3. Learn day1 变量/数据类型

    1.Python 简介 (1) 1989年开发的语言,创始人范罗苏姆(Guido van Rossum),别称:龟叔(Guido). (2) python具有非常多并且强大的第三方库,使得程序开发起来 ...

  4. 新版本MenuDemo——使用Duilib模拟Windows本机菜单

    相信玩Duilib朋友已经开始期待一个很长的文章.由于我的文章在一周前公布--"无焦点窗体的实现"里面提到了无焦点窗体在菜单里面的应用,并承诺大家,写一个关于Menu实现的Demo ...

  5. Markdown

    1. 斜体和粗体 代码: *斜体*或_斜体_ **粗体** ***加粗斜体*** ~~删除线~~ 显示效果: 这是一段斜体 这是一段粗体 这是一段加粗斜体 这是一段删除线 2. 分级标题 第一种写法: ...

  6. TCP同步传送数据示例(简洁、清楚)

    转自:http://www.2cto.com/kf/201206/134841.html 本例子写了个简单的TCP数据传送功能.没有使用BinaryWriter,BinaryReader,而是使用Ne ...

  7. WPF中的Style

    一.Style基础知识 构成Style最重要的两种元素是Setter和Trigger Setter类帮助我们设置控件的静态外观风格 Trigger类帮助我们设置控件的行为风格 Setter类的Prop ...

  8. 分享几个python小脚本

    by 梁凯 今天我想给大家分享几个python脚本,分别是: 1.公司访问外网认证脚本(最初有同事写过,我优化了一下). 2.统计周报系统所有同事的最近一篇周报. 3.统计测试技术分享里指定一个月所有 ...

  9. Markdown几个简单的例子

    定义型列表 语法说明: 定义型列表由名词和解释组成.一行写上定义,紧跟一行写上解释. 解释的写法:紧跟一个缩进(Tab) Markdown : 轻量级文本标记语言,可以转换成html,pdf等格式(左 ...

随机推荐

  1. django-附件上传、media、extra、事务

    1 普通上传 1.1 html <form action="/index/" method="post" enctype="multipart/ ...

  2. MariaDB 10 (MySQL DB) 多主复制并实现读写分离

    ----本文大纲 简介 资源配置 拓扑图 实现过程 ==================== 一.简介 MMM 即Master-Master Replication Manager for MySQL ...

  3. Supported_Hardware#4G_LTE_cards_and_modems

    https://wiki.mikrotik.com/wiki/Supported_Hardware#4G_LTE_cards_and_modems

  4. Android BottomNavigationBar底部导航控制器的使用

    最近Google在自己推出的Material design中增加了Bottom Navigation导航控制.Android一直没有官方的导航控制器,自己实现确实是五花八门,有了这个规定之后,就类似苹 ...

  5. 查看系统自带的RPM

    我在home目录下创建了目录mei 1.管理员权限 su 2.进入mei目录 cd /home/mei 3.创建cdrom目录作为挂载点 mkdir cdrom 4.把目录 /dev/cdrom-hd ...

  6. Code First 数据库的表中属性的配置

      数据类型的约定配置 默认规则 列的数据类型是由数据库决定的,SqlServer的默认规则如下 String: nvarchar(MAX) Int:int Bool:bit Decimal:deci ...

  7. Enterprise Library:Unity的几个注意事项

    背景 在.Net平台中,几乎所有的Ioc容器在注册方面都不一致,使用Unity需要注意几个事项,咱们通过实验进行验证一下. 验证的内容: 集合的获取. 生命周期管理. 实验 代码 1 using Sy ...

  8. [Android Pro] Android7.0系统 关于Android获取流量计数TrafficStats.getUidRxBytes(uid)和TrafficStats.getUidTxBytes(uid)返回-1解决方案

    reference : http://blog.csdn.net/zhangyong7112/article/details/54574214 最近一个关于流量的项目在Android7.0系统的手机上 ...

  9. JavaScript 函数大全

    javascript函数一共可分为五类: ·常规函数 ·数组函数 ·日期函数 ·数学函数 ·字符串函数 1.常规函数 javascript常规函数包括以下9个函数: (1)alert函数:显示一个警告 ...

  10. java获取系统进程号

    public static final int jvmPid() { try { RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean( ...