热门标签 | 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


推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
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社区 版权所有