這篇博客呢,主要談談在實現電子簽名功能中踩過的幾個坑: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”……我表示當時完成這個功能的時候相當激動,顫抖的手握着電子簽字筆就寫下這么一行,然后截圖發給心目中的女神了……那天晚上離開公司的時候大雨瓢潑,我的心頭卻晴空萬里(●'◡'●)
最后祝各位勞動節快樂,相信每一份努力都不會被辜負!!