久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

Microsoft .NET Compact Framework 开发常见问题解答

發布時間:2025/4/16 asp.net 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Microsoft .NET Compact Framework 开发常见问题解答 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這個 FAQ 有部分是通過編輯公共
.NET Compact Framework 新聞組 (microsoft.public.dotnet.framework.compactframework) 貼出的問題和解答而得到的。.NET Compact Framework 團隊衷心感謝參加公共新聞組的每個人,感謝他們對本 FAQ 和整個 .NET Compact Framework 開發社區做出的貢獻。

要想獲得 FAQ 項,請將電子郵件發送到
netcfaq@microsoft.com。

本頁內容
1. 開發
2. 圖形
3. 部署
4. 圖形用戶界面 (GUI):窗體
5. 圖形用戶界面 (GUI):常規
6. 互操作性和本機代碼
7. 常規
8. 通信和 Web 服務
9. SQL CE 和數據
10. 其他信息
11. 連接
12. 基于 Windows Mobile 的 Smartphone

1. 開發

1.1. 什么是 Microsoft .NET Compact Framework?

Microsoft .NET Compact Framework 是針對 Microsoft .NET 計劃的智能設備開發框架,是實現 Microsoft 隨時隨地在任何設備上為客戶提供良好體驗的目標的關鍵所在。.NET Compact Framework 將托管代碼和 Web 服務帶給了智能設備,它允許安全的、可下載的應用程序在諸如個人數字助理 (PDA)、移動電話和機頂盒等設備上運行。


http://msdn.microsoft.com/mobility/prodtechinfo/devtools/netcf/overview/default.aspx

1.2.開發 .NET Compact Framework 應用程序需要什么工具?

Visual Studio .NET 為基于 Windows Mobile 的 Pocket PC 2000、基于 Windows Mobile 的 Pocket PC 2002 和 Windows CE .NET 4.1 設備開發基于 .NET Compact Framework 的應用程序需要 2003 Professional 或更高版本。Visual Studio .NET 2003 附帶了 .NET Compact Framework。


http://msdn.microsoft.com/mobility/prodtechinfo/devtools/vstudio/default.aspx

在最新的 Windows Mobile 平臺上進行開發還有其他的 SDK 可用:

Windows Mobile 2003 Pocket PC SDK:
http://www.microsoft.com/downloads/details.aspx?familyid=9996b314-0364-4623-9ede-0b5fbb133652&displaylang=en

Windows Mobile 2003 Smartphone SDK:
http://www.microsoft.com/downloads/details.aspx?familyid=a6c4f799-ec5c-427c-807c-4c0f96765a81&displaylang=en

本文將提供用 .NET Compact Framework 1.0 和 Visual Studio .NET 2003 開發健壯的智能客戶端設備應用程序的說明。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfgetstarted.asp

1.3. 哪里可以下載最新的工具和軟件?

Visual Studio .NET 2003 試用版可以通過以下地址獲得:
http://msdn.microsoft.com/vstudio/productinfo/trial/default.aspx

最新的平臺更新和 .NET Compact Framework service pack 可以通過以下地址獲得:
http://msdn.microsoft.com/mobility/downloads/default.aspx

1.4. .NET Compact Framework 支持什么設備?

.NET Compact Framework 支持基于 Windows Mobile 2000 的 Pocket PC、基于 Windows Mobile 2002 的 Pocket PC、基于 Windows Mobile 2003 的 Pocket PC、基于 Windows Mobile 的 Smartphone 和運行 Windows CE .NET 4.1 及更高版本的嵌入式系統。

1.5. 以后 .NET Compact Framework 將會支持什么設備?

不久以后,.NET Compact Framework 將會作為一個操作系統 (OS) 組件,在所有的 Microsoft 智能設備中提供,包括將來基于 Windows Mobile 的 Pocket PC 設備、基于 Windows Mobile 的 Pocket PC Phone Edition、基于 Windows Mobile 的 Smartphone、Windows CE for Automotive 和 MSTV。每種特定設備的具體時間選擇將由各個產品發布周期確定。

Windows CE .NET 4.1 也支持 .NET Compact Framework,將其作為一個集成的 OS 組件,因此允許 OEM 使用 Platform Builder 工具將 .NET Compact Framework 嵌入到所有裝備 Windows CE 的新設備中。

1.6. 調試器在與模擬器建立連接時為什么會失敗(錯誤啟動應用程序)?

以下鏈接是針對調試的安裝和疑難解答指南:
http://download.microsoft.com/download/c/d/b/cdbff573-73fb-4f9f-a464-c5adc890e1ae/Readme.htm

1.7. .NET Framework 和 .NET Compact Framework 之間有什么區別?

請參見下面 .NET Framework 和 .NET Compact Framework 之間的比較:
http://msdn.microsoft.com/library/en-us/dv_evtuv/html/etconComparisonsWithNETFramework.asp

.NET Compact Framework 類庫比較工具中的信息:
http://msdn.microsoft.com/library/en-us/dv_spchk/html/NET_Compact_Framework.htm

1.8.最新的 .NET Compact Framework Service Pack 有什么新內容?

.NET Compact Framework SP2 提供了針對大量缺陷的補丁。補丁列表可由以下鏈接獲得:
http://www.microsoft.com/downloads/details.aspx?familyid=10600643-09b3-46d8-ba28-bc494bc20d26&displaylang=en

.NET Compact Framework SP1 提供了針對大量缺陷的補丁。補丁列表可由以下鏈接獲得:
http://www.microsoft.com/downloads/details.aspx?familyid=1f62a2a3-7282-4ba9-b26b-2267e972501d&displaylang=en

注: Service Pack 2 (SP2) 替代了 Service Pack 1 (SP1),它包括所有 service pack 的最新更新。

1.9. 在 .NET Compact Framework 開發中,基于 Windows Mobile 的 Pocket PC 和 Windows CE .NET 之間有什么區別?

這篇文章概述了為基于 Windows Mobile 的 Pocket PC 和 Microsoft Windows CE .NET 平臺開發基于 Microsoft .NET Compact Framework 的應用程序之間的區別。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfPPCtoCE.asp

1.10. 在哪里可以找到有關如何創建基于 .NET Compact Framework 的應用程序的更多信息?

下列資源有助于您了解如何創建基于 .NET Compact Framework 的應用程序:

?

.NET Compact Framework 快速入門
http://samples.gotdotnet.com/quickstart/compactframework/

?

MSDN 移動與嵌入式技術開發人員中心中的 .NET Compact Framework 白皮書:
http://msdn.microsoft.com/mobility/understanding/articles/default.aspx

1.11. .NET Compact Framework 的文檔在什么位置?


http://msdn.microsoft.com/library/en-us/dv_evtuv/html/etconNETCompactFramework.asp

1.12. 如何指定在每次調試器運行時不必復制依賴文件?

在 Visual Studio .NET 2003 中,右鍵單擊該項目并選擇 Properties。將 Build Action 更改為 None。這樣就不會再復制此文件了。如果此文件已修改或者需要再復制,則將 Build Action 更改為 Content。

1.13. 如何設置模擬器屬性?

在 Visual Studio .NET 2003 中,從菜單中選擇 Tools->Options。然后打開 Device Tools 文件夾并選擇 Devices?,F在應該能看到一個顯示設備選擇列表的對話框。選擇您想要修改的設備,然后按 Configure 按鈕。

現在您應該能夠看到一個含有幾個選項卡的對話框,它允許您訪問和修改設置,例如內存和屏幕大小。

1.14. 如何調試 Microsoft .NET Compact Framework 應用程序?

Microsoft .NET Compact Framework 完全集成在 Visual Studio .NET 2003 中,它支持的調試功能與對其他 Visual Studio .NET 應用程序類型可用的調試功能相同。但是,在獨立設備或在仿真器中調試運行的應用程序時,用戶需要注意一些特殊事項。請參考下列建議以獲得最詳盡的 .NET Compact Framework 調試體驗:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/CompactFXDebug.asp

1.15. 如何開始使用 Visual Basic .NET 為設備開發應用程序?

了解如何使用用于 Visual Studio .NET 的智能設備擴展 (SDE) 來為支持 .NET Compact Framework 的智能設備構建 Windows 應用程序。這篇文章包括對整個開發、調試和部署過程的檢查,并探討了 .NET Framework 和 .NET Compact Framework 之間的區別。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/sdeforvb.asp

1.16. 如何將 .NET Compact Framework 程序集安裝到全局程序集緩存 (GAC) 中?


http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOGAC.asp

1.17. 當通過 Visual Studio .NET 2003 部署智能設備應用程序時,如何處理“共享沖突”?

這篇文章闡述了阻止通過 Visual Studio .NET 2003 部署應用程序的共享沖突產生的原因,并介紹了解決這一沖突的方法。
http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOSharingviolation.asp

1.18. 公共語言運行庫 (CLR) 是什么?

.NET Compact Framework 提供了一個名為公共語言運行庫的運行時環境,它運行代碼并提供一些可以使開發過程更加輕松的服務。在這篇概述中可以了解更多內容:
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcommonlanguageruntimeoverview.asp

1.19. 全局程序集緩存 (GAC) 是什么?

每臺安裝公共語言運行庫的計算機都有一個機器范圍的代碼緩存,稱為全局程序集緩存。全局程序集緩存中存儲的程序集是專門由計算機中的幾個應用程序共享的程序集。這篇文章提供了有關 GAC 的更多信息:
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconglobalassemblycache.asp

1.20. 在 .NET Compact Framework 中如何管理內存?

自動內存管理是在托管執行過程中 CLR 提供的服務之一。CLR 垃圾回收器管理應用程序的內存分配和釋放,如這篇文章所描述的:
http://msdn.microsoft.com/library/en-us/cpguide/html/cpconautomaticmemorymanagement.asp

1.21. 當網絡協議數超過 50 時,為什么就無法部署到設備?

請參見本 FAQ 中標題為“11.4.當網絡協議數超過 50 時,為什么無法部署到設備?”的項。

1.22. 為什么有跨平臺二進制?

.NET Compact Framework 和執行引擎是完整的 .NET Framework 和 CLR 的一個兼容子集實現。當不存在強名稱綁定策略時,針對 .NET Compact Framework 編譯的應用程序將會綁定和運行在整個 .NET Framework 上,但有一些重要的例外:

?

.NET Compact Framework 程序集由不同的強名稱密鑰對進行簽名,這樣 CLR 可以將它們與其全部 .NET 副本區分開來。

?

將 來發布的完整的 .NET Framework 和 CLR 將包括綁定策略,它可以將完整的 .NET Framework 程序集替換為兼容 .NET Compact Framework 引用。然后在一些常見的情況中,它可以重復使用現有的組件而不需要重新鏈接。例如,如果您的組件只引用 .NET Compact Framework System 和 System.NET 類,則它可以在 .NET Compact Framework 和整個 .NET Framework 上很好地運行而不需要重新鏈接。

?

如果您的引用功能與 .NET Compact Framework 不同,例如基于 Windows Mobile 的 Pocket PC 特定的 UI 控件,則您的程序將會在與整個 .NET Framework 綁定時失敗。

?

就像跨平臺二進制兼容性簡化了中間件組件的開發和部署一樣,Microsoft 相信胖客戶端應用程序應該利用特定于設備的功能來提高用戶體驗。這意味著最好的 GUI 代碼可能是特定于目標的。

?

雖 然 Microsoft 已經做出了很大的努力,將特定于設備的功能分解為離散的命名空間和程序集以避免綁定沖突,但可能存在版本 1 無法處理的不兼容分解的情況。在這些情況下,在整個 .NET Framework 中濫用特定于設備的功能將會引發運行時異常而非應用程序加載異常。

1.23. 所有這些 ARM 二進制是些什么?

XScale 支持 ARM v5 指令集,不過它也向后兼容 ARMv4 指令集。它有三個變種:

?

ARMv4 -> 它只支持 32 位 ARMv4 指令

?

ARMv4T ->“T”代表 Thumb。Thumb 是 ARM 16 位指令模式

?

ARMv4I ->“I”代表交互作用 (Interworking)。它允許 32 位指令和 16 位指令共存

對于其他的 ARM 處理器:

?

StrongARM (SA1110) -> 只支持 ARMv4 指令

?

ARM920T 等 -> 通常支持這三個變種

.NET Compact Framework 將提供三組用于 ARM 的二進制。

?

用 于基于 Windows Mobile 2000 和基于 Windows Mobile 2002 的 Pocket PC 2002 的 ARMv4。它將運行 ARM 設備(包括 Xscale)的所有 ARM。部署到這些設備中的 cab 只能在名稱中包含“arm”。

?

用 于 Windows CE.NET 的 ARMv4。它將運行在通過 Platform Builder 中的 ARMv4 內核編譯的 Windows CE.NET 設備中。它也是用于基于 Windows Mobile 的 Pocket PC 2003 的二進制。為這些設備部署的 cab 在名稱中包含“armv4”。

?

用 于 Windows CE.NET 的 ARMv4T 或 ARMv4I。它將運行在通過 Platform builder 中的 ARMv4T 或 ARMv4I 內核編譯的 Windows CE.NET 設備中。部署到這些設備中的 cab 在名稱中包含“armv4T”。

1.24. 如何寫入設備的注冊表中?

Visual Studio .NET 沒有附帶用于 Windows CE 的遠程注冊表編輯器。要設置注冊表項,可以使用以下工具之一:

?

Microsoft Embedded Visual Tools Remote Registry Editor

?

Microsoft Windows CE Platform Builder Remote Registry Editor

?

基于 PHM Windows Mobile 的 Pocket PC Registry Editor(共享件,可以很容易在網上找到)

1.25. 安裝完成后如何防止 .CAB 文件被刪除?

將 .CAB 文件的屬性設置為只讀,可以防止 .CAB 文件被自動刪除。

1.26. 如何確定設備中安裝的 .NET Compact Framework 的版本?

發行的每個 .NET Compact Framework 版本都有一個不同的 Win32 文件版本號(它是與程序集版本相獨立的版本號,對于發行的所有 .NET Compact Framework 第一版(包括 Service Pack),這兩者應該是一樣的)。

要查看安裝的是什么版本,可以使用文件資源管理器,定位于設備的 "Windows 目錄,并單擊名為 CGACUTIL 的文件。將會彈出一個消息框,顯示安裝在設備中的 .NET Compact Framework 的 Win32 文件版本。

RTM = 1.0.2268.0SP1 = 1.0.3111.0SP2 Recall = 1.0.3226.0SP2 Beta = 1.0.3227.0SP2 Final = 1.0.3316.0

要以編程方式確定版本,可以使用 System.Environment.Version.ToString()。

要通過桌面安裝程序確定版本,請參見本 FAQ 中標題為“3.10.如何通過桌面安裝程序檢測 .NET Compact Framework 的版本?”的項。

1.27. 如何將文件復制到模擬器中?

一種方式是在開發 PC 中創建一個文件共享,然后通過模擬器中的文件資源管理器連接到該共享。也可以將文件從共享位置復制并粘貼到模擬器的本地文件系統中。另一種方式是將文件添 加到智能設備項目中,并將它們的 Build Action 屬性設置為“Content”。有關“文件屬性”的更多信息,請參閱 Visual Studio .NET 聯機文檔:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbconfileproperties.asp

以下內容逐步介紹了如何將一個“Content”文件添加到智能設備項目中:

1.

打開或創建一個智能設備項目,

2.

在“View”菜單中,單擊“Solution Explorer”,

3.

在“Solution Explorer”中,右鍵單擊您的項目,指向“Add”并單擊“Add Existing Item”。瀏覽至想要的文件并添加到該項目中。

4.

在“Solution Explorer”中,右鍵單擊添加的文件并單擊“Properties”,

5.

如果 Build Action 屬性尚未設置,則將它設置為“Content”。

1.28. 為什么基于 Windows Mobile 的 Pocket PC 2002 SDK 安裝失敗?

表現:在“注冊組件”時,基于 Windows Mobile 的 Pocket PC 2002 SDK 安裝程序掛起。

原因: 在嘗試運行模擬器時,未注冊的組件導致安裝掛起。

解決辦法: 在控制臺窗口提示中鍵入:cd "WINNT"system32regsvr32 atl.dll

1.29. 如何調試智能設備應用程序使用的 Web 服務?

您需要將調試器附加到 ASP.NET 輔助進程中。

有關更多信息,請參見以下鏈接:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtskdebugginganaspdeployedwebapplication.asp

1.30. 什么是 .NET Compact Framework 的足跡?

.NET Compact Framework 存儲大小:

?

在基于 Windows Mobile 的 Pocket PC 2000/2002 上有 1.55MB (ROM)

?

在用于 Pocket PC 2003 或 Windows CE .NET 設備的 Windows Mobile 上有 1.35MB (ROM)

運行 RAM 的要求:

?

.5 MB+(取決于應用程序)

典型的應用程序大小:

?

5 - 100 KB

1.31. 如何將 imgdecmp.dll 包括在模擬器映像中?

您必須讓 OEM 將它包括在設備的映像中。如果您就是 OEM 而且您正在使用 Platform Builder 4.2,則包括 .NET 項目的 OS 依賴項會自動使 imgdecmp.dll 成為模擬器映像的一部分 — 如果這樣不行則再引用 cesysgen.bat。另一種方法是設置環境變量“__SYSGEN_IMGDECMP=1”,顯式強制該 DLL 包含在映像中。

1.32. 如何以編程方式替換全局程序集緩存 (GAC) 中的程序集?

可以通過以編程方式啟動 cgacutil 來直接在 GAC 中安裝程序集和從 GAC 中刪除程序集。

?

使用 -u 選項可以從 GAC 刪除程序集

?

使用 -i 選項可以在 GAC 中安裝程序集

通常最安全的做法是重新安裝一個程序集之前先將它刪除。

1.33. 如何在臺式計算機或便攜式計算機中顯示基于 Windows Mobile 的 Pocket PC 應用程序而不需要任何設備端配置?

從 Windows Mobile Developer Power Toys 下載 ActiveSync Remote Display:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

1.34. 如何使 Activesync 能夠從 Visual Studio .NET 2003 連接到模擬器會話?

請參見本 FAQ 中標題為“11.17.如何使 Activesync 能夠從 Visual Studio .NET 2003 連接到模擬器會話?”的項。

1.35. 如何將文件復制到當前連接到桌面 ActiveSync 的設備中?

請參見本 FAQ 中標題為“11.18.如何將文件復制到當前連接到桌面 ActiveSync 的設備中?”的項。

1.36. 如何重點測試用戶輸入?

從 Windows Mobile Developer Power Toys 下載 Hopper:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

1.37. 從哪里可以獲得平臺生成器目標控件窗口的 UI 版本?

從 Windows Mobile Developer Power Toys 下載 Jshell:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

1.38. 從哪里可以獲得用于基于 Windows Mobile 的 Pocket PC 2003 設備的命令外殼?

從 Windows Mobile Developer Power Toys 下載 PPC 命令外殼:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

1.39. 如何獲得當前運行進程的詳細信息?

從 Windows Mobile Developer Power Toys 下載 RAPI Debug:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

1.40. 如何從桌面遠程啟動基于 Windows Mobile 的 Pocket PC 上的應用程序?

從 Windows Mobile Developer Power Toys 下載 RAPI Start:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

1.41. 為什么不能加載具有相同名稱的不同程序集?

這是設計的原因。您要么必須更改 DLL 的名稱,或者如果 DLL 具有強名稱,則將它們放在 GAC 中并使用具有完全強名稱的 Assembly.Load。

1.42. 如何強制 Visual Studio .NET 2003 連接到較新版本的基于 Windows Mobile 的 Pocket PC 2003 模擬器?

從 Windows Mobile Developer Power Toys 下載 Emulator ActiveSync Connection Tool:
http://www.microsoft.com/downloads/details.aspx?familyid=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

它允許 ActiveSync 通過 Visual Studio .NET 2003 連接到您的模擬器會話。為 4.2 模擬器創建一個 ActiveSync 會話,它可以使 Visual Studio 2003 將其視為一個真正的設備(選擇 PPC 設備作為部署目標)。

1.43. 為什么我的自定義控件不能正確地顯示在工具箱中?

當在 Visual Studio .NET 2003 中為智能設備自定義控件添加設計器支持時,您可能會碰到以下問題:

?

在設計時無法將一個圖標與控件相關,以便顯示在工具箱中

?

當添加到工具箱中時,該組件變灰

原因

?

使用獨立于控件項目的設計項目。Visual Studio .NET 自動將項目的默認命名空間作為位圖的名稱。“默認命名空間”默認為項目名稱。這可能會產生問題,因為設計項目的名稱與運行時項目的名稱略有差別。

?

沒有設置正確的 ToolBoxItemFilterAttribute 值

解決方案

提供以下示例:Runtime VS.NET Project:MyProject類名稱:MyProject.MyClass設計 VS.NET 項目名稱:MyProject.DesignVS.NET 設計項目中的 BitMap 名稱:Foo.bmp設計程序集中的位圖名稱:MyProject.Design.MyClass.bmp— 這樣會產生問題,因為該位圖需要以下名稱:MyProject.MyClass.bmp

在以上示例中,將設計項目的默認命名空間設置為“MyProject”而非“MyProject.Design”就可以解決這個問題。

檢查程序集中位圖名稱的最簡單方法是運行 ILDASM 并打開 Manifest。該清單的尾部列出了嵌入式資源。

如果您創建了一個從 Component 類派生的自定義組件,則您的代碼必須包括以下語句,這樣您的組件才能出現在工具箱中:

ToolBoxItemFilterAttribute("NETCF",ToolBoxItemFilterType.Require)
ToolBoxItemFilterAttribute("System.CF.Windows.Forms", ToolBoxITemFilterType.Custom)
返回頁首

2. 圖形

2.1. 如何創建 Graphics 對象?

圖形對象根據其用途有幾種創建方式:

通過 OnPaint,使用 PaintEventArgs 中提供的對象:

//C#

protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawLine(...);
}

'VB

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
e.Graphics.DrawLine(...)
End Sub 'OnPaint

通過代碼中的其他區域,該函數是 Control 的一個方法,可以用來創建任何控件的圖形對象:

//C#

using System.Drawing;
Graphics g = this.CreateGraphics();

'VB

Imports System.Drawing
Dim g As Graphics = Me.CreateGraphics()

直接在一個位圖中繪制:

//C#

using System.Drawing;
Bitmap bm = new Bitmap(10,10);
Graphics g = Graphics.FromImage(bm);

'VB

Imports System.Drawing
Dim bm As New Bitmap(10, 10)
Dim g As Graphics = Graphics.FromImage(bm)

2.2. 可以怎樣優化 GDI+ 呈現?

當使用 Graphics 繪畫調用時,有幾種基本的編碼實踐可以幫助提高繪畫速度:

?

只創建一個 Graphics 對象(或者使用來自 OnPaint 中的 PaintEventArgs 的 Graphics 對象)。

?

在屏幕外的位圖中完成所有繪畫,然后拖曳該位圖,使它一次全部顯示出來。

?

只重畫圖像的更改部分。

?

盡可能使繪制的源和目的大小相同(不要拉伸等等)。

也許最重要的實踐是保留需要重畫的項目的痕跡以便使出現的繪畫量盡可能少。例如,如果拖曳光標跨過圖像,就不需要重畫整個圖像。相反,只需重畫前一個光標位置覆蓋的圖像部分。

2.3. 如何在窗體中繪制圖像?

此示例顯示了如何將一個圖形作為窗體的背景圖像顯示:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/bkgndimage.aspx

2.4. 如何繪制具有透明度的圖像?

繪制有透明度的圖像需要一個指定透明顏色的 ImageAttributes 對象。當前,.NET Compact Framework 支持單種顏色的原色調透明度。雖然 SetColorKey 函數允許一個顏色范圍,但最小和最大的顏色必須相同,否則會產生運行時 ArgumentException:

//C#

using System.Drawing.Imaging;
ImageAttributes attr = new ImageAttributes();

'VB

Imports System.Drawing.Imaging
Dim attr As New ImageAttributes()

以下代碼演示了如何根據圖像的左上像素設置透明色調。

//C#

attr.SetColorKey(bmp.GetPixel(0,0), bmp.GetPixel(0,0));

'VB

attr.SetColorKey(bmp.GetPixel(0,0), bmp.GetPixel(0,0))

也可以按照如下所述方法顯式設置顏色:

//C#

attr.SetColorKey(Color.FromA#ff00ff,Color.FromA#ff00ff);
attr.SetColorKey(Color.Fuchsia, Color.Fuchsia);

'VB

attr.SetColorKey(Color.FromA#ff00ff,Color.FromA#ff00ff)
attr.SetColorKey(Color.Fuchsia, Color.Fuchsia)

然后可以用重載的 Graphics.DrawImage 函數(它將 ImageAttributes 對象作為一個參數)來繪制圖像:

//C#

Rectangle dstRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
g.DrawImage(bmp, dstRect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attr);

'VB

Dim dstRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
g.DrawImage(bmp, dstRect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, attr)

2.5. 當我在 TextBox 中調用 CreateGraphics 時它為什么會失敗?

只有 Control 和 Form 類支持 Control.CreateGraphics()。

2.6. 如何確定文本的屏幕大小?

使用 Graphics 方法 MeasureString。以下代碼演示了如何在一些文本周圍繪制一個框:

//C#

using System.Drawing;
protected override void OnPaint(PaintEventArgs e)
{
string s = "Hello World"
Pen pen = new Pen(Color.Fuchsia);
Font font = new Font("Arial", 18, FontStyle.Regular);
Brush brush = new SolidBrush(Color.Black);
SizeF sSize = e.Graphics.MeasureString(s, font);
Rectangle r = new Rectangle(9, 199,(int)sSize.Width + 1, (int)sSize.Height + 1);
e.Graphics.DrawRectangle(pen, r);
e.Graphics.DrawString(s, font, brush, 10.0f, 200.0f);
base.OnPaint (e);
}

'VB

Imports System.Drawing
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim s As String = "Hello World"
Dim pen As New Pen(Color.Fuchsia)
Dim font As New Font("Arial", 18, FontStyle.Regular)
Dim brush = New SolidBrush(Color.Black)
Dim sSize As SizeF = e.Graphics.MeasureString(s, font)
Dim r As New Rectangle(9, 199, Fix(sSize.Width) + 1, Fix(sSize.Height) + 1)
e.Graphics.DrawRectangle(pen, r)
e.Graphics.DrawString(s, font, brush, 10F, 200F)
MyBase.OnPaint(e)
End Sub 'OnPaint

2.7. 可以設置畫筆的寬度嗎?

.NET Compact Framework 中不可以設置畫筆寬度。有一些替代辦法,包括:

?

采用 Graphics.FillRectangle 方法繪制實心矩形

?

繪制多條并行線

?

采用 GAPI 編寫自定義圖形例程

2.8. 如何縮放圖像?

雖然沒有對縮放和拉伸單個圖像的內在支持,但這些效果也可以很輕松地實現,方法是使用相關的 Graphics 對象創建新的 Bitmap 對象,然后將原有 Bitmap 想要的部分復制到新建對象上。以下示例創建了兩個大小相同的位圖,其中第二個位圖包含第一個位圖經放大的中心部分,并假定項目有一個名為 MyImage.bmp 的嵌入式資源。這樣的技術也可以用來拉伸圖像,方法是修改源和目的矩形以便它們沒有保留其原有的縱橫比。

//C#

using System.Drawing;
using System.Reflection;
Bitmap m_bmpOriginal;
Bitmap m_bmpZoom;
private void Form1_Load(object sender, System.EventArgs e)
{
Assembly asm = Assembly.GetExecutingAssembly();
m_bmpOriginal = new Bitmap(asm.GetManifestResourceStream(asm.GetName().Name
+ ".MyImage.bmp"));
// Take the center quarter of m_bmpOriginal
// and create stetch it into m_bmpZoom of the same size
m_bmpZoom = new Bitmap(m_bmpOriginal.Width, m_bmpOriginal.Height);
Graphics gZoom = Graphics.FromImage(m_bmpZoom);
Rectangle srcRect = new Rectangle(m_bmpOriginal.Width / 4, m_bmpOriginal.Height / 4,
m_bmpOriginal.Width / 2, m_bmpOriginal.Height / 2);
Rectangle dstRect = new Rectangle(0, 0, m_bmpZoom.Width, m_bmpZoom.Height);
gZoom.DrawImage(m_bmpOriginal, dstRect, srcRect, GraphicsUnit.Pixel);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(m_bmpOriginal, 0, 0);
e.Graphics.DrawImage(m_bmpZoom, 125, 0);
base.OnPaint (e);
}

'VB

Imports System.Drawing
Imports System.Reflection
Private m_bmpOriginal As Bitmap
Private m_bmpZoom As Bitmap
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim asm As [Assembly] = [Assembly].GetExecutingAssembly()
m_bmpOriginal = New Bitmap(asm.GetManifestResourceStream((asm.GetName().Name _
+ ".MyImage.bmp")))
' Take the center quarter of m_bmpOriginal
' and create stetch it into m_bmpZoom of the same size
m_bmpZoom = New Bitmap(m_bmpOriginal.Width, m_bmpOriginal.Height)
Dim gZoom As Graphics = Graphics.FromImage(m_bmpZoom)
Dim srcRect As New Rectangle(m_bmpOriginal.Width / 4, m_bmpOriginal.Height / 4, _
m_bmpOriginal.Width / 2, m_bmpOriginal.Height / 2)
Dim dstRect As New Rectangle(0, 0, m_bmpZoom.Width, m_bmpZoom.Height)
gZoom.DrawImage(m_bmpOriginal, dstRect, srcRect, GraphicsUnit.Pixel)
End Sub 'Form1_Load
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
e.Graphics.DrawImage(m_bmpOriginal, 0, 0)
e.Graphics.DrawImage(m_bmpZoom, 125, 0)
MyBase.OnPaint(e)
End Sub 'OnPaint

2.9. 為什么我不能加載圖像?

確保 imgdecmp.dll 位于設備的 Windows 目錄。

有關更多信息,請參見本 FAQ 中的主題“ HYPERLINK "l "1.31" 1.31.如何將 imgdemp.dll 包括在模擬器映像中?”。

2.10. 如何使用 GAPI 創建圖形引擎?

這篇文章描述了如何創建包裝 GAPI (Game API) 的 DLL,使之與 .NET Compact Framework 兼容,并用它來創建和優化托管代碼中的基本圖形庫。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI1.asp

這篇文章實現了位圖的加載和顯示,從而擴展了“Dancing Rectangles”示例。它還實現了一些更高級的功能,例如動畫位圖、源和目的色調透明和 alpha 值混合處理(也就是半透明)。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI2.asp

這篇文章實現了點、線和從 8 位位圖轉換而來的自定義 1 位字體的繪制,從而擴展了“Dancing Zombies”示例。它還實現了一個重寫硬件按鈕功能和跟蹤按鈕狀態的輸入系統。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI3.asp

返回頁首

3. 部署

3.1. 如何創建基于 Windows Mobile 的 Pocket PC 安裝應用程序?

這篇文章介紹了如何創建一個 .msi 文件,它可以從桌面運行,并在其他基于 Windows Mobile 的 Pocket PC 設備上安裝應用程序。此開發過程是自動化的,所以它可以輕松地構建所有必需的組件并將其包裝在 .msi 文件中。這篇文章提供了 C# 和 Microsoft Visual Basic .NET 的示例代碼。


http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdeployment.asp

3.2. 應用程序安裝中可以包括哪些可重新發布的文件?

您可以將最終用戶可重新發布的文件隨應用程序提供給您的客戶,以便幫助他們更新設備。您不應該解開最終用戶可重新發布的文件并將其中的內容發送給您的客戶。不過您可以解開開發人員可重新發布的文件并將其中的內容發送給您的客戶。

.NET Compact Framework 可重新發布的包可以在這里下載:
http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

3.3. 如何在桌面上創建不需要 .NET Framework 的安裝程序?

創建 INF 文件

基于 Windows Mobile 的 Pocket PC 安裝程序的主要組件之一是 INF 文件。此文件描述了需要復制哪些文件以及需要為不同的目標平臺創建哪些注冊表項。

此 INF 文件是一個文本文件,它分成幾節。每節都有一個節頭,位于方括號中,它可以有幾個僅與特定目標硬件類型相關的子節。

只要有子節,子節的優先級就高于父節,所以如果一個值在節及其子節中都進行了設置,則會使用子節中的值?;谶@個原因,應該將共享設置放在父節中,而將特定于每個硬件配置的設置放在子節中。

請按照以下步驟創建 INF 文件:

?

在 [Version] 節中,將 Provider 值設置為您公司的名稱。

?

在 [CEStrings] 節中,將. AppName 和 CompanyName 變量設置為應用程序名稱和公司名稱(不帶空格)。

?

在 [Strings] 節中,您可能不需要進行任何更改,但要注意不同的 CPU 類型。

?

在 [DefaultInstall] 節中,列出應該調用的不同節,方法是將 CopyFiles、AddReg 和 CEShortcuts 值設置為不同的節名。如果有多個節,節名間應該以逗號分隔。

?

在 [SourceDiskFiles] 節中,列出要從 [SourceDiskNames] 節復制的各個文件和相應的編號。應該將這些編號看作是組編號,而非物理磁盤編號。通常文件是按類型分組的,例如“聲音文件”、“圖形文件”、“數據庫文 件”等等,但如何分組由您決定。

?

在 [DestinationDirs] 節中,為 [SourceDiskFiles] 節中的每種文件類型指定一個目標目錄。請注意,有一些預定義的變量可供您使用,例如 CE1(指定的目標目錄)和 CE2(WINDOWS 目錄),所以指定諸如“%CE1%"Database”這樣的目錄將會在用戶安裝時選擇的目錄下創建一個子目錄。

?

為 [DefaultInstall] 節的 CopyFiles 變量中的每一項創建節(名稱必須嚴格匹配,所以要檢查再檢查)。在每一節中,指定文件的名稱及用于復制文件的屬性。屬性可以在 eMbedded Visual Tools 文檔中找到。

?

為 [DefaultInstall] 節的 RegSettings 變量中的每一項創建節。

?

為 [DefaultInstall] 節的 Shortcuts 變量中的每一項創建節。%CE17% 預定義變量表示 "WINDOWS"Start Menu 目錄。

創建 CAB 文件

Cabinet 文件是高度壓縮的文件,由包括在 eMbedded Visual Tools 中的 CABWIZ 實用工具構建。

CABWIZ 實用工具具有以下形式:

CABWIZ [/err ] /cpu

/cpu 參數后面的每一項將創建一個文件名為 YOURAPP.CPUTYPE.CAB 的獨立 CAB 文件。每個 CAB 文件只包含壓縮文件和用于匹配設備類型的設置。

創建 INI 文件

客戶的個人計算機并沒有讀取 CAB 文件的內容;它只是將適當的 CAB 文件復制到基于 Windows Mobile 的 Pocket PC 中,然后由后者讀取該 CAB 文件并使用 WCELOAD.EXE 應用程序提取內容。在這臺個人計算機中,有一個名為 CEAPPMGR.EXE 的實用工具,它協調設備的安裝、將設備類型與每個可用的 CAB 文件類型相匹配、將 CAB 文件發送到設備,并調用基于 Windows Mobile 的 Pocket PC 設備中的 WCELOAD.EXE 應用程序。

請注意,可以指定多個 INI 文件,這樣將安裝多個組件。這將允許使用基于 Windows Mobile 的 Pocket PC 中的 Remove Programs(位于“System”選項卡的 Settings 下)來刪除個別組件。

小結

一旦您使用 CAB 文件、SETUP.INI 文件和一個 SETUP.EXE 文件來調用 CE Application Manager,您只需將這些文件放在光盤、磁盤或 ZIP 文件中,將它們分發給您的客戶。理解獲取這些文件的所需步驟可能會占用您第一次安裝的大量時間,但以后的安裝將會很快,因為您只需更改任何前面安裝的源文 件中的少量值即可。

3.4. 如何創建與基于 Windows Mobile 的 Pocket PC 平臺無關的 CAB 文件?

您可以創建一個 .inf 文件,用它生成適合在任何基于 Windows Mobile 的 Pocket PC 設備上安裝應用程序的 CAB 文件。具體做法請參見這個示例:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/cabfile.aspx

3.5. 為什么每種處理器類型都有不同的 CAB 文件?

每個 CAB 都包含一個小型本機可執行文件,它在設備中執行框架依賴項檢測。此實用工具特定于處理器/平臺,每種處理器類型都必須有單獨的 CAB。

3.6. 如何創建一個桌面安裝程序來檢測目標設備中是否存在 .NET Compact Framework,并在需要時安裝它?

MSDN Library 中標題為“Creating an MSI Package that Detects and Updates the .NET Compact Framework”的文章描述了一種可能會用到的技術:
http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull=/library/en-us/dnnetcomp/html/netcfdepl.asp

3.7. 如何將 .NET Compact Framework Service Pack 部署到模擬器中?

從以下地址下載“Developer”版本的 service pack 并安裝到您的桌面開發 PC 中(下載的標題如下所示:“Microsoft? .NET Compact Framework 1.0 SPx Developer Redistributable”)
http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

然后將適當的 .NET Compact Framework cab 文件復制到模擬器中(按照下一段)。在模擬器中通過 File Explorer 指向 PC 中的一個共享,然后將該 cab 復制并粘貼到模擬器文件系統中的某個位置。現在從 File Explorer 啟動該 cab 文件,如果詢問是否覆蓋所有項,則回答“是”。

模擬器CAB 文件

Windows Mobile 2002 for Pocket PC

netcf.core.ppc3.x86.cab

Windows Mobile 2003 for Pocket PC

netcf.core.wce4.x86.cab

Windows Mobile 2003 for Smartphone

不支持 RAM 安裝

3.8. 如何將 SQL Server CE 包含在我的應用程序安裝中?

要隨一個應用程序安裝 SQL Server CE,只需將恰當的 SQL Server CE CAB 文件作為應用程序安裝的一部分加以安裝。有兩組與 SQL Server CE 相關的 cab。

開發人員 CAB 包括查詢分析器和錯誤字符串。此 CAB 不應該包括在應用程序部署中。它包含在兩個實際的文件中,一個用于基于 Windows Mobile 的 Pocket PC,一個用于 Windows CE 4.x 設備:

sqlce.dev.ppc3..cabsqlce.dev.wce4..cab

SQL Server CE CAB,它包括引擎、客戶端代理和托管擴展,因為利用 System.Data.SqlServerCe 組件的應用程序需要客戶端代理。此 CAB 也包含在兩個實際的文件中,一個用于基于 Windows Mobile 的 Pocket PC,一個用于 Windows CE 4.x 設備:

sqlce.ppc3..cabsqlce.wce4..cab

訪問 SQL Server 的應用程序,也就是利用 System.Data.SqlClient 組件的應用程序應該部署該“sql”CAB。此 CAB 也包含在兩個實際的文件中,一個用于基于 Windows Mobile 的 Pocket PC,一個用于 Windows CE 4.x 設備:

sql.ppc3..cabsql.wce4..cab

所有這些 CAB 都包含在 Visual Studio .NET 2003 Professional Edtion 安裝中。默認位置為:

"Program Files"Microsoft Visual Studio .NET 2003"CompactFrameworkSDK"v1.0.5000"Windows CE"...

3.9. 如何在啟動時運行我的應用程序?

?

在 "Windows"Startup 中安裝應用程序的快捷方式

?

在 HKLM"Init 中添加一個注冊表項

?

P/Invoke CeRunAppAtEvent

3.10. 如何通過桌面安裝程序檢測 .NET Compact Framework 的版本?

請參考文章“Creating an MSI Package that Detects and Updates the .NET Compact Framework”:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdepl.asp

具體為:

檢測 Microsoft .NET Compact Framework您需要創建一個 .dll,它可以作為自定義操作從 MSI 文件調用。

首先使用 CeRapiInitEx 連接到設備。

使用 CeFindAllFiles 搜索設備的 Windows 目錄中是否存在 GAC_mscorlib_*.dll。如果存在,則設備中已經安裝了某種風格的 .NET Compact Framework。

查詢設備注冊表并枚舉 HKLM"SOFTWARE"Microsoft".NETCompactFramework 中的值。您應該找到表示現有 .NET Compact Framework 的內部版本的注冊表項。(比如 1.0.2268.00:REG_DWORD:0)。此版本是由所有 .cab 安裝創建的,并包含在以后所有 ROM 安裝中。最初 ROM 安裝的 RTM .NET Compact Framework 缺少這一項,所以如果您沒有找到它,就假定它的值為 1.0.2268.0。

有關版本號的更多信息,請參見本 FAQ 中標題為“1.26.如何確定設備中安裝的 .NET Compact Framework 的版本”的項。

返回頁首

4. 圖形用戶界面 (GUI):窗體

4.1. 如何創建全屏窗體?

您需要將 WindowState 屬性設置為 Maximized。要創建“不可見”窗體,如同在窗體中的一個全屏圖像,您還需要將 FormBorderStyle 設置為 None、關閉 ControlBox,并刪除窗體中的任何菜單實例。

//C#

this.WindowState = FormWindowState.Maximized;
this.FormBorderStyle = FormBorderStyle.None;
this.ControlBox = false;
this.Menu = null;

'VB

Me.WindowState = FormWindowState.Maximized
Me.FormBorderStyle = FormBorderStyle.None
Me.ControlBox = False
Me.Menu = Nothing

4.2. 何時應該使用窗體構造函數,何時應該使用 Load 函數?

對于任何涉及 UI 的窗體,最好使用窗體的 load 函數。在構造函數中加載和創建數據和控件的實例通常是安全的。然而,任何涉及 UI 元素的控件或窗體的初始化都應該在 load 函數中完成。例如,在構造函數中創建控件的實例并添加到窗體中是安全的,但控件位置的設置就應該在 load 函數中完成。

4.3.如何將智能最小化按鈕替換為關閉按鈕?

將窗口風格轉換為關閉而非智能最小化可以通過 IDE 中的設計器屬性來完成,或者以編程方式完成。(x) 按鈕將應用程序智能最小化,而 (ok) 按鈕則將其關閉。

通過設計器轉換窗口風格的方法是:在 Visual Studio IDE 中,打開窗體設計器,查看 Properties。右鍵單擊窗體并選擇 Properties。在 Window Style 節中,將 MinimizeBox 設置為 False

在代碼中轉換窗口風格的方法是:只需將以下的代碼行添加到窗體的 load 函數中:

//C#

this.MinimizeBox = false;

'VB

Me.MinimizeBox = False

4.4. 如何創建適用于 .NET Compact Framework 的 Multiple Form Application Framework?

這篇文章討論了如何為您的基于 .NET Compact Framework 的應用程序創建有效的用戶界面引擎:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfuiframework.asp

4.5. 如何提高基于 .NET Compact Framework 的應用程序窗體加載性能?

了解如何通過這些簡單的優化技術降低 .NET Compact Framework Windows 窗體應用程序加載所需要的時間:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfimproveformloadperf.asp

4.6. 如何在運行時修改窗體風格?

這個快速入門描述了一些代碼語句,它們用于更改基于 Windows Mobile 的 Pocket PC 應用程序中的窗體的外觀和行為:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/ppcformproperties.aspx

4.7. 如何滾動窗體內容?

這個快速入門介紹了如何使用水平和垂直滾動條控件來滾動和下拉窗體中的圖像:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/scrolling.aspx

4.8. 如何生成浮動窗體?它看起來像是窗體始終全屏顯示。

具有邊框的頂級窗體始終全屏顯示,不能移動和調整大小。無邊框窗體或子窗體可以移動和調整大小。

使用:Form.BorderStyle = BorderStyle.None;

4.9.如何強制一個窗體保持最小化?

請參閱本 FAQ 中的主題“6.6.如何強制一個窗體保持最小化?”。

4.10. 我有一個含有許多控件的智能設備窗體。為什么會在運行時得到“NotSupportedException”?

如果您有一個含有許多控件的窗體,當您運行應用程序時可能會得到 NotSupportedException。如果您在調試器下運行,則可能會發現異常是由調用窗體構造函數中的 InitializeComponent() 引發的。您最可能遇到的一個事實是 Compact Framework CLR 硬性限制每個方法只有 64KB JITed 代碼。這意味著當 CLR 將 IL 轉換為方法(在本例中為 InitializeComponent 方法)時,產生的本機代碼必須少于 64KB。如果產生的本機代碼大于此值,則會引發 NotSupportedException。也可能出現的情況是,當在調試器下運行(例如通過 F5)時會看到異常,但不帶調試器運行(通過 Ctrl-F5)時不會有異常。當 JITed 代碼的大小非常接近于 64KB 限制時就會出現這種情況,因為調試器在運行時需要生成其他一些代碼。

也可能出現的情況是,在設備中會產生這種異常,但在模擬器中不會(或反之),因為處理器家族之間 JITed 代碼的大小有所不同(例如,許多基于 Windows Mobile 的 Pocket PC 設備使用 ARM 指令,而模擬器使用 x86 指令)。

超出此限制之前,窗體中可含有的控件數并沒有一個固定的值。這是因為設計器生成的代碼量因控件而異。例如,Button 控件通常生成的代碼少于 TabControl 生成的代碼,這取決于控件屬性的設置方式。如果您通過屬性網格中的生成器為控件填充集合,則擁有集合的控件(比如 ListBox 或 TreeView 控件)會生成大量代碼。另外,本地化窗體(其 Localizable 屬性設置為 True)中控件生成的代碼會比非本地化窗體多,因為 InitializeComponent 中生成的代碼會根據來自資源文件的值設置屬性,而不是使用硬編碼的值。

如果您碰到這種問題,有幾種不同的技術可以使用:

?

將一個窗體分割成多個窗體。將大量控件放在一個窗體中對窗體加載和應用程序啟動時間也有不利的影響。如果可能,要將 UI 分在兩個或更多的窗體中。

?

不 要通過設計時生成器填充大的內部控件集合。例如,如果您在 TreeView 控件的 Nodes 集合中添加許多節點,就會在 InitializeComponent 方法中額外添加大量代碼。如果可能,應該移動這些代碼,使集合填充到構造函數或 Form.Load 事件處理程序中。這種技術的缺點是集合將無法很容易地通過設計器編輯,但有助于調整生成代碼的大小。

?

不 要將自己的代碼添加到 InitializeComponent 方法中。這通常是一個很好的指導原則,因為在這個方法中修改或添加由設計器生成的代碼是不受支持的。這樣做也會導致設計器中出現意外行為。如果您要將自己 的自定義啟動代碼添加到窗體中,就應該將它放在構造函數或 Form.Load 事件處理程序中。

?

在 運行時以編程方式初始化類似的控件。例如,如果您創建了 12 個 Button 控件,它們只有 Text 和 Position 屬性不同,則您可以考慮通過一個循環來創建和初始化,而不是讓這 12 個控件都在設計器生成的代碼中創建和初始化。另外,如果您自己編寫代碼實現,不要將代碼放在 InitializeComponent 中。

修改 InitializeComponent 的一個令人遺憾的負面影響是:在 InitializeComponent 外的代碼中實例化的任何控件都無法使用窗體設計器編輯。另外,如果您手動編輯 InitializeComponent 中的代碼,則會發現設計器可能無法正確解釋您修改過的代碼,從而不再呈現窗體?;谶@些原因,最好選擇上面列出的不修改 InitializeComponent 的解決辦法。

4.11. 哪種關閉窗體的方法更合適:Application.Exit 還是 Form.Close?

Application.Exit 是一種強行退出方式,就像 Win32 的 PostQuitMessage()。它意味著放棄所有消息泵,展開調用堆棧,并將執行返回給系統。

在 Windows(Win32 或 .NET)中關閉應用程序的正確方式是關閉它的主應用程序窗口(例如 Form.Close)。主消息泵結束后依然存在的任何窗口都需要手動關閉。在應用程序退出之前通過調用 Form.Close 或 Form.Dispose 來關閉窗口是清除窗口的良好做法,但這需要您有意識地去做。我們需要記住,.NET Framework 的 OnClosing() 是 Win32 的托管版本的 WM_CLOSE,而非 WM_DESTROY。

另外,如果您使用 form.Close(),通過處理 OnClosing 或 OnClosed 事件,就可以讓您的應用程序清理內容、關閉文件等。如果您通過 Application.Exit 強行退出應用程序,就無法調用這些事件。

4.12. 為什么會在用于 Smartphone 的 Windows Mobile 2003 中顯示一個消息框,它含有 Abort、Retry 和 Fail 組合按鈕或 Yes、No、Cancel 組合按鈕,或者因為默認按鈕導致 NotSupportedException 而有第三種按鈕?

用于 Smartphone 的 Windows Mobile 2003 只支持有 1 個或 2 個按鈕的消息框。

4.13 如何獲得基于 Windows Mobile 的 Pocket PC 開始菜單中最近使用過的 (MRU) 列表中的一個圖標?

為您的應用程序創建一個快捷方式,放在 "windows"start menu"programs 中的某個位置。當通過這個快捷方式啟動您的應用程序時,它的圖標就會出現在 MRU 列表中。

4.14 如何將一個窗體放在屏幕中央?

要顯示一個非全屏窗體,請確保窗體的 FormBorderStyle 屬性設置為 FormBorderStyle.None。要使窗體位于中央,請將以下代碼添加到窗體的 FormLoad 事件處理程序中:將 FormBorderStyle 設置為 FormBorderStyle.None,然后:

//c#

Rectangle screen = Screen.PrimaryScreen.Bounds;
this.Location = new Point((screen.Width - this.Width) / 2,
(screen.Height - this.Height ) / 2);

'VB

Dim theScreen As Rectangle
theScreen = Screen.PrimaryScreen.Bounds()
Me.Location = New Point((theScreen.Width - Me.Width) / 2, _
(theScreen.Height - Me.Height) / 2)

4.15 為什么我不能顯示一個已經關閉了的窗體?

一旦一個窗體關閉,它就會被處置,因此可能被系統回收垃圾,所以試圖顯示已關閉的窗體是不安全的。一種替代的解決方案是使用 Form.Hide 和 Form.Show 來分別隱藏和顯示窗體。

4.16 如何啟用一個應用程序的多個實例?

.NET Compact Framework 不支持多實例。以下代碼示例提供了一種解決方案,它允許當啟動應用程序時(但是已有一個運行著的實例)實例化而非最大化應用程序。

注:并非所有版本的 OS(包括未來版本)都支持以下代碼,也不保證在所有這些版本中都能工作。

// C#

using System.Runtime.InteropServices;
using System.Reflection;
private void Form1_Load(object sender, System.EventArgs e)
{
this.Text = string.Format("Form {0}", new Random().Next());
}
[DllImport("CoreDll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("CoreDll")]
public static extern int SetWindowText(IntPtr hWnd, string lpString);
protected override void OnResize(EventArgs e)
{
Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
IntPtr hWnd = FindWindow("#NETCF_AGL_PARK_",
asm.GetModules()[0].FullyQualifiedName);
if (hWnd != IntPtr.Zero)
SetWindowText(hWnd, "#42");
base.OnResize (e);
}
'VB
Imports System.Runtime.InteropServices
Imports System.Reflection
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = String.Format("Form {0}", New Random().Next())
End Sub 'Form1_Load
_
Public Shared Function FindWindow(ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
_
Public Shared Function SetWindowText(ByVal hWnd As IntPtr, _
ByVal lpString As String) As Integer
End Function
Protected Overrides Sub OnResize(ByVal e As EventArgs)
Dim asm As [Assembly] = System.Reflection.Assembly.GetExecutingAssembly()
Dim hWnd As IntPtr = FindWindow("#NETCF_AGL_PARK_", _
asm.GetModules()(0).FullyQualifiedName)
If hWnd.ToInt32() <> IntPtr.Zero.ToInt32() Then
SetWindowText(hWnd, "#42")
End If
MyBase.OnResize(e)
End Sub 'OnResize
返回頁首

5. 圖形用戶界面 (GUI):常規

5.1. 如何創建圖像按鈕或多行文本按鈕?

創建圖像按鈕或多行文本按鈕需要一個自定義控件。自定義控件可以用必需的自定義數據來進行按鈕的繪制。有關創建自定義控件的更多信息,請參見以下鏈接:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/customctrlscompactfx.asp

這個快速入門描述了如何創建圖像按鈕:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/picturebutton.aspx

5.2. TextBox.AcceptsReturn 如何在 .NET Compact Framework 中工作?

雖然您可以將 AcceptsReturn 設置為 false,但它始終是按 true 來操作的。如果您想用 ENTER 鍵來激活特定按鈕,您可以從 TextBox 派生一個類,當 KeyPress 事件發生時,提供 ENTER 的事件處理代碼。

5.3. 當數據加載到 ComboBox 中時,為什么沒有觸發 SelectedIndexChanged 事件?

這是一個已知的問題,將在 .NET Compact Framework 今后的版本中解決。

5.4. Show 和 ShowDialog 之間有什么區別?

ShowDialog 以模式方式顯示窗體,這意味著它是一個模塊化的函數調用,只有當窗體關閉時才返回。此方法返回一個 DialogResult 枚舉類型,它指明關閉情況。

Show 是一個顯示控件的非模塊化函數,它會立即返回而且沒有返回結果。顯示控件等同于將 Visible 屬性設置為 true。當調用 Show 方法后,Visible 屬性會返回 true 值直到 Hide 方法被調用。

5.5. 為什么我不能創建 ContextMenu 分隔符?

這是一個已知的 bug,即當在 ContextMenu 控件中添加一個 ContextMenu 項后,將它設為分隔符就會引發 NotSupportedException。問題在于 WinCE 有一個限制,即當 ContextMenu 的父級是一個控件時,向該 ContextMenu 添加一個菜單項后就不允許將該菜單項標記(更改)為分隔符。在 Visual Studio 2003 中,設計器分割設備項目的代碼與在桌面上類似,都會產生這種問題。可以這樣來解決:在一個獨立于 InitilizeComponent 的方法中添加 ContextMenu。

5.6. 當我在運行時向 ToolBar 分配一個 ImageList 時,為什么圖像沒有顯示?

您可以將 ImageList 分配給 ToolBar,通常在窗體的 load 函數中進行,但要確保再次應用 ToolBar 按鈕的圖像索引。在本機 ToolBar 控件中,不支持在設置 ToolBar 的 ImageList 之前設置 ToolBar 按鈕的圖像索引。

5.7. 如何設置等待光標?

這是將光標更改為等待光標的代碼:

//C#

Cursor.Current = Cursors.WaitCursor;

'VB

Cursor.Current = Cursors.WaitCursor

這是將光標重新更改為默認光標的代碼:

//C#

Cursor.Current = Cursors.Default;

'VB

Cursor.Current = Cursors.Default

5.8. 如何在菜單項中顯示“and”符 (&)?

.NET Compact Framework 當前不支持這種能力。使用“&&”不會在菜單項的文本中出現“and”符。

5.9. 如何創建基于 Microsoft .NET Compact Framework 的動畫控件?

這篇文章將向您介紹如何構建基于 .NET Compact Framework 的動畫控件:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/animationcontrol.asp

5.10. 如何為 .NET Compact Framework 創建自定義控件?

了解如何為 .NET Compact Framework 創建控件會提高您在 .NET Framework 中創建控件的能力。這篇文章還包括一個創建自定義控件的代碼示例:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/customctrlscompactfx.asp

5.11. 如何創建基于 Microsoft .NET Compact Framework 的圖像按鈕?

這篇文章討論了創建基于 .NET Compact Framework 的圖像按鈕的方法:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/ImageButton.asp

5.12. 如何使用 Microsoft .NET Compact Framework MessageWindow 類?

了解如何使用 .NET Compact Framework MessageWindow 類來創建 NotifyIcon:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/messagewindow.asp

鼠標指針單擊定義為 Rectangle 結構的自定義控件時,或者當鼠標單擊 Panel 控件時,這個快速入門使用 MessageWindow 來向窗體發送消息:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/messagewindow.aspx

5.13. 如何向 DataGrid 添加行和列?

這個快速入門介紹了如何在運行時向 DataGrid 控件添加或刪除行和列:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridadding.aspx

5.14. 如何在 DataGrid 中實現單元格編輯?

.NET Compact Framework 中的 DataGrid 控件提供了完整的 .NET Framework 中的 DataGrid 控件的幾乎全部功能。.NET Compact Framework 版本的 DataGrid 的一個主要區別在于它無法在運行時在 DataGrid 中編輯單元格。這個快速入門介紹了一種以編程方式編輯單元格的方法:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridediting.aspx

5.15. 如何設置 DataGrid 的 DataSource?

.NET Compact Framework 中的 DataGrid 控件提供了完整 .NET Framework 中 DataGrid 控件的幾乎全部功能。.NET Compact Framework 版本的一個主要區別在于它無法將控件的 DataSource 設置為 DataSet。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagrid.aspx

5.16. 如何對 DataGrid 的列進行排序?

.NET Compact Framework 中的 DataGrid 控件提供了完整 .NET Framework 中 DataGrid 控件的幾乎全部功能。.NET Compact Framework 版本的 DataGrid 的一個主要區別在于它無法在運行時對列排序。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridsorting.aspx

5.17. 如何對 ListView 項目進行排序?

.NET Compact Framework 不支持 ListView.Sort 方法,但您仍然可以對項目排序。這個快速入門定義了 IComparable 接口的實現,可以將它用于 ArrayList.Sort 方法:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/listviewsort.aspx

5.18. 如何使用 InputPanel Component (SIP)?

這個快速入門介紹了如何啟動和禁用基于 Windows Mobile 的 Pocket PC 中的軟輸入面板 (SIP),以及當 SIP 顯示時如何調整選項卡控件的大小使之適應窗體區域的改變:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/inputpanel.aspx

多個窗體應該共享同一個 InputPanel 對象。可以這樣實現:在主窗體中創建 InputPanel,再將它傳遞給后續窗體或向其他需要利用該 SIP 的窗體公開一些 SIP 控件方法或屬性。

5.19. 如何創建自定義事件?

這個快速入門描述了如何派生 Button 類及重寫方法來實現雙擊事件。當在 SystemInformation.DoubleClickTime 值(它是在雙擊有效的鼠標點擊期間允許的毫秒數)的范圍內點擊一次后又點擊一次時就會引發此自定義事件。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/btndclick.aspx

.NET Compact Framework 不支持控件(包括 Windows.Forms.Control 基類)的 OnEnter 和 OnLeave 方法。然而,因為支持 Control.OnMouseMove 方法,所以您可以使用它和 Control.Capture 屬性來確定鼠標進入或離開控件的時間。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/enterleave.aspx

5.20. 如何創建所有者描述的列表框?

您可以使用 .NET Compact Framework 來創建所有者描述的列表框。.NET Compact Framework 不支持列表框和其他控件的 DrawMode、DrawItem 及其他繪制成員,但您可以編程實現該功能。這個快速入門提供了一個自定義控件類來創建所有者描述的列表框,并將控件實現為列表框來選擇字體。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/ownerdrawnlistbox.aspx

5.21. 如何創建 true/false 復選框?

這個快速入門擴展了 Windows.Forms.CheckBox 控件的功能,從而可以創建 True/False 復選框:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/tfcheckbox.aspx

5.22. 當我設置 InputPanel.Enabled = true 時,為什么會產生異常?

InputPanel 組件要求 MainMenu 控件位于窗體中,并且要求窗體在屏幕上可見。

5.23. 為什么我的自定義控件不會自動繼承其父級的字體?

.NET Compact Framework 中不支持這種行為。

5.24. 當我手動鍵入新文本時,為什么 NumericUpDown 和 DomainUpDown 控件不會激發它們的 ValueChanged 和 SelectedItemChanged 事件?

只有當用戶在代碼中更改控件的值時才會激發 ValueChanged 和 SelectedItemChanged 事件,或者通過向上/向下箭頭的方式激發。用戶在控件中輸入文本時不會激發這些事件。

5.25. 為什么 NumericUpDown 控件增加的值不是設置的增加值?

當按下向上或向下箭頭之后,如果下一個值不是增量的倍數,則它會在這個方向上繼續往前(向上或向下),直到發現增量的下一個倍數為止。

5.26. 為什么我無法將 StatusBar 控件放在窗體的任何位置?它好像總要跑到底部?

StatusBar 控件始終??吭诖绑w的底部。它的大小不能更改。

5.27. 為什么我的自定義控件不會自動繼承其父級的背景顏色?

.NET Compact Framework 中不支持這種行為。解決辦法是重寫 OnParentChanged 方法并手動設置顏色:

//C#

protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
this.BackColor = Parent.BackColor;
}

'VB

Protected Overrides Sub OnParentChanged(ByVal e As EventArgs)
MyBase.OnParentChanged(e)
Me.BackColor = Parent.BackColor
End Sub 'OnParentChanged

5.28. 為什么 NumericUpDown 控件雖然能夠接受小數值,但好像不能使用任何大于 2^16 的數值?

雖然數值形式的 NumericUpDown 控件接受小數值,但 .NET Compact Framework 將此控件的值視為整數。例如,指定值 10.23,則控件會將它計算為 10。另外,當此控件在基于 Windows Mobile 的 Pocket PC 上實現時,它不接受大于 16 位有符號整數的值。

5.29. 為什么我不能在 DomainUpDown 控件中鍵入文本以及讓它選擇相關的項目?

DomainUpDown 控件不對鍵入控件的文本執行檢驗(不像完整的 .NET Framework)。當您鍵入一些新的文本并按下向上/向下箭頭時,它在更改前就移到了下一項。

5.30. 為什么 OpenFileDialog 限制為“My Documents”文件夾?

OpenFileDialog 的初始目錄限制為“My Documents”文件夾或其任何子文件夾?;?Windows Mobile 的 Pocket PC 操作系統強加的這個限制是為了幫助用戶將文件組織在標準目錄中。

5.31. 如何能夠不通過菜單激活 SIP (InputPanel)?

SIP 可以通過 P/Invoke 函數“SipShowIM”來激活,如下所示。

//C#

using System.Runtime.InteropServices;
const uint SIPF_OFF = 0x0;
const uint SIPF_ON = 0x1;
[DllImport("coredll.dll")]
private extern static void SipShowIM(uint dwFlag);

'VB

Imports System.Runtime.InteropServices
Const SIPF_OFF As Integer = &H0
Const SIPF_ON As Integer = &H1
_
Private Shared Function SipShowIM(ByVal dwFlag As Integer) As Integer
End Function

5.32. 如何向 TreeView 中的每個節點添加一個子節點?

向所有節點添加子節點是這樣實現的:循環訪問 TreeView 中的所有節點,并向每個節點添加新節點。

//C#

foreach (TreeNode node in treeView1.Nodes)
{
node.Nodes.Add(new TreeNode("SubNode"));
}

'VB

Dim node As TreeNode
For Each node In treeView1.Nodes
node.Nodes.Add(New TreeNode("SubNode"))
Next node

5.33. 如何確定 DataGrid 中的行或列的數目?

DataGrid 中的行數和列數可以通過數據源本身確定。例如:

//C#

DataSet ds = new DataSet();
int numRows = ds.Tables[0].Rows.Count;
int numCols = ds.Tables[0].Columns.Count;

'VB

Dim ds As New DataSet()
Dim numRows As Integer = ds.Tables(0).Rows.Count
Dim numCols As Integer = ds.Tables(0).Columns.Count

如果 DataGrid 綁定到 DataView,您還可以使用 DataView.Count。

5.34. 如何創建所有者描述的 Listbox?

請參見 .NET Compact Framework QuickStarts、Implementing Events 主題:
http://samples.gotdotnet.com/quickstart/compactframework/doc/btndclick.aspx

5.35. 如何在 .NET Compact Framework 中實現 Control.GetNextControl?

.NET Compact Framework 中的控件的 Tab 鍵順序與 Form.Controls 集合中的控件的順序直接對應。因此,可以這樣實現 GetNextControl:確定指定控件的索引,并確定它在集合中的鄰居。

//C#

public Control GetNextControl(Control ctl, bool forward)
{
int curIndex = this.Controls.IndexOf(ctl);
if (forward)
{
if (curIndex < this.Controls.Count)
curIndex++;
else
curIndex = 0;
}
else
{
if (curIndex > 0)
curIndex--;
else
curIndex = this.Controls.Count - 1;
}
return this.Controls[curIndex];
}

'VB

Public Function GetNextControl(ByVal ctl As Control, _
ByVal forward As Boolean) As Control
Dim curIndex As Integer = Me.Controls.IndexOf(ctl)
If forward Then
If curIndex < Me.Controls.Count Then
curIndex += 1
Else
curIndex = 0
End If
Else
If curIndex > 0 Then
curIndex -= 1
Else
curIndex = Me.Controls.Count - 1
End If
End If
Return Me.Controls(curIndex)
End Function 'GetNextControl

5.36. 當用戶單擊樹視圖節點時,如何才能得到通知?

TreeView 不支持 Click 事件,不過有一個解決辦法,那就是使用 AfterSelect 事件來代替。

5.37. 如何設置全屏多行編輯控件窗口的標題?

這在當前版本的 .NET Compact Framework 中不支持。

5.38. 當我將 ComboBox.SelectedValue 設置為 validItemInCollection 時,為什么不能看到選定的有效項?

只有當控件被數據綁定時,設置 SelectedValue 屬性才有效。

5.39. 如何檢測發生“tap & hold”的位置,以便在自定義控件中生成上下文菜單?

處理 ContextMenu.Popup 事件,然后使用“Control.MousePosition”查詢當前鼠標坐標。

5.40. 為什么滾動條的值永遠不會被設置為最大值?

與 NumericUpDown 控件類似,可達的最大值是縮略圖上面的第一個空行。更具體地說,根據編輯器屬性,它等于:

Maximum - (LargeChange + 1)。

5.41. 如何通過 Tab 鍵從自定義控件回到前一個控件?

當檢測到 Keys.Up 鍵時,在 KeyDown 事件處理程序中調用 this.Parent.Controls(this.Parent.GetChildIndex(customcontrol) - 1).Focus()。

5.42. 如何添加具有透明度的工具欄按鈕?

圖標支持透明,不過在 Visual Studio .NET 2003 設計器中有一個已知的 bug,它會創建不正確的代碼并使得圖標不透明。一種解決辦法是在 InitializeComponent 外面的 ImageList 中添加一個圖標文件,并將圖標文件作為內容或嵌入式資源添加到項目中。以下代碼演示了這種做法:

//C#

using System.Drawing;
using System.IO;
using System.Reflection;
// Loaded as content example
private void Form1_Load(object sender, System.EventArgs e)
{
this.imageList1.Images.Add(new Icon(File.Open("fullFileName.ico",
FileMode.Open)));
this.toolBar1.Buttons[0].ImageIndex = 0;
}
// Loaded as a resource example
private void Form1_Load(object sender, System.EventArgs e)
{
this.imageList1.Images.Add(new
Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream(
".filename.ico")));
this.toolBar1.Buttons[0].ImageIndex = 0;
}

'VB

Imports System.Drawing
Imports System.IO
Imports System.Reflection
' Loaded as content example
Private Sub Form1_Load1(ByVal sender As Object, ByVal e As System.EventArgs)
Me.imageList1.Images.Add(New Icon(File.Open("fullFileName.ico", _
FileMode.Open)))
Me.toolBar1.Buttons(0).ImageIndex = 0
End Sub 'Form1_Load1
' Loaded as a resource example
Private Sub Form1_Load2(ByVal sender As Object, ByVal e As System.EventArgs)
Me.imageList1.Images.Add(New _
Icon([Assembly].GetExecutingAssembly().GetManifestResourceStream( _
".filename.ico")))
Me.toolBar1.Buttons(0).ImageIndex = 0
End Sub 'Form1_Load2

5.43. 如何允許在 ListView 控件中有多重選擇?

將 ListView 控件的 CheckBoxes 屬性設置為 True,這樣可以在列表中的每一項旁邊顯示一個 CheckBox,從而允許用戶選擇多個項。

也可以使用 P/Invoke 來設置 ListView 的功能,以便接受多重選擇。有關這一點的示例,請參見本 FAQ 中標題為“6.24.如何允許一個控件接受多重選擇?”的項。

返回頁首

6. 互操作性和本機代碼

6.1. 如何調用位于本機 DLL 中的函數?

本機 DLL 函數可以通過平臺調用 (P/Invoke) 來調用。這些文章將提供有關這種技術的說明和更多信息:

?

了解如何使用 .NET Compact Framework 的平臺調用 (P/Invoke) 功能:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfintrointerp.asp

?

探討 .NET Compact Framework 中的高級互操作性。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfadvinterop.asp

?

學習如何創建可通過平臺調用在智能設備應用程序中使用的非托管函數。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/unmanagedfuncs.asp

?

了解如何使用 .NET Compact Framework 在托管和非托管代碼之間封送數據。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmarshallingtypes.asp

?

了解如何使用 dumpbin.exe 作為在基于 Microsoft .NET Compact Framework 的應用程序中聲明 P/Invoke 的手段。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdumpbinpinvoke.asp

6.2. 如何將 dumpbin.exe 作為聲明 P/Invoke 的手段?

請參見本 FAQ 中的主題“6.1.如何調用位于本機 DLL 中的函數?”。

6.3. 如何編寫基于 Microsoft .NET Compact Framework 的應用程序的非托管函數?

請參見本 FAQ 中的主題“6.1.如何調用位于本機 DLL 中的函數?”。

6.4. 如何進行 P/Invoke GetTickCount?

不需要 P/Invoke GetTickCount 函數,原因是 Environment.TickCount 就可以實現。有關更多信息,請參見本 FAQ 中的主題“7.2.如何計算準確的時間間隔?”。

6.5. 如何確定一個設備有多少可用內存?

可以 P/Invoke GetSystemMemoryDivision 和 GlobalMemorySystem 函數來確定內存如何在程序和存儲中劃分與分配。

可以在 API 引用文檔中找到參數定義。

//C#

using System.Runtime.InteropServices;
public class MEMORYSTATUS
{
public uint dwLength;
public uint dwMemoryLoad;
public uint dwTotalPhys;
public uint dwAvailPhys;
public uint dwTotalPageFile;
public uint dwAvailPageFile;
public uint dwTotalVirtual;
public uint dwAvailVirtual;
}
[DllImport("CoreDll.dll")]
public static extern void GlobalMemoryStatus
(
MEMORYSTATUS lpBuffer
);
[DllImport("CoreDll.dll")]
public static extern int GetSystemMemoryDivision
(
ref uint lpdwStorePages,
ref uint lpdwRamPages,
ref uint lpdwPageSize
);
public void Test()
{
uint storePages = 0;
uint ramPages = 0;
uint pageSize = 0;
int res = GetSystemMemoryDivision(ref storePages, ref ramPages, ref pageSize);
MEMORYSTATUS memStatus = new MEMORYSTATUS();
GlobalMemoryStatus(memStatus);
}

'VB

Imports System.Runtime.InteropServices
Public Structure MEMORYSTATUS
Public dwLength As UInt32
Public dwMemoryLoad As UInt32
Public dwTotalPhys As UInt32
Public dwAvailPhys As UInt32
Public dwTotalPageFile As UInt32
Public dwAvailPageFile As UInt32
Public dwTotalVirtual As UInt32
Public dwAvailVirtual As UInt32
End Structure 'MEMORYSTATUS
_
Private Shared Sub GlobalMemoryStatus(ByRef ms As MEMORYSTATUS)
End Sub
_
Public Shared Function GetSystemMemoryDivision( _
ByRef lpdwStorePages As UInt32, _
ByRef lpdwRamPages As UInt32, _
ByRef lpdwPageSize As UInt32) As Integer
End Function
Public Shared Sub Test()
Dim storePages As UInt32
Dim ramPages As UInt32
Dim pageSize As UInt32
Dim res As Integer = GetSystemMemoryDivision(storePages, ramPages, pageSize)
Dim memStatus As New MEMORYSTATUS
GlobalMemoryStatus(memStatus)
End Sub 'Test

6.6. 如何強制一個窗體保持最小化?

1.

重寫窗體的 OnGotFocus 方法。

2.

查找窗體的窗口。

3.

調用 ShowWindow(hwnd, SW_MINIMIZE) 來強制窗體最小化。

//C#

using System.Runtime.InteropServices;
[DllImport("CoreDll")]
public static extern IntPtr FindWindow(string className,string WindowsName);
[DllImport("CoreDll")]
public static extern bool ShowWindow(IntPtr hwnd,int nCmdShow);
const int SW_MINIMIZE = 6;
protected override void OnGotFocus(EventArgs e)
{
IntPtr hwnd = FindWindow(null, this.Text);
ShowWindow(hwnd, SW_MINIMIZE);
base.OnGotFocus(e);
}

'VB

Imports System.Runtime.InteropServices
_
Public Shared Function FindWindow(ByVal className As String, _
ByVal WindowsName As String) As IntPtr
End Function
_
Public Shared Function ShowWindow(ByVal hwnd As IntPtr, _
ByVal nCmdShow As Integer) As Boolean
End Function
Private Const SW_MINIMIZE As Integer = 6
Protected Overrides Sub OnGotFocus(ByVal e As EventArgs)
Dim hwnd As IntPtr = FindWindow(Nothing, Me.Text)
ShowWindow(hwnd, SW_MINIMIZE)
MyBase.OnGotFocus(e)
End Sub 'OnGotFocus

6.7. 如何在 .NET Compact Framework 中,在平臺調用 (P/Invoke) 期間封送處理類型?

請參見本 FAQ 中的主題“6.1.如何調用位于本機 DLL 中的函數?”。

6.8. 如何獲得一個控件或窗體的句柄 (HWND)?

實際上有幾種使用 P/Invoke 的方法可以訪問控件的 HWND 句柄。下面顯示了其中兩種方法,一種使用 GetCapture,另一種使用 FindWindow。

//C#

[DllImport("coredll.dll"]
public static extern IntPtr GetCapture();
[DllImport("coredll.dll")]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
this.Text = "FindMe";
IntPtr hwnd1 = FindWindow(null, "FindMe");
this.Capture = true;
IntPtr hwnd2 = GetCapture();
this.Capture = false;

'VB

_
Public Shared Function GetCapture() As IntPtr
End Function
_
Public Shared Function FindWindow(ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
Me.Text = "FindMe"
Dim deskWin As IntPtr = FindWindow(Nothing, "FindMe")
Me.Capture = True
Dim hwnd As IntPtr = GetCapture()
Me.Capture = False

6.9. 如何使用性能計數器函數?

可以使用 QueryPerformanceFrequency 和 QueryPerformanceCounter 函數來創建高分辨率的計時方案。這些函數是 OEM 專有的,在本例中沒有實現,它們通常默認為 GetTickCount 函數。因此,使用這些函數將始終確保計時器(如果實現)盡可能準確。當實現時,這種功能提供的準確性比 GetTickCount 或 Environment.TickCount 要高,實際上后者調用的是前者。

在這種情況下性能計數器是 GetTickCount 的一個實例,QueryPerformanceFrequency 會將計時器的頻率設置為 1000。如果這些函數都沒有實現,則它們會返回 0。以下代碼演示了如何使用這些函數。

//C#

[DllImport("CoreDll.dll")]
public static extern int QueryPerformanceFrequency(ref Int64 lpFrequency);
[DllImport("CoreDll.dll")]
public static extern int QueryPerformanceCounter(ref Int64 lpPerformanceCount);
private void TestTimer()
{
System.Int64 freq = 0;
if (QueryPerformanceFrequency(ref freq) != 0)
{
System.Int64 count1 = 0;
System.Int64 count2 = 0;
if (QueryPerformanceCounter(ref count1) != 0)
{
System.Threading.Thread.Sleep(1200);
QueryPerformanceCounter(ref count2);
System.Int64 time_ms = (count2 - count1) * 1000 / freq;
}
}
}

'VB

_
Public Shared Function QueryPerformanceFrequency(ByRef lpFrequency As Int64) As Integer
End Function
_
Public Shared Function QueryPerformanceCounter(ByRef lpPerformanceCount As Int64) As Integer
End Function
Private Sub TestTimer()
Dim freq As System.Int64 = 0
If QueryPerformanceFrequency(freq) <> 0 Then
Dim count1 As System.Int64 = 0
Dim count2 As System.Int64 = 0
If QueryPerformanceCounter(count1) <> 0 Then
System.Threading.Thread.Sleep(1200)
QueryPerformanceCounter(count2)
Dim time_ms As System.Int64 = (count2 - count1) * 1000 / freq
End If
End If
End Sub 'TestTimer

6.10. 通過 P/Invoke 封送處理類型有哪些限制?

?

返回值

?

只能是小于或等于 32 位的值類型

?

沒有浮點

?

參數

?

只支持封送處理直接復制到本機結構中的類型

?

可直接復制到本機結構中的類型 -> 托管和本機兩種結構在內存中有相同的表示

?

非直接復制到本機結構中的類型 -> 需要進行內存轉換

?

由于只有直接復制到本機結構中的類型,所以所有對象都是固定的,不會被復制

?

例外:在 VB.NET 中傳遞 String ByVal

?

這意味著您不能封送處理嵌套對象,因為它需要進行內存轉換(非直接復制到本機結構中)

?

只能是小于或等于 32 位的值類型

?

值在堆棧中傳遞

?

例外:float32

?

引用

?

傳遞可直接復制到本機結構中的引用類型

?

將引用傳遞給值類型

?

這是傳遞 float32 的方法

?

可以傳遞值類型數組

在本機獲得指向第一個對象的指針,對象按照您期望的那樣順序排列

?

String 較特殊,它傳遞字符數組 -> 不可變

?

StringBuilder 較特殊,它傳遞字符數組 -> 可變(需要單獨傳遞長度)

?

注:C# bool 只有 8 位,不等于 Win32 BOOL

?

對齊方式:默認編譯器對齊(4 字節)

?

Marshal.GetLastWin32Error 支持 GetLastError() 語義

?

不受支持:

?

MarshalAs:不支持非直接復制到本機結構中的類型

?

StructLayout:無法更改布局

?

委托 (Delegate)

?

DateTime

?

只支持默認調用約定

6.11. 當我對 GetLastError 進行 P/Invoke 時,為什么得到奇數個返回節點?

通常對 Windows GetLastError() API 進行 P/Invoke 是不好的做法,因為 CLR 產生的本機調用可能已經更改了最近的錯誤代碼。相反,應該標記 P/Invoke 聲明來保存返回的錯誤代碼并調用 System.Runtime.InteropServices.Marshal.GetLastWin32Error() 方法來檢索該錯誤代碼。

//C#

using System.Runtime.InteropServices;
using System.ComponentModel;
[DllImport("coredll.dll", SetLastError=true)]
public static extern uint Foo();
if (Foo() == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "Foo failed");
}

'VB

Imports System.Runtime.InteropServices
Imports System.ComponentModel
_
Public Shared Function Foo() As Integer
End Function
If (Foo() = 0) Then
Throw New Win32Exception(Marshal.GetLastWin32Error(), "Foo failed")
End If

6.12. 可以傳遞給本機函數的參數數目是否有限制?

是。.NET Compact Framework 第 1 版限制為 12 個。

6.13. 當我對本機函數進行 P/Invoke 時,為什么會產生“NotSupportedException”?

有三種常見的可能:

?

托管代碼中的聲明不正確

?

.NET Compact Framework 不支持您試圖要做的事情

?

在導出時改變 dll 名稱

請檢查以下情況:

?

是否違背任何 .NET Compact Framework P/Invoke 限制?

?

是否有參數需要預分配內存(即,參數是指針)?如果是這樣,您就應該將一個引用傳遞給現有的變量。

?

導出函數的名稱是否正確?可以通過 DUMPBIN.EXE 來驗證

?

您是否試圖傳遞過多參數?

例如,在以上的第二種情況,RegOpenKey API 需要一個指向 HKEY 的指針作為它的最后一個參數。您可以按照以下方式聲明和調用它:

//C#

[DllImport("coredll.dll", SetLastError=true)]
public static extern long RegOpenKey(
IntPtr hkey,
string lpSubKey,
ref IntPtr hkeyResult
);
public long OpenMySubKey()
{
IntPtr hkey = IntPtr.Zero;
return RegOpenKey(HKEY_CLASSES_ROOT, "MySubKey", ref hkey);
}

'VB

_
Public Shared Function RegOpenKey(ByVal hkey As IntPtr, ByVal lpSubKey As String, _
ByRef hkeyResult As IntPtr) As Long
End Function
Public Function OpenMySubKey() As Long
Dim hkey As IntPtr = IntPtr.Zero
Return RegOpenKey(HKEY_CLASSES_ROOT, "MySubKey", hkey)
End Function 'OpenMySubKey

6.14. 如何將 byte[] 轉換為 IntPtr?

有幾種方法可以訪問與字節數組相對應的 IntPtr。

第一種是使用不安全的代碼塊來訪問直接指向字節數組的指針。

//C#

unsafe
{
byte[] test = new byte[5];
fixed (byte* p = &test[0])
{
*p = 0xff;
}
}

也可以使用 GCHandle 來獲得對象。

//C#

using System.Runtime.InteropServices;
byte[] test = new byte[5];
GCHandle hObject = GCHandle.Alloc(test, GCHandleType.Pinned);
IntPtr pObject = hObject.AddrOfPinnedObject();
if(hObject.IsAllocated)
hObject.Free();

'VB

Imports System.Runtime.InteropServices
Dim test(4) As Byte
Dim hObject As GCHandle = GCHandle.Alloc(test, GCHandleType.Pinned)
Dim pObject As IntPtr = hObject.AddrOfPinnedObject()
If hObject.IsAllocated Then
hObject.Free()
End If

最后,可以這樣實現:通過 LocalAlloc 創建內存塊并將數據封送處理到該內存塊。

//C#

[DllImport("coredll.dll",SetLastError=true)]
public static extern IntPtr LocalAlloc(uint uFlags, uint uBytes);
[DllImport("coredll.dll",SetLastError=true)]
public static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("coredll.dll",SetLastError=true)]
public static extern IntPtr LocalReAlloc(IntPtr hMem, uint uBytes, uint fuFlags);
public const uint LMEM_FIXED = 0;
public const uint LMEM_MOVEABLE = 2;
public const uint LMEM_ZEROINIT = 0x0040;
byte[] test = new byte[5];
IntPtr p = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, (uint)test.Length);
if (p == IntPtr.Zero)
{
throw new OutOfMemoryException();
}
else
{
Marshal.Copy(test, 0, p, test.Length);
}

'VB

_
Public Shared Function LocalAlloc(ByVal uFlags As UInt32, _
ByVal uBytes As UInt32) As IntPtr
End Function
_
Public Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr
End Function
_
Public Shared Function LocalReAlloc(ByVal hMem As IntPtr, _
ByVal uBytes As UInt32, ByVal fuFlags As UInt32) As IntPtr
End Function
Public Const LMEM_FIXED As Integer = 0
Public Const LMEM_MOVEABLE As Integer = 2
Public Const LMEM_ZEROINIT As Integer = &H40
Dim test(4) As Byte
Dim p As IntPtr = LocalAlloc(Convert.ToUInt32(LMEM_FIXED Or LMEM_ZEROINIT), _
Convert.ToUInt32(test.Length))
If p.Equals(IntPtr.Zero) Then
Throw New OutOfMemoryException
Else
Marshal.Copy(test, 0, p, test.Length)
End If

6.15. 當我調用來自本機 DLL 的函數時,為什么會產生 MissingMethodException?

當確定 MissingMethodException 的情況時,有幾個問題需要考慮。當產生異常時,應該驗證以下幾點:

?

面向基于 Windows Mobile 的 Pocket PC 2003 是否使用 Microsoft eMbedded Visual C++ 4.0。

?

面向基于 Windows Mobile 的 Pocket PC 2000 或 2002 是否使用 Microsoft eMbedded Visual Tools 3.0

?

驗證函數的參數是否與原來的那些相匹配

?

本機代碼中的 long 通常是 32 位,而在 .NET Compact Framework 中是 64 位

?

要注意 bool

?

根據 MSDN 文檔,“Its size is unspecified.”:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vccelng4/html/ellrffundamentaltypes.asp

?

在 MSDN 文檔的一個 Microsoft 特定章節中,bool 大小被描述為因用于構建二進制的 Visual C++ 版本而異:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vccelng4/html/ellrfbool.asp

?

BOOL 被定義為 int(32 位值)

?

.NET Compact Framework 可直接復制到本機結構中的類型:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vccelng4/html/ellrffundamentaltypes.asp

?

非直接復制到本機結構中的類型和封送處理支持:
http://msdn.microsoft.com/library/en-us/dv_evtuv/html/etconNonBlittableTypesMarshalingSupport.asp

?

確保函數名稱拼寫正確

?

驗證 DLL 的所在位置正確 — Windows 或目標設備的執行文件夾

?

使用 DUMPBIN 驗證函數的名稱沒有在導出 DLL 時改變(extern "C" 修復這個問題)。有關這個主題的更多信息,可以在本 FAQ 中的“6.1.如何調用位于本機 DLL 中的函數?”小節找到。

?

驗證導入的 DLL 沒有依賴于其他 DLL。缺少依賴的 DLL 會導致 MissingMethodException。

有關最新的 Microsoft eMbedded Visual Tools 和 SDK 下載,請訪問 MSDN 移動與嵌入式技術開發人員中心“產品與更新”下載頁面,位于:
http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

6.16. 如何設置系統時間?

可以通過 P/Invoke SetSystemTime 函數來設置系統時間。

//C#

using System.Runtime.InteropServices;
public struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
[DllImport("coredll.dll")]
public extern static void GetSystemTime(ref SYSTEMTIME lpSystemTime);
[DllImport("coredll.dll")]
public extern static uint SetSystemTime(ref SYSTEMTIME lpSystemTime);
// Set the clock ahead one hour
SYSTEMTIME st = new SYSTEMTIME();
GetSystemTime(ref st);
st.wHour = (ushort)(st.wHour + 1 % 24);
SetSystemTime(ref st);

'VB

Imports System.Runtime.InteropServices
Public Structure SYSTEMTIME
Public wYear As UInt16
Public wMonth As UInt16
Public wDayOfWeek As UInt16
Public wDay As UInt16
Public wHour As UInt16
Public wMinute As UInt16
Public wSecond As UInt16
Public wMilliseconds As UInt16
End Structure
_
Public Shared Sub GetSystemTime(ByRef lpSystemTime As SYSTEMTIME)
End Sub
_
Public Shared Function SetSystemTime(ByRef lpSystemTime As SYSTEMTIME) As UInt32
End Function
'Set the clock ahead one hour
Dim st As New SYSTEMTIME
GetSystemTime(st)
st.wHour = Convert.ToUInt16(((Convert.ToInt32(st.wHour) + 1)) Mod 24)
SetSystemTime(st)

6.17. 如何以編程方式軟重置設備?

可以通過 P/Invoke KernelIoControl 函數來軟重置設備,如以下代碼所示。有關如何使用該函數及擴展該示例功能的更多信息,請參考 Visual Studio .NET 幫助。

注:在基于 Windows Mobile 的 Smartphone 設備中,只有當您簽署一個有特權的證書時,它才會生效。

//C#

using System.Runtime.InteropServices;
public const uint FILE_DEVICE_HAL = 0x00000101;
public const uint METHOD_BUFFERED = 0;
public const uint FILE_ANY_ACCESS = 0;
public uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
[DllImport("Coredll.dll")]
public extern static uint KernelIoControl
(
uint dwIoControlCode,
IntPtr lpInBuf,
uint nInBufSize,
IntPtr lpOutBuf,
uint nOutBufSize,
ref uint lpBytesReturned
);
uint ResetPocketPC()
{
uint bytesReturned = 0;
uint IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15,
METHOD_BUFFERED, FILE_ANY_ACCESS);
return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0,
IntPtr.Zero, 0, ref bytesReturned);
}
private void Form1_Load(object sender, System.EventArgs e)
{
DialogResult r = MessageBox.Show
(
"Are you sure you want to reset?",
"Test",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2
);
if (r == DialogResult.Yes)
{
ResetPocketPC();
}
}

'VB

Public Const FILE_DEVICE_HAL As Integer = &H101
Public Const METHOD_BUFFERED As Integer = 0
Public Const FILE_ANY_ACCESS As Integer = 0
Public Function CTL_CODE( _
ByVal DeviceType As Integer, _
ByVal Func As Integer, _
ByVal Method As Integer, _
ByVal Access As Integer) As Integer
Return (DeviceType << 16) Or (Access << 14) Or (Func << 2) Or Method
End Function 'CTL_CODE
_
Public Shared Function KernelIoControl _
( _
ByVal dwIoControlCode As Integer, _
ByVal lpInBuf As IntPtr, _
ByVal nInBufSize As Integer, _
ByVal lpOutBuf As IntPtr, _
ByVal nOutBufSize As Integer, _
ByRef lpBytesReturned As Integer _
) As Integer
End Function
Function ResetPocketPC() As Integer
Dim bytesReturned As Integer = 0
Dim IOCTL_HAL_REBOOT As Integer = CTL_CODE(FILE_DEVICE_HAL, _
15, METHOD_BUFFERED, FILE_ANY_ACCESS)
Return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, _
IntPtr.Zero, 0, bytesReturned)
End Function 'ResetPocketPC
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
Dim r As DialogResult = MessageBox.Show( _
"Are you sure you want to reset?", _
"Test", _
MessageBoxButtons.YesNo, _
MessageBoxIcon.Question, _
MessageBoxDefaultButton.Button2)
If r = DialogResult.Yes Then
ResetPocketPC()
End If
End Sub 'Form1_Load

6.18. 如何將一個圖標放在標題欄上,而不管哪個窗體是活動的?

在當前版本的 .NET Compact Framework 中不支持這項功能。不過您可以 P/Invoke 基于 Windows Mobile 的 Pocket PC 的通知系統來做到這一點。有關更多信息,請參考以下內容:

示例代碼:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppc2k2/html/ppc_fications.asp

AYGShell API:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceui40/html/_cerefaygshellfunctions.asp

本機 Notification API 為:SHNotificationAdd、SHNotificationRemove、SHNotificationGetData 和 SHNotificationUpdate。

6.19. 如何禁用和捕獲硬件按鈕?

請參考 P/Invoke 庫中的示例。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PInvokeLib.asp

6.20. 如何隱藏開始圖標?

可以使用 SHFullScreen API 來隱藏開始圖標。

//C#

const uint SHFS_SHOWTASKBAR = 0x0001;
const uint SHFS_HIDETASKBAR = 0x0002;
const uint SHFS_SHOWSIPBUTTON = 0x0004;
const uint SHFS_HIDESIPBUTTON = 0x0008;
const uint SHFS_SHOWSTARTICON = 0x0010;
const uint SHFS_HIDESTARTICON = 0x0020;
[DllImport("aygshell.dll")]
static extern uint SHFullScreen(IntPtr hwndRequester, uint dwState);
[DllImport("coredll.dll")]
public static extern IntPtr GetCapture();
private void Form1_Load(object sender, System.EventArgs e)
{
Capture = true;
IntPtr hwnd = GetCapture();
Capture = false;
SHFullScreen(hwnd, SHFS_HIDESTARTICON);
}

'VB

Const SHFS_SHOWTASKBAR As Integer = &H1
Const SHFS_HIDETASKBAR As Integer = &H2
Const SHFS_SHOWSIPBUTTON As Integer = &H4
Const SHFS_HIDESIPBUTTON As Integer = &H8
Const SHFS_SHOWSTARTICON As Integer = &H10
Const SHFS_HIDESTARTICON As Integer = &H20
_
Shared Function SHFullScreen(ByVal hwndRequester As IntPtr, ByVal dwState As Integer) As Integer
End Function
_
Public Shared Function GetCapture() As IntPtr
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Capture = True
Dim hwnd As IntPtr = GetCapture()
Capture = False
SHFullScreen(hwnd, SHFS_HIDESTARTICON)
End Sub 'Form1_Load

6.21. 如何枚舉、創建和終止進程?

請參考以下示例:
http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull=/library/en-us/dnnetcomp/html/processmanager.asp

6.22. 在哪可以找到 P/Invoke 示例的集中庫?

此示例演示了如何 P/Invoke 許多有用的本機函數,它們無法直接通過 .NET Compact Framework 使用。它提供了一個測試窗體,此窗體枚舉所有可用的測試過程并允許用戶從中選擇和運行:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PInvokeLib.asp

6.23. 如何通過 Waveform Audio 界面播放和錄制 .WAV 音頻文件?

了解如何使用 Waveform Audio Interface 來錄制和播放“.wav”文件:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WaveInOut.asp

6.24. 如何允許一個控件接受多重選擇?

有些控件可以使用以下代碼來實現:

//C#

using System.Runtime.InteropServices;
private const int GWL_STYLE = -16;
private const int LVS_SINGLESEL = 0x0004;
[DllImport("coredll")]
private static extern IntPtr GetCapture();
[DllImport("coredll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("coredll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex,
int dwNewLong);
// Toggle off single selection
this.listView1.Capture = true;
IntPtr hWnd = GetCapture();
this.listView1.Capture = false;
int style = GetWindowLong(hWnd, GWL_STYLE);
SetWindowLong(hWnd, GWL_STYLE, (style & ~LVS_SINGLESEL));

'VB

Imports System.Runtime.InteropServices
Private Const GWL_STYLE As Integer = -16
Private Const LVS_SINGLESEL As Integer = &H4
_
Private Shared Function GetCapture() As IntPtr
End Function
_
Private Shared Function GetWindowLong(ByVal hWnd As IntPtr, _
ByVal nIndex As Integer) As Integer
End Function
_
Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, _
ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
End Function
' Toggle off single selection
Me.ListView1.Capture = True
Dim hWnd As IntPtr = GetCapture()
Me.ListView1.Capture = False
Dim style As Integer = GetWindowLong(hWnd, GWL_STYLE)
SetWindowLong(hWnd, GWL_STYLE, (style And (Not LVS_SINGLESEL)))
返回頁首

7. 常規

7.1. 如何確定應用程序的根目錄?

應用程序可以使用 Reflection 來確定它運行所在的目錄,并且可以使用 IO.Path 命名空間輕松地修改該目錄。

//C#

using System.Reflection;
using System.IO;
// This is the full directory and exe name
String fullAppName = Assembly.GetExecutingAssembly().GetName().CodeBase;
// This strips off the exe name
String fullAppPath = Path.GetDirectoryName(fullAppName);
// This adds a file name to the path
String fullFileName = Path.Combine(fullAppPath, "myfile.txt");

'VB

Imports System.IO
Imports System.Reflection
' This is the full directory and exe name
Dim fullAppName As String = [Assembly].GetExecutingAssembly().GetName().CodeBase
' This strips off the exe name
Dim fullAppPath As String = Path.GetDirectoryName(fullAppName)
' This adds a file name to the path
Dim fullFileName As String = Path.Combine(fullAppPath, "myfile.txt")

了解如何確定當前執行的應用程序的路徑。在 Embedded Visual Basic 中,執行的應用程序路徑可以通過 App.Path 屬性來獲得??梢酝ㄟ^檢驗執行程序集的 AssemblyName 對象(它充分描述了程序集的標識)來確定執行應用程序的路徑:
http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOExecutingAppPath.asp

這個快速入門獲得包含程序集及相關數據文件的目錄的路徑說明。Windows CE .NET 并沒有一開始就為應用程序提供一個當前的目錄設置:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/getappdir.aspx

7.2. 如何計算準確的時間間隔?

應用程序有四個主要的方法可以確定時間間隔:

?

System.Environment.TickCount維護一個有符號整數值,代表自打開設備以來經過的毫秒數。不過 .NET Compact Framework 是不確定的,所以不能保證這個值比 500 毫秒分辨率還準確,雖然通常它會比這個值還準確。

?

GetTickCount()Environment.TickCount 屬性已經調用了 GetTickCount 函數,所以 P/Invoke 這個函數并沒有什么用處。

?

性能監視器可以用于分析目的,但在發布的應用程序中并不打算使用。有關更多信息,請參見本 FAQ 中的主題“7.5.如何使用性能監視器?”。

?

計時器應用程序可以提供一個委托給使用 System.Threading.Timer 來設置特定間隔的線程計時器。

?

性能計數器如果由 OEM 實現,則保證 QueryPerformanceCounter 函數可以提供最高分辨率的可用計時器。有關如何使用性能計數器的信息,請參見本 FAQ 中的主題“6.9.如何使用性能計數器函數?”。

7.3. 如何以流的形式訪問嵌入式資源?

要訪問嵌入式資源,應用程序只需訪問相關的程序集并調用 GetManifestResourceStream 函數。以下是從嵌入式資源創建 Bitmap 的示例:

//C#

using System.Reflection;
Assembly asm = Assembly.GetExecutingAssembly();
Bitmap bmpSprite = new Bitmap(asm.GetManifestResourceStream("AssemblyName.FileName"));

'VB

Imports System.Reflection
Dim asm As [Assembly] = [Assembly].GetExecutingAssembly()
Dim bmpSprite As New Bitmap(asm.GetManifestResourceStream("AssemblyName.FileName"))

在以上的示例中,字符串的 AssemblyName 部分可以在運行時通過調用 asm.GetName().Name 來獲得。

注:如果程序集名稱中有空格,則會替換為下劃線“_”,并且必須這樣訪問。

7.4. 為什么我會得到這樣的消息:“An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll?”

這是 .NET Compact Framework 中的一個 bug。它是由于 Windows CE 中的底層安全套接字層 (SSL) 實現的局限性造成的。不過有一個解決辦法。如果您將 req.AllowWriteStreamBuffering 設置為 true,并且不設置 req.ContentLength,則不會看到這種異常。

7.5. 如何使用性能監視器?

性能計數器是通過修改設備的注冊表創建的:

1.

創建注冊表項:“HKEY_LOCAL_MACHINE"SOFTWARE"Microsoft".NETCompactFramework"PerfMonitor”

2.

在這個項中創建一個名為 Counters 的 DWORD 類型值。

3.

將 Counters 的值設置為 1 來啟用性能計數器,或者設置為 0 來禁用它們。

啟用性能計數器將會在應用程序關閉時創建一個名為“mscoree.stat”的文本文件。此文件可以在設備的根目錄中找到。它是一個按“固定寬度”分隔的文件,所以可以直接導入 Excel。

注: 在分析期間只能有一個托管應用程序在運行。

注: 當使用計數器時,性能會下降 30%。

7.6. 如何阻止應用程序關閉?

應用程序可以重寫 OnClosing 方法,當您將 CancelEventArgs.Cancel 設置為 true 時就可以取消關閉操作。

//C#

protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
}

'VB

Protected Overrides Sub OnClosing(ByVal e As CancelEventArgs)
e.Cancel = True
End Sub 'OnClosing

7.7. 如何在我的應用程序中啟動另一個應用程序?

您可以調用本機函數 CreateProcess 來啟動第二個應用程序,然后調用本機函數 WaitForSingleObject 來暫停調用的應用程序直到第二個應用程序完成。這個快速入門使用基于 Windows Mobile 的 Pocket PC 計算器來演示這個過程:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/waitforsingleobject.aspx

7.8. .NET Compact Framework 應用程序創建了什么線程?

.NET Compact Framework 應用程序創建的線程達到四個:

?

一個主應用程序線程。

?

一個用于控制各種周期計時器和可由系統或應用程序安排的超時的線程。

?

一個用于跟蹤 TCP/IP 活動接口(模擬在 Windows XP 中存在,但在 Windows CE 中不存在的媒體感知行為 (media sense behavior))變化的線程。

?

一個用于運行 Finalizer 對象的線程。它是在對第一個Finalizable 的對象進行垃圾回收時創建的。

7.9. 如何將一個字節數組轉換為結構?

雖然在 C++ 中可以方便快捷地將一個類或結構內存映射保存成文件,并通過類型轉換直接重新加載到類中,但托管代碼的性質決定它不可能這樣做。然而,可以創建一個類,將內存映射作為其數據加以存儲并利用屬性來訪問和設置這些數據。如以下示例所示:

//C#

public class MyClass
{
protected byte[] m_data = null;
// uint uiDummy
// short sDummy
// This is a bit unsafe so you should throw an
// exception or assert if the byte array length is
// not 6. A safer but less memory efficient approach
// would be to set m_data = new byte[6] and then copy
//bytes to m_data.
public MyClass(byte[] bytes) {m_data = bytes;}
// Get/Set the uint
public uint uiDummy
{
get {return BitConverter.ToUInt32(m_data, 0);}
set
{
Buffer.BlockCopy(BitConverter.GetBytes(value), 0,
m_data, 0, BitConverter.GetBytes(value).Length);
}
}
// Get/Set the short
public short sDummy
{
get {return BitConverter.ToInt16(m_data, 4);}
set
{
Buffer.BlockCopy(BitConverter.GetBytes(value),
0, m_data, 4, BitConverter.GetBytes(value).Length);
}
}
}
byte[] fromFile = {1,1,1,1,2,2};
MyClass myClass = new MyClass(fromFile);
uint test1 = myClass.uiDummy; // 0x1010101
short test2 = myClass.sDummy; // 0x202
myClass.sDummy = 0x0505; // Test setting the short
uint test4 = myClass.uiDummy; // 0x1010101
short test5 = myClass.sDummy; // 0x505

'VB

Public Class ByteClass
Protected m_data As Byte() = Nothing
' uint uiDummy
' short sDummy
' This is a bit unsafe so you should throw an exception
' or assert if the byte array length is not 6. A safer
' but less memory efficient approach would be to set
' m_data = new byte[6] and then copy bytes to m_data.
Public Sub New(ByVal bytes() As Byte)
m_data = bytes
End Sub 'New
' Get/Set the uint
Public Property uiDummy() As UInt32
Get
Return BitConverter.ToUInt32(m_data, 0)
End Get
Set(ByVal Value As System.UInt32)
Buffer.BlockCopy(BitConverter.GetBytes(Value), _
0, m_data, 0, BitConverter.GetBytes(Value).Length)
End Set
End Property
' Get/Set the short
Public Property sDummy() As Short
Get
Return BitConverter.ToInt16(m_data, 4)
End Get
Set(ByVal Value As Short)
Buffer.BlockCopy(BitConverter.GetBytes(Value), _
0, m_data, 4, BitConverter.GetBytes(Value).Length)
End Set
End Property
End Class 'ByteClass
Dim fromFile As Byte() = {1, 1, 1, 1, 2, 2}
Dim testClass As New ByteClass(fromFile)
Dim test1 As System.UInt32 = testClass.uiDummy ' 0x1010101
Dim test2 As Short = testClass.sDummy ' 0x202
testClass.sDummy = &H505 ' Test short
Dim test4 As System.UInt32 = testClass.uiDummy ' 0x1010101
Dim test5 As Short = testClass.sDummy ' 0x505

7.10. 我是否可以創建一個自定義委托來傳遞給調用?

不可以,在 .NET Compact Framework 中只能夠調用 EventHandler 方法。實現它的正確方法如下所述:

//C#

public void HandleMe(object o, EventArgs e) {...}
form.Invoke(new EventHandler(form.HandleMe));

'VB

Public Sub HandleMe(o As Object, e As EventArgs)
End Sub 'HandleMe
form.Invoke(New EventHandler(AddressOf form.HandleMe))

雖然以下代碼能夠編譯,但不能正確工作:

//C#

public delegate void MyHandler();
public void HandleMeBadly() {...}
form.Invoke(new MyHandler(form.HandleMeBadly));

'VB

Delegate Sub MyHandler()
Public Sub HandleMeBadly()
End Sub 'HandleMeBadly
form.Invoke(New MyHandler(form.HandleMeBadly))

7.11. 如何通過 Microsoft .NET Compact Framework 訪問 Phone API?

請參閱以下文章來了解如何通過基于 .NET Compact Framework 的應用程序訪問 Phone API:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfphoneapi.asp

7.12. 如何在基于 Windows Mobile 的 Pocket PC 上生成 GUID?

Guid.NewGuid 方法生成新的 GUID,但在 .NET Compact Framework 中不支持。閱讀這篇文章來了解如何為基于 Windows Mobile 的 Pocket PC 應用程序生成符合文檔化的 GUID 規范的 GUID 對象:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCGuidGen.asp

7.13. 如何將 Pocket Outlook 數據合并到基于 .NET Compact Framework 的應用程序中?

這篇文章討論了如何使用 InTheHand Pocket Outlook .NET 組件:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/inthehandpoom.asp

7.14. 我是否可以確定 .NET Compact Framework 中文件的版本?

Visual Studio .NET 2003 幫助為 .NET Compact Framework 提供了一個不安全的代碼示例,它 P/Invoke C# 程序員參考 (Programmer's Reference) 中的 GetFileVersionInfo。此示例的一個問題是它需要 OEM 提供這種功能,不能始終有保證。

要查看程序集的版本可以使用 Reflection,如下所示:

//C#

using System.Reflection;
String ver = Assembly.GetExecutingAssembly().GetName().Version.ToString();

'VB

Imports System.Reflection;
Dim ver As String = [Assembly].GetExecutingAssembly().GetName().Version.ToString()

7.15. 有哪些技術可用于進行 .NET Compact Framework 后臺處理?

執行后臺處理牽涉到很多方面,要求非常仔細地進行設計。本文提供了一些有關充分利用后臺處理的建議,并提出了很多必須解決的問題:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/BackgroundProcess.asp

7.16. .NET Compact Framework 多線程有什么技巧?

了解如何通過 .NET Compact Framework 在 Windows 窗體應用程序中使用多線程。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmultithreadedapp.asp

7.17. 如何在智能設備應用程序中使用模糊處理?

了解如何使用 PreEmptive Dotfuscator 混淆器 (obfuscator) 來保護源代碼。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfobfuscation.asp

7.18. 如何使用加密服務來加密和解密數據?

請參見本 FAQ 中的主題“10.5.編寫基于 Windows Mobile 的 Pocket PC 簽名捕獲應用程序。”

7.19. 如何通過 .NET Compact Framework 檢索唯一的 Windows CE 設備 ID?

了解如何使用 .NET Compact Framework 從 Windows CE 設備中檢索設備 ID。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/retrievedeviceid.asp

您可以使用平臺調用來獲得基于 Windows Mobile 的 Pocket PC 的設備 ID(也就是所謂的序列號)。當應用程序運行時,這個快速入門在消息框中顯示該 ID。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/deviceid.aspx

7.20. 如何通過基于 Microsoft .NET Compact Framework 的應用程序發送短消息服務 (SMS) 消息?

這篇文章將向您介紹如何通過基于 .NET Compact Framework 的應用程序發送短消息服務 (SMS) 消息:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfsendsms.asp

7.21. 如何不使用 Control.Name 屬性確定事件的發送方?

這篇文章將討論假設 .NET Compact Framework 控件不支持 name 屬性,如何確定事件的發送方:
http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOsenderevent.asp

7.22. 如何在線程中調用方法參數?

可以在應用程序中使用線程來更新用戶界面,從而提高性能。Control 基類提供 Invoke、BeginInvoke 和 EndInvoke 方法以便在控件的創建線程中調用方法。不過 .NET Compact Framework 不支持異步 BeginInvoke 和 EndInvoke 調用。另外,對于同步調用,當前不支持將參數傳遞給 Invoke。這個快速入門通過一個自定義類 (ControlInvoker) 來提供后一種功能,它允許將參數傳遞給 Invoke 方法:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/controlinvoker.aspx

7.23. 如何創建通知和定時應用程序?

這個快速入門包含用于設置用戶通知和定時應用程序的平臺調用聲明和方法。您可以安排一個通知對話框在指定時間出現或響應通知。您也可以設置一個應用程序在指定時間運行或響應通知。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/notifications.aspx

7.24. 如何播放聲音?

這個快速入門演示了使用平臺調用來播放兩個 WAV 文件,一個用作嵌入式資源,另一個用作內容。此窗體包含兩個按鈕,一個播放作為嵌入式資源的 Chimes.wav,另一個播放作為獨立文件的 Chord.wav。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/playsounds.aspx

7.25. 如何使用命令行參數?

要在代碼中訪問命令行參數,只需修改 main 的定義,使之接受適當的參數。以下代碼演示了這種方法:

//C#

static void Main(string[] args)
{
// Do your thing here
}

'VB

Shared Sub Main(ByVal args() As String)
'Do your thing here
End Sub

為了在 Microsoft Visual Studio 2003 中進行調試,可以通過 IDE 設置命令行參數。從主菜單中選擇 Project->Project Name Properties。在 Property Pages 對話框中,選擇 Configuration Properties->Debugging。在 Command Line Arguments: 文本框中鍵入一個字符串。

7.26. 當使用被處置對象上的屬性或方法時,為什么會產生異常?

完整版的 .NET Framework 并不保證訪問被處置對象上的屬性或方法始終能成功。然而,在 .NET Framework 中訪問某些屬性(如 Text)通常能成功。由于 .NET Framework 和 .NET Compact Framework 在實現上的區別,在 .NET Compact Framework 中訪問被處置的對象上的方法或屬性幾乎都會失敗。

7.27. 如何獲得“Enter”、“TAB”和“Arrow”按鍵事件?

要獲得非字符鍵(例如箭頭鍵),應使用 KeyDown 和 KeyUp 事件。

以前,.NET Compact Framework 只支持一些選定控件(窗體、面板、文本框和自定義控件)上的按鍵事件。Service Pack 2 (SP2) 及更高版本支持所有控件的按鍵事件。

注:要按 Tab 鍵瀏覽控件,請將焦點設為第一個控件,否則按 Tab 鍵就無效。

由于一個已知的 bug,在鍵盤上按擊 Tab 鍵當前還無法在模擬器上使用,不過,要是模擬器使用了 SIP 就可以。

模擬器的這個問題似乎是由 Visual Studio 帶來的,而非 .NET Compact Framework 的問題。當 .NET Compact Framework 從 OS 接收到相應的本機 WM_KEY* 消息時,它就會激發 Key 事件。當您在模擬器下運行本機應用程序時,當您按下鍵盤上的 Tab 鍵時并無法獲得 WM_KEYDOWN。如果您在模擬器或實際的設備中使用 SIP,就不會有這樣的問題。

要下載最新的 Service Pack,請參見本 FAQ 中標題為“1.3.哪里可以下載最新的工具和軟件?”的項。

7.28. 如何刪除只讀文件?

使用 System.IO.FileInfo 類來訪問文件屬性。

//C#

System.IO.FileInfo fi = new System.IO.FileInfo("filename");
// remove readonly attribute
if ((fi.Attributes & System.IO.FileAttributes.ReadOnly) != 0)
fi.Attributes -= System.IO.FileAttributes.ReadOnly;
System.IO.File.Delete("filename");

'VB

Dim fi As New System.IO.FileInfo("filename")
'remove readonly attribute
If(fi.Attributes And System.IO.FileAttributes.ReadOnly) <> 0 Then
fi.Attributes -= System.IO.FileAttributes.ReadOnly
System.IO.File.Delete("filename")

7.29. 如何在運行時確定一個成員是否存在?

可以在運行時使用 Reflection 來確定一個成員是否存在。以下代碼演示了如何使用 Reflection 來訪問 Bitmap 對象的“Width”屬性和“GetPixel”方法。對于“Width”屬性,該代碼用一個“get”組件來枚舉所有“public”屬性,然后從中搜 索一個名為“Width”的屬性。

“GetPixel”示例演示了當一個已知函數的參數順序未知時,如何使用 Reflection 來調用它。此示例的建立是假設作者知道有一個名為“GetPixel”的方法,它帶有 x、y 像素位置,但不知道它們在參數列表中出現的順序。此示例枚舉了各個方法,從中搜索名為“GetPixel”的方法,然后枚舉參數列表,確定是第一個還是第 二個參數名為“X”。請記住,由于硬件像素格式的不同,在本示例中 GetPixel 的返回值可能與 SetPixel 設置的值不同。

Reflection 提供了許多在運行時確定功能的強大工具,要了解相關信息,請參考 System.Type 和 System.Reflection 命名空間的有關文檔。

//C#
using System.Reflection;
using System.Drawing;
Bitmap bm = new Bitmap(200, 100);
int width = 0;
// Explicitly set one pixel for testing
int x = 199;
int y = 20;
Color pixColor = Color.Black;
bm.SetPixel(x,y,Color.Magenta);
// Get the "Width" property
PropertyInfo[] propInfo =
bm.GetType().GetProperties(BindingFlags.GetProperty |
BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < propInfo.Length; i++)
{
if (propInfo[i].Name == "Width")
{
width = (int)propInfo[i].GetValue(bm, null);
break;
}
}
// Call the GetPixel method
MethodInfo[] methInfo = bm.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < methInfo.Length; i++)
{
if (methInfo[i].Name == "GetPixel")
{
ParameterInfo[] paramInfo = methInfo[i].GetParameters();
if (paramInfo.Length == 2)
{
object[] xy = new object[2];
if (paramInfo[0].Name == "x")
{
xy[0] = x;
xy[1] = y;
}
else
{
xy[1] = x;
xy[0] = y;
}
pixColor = (Color)methInfo[i].Invoke(bm, xy);
break;
}
'VB
Imports System.Reflection
Imports System.Drawing
Dim bm As New Bitmap(200, 100)
Dim width As Integer = 0
' Explicitly set one pixel for testing
Dim x As Integer = 199
Dim y As Integer = 20
Dim pixColor As Color = Color.Black
bm.SetPixel(x, y, Color.Magenta)
' Get the "Width" property
Dim propInfo As PropertyInfo() = _
bm.GetType().GetProperties((BindingFlags.GetProperty Or _
BindingFlags.Public Or BindingFlags.Instance))
Dim i As Integer
For i = 0 To propInfo.Length - 1
If propInfo(i).Name = "Width" Then
width = Fix(propInfo(i).GetValue(bm, Nothing))
Exit For
End If
Next i
' Call the SetPixel method
Dim methInfo As MethodInfo() = bm.GetType().GetMethods((BindingFlags.Public _
Or BindingFlags.Instance))
For i = 0 To methInfo.Length - 1
If methInfo(i).Name = "GetPixel" Then
Dim paramInfo As ParameterInfo() = methInfo(i).GetParameters()
If paramInfo.Length = 2 Then
Dim xy(1) As Object
If paramInfo(0).Name = "x" Then
xy(0) = x
xy(1) = y
Else
xy(1) = x
xy(0) = y
End If
pixColor = CType(methInfo(i).Invoke(bm, xy), Color)
Exit For
End If
End If
Next i

7.30. 如何以編程方式確定設備名稱?

設備名稱可以通過 System.Net 命名空間來訪問,如以下代碼所示。

//C#

String devName = System.Net.Dns.GetHostName();

'VB

Dim devName As String = System.Net.Dns.GetHostName()

7.31. 如何通過命令行構建 C# 智能設備項目?

逐行鍵入以下命令(為了顯示清晰,每個命令分為兩行):

set CFPath=%SystemDrive%"Program Files"Microsoft Visual Studio .NET 2003"
CompactFrameworkSDK"v1.0.5000"Windows CE
csc Form1.cs /noconfig /nostdlib /lib:"%CFPath%" /r:"%CFPath%"system.dll";"%CFPath%"
system.drawing.dll";"%CFPath%"system.windows.forms.dll";"%CFPath%"mscorlib.dll"

7.32. 如何中止執行的線程?

在 .NET Compact Framework 中,Thread 類沒有 Abort 方法,所以必須通過從執行過程返回來中止線程。通常,應用程序會通過設置全局變量來通知線程有一個關閉事件。然后主線程等待輔助線程完成處理,完成后再關 閉應用程序。以下 HOWTO 文章演示了如何實現。
http://msdn.microsoft.com/library/en-us/dncfhowto/html/stopmt.asp

7.33. 為什么我不能在基于 Windows Mobile 的 Pocket PC 模擬器上播放影片?

Windows Media Player 只能在基于 Windows Mobile 的 Pocket PC 2003 模擬器上使用。Windows Media Player 安裝包只能在通過 ActiveSync 連接的硬件設備上安裝,不能安裝在模擬器上。

7.34. 如何阻止窗體標題顯示在活動應用程序列表中?

基于 Windows Mobile 的 Pocket PC 中的 Active Programs 列表枚舉了所有打開的窗體。要阻止一個窗體顯示在列表中,只需將該窗體的標題設置為空字符串。以下示例顯示了如何只在列表中保留應用程序名稱,而窗體則通 過另一個窗體顯示:

//C#

string AppName = "MyApp";
Form1 form1 = new Form1();
this.Text = "";
form1.Text = AppName;
form1.ShowDialog();
this.Text = AppName;

'VB

Dim AppName As String = "MyApp"
Dim form1 As New Form1()
Me.Text = ""
form1.Text = AppName
form1.ShowDialog()
Me.Text = AppName

7.35. 如何通過控件的實例名稱訪問一個控件?

您可以使用 Reflection,通過控件的名稱來查找它的實例。下面是一些示例代碼:

//C#

private void Form1_Load(object sender, System.EventArgs e)
{
ComboBox c = (ComboBox)this.ControlFromName("combobox1");
c.Items.Add("1");
this.GetControls();
}
private Control ControlFromName(string name)
{
object o = this.GetType().GetField(name,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.IgnoreCase).GetValue(this);
return((Control)o);
}
private void GetControls()
{
System.Reflection.FieldInfo[] fis = this.GetType().GetFields
(
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.IgnoreCase
);
foreach(System.Reflection.FieldInfo fi in fis)
{
if (fi.GetValue(this) is Control)
MessageBox.Show(fi.Name);
}
}

'VB

Private Function ControlFromName(ByVal name As String) As Control
Dim o As ObjectDim o As Object
o = Me.GetType().GetField(name, Reflection.BindingFlags.NonPublic Or _
Reflection.BindingFlags.Instance Or _
Reflection.BindingFlags.IgnoreCase).GetValue(Me)
Return (CType(o, Control))
End Function
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim c As ComboBox
c = CType(ControlFromName("_combobox1"), ComboBox)
c.Items.Add("1")
Me.GetControls()e.GetControls()
End Sub
Private Sub GetControls()
Dim fis As System.Reflection.FieldInfo()
fis = Me.GetType().GetFields(Reflection.BindingFlags.NonPublic Or _
Reflection.BindingFlags.Instance Or _
Reflection.BindingFlags.IgnoreCase)
For Each fi As Reflection.FieldInfo In fis
If TypeOf (fi.GetValue(Me)) Is Control Then
MessageBox.Show(fi.Name)
End Ifnd If
Next
End Sub

7.36. 如何檢測硬件定向填充按鈕?

硬件定向填充按鈕可以通過標準按鍵事件來檢測,方法是比較 KeyEventArgs 參數中的 KeyCode。

//C#

protected override void OnKeyDown(KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
MessageBox.Show("Up Key Pressed");
break;
case Keys.Down:
MessageBox.Show("Down Key Pressed");
break;
case Keys.Left:
MessageBox.Show("Left Key Pressed");
break;
case Keys.Right:
MessageBox.Show("Right Key Pressed");
break;
}
base.OnKeyDown (e);
}

'VB

Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
Select Case e.KeyCode
Case Keys.Up
MessageBox.Show("Up Key Pressed")
Case Keys.Down
MessageBox.Show("Down Key Pressed")
Case Keys.Left
MessageBox.Show("Left Key Pressed")
Case Keys.Right
MessageBox.Show("Right Key Pressed")
End Select
MyBase.OnKeyDown(e)
End Sub 'OnKeyDown

7.37. 當只支持 Click 事件時,如何獲得雙擊事件?

請參見 .NET Compact Framework QuickStarts、Implementing Events 主題:
http://samples.gotdotnet.com/quickstart/compactframework/doc/btndclick.aspx

7.38. 如何獲得 onenter/onleave 風格的通知?

請參考 .NET Compact Framework QuickStarts?¢OnEnter/OnLeave 功能:
http://samples.gotdotnet.com/quickstart/compactframework/doc/enterleave.aspx

7.39. 如何在不掛起應用程序的模式對話框中使用線程處理?

創建一個行為像模式對話框的非模式對話框。

//C#

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
using System.ComponentModel;
public interface IModelessDialogCallback
{
void DialogResultCallback(DialogResult result);
}
public class Test : System.Windows.Forms.Form, IModelessDialogCallback
{
ModelessDialog dlg;
Button bShow;
int counter = 0;
protected override void OnLoad(EventArgs e)
{
this.Text = "Modal(less) Dialog Example";
this.bShow = new Button();
this.bShow.Parent = this;
this.bShow.Bounds = new Rectangle (10, 10, 150, 30);
this.bShow.Text = "Show Dialog";
this.bShow.Click += new EventHandler(this._Click);
this.dlg = new ModelessDialog(this);
}
private void _Click(object o, EventArgs e)
{
this.Enabled = false;
this.bShow.Text = "waiting for dlg";
dlg.Show();
}
public void DialogResultCallback(DialogResult result)
{
MessageBox.Show("dialog returned: " + (result == DialogResult.OK ? "OK" : "Cancel"));
this.Enabled = true;
this.bShow.Text = "Show Dialog:" + ++counter;
}
public static void Main()
{
Application.Run(new Test());
}
}
public class ModelessDialog : Form
{
IModelessDialogCallback parent;
Button bOK, bCancel;
public ModelessDialog(IModelessDialogCallback parent)
{
this.parent = parent;
this.Text = "Modeless Dialog";
this.bOK = new Button();
this.bOK.Parent = this;
this.bOK.Bounds = new Rectangle (10, 10, 150, 30);
this.bOK.Text = "OK";
this.bOK.Click += new EventHandler(this._Click);
this.bCancel = new Button();
this.bCancel.Parent = this;
this.bCancel.Bounds = new Rectangle (10, 50, 150, 30);
this.bCancel.Text = "Cancel";
this.bCancel.Click += new EventHandler(this._Click);
}
private void _Click(object o, EventArgs e)
{
this.Hide();
this.parent.DialogResultCallback(o == this.bOK ? DialogResult.OK : DialogResult.Cancel);
}
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
this.parent.DialogResultCallback(DialogResult.Cancel);
}
}

'VB

Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Collections
Imports System.ComponentModel
Public Interface IModelessDialogCallback
Sub DialogResultCallback(result As DialogResult)
End Interface IModelessDialogCallback'
Public Class Test
Inherits System.Windows.Forms.Form
Implements IModelessDialogCallback
Private dlg As ModelessDialog
Private bShow As Button
Private counter As Integer = 0
Protected Overrides Sub OnLoad(e As EventArgs)
Me.Text = "Modal(less) Dialog Example"
Me.bShow = New Button()
Me.bShow.Parent = Me
Me.bShow.Bounds = New Rectangle(10, 10, 150, 30)
Me.bShow.Text = "Show Dialog"
AddHandler Me.bShow.Click, AddressOf Me._Click
Me.dlg = New ModelessDialog(Me)
End Sub 'OnLoad
Private Sub _Click(o As Object, e As EventArgs)
Me.Enabled = False
Me.bShow.Text = "waiting for dlg"
dlg.Show()
End Sub '_Click
Public Sub DialogResultCallback(ByVal result As DialogResult) Implements _
IModelessDialogCallback.DialogResultCallback
MessageBox.Show(("dialog returned: " + IIf(result = DialogResult.OK, "OK", "Cancel")))
Me.Enabled = True
counter += 1
Me.bShow.Text = String.Format("Show Dialog: {0}", counter)
End Sub 'DialogResultCallback
Public Shared Sub Main()
Application.Run(New Test)
End Sub 'Main
End Class 'Test
Public Class ModelessDialog
Inherits Form
Private myParent As IModelessDialogCallback
Private bOK, bCancel As Button
Public Sub New(parent As IModelessDialogCallback)
Me.myParent = parent
Me.Text = "Modeless Dialog"
Me.bOK = New Button()
Me.bOK.Parent = Me
Me.bOK.Bounds = New Rectangle(10, 10, 150, 30)
Me.bOK.Text = "OK"
AddHandler Me.bOK.Click, AddressOf Me._Click
Me.bCancel = New Button()
Me.bCancel.Parent = Me
Me.bCancel.Bounds = New Rectangle(10, 50, 150, 30)
Me.bCancel.Text = "Cancel"
AddHandler Me.bCancel.Click, AddressOf Me._Click
End Sub 'New
Private Sub _Click(o As Object, e As EventArgs)
Me.Hide()
Me.myParent.DialogResultCallback(IIf(o Is Me.bOK, DialogResult.OK, DialogResult.Cancel))
End Sub '_Click
Protected Overrides Sub OnClosing(e As CancelEventArgs)
e.Cancel = True
Me.Hide()
Me.myParent.DialogResultCallback(DialogResult.Cancel)
End Sub 'OnClosing
End Class 'ModelessDialog

7.40. 如何有效地對浮點數進行取整?

對數字取整有兩個主要的方法:

?

Convert.ToInt32

?

Cast 或 Fix(C# 或 VB)

Convert.ToInt32 會自動處理取整,其中,余數為 .5 或更大會使數值向上取整。強制轉換或使用 Fix 需要將數值加 .5 以確保取整正確,因為這些方法只是刪除余數。

在模擬器和一個 Compaq iPAQ H3600 序列的設備上對每種方法進行 100 萬次操作得到了以下的分析結果,其中 num 是一個浮點數,值設置為 3.6F:


Emulator


iPAQ


Operation

Debug (ms)

Release (ms)

Debug (ms)

Release (ms)

C#: Convert.ToInt32(num)

1321

1109

6264

6283

C#: (int)(num + .5F)

170

49

1479

59

VB: Convert.ToInt32(num)

1218

1232

6531

6517

VB: Fix(num + .5F)

3873

3677

18144

17955

因此,通過檢驗設備的發布構建結果,可以得出結論:對于當前推出的設備,在 C# 中使用強制轉換最有效,而在 VB 中使用 Convert.ToInt32 最有效。在 C# 中,已證明強制轉換快 106 倍以上,而在 VB 中,Convert.ToInt32 快近 3 倍。

//C#

float temp = 3.6f;
int rounded1 = (int)(temp + .5f);
int rounded2 = Convert.ToInt32(temp);

'VB

Dim temp As Single = 3.6F
Dim rounded1 As Integer = Fix(temp + .5F)
Dim rounded2 As Integer = Convert.ToInt32(temp)

7.41. 當顯示模式對話框時,為什么 Control.Invoke 用了那么長時間?

當通過 ShowDialog 顯示一個模式對話框時,使用 Control.Invoke 會有一個已知的 bug。請下載最新的 .NET Compact Framework Service Pack 來修復這個問題:

最新的平臺更新和 .NET Compact Framework service pack 可以通過以下地址獲得:
http://msdn.microsoft.com/mobility/downloads/default.aspx

7.42. 是否有辦法檢索程序集的區域性信息?

區域性信息可以通過 Reflection 來檢索:

//C#

using System.Reflection;
using System.Globalization;
Assembly asm = Assembly.GetExecutingAssembly();
CultureInfo ci = asm.GetName().CultureInfo;

'VB

Imports System.Reflection
Imports System.Globalization
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim ci As CultureInfo = asm.GetName().CultureInfo

7.43. 當調用一些 System.Math 方法時,為什么會產生 NotSupportedException?

并非所有平臺都支持全部 Math 方法,不過它們包含在該 API 中以便能夠兼容。這些方法的實現可以用以下使用等效函數的實現來替代:

//C#

double angle = 1.2;
// sinh(double angle): (e^x - e^-x) / 2
double res = (Math.Exp(angle) - Math.Exp(-angle)) / 2.0;
// cosh(double angle): (e^x + e^-x) / 2
res = (Math.Exp(angle) + Math.Exp(-angle)) / 2.0;
// tanh(double angle): sinh / cosh
res = (Math.Exp(angle) - Math.Exp(-angle)) /
(Math.Exp(angle) + Math.Exp(-angle));

'VB

Dim angle As Double = 1.2
' sinh(double angle): (e^x - e^-x) / 2
Dim res As Double = (Math.Exp(angle) - Math.Exp(-angle)) / 2.0
' cosh(double angle): (e^x + e^-x) / 2
res = (Math.Exp(angle) + Math.Exp(-angle)) / 2.0
' tanh(double angle): sinh / cosh
res = (Math.Exp(angle) - Math.Exp(-angle)) / _
(Math.Exp(angle) + Math.Exp(-angle))
返回頁首

8. 通信和 Web 服務

8.1. 如何通過 TCP 套接字向桌面服務器發送數據?

請參見本 FAQ 中的主題“10.5.編寫基于 Windows Mobile 的 Pocket PC 簽名捕獲應用程序?!?。

8.2. 為什么我不能訪問本地主機上的 Web 服務?

不要在設備中使用本地主機來創建 Web 服務,因為本地主機指的是運行應用程序的設備,就像在設備本身中創建一樣。相反,應該使用機器名稱或 IP 地址。

8.3. 如何通過 Microsoft .NET Compact Framework 使用 Web 服務?

這篇文章說明了如何通過使用 .NET Compact Framework 的智能設備應用程序,以同步和異步方式調用 Web 服務:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfwebservices.asp

8.4. 如何通過代理提交 HTTP GET 請求?

要通過或不通過指定代理提交 HTTP GET 請求,應該: 使用 StreamReader,將 HTML 響應讀到字符數組緩沖中。然后在 ListBox 中顯示該響應,如以下屏幕快照所示:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/httpgetwithproxy.aspx

8.5. 如何使用 Web 服務?

這個快速入門描述了如何使用能為簡單運算提供結果的 Web 服務。此 Web 服務在完整版的 .NET Framework 快速入門中標題為“Write a Simple Web service”的文章中有所描述。這個快速入門為該 Web 服務提供了一個客戶端應用程序:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/xmlwebservice.aspx

8.6. 如何通過 Microsoft MapPoint 3.0 獲得映射?

這個快速入門描述了如何對 MapPoint Web 服務進行編程來獲得基于 Windows Mobile 的 Pocket PC 上指定位置的映射,如以下屏幕快照所示:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/mappointfindmap.aspx

8.7. 如何通過 MapPoint 3.0 獲得映射和方向?

這個快速入門描述了如何使用 MapPoint Web 服務來獲得指定位置之間帶有方向的映射,如以下屏幕快照所示:
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/mappointdirections.aspx

8.8. .NET Compact Framework 是否支持 NTLM 身份驗證?

推薦的解決方案是使用摘要式身份驗證來代替基本或 NTLM 身份驗證。 .NET Compact Framework 支持摘要式身份驗證。

8.9. 當使用阻塞套接字時,當 blocking 設置為 false 時為什么 Send 會引發 InvalidOperationException?

當在阻塞套接字中將 Blocking 設置為 false 時會出現一個已知的問題。當進行套接字編程(托管和本機)時有三個范例,強烈建議開發人員使用異步 I/O 函數來作為這個問題的解決方案。在托管代碼中 Select 效率很低,而普通的 case exception 代價也很高。下面詳細介紹了這三個范例,其中最后一個是最佳的方法。

?

在 阻塞套接字上使用阻塞調用(即,send()、recv() 等)。這是最簡單的方法,也可能是使用最普遍的。這些函數以同步方式執行操作,阻塞當前執行的線程。這是客戶端和多線程服務器最可接受的方式 (Microsoft 不建議每個客戶端使用一個線程,因為 Windows 中線程是很寶貴的)。請注意,雖然在一段未定時間內操作可能會阻塞(即,直到操作能夠完成),但大多數情況下它們會立即完成。

?

非 阻塞套接字與 select 或 poll 一起使用。使用相同的“阻塞”函數,但將套接字置為一種特殊模式,這種模式可以阻止套接字阻塞。當出現函數要阻塞的情況時,它就會返回一個錯誤代碼(在托 管代碼中,將會引發一個異常)。然后您可以使用 poll 或 select 來等待,直到某個時刻一個操作完成(select 允許您管理多個套接字,所以您只能在一個線程中處理多個客戶端),再執行操作。當創建這些調用時,操作系統中已沒有線程,所以這是唯一可行的方法。到目前 為止,使用這種機制導致在套接字編程中可能會使性能最嚴重地惡化。在托管代碼中這個問題更加突出,因為它會引發異常,這樣會使性能下降得更厲害。

?

在套接字中使用異步 I/O 函數。這是所有解決方案中最好的一種。它允許您以異步方式執行操作,并且會通過回調通知您。通常其性能會比使用帶 select 的非阻塞 I/O 更好,建議采用這種方法來實現(至少在本機代碼中)。

8.10. 如何創建 http-server?

獲得關于實現移動 Web 服務器體系結構的技術內涵。了解該體系結構中的用例、Web 服務器框架及未來的開發:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/NETCFMA.asp

8.11. 當通過 ReuseAddress 集調用 SetSocketOption 時為什么會產生異常?

這是 .NET Compact Framework 版本 1 中的一個已知問題。要解決這個問題,您可以 P/Invoke setsockopt,將 SO_REUSEADDR 設置為 true。

8.12. 當通過 WebRequest 命名空間,使用 SSL 與服務器通信時,為什么會產生套接字錯誤?

這是 .NET Compact Framework 中的一個已知問題。這個問題可以這樣解決:將 HttpWebRequest.AllowStreamWriteBuffering 設置為 True,并注釋掉對 ContentLength 的設置。

8.13. 當執行 HTTPWebRequest 時,為什么會產生無效塊長度錯誤呢?

這是一個已知問題,在 .NET Compact Framework Service Pack 第 2 版及更高版本中已修復。

要下載最新的 Service Pack,請參見本 FAQ 中標題為“1.3.哪里可以下載最新的工具和軟件?”的項。

返回頁首

9. SQL CE 和數據

9.1. 采用 .NET Compact Framework、SQL Server CE 和復制開發應用程序時有哪些開發注意事項?

這篇文章將詳細討論這個主題:
http://msdn.microsoft.com/msdnmag/issues/03/09/datapoints/toc.asp

9.2. 如何將合并復制與 .NET Compact Framework 一起使用?

這篇文章將討論如何在基于 .NET Compact Framework 的應用程序中以編程方式調用合并復制:
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmergereplication.asp

SQL Server CE 是一個管理設備數據的強大工具,但該數據必須保留在設備中,除非有一種方式可以將它復制到桌面 SQL Server 中??梢允褂煤喜椭苼砉芾砦挥谠O備本地的數據,然后當設備連接到 SQL Server 的實例時再將它合并。.NET Compact Framework 提供了 SqlCeReplication 對象,所以合并復制可以用編程方式執行。
http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlcemergereplication.aspx

9.3. 如何在 XML 中使用 ADO.NET 數據綁定?

按下列步驟進行:

1.

通過提供的 XML 文件創建一個 XML 架構文件 (.xsd)。

2.

加載 XML 數據及其架構以執行綁定。

3.

將該 XML 重新保存成一個文件。


http://samples.gotdotnet.com/quickstart/CompactFramework/doc/adonetdatabinding.aspx

9.4. 如何創建 SQL Server CE 數據庫?

您可以使用 .NET Compact Framework 來創建和管理 Windows CE .NET 設備中的 SQL Server CE 數據庫。這個快速入門介紹了如何實現:

?

創建一個 SQL CE 數據庫。

?

連接到 SQL CE 數據庫。

?

在 SQL CE 數據庫中創建一張表。

?

在 SQL CE 數據庫中插入一行。


http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlcedbcreate.aspx

9.5. 如何提交 SQL Server CE 參數化查詢?

您可以使用 .NET Compact Framework,通過用戶輸入在 SQL Server CE 數據庫中插入值。此示例顯示了如何實現:

?

設計一個 UI,以便用戶設置查詢值。

?

連接到一個 SQL CE 數據庫。

?

在 SQL CE 數據庫中插入含有用戶值的一行


http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlceparameterizedquery.aspx

9.6. 為什么使用 RDA 和 push 方法會因 27750 錯誤而失敗?

表現當進行以下調用時:

rda = new SqlCeRemoteDataAccess();

會產生一個本機錯誤代碼為 27750 的 SQLCeException 類型的錯誤。這個錯誤對應于“Cannot load sscemw20.dll or ssceca20.dll is missing or not registered.”(不能加載 sscemw20.dll,或 ssceca20.dll 丟失或沒有注冊。)

解決方案

在應用程序啟動時加載該庫,即使您不需要用到它。要加載該庫,您可以加載 SqlCeEngine 對象。

SqlCeEngine eng = new SqlCeEngine();
返回頁首

10. 其他信息

10.1. Pocket TaskVision 應用程序。

本文檔概述了 Pocket TaskVision 示例應用程序所特有的開發任務。與桌面系統相比,基于 Windows Mobile 的 Pocket PC 設備的存儲容量、內存更少,處理器也較為低端 — 本文檔將提到存儲和性能的一些注意事項。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/wnf_pkttaskvision.asp

10.2. 創建基于 .NET Compact Framework 的進程管理器。

在這篇文章中,可以了解到如何將結構作為字節數組加以封送。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/ProcessManager.asp

10.3. 使用 Microsoft .NET Compact Framework 開發移動游戲。

了解如何創建基于 .NET Compact Framework 的游戲。了解編寫面向小型設備游戲的主要需求,以及了解 .NET Compact Framework 如何輕松地處理它們。包括可以用來解除游戲限制的高級性能調優技術。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfgaming.asp

10.4. 創建基于 .NET Compact Framework 的 DateTimePicker 控件。

了解如何在基于 Windows Mobile 的 Pocket PC 項目中使用 DateTimePicker 托管類。.NET Compact Framework 為大多數控件提供托管類,但不支持 DateTimePicker 類。P/Invoke 本機控件的 Wrapper 類可以在網上找到,但此示例提供了一個純托管的 DateTimePicker 類,您可以在基于 Windows Mobile 的 Pocket PC 項目中使用它。該類和示例應用程序用 C# 和 Visual Basic .NET 兩種語言提供。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdatetimepicker.asp

10.5. 編寫基于 Windows Mobile 的 Pocket PC 簽名捕獲應用程序。

這篇文章討論了基于 Windows Mobile 的 Pocket PC 簽名示例應用程序。此示例包括一個在基于 Windows Mobile 的 Pocket PC 上運行的客戶端,它將簽名數據通過 TCP 套接字發送給在桌面上運行的服務器。數據是通過加密服務加密和解密的。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCSignatureApp.asp

10.6. 是否有非 Microsoft 網站提供有關開發基于 .NET Compact Framework 的應用程序的信息?

請參見 MSDN 移動與嵌入式技術開發人員中心的“Related Sites”部分:
http://msdn.microsoft.com/mobility/Community/related/default.aspx

返回頁首

11. 連接

11.1. 為什么我無法通過 ActiveSync 部署到 Windows CE 設備?

表現:當通過 ActiveSync 連接 Windows CE 設備時,會出現部署和調試(F5 和 Ctrl-F5)失敗,通常錯誤消息為“There were deployment errors.Continue?”

原因:由于 ActiveSync 3.5 和 3.6 不提供有關設備指令集的準確信息,所以 ConMan(用于設備連接的 Visual Studio .NET 2003 組件)無法使用 ActiveSync 返回的信息來將 Windows CE 設備映射到正確的 .NET Compact Framework 目標(MIPSII、ARMV4 等)。

解決辦法:安裝并運行單獨提供的 Windows CE 配置外接程序(下面提供鏈接)。對于 ARMV4 設備,一種替代辦法是在部署開始時選擇基于 Windows Mobile 的 Pocket PC 設備。

Windows CE 配置外接程序可以通過以下鏈接下載:
http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

11.2. 為什么我無法通過 ActiveSync 調試 CEPC 或其他任何基于 x86 的 Windows CE 設備?

表現:運行 Windows CE 設備配置外接程序之后,用戶就可以部署(不帶調試 (Ctrl-F5))到連接 CEPC 的 ActiveSync(或任何基于 x86 的 Windows CE 設備),但不能調試 (F5)。非基于 x86 的 Windows CE 設備不會有這個問題。

原因:調試 Windows CE 模擬器(也基于 x86)使用的 TCP 端口與 ActiveSync 用于調試基于 x86 的設備的端口相沖突。要支持模擬器調試,默認情況下必須禁用調試 CEPC 和其他 x86 設備。

解決辦法:以下解決辦法將允許調試 x86 設備,但禁用在 Windows CE 模擬器下調試。這種解決辦法需要 WinCEx86Device.reg 和 ProxyPorts.reg 文件,它們可以在 SDK utilities 目錄中找到:“"CompactFrameworkSDK"WinCE Utilities"WinCE Proxy Ports Reg”。

如果您沒有這些文件,可以通過以下鏈接下載:
http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

?

將 WinCEx86Device.reg 導入注冊表。現在您可以調試 x86 設備,但在 Windows CE 模擬器下調試會失敗。

?

要還原模擬器調試,可以刪除注冊表項“HKEY_LOCAL_MACHINE"SOFTWARE"Microsoft"Windows CE Services"ProxyPorts”,然后導入 ProxyPorts.reg。

11.3. 當設備中缺少 Toolhelp.dll 時為什么會調試失敗?

表現:按下 F5 后,包括應用程序可執行文件和 .NET Compact Framework cab 文件在內的所有文件都會復制到設備中,IDE 報告應用程序啟動成功,但在設備上什么都沒啟動。如果您檢查設備的 "windows 文件夾,toolhelp.dll 不存在。

原因: 一些設備映像可能不包含 SDE 調試所需要的 toolhelp.dll。

解決辦法:將 toolhelp.dll 從 Windows CE SDK 復制到設備的 "windows 文件夾中。對于每個設備,可以在相應的目標目錄中找到此文件。

例如,對于 ARM 設備:“"CompactFrameworkSDK"WinCE Utilities"ToolHelp"WinCE4"armv4”。

如果您沒有這個文件,可以通過以下鏈接下載:
http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

11.4. 當網絡協議數超過 50 時,為什么無法部署到設備?

表現:當按下 Ctrl-F5 或 F5 時會出現“deployment error”消息框。運行 EnumProtocols.exe 列出 50 多個協議。(EnumProtocols.exe 可以在 WinCE utilites 目錄:“"CompactFrameworkSDK"WinCE Utilities"EnumProtocols”中找到)。如果您沒有此文件,可以通過以下鏈接下載:
http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

原因:這是一個已知的問題,即當前機器中安裝的網絡協議數超過 50 時,.NET Framework 的 System.Net.Dns.GetHostName 方法會引發異常。這個方法是由 ConMan 調用的,而異常會導致 ConMan 傳輸初始化失敗。

解決辦法:卸載實際上不需要的網絡協議。一種方式是進入設備管理器(右鍵單擊“My Computer”,選擇 Properties->Hardware,按“Device Manager”按鈕)并刪除“Network adapters”下的未使用項。另一種方式是卸載已安裝了協議的應用程序。這些應用程序可以從 EnumProtocles.exe 的輸出中找到。

11.5. 卸載 ActiveSync 之后為什么無法通過 ActiveSync 部署到設備?

表現:當卸載 ActiveSync 之后,按下 Ctrl-F5 或 F5 會出現“deployment error”消息框。卸載 ActiveSync 通常發生在用戶升級 ActiveSync 時,比如從 3.5 版升級到 3.6 版。

原因:ConMan 利用“HKEY_LOCAL_MACHINE"SOFTWARE"Microsoft"Windows CE Services"ProxyPorts”下的一些注冊表值進行部署和通過 ActiveSync 調試。當 ActiveSync 卸載時,這些注冊表值會刪除。

解決辦法:重新安裝或修復 Visual Studio .NET 2003。一個比較簡單的修復辦法是導入 ProxyPorts.reg,可以在 WinCE utilities 文件夾中找到:“"CompactFrameworkSDK"WinCE Utilities"WinCE Proxy Ports Reg”。如果您沒有此文件,可以通過以下鏈接下載:
http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

可能需要 un-cradle/re-cradle 或軟重啟設備才能使修復生效。建議用戶永遠都不要卸載 ActiveSync。要升級 ActiveSync,應該直接安裝新版本,它會正確重寫舊版本。

11.6. 本地化機器名稱或用戶名為什么可能導致設備部署失敗?

表現:當機器名稱或登錄用戶名包含當前代碼頁中沒有的字符或 ASCII 值低于 0x20 的字符時,部署到設備會失敗,而部署到模擬器則工作正常。

原因: ConMan 內部的安全身份驗證以 ASCII 形式使用機器名和用戶名,它無法處理上述范圍中的字符。

解決辦法:不要在機器名和用戶名中使用上述字符。如果用戶對什么字符屬于這種范圍不清楚,只使用英文字母和數字總是安全的。

11.7. 如果登錄用戶不屬于 Administrators 組,為什么部署到設備會失敗?

表現:如果當前登錄用戶不在 Administrators 組中,部署到設備總會失敗,即使用戶在 Visual Studio Developers 組和 Debugger Users 組中。另一方面,部署到模擬器并進行調試則工作正常。

原因: 在設備部署期間,ConMan 代碼在內部打開文件的模式需要有管理員權限。

解決辦法: 將當前用戶添加到 Administrators 組,或者將部署目標只限制為模擬器。

11.8. 為什么部署到基于 Windows Mobile 的 Pocket PC 設備或模擬器會因共享沖突錯誤而失敗?

表現:當將一個應用程序部署到基于 Windows Mobile 的 Pocket PC 2002/2003 設備或模擬器時,部署會失敗,輸出消息類似于“Could not write to output file 'SmartDeviceApplication1.exe' - Sharing violation”。當同一個應用程序以前已經部署到同一臺設備或模擬器時,通常會出現這種問題。

原因:默認情況下,用于基于 Windows Mobile 的 Pocket PC 2002 或 2003(非 2000)的應用程序中的 X 按鈕并沒有關閉進程。它只是“最小化”應用程序窗口。當用戶試圖再次部署該應用程序時,“最小化”的實例會導致共享沖突并使部署失敗。另一種可能的原因是 用戶中途強行終止調試會話。

解決辦法:確保當再次部署時,設備或模擬器中的應用程序已經真正關閉。在基于 Windows Mobile 的 Pocket PC 中,要查看正在運行的進程,請轉到 Start->Settings->Memory->Running Programs。如果想要有一個按鈕能真正關閉應用程序,請顯式創建這樣的按鈕,或者將 Windows 窗體的 Minimize Box 屬性設置為 False,這樣X 按鈕就成了能關閉應用程序的 OK 按鈕。如果原因是手動終止調試會話,則可能需要軟重啟設備或模擬器。

11.9. 當模擬器第一次在 Windows Server 2003 機器上使用時,為什么會產生安全警告消息?

表現:當在 Windows Server 2003 機器上安裝 Visual Studio .NET 2003 之后,第一次使用模擬器時會彈出一個標題為“Security Alert — Driver Installation”的消息框。消息文本的開頭為“The driver software you are installing for:Virtual PC Application Services has been signed with Authenticode(TM) technology.The publisher's identity has been identified, and the driver has not been modified since it was published”。文本結束部分寫到“However, this driver cannot be tested by Microsoft Windows Hardware Quality Labs to verify its compatibility with this version of Windows. Do you trust this publisher and want to install the driver?”

原因:Visual Studio .NET 2003 安裝了一個 Virtual PC Application Services Emulator 驅動程序,它并沒有傳遞 Windows Server 2003 的 Driver Validation 系統的驗證結果。

解決辦法:當出現這種警告消息時,單擊 Yes 按鈕。否則模擬器將不工作。

11.10. 當模擬器在啟動時,為什么會產生關于丟失文件的錯誤消息?

表現:當模擬器在啟動時,會出現一個標題為“Emulator for Windows CE”的消息框,消息文本為“One or more files from the Emulator for Windows CE installation is missing.Please reinstall Emulator for Windows CE and try again.” 出現這個消息框之后,連接或部署到模擬器會失敗。

原因: 一個典型原因是模擬器驅動程序沒有安裝或已損壞。

解決辦法:轉到“Device Manager”(右鍵單擊“My Computer”,選擇“Properties->Hardware”并按“Device Manager”按鈕),檢查 System Devices 組中是否安裝“Virtual PC Application Services”。如果該驅動程序沒有安裝,則通過運行“"CompactFrameworkSDK"ConnectionManager"Bin" DriverInstall"Smart Devices Emulator.msi”來安裝。

注:運行 msi 文件之后確認出現“Virtual PC Application Services”。如果沒有出現,則重啟 PC 并嘗試再次安裝。

11.11. 為什么有時第一次模擬器部署嘗試會失敗?

表現:模擬器啟動緩慢,最終部署失敗并出現一條連接錯誤消息。啟動主要包括啟動模擬器映像和下載 .NET Compact Framework 文件。在低端機器上,當第一次使用模擬器,或者前一次使用“turn off”而非“saving state”來關閉模擬器時更容易發生這種失敗。

原因: 由于模擬器的某些性能問題,它的啟動需要很長時間,在 ConMan 超時時間內無法完成。

解決辦法:如果可能,當關閉模擬器時,始終選擇“saving state”而非“turn off”,這樣模擬器下一次啟動時啟動速度就會更快?;蛘咴诓渴鹬巴ㄟ^單擊“Connect to Device”按鈕來預啟動模擬器,該按鈕位于菜單欄中模擬器名稱的旁邊。請注意,當預啟動之后,第一次部署仍然會失敗。(請參閱關于這個問題的詳細信 息。)另外,鼠標懸停在模擬器映像上可能加速模擬器啟動。

11.12. 當通過 Connect to Device 按鈕啟動模擬器之后,為什么第一次部署嘗試失敗?

表現:當通過“Connect to Device”按鈕啟動模擬器時,第一次部署嘗試總是失敗。

解決辦法:通過此按鈕啟動模擬器之后第一次部署失敗這個問題目前還無法解決,但以后的部署嘗試就會成功。

11.13. 如果機器沒有網絡連接,為什么模擬器調試會失敗?

表現: 當機器沒有活動的網絡連接時,用模擬器調試 (F5) 無法工作,但不帶調試的部署 (Ctrl-F5) 卻能正常工作。

原因: 模擬器調試依賴于 TCP 傳輸。

解決辦法:在機器上安裝 Microsoft Loopback Adapter。

在 Microsoft Windows XP 中安裝 Microsoft Loopback Adapter

1.

打開“Control Panel”,選擇“Add Hardware”,然后選擇“Next”。

2.

選擇“Yes”,我已經連接了硬件,然后選擇“Next”。

3.

從 Installed hardware 列表中選擇“Add a new hardware device”,然后選擇“Next”。

4.

選擇“Install the hardware that I manually select from a list (Advanced) ”,然后選擇“Next”。

5.

從 Common hardware types 列表中選擇“Network adapters”,然后選擇“Next”。

6.

從 Manufacturer 列表中選擇“Microsoft”。

7.

從 Network Adapter 列表中選擇“Microsoft Loopback Adapter”,然后選擇“Next”。

8.

選擇“Next”,然后選擇“Finish”。

在 Microsoft Windows 2000 中安裝 Microsoft Loopback Adapter

1.

打開“Control Panel”,選擇“Add/Remove Hardware”,然后選擇“Next”。

2.

選擇“Add/Troubleshoot a device”,然后選擇“Next”。

3.

從 Devices 列表中選擇“Add a new device”,然后選擇“Next”。

4.

選擇“No”,我想從列表中選擇該硬件,然后選擇“Next。

5.

從 Hardware types 列表中選擇“Network adapters”,然后選擇“Next”。

6.

從 Manufacturers 列表中選擇“Microsoft”。

7.

從 Network Adapter 列表中選擇“Microsoft Loopback Adapter”,然后選擇“Next”。

8.

選擇“Next”,然后選擇“Finish”。

11.14. 如果模擬器使用 COM 端口,為什么無法引導(黑屏)?

表現:當模擬器映像啟動時,它始終保持黑屏。當模擬器配置為至少使用一個 COM 端口時出現這個問題。

原因:默認情況下,模擬器沒有分配 COM 端口,但用戶可能會更改配置,為該模擬器分配一個 COM 端口。當為模擬器分配的 COM 端口被 ActiveSync 或其他任何正在運行的應用程序使用時,模擬器映像就會加載失敗。

解決辦法:刪除所有為模擬器分配的 COM 端口,或者將它們更改為沒有被 ActiveSync 或其他任何正在運行的應用程序使用的端口。要在 Visual Studio .NET 2003 中刪除或更改 COM 端口配置,請轉到 Tools/Options/Devices,在 Devices 窗口中選擇一個模擬器,然后單擊 Configure 按鈕。

11.15. 為什么 Visual Studio .NET 2003 Emulator 無法和 eMbedded Visual Tools Emulator 一起同時工作?

表現:當 eMbedded Visual Tools (Platform Builder) Emulator 運行時,Visual Studio .NET 2003 Emulator 部署失敗,反之亦然。有時甚至在 Visual Studio .NET 2003 Emulator 關閉之后 eMbedded Visual Tools Emulator 仍然無法工作。

原因:Visual Studio .NET 2003 Emulator 和 eMbedded Visual Tools Emulator 在內部使用 Emulator.exe 的兩個不同實例,它們互相不兼容。因為它們共享相同的可執行文件名稱,而該 exe 是單實例的應用程序,這樣當用于 eMbedded Visual Tools 的 Emulator.exe 運行時,用于 Visual Studio .NET 2003 的那一個就不能啟動,反之亦然。另一個問題是當 Visual Studio .NET 2003 Emulator 用戶接口關閉時,emulator.exe 不會關閉,直到宿主 Visual Studio IDE 實例關閉為止。在這種情況下,即使沒有可見的模擬器在運行,eMbedded Visual Tools Emulator 也不能啟動。

解決辦法:不要同時使用兩個模擬器。如果一個模擬器不能啟動,請檢查任務管理器,關閉任何正在運行的 emulator.exe 進程。

11.16. 為什么我無法通過 TCP 連接(而非 ActiveSync 連接)部署到設備?

表現:當設備與 Visual Studio 機器沒有 ActiveSync 連接,但有一個有效的 TCP 連接時,部署無效。

原因:ConMan 利用 ActiveSync 連接在 Visual Studio 機器和設備之間執行一些初始設置。如果沒有可用的 ActiveSync 連接,則必須手動執行該設置。

解決辦法:使用單獨提供的 Keyman 工具來執行初始的設備設置,步驟如下:

?

選 擇正確風格的 Keyman.exe(比如 ARMV4 或 SH4 等),將它放在設備中。啟動 Keyman 并選擇“FILE->CONNECT”。現在 Keyman 等待 VS 機器通過 TCP/IP 來連接它。當 VS 機器連接之后斷開連接,這樣設備中的 Keyman 就會自動退出。

?

在 VS 機器中,將 CryptoAPIWrapper.dll 從 " CompactFrameworkSDK"ConnectionManager"bin 復制到 KeymanDesktop.exe 的目錄。啟動 KeymanDesktop.exe。

?

單擊“Save”,將設置保存在 KeymanDesktop.exe 正在運行的當前目錄中。下一次 exe 啟動時就會加載這個保存的默認值。

?

鍵入設備的 IP 地址

?

使用 Device Port 的推薦值。

?

鍵入 ConmanClient 位(例如 ConManClient.exe 駐留位)所在的“Target”目錄的路徑。典型值為 " CompactFrameworkSDK"ConnectionManager"Target。

?

使用 Connect 按鈕來進行連接。

?

連接之后單擊“prep device”。如果成功,會彈出一個對話框,告知您一切正常。

?

使用 Disconnect 按鈕來斷開連接。當您斷開連接時,設備端位會自動退出。

?

啟動設備中的 ConManClient.exe。首先,必須選擇某種風格的目標設備。另外,還必須選擇 Visual Studio 中“Target”目錄的位置。

11.17. 如何使 Activesync 能夠從 Visual Studio .NET 2003 連接到模擬器會話?

從 Windows Mobile Developer Power Toys 下載 Emulator ActiveSync Connection Tool:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

11.18. 如何將文件復制到當前連接到桌面 ActiveSync 的設備中?

從 Windows Mobile Developer Power Toys 下載 CECopy:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

11.19. 為什么 Visual Studio 調試器連接到 ARMV4I 設備失敗?

原因選擇 ARMV4I CPU 類型后連接工具存在的 bug

解決辦法配置用于 ARMV4T CPU 類型的工具:

1.

在 Visual Studio 中,在“Tools”菜單中單擊“Select Windows CE Device CPU”。注:此菜單項是由用于 Visual Studio .NET 2003 Add-on Pack 的 Windows CE Utilities 安裝的

2.

將設備體系結構更改為 ARMV4T

3.

單擊“Configure”,然后單擊“Close”。如果提示重啟,則重啟 Visual Studio

返回頁首

12. 基于 Windows Mobile 的 Smartphone

12.1. 從哪里可以獲得最新的基于 Windows Mobile 的 Smartphone SDK?

從這里可以下載 Windows Mobile 2003 Smartphone SDK:
http://www.microsoft.com/downloads/details.aspx?familyid=a6c4f799-ec5c-427c-807c-4c0f96765a81&displaylang=en

12.2. 基于 Windows Mobile 的 Smartphone 菜單的規則是什么?

基于 Windows Mobile 的 Smartphone 菜單有若干規則,例如:

?

第一個菜單項(對應于左邊的軟按鈕)不能有任何子項

?

第二個菜單項(對應于右邊的軟按鈕)可以有子項

?

其他任何頂級菜單項都不使用

如果第一個菜單項有不止一個項,則會產生 NotSupportedException。

要獲得完整的需求列表,請參考
基于 Windows Mobile 的 Smartphone 幫助文檔。

前面的鏈接是從 Windows Mobile 2003 Smartphone SDK 引用的:
http://www.microsoft.com/downloads/details.aspx?familyid=a6c4f799-ec5c-427c-807c-4c0f96765a81&displaylang=en

12.3. 當創建基于 Windows Mobile 的 Smartphone 項目時,為什么在工具箱會有禁用的控件?

基于 Windows Mobile 的 Smartphone 平臺只支持一小組控件。不支持的控件則禁用。

有關更多信息,請參考下面的
基于 Windows Mobile 的 Smartphone 幫助文檔。

前面的鏈接是從 Windows Mobile 2003 Smartphone SDK 引用的:
http://www.microsoft.com/downloads/details.aspx?familyid=a6c4f799-ec5c-427c-807c-4c0f96765a81&displaylang=en

12.4. 基于 Windows Mobile 的 Smartphone 是否支持 .NET Compact Framework 的 RAM 安裝?

不支持。.NET Compact Framework 是通過操作系統更新提供的,這取決于運營商 /OEM 的決定。因此,.NET Compact Framework 通常會作為更大的用于 Smartphone 的 Windows Mobile 操作系統更新的一部分提供。

12.5. 如何設置全屏多行編輯控件窗口的標題?

當前版本的 .NET Compact Framework 中不支持這項功能。

12.6. 如何通過現有的基于 Windows Mobile 的 Pocket PC CAB 文件生成基于 Windows Mobile 的 Smartphone CABWizSP XML 文檔?

從 Windows Mobile Developer Power Toys 下載 Convert PPC DAT to SP XML:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

12.7. 如何通過 ActiveSync 向基于 Windows Mobile 的 Smartphone 2003 Emulator 發送字符和字符串?

從 Windows Mobile Developer Power Toys 下載 TypeIt:
http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

12.8. 如何以編程方式設置基于 Windows Mobile 的 Smartphone 輸入模式?

可以根據以下代碼,使用 GetFocus 和 SendMessage API 來設置輸入模式:

'VB

Imports System.Runtime.InteropServices
Public Const EM_SETINPUTMODE As Integer = &HDE
Public Const EIM_SPELL As Integer = 0
Public Const EIM_AMBIG As Integer = 1
Public Const EIM_NUMBERS As Integer = 2
_
Public Shared Function GetFocus() As IntPtr
End Function
_
Public Shared Function SendMessage(ByVal hWnd As IntPtr, _
ByVal Message As Integer, ByVal wParam As Integer, _
ByVal lParam As Integer) As Integer
End Function
'Sample use setting TextBox to number input
Private Sub txtAmount_GotFocus(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles txtAmount.GotFocus
Dim hWnd As IntPtr
hWnd = Me.GetFocus()
SendMessage(hWnd, EM_SETINPUTMODE, 0, EIM_NUMBERS)
txtAmount.SelectionStart = txtAmount.Text.Length
End Sub

//C#

using System.Runtime.InteropServices;
public const uint EM_SETINPUTMODE = 0xDE;
public const uint EIM_SPELL = 0;
public const uint EIM_AMBIG = 1;
public const uint EIM_NUMBERS = 2;
[DllImport("coredll.dll")]
public static extern IntPtr GetFocus();
[DllImport("coredll.dll")]
public static extern int SendMessage(IntPtr hWnd,
uint Message, uint wParam, uint lParam);
// Sample use setting TextBox to number input
private void Form1_Load(object sender, System.EventArgs e)
{
txtAmount.GotFocus +=
new System.EventHandler(txtAmount_GotFocus);
}
private void txtAmount_GotFocus(object sender, System.EventArgs e)
{
IntPtr hWnd;
hWnd = GetFocus();
SendMessage(hWnd, EM_SETINPUTMODE, 0, EIM_NUMBERS);
txtAmount.SelectionStart = txtAmount.Text.Length;
}

轉載于:https://www.cnblogs.com/geoff/archive/2007/12/03/981435.html

總結

以上是生活随笔為你收集整理的Microsoft .NET Compact Framework 开发常见问题解答的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

男女爱爱好爽视频免费看 | 图片区 小说区 区 亚洲五月 | 国产偷国产偷精品高清尤物 | 国产香蕉97碰碰久久人人 | 人人爽人人澡人人人妻 | 欧美人与善在线com | 亚洲中文字幕在线观看 | 日韩成人一区二区三区在线观看 | 狂野欧美性猛xxxx乱大交 | 久久久精品欧美一区二区免费 | 一本精品99久久精品77 | 少妇人妻av毛片在线看 | 丝袜美腿亚洲一区二区 | 伊人久久婷婷五月综合97色 | 久久久www成人免费毛片 | 人人妻人人澡人人爽人人精品 | 高清无码午夜福利视频 | 男女爱爱好爽视频免费看 | 亚洲日韩av片在线观看 | 国产精品理论片在线观看 | 亚洲精品久久久久avwww潮水 | 激情国产av做激情国产爱 | 国产精品久久久一区二区三区 | 最新国产乱人伦偷精品免费网站 | 中文字幕无码av波多野吉衣 | 日本大乳高潮视频在线观看 | 国内精品久久久久久中文字幕 | 人人妻人人藻人人爽欧美一区 | 亚洲欧美色中文字幕在线 | 中文字幕无码av波多野吉衣 | 黑人巨大精品欧美一区二区 | 人妻天天爽夜夜爽一区二区 | 香港三级日本三级妇三级 | 学生妹亚洲一区二区 | 曰本女人与公拘交酡免费视频 | 中文亚洲成a人片在线观看 | 欧美老人巨大xxxx做受 | 日韩人妻无码一区二区三区久久99 | 久久久久人妻一区精品色欧美 | 欧美日韩久久久精品a片 | 久精品国产欧美亚洲色aⅴ大片 | 综合网日日天干夜夜久久 | 激情爆乳一区二区三区 | 丰满少妇女裸体bbw | 精品国产成人一区二区三区 | 国产人妻精品一区二区三区 | 在线亚洲高清揄拍自拍一品区 | 少妇性荡欲午夜性开放视频剧场 | 无套内谢的新婚少妇国语播放 | 欧美一区二区三区 | 久久久久成人片免费观看蜜芽 | 精品无码国产自产拍在线观看蜜 | 动漫av网站免费观看 | 久久久国产一区二区三区 | 日本高清一区免费中文视频 | 欧美大屁股xxxxhd黑色 | 天天综合网天天综合色 | 国产精品第一区揄拍无码 | 亚洲第一网站男人都懂 | 国模大胆一区二区三区 | 日韩精品无码一区二区中文字幕 | 精品熟女少妇av免费观看 | 男女爱爱好爽视频免费看 | 国产福利视频一区二区 | 粉嫩少妇内射浓精videos | 中国女人内谢69xxxx | 99久久精品国产一区二区蜜芽 | 人人妻人人澡人人爽人人精品 | 一本久久a久久精品vr综合 | 欧美国产日产一区二区 | 精品无码一区二区三区的天堂 | 欧美成人家庭影院 | 漂亮人妻洗澡被公强 日日躁 | 亚洲中文无码av永久不收费 | 在线精品亚洲一区二区 | 无码人妻少妇伦在线电影 | 国产亚洲tv在线观看 | 澳门永久av免费网站 | 国产精品无码久久av | 亚洲欧美日韩成人高清在线一区 | 亚洲欧洲中文日韩av乱码 | 欧美人与物videos另类 | 日本xxxx色视频在线观看免费 | 亚洲国产精品无码一区二区三区 | 图片区 小说区 区 亚洲五月 | 久久久久av无码免费网 | 性色欲网站人妻丰满中文久久不卡 | 久久99精品国产麻豆蜜芽 | 久久人人爽人人爽人人片av高清 | 东京一本一道一二三区 | 高中生自慰www网站 | 亚洲日韩乱码中文无码蜜桃臀网站 | 亚洲精品国偷拍自产在线观看蜜桃 | 色妞www精品免费视频 | 国产无av码在线观看 | 成年女人永久免费看片 | 人妻互换免费中文字幕 | 无码人妻丰满熟妇区毛片18 | 亚洲国产精品毛片av不卡在线 | 奇米影视7777久久精品 | 日本一卡二卡不卡视频查询 | 东京无码熟妇人妻av在线网址 | 国产精品美女久久久 | 免费无码av一区二区 | 国产亚洲精品久久久久久国模美 | 色一情一乱一伦一区二区三欧美 | 国产国语老龄妇女a片 | 亚洲日韩乱码中文无码蜜桃臀网站 | 狠狠噜狠狠狠狠丁香五月 | 蜜桃av抽搐高潮一区二区 | 婷婷丁香六月激情综合啪 | 少妇被黑人到高潮喷出白浆 | 日本成熟视频免费视频 | 国产精品久久久av久久久 | 秋霞成人午夜鲁丝一区二区三区 | 久久99精品国产麻豆 | 在线 国产 欧美 亚洲 天堂 | 最近中文2019字幕第二页 | 成人精品天堂一区二区三区 | 永久黄网站色视频免费直播 | 丝袜美腿亚洲一区二区 | 中文字幕+乱码+中文字幕一区 | 一本无码人妻在中文字幕免费 | 亚洲热妇无码av在线播放 | 国产精品第一国产精品 | 中文字幕无码av波多野吉衣 | 麻豆国产丝袜白领秘书在线观看 | 久久精品国产精品国产精品污 | 激情国产av做激情国产爱 | 欧美人与物videos另类 | 国产99久久精品一区二区 | 东京热男人av天堂 | 人人妻人人澡人人爽精品欧美 | 亚洲 高清 成人 动漫 | 亚洲啪av永久无码精品放毛片 | 中文字幕 人妻熟女 | 国产成人综合美国十次 | 少妇被粗大的猛进出69影院 | 国产sm调教视频在线观看 | 免费乱码人妻系列无码专区 | 欧美日韩一区二区三区自拍 | 野外少妇愉情中文字幕 | 高潮毛片无遮挡高清免费 | 国产三级久久久精品麻豆三级 | 无码人妻少妇伦在线电影 | 欧美日韩视频无码一区二区三 | 久久精品国产99久久6动漫 | 最新国产麻豆aⅴ精品无码 | 国产色精品久久人妻 | 中文字幕av日韩精品一区二区 | 午夜理论片yy44880影院 | 亚洲成a人片在线观看日本 | 无码国内精品人妻少妇 | 蜜桃臀无码内射一区二区三区 | 一本色道久久综合亚洲精品不卡 | 亚洲精品国产精品乱码不卡 | 精品国偷自产在线视频 | 亚洲欧美精品伊人久久 | 中文字幕无码免费久久99 | 伊人久久婷婷五月综合97色 | 欧美第一黄网免费网站 | 国内精品九九久久久精品 | 色欲综合久久中文字幕网 | 久久99热只有频精品8 | av无码久久久久不卡免费网站 | 精品偷自拍另类在线观看 | 日日躁夜夜躁狠狠躁 | 99久久精品午夜一区二区 | 久久亚洲国产成人精品性色 | 丝袜人妻一区二区三区 | 国产综合在线观看 | 97无码免费人妻超级碰碰夜夜 | 熟妇激情内射com | 亚洲熟悉妇女xxx妇女av | a国产一区二区免费入口 | 国产内射爽爽大片视频社区在线 | 日日摸夜夜摸狠狠摸婷婷 | 久9re热视频这里只有精品 | 最新国产乱人伦偷精品免费网站 | 国产极品视觉盛宴 | 激情内射日本一区二区三区 | 欧美人与牲动交xxxx | 欧美国产日韩久久mv | 亚洲国产精品无码久久久久高潮 | 精品人妻人人做人人爽夜夜爽 | 日产精品99久久久久久 | 亚洲中文字幕无码一久久区 | 国产精品va在线播放 | 在线播放亚洲第一字幕 | 人妻少妇精品无码专区二区 | 亚洲gv猛男gv无码男同 | 国内综合精品午夜久久资源 | 中文字幕乱妇无码av在线 | 青青久在线视频免费观看 | 亚洲中文字幕无码中字 | 亚洲一区二区三区偷拍女厕 | 99精品国产综合久久久久五月天 | 青青草原综合久久大伊人精品 | 精品久久久久久人妻无码中文字幕 | 日韩人妻无码一区二区三区久久99 | 日本精品人妻无码77777 天堂一区人妻无码 | 中文字幕人妻无码一区二区三区 | 麻豆国产丝袜白领秘书在线观看 | 窝窝午夜理论片影院 | 久久久精品456亚洲影院 | 久久国产精品萌白酱免费 | 亚洲国产成人a精品不卡在线 | 久久亚洲a片com人成 | 欧美 日韩 人妻 高清 中文 | 日本一区二区更新不卡 | 国产精品久久久久9999小说 | 国产9 9在线 | 中文 | 日本乱偷人妻中文字幕 | 精品乱子伦一区二区三区 | 日韩欧美成人免费观看 | 无码吃奶揉捏奶头高潮视频 | 亚洲综合伊人久久大杳蕉 | 无码国产激情在线观看 | 国产午夜亚洲精品不卡下载 | 日韩精品乱码av一区二区 | 国产午夜精品一区二区三区嫩草 | 久久久亚洲欧洲日产国码αv | 国产国语老龄妇女a片 | 日本大乳高潮视频在线观看 | 无码精品国产va在线观看dvd | 国产精品二区一区二区aⅴ污介绍 | 亚洲s色大片在线观看 | 男女爱爱好爽视频免费看 | 成人精品一区二区三区中文字幕 | 亚洲日韩av一区二区三区中文 | 大肉大捧一进一出视频出来呀 | 内射后入在线观看一区 | 国内少妇偷人精品视频 | 精品久久久久久亚洲精品 | 欧美老妇与禽交 | 俺去俺来也在线www色官网 | 老子影院午夜精品无码 | 青青青手机频在线观看 | 精品日本一区二区三区在线观看 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 一本加勒比波多野结衣 | 国产熟妇高潮叫床视频播放 | 成年美女黄网站色大免费全看 | 熟女少妇人妻中文字幕 | 岛国片人妻三上悠亚 | 国产精品自产拍在线观看 | 日欧一片内射va在线影院 | 国产又爽又猛又粗的视频a片 | 少妇久久久久久人妻无码 | 亚洲日韩av一区二区三区四区 | 国语精品一区二区三区 | 正在播放老肥熟妇露脸 | а天堂中文在线官网 | 欧美成人家庭影院 | 特黄特色大片免费播放器图片 | 久久国产36精品色熟妇 | 久久人妻内射无码一区三区 | 丰满诱人的人妻3 | 亚洲国产精品久久久久久 | 中文字幕av日韩精品一区二区 | 亚洲熟妇自偷自拍另类 | 4hu四虎永久在线观看 | 天天av天天av天天透 | 国产农村乱对白刺激视频 | 俺去俺来也在线www色官网 | 内射老妇bbwx0c0ck | 精品人妻中文字幕有码在线 | 国产色视频一区二区三区 | 亚洲欧美精品伊人久久 | 亚洲中文字幕无码一久久区 | 午夜肉伦伦影院 | 国产精品久久国产精品99 | 青春草在线视频免费观看 | 131美女爱做视频 | 小sao货水好多真紧h无码视频 | 国产精品毛片一区二区 | 国模大胆一区二区三区 | 欧美丰满少妇xxxx性 | 中文无码成人免费视频在线观看 | 扒开双腿疯狂进出爽爽爽视频 | 精品久久8x国产免费观看 | 国产精品无码mv在线观看 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 欧美丰满熟妇xxxx性ppx人交 | 99久久精品无码一区二区毛片 | 日本免费一区二区三区最新 | 国产精品高潮呻吟av久久4虎 | 亚洲精品一区二区三区四区五区 | 狠狠色色综合网站 | 乱人伦人妻中文字幕无码 | 无套内射视频囯产 | 久久久久亚洲精品男人的天堂 | 正在播放老肥熟妇露脸 | 国产精品理论片在线观看 | а√天堂www在线天堂小说 | 夜夜躁日日躁狠狠久久av | 亚洲 欧美 激情 小说 另类 | 午夜熟女插插xx免费视频 | 丰满少妇人妻久久久久久 | 国产suv精品一区二区五 | 97久久超碰中文字幕 | 国产成人精品视频ⅴa片软件竹菊 | 激情人妻另类人妻伦 | 中文无码精品a∨在线观看不卡 | 国产三级久久久精品麻豆三级 | 精品国产麻豆免费人成网站 | 亚洲色无码一区二区三区 | 中文字幕日韩精品一区二区三区 | 亚洲熟悉妇女xxx妇女av | 内射白嫩少妇超碰 | 国产精品对白交换视频 | 理论片87福利理论电影 | 国产麻豆精品精东影业av网站 | 国产亚洲精品久久久闺蜜 | 欧美人与牲动交xxxx | 久久综合香蕉国产蜜臀av | 性生交大片免费看女人按摩摩 | 日韩欧美群交p片內射中文 | 国产97人人超碰caoprom | 欧美丰满熟妇xxxx性ppx人交 | 麻豆国产丝袜白领秘书在线观看 | 熟女体下毛毛黑森林 | 亚洲va欧美va天堂v国产综合 | 久久99精品国产麻豆 | 亚洲熟女一区二区三区 | 国产精品无码一区二区桃花视频 | 18黄暴禁片在线观看 | 国产suv精品一区二区五 | 中文字幕中文有码在线 | www一区二区www免费 | 久久 国产 尿 小便 嘘嘘 | 小sao货水好多真紧h无码视频 | 99久久人妻精品免费二区 | 国产内射爽爽大片视频社区在线 | 精品国产一区二区三区四区 | 无码帝国www无码专区色综合 | 国产精品18久久久久久麻辣 | 成 人 网 站国产免费观看 | 波多野结衣高清一区二区三区 | 亚洲一区二区三区含羞草 | 久久人人爽人人爽人人片ⅴ | 亚洲毛片av日韩av无码 | 国产精品a成v人在线播放 | 日欧一片内射va在线影院 | 中文字幕日韩精品一区二区三区 | 在线欧美精品一区二区三区 | 日韩精品成人一区二区三区 | 日本欧美一区二区三区乱码 | 内射白嫩少妇超碰 | 老子影院午夜伦不卡 | 老司机亚洲精品影院 | 性做久久久久久久久 | 国产麻豆精品精东影业av网站 | 色欲av亚洲一区无码少妇 | 国产亚洲精品久久久久久国模美 | 久久国产36精品色熟妇 | 国产人成高清在线视频99最全资源 | 初尝人妻少妇中文字幕 | 日韩人妻无码一区二区三区久久99 | 波多野结衣av在线观看 | 亚洲一区二区三区在线观看网站 | 精品人妻人人做人人爽 | 草草网站影院白丝内射 | 亚洲欧美日韩国产精品一区二区 | 免费播放一区二区三区 | 男人扒开女人内裤强吻桶进去 | 精品国产一区二区三区av 性色 | 国产人妻人伦精品1国产丝袜 | 无码人妻丰满熟妇区毛片18 | 我要看www免费看插插视频 | 2020最新国产自产精品 | 正在播放老肥熟妇露脸 | 国产人妻久久精品二区三区老狼 | 中文字幕精品av一区二区五区 | 欧美成人免费全部网站 | 人人妻人人澡人人爽精品欧美 | 男女爱爱好爽视频免费看 | 熟女俱乐部五十路六十路av | 无人区乱码一区二区三区 | 久久天天躁狠狠躁夜夜免费观看 | 国产亚洲人成在线播放 | 丝袜足控一区二区三区 | 欧美 日韩 亚洲 在线 | 无码人妻精品一区二区三区下载 | 人妻无码αv中文字幕久久琪琪布 | 久久精品国产99久久6动漫 | yw尤物av无码国产在线观看 | v一区无码内射国产 | 国产av久久久久精东av | 国内揄拍国内精品人妻 | 无码一区二区三区在线观看 | 少妇高潮一区二区三区99 | 国产成人精品优优av | 久久久久人妻一区精品色欧美 | 成人免费无码大片a毛片 | 精品水蜜桃久久久久久久 | 亚洲色欲久久久综合网东京热 | 亚洲成在人网站无码天堂 | 国产人妻久久精品二区三区老狼 | 麻豆成人精品国产免费 | 少妇被黑人到高潮喷出白浆 | 精品国产一区二区三区四区在线看 | 免费国产成人高清在线观看网站 | 九九久久精品国产免费看小说 | 欧美xxxxx精品 | 国产亚洲欧美在线专区 | 亚洲国产高清在线观看视频 | 熟妇人妻无码xxx视频 | 亚洲精品国偷拍自产在线麻豆 | 亚洲精品中文字幕久久久久 | 国产办公室秘书无码精品99 | 色偷偷人人澡人人爽人人模 | 中文字幕+乱码+中文字幕一区 | 色一情一乱一伦一视频免费看 | 永久免费观看美女裸体的网站 | 日韩视频 中文字幕 视频一区 | 国产三级久久久精品麻豆三级 | 国产成人精品久久亚洲高清不卡 | 中国女人内谢69xxxx | 丰满诱人的人妻3 | 亚洲国产一区二区三区在线观看 | 无码乱肉视频免费大全合集 | 久久亚洲精品成人无码 | 波多野结衣高清一区二区三区 | 我要看www免费看插插视频 | 十八禁真人啪啪免费网站 | 欧美怡红院免费全部视频 | 一区二区三区乱码在线 | 欧洲 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 久久精品视频在线看15 | 国产人妻精品一区二区三区不卡 | 狠狠色噜噜狠狠狠狠7777米奇 | 欧美成人免费全部网站 | 九九在线中文字幕无码 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲成a人片在线观看无码3d | 久久国内精品自在自线 | 国产又爽又黄又刺激的视频 | 国产性生大片免费观看性 | 国产精品第一国产精品 | 荫蒂被男人添的好舒服爽免费视频 | 国产精品久久久久无码av色戒 | 欧美刺激性大交 | 激情内射日本一区二区三区 | 水蜜桃色314在线观看 | 少妇高潮一区二区三区99 | 免费网站看v片在线18禁无码 | 亚洲精品中文字幕乱码 | 波多野结衣乳巨码无在线观看 | 无码国内精品人妻少妇 | 精品久久久久香蕉网 | 午夜福利一区二区三区在线观看 | 爽爽影院免费观看 | 国产成人无码a区在线观看视频app | 在线观看国产一区二区三区 | 亚洲天堂2017无码 | 老熟女乱子伦 | 疯狂三人交性欧美 | 好男人社区资源 | 波多野结衣乳巨码无在线观看 | 中文精品久久久久人妻不卡 | 国产精品久久久久影院嫩草 | 日日天日日夜日日摸 | 四虎国产精品一区二区 | 四虎国产精品一区二区 | 人妻夜夜爽天天爽三区 | 少妇厨房愉情理9仑片视频 | 亚洲日韩中文字幕在线播放 | 久久成人a毛片免费观看网站 | 国产婷婷色一区二区三区在线 | 2020久久香蕉国产线看观看 | 妺妺窝人体色www婷婷 | 亚洲爆乳精品无码一区二区三区 | 欧美性黑人极品hd | 成熟女人特级毛片www免费 | 欧美国产日韩久久mv | 九九热爱视频精品 | yw尤物av无码国产在线观看 | 亚洲乱码国产乱码精品精 | 久久亚洲日韩精品一区二区三区 | 亚洲 日韩 欧美 成人 在线观看 | 又粗又大又硬又长又爽 | 国产精品久久久一区二区三区 | 国产精品久久精品三级 | 色诱久久久久综合网ywww | 午夜福利一区二区三区在线观看 | 日韩 欧美 动漫 国产 制服 | 国产高清av在线播放 | 欧美性色19p | 久久精品国产99久久6动漫 | 亚洲爆乳精品无码一区二区三区 | 国产乱人无码伦av在线a | 黑人巨大精品欧美一区二区 | 美女毛片一区二区三区四区 | 中文字幕无码乱人伦 | 亚洲欧美中文字幕5发布 | 色婷婷综合中文久久一本 | 草草网站影院白丝内射 | 亚洲中文字幕无码一久久区 | 成人无码精品1区2区3区免费看 | 荫蒂添的好舒服视频囗交 | 日韩人妻无码一区二区三区久久99 | 大肉大捧一进一出视频出来呀 | 天天拍夜夜添久久精品大 | 欧洲精品码一区二区三区免费看 | aa片在线观看视频在线播放 | 日本一卡二卡不卡视频查询 | 国产乱人伦av在线无码 | 国产精品免费大片 | 免费观看的无遮挡av | 国产人妻精品一区二区三区 | 精品国产一区av天美传媒 | 中文字幕无码av波多野吉衣 | 国产精品-区区久久久狼 | 97久久超碰中文字幕 | 久久午夜无码鲁丝片秋霞 | 人人爽人人澡人人人妻 | 国产精品永久免费视频 | 久久精品人妻少妇一区二区三区 | 高清国产亚洲精品自在久久 | 人妻少妇精品无码专区动漫 | 国产成人无码a区在线观看视频app | 国产一区二区三区日韩精品 | 久久久精品欧美一区二区免费 | 亚洲狠狠婷婷综合久久 | 天天综合网天天综合色 | 色婷婷综合中文久久一本 | 丰满人妻一区二区三区免费视频 | 亚洲爆乳精品无码一区二区三区 | 中文字幕乱码中文乱码51精品 | 国产精品资源一区二区 | 亚洲gv猛男gv无码男同 | 一个人看的视频www在线 | 伊在人天堂亚洲香蕉精品区 | 欧美人与禽zoz0性伦交 | 亚洲国产欧美日韩精品一区二区三区 | 天堂а√在线地址中文在线 | 美女扒开屁股让男人桶 | 日本精品人妻无码免费大全 | 国产精品国产自线拍免费软件 | 草草网站影院白丝内射 | 国产亚洲精品久久久久久久 | 亚洲国产精品久久久久久 | 久久久无码中文字幕久... | 人人妻人人澡人人爽欧美一区 | 九九热爱视频精品 | 色婷婷综合中文久久一本 | 中文字幕乱码人妻二区三区 | 女人和拘做爰正片视频 | 国内揄拍国内精品少妇国语 | 7777奇米四色成人眼影 | 内射白嫩少妇超碰 | 国产精品无码永久免费888 | 日本成熟视频免费视频 | 初尝人妻少妇中文字幕 | 狂野欧美激情性xxxx | 国产色xx群视频射精 | 内射后入在线观看一区 | 中文字幕无码日韩专区 | 99久久人妻精品免费一区 | 欧美性猛交内射兽交老熟妇 | 中文字幕无码av波多野吉衣 | 国产两女互慰高潮视频在线观看 | 97夜夜澡人人双人人人喊 | 亚洲色在线无码国产精品不卡 | 欧美熟妇另类久久久久久多毛 | av在线亚洲欧洲日产一区二区 | 亚洲成色在线综合网站 | 亚洲第一网站男人都懂 | 日日摸天天摸爽爽狠狠97 | 强奷人妻日本中文字幕 | 久久久久亚洲精品男人的天堂 | 中文毛片无遮挡高清免费 | 国产一区二区三区影院 | 色欲av亚洲一区无码少妇 | 国产精品毛片一区二区 | 亚洲成av人片在线观看无码不卡 | 一个人免费观看的www视频 | 亚洲成a人片在线观看无码3d | 久久精品国产99久久6动漫 | 久久久久久久久蜜桃 | 亚洲成熟女人毛毛耸耸多 | 18无码粉嫩小泬无套在线观看 | 宝宝好涨水快流出来免费视频 | 四十如虎的丰满熟妇啪啪 | 久久亚洲日韩精品一区二区三区 | 天堂亚洲2017在线观看 | 狂野欧美性猛交免费视频 | 娇妻被黑人粗大高潮白浆 | 免费网站看v片在线18禁无码 | 一本久道高清无码视频 | 美女极度色诱视频国产 | 波多野结衣一区二区三区av免费 | 99久久精品午夜一区二区 | 少妇高潮喷潮久久久影院 | 国产热a欧美热a在线视频 | 欧美人与禽zoz0性伦交 | 国产午夜亚洲精品不卡 | 国产麻豆精品一区二区三区v视界 | 牲欲强的熟妇农村老妇女视频 | 亚洲成a人片在线观看无码 | 欧美人与物videos另类 | 亚洲区欧美区综合区自拍区 | 97色伦图片97综合影院 | 欧美亚洲国产一区二区三区 | 亚洲日韩精品欧美一区二区 | 欧美精品在线观看 | 大屁股大乳丰满人妻 | 久久久久亚洲精品中文字幕 | 日产国产精品亚洲系列 | 国精产品一区二区三区 | 熟女体下毛毛黑森林 | 精品久久久久久人妻无码中文字幕 | 伊人久久大香线焦av综合影院 | 77777熟女视频在线观看 а天堂中文在线官网 | 荫蒂被男人添的好舒服爽免费视频 | 国产成人一区二区三区别 | 亚洲精品中文字幕乱码 | 99国产精品白浆在线观看免费 | 成人欧美一区二区三区黑人免费 | 国产精品视频免费播放 | 国产精品久久福利网站 | 97人妻精品一区二区三区 | 亚洲成在人网站无码天堂 | 免费观看的无遮挡av | 欧美日韩久久久精品a片 | 欧美真人作爱免费视频 | 久久久久久久久蜜桃 | 国产黄在线观看免费观看不卡 | 亚洲日韩av一区二区三区中文 | 久久久婷婷五月亚洲97号色 | 国产激情艳情在线看视频 | 久久综合给合久久狠狠狠97色 | 老熟女重囗味hdxx69 | 色偷偷人人澡人人爽人人模 | 黑人巨大精品欧美黑寡妇 | 国内精品人妻无码久久久影院蜜桃 | 中文字幕无码日韩专区 | 7777奇米四色成人眼影 | 亚洲天堂2017无码中文 | 色狠狠av一区二区三区 | 亚洲精品中文字幕乱码 | 精品国产一区二区三区av 性色 | 在线亚洲高清揄拍自拍一品区 | 亚洲国精产品一二二线 | 成 人影片 免费观看 | 兔费看少妇性l交大片免费 | 亚洲伊人久久精品影院 | 巨爆乳无码视频在线观看 | 又湿又紧又大又爽a视频国产 | 亚洲精品无码国产 | 亚洲中文字幕成人无码 | 亚洲色偷偷偷综合网 | 国产精品久久久久影院嫩草 | 无码精品人妻一区二区三区av | 亚洲 另类 在线 欧美 制服 | 久久国产精品偷任你爽任你 | 天天av天天av天天透 | 国产激情艳情在线看视频 | 人妻无码久久精品人妻 | 在线精品国产一区二区三区 | 又大又紧又粉嫩18p少妇 | 国产区女主播在线观看 | 狠狠综合久久久久综合网 | 又色又爽又黄的美女裸体网站 | 久久伊人色av天堂九九小黄鸭 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 性欧美大战久久久久久久 | 日韩人妻少妇一区二区三区 | 亚洲成a人片在线观看无码3d | 国产手机在线αⅴ片无码观看 | 欧美 亚洲 国产 另类 | 对白脏话肉麻粗话av | 国产成人无码av在线影院 | 日本熟妇浓毛 | 国色天香社区在线视频 | 国产午夜无码精品免费看 | 亚洲va中文字幕无码久久不卡 | 精品国偷自产在线视频 | 一本大道伊人av久久综合 | 色综合久久久无码中文字幕 | 国产成人无码午夜视频在线观看 | 亚洲日韩精品欧美一区二区 | 成在人线av无码免观看麻豆 | 日韩欧美成人免费观看 | 亚洲成a人片在线观看日本 | 人妻少妇精品无码专区动漫 | 国产精品无套呻吟在线 | 午夜福利一区二区三区在线观看 | 女人被男人躁得好爽免费视频 | 国产激情艳情在线看视频 | 国产69精品久久久久app下载 | 国产精品无套呻吟在线 | 东京无码熟妇人妻av在线网址 | 亚洲精品国偷拍自产在线观看蜜桃 | 98国产精品综合一区二区三区 | 精品国偷自产在线 | 精品一区二区三区波多野结衣 | 漂亮人妻洗澡被公强 日日躁 | 老熟妇仑乱视频一区二区 | 精品夜夜澡人妻无码av蜜桃 | 青青久在线视频免费观看 | 久久午夜无码鲁丝片秋霞 | 精品人妻av区 | av小次郎收藏 | 蜜臀aⅴ国产精品久久久国产老师 | 无码精品国产va在线观看dvd | 国产精品美女久久久久av爽李琼 | 中文无码成人免费视频在线观看 | 在线观看欧美一区二区三区 | 97夜夜澡人人双人人人喊 | 日本一区二区三区免费播放 | 无码精品国产va在线观看dvd | 亚洲性无码av中文字幕 | 天堂久久天堂av色综合 | 国产精品久久久久久亚洲影视内衣 | 日产国产精品亚洲系列 | 久久精品中文字幕大胸 | 波多野42部无码喷潮在线 | 精品亚洲韩国一区二区三区 | 国产极品美女高潮无套在线观看 | 无码人妻精品一区二区三区下载 | 无码人妻丰满熟妇区五十路百度 | 亚洲 高清 成人 动漫 | av无码久久久久不卡免费网站 | 无码国产乱人伦偷精品视频 | 欧美一区二区三区视频在线观看 | 亚洲国产精华液网站w | 少女韩国电视剧在线观看完整 | 窝窝午夜理论片影院 | 亲嘴扒胸摸屁股激烈网站 | 国产在热线精品视频 | 欧美猛少妇色xxxxx | 久久无码专区国产精品s | 精品国产一区av天美传媒 | 丁香啪啪综合成人亚洲 | 国产偷抇久久精品a片69 | 夜夜夜高潮夜夜爽夜夜爰爰 | 久久久久人妻一区精品色欧美 | 亚洲精品一区国产 | 青青青手机频在线观看 | 欧美野外疯狂做受xxxx高潮 | 亚洲 欧美 激情 小说 另类 | 久久人人爽人人爽人人片av高清 | 亚洲国产精品无码久久久久高潮 | 色一情一乱一伦一视频免费看 | 国产成人无码av在线影院 | 99久久久无码国产精品免费 | 免费观看黄网站 | 亚洲一区二区三区偷拍女厕 | 亚洲日韩乱码中文无码蜜桃臀网站 | 久久久中文字幕日本无吗 | 亚洲 欧美 激情 小说 另类 | 国产精品久久国产三级国 | 国产精品久久久 | 欧美人与禽zoz0性伦交 | 亚洲七七久久桃花影院 | 高清无码午夜福利视频 | 国产亚洲视频中文字幕97精品 | 四虎国产精品免费久久 | 性欧美牲交xxxxx视频 | 爆乳一区二区三区无码 | 成人片黄网站色大片免费观看 | 午夜福利电影 | 久久国产精品偷任你爽任你 | 丁香啪啪综合成人亚洲 | 欧美变态另类xxxx | 欧美激情综合亚洲一二区 | 国产激情无码一区二区 | 久久97精品久久久久久久不卡 | а天堂中文在线官网 | 又紧又大又爽精品一区二区 | 亚洲欧美日韩国产精品一区二区 | 国产精品人人爽人人做我的可爱 | 亚洲国产欧美日韩精品一区二区三区 | 国产亚洲精品久久久久久久久动漫 | 少妇性俱乐部纵欲狂欢电影 | 亚洲精品久久久久avwww潮水 | 亚洲一区二区三区播放 | 亚洲日韩乱码中文无码蜜桃臀网站 | 中文字幕无码人妻少妇免费 | 99精品久久毛片a片 | 精品久久久久久亚洲精品 | 国产午夜精品一区二区三区嫩草 | 俺去俺来也www色官网 | 成人毛片一区二区 | 国产一区二区三区影院 | 无码成人精品区在线观看 | 日本精品人妻无码77777 天堂一区人妻无码 | 漂亮人妻洗澡被公强 日日躁 | 18禁黄网站男男禁片免费观看 | 最近的中文字幕在线看视频 | 中文字幕亚洲情99在线 | 久9re热视频这里只有精品 | 国产精品无码一区二区桃花视频 | 在线a亚洲视频播放在线观看 | а√资源新版在线天堂 | 装睡被陌生人摸出水好爽 | 亚洲va中文字幕无码久久不卡 | 国产福利视频一区二区 | 亚洲第一无码av无码专区 | 狠狠cao日日穞夜夜穞av | 人妻尝试又大又粗久久 | 黑人大群体交免费视频 | 日欧一片内射va在线影院 | 国产激情精品一区二区三区 | 无遮挡国产高潮视频免费观看 | 捆绑白丝粉色jk震动捧喷白浆 | 老司机亚洲精品影院无码 | 对白脏话肉麻粗话av | 国产av一区二区精品久久凹凸 | 久热国产vs视频在线观看 | 对白脏话肉麻粗话av | 国产无套粉嫩白浆在线 | 国内精品一区二区三区不卡 | 熟妇激情内射com | 免费看男女做好爽好硬视频 | 亚洲中文字幕无码中文字在线 | 曰本女人与公拘交酡免费视频 | 亚洲综合精品香蕉久久网 | 国产色xx群视频射精 | 娇妻被黑人粗大高潮白浆 | 色 综合 欧美 亚洲 国产 | 欧美人与物videos另类 | 亚洲色欲久久久综合网东京热 | 乱码午夜-极国产极内射 | 日日摸夜夜摸狠狠摸婷婷 | 亚洲色偷偷男人的天堂 | 日韩av无码中文无码电影 | 亚洲成av人片在线观看无码不卡 | 麻豆精产国品 | 欧美日韩一区二区综合 | 国产乱人伦偷精品视频 | 国产精品久久久久久亚洲影视内衣 | 乱人伦中文视频在线观看 | 日日摸夜夜摸狠狠摸婷婷 | 亚洲精品无码国产 | 国产精品毛片一区二区 | 色婷婷欧美在线播放内射 | 亚洲中文字幕无码一久久区 | 无码人妻少妇伦在线电影 | 东京一本一道一二三区 | 永久免费观看美女裸体的网站 | av无码不卡在线观看免费 | 成人性做爰aaa片免费看不忠 | 日本精品人妻无码免费大全 | 强伦人妻一区二区三区视频18 | 国产办公室秘书无码精品99 | 十八禁视频网站在线观看 | 丰满岳乱妇在线观看中字无码 | 领导边摸边吃奶边做爽在线观看 | 在线观看国产午夜福利片 | 激情国产av做激情国产爱 | 亚洲无人区午夜福利码高清完整版 | 精品久久8x国产免费观看 | 一本久久a久久精品vr综合 | 天堂亚洲免费视频 | 精品乱码久久久久久久 | 日本丰满熟妇videos | 无码av免费一区二区三区试看 | 亚洲人成影院在线观看 | 日韩无码专区 | 精品国产精品久久一区免费式 | 亚洲va欧美va天堂v国产综合 | 国产人妻人伦精品1国产丝袜 | 无码吃奶揉捏奶头高潮视频 | 妺妺窝人体色www在线小说 | 一个人免费观看的www视频 | 亚洲中文字幕无码中文字在线 | 国产一区二区不卡老阿姨 | 欧美zoozzooz性欧美 | 亚洲一区二区三区在线观看网站 | 国产黄在线观看免费观看不卡 | 无遮挡国产高潮视频免费观看 | 色一情一乱一伦 | av无码电影一区二区三区 | 欧美第一黄网免费网站 | 欧美老熟妇乱xxxxx | 久久伊人色av天堂九九小黄鸭 | 亚洲码国产精品高潮在线 | 午夜男女很黄的视频 | 欧美人妻一区二区三区 | 人妻aⅴ无码一区二区三区 | 亚洲成在人网站无码天堂 | 欧美三级不卡在线观看 | 国产一区二区不卡老阿姨 | 日本护士xxxxhd少妇 | 成年美女黄网站色大免费视频 | 久久精品中文闷骚内射 | 国产无遮挡又黄又爽又色 | 亚洲色www成人永久网址 | 色欲综合久久中文字幕网 | 亚洲精品中文字幕久久久久 | 欧美大屁股xxxxhd黑色 | 久精品国产欧美亚洲色aⅴ大片 | 久久精品国产大片免费观看 | 国产精品久久福利网站 | 国内精品久久久久久中文字幕 | 国产乱码精品一品二品 | 国产精品人人妻人人爽 | 日日天日日夜日日摸 | 大肉大捧一进一出好爽视频 | 亚洲а∨天堂久久精品2021 | 欧美日韩色另类综合 | 婷婷六月久久综合丁香 | 精品无人区无码乱码毛片国产 | yw尤物av无码国产在线观看 | 黑人玩弄人妻中文在线 | 亚洲爆乳精品无码一区二区三区 | 久久亚洲日韩精品一区二区三区 | 日韩人妻无码中文字幕视频 | 国产网红无码精品视频 | 精品无码一区二区三区爱欲 | 久久久久久久久888 | 国产三级精品三级男人的天堂 | 日韩无码专区 | 欧美黑人巨大xxxxx | 国产精品无码一区二区三区不卡 | 色综合视频一区二区三区 | 无码国产乱人伦偷精品视频 | 日韩视频 中文字幕 视频一区 | 日本一本二本三区免费 | 激情爆乳一区二区三区 | 亚洲日本一区二区三区在线 | 麻豆人妻少妇精品无码专区 | 97色伦图片97综合影院 | 成人欧美一区二区三区黑人免费 | 国产深夜福利视频在线 | 久久无码中文字幕免费影院蜜桃 | 九九在线中文字幕无码 | 国产尤物精品视频 | 强伦人妻一区二区三区视频18 | 一本久道久久综合狠狠爱 | 2020久久香蕉国产线看观看 | 国产人妻精品一区二区三区不卡 | 国产小呦泬泬99精品 | 精品欧洲av无码一区二区三区 | 色欲av亚洲一区无码少妇 | 国产特级毛片aaaaaaa高清 | 欧美人与动性行为视频 | 日韩少妇内射免费播放 | 野外少妇愉情中文字幕 | 国产尤物精品视频 | 粉嫩少妇内射浓精videos | 欧美一区二区三区视频在线观看 | 免费人成网站视频在线观看 | 牛和人交xxxx欧美 | 狂野欧美激情性xxxx | 免费中文字幕日韩欧美 | 亚洲精品美女久久久久久久 | 国产做国产爱免费视频 | 亚洲欧美精品aaaaaa片 | 无码人妻黑人中文字幕 | 麻豆精品国产精华精华液好用吗 | 在线天堂新版最新版在线8 | 伊人久久大香线蕉av一区二区 | 亚洲gv猛男gv无码男同 | 亚洲欧美综合区丁香五月小说 | 精品亚洲成av人在线观看 | 精品一区二区三区波多野结衣 | 色综合天天综合狠狠爱 | 粉嫩少妇内射浓精videos | 日本xxxx色视频在线观看免费 | 国产熟妇另类久久久久 | 国产人妻大战黑人第1集 | 少妇无码吹潮 | 亚洲色在线无码国产精品不卡 | 一区二区传媒有限公司 | 成人性做爰aaa片免费看 | 国产偷自视频区视频 | 在线亚洲高清揄拍自拍一品区 | 永久免费精品精品永久-夜色 | 欧美黑人巨大xxxxx | 国产成人综合美国十次 | 国产精品无码一区二区三区不卡 | 亚洲精品美女久久久久久久 | 麻花豆传媒剧国产免费mv在线 | 中文字幕人妻无码一夲道 | 国产精品二区一区二区aⅴ污介绍 | 一个人免费观看的www视频 | 老头边吃奶边弄进去呻吟 | 亚洲精品中文字幕久久久久 | 国产亚洲人成a在线v网站 | 久久精品国产亚洲精品 | 曰韩少妇内射免费播放 | 国产在线精品一区二区高清不卡 | 久久99精品久久久久婷婷 | 午夜男女很黄的视频 | 成人精品视频一区二区 | 成人无码精品1区2区3区免费看 | 九一九色国产 | 青草青草久热国产精品 | 日韩成人一区二区三区在线观看 | 亚洲男人av香蕉爽爽爽爽 | 亚洲精品美女久久久久久久 | 日韩成人一区二区三区在线观看 | 久久亚洲中文字幕无码 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产性生交xxxxx无码 | 亚洲国产精品毛片av不卡在线 | 搡女人真爽免费视频大全 | 免费观看激色视频网站 | 婷婷六月久久综合丁香 | 亚洲经典千人经典日产 | 无码中文字幕色专区 | 国产激情综合五月久久 | 亚洲日韩中文字幕在线播放 | 狠狠色丁香久久婷婷综合五月 | 人人澡人摸人人添 | 日韩视频 中文字幕 视频一区 | 国产成人精品优优av | 亚洲精品国产品国语在线观看 | 国产精品久久福利网站 | 成人一在线视频日韩国产 | 一本色道久久综合亚洲精品不卡 | 亚洲人成影院在线无码按摩店 | 捆绑白丝粉色jk震动捧喷白浆 | 偷窥日本少妇撒尿chinese | 中文字幕无码乱人伦 | 亚洲gv猛男gv无码男同 | 亚洲色偷偷偷综合网 | 高清不卡一区二区三区 | 色狠狠av一区二区三区 | 欧美丰满熟妇xxxx性ppx人交 | 欧美成人午夜精品久久久 | 国产精品无码一区二区三区不卡 | 久9re热视频这里只有精品 | 精品亚洲韩国一区二区三区 | 久久精品无码一区二区三区 | 国产在线精品一区二区高清不卡 | 天天爽夜夜爽夜夜爽 | 中文字幕av无码一区二区三区电影 | 成人试看120秒体验区 | 2020久久香蕉国产线看观看 | 无遮挡国产高潮视频免费观看 | 天堂无码人妻精品一区二区三区 | 成人无码视频在线观看网站 | 亚洲精品国产a久久久久久 | 久久国产精品偷任你爽任你 | 久久国产精品萌白酱免费 | 亚洲自偷自拍另类第1页 | 秋霞成人午夜鲁丝一区二区三区 | 男女猛烈xx00免费视频试看 | 中文字幕 亚洲精品 第1页 | 日本免费一区二区三区最新 | 窝窝午夜理论片影院 | 丰满人妻一区二区三区免费视频 | 2019午夜福利不卡片在线 | 国产午夜无码视频在线观看 | 小鲜肉自慰网站xnxx | 免费看少妇作爱视频 | 撕开奶罩揉吮奶头视频 | 人人妻人人澡人人爽欧美一区 | 性欧美大战久久久久久久 | 国内精品一区二区三区不卡 | a国产一区二区免费入口 | 日本乱偷人妻中文字幕 | 久久精品99久久香蕉国产色戒 | 日本一卡二卡不卡视频查询 | 国内老熟妇对白xxxxhd | 国产精品久久久av久久久 | 欧美精品免费观看二区 | 国产成人久久精品流白浆 | 亚洲国产一区二区三区在线观看 | 久久午夜无码鲁丝片秋霞 | 久久综合狠狠综合久久综合88 | 国产成人午夜福利在线播放 | 人人妻人人澡人人爽人人精品浪潮 | 精品人妻人人做人人爽夜夜爽 | 久久www免费人成人片 | 在线观看免费人成视频 | 日本精品少妇一区二区三区 | 蜜臀av无码人妻精品 | 无码av最新清无码专区吞精 | 婷婷色婷婷开心五月四房播播 | 国产乱人伦偷精品视频 | 国产激情综合五月久久 | 扒开双腿吃奶呻吟做受视频 | 欧洲极品少妇 | 狠狠躁日日躁夜夜躁2020 | 97色伦图片97综合影院 | 夜夜夜高潮夜夜爽夜夜爰爰 | 久久久久人妻一区精品色欧美 | 亚洲乱码中文字幕在线 | 色五月五月丁香亚洲综合网 | 人人妻人人澡人人爽欧美一区九九 | 日本精品久久久久中文字幕 | 亚洲熟妇色xxxxx亚洲 | 亚洲中文无码av永久不收费 | 亚洲人成影院在线观看 | 色爱情人网站 | 无码成人精品区在线观看 | 中文精品久久久久人妻不卡 | 人妻尝试又大又粗久久 | 青草青草久热国产精品 | 在线观看国产午夜福利片 | 中文字幕无码av激情不卡 | 午夜性刺激在线视频免费 | 亚洲欧美精品aaaaaa片 | 亚洲欧美日韩国产精品一区二区 | 久久久婷婷五月亚洲97号色 | 中文字幕无码免费久久99 | 又色又爽又黄的美女裸体网站 | 日韩无套无码精品 | 久久久久久久女国产乱让韩 | 成人无码精品1区2区3区免费看 | 丰满护士巨好爽好大乳 | 国产一区二区不卡老阿姨 | 亚洲爆乳大丰满无码专区 | 水蜜桃色314在线观看 | 男人和女人高潮免费网站 | 亚洲精品一区二区三区大桥未久 | 无码成人精品区在线观看 | 天堂а√在线中文在线 | 精品国产一区av天美传媒 | 久久久精品456亚洲影院 | 狠狠色噜噜狠狠狠7777奇米 | 国产69精品久久久久app下载 | 国产网红无码精品视频 | 国产明星裸体无码xxxx视频 | 波多野结衣av一区二区全免费观看 | 精品国产青草久久久久福利 | 国产肉丝袜在线观看 | 熟女少妇在线视频播放 | 精品少妇爆乳无码av无码专区 | 欧美性生交活xxxxxdddd | 丰满护士巨好爽好大乳 | 亚洲成av人片在线观看无码不卡 | 国产一精品一av一免费 | 图片小说视频一区二区 | 在线欧美精品一区二区三区 | 无码播放一区二区三区 | 水蜜桃亚洲一二三四在线 | 天堂在线观看www | 欧洲欧美人成视频在线 | 国产suv精品一区二区五 | 国产精品久久国产三级国 | 粉嫩少妇内射浓精videos | 99er热精品视频 | 亚洲精品久久久久中文第一幕 | 55夜色66夜色国产精品视频 | 亚洲精品一区三区三区在线观看 | 中文毛片无遮挡高清免费 | 波多野结衣乳巨码无在线观看 | 无码免费一区二区三区 | 亚洲中文字幕乱码av波多ji | 亚洲精品综合五月久久小说 | 久久99精品久久久久婷婷 | 岛国片人妻三上悠亚 | 无码精品人妻一区二区三区av | 女人和拘做爰正片视频 | 人妻少妇精品无码专区动漫 | 午夜时刻免费入口 | 久久精品女人天堂av免费观看 | 中文字幕无线码免费人妻 | 午夜时刻免费入口 | 国产在线一区二区三区四区五区 | 一二三四在线观看免费视频 | 暴力强奷在线播放无码 | 性色欲网站人妻丰满中文久久不卡 | 亚洲小说春色综合另类 | 亚洲一区二区三区含羞草 | 日韩av激情在线观看 | 国产亚洲精品久久久久久国模美 | av在线亚洲欧洲日产一区二区 | 婷婷丁香六月激情综合啪 | 久久国产精品二国产精品 | 久久精品视频在线看15 | av无码久久久久不卡免费网站 | 久久久久国色av免费观看性色 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 成人综合网亚洲伊人 | 精品欧美一区二区三区久久久 | 国产高清不卡无码视频 | 国产精品va在线观看无码 | 亚洲欧美中文字幕5发布 | 国产精品丝袜黑色高跟鞋 | 牲欲强的熟妇农村老妇女视频 | 一个人看的www免费视频在线观看 | 久久婷婷五月综合色国产香蕉 | 国产超碰人人爽人人做人人添 | а√天堂www在线天堂小说 | 亚洲欧美色中文字幕在线 | 欧美日本免费一区二区三区 | 成人无码影片精品久久久 | 亚洲经典千人经典日产 | 免费无码av一区二区 | 亚洲欧美国产精品久久 | 国产 浪潮av性色四虎 | 成人亚洲精品久久久久软件 | 久久aⅴ免费观看 | 日本一卡2卡3卡四卡精品网站 | 久久国内精品自在自线 | 两性色午夜视频免费播放 | 少妇邻居内射在线 | 国产极品美女高潮无套在线观看 | 久久久精品成人免费观看 | 狂野欧美性猛xxxx乱大交 | 日本大香伊一区二区三区 | 亚洲国产欧美在线成人 | 麻豆人妻少妇精品无码专区 | 国产亚洲精品久久久ai换 | 精品夜夜澡人妻无码av蜜桃 | 精品国产aⅴ无码一区二区 | 久精品国产欧美亚洲色aⅴ大片 | 日韩精品无码一本二本三本色 | 久久亚洲精品中文字幕无男同 | 国产精品无码一区二区桃花视频 | 思思久久99热只有频精品66 | 欧美大屁股xxxxhd黑色 | 99久久久国产精品无码免费 | 国内揄拍国内精品少妇国语 | 亚洲码国产精品高潮在线 | 国产精品视频免费播放 | 精品少妇爆乳无码av无码专区 | 无码一区二区三区在线 | 亚洲无人区午夜福利码高清完整版 | 久久视频在线观看精品 | 中文字幕日产无线码一区 | 无码人妻精品一区二区三区下载 | 国产又爽又猛又粗的视频a片 | 日韩 欧美 动漫 国产 制服 | 任你躁在线精品免费 | 美女张开腿让人桶 | 国产手机在线αⅴ片无码观看 | 色一情一乱一伦一区二区三欧美 | 免费看男女做好爽好硬视频 | 成人精品天堂一区二区三区 | 久久精品国产一区二区三区肥胖 | 国产成人精品无码播放 | 久精品国产欧美亚洲色aⅴ大片 | 中文字幕精品av一区二区五区 | 小泽玛莉亚一区二区视频在线 | 亚洲 另类 在线 欧美 制服 | 波多野结衣aⅴ在线 | 中文字幕乱码人妻二区三区 | 国产高潮视频在线观看 | 内射爽无广熟女亚洲 | 荫蒂被男人添的好舒服爽免费视频 | 好屌草这里只有精品 | 色五月丁香五月综合五月 | 青青草原综合久久大伊人精品 | 人人妻人人澡人人爽欧美精品 | 亚洲国产一区二区三区在线观看 | 亚洲精品一区二区三区大桥未久 | 97夜夜澡人人爽人人喊中国片 | 国产精品毛多多水多 | 熟妇人妻无乱码中文字幕 | 成在人线av无码免费 | 99麻豆久久久国产精品免费 | 帮老师解开蕾丝奶罩吸乳网站 | 中文字幕人妻丝袜二区 | 国产精品无码一区二区桃花视频 | 欧美国产日韩亚洲中文 | 亚洲色偷偷男人的天堂 | 波多野结衣高清一区二区三区 | 人妻少妇精品久久 | 亚洲国产高清在线观看视频 | 熟女俱乐部五十路六十路av | 国产莉萝无码av在线播放 | 国产超碰人人爽人人做人人添 | 性生交片免费无码看人 | 国产精品内射视频免费 | 十八禁真人啪啪免费网站 | 人妻少妇精品无码专区二区 | 欧美国产日韩久久mv | 国内揄拍国内精品人妻 | 狠狠色噜噜狠狠狠狠7777米奇 | 亚洲精品一区二区三区在线观看 | 久久国产精品二国产精品 | 亚洲人成网站色7799 | 国产精品久久久久久亚洲影视内衣 | 国产亚av手机在线观看 | 国产精品久久精品三级 | 国产亚洲精品久久久久久久 | 偷窥日本少妇撒尿chinese | 国产精品久免费的黄网站 | 强伦人妻一区二区三区视频18 | 蜜桃视频插满18在线观看 | 撕开奶罩揉吮奶头视频 | 中文无码伦av中文字幕 | 中文精品久久久久人妻不卡 | 中文字幕乱码中文乱码51精品 | 国产美女精品一区二区三区 | 亚洲精品一区二区三区大桥未久 | 久久久国产一区二区三区 | 毛片内射-百度 | 成人欧美一区二区三区 | 久久国产精品二国产精品 | 国产激情无码一区二区 | 免费无码一区二区三区蜜桃大 | 青青青手机频在线观看 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲大尺度无码无码专区 | 亚拍精品一区二区三区探花 | 99re在线播放 | 中文字幕乱码中文乱码51精品 | 国产亚洲视频中文字幕97精品 | 国产精品久久久久影院嫩草 | 久久久久久国产精品无码下载 | 中文字幕 人妻熟女 | 久久久久免费看成人影片 | 欧美国产日产一区二区 | 国产精品亚洲专区无码不卡 | 99久久亚洲精品无码毛片 | 99久久精品国产一区二区蜜芽 | 图片区 小说区 区 亚洲五月 | 欧美xxxxx精品 | 激情内射日本一区二区三区 | 亚洲国产一区二区三区在线观看 | 国产国语老龄妇女a片 | 国产人妻久久精品二区三区老狼 | 亚洲欧美综合区丁香五月小说 | 综合网日日天干夜夜久久 | 免费无码午夜福利片69 | 性生交大片免费看l | 国产在线aaa片一区二区99 | 亚洲精品午夜国产va久久成人 | 久久国产精品_国产精品 | 色狠狠av一区二区三区 | 国产9 9在线 | 中文 | 国产亚洲精品久久久久久久久动漫 | 国产三级精品三级男人的天堂 | 亚洲日韩av一区二区三区四区 | 天堂а√在线中文在线 | 兔费看少妇性l交大片免费 | 欧美 日韩 人妻 高清 中文 | 西西人体www44rt大胆高清 | 东京一本一道一二三区 | 暴力强奷在线播放无码 | 久久天天躁狠狠躁夜夜免费观看 | 一区二区传媒有限公司 | 国产97人人超碰caoprom | 亚洲日韩乱码中文无码蜜桃臀网站 | 中文毛片无遮挡高清免费 | 亚洲一区二区三区 | 亚洲熟女一区二区三区 | 久久久精品成人免费观看 | 日韩精品a片一区二区三区妖精 | 伊人久久大香线蕉午夜 | 午夜性刺激在线视频免费 | 55夜色66夜色国产精品视频 | 日韩欧美成人免费观看 | 嫩b人妻精品一区二区三区 | 色欲综合久久中文字幕网 | 激情亚洲一区国产精品 | 综合网日日天干夜夜久久 | 亚洲 另类 在线 欧美 制服 | 成人精品天堂一区二区三区 | 99久久精品无码一区二区毛片 | 精品午夜福利在线观看 | 97人妻精品一区二区三区 | 国产无av码在线观看 | 少妇厨房愉情理9仑片视频 | 欧美 日韩 亚洲 在线 | 亚洲国产成人a精品不卡在线 | 国产精品资源一区二区 | 国产激情无码一区二区 | 亚洲小说图区综合在线 | 欧美色就是色 | 久久97精品久久久久久久不卡 | 国产乱人伦偷精品视频 | 久久精品一区二区三区四区 | 人妻熟女一区 | 国产亚洲精品久久久久久国模美 | 人人妻人人澡人人爽欧美一区九九 | 亚洲一区二区三区在线观看网站 | 色 综合 欧美 亚洲 国产 | 97人妻精品一区二区三区 | 国产xxx69麻豆国语对白 | 国产成人精品视频ⅴa片软件竹菊 | 国产手机在线αⅴ片无码观看 | 久久99热只有频精品8 | 国产成人精品久久亚洲高清不卡 | 欧美放荡的少妇 | 无码中文字幕色专区 | 亚洲精品午夜无码电影网 | 中文字幕人成乱码熟女app | 最新国产乱人伦偷精品免费网站 | 无码帝国www无码专区色综合 | 国产亚洲欧美在线专区 | 国产黑色丝袜在线播放 | 131美女爱做视频 | 日本一区二区三区免费高清 | 欧美熟妇另类久久久久久多毛 | 兔费看少妇性l交大片免费 | 一个人看的视频www在线 | 亚洲综合伊人久久大杳蕉 | 国产精品美女久久久久av爽李琼 | 久久综合久久自在自线精品自 | 国产成人精品优优av | 无遮挡国产高潮视频免费观看 | 久久精品国产日本波多野结衣 | 久久天天躁狠狠躁夜夜免费观看 | 男人扒开女人内裤强吻桶进去 | 亚洲色在线无码国产精品不卡 | 熟女体下毛毛黑森林 | 欧美性生交xxxxx久久久 | 国产免费无码一区二区视频 | 国产麻豆精品精东影业av网站 | 免费国产成人高清在线观看网站 | 久久久国产一区二区三区 | 乱码午夜-极国产极内射 | 黑人巨大精品欧美黑寡妇 | 中文字幕人妻无码一夲道 | 少妇无码一区二区二三区 | 少妇的肉体aa片免费 | 无码午夜成人1000部免费视频 | 欧美黑人乱大交 | 人人妻人人澡人人爽精品欧美 | 精品国精品国产自在久国产87 | 国产美女精品一区二区三区 | 色狠狠av一区二区三区 | 亚洲综合伊人久久大杳蕉 | 伊人久久大香线蕉亚洲 | 亚洲国产精品久久久久久 | 亚洲精品久久久久中文第一幕 | 人妻中文无码久热丝袜 | 性欧美大战久久久久久久 | 欧美老熟妇乱xxxxx | 97资源共享在线视频 | 极品嫩模高潮叫床 | 高潮毛片无遮挡高清免费视频 | 18无码粉嫩小泬无套在线观看 | 天天摸天天碰天天添 | 女人高潮内射99精品 | 极品嫩模高潮叫床 | 亚洲精品国产a久久久久久 | 精品国产一区二区三区四区在线看 | 双乳奶水饱满少妇呻吟 | 精品国产青草久久久久福利 | 日韩少妇内射免费播放 | 国产精品无码一区二区三区不卡 | 亚洲国产av精品一区二区蜜芽 | 精品水蜜桃久久久久久久 | 国产内射老熟女aaaa | 国产精品久久久久久久9999 | 国产成人无码av一区二区 | 欧美freesex黑人又粗又大 | 久久综合网欧美色妞网 | 久久久中文字幕日本无吗 | 亚洲精品一区二区三区在线 | 理论片87福利理论电影 | 少妇人妻av毛片在线看 | 久久国产36精品色熟妇 | 国产成人午夜福利在线播放 | 中文久久乱码一区二区 | 亚洲精品一区二区三区在线 | 国产成人人人97超碰超爽8 | 一本加勒比波多野结衣 | 亚洲中文字幕在线无码一区二区 | 国产精品永久免费视频 | 最新国产乱人伦偷精品免费网站 | 午夜福利不卡在线视频 | aa片在线观看视频在线播放 | 日韩 欧美 动漫 国产 制服 | 无码人妻出轨黑人中文字幕 | 欧美黑人乱大交 | 国产两女互慰高潮视频在线观看 | 午夜福利一区二区三区在线观看 | 成熟妇人a片免费看网站 | 少妇一晚三次一区二区三区 | 国产午夜手机精彩视频 | 国产精品a成v人在线播放 | 久久精品一区二区三区四区 | 99视频精品全部免费免费观看 | 亚洲午夜久久久影院 | 中文字幕av日韩精品一区二区 | 99精品无人区乱码1区2区3区 | 国产av无码专区亚洲a∨毛片 | 日日天干夜夜狠狠爱 | 久久综合久久自在自线精品自 | 国产精品久免费的黄网站 | 老熟妇乱子伦牲交视频 | 国产情侣作爱视频免费观看 | 国产一区二区三区四区五区加勒比 | 性欧美牲交在线视频 | 国产人妻人伦精品1国产丝袜 | 熟女少妇人妻中文字幕 | 午夜理论片yy44880影院 | 国产人妻久久精品二区三区老狼 | 亚洲狠狠色丁香婷婷综合 | 18禁止看的免费污网站 | 国产三级精品三级男人的天堂 | 激情五月综合色婷婷一区二区 | 99麻豆久久久国产精品免费 | 国产美女精品一区二区三区 | 无码人妻av免费一区二区三区 | 久久精品女人的天堂av | 国产成人精品无码播放 | 精品国产一区av天美传媒 | 欧美日韩一区二区免费视频 | 亚洲爆乳大丰满无码专区 | 少妇无码av无码专区在线观看 | 成人一区二区免费视频 | 鲁一鲁av2019在线 | 中文字幕乱码亚洲无线三区 | 日本丰满熟妇videos | 国产精品视频免费播放 | 在线成人www免费观看视频 | 午夜福利试看120秒体验区 | 久久天天躁夜夜躁狠狠 | av香港经典三级级 在线 | 成人精品视频一区二区三区尤物 | 国产综合色产在线精品 | 国产农村妇女高潮大叫 | 精品国产麻豆免费人成网站 | 国产熟妇高潮叫床视频播放 | 乱人伦中文视频在线观看 | 精品国偷自产在线 | 色欲人妻aaaaaaa无码 | 亚洲精品美女久久久久久久 | 综合网日日天干夜夜久久 | 久久久久久久久888 | 国产无套内射久久久国产 | 无码人妻出轨黑人中文字幕 | 一个人免费观看的www视频 | 狠狠色色综合网站 | 四虎永久在线精品免费网址 | 亚洲精品国产a久久久久久 | 亚洲国产精品一区二区美利坚 | 人妻无码久久精品人妻 | 影音先锋中文字幕无码 | 东京热一精品无码av | 免费看男女做好爽好硬视频 | 精品国产福利一区二区 | 天天拍夜夜添久久精品大 | 天天爽夜夜爽夜夜爽 | 亚洲无人区午夜福利码高清完整版 | 装睡被陌生人摸出水好爽 | 久热国产vs视频在线观看 | 成人免费视频视频在线观看 免费 | 久久午夜无码鲁丝片午夜精品 | 欧美怡红院免费全部视频 | 精品人妻人人做人人爽夜夜爽 | 两性色午夜免费视频 | 麻豆国产人妻欲求不满谁演的 | 国产日产欧产精品精品app | 国产无遮挡吃胸膜奶免费看 | 熟女体下毛毛黑森林 | 免费网站看v片在线18禁无码 | 国产美女极度色诱视频www | 内射爽无广熟女亚洲 | 国产精品丝袜黑色高跟鞋 | 日日摸日日碰夜夜爽av | 亚洲日本一区二区三区在线 | 亚洲精品国产精品乱码不卡 | 亚洲中文字幕久久无码 | 国产精品无码一区二区桃花视频 | 男女超爽视频免费播放 | 久久97精品久久久久久久不卡 | 亚洲精品久久久久中文第一幕 | 偷窥村妇洗澡毛毛多 | 亚洲va中文字幕无码久久不卡 | 国产av无码专区亚洲awww | 麻豆av传媒蜜桃天美传媒 | 欧美亚洲日韩国产人成在线播放 | 日韩欧美群交p片內射中文 | 丰满少妇熟乱xxxxx视频 | 国产精品久久久av久久久 | 色综合久久久无码网中文 | 超碰97人人做人人爱少妇 | 欧美人与物videos另类 | 亚洲 另类 在线 欧美 制服 | 亚洲熟妇色xxxxx欧美老妇 | 高清无码午夜福利视频 | 国产精品久久福利网站 | 98国产精品综合一区二区三区 | 国产一区二区三区影院 | 欧美老妇与禽交 | 麻豆国产人妻欲求不满谁演的 | 曰本女人与公拘交酡免费视频 | 色婷婷欧美在线播放内射 | 日本大香伊一区二区三区 | 国产人妻精品午夜福利免费 | 欧美大屁股xxxxhd黑色 | 蜜臀av无码人妻精品 | 噜噜噜亚洲色成人网站 | 亚洲中文字幕久久无码 | 国产激情一区二区三区 | 亚洲 另类 在线 欧美 制服 | 狠狠综合久久久久综合网 | 亚拍精品一区二区三区探花 | 久久久久免费精品国产 | 国产猛烈高潮尖叫视频免费 | 国产 精品 自在自线 | 国产亚洲美女精品久久久2020 | 久久久国产一区二区三区 | 亚洲国精产品一二二线 | 国产人妻精品午夜福利免费 | 男女下面进入的视频免费午夜 | 天堂在线观看www | 精品国产麻豆免费人成网站 | 麻豆精品国产精华精华液好用吗 | 亚洲综合在线一区二区三区 | 久久综合给久久狠狠97色 | 又湿又紧又大又爽a视频国产 | 日本护士xxxxhd少妇 | 日韩av无码中文无码电影 | 国产手机在线αⅴ片无码观看 | 亚洲欧洲中文日韩av乱码 | 亚洲人成网站在线播放942 | 亚洲中文字幕久久无码 | 亚洲人成影院在线无码按摩店 | 色诱久久久久综合网ywww | 中文字幕日韩精品一区二区三区 | 亚洲春色在线视频 | 国产9 9在线 | 中文 | 麻豆国产人妻欲求不满谁演的 | 国产真实夫妇视频 | 宝宝好涨水快流出来免费视频 | 亚洲va中文字幕无码久久不卡 | 伊人色综合久久天天小片 | 色综合久久88色综合天天 | 麻豆成人精品国产免费 | 日韩精品一区二区av在线 | 欧美人妻一区二区三区 | 中文字幕无线码 | 亚洲精品一区二区三区在线观看 | 国产精品亚洲а∨无码播放麻豆 | 狠狠色欧美亚洲狠狠色www | 久久伊人色av天堂九九小黄鸭 | 岛国片人妻三上悠亚 | 99riav国产精品视频 | 天天做天天爱天天爽综合网 | 日韩精品无码免费一区二区三区 | 国产在线aaa片一区二区99 | 红桃av一区二区三区在线无码av | 国产成人无码av在线影院 | 人妻有码中文字幕在线 | 日韩av无码中文无码电影 | 国产做国产爱免费视频 | 久久zyz资源站无码中文动漫 | 国产精品久久久av久久久 | 亚洲va欧美va天堂v国产综合 | 天堂а√在线中文在线 | 国产午夜视频在线观看 | 久激情内射婷内射蜜桃人妖 | 亚洲精品国产第一综合99久久 | 久久久久久av无码免费看大片 | 亚洲成av人在线观看网址 | 国产无遮挡又黄又爽又色 | 久久亚洲中文字幕精品一区 | 性色av无码免费一区二区三区 | 99精品视频在线观看免费 | 又粗又大又硬又长又爽 | 亚洲中文无码av永久不收费 | 欧美日韩一区二区综合 | 免费观看的无遮挡av | a片免费视频在线观看 | 亚洲小说春色综合另类 | 无码人妻久久一区二区三区不卡 | 欧美熟妇另类久久久久久多毛 | 午夜时刻免费入口 | 久久亚洲中文字幕无码 | 亚洲色欲久久久综合网东京热 | 九一九色国产 | 亚洲欧美日韩成人高清在线一区 | 亚洲熟妇色xxxxx亚洲 | 97色伦图片97综合影院 | 55夜色66夜色国产精品视频 | 成人亚洲精品久久久久 | 亚洲精品一区二区三区大桥未久 | 成人av无码一区二区三区 | 最近免费中文字幕中文高清百度 | аⅴ资源天堂资源库在线 | 午夜丰满少妇性开放视频 | 性欧美熟妇videofreesex | 真人与拘做受免费视频 | 亚洲日韩一区二区三区 | 欧美精品免费观看二区 | 荫蒂添的好舒服视频囗交 | 色欲综合久久中文字幕网 | 风流少妇按摩来高潮 | 亚洲一区二区三区在线观看网站 | 激情人妻另类人妻伦 |