这篇博客呢,主要谈谈在实现电子签名功能中踩过的几个坑:1.System.BadImageFormatException异常;2.无法加载DLL“###.dll”,: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E);3.wpf获取控件句柄。

如果你想了解如何在wpf中使用InkCanvas实现一个类似于签名板(涂鸦板系列)的功能,请参考我的上一篇博客

再扯点题外话,写这篇博客的很大一部分原因是InkCanvas版本的签名板被否决了。究其原因呢,是这个签名板将用于触摸屏上的用户签名,而InkCanvas版本在触摸屏上手写签名的体验可以用糟糕来形容。所以呢,最终采用了另一个解决方案:调用一个C++的dll(这个dll是公司提供的,而且有WinForm版的Demo,我只需要正确的“搬砖”就好了),通过电子签名笔来完成签名。

闲话扯完了,现在我们来聊聊那几个问题:

1.System.BadImageFormatException异常

这个异常是我在尝试编译WinForm版Demo的时候触发的,网上搜索了一下,在一篇博客中找到了原因——目标程序的目标平台与某一依赖项的目标编译平台不一致。于是我将相关工程的目标平台都更改为x86,问题就解决了。下方提供一个修改目标平台的示例:

大致修改过程:在工程上右键 => 属性 => 编译 => 目标平台

2.无法加载DLL“###.dll”,: 找不到指定的模块

隐约记得很久以前遇上过这个问题,但忘了具体怎么处理的了。所以上网搜索了一下,关于这个问题的帖子不少,但都大同小异……大体上都说将dll手动拷贝到项目文件夹中bin目录下;将dll拷贝到system32目录下;还有一个感觉看起来十分高大上的解决方法,个人就没什么兴趣看了。拜托!在我的记忆中,这不应该是件很麻烦的事情啊,而且现在的VS这么强大,还需要手动去搞这种事情??最终决定自己摸索,也终于找到了解决方法。

相信到这里各位都看出问题了吧——dll的Copy to Output Directory(复制到输出目录)这一项默认选的是永不复制!!搞骚,吓得我赶紧修改成Copy if newer(如果更新就会重新复制一份到输出目录,如果你想选始终复制Copy always我也不拦着),然后这个问题就没有然后了。当然,有可能我遇上的问题比较简单,这个解决方案可能对某些情况不适用,各位可以在博客下方留言,我们一起讨论。

3. wpf获取控件句柄

由于在调用C++的dll完成签名板功能时,需要把签名板的句柄作为参数传递过去,所以我在此把这个地方拿出来谈一谈。

网上关于wpf获取控件句柄的帖子也不少,但恕我直言,大都是在扯淡~

比如说下方截图:

容我先按照这个方法测试一票:

我们发现,这两个方法拿到的句柄一毛一样……

听老司机说,wpf的控件是画出来的,不会为每个控件分配句柄,所以通过这个方法拿到的所谓的控件的句柄,实际上是整个窗体的句柄。而我们的需求是要切切实实的拿到对应控件的句柄,所以,就只能想办法借助winform了。

接下来,我们来看看具体步骤:

1)添加两个引用(System.Windows.Forms 和 WindowsFormsIntegration)

为了相对快速找到这两个库,我搜索了关键字“windows”

2)XAML

A.引入命名空间

xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"

B.控件调用

<wfi:WindowsFormsHost Width="500" Height="240" Background="White">
<wf:Panel x:Name="panelSignature"/>
</wfi:WindowsFormsHost>

C.说明

a.有细心的童鞋会发现,WindowsFormHost的前方不必使用WindowsFormsIntegration对应的名称(我给的名称是wfi,各位请随意)进行限制,XAML中只导入System.Windows.Forms的命名空间也是可以的,但为了更清楚WindowsFormHost的来历(在哪个程序集的哪个命名空间下),我比较推荐将命名空间导入的写法。

b.可能有童鞋在添加引用之后就着手于Xaml的编码工作,然后发现VS不能正确的进行智能提示。我建议添加引用后Build(编译)一下,以便让编译器知道已经导入了新的dll,而后智能提示就可以正常运作了。

3)逻辑代码

var hwnd = panelSignature.Handle;

WinForm这边获取控件的句柄是很简单的,就这么一行代码就可以了。看看效果:

嗯~不一样,不一样就对了O(∩_∩)O

4.扯淡时间

完成签名板这个任务花了两天时间,第一天写出了InkCanvas版本,第二天完成了目前公司采用的这个版本。先来张测试截图:

有童鞋可能会问:怎么不写“测试”二字,亦或是“Hello World”……我表示当时完成这个功能的时候相当激动,颤抖的手握着电子签字笔就写下这么一行,然后截图发给心目中的女神了……那天晚上离开公司的时候大雨瓢泼,我的心头却晴空万里(●'◡'●)

最后祝各位劳动节快乐,相信每一份努力都不会被辜负!!

【WPF】学习笔记(二)——依旧是一个电子签名板的更多相关文章

  1. WPF学习笔记二 依赖属性实现原理及性能分析

    在这里讨论依赖属性实现原理,目的只是学习WPF是怎么设计依赖属性的,同时更好的使用依赖属性. 首先我们来思考一个简单的问题:我们希望能验证属性的值是否有效,属性变更时进行自己的处理.回顾一下.net的 ...

  2. Struts2学习笔记(二):第一个Struts2应用

    一.创建Action类. 创建工程Struts2Demo struts 2中的Action类并不需要继承struts 2中的某个父类,普遍的java类就可以. 在org.sunny.user.acti ...

  3. WPF学习笔记二之依赖属性

    1.快捷生成依赖属性:propdp然后按两次tab键 2.应用场景:自定义控件 什么是依赖属性:依赖属性自己没有值,通过依赖别人(如Binding)来获得值. 依赖属性为什么会出现:控件常用字段有限, ...

  4. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  5. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  6. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  7. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  8. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  9. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

随机推荐

  1. [笔记]LR和SVM的相同和不同

    之前一篇博客中介绍了Logistics Regression的理论原理:http://www.cnblogs.com/bentuwuying/p/6616680.html. 在大大小小的面试过程中,经 ...

  2. jsp页面中从forEach里向action里面传递其中的一个对象

    <c:forEach var="user" items="${users }"> <form action="user_update ...

  3. signedCookies

    var express = require('../') , request = require('supertest') , cookieParser = require('cookie-parse ...

  4. RegExp类型(正则表达式)

    直接量语法 /pattern/attributes 创建 RegExp 对象的语法: new RegExp(pattern, attributes); 一.attributes: 修饰符 描述 i 执 ...

  5. JavaScript高级程序设计---学习笔记(一)

    今天,2017.3.17开始利用课余时间仔细学习<JavaScript高级程序设计>,将需要掌握的知识点记录下来,争取把书里的所有代码敲一遍并掌握. 1.标识符命名最好是第一个字母小写,剩 ...

  6. c++学习笔记之封装篇(上)

    title: c++学习笔记之封装篇(上) date: 2017-03-12 18:59:01 tags: [c++,c,封装,类] categories: [学习,程序员,c/c++] --- 一. ...

  7. MCMC(一)蒙特卡罗方法

    MCMC(一)蒙特卡罗方法 MCMC(二)马尔科夫链(待填坑) MCMC(三)M-H采样和Gibbs采样(待填坑) 作为一种随机采样方法,马尔科夫链蒙特卡罗(Markov Chain Monte Ca ...

  8. 直接在CMake项目中编译GoogleTest和GoogleMock作为项目的一部分

    直接在CMake项目中编译GoogleTest和GoogleMock作为项目的一部分 本文是关于如何将GoogleTest和GoogleMock在没有预先编译安装在机器的情况下,直接在项目中作为项目的 ...

  9. 使用VSCode 断点调试 js项目,html页面

    一.效果目的 1.在VSCode里,直接F5打开html页面,并且可以在编辑器里,进行断点调试js代码: 二.工具准备 1.VSCode 软件 2.一个js项目 3.VSCode 上装一个插件:Deb ...

  10. Android 瘦身之道 ---- so文件

    Android 瘦身之道 ---- so文件 [TOC] 1. 前言 目前Android 瘦身只有几个方面可以入手,因为apk的结构就已经固定了. res 目录下的资源文件.(通常是压缩图片,比如 矢 ...