GSpring

生活需要理想,却不能理想化的生活

导航

微软.net精简框架常见问题及回答(中文版)

微软.net精简框架常见问题及回答(中文版)

[日期:2004-10-23] 来源:http://blog.csdn.net/jinco/  作者:jinco [字体: ]

此FAQ的内容,一部分来自 net精简框架新闻组 (microsoft.public.dotnet.framework.compactframework)张贴和回答的问题。.net精简框架开发小组感谢每一位参与新闻组的人事,感谢他们对FAQ编写的积极参与和对FAQ的投稿。

要申请添加FAQ项目,请发邮件到 netcffaq@microsoft.com.

1. 开发

1.1. 什么是微软 .net精简框架?
1.2. 我需要什么工具才能开发.net精简框架的应用?
1.3. 哪里可以下载最新的工具和相关软件?
1.4. .net精简框架支持些什么设备?
1.5. .net精简框架以后将支持什么设备?
1.6. 调试程序时为什么会出现“与模拟器建立连接失败”的错误(刚开始执行程序的时候)?
1.7. .net框架和.net精简框架之间有什么区别?
1.8. .net精简框架的补丁有什么改进?
1.9. Poclet PC上的.net精简框架开发和Windows CE .NET上的.net精简框架开发有什么不同?
1.10. 哪里有更多的关于建立.net精简框架上的应用程序的信息?
1.11. .net精简框架的文档在哪里?
1.12. 怎样设置才不会在每次调试的时候把所涉及的文件都拷贝到设备上?
1.13. 怎样设置模拟器的属性?
1.14. 怎么调试.net精简框架的应用程序?
1.15. 怎样开始使用Visual Basic .NET开发.net精简框架的程序?
1.16. 怎样才能把.net精简框架安装到装配集中(GAC)?
1.17. 当从Visual Studio .NET 2003中发布程序到设备上的时候,怎样处理"Sharing Violation"?
1.18. 什么是common language runtime (CLR)?
1.19. 什么是Global Assembly Cache (GAC)?
1.20. 在.net精简框架下内存管理是怎样的?
1.21. 当我的网络协议数超过50个的时候,为什么不能向发布程序?
1.22. 为什么会有跨平台代码?
1.23. 这些ARM指令代表什么?
1.24. 怎样写注册表?
1.25. How can I prevent .CAB files from being deleted after installation?
1.26. How can I determine the version of the .NET Compact Framework that is installed on a device?
1.27. How do I copy files to the emulator?
1.28. Why does installation of the PocketPC 2002 SDK fail?
1.29. How do I debug a Web service consumed by a Smart Device application?
1.30. What is the footprint of the .NET Compact Framework?
1.31. How do I include imgdecmp.dll in an emulator image?
1.32. How do I programmatically replace Assemblies in the Global Assembly Cache (GAC)?
1.33. How can I display Pocket PC applications on my desktop or laptop without needing any device side configuration?
1.34. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?
1.35. How can I copy files to the device currently connected to desktop ActiveSync?
1.36. How can I stress test user input?
1.37. Where can I get a UI version of the Platform Builder Target Control Window?
1.38. Where can I get a Command shell for Pocket PC 2003 devices?
1.39. How can I get detailed information about currently running processes?
1.40. How can I remotely start an application on a Pocket PC from my desktop?
1.41. Why can't I load different assemblies with the same name?
1.42. How can I force Visual Studio .NET 2003 to connect to newer versions of the Pocket PC 2003 emulator?
1.43. Why don't my custom controls show up properly in the toolbox?
2. 图形
2.1. 怎样建立一个图形对象?
2.2. 怎样优化GDI+?
2.3. 怎样在窗体上画一个图案?
2.4. 怎样画一个带有透明色的图案?
2.5. 为什么从TextBox上调用CreateGraphics会失败?
2.6. 怎样获得屏幕上文字的大小?
2.7. Can I set the width of a pen?
2.8. How do I zoom an image?
2.9. Why can't I load an image?
3. 发布
3.1. 怎样建立一个PocketPC的设置程序?
3.2. 哪个发布包可以包括在我的安装程序中?
3.3. 怎样可以建立一个不需要.net框架的安装程序?
3.4. 怎样建立不受PocketPC系统约束的CAB安装文件?
3.5. 为什么不同的处理器会有不同的CAB安装文件?
3.6. How do I create a desktop installer that detects the presence of the .NET Compact Framework on the target device and installs it if necessary?
3.7. How do I deploy a .NET Compact Framework Service Pack to the emulator?
3.8. How do I include SQL Server CE with my application installation?
3.9. How do I use GAPI to create a graphics engine?
4. 图形用户界面(GUI): 窗体
4.1. 怎样建立一个全屏的窗体?
4.2. 什么时候用窗体的构造器?什么时候用窗体的Load事件?
4.3. 怎样把最小化按钮换成关闭按钮?
4.4. 怎样在.net精简框架上建立多窗体系统结构?
4.5. 怎样提高.net精简框架应用程序的载入速度?
4.6. 运行时怎样修改窗体的风格?
4.7. 怎样滚动窗体的内容?
4.8. 怎样制作一个浮动的窗体?好象所有的窗体总是全屏状态的。
4.9. 怎样强迫一个窗体变成最小化?
4.10. 我有一个包含很多控件的智能设备窗体,为什么运行的时候出现"NotSupportedException"错误?
4.11. 哪个是正确关闭窗体的方法:Appplication.Exit 还是 Form.Close ?
4.12. Why does showing a MessageBox on Windows Mobile 2003 for Smartphone with the Abort, Retry, and Fail set of buttons or the Yes, No, Cancel set of buttons, or the third button as the default button result in a NotSupportedException?
4.13 How do I get an icon in the Pocket PC Start Menu Most Recently Used (MRU) List?
4.14 How do I center a Form on the screen?
4.15 Why can't I show a Form that has been closed?
4.16 How can I enable multiple instances of an application?
5. 图形用户界面 (GUI): 通用
5.1. 怎样建立一个带有图形或支持多行的按钮?
5.2. TextBox.AcceptsReturn在.net精简框架下是怎样工作的?
5.3. 当数据载入ComboBox的时候,为什么SelectedIndexChanged事件没有被触发?
5.4. Show和ShowDialog有什么不同?
5.5. 为什么我不能建立右键菜单分离器?(separator)
5.6. 运行时把ImageList赋给ToolBar时,为什么图象不出现?
5.7. 怎样把光标设置成等待状态?
5.8. 如何在菜单项中显示符号:&?
5.9. 如何制作基于.net精简框架的动画控件?
5.10. 如何在.net精简框架上制作自定义控件?
5.11. 如何制作基于.net精简框架的带图片的按钮?
5.12. 如何使用.net精简框架下的MessageWindow类库?
5.13. 如何向DataGrid中添加行和列?
5.14. 如何实现DataGrid的编辑?
5.15. 怎样设置DataGrid的DataSource?
5.16. 怎样对DataGrid的列排序?
5.17. 怎样对ListView中的内容排序?
5.18. 如何使用 输入板(SIP)控件?
5.19. 如何自定义事件?
5.20. 如何做一个 owner-drawn List Box?
5.21. 如何做一个多选框判断真假?
5.22. 设置InputPanel.Enabled = true的时候为什么出现异常?
5.23. 为什么自定义控件不会自动继承父类的字体?
5.24. 为什么当输入字符时,NumericUpDown 和 DomainUpDown 控件不会引发 ValueChanged 和 SelectedItemChanged 事件?
5.25. 为什么NumericUpDown控件增长的值不是设置好的值?
5.26. 为什么StatusBar不能放在窗体的任意位置?一定要在底部?
5.27. 为什么我的控件自动继承了父控件的背景色?
5.28. 为什么NumericUpDown控件能接受decimal类型的值,但不会显示大于2^16的值?
5.29. 为什么不能在DomainUpDown 中输入文字,而要选择?
5.30. 为什么OpenFileDialog被限制在"My Documents" 文件夹中?
5.31. How can I activate the SIP (InputPanel) without a menu?
5.32. How do I add a subnode to every node in a TreeView?
5.33. How do I determine the number of rows or columns in a DataGrid?
5.34. How do I create a owner drawn Listbox?
5.35. How can I implement Control.GetNextControl under the .NET Compact Framework?
5.36. How do I get notified when the user clicks on a treeview node?
5.37. How do I set the title of a fullscreen multiline edit control window?
5.38. Why don' I see the validItem selected when I set ComboBox.SelectedValue to validItemInCollection?
5.39. How do I detect the location where a 'tap & hold' occurred to bring up a context menu on my custom control?
5.40. Why doesn't the scrollbar value ever get set to the maximum value?
5.41. How do I tab out of a custom control to the previous control?
5.42. How do I add Toolbar buttons with Transparency? 
6. 与本地代码(Native Code)协同工作
6.1. 如何调用本地写的DLL中的函数?
6.2. 如何使用dumpbin.exe帮助描述 P/Invokes?
6.3. 如何为微软.net精简框架写非托管代码?
6.4. 如何调用 P/Invoke GetTickCount?
6.5. 如何获得系统还有多少可用内存?
6.6. 如何是窗口一直保持最小化?
6.7. 在微软.net精简框架上调用系统函数时,如何装配数据类型?
6.8. 如何得到一个窗体或控件的句柄 (HWND) ?
6.9. 如何使用性能计数器功能?
6.10. 调用本地代码时,数据类型有什么限制?What are the limitations on marshalling types via P/Invoke?
6.11. 调用GetLastError时,总是获得不定的代码?
6.12. 调用本地代码时,有没有参数数量的限制?
6.13. 调用本地代码时,为什么得到"NotSupportedException"异常?
6.14. 如何把 byte[] 转换成 IntPtr?
6.15. Why do I get a MissingMethodException when I call a function from a native DLL?
6.16. How do I set the system time?
6.17. How do I programmatically soft reset the device?
6.18. How can I put an icon on the title bar regardless of the which form is active?
6.19. How do I disable and capture hardware buttons?
6.20. How do I hide the start icon?
6.21. How do I enumerate, create, and terminate processes?
6.22. Where can I find a centralized library of P/Invoke samples?
6.23. How do I play and record .WAV audio files with the Waveform Audio Inteface? 
7. 通用
7.1. 如何确定应用程序的主目录?
7.2. 如何计算精确的时间间隔?
7.3. 如何把嵌入式资源当作一个流(Stream)?
7.4. 为什么得到一个"An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll"的错误?
7.5. 如何使用性能监视器?
7.6. 如何取消一个程序的关闭?
7.7. 如何在我的程序中调用另一个应用程序?
7.8. .net精简框架的应用程序会建立什么线程?
7.9. 如何把byte数组转换成结构体?
7.10. 我可以建立一个委托(delegate)交给Invoke吗?
7.11. 如何在微软.net精简框架上使用电话API?
7.12. 如何在Pocket Pc上生成GUID?
7.13. 如何让我的.net精简框架程序和Pocket Outlook的数据结合?
7.14. 我可以判断.net精简框架中一个文件的版本吗?
7.15. 微软.net精简框架的后台处理有什么相关技术?
7.16. 在微软.net精简框架上使用多线程有什么技巧?
7.17. 如何在 智能设备应用 中使用混淆器?
7.18. 如何使用密码服务对数据进行加密或解密?
7.19. 如何在微软.net精简框架上获得Windows CE设备的唯一号码?
7.20. 如何在微软.net精简框架的应用程序上发送短消息?
7.21. 不使用Control.Name,可以判断事件的发送者吗?
7.22. 如何在线程中调用方法的参数?
7.23. 如何建立提醒程序和定时程序?
7.24. 如何播放声音?
7.25. 如何使用命令行参数?
7.26. 当使用已经释放的对象的方法或属性的时候,为什么得到一个异常?
7.27. 如何获得"Enter", "TAB", 和 "Arrow"按键的事件?
7.28. 如何删除一个只读文件?
7.29. How do I determine if a member exists at runtime?
7.30. How do I determine the device name programatically?
7.31. How do I build a C# Smart Device project from the command line?
7.32. How do I abort an executing thread?
7.33. Why can't I play a movie on the Pocket PC emulator?
7.34. How do I suppress Form titles from showing in the active applications list?
7.35. How do I access a Control from its instance name?
7.36. How do I detect the hardware directional pad buttons?
7.37. How do I get a double click event when only the Click event is supported?
7.38. How do I get onenter/onleave style notifications?
7.39. How do I use threading in a modal dialog that doesn't hang my app?
7.40. How do I round floating point numbers efficiently?
7.41. Why does Control.Invoke take so long when a modal dialog is displayed?
7.42. Is there a way to retrieve the culture information of an Assembly?
8. 通讯和Web服务
8.1. 如何通过TCP Socket向桌面机发送数据?
8.2. 为什么不能访问本机上的Web服务?
8.3. 如何在微软.net精简框架上调用Web服务
8.4. 如何通过代理服务器提交HTTP GET申请?
8.5. 如何使用Web服务?
8.6. 如何使用MapPoint3.0得到地图?
8.7. 如何使用MapPoint3.0获得地图和方向?
8.8. Is NTLM authentication supported by the .NET Compact Framework?
8.9. When using blocking Sockets, why does Send throw an InvalidOperationException when blocking is set to false?
8.10. How do I create an http-server?
8.11. Why do I get an exception when calling SetSocketOption with ReuseAddress set?
8.12. Why do I get a socket error using SSL to communicate with a server via the WebRequest namespace?
9. SQL CE 和 数据
9.1. 使用.net精简框架、SQL Server CE 和 复制 开发应用程序时,要注意些什么?
9.2. 如何在微软.net精简框架上使用合并复制(Merge Replication)?
9.3. 如何将ADO.NET数据和XML绑定?
9.4. 如何建立SQL Server CE的数据库?
9.5. 如何向SQL Server CE提交一个带参数的查询?
9.6. Why does using RDA and the push method fail with error 27750?
10. 其他信息
10.1. Pocket TaskVision 程序
10.2. 建立基于微软.net精简框架的进程管理器
10.3. 使用微软.net精简框架开发移动游戏
10.4. 制作一个微软.net精简框架的DateTimePicker控件
10.5. 写一个捕捉Pocket PC签名的程序
10.6. 有没有非微软的网站提供在.net精简框架上开发应用的信息?
11. 连通性
11.1. 为什么不同通过ActiveSync把程序部署到Windows CE的设备上?
11.2. 为什么不能通过ActiveSync调试 CEPC 或其他 x86 的Windows CE设备?
11.3. 为什么当设备上的Toolhelp.dll文件丢失后,调试就会失败?
11.4. 为什么当网络协议数超过50个的时候,就不能向设备发布程序?
11.5. 为什么卸载ActiveSync后,不能通过ActiveSync向设备发布?
11.6. 为什么本地化的机器名或用户名或导致向设备发布程序的失败?
11.7. 为什么当前用户不属于Administrators组的时候,不能向设备发布程序?
11.8. 为什么向Pocket PC或模拟器发布的时候出现 sharing violation 的错误?
11.9. 为什么在.NET Server的计算机上第一次使用模拟器的时候,得到一个安全警告消息?
11.10. 为什么在模拟器刚开始运行的时候出现关于找不到文件的错误信息?
11.11. 为什么第一次用模拟器发布时,会出现偶尔的错误?
11.12. 为什么第一次用Connect按钮连接模拟器并发布程序的时候失败了?
11.13. 为什么当计算机没有网络连接的时候,用模拟器调试程序会出现错误?
11.14. 为什么当模拟器使用了一个COM端口的时候不启动不了(黑屏)?
11.15. 为什么Visual Studio .NET 2003的模拟器不能和eMbedded Visual Tools的模拟器同时使用?
11.16. 为什么没有ActiveSync连接的时候不能通过TCP连接向设备发布程序?
11.17. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?
11.18. How can I copy files to the device currently connected to desktop ActiveSync?
11.19. Why does the Visual Studio debugger fail to connect to an ARMV4I device?
12. Smartphone
12.1. Where can I get the latest Smartphone SDK?
12.2. What are the rules for Smartphone menus?
12.3. Why are there disabled controls in the toolbox when creating a Smartphone project?
12.4. Does Smartphone support RAM installs of the .NET Compact Framework?
12.5. How do I set the title of a fullscreen multiline edit control window?
12.6. How can I generate Smartphone CABWizSP XML docs from existing Pocket PC CAB files?
12.7. How can I send characters and strings to the Smartphone 2003 Emulator via ActiveSync?
12.8. How do I programmatically set the Smartphone input mode?
Top of Page Top of Page


1. 开发

1.1. 什么是微软 .net精简框架?

微软.net精简框架是.net框架为智能设备开发的平台,是实现微软的目标:“为用户提供精彩的体验--任何时间、任何地点、任何设备” 的关键部分。.net精简框架把托管代码的世界从web服务带到了智能设备上, 允许在个人数字助理(PDA)、移动电话、机顶盒设备上的 安全的、可下载的应用。

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

1.2. 我需要什么工具才能开发.net精简框架的应用?

Visual Studio .NET 2003 是在Pocket PC 2000、Pocket PC 2002和Windows CE.NET 4.1上开发.net精简框架所需要的, .net精简框架与Visual Studio .NET 2003一同发售.
http://msdn.microsoft.com/mobility/prodtechinfo/devtools/vstudio/default.aspx

其他Windows移动平台开发包可以在以下地方获得:

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精简框架和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精简框架和补丁集可以在这里获得:
http://msdn.microsoft.com/mobility/downloads/default.aspx

1.4. .net精简框架支持些什么设备?

.net精简框架可以在Pocket PC 2000, Pocket PC 2002, Windows Mobile 2003的Pocket PC 和 基于Windows CE.NET 4.1嵌入式系统的Pocket PC、智能手机 上运行。

1.5. .net精简框架以后将支持什么设备?

.net精简框架将被集成到微软系统中并成为一部分,包括未来的Pocket PC设备,Pocket PC电话版,智能手机,车载Windows CE系统,MSTV。 各种设备的发布时间待定。

.net精简框架将作为Windows CE .NET 4.1系统组件的一部分,因此允许OEM厂商使用PlatformBuilder把.net精简框架集成到新的Windows CE设备中。

1.6. 调试程序时为什么会出现“与模拟器建立连接失败”的错误(刚开始执行程序的时候)?

下面这个连接将告诉你如何设置调试和排错。
http://download.microsoft.com/download/c/d/b/cdbff573-73fb-4f9f-a464-c5adc890e1ae/Readme.htm

1.7. .net框架和.net精简框架之间有什么区别?

.NET框架 和 .net精简框架 的关系:
http://msdn.microsoft.com/library/en-us/dv_evtuv/html/etconComparisonsWithNETFramework.asp

在线查看.net精简框架类库关系工具:
http://msdn.microsoft.com/library/en-us/dv_spchk/html/NET_Compact_Framework.htm

1.8. .net精简框架的补丁有什么改进?

.net精简框架 SP1 修正了许多漏洞,查看修正项目列表:
http://www.microsoft.com/downloads/details.aspx?familyid=1f62a2a3-7282-4ba9-b26b-2267e972501d&displaylang=en

1.9. Poclet PC上的.net精简框架开发和Windows CE .NET上的.net精简框架开发有什么不同?

这篇文章将描述在Pocket PC和Windows CE.NET平台上开发基于.net 精简框架的应用程序的区别之处。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfPPCtoCE.asp

1.10. 哪里有更多的关于建立.net精简框架上的应用程序的信息?

以下资源能教会您怎样建立.net精简框架应用程序:

  • .net精简框架  快速入门
    http://samples.gotdotnet.com/quickstart/compactframework/
  • .net精简框架白皮书 MSDN移动和嵌入式开发中心:
    http://msdn.microsoft.com/mobility/understanding/articles/default.aspx

    1.11. .net精简框架的文档在哪里?

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

    1.12. 怎样设置才不会在每次调试的时候把所涉及的文件都拷贝到设备上?

    在Visual Studio .NET 2003, 右键点击文件并选择属性,把Build的属性设置为None.文件将不再被拷贝.如果文件修改过了,需要重新拷贝,把Build属性改为Content即可.

    1.13. 怎样设置模拟器的属性?

    在Visual Studio .NET 2003菜单中,选择 Tools->Options. 打开 Device Tools 文件夹,并选择 Devices. 您应该看到一个显示设备列表的对话框.选择您想修改的设备,按Configuration按钮.
    现在您应该看到一个包含多个TAB并可以修改设置的对话框,如设置内存和屏幕大小等.

    1.14. 怎么调试.net精简框架的应用程序?

    微软.net精简框架完全集成在Visual Studio .NET 2003中,在Visual Studio .NET 2003下调试.net精简框架的应用和在Visual Studio .NET 2003下调试其他应用一样。在一个单独的设备上调试程序和在模拟器中调试程序需要注意不同的地方。查看下面文章可以获得更多调试.net精简框架的经验。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/CompactFXDebug.asp

    1.15. 怎样开始使用Visual Basic .NET开发.net精简框架的程序?

    了解怎样使用Smart Device Extensions (SDE)编写只能设备的应用。这篇文章详细介绍了在.net精简框架上开发、调试、发布的完整过程,并描述了和在.net框架上开发的区别。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/sdeforvb.asp

    1.16. 怎样才能把.net精简框架安装到装配集中(GAC)?

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

    1.17. 当从Visual Studio .NET 2003中发布程序到设备上的时候,怎样处理"Sharing Violation"?

    This article illustrates the cause of a sharing violation that prevents the deployment of your application from Visual Studio .NET 2003, and gives instructions on how to work around it.
    http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOSharingviolation.asp

    1.18. 什么是common language runtime (CLR)?

    .net精简框架提供的运行环境叫做CLR,它使程序运行,并且是开发更加容易。以下文章将使您了解更多关于CLR:
    http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcommonlanguageruntimeoverview.asp

    1.19. 什么是Global Assembly Cache (GAC)?

    每一台装了.net环境的机器都会有一个本机器范围内的缓冲,这就是GAC。GAC中存放的装配会被这台计算机上的一些应用程序共享 。这篇文章将告诉你更多关于GAC的信息:
    http://msdn.microsoft.com/library/en-us/cpguide/html/cpconglobalassemblycache.asp

    1.20. 在.net精简框架下内存管理是怎样的?

    自动内存管理是CLR提供的一项服务。CLR的垃圾回收器会管理应用程序内存的分派和回收,以下文章将为您解释:
    http://msdn.microsoft.com/library/en-us/cpguide/html/cpconautomaticmemorymanagement.asp

    1.21. 当我的网络协议数超过50个的时候,为什么不能向发布程序?

    请查看本文章的  "11.4. 为什么当网络协议数超过50个的时候,就不能向设备发布程序?"  部分。

    1.22. 为什么会有跨平台代码?

    .net精简框架和它的执行引擎是.net框架和CLR的子集。缺省的强名称策略,针对.net精简框架编译的程序同样可以在完整的.NET框架上运行,但会有一些重要的异常信息:
    • .net精简框架装配使用和.net框架不用的强名称签名,所以CLR可以区分它们。
    • 在未来发布的.NET框架和CLR的绑定策略中将使用.NET框架装配代替兼容.NET精简框架参考。这样,在普通情况下,不需要重新连接就能重用组件。 例如:如果您的组件只引用了.net精简框架的 System 和 System.NET 类库,它则不需要重新连接就适合在.net精简框架和完整的.NET框架下运行。
    • 如果你引用了.net精简框架特有的功能,如PocketPC特有的用户界面,程序将不能在完整的.net框架上运行。
    • 如跨平台的中间组件的开发和发布,微软认为丰富的客户端应用应该利用智能设备特有的功能为用户带来更好的体验。这一味着好的图形用户界面基本上是客户端特有的。
    • 尽管微软花费很大精力为不同设备和功能划分了不同的命名空间和装配以避免装配冲突,但在1.0的版本里还是会有不能处理的兼容性问题。在这种情况下,在.net框架上不经意地使用了设备专有的功能将会导致程序在运行时的异常,而不是载入时的异常。

    1.23. 这些ARM指令代表什么?

    XScale支持ARM v5指令集,同时也向下兼容ARM v4指令集。这里有三种情况:
    • ARMv4 -> 只支持32位ARMv4指令
    • ARMv4T -> 'T' 表示 Thumb. Thumb 是ARM16位指令模式
    • ARMv4I -> 'I' 表示 Interworking. 允许32位和16位指令共存

    对于其他ARM处理器:
    • StrongARM (SA1110) -> 只支持ARMv4指令
    • ARM920T, etc -> 支持所有三种情况

    .net精简框架支持三种ARM代码
    • ARMv4 for PocketPC 2000 and Pocket PC 2002. 支持所有ARM设备,包括XScale。发布到设备的CAB文件名包含有"arm"字符。
    • ARMv4 for Windows CE.NET. 支持由PlatformBuilder使用ARMv4核心编译的Windows CE.NET设备。Pocket PC 2003支持这种代码。发布到设备的CAB文件名包含有"armv4"字符。
    • ARMv4T or ARMv4I for Windows CE.NET. 支持由PlatformBuilder使用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 Pocket PC Registry Editor (共享软件,很容易在网上找到)
    1.25. How can I prevent .CAB files from being deleted after installation?

    Automatic deletion of .CAB files can be prevented by setting the property of the .CAB file(s) to Read Only.

    1.26. How can I determine the version of the .NET Compact Framework that is installed on a device?

    Each version of the .NET Compact Framework is released with a different Win32 File Version number (this is a separate version number from the Assembly Version, which should be the same across all releases of the Version 1 .NET Compact Framework, including Service Packs).

    In order to see what version is installed, use File Explorer to navigate to the \Windows directory on the device, and click the file called CGACUTIL. You will get a message box showing you the Win32 File Version of the .NET Compact Framework installed on the device.

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

    To determine the version programmatically you can use System.Environment.Version.ToString().

    1.27. How do I copy files to the emulator?

    One approach would be to create a file share on your development PC, and then connect to that share via File Explorer in the emulator. You may then copy and paste the files from the share to the emulator's local file system. Another approach would be to add the file(s) to a smart device project and set their Build Action(s) property to "Content". See the Visual Studio .NET online documentation for more information on "File Properties":

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbconfileproperties.asp

    Step by step instructions for adding a "Content" file to a smart device project:
    1. Open or create a smart device project,
    2. On the View menu, click Solution Explorer,
    3. In Solution Explorer, right-click on your project, point to Add, and click Add Existing Item. Browse to and add the desired file to the project.
    4. Right-click on the file that you added, in solution explorer, and click Properties,
    5. Set the Build Action property to "Content", if it is not already set.
    1.28. Why does installation of the PocketPC 2002 SDK fail?

    Symptom: The Pocket PC 2002 SDK installer hangs while "registering components."

    Cause: An unregestered component causes the installation to hang while attempting to run the emulator.

    Workaround: From a console window prompt:
    cd \WINNT\system32
    regsvr32 atl.dll

    1.29. How do I debug a Web service consumed by a Smart Device application?

    You need to attach the debugger to the ASP.NET worker process.

    Refer to the following link for more information:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtskdebugginganaspdeployedwebapplication.asp

    1.30. What is the footprint of the .NET Compact Framework?

    .NET Compact Framework storage size:
    • 1.55MB (ROM) on Pocket PC 2000/2002
    • 1.35MB (ROM) on Windows Mobile for Pocket PC 2003 or Windows CE .NET Devices
    Running RAM requirements:
    • .5 MB+ (depends on application)
    Typical application sizes:
    • 5 - 100 KB
    1.31. How do I include imgdecmp.dll in an emulator image?

    You must ask the OEM to include it in the device's image. If you are the OEM and you are using Platform Builder 4.2, then including the OS Dependencies for the .NET item automatically causes imgdecmp.dll to be part of the emulator image - if that is not working then refer to cesysgen.bat. Another method is to set the environment variable "__SYSGEN_IMGDECMP=1" to explicitly force the DLL into the image.

    1.32. How do I programmatically replace Assemblies in the Global Assembly Cache (GAC)?

    One can install and remove Assemblies directly to and from the GAC by programmatically launching cgacutil.
    • Remove assemblies from the GAC using the -u option
    • Install assemblies to the GAC using the -i option
    It is typically safest to remove the Assembly before reinstalling it.

    1.33. How can I display Pocket PC applications on my desktop or laptop without needing any device side configuration?

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

    1.34. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?

    See the entry titled "11.17. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?" of this FAQ.

    1.35. How can I copy files to the device currently connected to desktop ActiveSync?

    See the entry titled "11.18. How can I copy files to the device currently connected to desktop ActiveSync?" of this FAQ.

    1.36. How can I stress test user input?

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

    1.37. Where can I get a UI version of the Platform Builder Target Control Window?

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

    1.38. Where can I get a Command shell for Pocket PC 2003 devices?

    Download PPC Command Shell from Windows Mobile Developer Power Toys:
    http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

    1.39. How can I get detailed information about currently running processes?

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

    1.40. How can I remotely start an application on a Pocket PC from my desktop?

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

    1.41. Why can't I load different assemblies with the same name?

    This is by design. You must either change the names of the DLLs, or if the DLLs are strong named, place them in the GAC and use Assembly.Load with a full strong name.

    1.42. How can I force Visual Studio .NET 2003 to connect to newer versions of the Pocket PC 2003 emulator?

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

    This allows ActiveSync to connect to your Emulator session from Visual Studio .NET 2003. Create an ActiveSync session to the 4.2 emulator, this will allow Visual Studio 2003 to consider it a real device (Choose PPC device as the deployment target).

    1.43. Why don't my custom controls show up properly in the toolbox?

    While adding designer support in Visual Studio .NET 2003 for Smart Device custom controls, you may run into the following issues:
    • Unable to associate an Icon to the Control for showing it in the toolbox at design time
    • The component, when added to the toolbox, becomes greyed out
    Causes
    • Using a design project separate from the control project. Visual Studio .NET automatically prepends the project default namespace to the bitmap name. The "default namespace" defaults to the project name. This may be a problem because the design project has a slightly different name than the runtime project.
    • Not setting the correct ToolBoxItemFilterAttribute values
    Resolutions

    Given the following example:
    Runtime VS.NET Project: MyProject
    Class Name: MyProject.MyClass
    Design VS.NET Project Name: MyProject.Design
    BitMap name in VS.NET Design Project: Foo.bmp
    Bitmap name in design assembly: MyProject.Design.MyClass.bmp
    -- This creates a problem because the bitmap needs the name: MyProject.MyClass.bmp

    In the above example, setting the design project's default namespace to "MyProject" rather then "MyProject.Design" should fix the problem.

    The easiest way to check the name of the bitmap within the assembly is to run ILDASM and open the Manifest. The embedded resources are listed at the end of the manifest.

    If you create a custom component derived from the Component class, your code must include the following statements so that your component appears in the Toolbox:
    ToolBoxItemFilterAttribute("NETCF",ToolBoxItemFilterType.Require)
    ToolBoxItemFilterAttribute("System.CF.Windows.Forms", ToolBoxITemFilterType.Custom)
    
     

    Top of Page Top of Page

    2. 图形


     

    2.1. 怎样建立一个图形对象?

    有很多种方法可以建立图形对象,看你怎么用:

    在OnPaint中,使用object参数提供的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
    
    在程序的其他部分,利用控件的一个方法,可以用来建立任意控件的图形对象:
    //C#
    using System.Drawing;
    
    Graphics g = this.CreateGraphics();
    
    'VB
    Imports System.Drawing
    
    Dim g As Graphics = Me.CreateGraphics()
    
    直接画到bitmap位图文件中:
    //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的绘图速度:
    • 只建立一个图形对象 (或只使用OnPaint中的 PaintEventArgs)。
    • 把所有绘图工作先画到不显示的位图上,再一次性把位图显示出来。
    • 只重画变化的部分图象。
    • 尽可能在相同的区域上画相同大小的图象。
    主要思路:最小化地重画图象。例如,当光标拖过图象时,不需要把整个图重新画一遍。只需要重画光标之前经过的地方。

    2.3. 怎样在窗体上画一个图案?

    这里有个例子,告诉你怎样把图片画到窗体的背景上:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/bkgndimage.aspx

    2.4. 怎样画一个带有透明色的图案?

    画一个带有透明色的图象,需要设置ImageAttributes对象的透明色。目前.net精简框架支持单种颜色的透明色。虽然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.FromArgb(255,0,255),Color.FromArgb(255,0,255));
    attr.SetColorKey(Color.Fuchsia, Color.Fuchsia);
    
    'VB
    attr.SetColorKey(Color.FromArgb(255,0,255),Color.FromArgb(255,0,255))
    attr.SetColorKey(Color.Fuchsia, Color.Fuchsia)
    
    图象会被重载的Graphics.DrawImage方法重画,并且使用ImageAttributes对象作为一个参数parameter:
    //C#
    g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height,GraphicsUnit.Pixel, attr);
    
    'VB
    g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height,GraphicsUnit.Pixel, attr)
    
    2.5. 为什么从TextBox上调用CreateGraphics会失败?

    只有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. Can I set the width of a pen?

    Setting the pen width is not available in the .NET Compact Framework. Some alternate solutions include:

    • Drawing filled rectangles with the Graphics.FillRectangle method
    • Drawing multiple lines next to each other
    • Writing a custom graphics routine with GAPI
    2.8. How do I zoom an image?

    While there is no inherent support for zooming or stretching a single image, these effects can be achieved quite easily by creating a new Bitmap object with an associated Graphics object and copying the desired portion of the original Bitmap into it. The following sample creates two bitmaps of the same size, where the second contains a zoomed center section of the first, provided the project has an embedded resource named MyImage.bmp. This same technique could be used to stretch images by modifying the source and destination rectangles such that they do not maintain their original aspect ratio.
    //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. Why can't I load an image?

    Ensure that imgdecmp.dll is in the device's Windows directory.

    For more information, see the topic "1.31. How do include imgdemp.dll in an emulator image?" of this FAQ.


     Top of Page Top of Page

    3. 发布


     

    3.1. 怎样建立一个PocketPC的设置程序?

    这篇文章告诉您如何建立一个单独的.msi文件,可以运行并把应用安装到不同的Pocket PC设备上。整个过程都是自动的,所以很容易把所有需要的组件都打包到.msi文件中。包含C#和Microsoft Visual Basic .NET代码。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdeployment.asp

    3.2. 哪个发布包可以包括在我的安装程序中?

    您可以为您的用户提供一个最终的发布包,以帮助他们升级设备。您不能拆开这个发布包把内容给您的用户。但是,您可以拆开开发人员的发布包把内容给您的用户。

    3.3. 怎样可以建立一个不需要.net框架的安装程序?

    这篇文章讨论了如何成功的安装一个Pocket PC的应用:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppc2k/html/ppc_allation.asp

    3.4. 怎样建立不受PocketPC系统约束的CAB安装文件?

    您可以建立一个.inf文件生成一个适合任何Pocket PC设备的应用程序安装文件。查看示例代码:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/cabfile.aspx

    3.5. 为什么不同的处理器会有不同的CAB安装文件?

    每一个CAB文件都包含一小段检测智能设备上的.net精简框架版本的代码。这个功能是处理器/平台特有的,不同的CAB文件根据处理器类型绑定不同的代码。

    3.6. How do I create a desktop installer that detects the presence of the .NET Compact Framework on the target device and installs it if necessary?


    The article titled "Creating an MSI Package that Detects and Updates the .NET Compact Framework" in the MSDN Library describes a technique that may be used:
    http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull=/library/en-us/dnnetcomp/html/netcfdepl.asp

    3.7. How do I deploy a .NET Compact Framework Service Pack to the emulator?

    Download and install to your desktop development PC a "Developer" version of the service pack (the download title will read something like: "Microsoft® .NET Compact Framework 1.0 SPx Developer Redistributable") from:
    http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

    The next step is to copy the appropriate .NET Compact Framework cab file (as per next paragraph) to the emulator. From within the emulator point File Explorer to a share on your PC and then copy and paste the cab to somewhere on the emulator's file system. Now launch the cab file from File Explorer and answer "Yes" if asked to overwrite anything.

    Emulator

    CAB File

    Pocket PC 2002 netcf.core.ppc3.x86.cab
    Windows Mobile 2003 for Pocket PC netcf.core.wce4.x86.cab
    Windows Mobile 2003 for Smartphone RAM installs not supported

    3.8. How do I include SQL Server CE with my application installation?

    To install SQL Server CE with an application, simply install the proper SQL Server CE CAB files as part of the application's installation. There are two sets of cabs associated with SQL Server CE.

    The developer CAB includes Query Analyzer, and error strings. This CAB should not be included with application deployment. It comes in two actual files, one for Pocket PC and one for Windows CE 4.x devices:

    sqlce.dev.ppc3.<processor>.cab
    sqlce.dev.wce4.<processor>.cab

    The SQL Server CE CAB, which includes the engine, client agent, and managed extensions for the client agent is required by applications utilizing System.Data.SqlServerCe components. This CAB also comes in two actual files, one for Pocket PC and one for Windows CE 4.x devices:

    sqlce.ppc3.<processor>.cab
    sqlce.wce4.<processor>.cab

    Applications that access SQL Server, ie applications utilizing System.Data.SqlClient components should deploy the 'sql' CAB. This CAB also comes in two actual files, one for Pocket PC and one for Windows CE 4.x devices:

    sql.ppc3.<processor>.cab
    sql.wce4.<processor>.cab

    All of these CABs are included in the Visual Studio .NET 2003 Professional Edtion install. The default location is:

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

    3.9. How do I use GAPI to create a graphics engine?

    This article describes how to create a DLL that wraps GAPI (Game API), such that it is .NET Compact Framework compliant, and use it to create and optimize a basic graphics library in managed code.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI1.asp

    This article expands upon the "Dancing Rectangles" sample by implementing loading and displaying of bitmaps. It also implements some more advanced features such as animated bitmaps, source and destination key transparency, and alpha blending, i.e., translucency.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI2.asp

    This article expands upon the "Dancing Zombies" sample by implementing drawing of points, lines, and custom 1 bit fonts converted from 8 bit bitmaps. It also implements an input system that overrides the functionality of the hardware buttons and tracks button states.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI3.asp  

    Top of Page Top of Page

    4. 图形用户界面(GUI): 窗体


     

    4.1. 怎样建立一个全屏的窗体?

    您必须把WindowState属性设置为最大化。做一个看不见的窗体,如把全屏的图片放到窗体中,您需要把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事件?

    窗体的load功能是做界面操作的最好方法。典型又安全的做法是在构造器中创建数据和控件的实例。任何包含用户界面的控件或窗体的初始化,都应该在load功能中完成。例如:在窗体的构造器中完成控件对象的建立,然后在load功能中设置控件的位置等 是安全的做法。

    4.3. 怎样把最小化按钮换成关闭按钮?

    通过开发环境的设计器,可以把窗体的自动最小化模式转变成关闭模式,或者通过变成实现。(x)按钮自动最小化应用程序,(ok)按钮回关闭程序。

    在设计器中转化窗体的风格
    打开Visual Studio环境的窗体设计器,查看属性。在窗体上右键并选择Properties,Window Style 部分把MinimizeBox设置为 False。

    在代码中转变窗体风格
    简单的在窗体的load功能中添加以下一行代码:
    //C#
    this.MinimizeBox = false;
    
    'VB
    Me.MinimizeBox = False
    
    4.4. 怎样在.net精简框架上建立多窗体系统结构?

    这篇文章讨论了如何在.net精简框架上为应用程序有效的建立用户界面:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfuiframework.asp

    4.5. 怎样提高.net精简框架应用程序的载入速度?

    通过下面文章中的优化技巧,减少.net精简框架应用程序的载如时间:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfimproveformloadperf.asp

    4.6. 运行时怎样修改窗体的风格?

    这篇快速入门教程描述了在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. 怎样强迫一个窗体变成最小化?

    请查看本问 "6.6. 如何是窗口一直保持最小化? " 部分。

    4.10. 我有一个包含很多控件的智能设备窗体,为什么运行的时候出现"NotSupportedException"错误?

    如果你的窗体中包含了很多控件,当你运行的时候可能会有NotSupportedException的错误。如果你是在Debug模式下运行的话,你会发现异常是来自于窗体的InitializeComponent部分。这种情况是由于精简框架CLR在编译类的方法时,会有64kb的限制造成的。这意味着CLR把方法(如,InitializeComponent)翻译成中间语言时,返回的机器码不能超过64KB。如果超过了64KB,NotSupportedException将被抛出。这也是为什么容易在Debug模式(F5)下导致错误,而非Debug模式(Ctrl+F5)却不容易出错。因为Debug模式运行时会生成更多容量的调试代码。

    除了模拟器,您也可能在智能设备上遇到这个错误,因为即时编译代码根据因CPU类型而异的(如,PocketPC使用的是ARM指令,而模拟器上使用的x86指令)

    没有一个准确的数字说明,一个窗体中到底可以包含多少个控件。因为不同控件的产生的代码量不一样。如,一个Button控件,比TabControl控件产生的代码要少。还会因由设置了多少属性而异。包含集合的控件,象ListBox或TreeView,如果在设计时向属性框中填入了很多值,编译时将产生大量代码。同样,设置了Localized的窗体(Localizable属性为true),会比没设置localize的窗体产生更多代码。因为localize需要从资源文件中读取属性值,放在InitializeComponent方法中。

    果你遇到这种情况,下面有一些技巧帮助你避免它的发生:
    • 把一个窗体的代码分成多个窗体。过多控件的窗体,会影响程序开始时载入的性能。尽可能把用户界面分成两个或多个窗体。
    • 不要在设计时填充大的、内部的、带集合的控件。如果你把很多节点集合加到TreeView控件中,这样会在InitializeComponent方法中加入大量代码。尽可能把加入集合的代码移到Form.Load事件中。这样做的缺点是,要在设计时编辑这些集合将变得不容易,但它有助于分割代码。
    • 不要把自己的代码添加到InitializeComponent方法中,这对通常的编码都有用,不建议添加、修改设计起生成的代码。这样做会造成设计器不可知的错误。如果你想添加自己的启动代码,你应该在Form.Load事件中做。
    • 运行时初始化类似的控件。比如,有12个Button控件,只是文字和位置不同,你应该考虑使用循环来设置属性,而不是在设计时设置属性。在次,如果你自己写代码来实现它,不要把代码放在InitializeComponent方法中。

    编辑InitializeComponent方法的缺点是,在InitializeComponent代码外建立对象实例的代码,将不能在设计器重被设计。同样,如果你手动修改了InitializeComponent中的代码,你会发现,设计器可能不再识别你修改的代码。所以以上技巧的前提是,不要修改InitializeComponent中的代码。

    4.11. 哪个是正确关闭窗体的方法:Appplication.Exit 还是 Form.Close ?

    Application.Exit是类似Win32平台下的PostQuitMessage()硬性退出。收回所有弹出的信息,释放呼叫堆栈,把执行权返回给系统。

    在windows平台(Win32或.NET)下正确关闭应用程序的方法是关闭主窗体(如:Form.Close)。所有主窗体结束时仍存在的窗体需要手工关闭。Any window that's still present after the main message pump ends needs to be manually closed. 好的方法就是在应用程序调用Form.Close或Form.Dispose退出之前,关闭所有窗体。需要记住.NET框架的OnClosing()就是Win32平台下WM_CLOSE的托管版本,而不是WM_DESTROY。

    另外,使用form.Close()的话,你的程序可以在OnClosing或OnClosed事件中处理释放资源、关闭文件等操作。如果使用Application.Exit退出,这些事件将不会被触发。


    4.12. Why does showing a MessageBox on Windows Mobile 2003 for Smartphone with the Abort, Retry, and Fail set of buttons or the Yes, No, Cancel set of buttons, or the third button as the default button result in a NotSupportedException?

    Windows Mobile 2003 for Smartphone only supports 1 or 2 button MessageBoxes.

    4.13 How do I get an icon in the Pocket PC Start Menu Most Recently Used (MRU) List?

    Create a shortcut to your application somewhere under \windows\start menu\programs. When your application is launched from this shortcut an icon for your applications will appear the MRU list.



    4.14 How do I center a Form on the screen?

    In order to display a non-full screen Form, ensure that the Form's FormBorderStyle property is set to FormBorderStyle.None. To center the form add the following code to the Form's FormLoad event handler: Set FormBorderStyle to FormBorderStyle.None then:
    //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 Why can't I show a Form that has been closed?

    Once a Form is closed, it is disposed and therefore may be garbage collected by the system so it is not safe to attempt to show a closed Form. An alternative solution is to use Form.Hide and Form.Show to hide and display Forms respectively.

    4.16 How can I enable multiple instances of an application?

    Multi-instancing is not supported by the .NET Compact Framework. The following code sample provides a solution that allows applications to be instanced rather than maximized when an application is launched but a running instance already exists.

    Note: The following code is not supported and is not guaranteed to work on all versions of the OS, including future versions.
    // 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
    
    <DllImport("CoreDll")> _
    Public Shared Function FindWindow(ByVal lpClassName As String, _
      ByVal lpWindowName As String) As IntPtr
    End Function
    
    <DllImport("CoreDll")> _
    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
    

     Top of Page Top of Page


    5. 图形用户界面 (GUI): 通用


     

    5.1. 怎样建立一个带有图形或支持多行的按钮?

    建立一个带有图形或支持多行的按钮需要使用自定义控件。自定义控件能继承button的paint方法,以及其他任何需要的自定义数据。参考以下连接获得更多关于自定义控件的信息:

    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精简框架下是怎样工作的?

    虽然设置了AcceptsReturn为false,但它还是按true的方式来操作。你可以写一个继承TextBox的类,在KeyPress事件中实现对Enter的处理。

    5.3. 当数据载入ComboBox的时候,为什么SelectedIndexChanged事件没有被触发?

    这是一个已经知道的问题,将在以后的.net精简框架中发布。

    5.4. Show和ShowDialog有什么不同?

    ShowDialog会把一个窗体以 模式 方式显示,这是一种独占调用方式,知道窗体关闭才会返回。这个方法将返回一个DialogResult枚举,表示关闭的条件。
    Show是一种非独占的调用方式,和显示一个控件一样,可以立刻返回,没有返回参数。显示一个控件意味着Visible属性被设置为true,直到Hide方法被调用,Visible方法才会变为false。

    5.5. 为什么我不能建立右键菜单分离器?(separator)

    这是一个已经知道的BUG,把右键菜单设置为分割线,将抛出NotSupportedException错误。这个问题是由于WinCE系统有个限制,不允许在已经加入右键菜单的菜单项设置为分隔符,并且菜单的父类是一个控件。在Visual Studio 2003种,设计器分割移动应用代码的方式和PC上的应用程序类似。这是导致此问题的原因。解决的方法是,把右键菜单单独放在InitilizeComponent方法外的地方。

    5.6. 运行时把ImageList赋给ToolBar时,为什么图象不出现?

    你可以在窗体载入的时候把ImageList分配给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. 如何在菜单项中显示符号:&?

    这项功能还不被.net精简框架支持。使用"&&"不会在菜单项的文字中显示"&"符号。

    5.9. 如何制作基于.net精简框架的动画控件?

    这篇文章将告诉你如何制作基于.net精简框架的动画控件:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/animationcontrol.asp

    5.10. 如何在.net精简框架上制作自定义控件?

    学习制作.net精简框架控件,提高您的技巧。(文章附带了自定义控件的示例代码):
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/customctrlscompactfx.asp

    5.11. 如何制作基于.net精简框架的带图片的按钮?

    这篇文章讨论了建立基于.net精简框架的带图片的按钮:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/ImageButton.asp

    5.12. 如何使用.net精简框架下的MessageWindow类库?

    学习如何使用.net精简框架 MessageWindow 类建立一个提示图标:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/messagewindow.asp

    这篇快速入门实现了,当鼠标点击矩形自定义控件或点击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精简框架中的DataGrid控件提供了几乎.net框架中的DataGrid控件的所有功能。一个主要的区别是.net精简框架中的DataGrid不能在运行时编辑单元。这篇快速入门教程演示了如何通过程序实现编辑单元格的一种方法:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridediting.aspx

    5.15. 怎样设置DataGrid的DataSource?

    与.net框架的DataGrid的另一个区别是,.net精简框架的DataGrid不支持把DataSource设置为DataSet。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagrid.aspx

    5.16. 怎样对DataGrid的列排序?

    与.net框架的DataGrid的另一个区别是,.net精简框架的DataGrid不支持在运行时按照列进行排序。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridsorting.aspx

    5.17. 怎样对ListView中的内容排序?

    .net精简框架不支持ListView.Sort方法,但任然可以排序。这篇快速入门教程定义了一个继承ArrayList.Sort的IComparable接口的方法:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/listviewsort.aspx

    5.18. 如何使用 输入板(SIP)控件?

    这篇快速入门教程演示了在PocketPC上打开和关闭软输入板(SIP),以及当SIP显示时,tab控件大小也跟随变化:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/inputpanel.aspx

    多个窗体应该共享一个输入板对象。可以通过先在主窗体中建立SIP对象,然后把它传给子窗体或暴露SIP对象的一些方法、属性给其他需要使用SIP的窗体。

    5.19. 如何自定义事件?

    这篇快速入门教程描述了如何继承Button类、重载方法来事现双击事件。这个自定义事件会在按钮被双击时触发,两次点击的间隔时间是SystemInformation.DoubleClickTime 属性的值,以毫秒为单位。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/btndclick.aspx

    .net精简框架的控件不支持OnEnter和OnLeave方法,包括Windows.Forms.Control基类。但是,因为支持Control.OnMouseMove方法,您可以通过它和Control.Capture 属性判断鼠标什么时候进入和离开控件。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/enterleave.aspx

    5.20. 如何做一个 owner-drawn List Box?

    您可以制作一个.net精简框架的owner drawn list box。.net精简框架的ListBox或其他控件不支持DrawMode、DrawItem, 或其他drawing方法,但您可以编程实现。这篇快速入门教程提供一个自定义控件类,建立一个owner-drawn list box,并实现了选择字体的控件的功能。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/ownerdrawnlistbox.aspx

    5.21. 如何做一个多选框判断真假?

    这篇快速入门教程提供了在Windows.Forms.CheckBox控件上建立真/假多选框:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/tfcheckbox.aspx

    5.22. 设置InputPanel.Enabled = true的时候为什么出现异常?

    InputPanel组件需要窗体包含MainMenu控件,而且那个窗体是显示在屏幕上的。

    5.23. 为什么自定义控件不会自动继承父类的字体?

    这个功能不被.net精简框架所支持。

    5.24. 为什么当输入字符时,NumericUpDown 和 DomainUpDown 控件不会引发 ValueChanged 和 SelectedItemChanged 事件?

    在代码中改变控件的值 或 按下了上、下箭头才会触发ValueChanged和SelectedItemChanged事件。当用户往控件中输入字符的时候时不会触发的。

    5.25. 为什么NumericUpDown控件增长的值不是设置好的值?

    当您按了上、下后出现的值,不是增长值的倍数,它将向着那个方向(上或下)直到下一个增长值的倍数的值。

    5.26. 为什么StatusBar不能放在窗体的任意位置?一定要在底部?

    StatusBar控件只能停靠在窗体的底部,它的大小不能改变。

    5.27. 为什么我的控件自动继承了父控件的背景色?

    这个功能不被.net精简框架所支持。可以采取的方法是继承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控件能接受decimal类型的值,但不会显示大于2^16的值?

    虽然NumericUpDown控件接受decimal类型的值,但.net精简框架把这个控件的值当作int类型来处理。如,10.23当作10。同样此控件在PocketPC上不接受大于带符号的16位整型。

    5.29. 为什么不能在DomainUpDown 中输入文字,而要选择?

    DomainUpDown控件不会对输入的文字进行确认(不象完整的.net框架)。如果您先输入了一些文字,再按上、下箭头,它会显示内容改变前的值的下一个值。

    5.30. 为什么OpenFileDialog被限制在"My Documents" 文件夹中?

    OpenFileDialog的初始化目录被限制在"My Documents"文件夹或它的子文件夹中。这个限制是由PocketPC系统强加的,为了帮助用户在标准目录下管理自己的文档。
     

    5.31. How can I activate the SIP (InputPanel) without a menu?

    The SIP can be activated by P/Invoking the function "SipShowIM" as follows.
    //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
    
    <DllImport("coredll.dll")> _
    Private Shared Function SipShowIM(ByVal dwFlag As Integer) As Integer
    End Function
    
    5.32. How do I add a subnode to every node in a TreeView?

    Adding subnodes to all nodes is accomplished by iterating through all of the nodes in the TreeView and adding a new node to each.
    //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. How do I determine the number of rows or columns in a DataGrid?

    The number of rows and columns in a DataGrid can be determined from the data source itself. For example:
    //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
    
    If the DataGrid is bound to the DataView you can also use DataView.Count.

    5.34. How do I create a owner drawn Listbox?

    See the .NET Compact Framework QuickStarts, Implementing Events topic:

    http://samples.gotdotnet.com/quickstart/compactframework/doc/btndclick.aspx

    5.35. How can I implement Control.GetNextControl under the .NET Compact Framework?

    The tab order of the controls in the .NET Compact Framework correspond directly to the order of the Controls in the Form.Controls collection. Therefore, GetNextControl can be implemented by determining the index of the specified Control and determing its neighbors in the collection.
    //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. How do I get notified when the user clicks on a treeview node?

    TreeView does not support the Click event, however, a workaround is to use the AfterSelect event instead.

    5.37. How do I set the title of a fullscreen multiline edit control window?

    This is not supported by the current version of the .NET Compact Framework.

    5.38. Why don' I see the validItem selected when I set ComboBox.SelectedValue to validItemInCollection?

    Setting the SelectedValue property only works if the control is databound.

    5.39. How do I detect the location where a 'tap & hold' occurred to bring up a context menu on my custom control?

    Handle the ContextMenu.Popup event, and then query the current mouse coordinates using 'Control.MousePosition'.

    5.40. Why doesn't the scrollbar value ever get set to the maximum value?

    Similar to the NumericUpDown control, the maximum achievable value is the first empty row above the thumb. More specifically, from the editor properties, this equates to:

    Maximum - (LargeChange + 1).

    5.41. How do I tab out of a custom control to the previous control?

    Call this.Parent.Controls(this.Parent.GetChildIndex(customcontrol) - 1).Focus() in the KeyDown event handler when a Keys.Up key is detected.

    5.42. How do I add Toolbar buttons with transparency?

    Icons support transparency, however, there is a known bug in Visual Studio .NET 2003 designer that creates incorrect code and makes icons non-transparent. A work around is to add an icon file to the ImageList outside of InitializeComponent and add the icon files to the project as content or embedded resources. The following code demonstrates this:
    //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
    
     

    Top of Page Top of Page

    6. 与本地代码(Native Code)互用


     

    6.1. 如何调用本地代码写的DLL中的函数?

    本地DLL代码可以通过系统的Invoke (P/Invoke)方法调用。这些文章提供了如何实现调用和更多的调用技巧:

    6.2. 如何使用dumpbin.exe帮助描述 P/Invokes?

    见本问答的 "6.1. 如何调用本地写的DLL中的函数? " 章节。

    6.3. 如何为微软.net精简框架写非托管代码?

    见本问答的 "6.1. 如何调用本地写的DLL中的函数? " 章节。

    6.4. 如何调用 P/Invoke GetTickCount?

    不需要使用P/Invoke调用GetTickCount功能,因为Environment.TickCount就提供了这个功能。
    见本问答的 " 7.2. 如何计算精确的时间间隔?" 章节。

    6.5. 如何获得系统还有多少可用内存?

    您可以调用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
    
    <DllImport("coredll.dll")> _
    Private Shared Sub GlobalMemoryStatus(ByRef ms As MEMORYSTATUS)
    End Sub
    
    <DllImport("CoreDll.dll")> _
    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
    
    <DllImport("CoreDll")> _
    Public Shared Function FindWindow(ByVal className As String, ByVal WindowsName As String) As IntPtr
    End Function
    
    <DllImport("CoreDll")> _
    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精简框架上调用系统函数时,如何装配数据类型?

    见本问答的 "6.1. 如何调用本地写的DLL中的函数? " 章节。

    6.8. 如何得到一个窗体或控件的句柄 (HWND) ?

    其实有一些使用调用本地代码的方法可以获得控件的句柄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
    <DllImport("coredll.dll", SetLastError:=True)> _
    Public Shared Function GetCapture() As IntPtr
    End Function
    
    <DllImport("coredll.dll", SetLastError:=True)> _
    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函数可以建立精确的计时程序。 这些功能是和设备提供商相关的,如果他们不能执行,那么只能和GetTickCount功能得到一样的结果。如果能执行这些函数,就能保证计时器最准确的运行,比GetTickCounter或Environment.TickCount准确得多。TickCount其实是调用GetTickCounter的。

    如果性能计数器是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
    <DllImport("CoreDll.dll")> _
    Public Shared Function QueryPerformanceFrequency(ByRef lpFrequency As Int64) As Integer
    End Function
    
    <DllImport("coredll.dll")> _
    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. 调用本地代码时,数据类型有什么限制?What are the limitations on marshalling types via P/Invoke?

    • 返回值
      • 只能是长度小于等于32位的类型
      • 非浮点型not floating point
    • 参数
      • Only support marshaling blittable types
        • blittable types -> same representation in memory in both managed and native
        • non-blittable -> memory transformation required
        • Since only blittable types, all objects are pinned and never copied
          • Exception: passing String ByVal in VB.NET
        • Implies that you can't marshal nested objects since this requires a memory transformation (non-blittable)
      • 只能是长度小于等于32位的类型
        • 值通过堆栈传递
        • 例外:float32
      • 参考(References)
        • Pass blittable reference types
        • 把参考传递到值类型变量
        • 这就是如何传递float32类型的值
      • 可以传递值类型的数组
        • 在本地代码中,您可以使用指针指向第一个对象,然后一个接一个地访问其他对象
      • String是特殊的,传递char数组 -> 不变的
      • StringBuilder是特殊的,传递char数组 -> 易变的 (需要单独传递长度)
      • 注意:C# bool是8个比特位的,并且不等于Win32的BOOL
      • 队列:编译器默认的队列 (4字节)
      • Marshal.GetLastWin32Error 支持 GetLastError() 语义
      • 未支持的:
        • MarshalAs: no support for non-blittable types
        • StructLayout: 不能改变外观
        • Delegates(委托)
        • DateTime
        • Only support default calling convention

    6.11. 调用GetLastError时,总是获得不定的代码?

    尽量不要尝试调用Windows GetLastError() API,因为CLR调用本地代码时可能会改变last error的代码。取而代之的是,使用调用的返回值标记错误代码,再调用System.Runtime.InteropServices.Marshal.GetLastWin32Error()方法来获得错误代码。
    using System.Runtime.InteropServices;
    
    [DllImport("coredll.dll", SetLastError=true)]
    int myFoo(...);
     
    Foo(...)
    {
        int rc = myFoo(...);
     
        if (rc == false)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "Foo failed");
        }
    }
    

    6.12. 调用本地代码时,有没有参数数量的限制?

    有限制。.net精简框架版本1.0的限制为12个。

    6.13. 调用本地代码时,为什么得到"NotSupportedException"异常?

    通常有三种可能性:
    • 在托管代码中的申明不正确
    • .net精简框架不支持你想做的操作
    • dll的名称在暴露过程中损坏了

    检查以下项目: 
    • 有没有违反.net精简框架 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
    <DllImport("coredll.dll", SetLastError:=True)> _
    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。

    第一种方法,使用非安全代码,直接用指针指向byte数组。
    //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和Marshalling函数复制内存块得到数据块。
    //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
    <DllImport("coredll.dll", SetLastError:=True)> _
    Public Shared Function LocalAlloc(ByVal uFlags As UInt32, ByVal uBytes As UInt32) As IntPtr
    End Function
    
    <DllImport("coredll.dll", SetLastError:=True)> _
    Public Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr
    End Function
    
    <DllImport("coredll.dll", SetLastError:=True)> _
    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. Why do I get a MissingMethodException when I call a function from a native DLL?

    There are several issues to consider when determining the case of a MissingMethodException. When this exception occurs you should verify the following:

    For the latest Microsoft eMbedded Visual Tools and SDK downloads, visit the MSDN Mobile and Embedded Developer Center "Products & Updates" download page at:
    http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

    6.16. How do I set the system time?
    You can set the system time by P/Invoking the SetSystemTime function.
    //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
    
    <DllImport("coredll.dll")> _
    Public Shared Sub GetSystemTime(ByRef lpSystemTime As SYSTEMTIME)
    End Sub
    
    <DllImport("coredll.dll")> _
    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. How do I programmatically soft reset the device?

    The device can be soft reset through P/Invoking of the KernelIoControl function, as demonstrated in the code below. For more information on how to use the function and extend the functionality of this sample, refer to Visual Studio .NET Help.

    Note: On Smartphone devices, this will only work if you are signed with a privileged certificate.
    //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
    
    <DllImport("Coredll.dll")> _
    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. How can I put an icon on the title bar regardless of the which form is active?

    This is not supported with the current version of the .NET Compact Framework. You can, however, P/Invoke Pocket PC's notificaiton system to do this. Refer to the following for more information:

    Sample Code:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppc2k2/html/ppc_fications.asp

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

    The native Notification APIs are: SHNotificationAdd, SHNotificationRemove, SHNotificationGetData, and SHNotificationUpdate.

    6.19. How do I disable and capture hardware buttons?

    Refer to the sample in the P/Invoke library.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PInvokeLib.asp#PInvokeLib_Topic03

    6.20. How do I hide the start icon?

    The Start icon can be hidden using the 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
    
    <DllImport("aygshell.dll")>  _
    Shared Function SHFullScreen(ByVal hwndRequester As IntPtr, ByVal dwState As Integer) As Integer
    End Function
    
    <DllImport("coredll.dll")>  _
    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. How do I enumerate, create, and terminate processes?

    Refer to the sample:
    http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull=/library/en-us/dnnetcomp/html/processmanager.asp

    6.22. Where can I find a centralized library of P/Invoke samples?

    This sample demonstrates how to P/Invoke numerous useful native functions that are not directly available through the .NET Compact Framework. A test Form is provided that enumerates all available test procedures and allows the user to select and run them:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PInvokeLib.asp

    6.23. How do I play and record .WAV audio files with the Waveform Audio Inteface?

    Learn how to use the Waveform Audio Interface to record and play ".wav" files:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WaveInOut.asp

     Top of Page Top of Page

    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 splashImageName = 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 splashImageName As String = Path.Combine(fullAppPath, "myfile.txt")
    
    学习如何获得程序执行的当前目录。在Embedded Visual Basic中,程序执行的当前目录可以通过App.Path属性获得。执行程序的目录可以通过程序集的AssemblyName对象的获得,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精简框架下,这个值的误差在0.5秒内,大多情况下会比0.5秒小。
    • GetTickCount()
      属性Environment.TickCount就是调用GetTickCount函数的,所以没有必要再调用本地代码中的这个方法。
    • Performance Monitor
      可以作为压力测试用途,但不是为最终使用的应用程序而设计的。如需更多信息,请查看本问答的 "7.5. 如何使用性能监视器? " 章节
    • Timers
      使用System.Threading.Timer类,可以在线程内设定计时器,用委托(delegate)指向应用程序 。
    • Performance Counter
      如果OEM厂商支持的话,QueryPerformanceCounter函数能提供最高精度的计时功能。
      请查看本问答的"6.9. 如何使用性能计数器功能? "章节。

    7.3. 如何把嵌入式资源当作一个流(Stream)?

    为了能够访问嵌入资源,应用程序只须简单地引用相关的程序集(assembly)并调用GetManifestResourceStream方法。下面这个例子岩石了如何从嵌入资源中建立一个位图:
    //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得到。

    注意:如果AssemblyName中有空格,它将被下划线代替,而且必须这样访问。

    7.4. 为什么得到一个"An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll"的错误?

    这是.net精简框架的BUG。这是由于Windows CE底层的Secure Sockets Layer (SSL)的限制造成的。但是,也偶避免的方法,如果设置 req.AllowWriteStreamBuffering为true,不要设置req.ContentLength属性,那就不会在发生这个错误了。

    7.5. 如何使用性能监视器?

    性能计数器通过编辑设备注册表建立:
    1. 建立注册表键:"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETCompactFramework\PerfMonitor"
    2. 新建双字节项,值就是计数器的名字。
    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函数暂停调用的程序,直到第二个程序运行结束。以下快速入门演示了通过PocketPC模拟器来实现这一操作:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/waitforsingleobject.aspx

    7.8. .net精简框架的应用程序会建立什么线程?

    一个.net精简框架程序最多会产生4个线程:
    • 一个主应用程序线程。
    • 一个线程控制各种时间间隔,时间间隔是供系统和其他应用程序使用的。
    • 一个线程跟踪活动的TCP/IP接口的变化(模拟Windows XP上的媒体动作,Windows CE上是没有这些操作的)。
    • 一个执行终止对象的线程。当第一个被垃圾回收的对象回收时,就被建立了。
    7.9. 如何把byte数组转换成结构体?

    在C++中,通过建造类型(typecasting)可以很方便和有效的保存一个类或结构体到文件,并直接从文件中重构出来。但托管代码的本性决定了它不能这样实现。但还是有办法实现的,建立一个类,把内存中的数据作为它的属性让其他类访问。例如:
    //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. 我可以建立一个委托(delegate)交给Invoke吗?

    不可以。在.net精简框架中,只有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))
    
    Although the following will compile, it will not work properly:
    //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. 如何在微软.net精简框架上使用电话API?

    查看这篇文章,学习如何在基于.net精简框架的应用程序中访问电话API:

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

    7.12. 如何在Pocket Pc上生成GUID?

    Guid.NewGuid方法可以生成新的GUID,但在.net精简框架中没有此方法。阅读这篇文章,学习如何根据GUID规范在PocketPC应用程序中建立GUID对象:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCGuidGen.asp

    7.13. 如何让我的.net精简框架程序和Pocket Outlook的数据结合?

    这篇文章讨论了如何使用InTheHand公司的Pocket Outlook .NET组件:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/inthehandpoom.asp

    7.14. 我可以判断.net精简框架中一个文件的版本吗?

    Visual Studio .NET 2003帮助中的C# Programmer's Reference提供了在.net精简框架下使用不安全代码调用GetFileVersionInfo函数。 这个例子带来的问题是,这个函数是由OEM厂商决定的,并且不保证能返回正确结果。

    使用Reflection可以获得程序集(Assembly)的版本:
    //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精简框架的后台处理有什么相关技术?

    使用后台处理,需要注意相关细节并小心设计。这篇文章提供一些关于后台处理最有用的建议,文中介绍的很多观点是必须说明的:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/BackgroundProcess.asp

    7.16. 在微软.net精简框架上使用多线程有什么技巧?

    学习如何在基于.net精简框架的Windows窗体应用程序中使用多线程。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmultithreadedapp.asp

    7.17. 如何在 智能设备应用 中使用混淆器?

    学习如何使用PreEmptive Dotfuscator混淆器保护你的代码。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfobfuscation.asp

    7.18. 如何使用密码服务对数据进行加密或解密?

    请参考本问答的 "10.5. 写一个捕捉Pocket PC签名的程序n ." 部分。

    7.19. 如何在微软.net精简框架上获得Windows CE设备的唯一号码?

    学习如何使用.net精简框架获得Windows CE设备的设备号。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/retrievedeviceid.asp

    你可以调用本地代码的函数来获得PocketPC的设备号,也就是序列号。这篇快速入门教程,演示了用MessageBox来显示设备号。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/deviceid.aspx

    7.20. 如何在微软.net精简框架的应用程序上发送短消息?

    这篇文章演示了如何从基于.net精简框架的应用程序中发送短消息:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfsendsms.asp

    7.21. 不使用Control.Name,可以判断事件的发送者吗?

    这篇文章讨论了在.net精简框架下如何判断事件的发送者,.net精简框架中的控件不支持name属性:
    http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOsenderevent.asp

    7.22. 如何在线程中调用方法的参数?

    在应用程序中使用多线程,可以提高用户界面的性能。基类Control提供Invoke、BeginInvoke和EndInvoke方法在控件中来建立线程。.net精简框架不支持异步的BeginInvoke和EndInvoke调用。到现在,也还不支持向同步Invoke调用传递参数。这篇快速入门教程提供一个自定义类ControlInvoker,可以实现向Invoke方法中传递参数:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/controlinvoker.aspx

    7.23. 如何建立提醒程序和定时程序?

    这篇快速入门文章描述了使用P/Invoke定义一个用户提醒和订时的应用。您可以计划提醒窗口弹出的时间。您也可以设置一个应用程序在特定的时间运行或响应某个事件。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/notifications.aspx

    7.24. 如何播放声音?

    这篇快速入门教程演示了使用P/Invoke播放个短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
    
    在Visual Studio 2003中测试的时候,可以通过继承开发环境设置命令行的参数。主菜单,选择 Project->Project Name Properties.Property Pages对话框中,选择 Configuration Properties->Debugging。Command Line Arguments 中输入字符串:text box.

    7.26. 当使用已经释放的对象的方法或属性的时候,为什么得到一个异常?

    完整的.net框架不保证,在访问一个已经释放的对象的属性或方法时能成功。在完整的.net框架下,虽然访问某些属性(像Text),经常能成功。根据.net框架和.net精简框架执行上的区别,在.net精简框架上访问已经释放了的对象的方法或属性会经常失败。

    7.27. 如何获得"Enter", "TAB", 和 "Arrow"按键的事件?

    使用KeyDown和KeyUp事件,可以获得无字符的键(像tab)。

    现在,只有一些特定的控件支持key的事件(如,form, panel, textbox 和自定义控件)。在.net精简框架SP2版本中,所有控件都将支持key事件。

    已经知道的问题,在使用模拟器时,从键盘按下tab键将不被支持,但从软键盘(SIP)上按下tab时,会有效果。

    这是VS带的模拟器的原因造成,而不是.net精简框架的问题。.net精简框架触发Key事件当它收到系统传来的WM_KEY*消息。当您在模拟器中运行本地代码程序时,从键盘按下tab键并不会让系统触发WM_KEYDOWN事件。若是通过模拟器的软键盘(SIP),或真正的设备,则不会有这个问题。

    7.28. 如何删除一个只读文件?

    使用System.IO.FileInfo类访问文件的属性。
    //C#
    System.IO.FileInfo fi = new System.IO.FileInfo("filename");
    // remove readonly attribute
    fi.Attributes -= System.IO.FileAttributes.ReadOnly;
    System.IO.File.Delete("filename");
    
    'VB
    Dim fi As New System.IO.FileInfo("filename")
    'remove readonly attribute
    fi.Attributes -= IO.FileAttributes.ReadOnly
    System.IO.File.Delete("filename")
    

    7.29. How do I determine if a member exists at runtime?

    The existence of a member can be determined at runtime using Reflection. The code below demonstrates how to use Reflection to access the "Width" property and the "GetPixel" method of a Bitmap object. In the case of the "Width" property, the code enumerates all "public" properties with a "get" component and then searches for one named "Width". The "GetPixel" sample demonstrates how one might use Reflection to call a known function where the parameter order is unknown. This sample is set up as if the author knows there is a method named "GetPixel" which takes a pixel location of x,y but does not know the order in which they appear in the parameter list. The sample enumerates the methods and searches for one named "GetPixel" and then enumerates the parameter list to determine whether the first or second parameter is named "X". Keep in mind that, due to the differences in hardware pixel formats, the value returned by GetPixel may be different from that set by SetPixel in this sample.

    Reflection provides many powerful tools for determing functionality at runtime so for information, refer to the documentation regarding System.Type and the namespace 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. How do I determine the device name programatically?

    The device name can be accessed through the System.Net namespace, as demonstrated by the following code.
    //C#
    String devName = System.Net.Dns.GetHostName();
    
    'VB
    Dim devName As String = System.Net.Dns.GetHostName()
    

    7.31. How do I build a C# Smart Device project from the command line?

    Enter the following commands as single lines (each is broken into two lines for clarity):
    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. How do I abort an executing thread??

    There is no Abort method to the Thread class in the .NET Compact Framework so a thread must be aborted by returning from the executing procedure. Typically, an application will notify threads of a closing event by setting a global variable. The main thread will then wait for worker threads to finish processing before closing the application. The following HOWTO article demonstrates how to accomplish this.

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


    7.33. Why can't I play a movie on the Pocket PC emulator?

    Windows Media Player is only available on the Pocket PC 2003 emulator. The Windows Media Player install package is for installation on a hardware device connected through ActiveSync and will not install to the emulator.

    7.34. How do I suppress Form titles from showing in the active applications list?

    The Active Programs list on the Pocket PC enumerates all open Forms. To stop a Form from being displayed in the list, simply set the Form's caption to be an empty string. The following example shows how to keep only the application name in the list while a Form is displayed from within another Form:
    //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. How do I access a Control from its instance name?

    You can use Reflection to look up a control instance by its name. Here is some sample code:
    //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. How do I detect the hardware directional pad buttons?

    The hardware directional pad buttons can be detected through the standard key events by comparing the KeyCode from the KeyEventArgs parameter.
    //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. How do I get a double click event when only the Click event is supported?

    See the .NET Compact Framework QuickStarts, Implementing Events topic:

    http://samples.gotdotnet.com/quickstart/compactframework/doc/btndclick.aspx

    7.38. How do I get onenter/onleave style notifications?

    See the .NET Compact Framework QuickStarts, OnEnter/OnLeave Functionality:

    http://samples.gotdotnet.com/quickstart/compactframework/doc/enterleave.aspx

    7.39. How do I use threading in a modal dialog that doesn't hang my app?

    Create a modeless dialog that behaves like a model dialog.
    //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. How do I round floating point numbers efficiently?

    There are two primary methods for rounding numbers:
    • Convert.ToInt32
    • Cast or Fix (C# or VB)
    Convert.ToInt32 automatically handles rounding, where remainders of .5 and greater cause the number to be rounded up. Casting or using Fix requires adding .5 to the number to ensure that it will round properly, as these methods simply remove the remainder.

    Profiling on the emulator and a Compaq iPAQ H3600 series device yielded the following results for 1 million operations of each method, where num is a float set to 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

    Thus, by examining the release build results for the device, it can be concluded that on the current generation of devices it is most efficient to use casting in C# and Convert.ToInt32 in VB. In C#, casting proved to be over 106 times faster, whereas in VB, Convert.ToInt32 was nearly 3 times faster.
    //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. Why does Control.Invoke take so long when a modal dialog is displayed?

    There is a known bug with using Control.Invoke while a modal dialog is displayed through ShowDialog. Download the latest .NET Compact Framework Service Pack to fix this:

    The latest platform updates and .NET Compact Framework service packs are available at:
    http://msdn.microsoft.com/mobility/downloads/default.aspx


    7.42. Is there a way to retrieve the culture information of an Assembly?

    Culture information can be retrieved through 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
    
     
     Top of Page Top of Page

    8.通讯和Web服务


     

    8.1. 如何通过TCP Socket向桌面机发送数据?

    请查看本问答的"10.5. 写一个捕捉Pocket PC签名的程序. " 部分。

    8.2. 为什么不能访问本机上的Web服务?

    不要在设备上使用localhost来引用Web服务,因为对于设备来说localhost就是运行应用程序所在的设备,就是设备它本身。您应该使用机器名或IP地址来引用Web服务。

    8.3. 如何在微软.net精简框架上调用Web服务

    这篇文章向您演示了如何从智能设备上,通过.net精简框架同步和异步调用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框架的快速入门中有说明,标题是"Write a Simple Web service,")。这个快速入门教程提供了一个Web服务的客户端应用:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/xmlwebservice.aspx

    8.6. 如何使用MapPoint3.0得到地图?

    这篇快速入门描述了如何使用MapPoint的Web服务,编程实现在PocketPC上获得特定位置的程序,如以下屏幕截图所示:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/mappointfindmap.aspx

    8.7. 如何使用MapPoint3.0获得地图和方向?

    这篇快速入门教程描述了如何使用MapPoint的Web服务,在PocketPC上获得特定位置的地图方向,如以下屏幕截图所示:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/mappointdirections.aspx

    8.8. Is NTLM authentication supported by the .NET Compact Framework?

    Using Digest authentication instead of Basic or NTLM authentication is the recommended solution. Digest authentication is supported by the .NET Compact Framework.

    8.9. When using blocking Sockets, why does Send throw an InvalidOperationException when blocking is set to false?

    There is a known issue with setting Blocking to false on a blocking socket. There are three paradigms when programming with sockets (both managed and native) and it is strongly recommended that developers use asynchronous I/O functions as a solution to this problem. Select is very inefficient in managed code, and the cost of the regular case exception is also high. The three paradigms are detailed below, with the last being the preferred method.

    • Use blocking calls on blocking sockets (i.e. send(), recv(), etc). This is the simplest method, and probably the most commonly used. The functions perform their operation synchronously, tying up the currently executing thread. This is most acceptable for clients, and multithreaded servers (Microsoft does not recommend using one thread per client because threads are very expensive on Windows). Note that though the operations may block for an unspecified period of time (i.e. until the operation can be completed), they will most often complete immediately.
    • Use non-blocking sockets in conjunction with select or poll. Use the same "blocking" functions, but put the socket in a special mode that prohibits it from blocking. In the cases when the function would block, it returns an error code (in managed code, this throws an exception). You can then use poll or select to wait until a point in time at which an operation would complete (select allows you to manage more than one socket, so you can handle multiple clients on only one thread), and then perform the operation. At the time these calls were created, there were no threads in operating systems, so this was the only way to do things. Using this mechanism has by far the absolute worst performance you could possibly get from socket programming. This problem is exacerbated in managed code, since you now expect an exception to be thrown, which is an even bigger performance hit.
    • Use asynchronous I/O functions on the socket. This is your best all around solution. It allows you to perform operations asynchronously, and you get notified by callbacks. In general, the performance is better than using non-blocking I/O with select, and this is the recommendation for how to do things (at least, in native code).


    8.10. How do I create an http-server?

    Get technical insight on the implementation of Mobile Web Server architecture. Understand use cases, the web server framework and future developments in the architecture:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/NETCFMA.asp

    8.11. Why do I get an exception when calling SetSocketOption with ReuseAddress set?

    This is a known issue in the version 1 of the .NET Compact Framework. To work around the issue, you can P/Invoke setsockopt with SO_REUSEADDR set to true.

    8.12. Why do I get a socket error using SSL to communicate with a server via the WebRequest namespace?

    There is a known issue in the .NET Compact Framework. You can work around this by setting HttpWebRequest.AllowStreamWriteBuffering to True and commenting out your setting of the ContentLength.

     

    Top of Page Top of Page

    9. SQL CE 和 数据


     

    9.1. 使用.net精简框架、SQL Server CE 和 复制 开发应用程序时,要注意些什么?

    这篇文章详细讨论了这个问题:
    http://msdn.microsoft.com/msdnmag/issues/03/09/datapoints/toc.asp

    9.2. 如何在微软.net精简框架上使用合并复制(Merge Replication)?

    这篇文章讨论了如何通过程序在.net精简框架的应用程序中调用合并、复制:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmergereplication.asp

    SQL Server CE是非常好的在设备上管理数据的工具,但在未复制到桌面机的SQL Server之前,它必须保留数据。使用合并、复制在设备上管理数据,然后当设备连接到桌面机时,再合并到桌面机的SQL Server的实例中。.net精简框架提供SqlCeReplication对象,可以通过程序实现数据的合并与复制。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlcemergereplication.aspx

    9.3. 如何将ADO.NET数据和XML绑定?

    以下三个步骤:

    1. 根据提供的XML文件,建立一个XML Schema文件(.xsd)。
    2. 读取XML数据和它的schema,以便操作。
    3. 将XML保存会文件。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/adonetdatabinding.aspx

    9.4. 如何建立SQL Server CE的数据库?

    您可以使用.net精简框架在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精简框架在用户输入时,向SQL Server CE的数据库中插入值。以下教程向您展示了如何实现此操作:
    • 设计一个用户可以设置查询值的界面。
    • 连接到SQL CE的数据库。
    • 把用户输入的值插入到SQL CE的数据库中
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlceparameterizedquery.aspx

    9.6. Why does using RDA and the push method fail with error 27750?

    Symptom
    When calling:
    rda = new SqlCeRemoteDataAccess();
    
    An error of type SQLCeException with a Native Error Code of 27750 occurs. This error corresponds to "Cannot load sscemw20.dll or ssceca20.dll is missing or not registered."

    Resolution
    Load the library at the start of the application, even if you do nothing with it. To load the library, you can load the SqlCeEngine object.
    SqlCeEngine eng = new SqlCeEngine();
    
       

    Top of Page Top of Page

    10. 其他信息


     

    10.1. Pocket TaskVision 程序

    This document provides an overview of the development tasks that were unique to the Pocket TaskVision sample application. Pocket PC devices have much lower storage capacities, memory and lower-end processors than desktop systems—storage and performance considerations are mentioned throughout the document.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/wnf_pkttaskvision.asp

    10.2. 建立基于微软.net精简框架的进程管理器

    In this article, learn how to marshal structures as byte arrays.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/ProcessManager.asp

    10.3. 使用微软.net精简框架开发移动游戏

    Learn how to create .NET Compact Framework-based games. Learn the key requirements for writing games targeting small devices and see that the .NET Compact Framework can handle them with ease. Include advanced performance-tuning techniques that you can use to push the limits of your game.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfgaming.asp

    10.4. 制作一个微软.net精简框架的DateTimePicker控件

    Learn how to use a managed DateTimePicker class in your Pocket PC projects. The .net精简框架 provides managed classes for most controls but the DateTimePicker class is not supported. Wrapper classes that P/Invoke the native control can be found on the Web, but this sample provides a purely managed DateTimePicker class that you can use in your Pocket PC projects. The class and sample application are provided in C# and Visual Basic .NET.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdatetimepicker.asp

    10.5. 写一个捕捉Pocket PC签名的程序.

    This article discusses the Pocket PC Signature sample application. The sample includes a client that runs on the Pocket PC that sends signature data over TCP sockets to a server that is running on the desktop. Data is encrypted and decrypted using the cryptography services.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCSignatureApp.asp

    10.6. 有没有非微软的网站提供在.net精简框架上开发应用的信息?

    See the "Related Sites" section of the MSDN Mobile and Embedded Developer Center:
    http://msdn.microsoft.com/mobility/Community/related/default.aspx


    Top of Page Top of Page

    11. 连通性


     

    11.1. 为什么不同通过ActiveSync把程序部署到Windows CE的设备上?

    Symptom: When a Windows CE device is connected through ActiveSync, deployment and debugging (F5 and Ctrl-F5) fail with the typical error message "There were deployment errors. Continue?"

    Cause: Due to the fact that ActiveSync 3.5 and 3.6 do not provide accurate information about the device instruction set, ConMan (Visual Studio .NET 2003 component for device connectivity) cannot use the information returned by ActiveSync to map a Windows CE device to the right .NET Compact Framework target (MIPSII, ARMV4 etc).

    Workaround: Install and run the separately provided Windows CE Configuration Add-In. For ARMV4 devices, an alternative is to select Pocket PC Device at the beginning of the deployment.

    11.2. 为什么不能通过ActiveSync调试 CEPC 或其他 x86 的Windows CE设备?

    Symptom: After running the Windows CE Device Configuration Add-In, the user can deploy without debugging (Ctrl-F5) to an ActiveSync connected CEPC (or any x86 based Windows CE device) but cannot debug (F5). Non-x86 based Windows CE devices do not have this problem.

    Cause: Debugging Windows CE Emulators (also x86 based) uses a TCP port that conflicts with the one used by ActiveSync for debugging x86 based devices. To support Emulator debugging, it is necessary to disable debugging for CEPC and other x86 devices by default.

    Workaround: The following workaround will allow debugging of x86 devices but disable debugging with the Windows CE Emulator. The workaround requires the files WinCEx86Device.reg, and ProxyPorts.reg which can be found in the SDK utilities directory: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\WinCE Proxy Ports Reg".

    If you do not have these files they can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    • Import WinCEx86Device.reg to the registry. Now you will be able to debug x86 devices, but debugging with the Windows CE Emulator will fail.
    • To restore Emulator debugging, remove the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\ProxyPorts" and then import ProxyPorts.reg.

    11.3. 为什么当设备上的Toolhelp.dll文件丢失后,调试就会失败?

    Symptom: After F5, all the files including the application executables and .net精简框架 cab files are copied to the device, and the IDE reports success on launching the application, but nothing is launched on the device. If you check the \windows folder of the device, toolhelp.dll does not exist.

    Cause: Some device images may not include toolhelp.dll which is required by SDE debugging.

    Workaround: Copy toolhelp.dll from Windows CE SDK to the \windows folder of the device. This file can be found in the corresponding target directory for each device.

    For example, for an ARM device: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\ToolHelp\WinCE4\armv4".

    If you do not have this file it can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    11.4. 为什么当网络协议数超过50个的时候,就不能向设备发布程序?

    Symptom: The "deployment error" message box occurs on Ctrl-F5 or F5. Running EnumProtocols.exe lists more than 50 protocols. (EnumProtocols.exe can be found in the WinCE utilites directory: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\EnumProtocols"). If you do not have this file it can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    Cause: It is a known issue that the .NET Framework method System.Net.Dns.GetHostName throws an exception when there are more than 50 network protocols installed on the current machine. The method is called by ConMan and the exception causes failure of the ConMan transport initialization.

    Workaround: Uninstall the network protocols that are not actually needed. One way to do this is to go to Device Manager (Right-click on "My Computer", select Properties->Hardware and press the "Device Manager" button) and remove unused entries under "Network adapters". Another way is to uninstall applications that have installed protocols. Those applications can be found from the output of EnumProtocles.exe.

    11.5. 为什么卸载ActiveSync后,不能通过ActiveSync向设备发布?

    Symptom: The "deployment error" message box occurs on Ctrl-F5 or F5 after ActiveSync has been uninstalled. Uninstalling ActiveSync typically happens when the user upgrades ActiveSync, e.g. from version 3.5 to 3.6.

    Cause: ConMan relies on some registry values under "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\ProxyPorts" for deployment and debugging through ActiveSync. These registry values are removed when ActiveSync is uninstalled.

    Workaround: Reinstall or repair Visual Studio .NET 2003.
    A simpler fix is to import ProxyPorts.reg which can be found in the WinCE utilities folder: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\WinCE Proxy Ports Reg" . If you do not have this file it can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    The device may need to be un-cradled/re-cradled or soft rebooted to make the fix take effect.
    It is recommended that users never uninstall ActiveSync. To upgrade ActiveSync, you should directly install the new version which will correctly override the old one.

    11.6. 为什么本地化的机器名或用户名或导致向设备发布程序的失败?

    Symptom: When the machine name or the logon user name contains any character that is not on the current code page or below ASCII value 0x20, deployment to devices fails while deployment to the Emulator works fine.

    Cause: ConMan security authentication internally uses the machine name and user name in the ASCII form which is not able to handle characters in the categories described above.

    Workaround: Do not use characters described above in the machine name or the user name. If the user is not clear what characters belong to those categories, it is always safe to use just English alphabetic letters and numbers.

    11.7. 为什么当前用户不属于Administrators组的时候,不能向设备发布程序?

    Symptom: If the current logon user is not in the Administrators group, deployment to devices always fails even though the user is in the Visual Studio Developers group and the Debugger Users group. On the other hand deployment/debugging to the Emulator works fine.

    Cause: During device deployment, the ConMan code internally opens a file in a mode that requires administrator privileges.

    Workaround: Add the current user to the Administrators group or limit the deployment target to the Emulator only.

    11.8. 为什么向Pocket PC或模拟器发布的时候出现 sharing violation 的错误?

    Symptom: When deploying an application to a Pocket PC 2002/2003 device or Emulator, the deployment fails with an output message similar to "Could not write to output file 'SmartDeviceApplication1.exe' - Sharing violation". This usually happens after the same application has previously deployed to the same device or Emulator.

    Cause: By default the X button on an application for Pocket PC 2002 or 2003 (not 2000) does not close the process. It only "minimizes" the application window. When the user tries to deploy the application again, the "minimized" instance will cause the sharing violation and fail the deployment.
    Another possible cause is that the user has forcibly terminated a debug session in the middle.

    Workaround: Make sure the application is really closed on the device or Emulator when deploying it again. To see running processes, go to Start->Settings->Memory->Running Programs on the Pocket PC. In case it is intended to have a button to really close an application, create such a button explicitly or set Windows Form's property Minimize Box to False so that the X button will become an OK button for closing the application. If the cause was the manual termination of a debug session, the device or the Emulator may need to be soft rebooted.

    11.9. 为什么在.NET Server的计算机上第一次使用模拟器的时候,得到一个安全警告消息?

    Symptom: When the Emulator is used for the first time after the installation of Visual Studio .NET 2003 on a .NET Server machine, a message box pops up titled "Security Alert – Driver Installation". The text of the message starts with "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". Near the end, it says "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?"

    Cause: Visual Studio .NET 2003 installs a Virtual PC Application Services Emulator driver which does not pass the validation of .NET Server's Driver Validation system.

    Workaround: When the alert message comes up, click the Yes button. Otherwise the Emulator will not work.

    11.10. 为什么在模拟器刚开始运行的时候出现关于找不到文件的错误信息?

    Symptom: When the Emulator is being started, a message box appears titled "Emulator for Windows CE" with the text "One or more files from the Emulator for Windows CE installation is missing. Please reinstall Emulator for Windows CE and try again." The connection or deployment to the Emulator will fail after the message box.

    Cause: A typical cause is that the Emulator driver is not installed or is corrupted.

    Workaround: Go to "Device Manager" (Right-click on "My Computer", select Properties->Hardware and press the "Device Manager" button) and check whether "Virtual PC Application Services" is installed under the System Devices group. If the driver is not installed, install it by running "<VSROOT>\CompactFrameworkSDK\ConnectionManager\Bin\DriverInstall\Smart Devices Emulator.msi".

    Note: Verify that the "Virtual PC Application Services" appears after running the msi file. If not then reboot the PC and attempt the installation again.

    11.11. 为什么第一次用模拟器发布时,会出现偶尔的错误?

    Symptom: The startup of the Emulator is slow and the deployment eventually fails with a connection error message. The startup mainly includes starting the Emulator image and downloading the .net精简框架 files. The failure happens more often on low-end machines when the Emulator is used for the first time or after "turn off" instead of "saving state" was used on the previous Emulator shutdown.

    Cause: Due to some performance issues in the Emulator, its startup may take too long to finish within the ConMan timeout period.

    Workaround: If possible, always choose "saving state" instead of "turn off" when closing the Emulator so that the startup will be much faster when the Emulator is started next time. Or before the deployment, pre-start the Emulator by clicking on the "Connect to Device" button which is located next to the Emulator name on the menu bar. Note that the first deployment will still fail after the pre-start. (See details in the issue about this.) In addition, hovering the mouse over the Emulator image may speed up the Emulator startup.

    11.12. 为什么第一次用Connect按钮连接模拟器并发布程序的时候失败了?

    Symptom: When the Emulator is started with the "Connect to Device" button, the first deployment attempt always fails.

    Workaround: There is no workaround at this point for the failure of the first deployment after the Emulator is started with the button, but the subsequent deployment attempts should succeed.

    11.13. 为什么当计算机没有网络连接的时候,用模拟器调试程序会出现错误?

    Symptom: When a machine has no active network connection, debugging with the Emulator (F5) does not work, while deployment without debugging (Ctrl-F5) works fine.

    Cause: Emulator debugging relies on TCP transport.

    Workaround: Install the Microsoft Loopback Adapter on the machine.

    To install the the Microsoft Loopback Adapter in Microsoft Windows XP

    1. Open Control Panel, choose Add Hardware, and then choose Next.
    2. Choose Yes, I have already connected the hardware, and then choose Next.
    3. From the Installed hardware list, select Add a new hardware device, and then choose Next.
    4. Choose Install the hardware that I manually select from a list (Advanced), and then choose Next.
    5. From the Common hardware types list, select Network adapters, and then choose Next.
    6. From the Manufacturer list, select Microsoft.
    7. From the Network Adapter list, select Microsoft Loopback Adapter, and then choose Next.
    8. Choose Next, and then choose Finish.

    To install the Microsoft Loopback Adapter in Microsoft Windows 2000

    1. Open Control Panel, choose Add/Remove Hardware, and then choose Next.
    2. Choose Add/Troubleshoot a device, and then choose Next.
    3. From the Devices list, select Add a new device, and then choose Next.
    4. Choose No, I want to select the hardware from a list, and then choose Next.
    5. From the Hardware types list, select Network adapters, and then choose Next.
    6. From the Manufacturers list, select Microsoft.
    7. From the Network Adapter list, select Microsoft Loopback Adapter, and then choose Next.
    8. Choose Next, and then choose Finish.

    11.14. 为什么当模拟器使用了一个COM端口的时候不启动不了(黑屏)?

    Symptom: When the Emulator image is starting up, it stays as a black screen forever. This happens when the Emulator is configured to use at least one COM port.

    Cause: By default, the Emulator is not assigned a COM port but the user may change the configuration to assign a COM port to the Emulator. When a COM port assigned to the Emulator is used by ActiveSync or any other running application, the Emulator image loading will fail.

    Workaround: Remove all of the COM ports assigned to the Emulator or change them to those not used by ActiveSync or any other running application. To remove or change the COM port configurations in Visual Studio .NET 2003, go to Tools/Options/Devices, choose an Emulator in the Devices window and click the Configure button.

    11.15. 为什么Visual Studio .NET 2003的模拟器不能和eMbedded Visual Tools的模拟器同时使用?

    Symptom: When the eMbedded Visual Tools (Platform Builder) Emulator is running, Visual Studio .NET 2003 Emulator deployment fails, and vice versa. Sometimes even after the Visual Studio .NET 2003 Emulator is closed, the eMbedded Visual Tools Emulator still does not work.

    Cause: The Visual Studio .NET 2003 Emulator and the eMbedded Visual Tools Emulator internally use two different instances of Emulator.exe which are not compatible with each other. Because they share the same executable name and the exe is a single instance application, while Emulator.exe for eMbedded Visual Tools is running, the one for Visual Studio .NET 2003 cannot be started, and vice versa. Another issue is that when the Visual Studio .NET 2003 Emulator user interface is closed, emulator.exe does not close until the hosting Visual Studio IDE instance is closed. In that case, the eMbedded Visual Tools Emulator cannot be started even though there is no Emulator running visually.

    Workaround: Do not use the two Emulators at the same time. If an Emulator cannot be started, check the Task Manager and close any running emulator.exe processes.

    11.16. 为什么没有ActiveSync连接的时候不能通过TCP连接向设备发布程序?

    Symptom: When a device does not have an ActiveSync connection with the Visual Studio machine but has a valid TCP connection, deployment does not work.

    Cause: ConMan relies on an ActiveSync connection to perform some initial settings between the Visual Studio machine and the device. If no ActiveSync connection is available, the setting will have to be performed manually.

    Workaround: Use the separately provided Keyman tool to perform the initial device settings with the following steps:

    1. Choose the correct flavor of Keyman.exe (e.g. ARMV4 or SH4, etc) and place it on the device. Launch Keyman and select "FILE->CONNECT". Keyman is now waiting for the VS machine to connect to it via TCP/IP. After the VS machine has connected, and then disconnected, Keyman on the device will automatically exit.
    2. On the VS machine, copy CryptoAPIWrapper.dll from <VSROOT>\ CompactFrameworkSDK\ConnectionManager\bin to the directory of KeymanDesktop.exe. Launch KeymanDesktop.exe.
    3. Click "Save" to save your settings in the current directory where KeymanDesktop.exe is running. The saved defaults will be loaded next time the exe is launched.
    4. Enter the IP Address of the device
    5. Use the recommended value for the Device Port.
    6. Enter the path of the "Target" directory where the ConmanClient bits such as ConManClient.exe reside. The typical value is \ CompactFrameworkSDK\ConnectionManager\Target.
    7. Use the Connect button to connect.
    8. Click on "prep device" after you have connected. On success, you will see a dialog telling you everything went OK.
    9. Use the Disconnect button to disconnect. When you disconnect, the device side bits will automatically exit.
    10. Launch ConManClient.exe on the device. First you must select the flavor of the target device. Also, you must select the location of your "Target" directory in Visual Studio.
    11.17. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?

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

    11.18. How can I copy files to the device currently connected to desktop ActiveSync?

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

    11.19. Why does the Visual Studio debugger fail to connect to an ARMV4I device?

    Cause
    Bug in the connection tool after selecting ARMV4I CPU type

    Resolution
    Configure tool for ARMV4T CPU type:
    1. In Visual Studio, on the Tools menu, click "Select Windows CE Device CPU". Note: this menu item is installed by the Windows CE Utilities for Visual Studio .NET 2003 Add-on Pack
    2. Change the device architecture to ARMV4T
    3. Click Configure, then click Close. Restart Visual Studio if prompted

    Top of Page Top of Page

    12. Smartphone


     

    12.1. Where can I get the latest Smartphone SDK?

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

    12.2. What are the rules for smartphone menus?

    Smartphone menus have several rules, such as:

    • the first menu item (corresponding to the left soft button) cannot have any sub items
    • the second menu item (corresponding to the right soft button) can have sub items
    • any other top level menu items are not used
    If the first menu item has more than 1 item, you will get a NotSupportedException.

    For a complete list of requirements, refer to the Smartphone help documentation:
    ms-help://MS.VSCC.2003/MS.Smartphone2003Help.1033/dv_smartphone/html/spconUsingMenus.htm

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

    12.3. Why are there disabled controls in the toolbox when creating a Smartphone project?

    The smartphone platform only supports a small set of controls. The controls that are not supported are disabled.

    For more information, refer to the following Smartphone help documentation:
    ms-help://MS.VSCC.2003/MS.Smartphone2003Help.1033/dv_smartphone/html/spconWindowsFormsSupport.htm

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

    12.4. Does Smartphone support RAM installs of the .NET Compact Framework?

    No. The .NET Compact Framework is serviced through operating system updates at the carrier's / OEM's discretion. Therefore, .NET Compact Framework will generally drop as part of larger Windows Mobile for Smartphone operating system updates.

    12.5. How do I set the title of a fullscreen multiline edit control window?

    This is not supported by the current version of the .NET Compact Framework.

    12.6. How can I generate Smartphone CABWizSP XML docs from existing Pocket PC CAB files?

    Download Convert PPC DAT to SP XML from Windows Mobile Developer Power Toys:
    http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

    12.7. How can I send characters and strings to the Smartphone 2003 Emulator via ActiveSync?

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

    12.8. How do I programmatically set the Smartphone input mode?

    The input mode can be set using GetFocus and SendMessage APIs according to the code below:
    '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
    
    <DllImport("coredll.dll")> _
    Public Shared Function GetFocus() As IntPtr
    End Function
    
    <DllImport("coredll.dll")> _
    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;
    }
    											


    Top of Page Top of Page
FastCounter by bCentral

最常见问题(FAQ)


微软.net精简框架最常见问题。

此FAQ的内容,一部分来自 net精简框架新闻组 (microsoft.public.dotnet.framework.compactframework)张贴和回答的问题。.net精简框架开发小组感谢每一位参与新闻组的人事,感谢他们对FAQ编写的积极参与和对FAQ的投稿。

要申请添加FAQ项目,请发邮件到 netcffaq@microsoft.com.

1. 开发

1.1. 什么是微软 .net精简框架?
1.2. 我需要什么工具才能开发.net精简框架的应用?
1.3. 哪里可以下载最新的工具和相关软件?
1.4. .net精简框架支持些什么设备?
1.5. .net精简框架以后将支持什么设备?
1.6. 调试程序时为什么会出现“与模拟器建立连接失败”的错误(刚开始执行程序的时候)?
1.7. .net框架和.net精简框架之间有什么区别?
1.8. .net精简框架的补丁有什么改进?
1.9. Poclet PC上的.net精简框架开发和Windows CE .NET上的.net精简框架开发有什么不同?
1.10. 哪里有更多的关于建立.net精简框架上的应用程序的信息?
1.11. .net精简框架的文档在哪里?
1.12. 怎样设置才不会在每次调试的时候把所涉及的文件都拷贝到设备上?
1.13. 怎样设置模拟器的属性?
1.14. 怎么调试.net精简框架的应用程序?
1.15. 怎样开始使用Visual Basic .NET开发.net精简框架的程序?
1.16. 怎样才能把.net精简框架安装到装配集中(GAC)?
1.17. 当从Visual Studio .NET 2003中发布程序到设备上的时候,怎样处理"Sharing Violation"?
1.18. 什么是common language runtime (CLR)?
1.19. 什么是Global Assembly Cache (GAC)?
1.20. 在.net精简框架下内存管理是怎样的?
1.21. 当我的网络协议数超过50个的时候,为什么不能向发布程序?
1.22. 为什么会有跨平台代码?
1.23. 这些ARM指令代表什么?
1.24. 怎样写注册表?
1.25. How can I prevent .CAB files from being deleted after installation?
1.26. How can I determine the version of the .NET Compact Framework that is installed on a device?
1.27. How do I copy files to the emulator?
1.28. Why does installation of the PocketPC 2002 SDK fail?
1.29. How do I debug a Web service consumed by a Smart Device application?
1.30. What is the footprint of the .NET Compact Framework?
1.31. How do I include imgdecmp.dll in an emulator image?
1.32. How do I programmatically replace Assemblies in the Global Assembly Cache (GAC)?
1.33. How can I display Pocket PC applications on my desktop or laptop without needing any device side configuration?
1.34. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?
1.35. How can I copy files to the device currently connected to desktop ActiveSync?
1.36. How can I stress test user input?
1.37. Where can I get a UI version of the Platform Builder Target Control Window?
1.38. Where can I get a Command shell for Pocket PC 2003 devices?
1.39. How can I get detailed information about currently running processes?
1.40. How can I remotely start an application on a Pocket PC from my desktop?
1.41. Why can't I load different assemblies with the same name?
1.42. How can I force Visual Studio .NET 2003 to connect to newer versions of the Pocket PC 2003 emulator?
1.43. Why don't my custom controls show up properly in the toolbox?
2. 图形
2.1. 怎样建立一个图形对象?
2.2. 怎样优化GDI+?
2.3. 怎样在窗体上画一个图案?
2.4. 怎样画一个带有透明色的图案?
2.5. 为什么从TextBox上调用CreateGraphics会失败?
2.6. 怎样获得屏幕上文字的大小?
2.7. Can I set the width of a pen?
2.8. How do I zoom an image?
2.9. Why can't I load an image?
3. 发布
3.1. 怎样建立一个PocketPC的设置程序?
3.2. 哪个发布包可以包括在我的安装程序中?
3.3. 怎样可以建立一个不需要.net框架的安装程序?
3.4. 怎样建立不受PocketPC系统约束的CAB安装文件?
3.5. 为什么不同的处理器会有不同的CAB安装文件?
3.6. How do I create a desktop installer that detects the presence of the .NET Compact Framework on the target device and installs it if necessary?
3.7. How do I deploy a .NET Compact Framework Service Pack to the emulator?
3.8. How do I include SQL Server CE with my application installation?
3.9. How do I use GAPI to create a graphics engine?
4. 图形用户界面(GUI): 窗体
4.1. 怎样建立一个全屏的窗体?
4.2. 什么时候用窗体的构造器?什么时候用窗体的Load事件?
4.3. 怎样把最小化按钮换成关闭按钮?
4.4. 怎样在.net精简框架上建立多窗体系统结构?
4.5. 怎样提高.net精简框架应用程序的载入速度?
4.6. 运行时怎样修改窗体的风格?
4.7. 怎样滚动窗体的内容?
4.8. 怎样制作一个浮动的窗体?好象所有的窗体总是全屏状态的。
4.9. 怎样强迫一个窗体变成最小化?
4.10. 我有一个包含很多控件的智能设备窗体,为什么运行的时候出现"NotSupportedException"错误?
4.11. 哪个是正确关闭窗体的方法:Appplication.Exit 还是 Form.Close ?
4.12. Why does showing a MessageBox on Windows Mobile 2003 for Smartphone with the Abort, Retry, and Fail set of buttons or the Yes, No, Cancel set of buttons, or the third button as the default button result in a NotSupportedException?
4.13 How do I get an icon in the Pocket PC Start Menu Most Recently Used (MRU) List?
4.14 How do I center a Form on the screen?
4.15 Why can't I show a Form that has been closed?
4.16 How can I enable multiple instances of an application?
5. 图形用户界面 (GUI): 通用
5.1. 怎样建立一个带有图形或支持多行的按钮?
5.2. TextBox.AcceptsReturn在.net精简框架下是怎样工作的?
5.3. 当数据载入ComboBox的时候,为什么SelectedIndexChanged事件没有被触发?
5.4. Show和ShowDialog有什么不同?
5.5. 为什么我不能建立右键菜单分离器?(separator)
5.6. 运行时把ImageList赋给ToolBar时,为什么图象不出现?
5.7. 怎样把光标设置成等待状态?
5.8. 如何在菜单项中显示符号:&?
5.9. 如何制作基于.net精简框架的动画控件?
5.10. 如何在.net精简框架上制作自定义控件?
5.11. 如何制作基于.net精简框架的带图片的按钮?
5.12. 如何使用.net精简框架下的MessageWindow类库?
5.13. 如何向DataGrid中添加行和列?
5.14. 如何实现DataGrid的编辑?
5.15. 怎样设置DataGrid的DataSource?
5.16. 怎样对DataGrid的列排序?
5.17. 怎样对ListView中的内容排序?
5.18. 如何使用 输入板(SIP)控件?
5.19. 如何自定义事件?
5.20. 如何做一个 owner-drawn List Box?
5.21. 如何做一个多选框判断真假?
5.22. 设置InputPanel.Enabled = true的时候为什么出现异常?
5.23. 为什么自定义控件不会自动继承父类的字体?
5.24. 为什么当输入字符时,NumericUpDown 和 DomainUpDown 控件不会引发 ValueChanged 和 SelectedItemChanged 事件?
5.25. 为什么NumericUpDown控件增长的值不是设置好的值?
5.26. 为什么StatusBar不能放在窗体的任意位置?一定要在底部?
5.27. 为什么我的控件自动继承了父控件的背景色?
5.28. 为什么NumericUpDown控件能接受decimal类型的值,但不会显示大于2^16的值?
5.29. 为什么不能在DomainUpDown 中输入文字,而要选择?
5.30. 为什么OpenFileDialog被限制在"My Documents" 文件夹中?
5.31. How can I activate the SIP (InputPanel) without a menu?
5.32. How do I add a subnode to every node in a TreeView?
5.33. How do I determine the number of rows or columns in a DataGrid?
5.34. How do I create a owner drawn Listbox?
5.35. How can I implement Control.GetNextControl under the .NET Compact Framework?
5.36. How do I get notified when the user clicks on a treeview node?
5.37. How do I set the title of a fullscreen multiline edit control window?
5.38. Why don' I see the validItem selected when I set ComboBox.SelectedValue to validItemInCollection?
5.39. How do I detect the location where a 'tap & hold' occurred to bring up a context menu on my custom control?
5.40. Why doesn't the scrollbar value ever get set to the maximum value?
5.41. How do I tab out of a custom control to the previous control?
5.42. How do I add Toolbar buttons with Transparency? 
6. 与本地代码(Native Code)协同工作
6.1. 如何调用本地写的DLL中的函数?
6.2. 如何使用dumpbin.exe帮助描述 P/Invokes?
6.3. 如何为微软.net精简框架写非托管代码?
6.4. 如何调用 P/Invoke GetTickCount?
6.5. 如何获得系统还有多少可用内存?
6.6. 如何是窗口一直保持最小化?
6.7. 在微软.net精简框架上调用系统函数时,如何装配数据类型?
6.8. 如何得到一个窗体或控件的句柄 (HWND) ?
6.9. 如何使用性能计数器功能?
6.10. 调用本地代码时,数据类型有什么限制?What are the limitations on marshalling types via P/Invoke?
6.11. 调用GetLastError时,总是获得不定的代码?
6.12. 调用本地代码时,有没有参数数量的限制?
6.13. 调用本地代码时,为什么得到"NotSupportedException"异常?
6.14. 如何把 byte[] 转换成 IntPtr?
6.15. Why do I get a MissingMethodException when I call a function from a native DLL?
6.16. How do I set the system time?
6.17. How do I programmatically soft reset the device?
6.18. How can I put an icon on the title bar regardless of the which form is active?
6.19. How do I disable and capture hardware buttons?
6.20. How do I hide the start icon?
6.21. How do I enumerate, create, and terminate processes?
6.22. Where can I find a centralized library of P/Invoke samples?
6.23. How do I play and record .WAV audio files with the Waveform Audio Inteface? 
7. 通用
7.1. 如何确定应用程序的主目录?
7.2. 如何计算精确的时间间隔?
7.3. 如何把嵌入式资源当作一个流(Stream)?
7.4. 为什么得到一个"An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll"的错误?
7.5. 如何使用性能监视器?
7.6. 如何取消一个程序的关闭?
7.7. 如何在我的程序中调用另一个应用程序?
7.8. .net精简框架的应用程序会建立什么线程?
7.9. 如何把byte数组转换成结构体?
7.10. 我可以建立一个委托(delegate)交给Invoke吗?
7.11. 如何在微软.net精简框架上使用电话API?
7.12. 如何在Pocket Pc上生成GUID?
7.13. 如何让我的.net精简框架程序和Pocket Outlook的数据结合?
7.14. 我可以判断.net精简框架中一个文件的版本吗?
7.15. 微软.net精简框架的后台处理有什么相关技术?
7.16. 在微软.net精简框架上使用多线程有什么技巧?
7.17. 如何在 智能设备应用 中使用混淆器?
7.18. 如何使用密码服务对数据进行加密或解密?
7.19. 如何在微软.net精简框架上获得Windows CE设备的唯一号码?
7.20. 如何在微软.net精简框架的应用程序上发送短消息?
7.21. 不使用Control.Name,可以判断事件的发送者吗?
7.22. 如何在线程中调用方法的参数?
7.23. 如何建立提醒程序和定时程序?
7.24. 如何播放声音?
7.25. 如何使用命令行参数?
7.26. 当使用已经释放的对象的方法或属性的时候,为什么得到一个异常?
7.27. 如何获得"Enter", "TAB", 和 "Arrow"按键的事件?
7.28. 如何删除一个只读文件?
7.29. How do I determine if a member exists at runtime?
7.30. How do I determine the device name programatically?
7.31. How do I build a C# Smart Device project from the command line?
7.32. How do I abort an executing thread?
7.33. Why can't I play a movie on the Pocket PC emulator?
7.34. How do I suppress Form titles from showing in the active applications list?
7.35. How do I access a Control from its instance name?
7.36. How do I detect the hardware directional pad buttons?
7.37. How do I get a double click event when only the Click event is supported?
7.38. How do I get onenter/onleave style notifications?
7.39. How do I use threading in a modal dialog that doesn't hang my app?
7.40. How do I round floating point numbers efficiently?
7.41. Why does Control.Invoke take so long when a modal dialog is displayed?
7.42. Is there a way to retrieve the culture information of an Assembly?
8. 通讯和Web服务
8.1. 如何通过TCP Socket向桌面机发送数据?
8.2. 为什么不能访问本机上的Web服务?
8.3. 如何在微软.net精简框架上调用Web服务
8.4. 如何通过代理服务器提交HTTP GET申请?
8.5. 如何使用Web服务?
8.6. 如何使用MapPoint3.0得到地图?
8.7. 如何使用MapPoint3.0获得地图和方向?
8.8. Is NTLM authentication supported by the .NET Compact Framework?
8.9. When using blocking Sockets, why does Send throw an InvalidOperationException when blocking is set to false?
8.10. How do I create an http-server?
8.11. Why do I get an exception when calling SetSocketOption with ReuseAddress set?
8.12. Why do I get a socket error using SSL to communicate with a server via the WebRequest namespace?
9. SQL CE 和 数据
9.1. 使用.net精简框架、SQL Server CE 和 复制 开发应用程序时,要注意些什么?
9.2. 如何在微软.net精简框架上使用合并复制(Merge Replication)?
9.3. 如何将ADO.NET数据和XML绑定?
9.4. 如何建立SQL Server CE的数据库?
9.5. 如何向SQL Server CE提交一个带参数的查询?
9.6. Why does using RDA and the push method fail with error 27750?
10. 其他信息
10.1. Pocket TaskVision 程序
10.2. 建立基于微软.net精简框架的进程管理器
10.3. 使用微软.net精简框架开发移动游戏
10.4. 制作一个微软.net精简框架的DateTimePicker控件
10.5. 写一个捕捉Pocket PC签名的程序
10.6. 有没有非微软的网站提供在.net精简框架上开发应用的信息?
11. 连通性
11.1. 为什么不同通过ActiveSync把程序部署到Windows CE的设备上?
11.2. 为什么不能通过ActiveSync调试 CEPC 或其他 x86 的Windows CE设备?
11.3. 为什么当设备上的Toolhelp.dll文件丢失后,调试就会失败?
11.4. 为什么当网络协议数超过50个的时候,就不能向设备发布程序?
11.5. 为什么卸载ActiveSync后,不能通过ActiveSync向设备发布?
11.6. 为什么本地化的机器名或用户名或导致向设备发布程序的失败?
11.7. 为什么当前用户不属于Administrators组的时候,不能向设备发布程序?
11.8. 为什么向Pocket PC或模拟器发布的时候出现 sharing violation 的错误?
11.9. 为什么在.NET Server的计算机上第一次使用模拟器的时候,得到一个安全警告消息?
11.10. 为什么在模拟器刚开始运行的时候出现关于找不到文件的错误信息?
11.11. 为什么第一次用模拟器发布时,会出现偶尔的错误?
11.12. 为什么第一次用Connect按钮连接模拟器并发布程序的时候失败了?
11.13. 为什么当计算机没有网络连接的时候,用模拟器调试程序会出现错误?
11.14. 为什么当模拟器使用了一个COM端口的时候不启动不了(黑屏)?
11.15. 为什么Visual Studio .NET 2003的模拟器不能和eMbedded Visual Tools的模拟器同时使用?
11.16. 为什么没有ActiveSync连接的时候不能通过TCP连接向设备发布程序?
11.17. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?
11.18. How can I copy files to the device currently connected to desktop ActiveSync?
11.19. Why does the Visual Studio debugger fail to connect to an ARMV4I device?
12. Smartphone
12.1. Where can I get the latest Smartphone SDK?
12.2. What are the rules for Smartphone menus?
12.3. Why are there disabled controls in the toolbox when creating a Smartphone project?
12.4. Does Smartphone support RAM installs of the .NET Compact Framework?
12.5. How do I set the title of a fullscreen multiline edit control window?
12.6. How can I generate Smartphone CABWizSP XML docs from existing Pocket PC CAB files?
12.7. How can I send characters and strings to the Smartphone 2003 Emulator via ActiveSync?
12.8. How do I programmatically set the Smartphone input mode?
Top of Page Top of Page


1. 开发

1.1. 什么是微软 .net精简框架?

微软.net精简框架是.net框架为智能设备开发的平台,是实现微软的目标:“为用户提供精彩的体验--任何时间、任何地点、任何设备” 的关键部分。.net精简框架把托管代码的世界从web服务带到了智能设备上, 允许在个人数字助理(PDA)、移动电话、机顶盒设备上的 安全的、可下载的应用。

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

1.2. 我需要什么工具才能开发.net精简框架的应用?

Visual Studio .NET 2003 是在Pocket PC 2000、Pocket PC 2002和Windows CE.NET 4.1上开发.net精简框架所需要的, .net精简框架与Visual Studio .NET 2003一同发售.
http://msdn.microsoft.com/mobility/prodtechinfo/devtools/vstudio/default.aspx

其他Windows移动平台开发包可以在以下地方获得:

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精简框架和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精简框架和补丁集可以在这里获得:
http://msdn.microsoft.com/mobility/downloads/default.aspx

1.4. .net精简框架支持些什么设备?

.net精简框架可以在Pocket PC 2000, Pocket PC 2002, Windows Mobile 2003的Pocket PC 和 基于Windows CE.NET 4.1嵌入式系统的Pocket PC、智能手机 上运行。

1.5. .net精简框架以后将支持什么设备?

.net精简框架将被集成到微软系统中并成为一部分,包括未来的Pocket PC设备,Pocket PC电话版,智能手机,车载Windows CE系统,MSTV。 各种设备的发布时间待定。

.net精简框架将作为Windows CE .NET 4.1系统组件的一部分,因此允许OEM厂商使用PlatformBuilder把.net精简框架集成到新的Windows CE设备中。

1.6. 调试程序时为什么会出现“与模拟器建立连接失败”的错误(刚开始执行程序的时候)?

下面这个连接将告诉你如何设置调试和排错。
http://download.microsoft.com/download/c/d/b/cdbff573-73fb-4f9f-a464-c5adc890e1ae/Readme.htm

1.7. .net框架和.net精简框架之间有什么区别?

.NET框架 和 .net精简框架 的关系:
http://msdn.microsoft.com/library/en-us/dv_evtuv/html/etconComparisonsWithNETFramework.asp

在线查看.net精简框架类库关系工具:
http://msdn.microsoft.com/library/en-us/dv_spchk/html/NET_Compact_Framework.htm

1.8. .net精简框架的补丁有什么改进?

.net精简框架 SP1 修正了许多漏洞,查看修正项目列表:
http://www.microsoft.com/downloads/details.aspx?familyid=1f62a2a3-7282-4ba9-b26b-2267e972501d&displaylang=en

1.9. Poclet PC上的.net精简框架开发和Windows CE .NET上的.net精简框架开发有什么不同?

这篇文章将描述在Pocket PC和Windows CE.NET平台上开发基于.net 精简框架的应用程序的区别之处。
http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfPPCtoCE.asp

1.10. 哪里有更多的关于建立.net精简框架上的应用程序的信息?

以下资源能教会您怎样建立.net精简框架应用程序:

  • .net精简框架  快速入门
    http://samples.gotdotnet.com/quickstart/compactframework/
  • .net精简框架白皮书 MSDN移动和嵌入式开发中心:
    http://msdn.microsoft.com/mobility/understanding/articles/default.aspx

    1.11. .net精简框架的文档在哪里?

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

    1.12. 怎样设置才不会在每次调试的时候把所涉及的文件都拷贝到设备上?

    在Visual Studio .NET 2003, 右键点击文件并选择属性,把Build的属性设置为None.文件将不再被拷贝.如果文件修改过了,需要重新拷贝,把Build属性改为Content即可.

    1.13. 怎样设置模拟器的属性?

    在Visual Studio .NET 2003菜单中,选择 Tools->Options. 打开 Device Tools 文件夹,并选择 Devices. 您应该看到一个显示设备列表的对话框.选择您想修改的设备,按Configuration按钮.
    现在您应该看到一个包含多个TAB并可以修改设置的对话框,如设置内存和屏幕大小等.

    1.14. 怎么调试.net精简框架的应用程序?

    微软.net精简框架完全集成在Visual Studio .NET 2003中,在Visual Studio .NET 2003下调试.net精简框架的应用和在Visual Studio .NET 2003下调试其他应用一样。在一个单独的设备上调试程序和在模拟器中调试程序需要注意不同的地方。查看下面文章可以获得更多调试.net精简框架的经验。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/CompactFXDebug.asp

    1.15. 怎样开始使用Visual Basic .NET开发.net精简框架的程序?

    了解怎样使用Smart Device Extensions (SDE)编写只能设备的应用。这篇文章详细介绍了在.net精简框架上开发、调试、发布的完整过程,并描述了和在.net框架上开发的区别。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/sdeforvb.asp

    1.16. 怎样才能把.net精简框架安装到装配集中(GAC)?

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

    1.17. 当从Visual Studio .NET 2003中发布程序到设备上的时候,怎样处理"Sharing Violation"?

    This article illustrates the cause of a sharing violation that prevents the deployment of your application from Visual Studio .NET 2003, and gives instructions on how to work around it.
    http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOSharingviolation.asp

    1.18. 什么是common language runtime (CLR)?

    .net精简框架提供的运行环境叫做CLR,它使程序运行,并且是开发更加容易。以下文章将使您了解更多关于CLR:
    http://msdn.microsoft.com/library/en-us/cpguide/html/cpconcommonlanguageruntimeoverview.asp

    1.19. 什么是Global Assembly Cache (GAC)?

    每一台装了.net环境的机器都会有一个本机器范围内的缓冲,这就是GAC。GAC中存放的装配会被这台计算机上的一些应用程序共享 。这篇文章将告诉你更多关于GAC的信息:
    http://msdn.microsoft.com/library/en-us/cpguide/html/cpconglobalassemblycache.asp

    1.20. 在.net精简框架下内存管理是怎样的?

    自动内存管理是CLR提供的一项服务。CLR的垃圾回收器会管理应用程序内存的分派和回收,以下文章将为您解释:
    http://msdn.microsoft.com/library/en-us/cpguide/html/cpconautomaticmemorymanagement.asp

    1.21. 当我的网络协议数超过50个的时候,为什么不能向发布程序?

    请查看本文章的  "11.4. 为什么当网络协议数超过50个的时候,就不能向设备发布程序?"  部分。

    1.22. 为什么会有跨平台代码?

    .net精简框架和它的执行引擎是.net框架和CLR的子集。缺省的强名称策略,针对.net精简框架编译的程序同样可以在完整的.NET框架上运行,但会有一些重要的异常信息:
    • .net精简框架装配使用和.net框架不用的强名称签名,所以CLR可以区分它们。
    • 在未来发布的.NET框架和CLR的绑定策略中将使用.NET框架装配代替兼容.NET精简框架参考。这样,在普通情况下,不需要重新连接就能重用组件。 例如:如果您的组件只引用了.net精简框架的 System 和 System.NET 类库,它则不需要重新连接就适合在.net精简框架和完整的.NET框架下运行。
    • 如果你引用了.net精简框架特有的功能,如PocketPC特有的用户界面,程序将不能在完整的.net框架上运行。
    • 如跨平台的中间组件的开发和发布,微软认为丰富的客户端应用应该利用智能设备特有的功能为用户带来更好的体验。这一味着好的图形用户界面基本上是客户端特有的。
    • 尽管微软花费很大精力为不同设备和功能划分了不同的命名空间和装配以避免装配冲突,但在1.0的版本里还是会有不能处理的兼容性问题。在这种情况下,在.net框架上不经意地使用了设备专有的功能将会导致程序在运行时的异常,而不是载入时的异常。

    1.23. 这些ARM指令代表什么?

    XScale支持ARM v5指令集,同时也向下兼容ARM v4指令集。这里有三种情况:
    • ARMv4 -> 只支持32位ARMv4指令
    • ARMv4T -> 'T' 表示 Thumb. Thumb 是ARM16位指令模式
    • ARMv4I -> 'I' 表示 Interworking. 允许32位和16位指令共存

    对于其他ARM处理器:
    • StrongARM (SA1110) -> 只支持ARMv4指令
    • ARM920T, etc -> 支持所有三种情况

    .net精简框架支持三种ARM代码
    • ARMv4 for PocketPC 2000 and Pocket PC 2002. 支持所有ARM设备,包括XScale。发布到设备的CAB文件名包含有"arm"字符。
    • ARMv4 for Windows CE.NET. 支持由PlatformBuilder使用ARMv4核心编译的Windows CE.NET设备。Pocket PC 2003支持这种代码。发布到设备的CAB文件名包含有"armv4"字符。
    • ARMv4T or ARMv4I for Windows CE.NET. 支持由PlatformBuilder使用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 Pocket PC Registry Editor (共享软件,很容易在网上找到)
    1.25. How can I prevent .CAB files from being deleted after installation?

    Automatic deletion of .CAB files can be prevented by setting the property of the .CAB file(s) to Read Only.

    1.26. How can I determine the version of the .NET Compact Framework that is installed on a device?

    Each version of the .NET Compact Framework is released with a different Win32 File Version number (this is a separate version number from the Assembly Version, which should be the same across all releases of the Version 1 .NET Compact Framework, including Service Packs).

    In order to see what version is installed, use File Explorer to navigate to the \Windows directory on the device, and click the file called CGACUTIL. You will get a message box showing you the Win32 File Version of the .NET Compact Framework installed on the device.

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

    To determine the version programmatically you can use System.Environment.Version.ToString().

    1.27. How do I copy files to the emulator?

    One approach would be to create a file share on your development PC, and then connect to that share via File Explorer in the emulator. You may then copy and paste the files from the share to the emulator's local file system. Another approach would be to add the file(s) to a smart device project and set their Build Action(s) property to "Content". See the Visual Studio .NET online documentation for more information on "File Properties":

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbconfileproperties.asp

    Step by step instructions for adding a "Content" file to a smart device project:
    1. Open or create a smart device project,
    2. On the View menu, click Solution Explorer,
    3. In Solution Explorer, right-click on your project, point to Add, and click Add Existing Item. Browse to and add the desired file to the project.
    4. Right-click on the file that you added, in solution explorer, and click Properties,
    5. Set the Build Action property to "Content", if it is not already set.
    1.28. Why does installation of the PocketPC 2002 SDK fail?

    Symptom: The Pocket PC 2002 SDK installer hangs while "registering components."

    Cause: An unregestered component causes the installation to hang while attempting to run the emulator.

    Workaround: From a console window prompt:
    cd \WINNT\system32
    regsvr32 atl.dll

    1.29. How do I debug a Web service consumed by a Smart Device application?

    You need to attach the debugger to the ASP.NET worker process.

    Refer to the following link for more information:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtskdebugginganaspdeployedwebapplication.asp

    1.30. What is the footprint of the .NET Compact Framework?

    .NET Compact Framework storage size:
    • 1.55MB (ROM) on Pocket PC 2000/2002
    • 1.35MB (ROM) on Windows Mobile for Pocket PC 2003 or Windows CE .NET Devices
    Running RAM requirements:
    • .5 MB+ (depends on application)
    Typical application sizes:
    • 5 - 100 KB
    1.31. How do I include imgdecmp.dll in an emulator image?

    You must ask the OEM to include it in the device's image. If you are the OEM and you are using Platform Builder 4.2, then including the OS Dependencies for the .NET item automatically causes imgdecmp.dll to be part of the emulator image - if that is not working then refer to cesysgen.bat. Another method is to set the environment variable "__SYSGEN_IMGDECMP=1" to explicitly force the DLL into the image.

    1.32. How do I programmatically replace Assemblies in the Global Assembly Cache (GAC)?

    One can install and remove Assemblies directly to and from the GAC by programmatically launching cgacutil.
    • Remove assemblies from the GAC using the -u option
    • Install assemblies to the GAC using the -i option
    It is typically safest to remove the Assembly before reinstalling it.

    1.33. How can I display Pocket PC applications on my desktop or laptop without needing any device side configuration?

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

    1.34. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?

    See the entry titled "11.17. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?" of this FAQ.

    1.35. How can I copy files to the device currently connected to desktop ActiveSync?

    See the entry titled "11.18. How can I copy files to the device currently connected to desktop ActiveSync?" of this FAQ.

    1.36. How can I stress test user input?

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

    1.37. Where can I get a UI version of the Platform Builder Target Control Window?

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

    1.38. Where can I get a Command shell for Pocket PC 2003 devices?

    Download PPC Command Shell from Windows Mobile Developer Power Toys:
    http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

    1.39. How can I get detailed information about currently running processes?

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

    1.40. How can I remotely start an application on a Pocket PC from my desktop?

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

    1.41. Why can't I load different assemblies with the same name?

    This is by design. You must either change the names of the DLLs, or if the DLLs are strong named, place them in the GAC and use Assembly.Load with a full strong name.

    1.42. How can I force Visual Studio .NET 2003 to connect to newer versions of the Pocket PC 2003 emulator?

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

    This allows ActiveSync to connect to your Emulator session from Visual Studio .NET 2003. Create an ActiveSync session to the 4.2 emulator, this will allow Visual Studio 2003 to consider it a real device (Choose PPC device as the deployment target).

    1.43. Why don't my custom controls show up properly in the toolbox?

    While adding designer support in Visual Studio .NET 2003 for Smart Device custom controls, you may run into the following issues:
    • Unable to associate an Icon to the Control for showing it in the toolbox at design time
    • The component, when added to the toolbox, becomes greyed out
    Causes
    • Using a design project separate from the control project. Visual Studio .NET automatically prepends the project default namespace to the bitmap name. The "default namespace" defaults to the project name. This may be a problem because the design project has a slightly different name than the runtime project.
    • Not setting the correct ToolBoxItemFilterAttribute values
    Resolutions

    Given the following example:
    Runtime VS.NET Project: MyProject
    Class Name: MyProject.MyClass
    Design VS.NET Project Name: MyProject.Design
    BitMap name in VS.NET Design Project: Foo.bmp
    Bitmap name in design assembly: MyProject.Design.MyClass.bmp
    -- This creates a problem because the bitmap needs the name: MyProject.MyClass.bmp

    In the above example, setting the design project's default namespace to "MyProject" rather then "MyProject.Design" should fix the problem.

    The easiest way to check the name of the bitmap within the assembly is to run ILDASM and open the Manifest. The embedded resources are listed at the end of the manifest.

    If you create a custom component derived from the Component class, your code must include the following statements so that your component appears in the Toolbox:
    ToolBoxItemFilterAttribute("NETCF",ToolBoxItemFilterType.Require)
    ToolBoxItemFilterAttribute("System.CF.Windows.Forms", ToolBoxITemFilterType.Custom)
    
     

    Top of Page Top of Page

    2. 图形


     

    2.1. 怎样建立一个图形对象?

    有很多种方法可以建立图形对象,看你怎么用:

    在OnPaint中,使用object参数提供的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
    
    在程序的其他部分,利用控件的一个方法,可以用来建立任意控件的图形对象:
    //C#
    using System.Drawing;
    
    Graphics g = this.CreateGraphics();
    
    'VB
    Imports System.Drawing
    
    Dim g As Graphics = Me.CreateGraphics()
    
    直接画到bitmap位图文件中:
    //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的绘图速度:
    • 只建立一个图形对象 (或只使用OnPaint中的 PaintEventArgs)。
    • 把所有绘图工作先画到不显示的位图上,再一次性把位图显示出来。
    • 只重画变化的部分图象。
    • 尽可能在相同的区域上画相同大小的图象。
    主要思路:最小化地重画图象。例如,当光标拖过图象时,不需要把整个图重新画一遍。只需要重画光标之前经过的地方。

    2.3. 怎样在窗体上画一个图案?

    这里有个例子,告诉你怎样把图片画到窗体的背景上:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/bkgndimage.aspx

    2.4. 怎样画一个带有透明色的图案?

    画一个带有透明色的图象,需要设置ImageAttributes对象的透明色。目前.net精简框架支持单种颜色的透明色。虽然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.FromArgb(255,0,255),Color.FromArgb(255,0,255));
    attr.SetColorKey(Color.Fuchsia, Color.Fuchsia);
    
    'VB
    attr.SetColorKey(Color.FromArgb(255,0,255),Color.FromArgb(255,0,255))
    attr.SetColorKey(Color.Fuchsia, Color.Fuchsia)
    
    图象会被重载的Graphics.DrawImage方法重画,并且使用ImageAttributes对象作为一个参数parameter:
    //C#
    g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height,GraphicsUnit.Pixel, attr);
    
    'VB
    g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height,GraphicsUnit.Pixel, attr)
    
    2.5. 为什么从TextBox上调用CreateGraphics会失败?

    只有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. Can I set the width of a pen?

    Setting the pen width is not available in the .NET Compact Framework. Some alternate solutions include:

    • Drawing filled rectangles with the Graphics.FillRectangle method
    • Drawing multiple lines next to each other
    • Writing a custom graphics routine with GAPI
    2.8. How do I zoom an image?

    While there is no inherent support for zooming or stretching a single image, these effects can be achieved quite easily by creating a new Bitmap object with an associated Graphics object and copying the desired portion of the original Bitmap into it. The following sample creates two bitmaps of the same size, where the second contains a zoomed center section of the first, provided the project has an embedded resource named MyImage.bmp. This same technique could be used to stretch images by modifying the source and destination rectangles such that they do not maintain their original aspect ratio.
    //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. Why can't I load an image?

    Ensure that imgdecmp.dll is in the device's Windows directory.

    For more information, see the topic "1.31. How do include imgdemp.dll in an emulator image?" of this FAQ.


     Top of Page Top of Page

    3. 发布


     

    3.1. 怎样建立一个PocketPC的设置程序?

    这篇文章告诉您如何建立一个单独的.msi文件,可以运行并把应用安装到不同的Pocket PC设备上。整个过程都是自动的,所以很容易把所有需要的组件都打包到.msi文件中。包含C#和Microsoft Visual Basic .NET代码。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdeployment.asp

    3.2. 哪个发布包可以包括在我的安装程序中?

    您可以为您的用户提供一个最终的发布包,以帮助他们升级设备。您不能拆开这个发布包把内容给您的用户。但是,您可以拆开开发人员的发布包把内容给您的用户。

    3.3. 怎样可以建立一个不需要.net框架的安装程序?

    这篇文章讨论了如何成功的安装一个Pocket PC的应用:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppc2k/html/ppc_allation.asp

    3.4. 怎样建立不受PocketPC系统约束的CAB安装文件?

    您可以建立一个.inf文件生成一个适合任何Pocket PC设备的应用程序安装文件。查看示例代码:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/cabfile.aspx

    3.5. 为什么不同的处理器会有不同的CAB安装文件?

    每一个CAB文件都包含一小段检测智能设备上的.net精简框架版本的代码。这个功能是处理器/平台特有的,不同的CAB文件根据处理器类型绑定不同的代码。

    3.6. How do I create a desktop installer that detects the presence of the .NET Compact Framework on the target device and installs it if necessary?


    The article titled "Creating an MSI Package that Detects and Updates the .NET Compact Framework" in the MSDN Library describes a technique that may be used:
    http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull=/library/en-us/dnnetcomp/html/netcfdepl.asp

    3.7. How do I deploy a .NET Compact Framework Service Pack to the emulator?

    Download and install to your desktop development PC a "Developer" version of the service pack (the download title will read something like: "Microsoft® .NET Compact Framework 1.0 SPx Developer Redistributable") from:
    http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

    The next step is to copy the appropriate .NET Compact Framework cab file (as per next paragraph) to the emulator. From within the emulator point File Explorer to a share on your PC and then copy and paste the cab to somewhere on the emulator's file system. Now launch the cab file from File Explorer and answer "Yes" if asked to overwrite anything.

    Emulator

    CAB File

    Pocket PC 2002 netcf.core.ppc3.x86.cab
    Windows Mobile 2003 for Pocket PC netcf.core.wce4.x86.cab
    Windows Mobile 2003 for Smartphone RAM installs not supported

    3.8. How do I include SQL Server CE with my application installation?

    To install SQL Server CE with an application, simply install the proper SQL Server CE CAB files as part of the application's installation. There are two sets of cabs associated with SQL Server CE.

    The developer CAB includes Query Analyzer, and error strings. This CAB should not be included with application deployment. It comes in two actual files, one for Pocket PC and one for Windows CE 4.x devices:

    sqlce.dev.ppc3.<processor>.cab
    sqlce.dev.wce4.<processor>.cab

    The SQL Server CE CAB, which includes the engine, client agent, and managed extensions for the client agent is required by applications utilizing System.Data.SqlServerCe components. This CAB also comes in two actual files, one for Pocket PC and one for Windows CE 4.x devices:

    sqlce.ppc3.<processor>.cab
    sqlce.wce4.<processor>.cab

    Applications that access SQL Server, ie applications utilizing System.Data.SqlClient components should deploy the 'sql' CAB. This CAB also comes in two actual files, one for Pocket PC and one for Windows CE 4.x devices:

    sql.ppc3.<processor>.cab
    sql.wce4.<processor>.cab

    All of these CABs are included in the Visual Studio .NET 2003 Professional Edtion install. The default location is:

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

    3.9. How do I use GAPI to create a graphics engine?

    This article describes how to create a DLL that wraps GAPI (Game API), such that it is .NET Compact Framework compliant, and use it to create and optimize a basic graphics library in managed code.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI1.asp

    This article expands upon the "Dancing Rectangles" sample by implementing loading and displaying of bitmaps. It also implements some more advanced features such as animated bitmaps, source and destination key transparency, and alpha blending, i.e., translucency.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI2.asp

    This article expands upon the "Dancing Zombies" sample by implementing drawing of points, lines, and custom 1 bit fonts converted from 8 bit bitmaps. It also implements an input system that overrides the functionality of the hardware buttons and tracks button states.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WrapGAPI3.asp  

    Top of Page Top of Page

    4. 图形用户界面(GUI): 窗体


     

    4.1. 怎样建立一个全屏的窗体?

    您必须把WindowState属性设置为最大化。做一个看不见的窗体,如把全屏的图片放到窗体中,您需要把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事件?

    窗体的load功能是做界面操作的最好方法。典型又安全的做法是在构造器中创建数据和控件的实例。任何包含用户界面的控件或窗体的初始化,都应该在load功能中完成。例如:在窗体的构造器中完成控件对象的建立,然后在load功能中设置控件的位置等 是安全的做法。

    4.3. 怎样把最小化按钮换成关闭按钮?

    通过开发环境的设计器,可以把窗体的自动最小化模式转变成关闭模式,或者通过变成实现。(x)按钮自动最小化应用程序,(ok)按钮回关闭程序。

    在设计器中转化窗体的风格
    打开Visual Studio环境的窗体设计器,查看属性。在窗体上右键并选择Properties,Window Style 部分把MinimizeBox设置为 False。

    在代码中转变窗体风格
    简单的在窗体的load功能中添加以下一行代码:
    //C#
    this.MinimizeBox = false;
    
    'VB
    Me.MinimizeBox = False
    
    4.4. 怎样在.net精简框架上建立多窗体系统结构?

    这篇文章讨论了如何在.net精简框架上为应用程序有效的建立用户界面:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfuiframework.asp

    4.5. 怎样提高.net精简框架应用程序的载入速度?

    通过下面文章中的优化技巧,减少.net精简框架应用程序的载如时间:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfimproveformloadperf.asp

    4.6. 运行时怎样修改窗体的风格?

    这篇快速入门教程描述了在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. 怎样强迫一个窗体变成最小化?

    请查看本问 "6.6. 如何是窗口一直保持最小化? " 部分。

    4.10. 我有一个包含很多控件的智能设备窗体,为什么运行的时候出现"NotSupportedException"错误?

    如果你的窗体中包含了很多控件,当你运行的时候可能会有NotSupportedException的错误。如果你是在Debug模式下运行的话,你会发现异常是来自于窗体的InitializeComponent部分。这种情况是由于精简框架CLR在编译类的方法时,会有64kb的限制造成的。这意味着CLR把方法(如,InitializeComponent)翻译成中间语言时,返回的机器码不能超过64KB。如果超过了64KB,NotSupportedException将被抛出。这也是为什么容易在Debug模式(F5)下导致错误,而非Debug模式(Ctrl+F5)却不容易出错。因为Debug模式运行时会生成更多容量的调试代码。

    除了模拟器,您也可能在智能设备上遇到这个错误,因为即时编译代码根据因CPU类型而异的(如,PocketPC使用的是ARM指令,而模拟器上使用的x86指令)

    没有一个准确的数字说明,一个窗体中到底可以包含多少个控件。因为不同控件的产生的代码量不一样。如,一个Button控件,比TabControl控件产生的代码要少。还会因由设置了多少属性而异。包含集合的控件,象ListBox或TreeView,如果在设计时向属性框中填入了很多值,编译时将产生大量代码。同样,设置了Localized的窗体(Localizable属性为true),会比没设置localize的窗体产生更多代码。因为localize需要从资源文件中读取属性值,放在InitializeComponent方法中。

    果你遇到这种情况,下面有一些技巧帮助你避免它的发生:
    • 把一个窗体的代码分成多个窗体。过多控件的窗体,会影响程序开始时载入的性能。尽可能把用户界面分成两个或多个窗体。
    • 不要在设计时填充大的、内部的、带集合的控件。如果你把很多节点集合加到TreeView控件中,这样会在InitializeComponent方法中加入大量代码。尽可能把加入集合的代码移到Form.Load事件中。这样做的缺点是,要在设计时编辑这些集合将变得不容易,但它有助于分割代码。
    • 不要把自己的代码添加到InitializeComponent方法中,这对通常的编码都有用,不建议添加、修改设计起生成的代码。这样做会造成设计器不可知的错误。如果你想添加自己的启动代码,你应该在Form.Load事件中做。
    • 运行时初始化类似的控件。比如,有12个Button控件,只是文字和位置不同,你应该考虑使用循环来设置属性,而不是在设计时设置属性。在次,如果你自己写代码来实现它,不要把代码放在InitializeComponent方法中。

    编辑InitializeComponent方法的缺点是,在InitializeComponent代码外建立对象实例的代码,将不能在设计器重被设计。同样,如果你手动修改了InitializeComponent中的代码,你会发现,设计器可能不再识别你修改的代码。所以以上技巧的前提是,不要修改InitializeComponent中的代码。

    4.11. 哪个是正确关闭窗体的方法:Appplication.Exit 还是 Form.Close ?

    Application.Exit是类似Win32平台下的PostQuitMessage()硬性退出。收回所有弹出的信息,释放呼叫堆栈,把执行权返回给系统。

    在windows平台(Win32或.NET)下正确关闭应用程序的方法是关闭主窗体(如:Form.Close)。所有主窗体结束时仍存在的窗体需要手工关闭。Any window that's still present after the main message pump ends needs to be manually closed. 好的方法就是在应用程序调用Form.Close或Form.Dispose退出之前,关闭所有窗体。需要记住.NET框架的OnClosing()就是Win32平台下WM_CLOSE的托管版本,而不是WM_DESTROY。

    另外,使用form.Close()的话,你的程序可以在OnClosing或OnClosed事件中处理释放资源、关闭文件等操作。如果使用Application.Exit退出,这些事件将不会被触发。


    4.12. Why does showing a MessageBox on Windows Mobile 2003 for Smartphone with the Abort, Retry, and Fail set of buttons or the Yes, No, Cancel set of buttons, or the third button as the default button result in a NotSupportedException?

    Windows Mobile 2003 for Smartphone only supports 1 or 2 button MessageBoxes.

    4.13 How do I get an icon in the Pocket PC Start Menu Most Recently Used (MRU) List?

    Create a shortcut to your application somewhere under \windows\start menu\programs. When your application is launched from this shortcut an icon for your applications will appear the MRU list.



    4.14 How do I center a Form on the screen?

    In order to display a non-full screen Form, ensure that the Form's FormBorderStyle property is set to FormBorderStyle.None. To center the form add the following code to the Form's FormLoad event handler: Set FormBorderStyle to FormBorderStyle.None then:
    //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 Why can't I show a Form that has been closed?

    Once a Form is closed, it is disposed and therefore may be garbage collected by the system so it is not safe to attempt to show a closed Form. An alternative solution is to use Form.Hide and Form.Show to hide and display Forms respectively.

    4.16 How can I enable multiple instances of an application?

    Multi-instancing is not supported by the .NET Compact Framework. The following code sample provides a solution that allows applications to be instanced rather than maximized when an application is launched but a running instance already exists.

    Note: The following code is not supported and is not guaranteed to work on all versions of the OS, including future versions.
    // 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
    
    <DllImport("CoreDll")> _
    Public Shared Function FindWindow(ByVal lpClassName As String, _
      ByVal lpWindowName As String) As IntPtr
    End Function
    
    <DllImport("CoreDll")> _
    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
    

     Top of Page Top of Page


    5. 图形用户界面 (GUI): 通用


     

    5.1. 怎样建立一个带有图形或支持多行的按钮?

    建立一个带有图形或支持多行的按钮需要使用自定义控件。自定义控件能继承button的paint方法,以及其他任何需要的自定义数据。参考以下连接获得更多关于自定义控件的信息:

    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精简框架下是怎样工作的?

    虽然设置了AcceptsReturn为false,但它还是按true的方式来操作。你可以写一个继承TextBox的类,在KeyPress事件中实现对Enter的处理。

    5.3. 当数据载入ComboBox的时候,为什么SelectedIndexChanged事件没有被触发?

    这是一个已经知道的问题,将在以后的.net精简框架中发布。

    5.4. Show和ShowDialog有什么不同?

    ShowDialog会把一个窗体以 模式 方式显示,这是一种独占调用方式,知道窗体关闭才会返回。这个方法将返回一个DialogResult枚举,表示关闭的条件。
    Show是一种非独占的调用方式,和显示一个控件一样,可以立刻返回,没有返回参数。显示一个控件意味着Visible属性被设置为true,直到Hide方法被调用,Visible方法才会变为false。

    5.5. 为什么我不能建立右键菜单分离器?(separator)

    这是一个已经知道的BUG,把右键菜单设置为分割线,将抛出NotSupportedException错误。这个问题是由于WinCE系统有个限制,不允许在已经加入右键菜单的菜单项设置为分隔符,并且菜单的父类是一个控件。在Visual Studio 2003种,设计器分割移动应用代码的方式和PC上的应用程序类似。这是导致此问题的原因。解决的方法是,把右键菜单单独放在InitilizeComponent方法外的地方。

    5.6. 运行时把ImageList赋给ToolBar时,为什么图象不出现?

    你可以在窗体载入的时候把ImageList分配给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. 如何在菜单项中显示符号:&?

    这项功能还不被.net精简框架支持。使用"&&"不会在菜单项的文字中显示"&"符号。

    5.9. 如何制作基于.net精简框架的动画控件?

    这篇文章将告诉你如何制作基于.net精简框架的动画控件:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/animationcontrol.asp

    5.10. 如何在.net精简框架上制作自定义控件?

    学习制作.net精简框架控件,提高您的技巧。(文章附带了自定义控件的示例代码):
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/customctrlscompactfx.asp

    5.11. 如何制作基于.net精简框架的带图片的按钮?

    这篇文章讨论了建立基于.net精简框架的带图片的按钮:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/ImageButton.asp

    5.12. 如何使用.net精简框架下的MessageWindow类库?

    学习如何使用.net精简框架 MessageWindow 类建立一个提示图标:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/messagewindow.asp

    这篇快速入门实现了,当鼠标点击矩形自定义控件或点击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精简框架中的DataGrid控件提供了几乎.net框架中的DataGrid控件的所有功能。一个主要的区别是.net精简框架中的DataGrid不能在运行时编辑单元。这篇快速入门教程演示了如何通过程序实现编辑单元格的一种方法:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridediting.aspx

    5.15. 怎样设置DataGrid的DataSource?

    与.net框架的DataGrid的另一个区别是,.net精简框架的DataGrid不支持把DataSource设置为DataSet。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagrid.aspx

    5.16. 怎样对DataGrid的列排序?

    与.net框架的DataGrid的另一个区别是,.net精简框架的DataGrid不支持在运行时按照列进行排序。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/datagridsorting.aspx

    5.17. 怎样对ListView中的内容排序?

    .net精简框架不支持ListView.Sort方法,但任然可以排序。这篇快速入门教程定义了一个继承ArrayList.Sort的IComparable接口的方法:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/listviewsort.aspx

    5.18. 如何使用 输入板(SIP)控件?

    这篇快速入门教程演示了在PocketPC上打开和关闭软输入板(SIP),以及当SIP显示时,tab控件大小也跟随变化:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/inputpanel.aspx

    多个窗体应该共享一个输入板对象。可以通过先在主窗体中建立SIP对象,然后把它传给子窗体或暴露SIP对象的一些方法、属性给其他需要使用SIP的窗体。

    5.19. 如何自定义事件?

    这篇快速入门教程描述了如何继承Button类、重载方法来事现双击事件。这个自定义事件会在按钮被双击时触发,两次点击的间隔时间是SystemInformation.DoubleClickTime 属性的值,以毫秒为单位。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/btndclick.aspx

    .net精简框架的控件不支持OnEnter和OnLeave方法,包括Windows.Forms.Control基类。但是,因为支持Control.OnMouseMove方法,您可以通过它和Control.Capture 属性判断鼠标什么时候进入和离开控件。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/enterleave.aspx

    5.20. 如何做一个 owner-drawn List Box?

    您可以制作一个.net精简框架的owner drawn list box。.net精简框架的ListBox或其他控件不支持DrawMode、DrawItem, 或其他drawing方法,但您可以编程实现。这篇快速入门教程提供一个自定义控件类,建立一个owner-drawn list box,并实现了选择字体的控件的功能。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/ownerdrawnlistbox.aspx

    5.21. 如何做一个多选框判断真假?

    这篇快速入门教程提供了在Windows.Forms.CheckBox控件上建立真/假多选框:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/tfcheckbox.aspx

    5.22. 设置InputPanel.Enabled = true的时候为什么出现异常?

    InputPanel组件需要窗体包含MainMenu控件,而且那个窗体是显示在屏幕上的。

    5.23. 为什么自定义控件不会自动继承父类的字体?

    这个功能不被.net精简框架所支持。

    5.24. 为什么当输入字符时,NumericUpDown 和 DomainUpDown 控件不会引发 ValueChanged 和 SelectedItemChanged 事件?

    在代码中改变控件的值 或 按下了上、下箭头才会触发ValueChanged和SelectedItemChanged事件。当用户往控件中输入字符的时候时不会触发的。

    5.25. 为什么NumericUpDown控件增长的值不是设置好的值?

    当您按了上、下后出现的值,不是增长值的倍数,它将向着那个方向(上或下)直到下一个增长值的倍数的值。

    5.26. 为什么StatusBar不能放在窗体的任意位置?一定要在底部?

    StatusBar控件只能停靠在窗体的底部,它的大小不能改变。

    5.27. 为什么我的控件自动继承了父控件的背景色?

    这个功能不被.net精简框架所支持。可以采取的方法是继承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控件能接受decimal类型的值,但不会显示大于2^16的值?

    虽然NumericUpDown控件接受decimal类型的值,但.net精简框架把这个控件的值当作int类型来处理。如,10.23当作10。同样此控件在PocketPC上不接受大于带符号的16位整型。

    5.29. 为什么不能在DomainUpDown 中输入文字,而要选择?

    DomainUpDown控件不会对输入的文字进行确认(不象完整的.net框架)。如果您先输入了一些文字,再按上、下箭头,它会显示内容改变前的值的下一个值。

    5.30. 为什么OpenFileDialog被限制在"My Documents" 文件夹中?

    OpenFileDialog的初始化目录被限制在"My Documents"文件夹或它的子文件夹中。这个限制是由PocketPC系统强加的,为了帮助用户在标准目录下管理自己的文档。
     

    5.31. How can I activate the SIP (InputPanel) without a menu?

    The SIP can be activated by P/Invoking the function "SipShowIM" as follows.
    //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
    
    <DllImport("coredll.dll")> _
    Private Shared Function SipShowIM(ByVal dwFlag As Integer) As Integer
    End Function
    
    5.32. How do I add a subnode to every node in a TreeView?

    Adding subnodes to all nodes is accomplished by iterating through all of the nodes in the TreeView and adding a new node to each.
    //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. How do I determine the number of rows or columns in a DataGrid?

    The number of rows and columns in a DataGrid can be determined from the data source itself. For example:
    //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
    
    If the DataGrid is bound to the DataView you can also use DataView.Count.

    5.34. How do I create a owner drawn Listbox?

    See the .NET Compact Framework QuickStarts, Implementing Events topic:

    http://samples.gotdotnet.com/quickstart/compactframework/doc/btndclick.aspx

    5.35. How can I implement Control.GetNextControl under the .NET Compact Framework?

    The tab order of the controls in the .NET Compact Framework correspond directly to the order of the Controls in the Form.Controls collection. Therefore, GetNextControl can be implemented by determining the index of the specified Control and determing its neighbors in the collection.
    //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. How do I get notified when the user clicks on a treeview node?

    TreeView does not support the Click event, however, a workaround is to use the AfterSelect event instead.

    5.37. How do I set the title of a fullscreen multiline edit control window?

    This is not supported by the current version of the .NET Compact Framework.

    5.38. Why don' I see the validItem selected when I set ComboBox.SelectedValue to validItemInCollection?

    Setting the SelectedValue property only works if the control is databound.

    5.39. How do I detect the location where a 'tap & hold' occurred to bring up a context menu on my custom control?

    Handle the ContextMenu.Popup event, and then query the current mouse coordinates using 'Control.MousePosition'.

    5.40. Why doesn't the scrollbar value ever get set to the maximum value?

    Similar to the NumericUpDown control, the maximum achievable value is the first empty row above the thumb. More specifically, from the editor properties, this equates to:

    Maximum - (LargeChange + 1).

    5.41. How do I tab out of a custom control to the previous control?

    Call this.Parent.Controls(this.Parent.GetChildIndex(customcontrol) - 1).Focus() in the KeyDown event handler when a Keys.Up key is detected.

    5.42. How do I add Toolbar buttons with transparency?

    Icons support transparency, however, there is a known bug in Visual Studio .NET 2003 designer that creates incorrect code and makes icons non-transparent. A work around is to add an icon file to the ImageList outside of InitializeComponent and add the icon files to the project as content or embedded resources. The following code demonstrates this:
    //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
    
     

    Top of Page Top of Page

    6. 与本地代码(Native Code)互用


     

    6.1. 如何调用本地代码写的DLL中的函数?

    本地DLL代码可以通过系统的Invoke (P/Invoke)方法调用。这些文章提供了如何实现调用和更多的调用技巧:

    6.2. 如何使用dumpbin.exe帮助描述 P/Invokes?

    见本问答的 "6.1. 如何调用本地写的DLL中的函数? " 章节。

    6.3. 如何为微软.net精简框架写非托管代码?

    见本问答的 "6.1. 如何调用本地写的DLL中的函数? " 章节。

    6.4. 如何调用 P/Invoke GetTickCount?

    不需要使用P/Invoke调用GetTickCount功能,因为Environment.TickCount就提供了这个功能。
    见本问答的 " 7.2. 如何计算精确的时间间隔?" 章节。

    6.5. 如何获得系统还有多少可用内存?

    您可以调用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
    
    <DllImport("coredll.dll")> _
    Private Shared Sub GlobalMemoryStatus(ByRef ms As MEMORYSTATUS)
    End Sub
    
    <DllImport("CoreDll.dll")> _
    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
    
    <DllImport("CoreDll")> _
    Public Shared Function FindWindow(ByVal className As String, ByVal WindowsName As String) As IntPtr
    End Function
    
    <DllImport("CoreDll")> _
    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精简框架上调用系统函数时,如何装配数据类型?

    见本问答的 "6.1. 如何调用本地写的DLL中的函数? " 章节。

    6.8. 如何得到一个窗体或控件的句柄 (HWND) ?

    其实有一些使用调用本地代码的方法可以获得控件的句柄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
    <DllImport("coredll.dll", SetLastError:=True)> _
    Public Shared Function GetCapture() As IntPtr
    End Function
    
    <DllImport("coredll.dll", SetLastError:=True)> _
    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函数可以建立精确的计时程序。 这些功能是和设备提供商相关的,如果他们不能执行,那么只能和GetTickCount功能得到一样的结果。如果能执行这些函数,就能保证计时器最准确的运行,比GetTickCounter或Environment.TickCount准确得多。TickCount其实是调用GetTickCounter的。

    如果性能计数器是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
    <DllImport("CoreDll.dll")> _
    Public Shared Function QueryPerformanceFrequency(ByRef lpFrequency As Int64) As Integer
    End Function
    
    <DllImport("coredll.dll")> _
    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. 调用本地代码时,数据类型有什么限制?What are the limitations on marshalling types via P/Invoke?

    • 返回值
      • 只能是长度小于等于32位的类型
      • 非浮点型not floating point
    • 参数
      • Only support marshaling blittable types
        • blittable types -> same representation in memory in both managed and native
        • non-blittable -> memory transformation required
        • Since only blittable types, all objects are pinned and never copied
          • Exception: passing String ByVal in VB.NET
        • Implies that you can't marshal nested objects since this requires a memory transformation (non-blittable)
      • 只能是长度小于等于32位的类型
        • 值通过堆栈传递
        • 例外:float32
      • 参考(References)
        • Pass blittable reference types
        • 把参考传递到值类型变量
        • 这就是如何传递float32类型的值
      • 可以传递值类型的数组
        • 在本地代码中,您可以使用指针指向第一个对象,然后一个接一个地访问其他对象
      • String是特殊的,传递char数组 -> 不变的
      • StringBuilder是特殊的,传递char数组 -> 易变的 (需要单独传递长度)
      • 注意:C# bool是8个比特位的,并且不等于Win32的BOOL
      • 队列:编译器默认的队列 (4字节)
      • Marshal.GetLastWin32Error 支持 GetLastError() 语义
      • 未支持的:
        • MarshalAs: no support for non-blittable types
        • StructLayout: 不能改变外观
        • Delegates(委托)
        • DateTime
        • Only support default calling convention

    6.11. 调用GetLastError时,总是获得不定的代码?

    尽量不要尝试调用Windows GetLastError() API,因为CLR调用本地代码时可能会改变last error的代码。取而代之的是,使用调用的返回值标记错误代码,再调用System.Runtime.InteropServices.Marshal.GetLastWin32Error()方法来获得错误代码。
    using System.Runtime.InteropServices;
    
    [DllImport("coredll.dll", SetLastError=true)]
    int myFoo(...);
     
    Foo(...)
    {
        int rc = myFoo(...);
     
        if (rc == false)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "Foo failed");
        }
    }
    

    6.12. 调用本地代码时,有没有参数数量的限制?

    有限制。.net精简框架版本1.0的限制为12个。

    6.13. 调用本地代码时,为什么得到"NotSupportedException"异常?

    通常有三种可能性:
    • 在托管代码中的申明不正确
    • .net精简框架不支持你想做的操作
    • dll的名称在暴露过程中损坏了

    检查以下项目: 
    • 有没有违反.net精简框架 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
    <DllImport("coredll.dll", SetLastError:=True)> _
    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。

    第一种方法,使用非安全代码,直接用指针指向byte数组。
    //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和Marshalling函数复制内存块得到数据块。
    //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
    <DllImport("coredll.dll", SetLastError:=True)> _
    Public Shared Function LocalAlloc(ByVal uFlags As UInt32, ByVal uBytes As UInt32) As IntPtr
    End Function
    
    <DllImport("coredll.dll", SetLastError:=True)> _
    Public Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr
    End Function
    
    <DllImport("coredll.dll", SetLastError:=True)> _
    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. Why do I get a MissingMethodException when I call a function from a native DLL?

    There are several issues to consider when determining the case of a MissingMethodException. When this exception occurs you should verify the following:

    For the latest Microsoft eMbedded Visual Tools and SDK downloads, visit the MSDN Mobile and Embedded Developer Center "Products & Updates" download page at:
    http://msdn.microsoft.com/mobility/downloads/updates/default.aspx

    6.16. How do I set the system time?
    You can set the system time by P/Invoking the SetSystemTime function.
    //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
    
    <DllImport("coredll.dll")> _
    Public Shared Sub GetSystemTime(ByRef lpSystemTime As SYSTEMTIME)
    End Sub
    
    <DllImport("coredll.dll")> _
    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. How do I programmatically soft reset the device?

    The device can be soft reset through P/Invoking of the KernelIoControl function, as demonstrated in the code below. For more information on how to use the function and extend the functionality of this sample, refer to Visual Studio .NET Help.

    Note: On Smartphone devices, this will only work if you are signed with a privileged certificate.
    //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
    
    <DllImport("Coredll.dll")> _
    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. How can I put an icon on the title bar regardless of the which form is active?

    This is not supported with the current version of the .NET Compact Framework. You can, however, P/Invoke Pocket PC's notificaiton system to do this. Refer to the following for more information:

    Sample Code:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnppc2k2/html/ppc_fications.asp

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

    The native Notification APIs are: SHNotificationAdd, SHNotificationRemove, SHNotificationGetData, and SHNotificationUpdate.

    6.19. How do I disable and capture hardware buttons?

    Refer to the sample in the P/Invoke library.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PInvokeLib.asp#PInvokeLib_Topic03

    6.20. How do I hide the start icon?

    The Start icon can be hidden using the 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
    
    <DllImport("aygshell.dll")>  _
    Shared Function SHFullScreen(ByVal hwndRequester As IntPtr, ByVal dwState As Integer) As Integer
    End Function
    
    <DllImport("coredll.dll")>  _
    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. How do I enumerate, create, and terminate processes?

    Refer to the sample:
    http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull=/library/en-us/dnnetcomp/html/processmanager.asp

    6.22. Where can I find a centralized library of P/Invoke samples?

    This sample demonstrates how to P/Invoke numerous useful native functions that are not directly available through the .NET Compact Framework. A test Form is provided that enumerates all available test procedures and allows the user to select and run them:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PInvokeLib.asp

    6.23. How do I play and record .WAV audio files with the Waveform Audio Inteface?

    Learn how to use the Waveform Audio Interface to record and play ".wav" files:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/WaveInOut.asp

     Top of Page Top of Page

    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 splashImageName = 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 splashImageName As String = Path.Combine(fullAppPath, "myfile.txt")
    
    学习如何获得程序执行的当前目录。在Embedded Visual Basic中,程序执行的当前目录可以通过App.Path属性获得。执行程序的目录可以通过程序集的AssemblyName对象的获得,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精简框架下,这个值的误差在0.5秒内,大多情况下会比0.5秒小。
    • GetTickCount()
      属性Environment.TickCount就是调用GetTickCount函数的,所以没有必要再调用本地代码中的这个方法。
    • Performance Monitor
      可以作为压力测试用途,但不是为最终使用的应用程序而设计的。如需更多信息,请查看本问答的 "7.5. 如何使用性能监视器? " 章节
    • Timers
      使用System.Threading.Timer类,可以在线程内设定计时器,用委托(delegate)指向应用程序 。
    • Performance Counter
      如果OEM厂商支持的话,QueryPerformanceCounter函数能提供最高精度的计时功能。
      请查看本问答的"6.9. 如何使用性能计数器功能? "章节。

    7.3. 如何把嵌入式资源当作一个流(Stream)?

    为了能够访问嵌入资源,应用程序只须简单地引用相关的程序集(assembly)并调用GetManifestResourceStream方法。下面这个例子岩石了如何从嵌入资源中建立一个位图:
    //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得到。

    注意:如果AssemblyName中有空格,它将被下划线代替,而且必须这样访问。

    7.4. 为什么得到一个"An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll"的错误?

    这是.net精简框架的BUG。这是由于Windows CE底层的Secure Sockets Layer (SSL)的限制造成的。但是,也偶避免的方法,如果设置 req.AllowWriteStreamBuffering为true,不要设置req.ContentLength属性,那就不会在发生这个错误了。

    7.5. 如何使用性能监视器?

    性能计数器通过编辑设备注册表建立:
    1. 建立注册表键:"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETCompactFramework\PerfMonitor"
    2. 新建双字节项,值就是计数器的名字。
    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函数暂停调用的程序,直到第二个程序运行结束。以下快速入门演示了通过PocketPC模拟器来实现这一操作:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/waitforsingleobject.aspx

    7.8. .net精简框架的应用程序会建立什么线程?

    一个.net精简框架程序最多会产生4个线程:
    • 一个主应用程序线程。
    • 一个线程控制各种时间间隔,时间间隔是供系统和其他应用程序使用的。
    • 一个线程跟踪活动的TCP/IP接口的变化(模拟Windows XP上的媒体动作,Windows CE上是没有这些操作的)。
    • 一个执行终止对象的线程。当第一个被垃圾回收的对象回收时,就被建立了。
    7.9. 如何把byte数组转换成结构体?

    在C++中,通过建造类型(typecasting)可以很方便和有效的保存一个类或结构体到文件,并直接从文件中重构出来。但托管代码的本性决定了它不能这样实现。但还是有办法实现的,建立一个类,把内存中的数据作为它的属性让其他类访问。例如:
    //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. 我可以建立一个委托(delegate)交给Invoke吗?

    不可以。在.net精简框架中,只有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))
    
    Although the following will compile, it will not work properly:
    //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. 如何在微软.net精简框架上使用电话API?

    查看这篇文章,学习如何在基于.net精简框架的应用程序中访问电话API:

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

    7.12. 如何在Pocket Pc上生成GUID?

    Guid.NewGuid方法可以生成新的GUID,但在.net精简框架中没有此方法。阅读这篇文章,学习如何根据GUID规范在PocketPC应用程序中建立GUID对象:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCGuidGen.asp

    7.13. 如何让我的.net精简框架程序和Pocket Outlook的数据结合?

    这篇文章讨论了如何使用InTheHand公司的Pocket Outlook .NET组件:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/inthehandpoom.asp

    7.14. 我可以判断.net精简框架中一个文件的版本吗?

    Visual Studio .NET 2003帮助中的C# Programmer's Reference提供了在.net精简框架下使用不安全代码调用GetFileVersionInfo函数。 这个例子带来的问题是,这个函数是由OEM厂商决定的,并且不保证能返回正确结果。

    使用Reflection可以获得程序集(Assembly)的版本:
    //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精简框架的后台处理有什么相关技术?

    使用后台处理,需要注意相关细节并小心设计。这篇文章提供一些关于后台处理最有用的建议,文中介绍的很多观点是必须说明的:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/BackgroundProcess.asp

    7.16. 在微软.net精简框架上使用多线程有什么技巧?

    学习如何在基于.net精简框架的Windows窗体应用程序中使用多线程。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmultithreadedapp.asp

    7.17. 如何在 智能设备应用 中使用混淆器?

    学习如何使用PreEmptive Dotfuscator混淆器保护你的代码。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfobfuscation.asp

    7.18. 如何使用密码服务对数据进行加密或解密?

    请参考本问答的 "10.5. 写一个捕捉Pocket PC签名的程序n ." 部分。

    7.19. 如何在微软.net精简框架上获得Windows CE设备的唯一号码?

    学习如何使用.net精简框架获得Windows CE设备的设备号。
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/retrievedeviceid.asp

    你可以调用本地代码的函数来获得PocketPC的设备号,也就是序列号。这篇快速入门教程,演示了用MessageBox来显示设备号。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/deviceid.aspx

    7.20. 如何在微软.net精简框架的应用程序上发送短消息?

    这篇文章演示了如何从基于.net精简框架的应用程序中发送短消息:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfsendsms.asp

    7.21. 不使用Control.Name,可以判断事件的发送者吗?

    这篇文章讨论了在.net精简框架下如何判断事件的发送者,.net精简框架中的控件不支持name属性:
    http://msdn.microsoft.com/library/en-us/dncfhowto/html/HOWTOsenderevent.asp

    7.22. 如何在线程中调用方法的参数?

    在应用程序中使用多线程,可以提高用户界面的性能。基类Control提供Invoke、BeginInvoke和EndInvoke方法在控件中来建立线程。.net精简框架不支持异步的BeginInvoke和EndInvoke调用。到现在,也还不支持向同步Invoke调用传递参数。这篇快速入门教程提供一个自定义类ControlInvoker,可以实现向Invoke方法中传递参数:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/controlinvoker.aspx

    7.23. 如何建立提醒程序和定时程序?

    这篇快速入门文章描述了使用P/Invoke定义一个用户提醒和订时的应用。您可以计划提醒窗口弹出的时间。您也可以设置一个应用程序在特定的时间运行或响应某个事件。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/notifications.aspx

    7.24. 如何播放声音?

    这篇快速入门教程演示了使用P/Invoke播放个短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
    
    在Visual Studio 2003中测试的时候,可以通过继承开发环境设置命令行的参数。主菜单,选择 Project->Project Name Properties.Property Pages对话框中,选择 Configuration Properties->Debugging。Command Line Arguments 中输入字符串:text box.

    7.26. 当使用已经释放的对象的方法或属性的时候,为什么得到一个异常?

    完整的.net框架不保证,在访问一个已经释放的对象的属性或方法时能成功。在完整的.net框架下,虽然访问某些属性(像Text),经常能成功。根据.net框架和.net精简框架执行上的区别,在.net精简框架上访问已经释放了的对象的方法或属性会经常失败。

    7.27. 如何获得"Enter", "TAB", 和 "Arrow"按键的事件?

    使用KeyDown和KeyUp事件,可以获得无字符的键(像tab)。

    现在,只有一些特定的控件支持key的事件(如,form, panel, textbox 和自定义控件)。在.net精简框架SP2版本中,所有控件都将支持key事件。

    已经知道的问题,在使用模拟器时,从键盘按下tab键将不被支持,但从软键盘(SIP)上按下tab时,会有效果。

    这是VS带的模拟器的原因造成,而不是.net精简框架的问题。.net精简框架触发Key事件当它收到系统传来的WM_KEY*消息。当您在模拟器中运行本地代码程序时,从键盘按下tab键并不会让系统触发WM_KEYDOWN事件。若是通过模拟器的软键盘(SIP),或真正的设备,则不会有这个问题。

    7.28. 如何删除一个只读文件?

    使用System.IO.FileInfo类访问文件的属性。
    //C#
    System.IO.FileInfo fi = new System.IO.FileInfo("filename");
    // remove readonly attribute
    fi.Attributes -= System.IO.FileAttributes.ReadOnly;
    System.IO.File.Delete("filename");
    
    'VB
    Dim fi As New System.IO.FileInfo("filename")
    'remove readonly attribute
    fi.Attributes -= IO.FileAttributes.ReadOnly
    System.IO.File.Delete("filename")
    

    7.29. How do I determine if a member exists at runtime?

    The existence of a member can be determined at runtime using Reflection. The code below demonstrates how to use Reflection to access the "Width" property and the "GetPixel" method of a Bitmap object. In the case of the "Width" property, the code enumerates all "public" properties with a "get" component and then searches for one named "Width". The "GetPixel" sample demonstrates how one might use Reflection to call a known function where the parameter order is unknown. This sample is set up as if the author knows there is a method named "GetPixel" which takes a pixel location of x,y but does not know the order in which they appear in the parameter list. The sample enumerates the methods and searches for one named "GetPixel" and then enumerates the parameter list to determine whether the first or second parameter is named "X". Keep in mind that, due to the differences in hardware pixel formats, the value returned by GetPixel may be different from that set by SetPixel in this sample.

    Reflection provides many powerful tools for determing functionality at runtime so for information, refer to the documentation regarding System.Type and the namespace 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. How do I determine the device name programatically?

    The device name can be accessed through the System.Net namespace, as demonstrated by the following code.
    //C#
    String devName = System.Net.Dns.GetHostName();
    
    'VB
    Dim devName As String = System.Net.Dns.GetHostName()
    

    7.31. How do I build a C# Smart Device project from the command line?

    Enter the following commands as single lines (each is broken into two lines for clarity):
    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. How do I abort an executing thread??

    There is no Abort method to the Thread class in the .NET Compact Framework so a thread must be aborted by returning from the executing procedure. Typically, an application will notify threads of a closing event by setting a global variable. The main thread will then wait for worker threads to finish processing before closing the application. The following HOWTO article demonstrates how to accomplish this.

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


    7.33. Why can't I play a movie on the Pocket PC emulator?

    Windows Media Player is only available on the Pocket PC 2003 emulator. The Windows Media Player install package is for installation on a hardware device connected through ActiveSync and will not install to the emulator.

    7.34. How do I suppress Form titles from showing in the active applications list?

    The Active Programs list on the Pocket PC enumerates all open Forms. To stop a Form from being displayed in the list, simply set the Form's caption to be an empty string. The following example shows how to keep only the application name in the list while a Form is displayed from within another Form:
    //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. How do I access a Control from its instance name?

    You can use Reflection to look up a control instance by its name. Here is some sample code:
    //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. How do I detect the hardware directional pad buttons?

    The hardware directional pad buttons can be detected through the standard key events by comparing the KeyCode from the KeyEventArgs parameter.
    //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. How do I get a double click event when only the Click event is supported?

    See the .NET Compact Framework QuickStarts, Implementing Events topic:

    http://samples.gotdotnet.com/quickstart/compactframework/doc/btndclick.aspx

    7.38. How do I get onenter/onleave style notifications?

    See the .NET Compact Framework QuickStarts, OnEnter/OnLeave Functionality:

    http://samples.gotdotnet.com/quickstart/compactframework/doc/enterleave.aspx

    7.39. How do I use threading in a modal dialog that doesn't hang my app?

    Create a modeless dialog that behaves like a model dialog.
    //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. How do I round floating point numbers efficiently?

    There are two primary methods for rounding numbers:
    • Convert.ToInt32
    • Cast or Fix (C# or VB)
    Convert.ToInt32 automatically handles rounding, where remainders of .5 and greater cause the number to be rounded up. Casting or using Fix requires adding .5 to the number to ensure that it will round properly, as these methods simply remove the remainder.

    Profiling on the emulator and a Compaq iPAQ H3600 series device yielded the following results for 1 million operations of each method, where num is a float set to 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

    Thus, by examining the release build results for the device, it can be concluded that on the current generation of devices it is most efficient to use casting in C# and Convert.ToInt32 in VB. In C#, casting proved to be over 106 times faster, whereas in VB, Convert.ToInt32 was nearly 3 times faster.
    //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. Why does Control.Invoke take so long when a modal dialog is displayed?

    There is a known bug with using Control.Invoke while a modal dialog is displayed through ShowDialog. Download the latest .NET Compact Framework Service Pack to fix this:

    The latest platform updates and .NET Compact Framework service packs are available at:
    http://msdn.microsoft.com/mobility/downloads/default.aspx


    7.42. Is there a way to retrieve the culture information of an Assembly?

    Culture information can be retrieved through 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
    
     
     Top of Page Top of Page

    8.通讯和Web服务


     

    8.1. 如何通过TCP Socket向桌面机发送数据?

    请查看本问答的"10.5. 写一个捕捉Pocket PC签名的程序. " 部分。

    8.2. 为什么不能访问本机上的Web服务?

    不要在设备上使用localhost来引用Web服务,因为对于设备来说localhost就是运行应用程序所在的设备,就是设备它本身。您应该使用机器名或IP地址来引用Web服务。

    8.3. 如何在微软.net精简框架上调用Web服务

    这篇文章向您演示了如何从智能设备上,通过.net精简框架同步和异步调用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框架的快速入门中有说明,标题是"Write a Simple Web service,")。这个快速入门教程提供了一个Web服务的客户端应用:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/xmlwebservice.aspx

    8.6. 如何使用MapPoint3.0得到地图?

    这篇快速入门描述了如何使用MapPoint的Web服务,编程实现在PocketPC上获得特定位置的程序,如以下屏幕截图所示:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/mappointfindmap.aspx

    8.7. 如何使用MapPoint3.0获得地图和方向?

    这篇快速入门教程描述了如何使用MapPoint的Web服务,在PocketPC上获得特定位置的地图方向,如以下屏幕截图所示:
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/mappointdirections.aspx

    8.8. Is NTLM authentication supported by the .NET Compact Framework?

    Using Digest authentication instead of Basic or NTLM authentication is the recommended solution. Digest authentication is supported by the .NET Compact Framework.

    8.9. When using blocking Sockets, why does Send throw an InvalidOperationException when blocking is set to false?

    There is a known issue with setting Blocking to false on a blocking socket. There are three paradigms when programming with sockets (both managed and native) and it is strongly recommended that developers use asynchronous I/O functions as a solution to this problem. Select is very inefficient in managed code, and the cost of the regular case exception is also high. The three paradigms are detailed below, with the last being the preferred method.

    • Use blocking calls on blocking sockets (i.e. send(), recv(), etc). This is the simplest method, and probably the most commonly used. The functions perform their operation synchronously, tying up the currently executing thread. This is most acceptable for clients, and multithreaded servers (Microsoft does not recommend using one thread per client because threads are very expensive on Windows). Note that though the operations may block for an unspecified period of time (i.e. until the operation can be completed), they will most often complete immediately.
    • Use non-blocking sockets in conjunction with select or poll. Use the same "blocking" functions, but put the socket in a special mode that prohibits it from blocking. In the cases when the function would block, it returns an error code (in managed code, this throws an exception). You can then use poll or select to wait until a point in time at which an operation would complete (select allows you to manage more than one socket, so you can handle multiple clients on only one thread), and then perform the operation. At the time these calls were created, there were no threads in operating systems, so this was the only way to do things. Using this mechanism has by far the absolute worst performance you could possibly get from socket programming. This problem is exacerbated in managed code, since you now expect an exception to be thrown, which is an even bigger performance hit.
    • Use asynchronous I/O functions on the socket. This is your best all around solution. It allows you to perform operations asynchronously, and you get notified by callbacks. In general, the performance is better than using non-blocking I/O with select, and this is the recommendation for how to do things (at least, in native code).


    8.10. How do I create an http-server?

    Get technical insight on the implementation of Mobile Web Server architecture. Understand use cases, the web server framework and future developments in the architecture:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/NETCFMA.asp

    8.11. Why do I get an exception when calling SetSocketOption with ReuseAddress set?

    This is a known issue in the version 1 of the .NET Compact Framework. To work around the issue, you can P/Invoke setsockopt with SO_REUSEADDR set to true.

    8.12. Why do I get a socket error using SSL to communicate with a server via the WebRequest namespace?

    There is a known issue in the .NET Compact Framework. You can work around this by setting HttpWebRequest.AllowStreamWriteBuffering to True and commenting out your setting of the ContentLength.

     

    Top of Page Top of Page

    9. SQL CE 和 数据


     

    9.1. 使用.net精简框架、SQL Server CE 和 复制 开发应用程序时,要注意些什么?

    这篇文章详细讨论了这个问题:
    http://msdn.microsoft.com/msdnmag/issues/03/09/datapoints/toc.asp

    9.2. 如何在微软.net精简框架上使用合并复制(Merge Replication)?

    这篇文章讨论了如何通过程序在.net精简框架的应用程序中调用合并、复制:
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfmergereplication.asp

    SQL Server CE是非常好的在设备上管理数据的工具,但在未复制到桌面机的SQL Server之前,它必须保留数据。使用合并、复制在设备上管理数据,然后当设备连接到桌面机时,再合并到桌面机的SQL Server的实例中。.net精简框架提供SqlCeReplication对象,可以通过程序实现数据的合并与复制。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlcemergereplication.aspx

    9.3. 如何将ADO.NET数据和XML绑定?

    以下三个步骤:

    1. 根据提供的XML文件,建立一个XML Schema文件(.xsd)。
    2. 读取XML数据和它的schema,以便操作。
    3. 将XML保存会文件。
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/adonetdatabinding.aspx

    9.4. 如何建立SQL Server CE的数据库?

    您可以使用.net精简框架在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精简框架在用户输入时,向SQL Server CE的数据库中插入值。以下教程向您展示了如何实现此操作:
    • 设计一个用户可以设置查询值的界面。
    • 连接到SQL CE的数据库。
    • 把用户输入的值插入到SQL CE的数据库中
    http://samples.gotdotnet.com/quickstart/CompactFramework/doc/sqlceparameterizedquery.aspx

    9.6. Why does using RDA and the push method fail with error 27750?

    Symptom
    When calling:
    rda = new SqlCeRemoteDataAccess();
    
    An error of type SQLCeException with a Native Error Code of 27750 occurs. This error corresponds to "Cannot load sscemw20.dll or ssceca20.dll is missing or not registered."

    Resolution
    Load the library at the start of the application, even if you do nothing with it. To load the library, you can load the SqlCeEngine object.
    SqlCeEngine eng = new SqlCeEngine();
    
       

    Top of Page Top of Page

    10. 其他信息


     

    10.1. Pocket TaskVision 程序

    This document provides an overview of the development tasks that were unique to the Pocket TaskVision sample application. Pocket PC devices have much lower storage capacities, memory and lower-end processors than desktop systems—storage and performance considerations are mentioned throughout the document.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/wnf_pkttaskvision.asp

    10.2. 建立基于微软.net精简框架的进程管理器

    In this article, learn how to marshal structures as byte arrays.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/ProcessManager.asp

    10.3. 使用微软.net精简框架开发移动游戏

    Learn how to create .NET Compact Framework-based games. Learn the key requirements for writing games targeting small devices and see that the .NET Compact Framework can handle them with ease. Include advanced performance-tuning techniques that you can use to push the limits of your game.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfgaming.asp

    10.4. 制作一个微软.net精简框架的DateTimePicker控件

    Learn how to use a managed DateTimePicker class in your Pocket PC projects. The .net精简框架 provides managed classes for most controls but the DateTimePicker class is not supported. Wrapper classes that P/Invoke the native control can be found on the Web, but this sample provides a purely managed DateTimePicker class that you can use in your Pocket PC projects. The class and sample application are provided in C# and Visual Basic .NET.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/netcfdatetimepicker.asp

    10.5. 写一个捕捉Pocket PC签名的程序.

    This article discusses the Pocket PC Signature sample application. The sample includes a client that runs on the Pocket PC that sends signature data over TCP sockets to a server that is running on the desktop. Data is encrypted and decrypted using the cryptography services.
    http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCSignatureApp.asp

    10.6. 有没有非微软的网站提供在.net精简框架上开发应用的信息?

    See the "Related Sites" section of the MSDN Mobile and Embedded Developer Center:
    http://msdn.microsoft.com/mobility/Community/related/default.aspx


    Top of Page Top of Page

    11. 连通性


     

    11.1. 为什么不同通过ActiveSync把程序部署到Windows CE的设备上?

    Symptom: When a Windows CE device is connected through ActiveSync, deployment and debugging (F5 and Ctrl-F5) fail with the typical error message "There were deployment errors. Continue?"

    Cause: Due to the fact that ActiveSync 3.5 and 3.6 do not provide accurate information about the device instruction set, ConMan (Visual Studio .NET 2003 component for device connectivity) cannot use the information returned by ActiveSync to map a Windows CE device to the right .NET Compact Framework target (MIPSII, ARMV4 etc).

    Workaround: Install and run the separately provided Windows CE Configuration Add-In. For ARMV4 devices, an alternative is to select Pocket PC Device at the beginning of the deployment.

    11.2. 为什么不能通过ActiveSync调试 CEPC 或其他 x86 的Windows CE设备?

    Symptom: After running the Windows CE Device Configuration Add-In, the user can deploy without debugging (Ctrl-F5) to an ActiveSync connected CEPC (or any x86 based Windows CE device) but cannot debug (F5). Non-x86 based Windows CE devices do not have this problem.

    Cause: Debugging Windows CE Emulators (also x86 based) uses a TCP port that conflicts with the one used by ActiveSync for debugging x86 based devices. To support Emulator debugging, it is necessary to disable debugging for CEPC and other x86 devices by default.

    Workaround: The following workaround will allow debugging of x86 devices but disable debugging with the Windows CE Emulator. The workaround requires the files WinCEx86Device.reg, and ProxyPorts.reg which can be found in the SDK utilities directory: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\WinCE Proxy Ports Reg".

    If you do not have these files they can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    • Import WinCEx86Device.reg to the registry. Now you will be able to debug x86 devices, but debugging with the Windows CE Emulator will fail.
    • To restore Emulator debugging, remove the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\ProxyPorts" and then import ProxyPorts.reg.

    11.3. 为什么当设备上的Toolhelp.dll文件丢失后,调试就会失败?

    Symptom: After F5, all the files including the application executables and .net精简框架 cab files are copied to the device, and the IDE reports success on launching the application, but nothing is launched on the device. If you check the \windows folder of the device, toolhelp.dll does not exist.

    Cause: Some device images may not include toolhelp.dll which is required by SDE debugging.

    Workaround: Copy toolhelp.dll from Windows CE SDK to the \windows folder of the device. This file can be found in the corresponding target directory for each device.

    For example, for an ARM device: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\ToolHelp\WinCE4\armv4".

    If you do not have this file it can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    11.4. 为什么当网络协议数超过50个的时候,就不能向设备发布程序?

    Symptom: The "deployment error" message box occurs on Ctrl-F5 or F5. Running EnumProtocols.exe lists more than 50 protocols. (EnumProtocols.exe can be found in the WinCE utilites directory: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\EnumProtocols"). If you do not have this file it can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    Cause: It is a known issue that the .NET Framework method System.Net.Dns.GetHostName throws an exception when there are more than 50 network protocols installed on the current machine. The method is called by ConMan and the exception causes failure of the ConMan transport initialization.

    Workaround: Uninstall the network protocols that are not actually needed. One way to do this is to go to Device Manager (Right-click on "My Computer", select Properties->Hardware and press the "Device Manager" button) and remove unused entries under "Network adapters". Another way is to uninstall applications that have installed protocols. Those applications can be found from the output of EnumProtocles.exe.

    11.5. 为什么卸载ActiveSync后,不能通过ActiveSync向设备发布?

    Symptom: The "deployment error" message box occurs on Ctrl-F5 or F5 after ActiveSync has been uninstalled. Uninstalling ActiveSync typically happens when the user upgrades ActiveSync, e.g. from version 3.5 to 3.6.

    Cause: ConMan relies on some registry values under "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\ProxyPorts" for deployment and debugging through ActiveSync. These registry values are removed when ActiveSync is uninstalled.

    Workaround: Reinstall or repair Visual Studio .NET 2003.
    A simpler fix is to import ProxyPorts.reg which can be found in the WinCE utilities folder: "<VSROOT>\CompactFrameworkSDK\WinCE Utilities\WinCE Proxy Ports Reg" . If you do not have this file it can be downloaded from the following link:
    http://www.microsoft.com/downloads/details.aspx?FamilyID=7ec99ca6-2095-4086-b0cc-7c6c39b28762&DisplayLang=en#filelist

    The device may need to be un-cradled/re-cradled or soft rebooted to make the fix take effect.
    It is recommended that users never uninstall ActiveSync. To upgrade ActiveSync, you should directly install the new version which will correctly override the old one.

    11.6. 为什么本地化的机器名或用户名或导致向设备发布程序的失败?

    Symptom: When the machine name or the logon user name contains any character that is not on the current code page or below ASCII value 0x20, deployment to devices fails while deployment to the Emulator works fine.

    Cause: ConMan security authentication internally uses the machine name and user name in the ASCII form which is not able to handle characters in the categories described above.

    Workaround: Do not use characters described above in the machine name or the user name. If the user is not clear what characters belong to those categories, it is always safe to use just English alphabetic letters and numbers.

    11.7. 为什么当前用户不属于Administrators组的时候,不能向设备发布程序?

    Symptom: If the current logon user is not in the Administrators group, deployment to devices always fails even though the user is in the Visual Studio Developers group and the Debugger Users group. On the other hand deployment/debugging to the Emulator works fine.

    Cause: During device deployment, the ConMan code internally opens a file in a mode that requires administrator privileges.

    Workaround: Add the current user to the Administrators group or limit the deployment target to the Emulator only.

    11.8. 为什么向Pocket PC或模拟器发布的时候出现 sharing violation 的错误?

    Symptom: When deploying an application to a Pocket PC 2002/2003 device or Emulator, the deployment fails with an output message similar to "Could not write to output file 'SmartDeviceApplication1.exe' - Sharing violation". This usually happens after the same application has previously deployed to the same device or Emulator.

    Cause: By default the X button on an application for Pocket PC 2002 or 2003 (not 2000) does not close the process. It only "minimizes" the application window. When the user tries to deploy the application again, the "minimized" instance will cause the sharing violation and fail the deployment.
    Another possible cause is that the user has forcibly terminated a debug session in the middle.

    Workaround: Make sure the application is really closed on the device or Emulator when deploying it again. To see running processes, go to Start->Settings->Memory->Running Programs on the Pocket PC. In case it is intended to have a button to really close an application, create such a button explicitly or set Windows Form's property Minimize Box to False so that the X button will become an OK button for closing the application. If the cause was the manual termination of a debug session, the device or the Emulator may need to be soft rebooted.

    11.9. 为什么在.NET Server的计算机上第一次使用模拟器的时候,得到一个安全警告消息?

    Symptom: When the Emulator is used for the first time after the installation of Visual Studio .NET 2003 on a .NET Server machine, a message box pops up titled "Security Alert – Driver Installation". The text of the message starts with "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". Near the end, it says "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?"

    Cause: Visual Studio .NET 2003 installs a Virtual PC Application Services Emulator driver which does not pass the validation of .NET Server's Driver Validation system.

    Workaround: When the alert message comes up, click the Yes button. Otherwise the Emulator will not work.

    11.10. 为什么在模拟器刚开始运行的时候出现关于找不到文件的错误信息?

    Symptom: When the Emulator is being started, a message box appears titled "Emulator for Windows CE" with the text "One or more files from the Emulator for Windows CE installation is missing. Please reinstall Emulator for Windows CE and try again." The connection or deployment to the Emulator will fail after the message box.

    Cause: A typical cause is that the Emulator driver is not installed or is corrupted.

    Workaround: Go to "Device Manager" (Right-click on "My Computer", select Properties->Hardware and press the "Device Manager" button) and check whether "Virtual PC Application Services" is installed under the System Devices group. If the driver is not installed, install it by running "<VSROOT>\CompactFrameworkSDK\ConnectionManager\Bin\DriverInstall\Smart Devices Emulator.msi".

    Note: Verify that the "Virtual PC Application Services" appears after running the msi file. If not then reboot the PC and attempt the installation again.

    11.11. 为什么第一次用模拟器发布时,会出现偶尔的错误?

    Symptom: The startup of the Emulator is slow and the deployment eventually fails with a connection error message. The startup mainly includes starting the Emulator image and downloading the .net精简框架 files. The failure happens more often on low-end machines when the Emulator is used for the first time or after "turn off" instead of "saving state" was used on the previous Emulator shutdown.

    Cause: Due to some performance issues in the Emulator, its startup may take too long to finish within the ConMan timeout period.

    Workaround: If possible, always choose "saving state" instead of "turn off" when closing the Emulator so that the startup will be much faster when the Emulator is started next time. Or before the deployment, pre-start the Emulator by clicking on the "Connect to Device" button which is located next to the Emulator name on the menu bar. Note that the first deployment will still fail after the pre-start. (See details in the issue about this.) In addition, hovering the mouse over the Emulator image may speed up the Emulator startup.

    11.12. 为什么第一次用Connect按钮连接模拟器并发布程序的时候失败了?

    Symptom: When the Emulator is started with the "Connect to Device" button, the first deployment attempt always fails.

    Workaround: There is no workaround at this point for the failure of the first deployment after the Emulator is started with the button, but the subsequent deployment attempts should succeed.

    11.13. 为什么当计算机没有网络连接的时候,用模拟器调试程序会出现错误?

    Symptom: When a machine has no active network connection, debugging with the Emulator (F5) does not work, while deployment without debugging (Ctrl-F5) works fine.

    Cause: Emulator debugging relies on TCP transport.

    Workaround: Install the Microsoft Loopback Adapter on the machine.

    To install the the Microsoft Loopback Adapter in Microsoft Windows XP

    1. Open Control Panel, choose Add Hardware, and then choose Next.
    2. Choose Yes, I have already connected the hardware, and then choose Next.
    3. From the Installed hardware list, select Add a new hardware device, and then choose Next.
    4. Choose Install the hardware that I manually select from a list (Advanced), and then choose Next.
    5. From the Common hardware types list, select Network adapters, and then choose Next.
    6. From the Manufacturer list, select Microsoft.
    7. From the Network Adapter list, select Microsoft Loopback Adapter, and then choose Next.
    8. Choose Next, and then choose Finish.

    To install the Microsoft Loopback Adapter in Microsoft Windows 2000

    1. Open Control Panel, choose Add/Remove Hardware, and then choose Next.
    2. Choose Add/Troubleshoot a device, and then choose Next.
    3. From the Devices list, select Add a new device, and then choose Next.
    4. Choose No, I want to select the hardware from a list, and then choose Next.
    5. From the Hardware types list, select Network adapters, and then choose Next.
    6. From the Manufacturers list, select Microsoft.
    7. From the Network Adapter list, select Microsoft Loopback Adapter, and then choose Next.
    8. Choose Next, and then choose Finish.

    11.14. 为什么当模拟器使用了一个COM端口的时候不启动不了(黑屏)?

    Symptom: When the Emulator image is starting up, it stays as a black screen forever. This happens when the Emulator is configured to use at least one COM port.

    Cause: By default, the Emulator is not assigned a COM port but the user may change the configuration to assign a COM port to the Emulator. When a COM port assigned to the Emulator is used by ActiveSync or any other running application, the Emulator image loading will fail.

    Workaround: Remove all of the COM ports assigned to the Emulator or change them to those not used by ActiveSync or any other running application. To remove or change the COM port configurations in Visual Studio .NET 2003, go to Tools/Options/Devices, choose an Emulator in the Devices window and click the Configure button.

    11.15. 为什么Visual Studio .NET 2003的模拟器不能和eMbedded Visual Tools的模拟器同时使用?

    Symptom: When the eMbedded Visual Tools (Platform Builder) Emulator is running, Visual Studio .NET 2003 Emulator deployment fails, and vice versa. Sometimes even after the Visual Studio .NET 2003 Emulator is closed, the eMbedded Visual Tools Emulator still does not work.

    Cause: The Visual Studio .NET 2003 Emulator and the eMbedded Visual Tools Emulator internally use two different instances of Emulator.exe which are not compatible with each other. Because they share the same executable name and the exe is a single instance application, while Emulator.exe for eMbedded Visual Tools is running, the one for Visual Studio .NET 2003 cannot be started, and vice versa. Another issue is that when the Visual Studio .NET 2003 Emulator user interface is closed, emulator.exe does not close until the hosting Visual Studio IDE instance is closed. In that case, the eMbedded Visual Tools Emulator cannot be started even though there is no Emulator running visually.

    Workaround: Do not use the two Emulators at the same time. If an Emulator cannot be started, check the Task Manager and close any running emulator.exe processes.

    11.16. 为什么没有ActiveSync连接的时候不能通过TCP连接向设备发布程序?

    Symptom: When a device does not have an ActiveSync connection with the Visual Studio machine but has a valid TCP connection, deployment does not work.

    Cause: ConMan relies on an ActiveSync connection to perform some initial settings between the Visual Studio machine and the device. If no ActiveSync connection is available, the setting will have to be performed manually.

    Workaround: Use the separately provided Keyman tool to perform the initial device settings with the following steps:

    1. Choose the correct flavor of Keyman.exe (e.g. ARMV4 or SH4, etc) and place it on the device. Launch Keyman and select "FILE->CONNECT". Keyman is now waiting for the VS machine to connect to it via TCP/IP. After the VS machine has connected, and then disconnected, Keyman on the device will automatically exit.
    2. On the VS machine, copy CryptoAPIWrapper.dll from <VSROOT>\ CompactFrameworkSDK\ConnectionManager\bin to the directory of KeymanDesktop.exe. Launch KeymanDesktop.exe.
    3. Click "Save" to save your settings in the current directory where KeymanDesktop.exe is running. The saved defaults will be loaded next time the exe is launched.
    4. Enter the IP Address of the device
    5. Use the recommended value for the Device Port.
    6. Enter the path of the "Target" directory where the ConmanClient bits such as ConManClient.exe reside. The typical value is \ CompactFrameworkSDK\ConnectionManager\Target.
    7. Use the Connect button to connect.
    8. Click on "prep device" after you have connected. On success, you will see a dialog telling you everything went OK.
    9. Use the Disconnect button to disconnect. When you disconnect, the device side bits will automatically exit.
    10. Launch ConManClient.exe on the device. First you must select the flavor of the target device. Also, you must select the location of your "Target" directory in Visual Studio.
    11.17. How can I allow Activesync to connect to an Emulator session from Visual Studio .NET 2003?

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

    11.18. How can I copy files to the device currently connected to desktop ActiveSync?

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

    11.19. Why does the Visual Studio debugger fail to connect to an ARMV4I device?

    Cause
    Bug in the connection tool after selecting ARMV4I CPU type

    Resolution
    Configure tool for ARMV4T CPU type:
    1. In Visual Studio, on the Tools menu, click "Select Windows CE Device CPU". Note: this menu item is installed by the Windows CE Utilities for Visual Studio .NET 2003 Add-on Pack
    2. Change the device architecture to ARMV4T
    3. Click Configure, then click Close. Restart Visual Studio if prompted

    Top of Page Top of Page

    12. Smartphone


     

    12.1. Where can I get the latest Smartphone SDK?

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

    12.2. What are the rules for smartphone menus?

    Smartphone menus have several rules, such as:

    • the first menu item (corresponding to the left soft button) cannot have any sub items
    • the second menu item (corresponding to the right soft button) can have sub items
    • any other top level menu items are not used
    If the first menu item has more than 1 item, you will get a NotSupportedException.

    For a complete list of requirements, refer to the Smartphone help documentation:
    ms-help://MS.VSCC.2003/MS.Smartphone2003Help.1033/dv_smartphone/html/spconUsingMenus.htm

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

    12.3. Why are there disabled controls in the toolbox when creating a Smartphone project?

    The smartphone platform only supports a small set of controls. The controls that are not supported are disabled.

    For more information, refer to the following Smartphone help documentation:
    ms-help://MS.VSCC.2003/MS.Smartphone2003Help.1033/dv_smartphone/html/spconWindowsFormsSupport.htm

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

    12.4. Does Smartphone support RAM installs of the .NET Compact Framework?

    No. The .NET Compact Framework is serviced through operating system updates at the carrier's / OEM's discretion. Therefore, .NET Compact Framework will generally drop as part of larger Windows Mobile for Smartphone operating system updates.

    12.5. How do I set the title of a fullscreen multiline edit control window?

    This is not supported by the current version of the .NET Compact Framework.

    12.6. How can I generate Smartphone CABWizSP XML docs from existing Pocket PC CAB files?

    Download Convert PPC DAT to SP XML from Windows Mobile Developer Power Toys:
    http://www.microsoft.com/downloads/details.aspx?FamilyId=74473FD6-1DCC-47AA-AB28-6A2B006EDFE9&displaylang=en

    12.7. How can I send characters and strings to the Smartphone 2003 Emulator via ActiveSync?

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

    12.8. How do I programmatically set the Smartphone input mode?

    The input mode can be set using GetFocus and SendMessage APIs according to the code below:
    '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
    
    <DllImport("coredll.dll")> _
    Public Shared Function GetFocus() As IntPtr
    End Function
    
    <DllImport("coredll.dll")> _
    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;
    }
    

posted on 2005-05-22 13:26  Chep  阅读(2210)  评论(0编辑  收藏  举报