热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

致微软:对WPF与Win32互操作焦点控制的Sample质疑

附件1:原MSDN的Sample  附件2:Helloj2ee修改的Sample

本文是讨论WPFWin32互操作的一个MSDNSample。这个Sample似乎有些问题。我写下来也是希望有各位高手能够指点。看看是微软不小心的小错误,还是我HelloJ2ee误打误撞。如果写这个Sample的微软同仁看到了这个例子,还请您多多指教。

 

我和芸芸众生一般,学习微软的技术,当然首当其冲的资料就是MSDN。学习WPFWin32

的互操作。我学习了微软的这个Sample,名为Hosting a Win32 HWND in WPF Sample。诸位可以在本地安装的MSDN里下载到这个例子,也可以在线上下载http://msdn.microsoft.com/zh-cn/library/ms771352.aspx 当然本文提供的第一个附件也是从这上面下载下来的。

这个例子能够很成功的将Win32嵌入在WPF当中。在焦点控制上,预期的结果应该是按下Tab键时。焦点会从111,如此反复循环。

致微软:对WPF与Win32互操作焦点控制的Sample质疑

 

如果你初次尝试,也许能够成功。百分之五十的可能性。为什么说是百分之五十呢,你可以再尝试着按一下Shift键。现在你的情况多半是从1开始到2 再到10,再2 10 焦点甚至无法从Win32窗口出去。如果你也是这种情况,那么到此为止。HelloJ2ee还掌握着真理。

 

那么这个示例的问题出在哪儿呢?初步来看问题如下,下面的代码是示例中重载了TranslateAccelerator的部分代码片断。问题出在第二行。这里原意是希望按下Shift键而且焦点在2号编辑框上,则让焦点回到1号按钮。但是它传递的是FocusNavigationDirection::Last

 

致微软:对WPF与Win32互操作焦点控制的Sample质疑致微软:对WPF与Win32互操作焦点控制的Sample质疑代码
if (GetKeyState(VK_SHIFT) && GetFocus() == firstTabStop) {
                    request 
= gcnew TraversalRequest(FocusNavigationDirection::Last);
                }
                
else if (!GetKeyState(VK_SHIFT) && GetFocus() == lastTabStop) {
                    request 
= gcnew TraversalRequest(FocusNavigationDirection::Next);
                }
                
if (request != nullptr) {
                    
return ((IKeyboardInputSink^)this)->KeyboardInputSite->OnNoMoreTabStops(request);
                }

 

 

 

我们再看下面的一个代码片断,这是示例当中的TabInfo的实现,看到FocusNavigationDirection::Last没有?它会将焦点设置到10Cancel按钮。于是就出现了前面我们说的情况从210 再从210这样反复循环下去。

 

致微软:对WPF与Win32互操作焦点控制的Sample质疑致微软:对WPF与Win32互操作焦点控制的Sample质疑代码
        virtual bool TabInto(TraversalRequest^ request) override {
            
if (request->FocusNavigationDirection == FocusNavigationDirection::Last) {
                HWND lastTabStop 
= GetDlgItem(dialog, IDCANCEL);
                SetFocus(lastTabStop);
            }
            
else {
                HWND firstTabStop 
= GetDlgItem(dialog, IDC_EDIT1);
                SetFocus(firstTabStop);
            }
            
return true;
        }

 

 

需要将前面的代码片断(重载了TranslateAccelerator的部分),

改变成FocusNavigationDirection::Previous,才对。但是这样也不会达到我们设想的预期效果。这一次更为糟糕,如果按一下Shift键。那么会出现这样的情况就是从12 再从21 如此反复循环。当然我说的这种情况,也许你不会出现。那是因为出现这样的情况是%50的可能性。%50的可能性就是在于你是否按下Shift键。

 

注意 我说的按下Shift 不是说一直按着不放 而是按了一下 甚至是无意就按了一下 整个焦点的控制就乱了。

这个程序的焦点控制的本意是不按Shift 只按Tab 焦点从111 这样循环下去。

而按Shift+Tab 焦点就从111 这样循环下去。现在所有的问题就在Shift键上。如果各位还和我一样出现这样的情况。那么真理还在Helloj2ee这边。

 

问题的关键在于GetKeyState(VK_SHIFT)。我在学习这个源码的时候,无意当中发现了这个源码作者的标注了一段话:

// this code should work, but therea bug with interop shift-tab in current builds

 if (GetKeyState(VK_SHIFT) && GetFocus() == firstTabStop) {

 

大致意思也就是说 这个地方Shift+Tab会有bug。那么正好和我发现的问题也是一样的。但是他说这个代码是可以工作的。只不过因为互操作的原因导致有bug。(英文不好不知道理解错否

 

那么我也信了,以为不需要再解决了。但是忍不住看了一下GetKeyState的文档。最关键的是GetKeyState的返回值得注解。如下:

The return value specifies the status of the specified virtual key, as follows:

If the high-order bit is 1, the key is down; otherwise, it is up.

If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.

 

诸位如果E文不好的好,我就勉为其难解释一下,大致的意思就是 这个返回值是一个Short型(两个Byte),那么高位如果是1的话,也就说明按键被按下。反之则没按下。如果低位是1 的话,证明按键是Toggled状态,反之则不是。随后举例说明什么是Toggled状态,比如大写开关,如果按下它就一直是大写。再按一次就恢复原状,就是一个开关一样的作用。

 

于是我又觉得隐约会有些问题。因为这个代码里只是通过判断GetKeyState(VK_SHIFT)返回值是否为0来表示是否按下。那么刚才一系列的症状是不是表示Shift处于Toggled状态呢?

 

于是我只好再将该代码做一次修改,修改后的重载的TranslateAccelerator代码片断如下,这里不是判断GetKeyState是否为0来判断Shift是否按下的。而是直接取其低位来判断Shift是否按下。然后再采取相应的动作。

 

致微软:对WPF与Win32互操作焦点控制的Sample质疑致微软:对WPF与Win32互操作焦点控制的Sample质疑代码
SHORT keystate = GetKeyState(VK_SHIFT);
                BYTE downstate 
= HIBYTE(keystate);
                BYTE togglestate 
= LOBYTE(keystate);
                
if(downstate)
                {
                    
if(GetFocus()==firstTabStop)
                    {
                        request 
= gcnew TraversalRequest(FocusNavigationDirection::Previous);
                    }
                }
                
else
                {
                    
if(GetFocus()==lastTabStop)
                    {
                        request 
= gcnew TraversalRequest(FocusNavigationDirection::Next);
                    }
                }

 

这样的改动下来,无论你是按Tab还是按Shift+Tab都能如你所愿的焦点移动。附件当中加上Helloj2ee的既是我改过的例子。

         这个示例是MSDN当中的一个示例,关于这个例子还有一篇相应的文档对该例子进行了说明,因此发现这个问题我首先是自省,看看是否是自己的错以免误伤了别人。这么晚在这儿发帖 也是把问题暴露出来。看看Helloj2ee是否一不小心还是自己搞错了。如果写这个Sample的微软同仁看到了这个例子,还请您多多指教。

转载于:https://www.cnblogs.com/helloj2ee/archive/2009/12/31/1636532.html


推荐阅读
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Hive常用命令及其用途,包括列出数据表、显示表字段信息、进入数据库、执行select操作、导出数据到csv文件等。同时还涉及了在AndroidManifest.xml中获取meta-data的value值的方法。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • IT方面的论坛太多了,有综合,有专业,有行业,在各个论坛里混了几年,体会颇深,以前是论坛哪里人多 ... [详细]
  • 本文介绍了在Ubuntu下制作deb安装包及离线安装包的方法,通过备份/var/cache/apt/archives文件夹中的安装包,并建立包列表及依赖信息文件,添加本地源,更新源列表,可以在没有网络的情况下更新系统。同时提供了命令示例和资源下载链接。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • GSIOpenSSH PAM_USER 安全绕过漏洞
    漏洞名称:GSI-OpenSSHPAM_USER安全绕过漏洞CNNVD编号:CNNVD-201304-097发布时间:2013-04-09 ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
author-avatar
不懂
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有