﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-cc</title><link>http://www.cppblog.com/xingmuxixi/</link><description /><language>zh-cn</language><lastBuildDate>Mon, 13 Apr 2026 09:42:28 GMT</lastBuildDate><pubDate>Mon, 13 Apr 2026 09:42:28 GMT</pubDate><ttl>60</ttl><item><title>Hibernate插入和修改数据到数据库中时不修改存在默认值字段[转]</title><link>http://www.cppblog.com/xingmuxixi/archive/2013/03/29/198909.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Fri, 29 Mar 2013 02:07:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2013/03/29/198909.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/198909.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2013/03/29/198909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/198909.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/198909.html</trackback:ping><description><![CDATA[<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">说明：</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">今天在做一个OA的简单增删除该查的时候，有一个时间类型的字段（数据插入时间），本身想着，这个字段直接中<a style="color: rgb(179,43,213); text-decoration: underline" title="Oracle" href="http://www.linuxidc.com/topicnews.aspx?tid=12" target="_blank">Oracle</a>数据库设置一个Default Value ，就不用再前台install这个字段的值了，但是后时间操作中发现插入的时候如果不通过hql去写代码的话，而是通过hibernate的接口getHibernateTemplate().saveOrUpdate(entity);的话，就出现问题，插入的时间类型字段的值是null，tmd有点郁闷，不好意思又说脏话了，也是当时头有点昏，呵呵。后来，一想如果通过getHibernateTemplate().saveOrUpdate(entity);这个借口，如果没有设置值，那么就会设置null，所有出现了这个问题。查看了下hibernate的接口文档，一看，原来是这样的。</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">需要添加下面的参数在*.hbm.xml中class节点设置，如下</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">一是将dynamic-insert设置为true</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">二是将对应字段的属性设置not-null为false</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&lt;hibernate-mapping&gt;<br />&lt;class name="com.tom.hibernate.xxxx" table="xxx schema="xxx"<span class="Apple-converted-space">&nbsp;</span><span style="color: rgb(255,0,0)">dynamic-insert="true" dynamic-update="true</span>"&gt;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">&lt;property name="entryDate" type="java.util.Date"&gt;<br />&lt;column name="ENTRY_DATE" length="7"<span style="color: rgb(255,0,0)"><span class="Apple-converted-space">&nbsp;</span>not-null="false"</span>/&gt;<br />&lt;/property&gt;</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">用拿来主义）贴过来一个这个接口说明：</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">下面是有关其它配置的说明</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Hibernate允许我们在映射文件里控制insert和update语句的内容.比如在映射文件中&lt;property 元素中的update属性设置成为false,那么这个字段,将不被包括在基本的update语句中,修改的时候,将不包括这个字段了.insert同理.dynamic动态SQL语句的配置也是很常用的.下面介绍配置SQL语句的具体属性:<br /><span style="color: rgb(255,0,0)">1)&lt;property&gt;元素 insert属性:设置为false,在insert语句中不包含这个字段,表示永远不会被插入,默认true<br />2)&lt;property&gt;元素 update属性:设置为false,在update语句中不包含这个字段,表示永远不会被修改,默认true<br />3)&lt;class&gt;元素 mutable属性:设置为false就是把所有的&lt;property&gt;元素的update属性设置为了false,说明这个对象不会被更新,默认true<br />4)&lt;property&gt;元素 dynamic-insert属性:设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认false<br />5)&lt;property&gt;元素 dynamic-update属性,设置为true,表示update对象的时候,生成动态的update语句,如果这个字段的值是null就不会被加入到update语句中,默认false<br />6)&lt;class&gt;元素 dynamic-insert属性:设置为true,表示把所有的&lt;property&gt;元素的dynamic-insert属性设置为true,默认false<br />7)&lt;class&gt;元素 dynamic-update属性:设置为true,表示把所有的&lt;property&gt;元素的dynamic-update属性设置为true,默认false</span></p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">Hibernate生成动态SQL语句的消耗的系统资源(比如CPU,内存等)是很小的,所以不会影响到系统的性能,如果表中包含N多字段,建议把dynamic-update属性和insert属性设置为true,这样在插入和修改数据的时候,语句中只包括要插入或者修改的字段.可以节省SQL语句的执行时间,提高程序的运行效率.</p>
<p style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; font: 14px/22px tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">另外一种做法请看如下配置：</p>
<h3 style="widows: 2; text-transform: none; background-color: rgb(239,239,239); font-variant: normal; font-style: normal; text-indent: 0px; font-family: tahoma, 宋体; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="title content-title">Hibernate &lt;property&gt;配置</h3>
<div style="widows: 2; text-transform: none; background-color: rgb(239,239,239); text-indent: 0px; margin: 20px auto; width: 605px; font: 14px/22px tahoma, 宋体; word-wrap: break-word; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" id="content" class="content mod-cs-content text-content clearfix">&lt;property name="name" unique="true" not-null="true" update="false" length="25"/&gt;<br /><br /><span style="color: rgb(255,0,0)">&lt;property&gt;元素 insert属性：设置为false，在insert语句中不包含这个字段，表示永远不会被插入。默认true。<br /><br />&lt;property&gt;元素 update属性：设置为false，在update语句中不包含这个字段，表示永远不会被修改。默认true。</span><br /><br />&lt;class&gt;元素 mutable属性：设置为false，就是把所有的&lt;property&gt;元素的update属性设置为了false，说明这个对象不会被更新。默认true。<br /><br />&lt;property&gt;元素 dynamic-insert属性：设置为true，表示insert对象的时候，生成动态的insert语句，如果这个字段的值是null就不会加入到insert语句当中。默认false<span class="Apple-converted-space">&nbsp;</span><br /><br />&lt;property&gt;元素 dynamic-update属性：设置为true，表示update对象的时候，生成动态的update语句，如果这个字段的值是null就不会被加入到update语句中。默认false<span class="Apple-converted-space">&nbsp;</span><br /><br />&lt;class&gt;元素 dynamic-insert属性：设置为true，表示把所有的&lt;property&gt;元素的dynamic-insert属性设置为true。默认false<span class="Apple-converted-space">&nbsp;</span><br /><br />&lt;class&gt;元素 dynamic-update属性：设置为true，表示把所有的&lt;property&gt;元素的dynamic-update属性设置为true。默认false<br /><br />dynamic-update，如果一个表字段比较多，并且经常只是更新一条记录的一两个字段，避免了过多无用的sql语句，动态更新会更有效。应用程序会增加工作量，但是数据库会减少工作量。在插入和修改数据的时候，语句中只包括要插入或者修改的字段，可以节省SQL语句的执行时间，提高程序的运行效率。</div><img src ="http://www.cppblog.com/xingmuxixi/aggbug/198909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2013-03-29 10:07 <a href="http://www.cppblog.com/xingmuxixi/archive/2013/03/29/198909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#自动实现Dll(OCX)控件注册的两种方法</title><link>http://www.cppblog.com/xingmuxixi/archive/2011/05/10/146134.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Tue, 10 May 2011 11:56:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2011/05/10/146134.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/146134.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2011/05/10/146134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/146134.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/146134.html</trackback:ping><description><![CDATA[<p>尽管MS为我们提供了丰富的.net framework库，我们的程序C#开发带来了极大的便利，但是有时候，一些特定功能的控件库还是需要由第三方提供或是自己编写。<br>当需要用到Dll引用的时候，我们通常会通过&#8220;添加引用&#8221;的方式将它们纳入到项目中，然后就可以像使用自己的类一样方便的使用它们了。<br>但是，有些Dll库(OCX)文件是需要注册到Windows注册表后才能正常添加和使用的。</p>
<p>本文介绍两种为Dll库(OCX)自动注册的方法，为大家提供参考。</p>
<p>首先，大家都知道在Windows的&#8220;运行&#8221;中，输入&#8220;Regsvr32.exe 路径&#8221;这样的方法来手动注册Dll控件(OCX)，显示这种方法对于程序的自动化部署等带来极大的不便，<br>因此，今天我们着重介绍如何用C#实现自动注册。</p>
<p>方法一：调用Regsvr32法</p>
<p>既然可以在运行栏中输入&#8220;Regsvr32.exe 路径&#8221;的方法来注册，那么，一定可以在C#程序中采用同样的方法来调用Regsvr32，以实现注册：</p>
<p>Process p = new Process();<br>p.StartInfo.FileName = "Regsvr32.exe";<br>p.StartInfo.Arguments = "/s C:\\DllTest.dll";//路径中不能有空格<br>p.Start();<br>采用这种方法，注意要添加对命名空间System.Diagnostics的引用：using System.Diagnostics;<br>另外，这种方法有一个不足之处，那就是注册工作是在本程序之外由Regsvr32.exe程序来完成的，系统内不方便知道注册的结果，也不方便对注册过程弹出的对话框进行自定义和控制。<br>这里附Regsvr32的参数说明：(感谢网友伍华聪的提醒)</p>
<p>regsvr32.exe是32位系统下使用的DLL注册和反注册工具，使用它必须通过命令行的方式使用，格式是：</p>
<p>　　regsvr32 [/u] [/s] [/n] [/i[:cmdline]] DLL文件名</p>
<p>　　命令可以在&#8220;开始&#8594;运行&#8221;的文本框中，也可以事先在bat批处理文档中编写好命令。未带任何参数是注册DLL文件功能，其它参数对应功能如下：</p>
<p>　　/u：反注册DLL文件;</p>
<p>　　/s：安静模式(Silent)执行命令，即在成功注册/反注册DLL文件前提下不显示结果提示框。</p>
<p>　　/c：控制端口;</p>
<p>　　/i：在使用/u反注册时调用DllInstall;</p>
<p>　　/n：不调用DllRegisterServer，必须与/i连用。</p>
<p>&nbsp;</p>
<p>方法二：调用DllRegisterServer函数法</p>
<p>&nbsp;研究Regsvr32.exe和Dll文件，我们会发现，其实每个需要注册的文件都包括一个DllRegisterServer()方法，Regsvr32.exe就是通过调用该方法来完成Dll的注册的。<br>知道了这个，我们就可以自己调用DllRegisterServer()来完成注册过程啦。</p>
<p>首先，还得引入外部方法：</p>
<p>[DllImport("DllTest.dll")]<br>public static extern int DllRegisterServer();//注册时用<br>[DllImport("DllTest.dll")]<br>public static extern int DllUnregisterServer();//取消注册时用</p>
<p>接下来就不难啦：int i = DllRegisterServer();<br>if (i &gt;= 0)<br>{<br>&nbsp;&nbsp;&nbsp; //注册成功!<br>}<br>else<br>{<br>&nbsp;&nbsp;&nbsp; //注册失败<br>}<br>取消注册的过程就不应再贴代码啦。<br>&nbsp;</p>
<p>如何对Dll是否已经注册过了做出判断？<br>一般情况下，我们可以将对Dll控件的注册过程放在系统启动的过程中来完成，但是，总不能每次启动都注册一次吧？这样做显然不合理。<br>那么，我们就来判断一下，当前Dll是否已经注册过，如果已注册过，就跳过注册过程。</p>
<p>每一个Dll的注册都会在注册表里记录下有关它本身的资料，如注册路径，唯一ID等。我们这里就是利用它留下的唯一ID号来判断：</p>
<p>RegistryKey rkTest = Registry.ClassesRoot.OpenSubKey("CLSID\\{7713F78A-44DE-42BA-A1F6-3FB0BD6CA63B}\\");<br>if (rkTest == null)<br>{&nbsp;&nbsp;<br>&nbsp;//Dll没有注册，在这里调用DllRegisterServer()吧<br>｝<br>注意要添加对命名空间Microsoft.Win32的引用：using Microsoft.Win32;</p>
<p>其中的&#8220;{7713F78A-44DE-42BA-A1F6-3FB0BD6CA63B}&#8221;就是该Dll的唯一ID啦，每一个Dll文件都会不一样的。</p>
<p>但是，问题又来了，怎么样知道它的唯一ID呢？其实很简单，那就是&#8220;逆向思维&#8221;。<br>我们可先注册这个Dll文件，然后到注册表的&#8220;HKEY_CLASSES_ROOT\CLSID&#8221;分支下&#8220;查找&#8221;Dll的名称或路径，就可以看到这个ID啦。 &nbsp;</p>
<br>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/146134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2011-05-10 19:56 <a href="http://www.cppblog.com/xingmuxixi/archive/2011/05/10/146134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#跨线程调用窗体控件的问题</title><link>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140735.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Sun, 27 Feb 2011 06:06:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140735.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/140735.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/140735.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/140735.html</trackback:ping><description><![CDATA[<p>&nbsp;前段时间遇到跨线程调用窗体控件的问题，其实一句话System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;就可以解决，但感觉会有不稳定因素，因此在网上找了一些相应的文章感觉还不错，第一种用的比较顺手：</p>
<p>(注：在devexpress控件中用DevExpress.Data.CurrencyDataController.DisableThreadingProblemsDetection = true;)</p>
<p>&nbsp;&nbsp;&nbsp; 用户不喜欢反应慢的程序。在执行耗时较长的操作时，使用多线程是明智之举，它可以提高程序 UI 的响应速度，使得一切运行显得更为快速。在 Windows 中进行多线程编程曾经是 C++ 开发人员的专属特权，但是现在，可以使用所有兼容 Microsoft .NET 的语言来编写。</p>
<p>不过Windows 窗体体系结构对线程使用制定了严格的规则。如果只是编写单线程应用程序，则没必要知道这些规则，这是因为单线程的代码不可能违反这些规则。然而，一旦采用多线程，就需要理解 Windows 窗体中最重要的一条线程规则：除了极少数的例外情况，否则都不要在它的创建线程以外的线程中使用控件的任何成员。本规则的例外情况有文档说明，但这样的情况非常少。这适用于其类派生自 System.Windows.Forms.Control 的任何对象，其中几乎包括 UI 中的所有元素。所有的 UI 元素（包括表单本身）都是从 Control 类派生的对象。此外，这条规则的结果是一个被包含的控件（如，包含在一个表单中的按钮）必须与包含它控件位处于同一个线程中。也就是说，一个窗口中的所有控件属于同一个 UI 线程。实际中，大部分 Windows 窗体应用程序最终都只有一个线程，所有 UI 活动都发生在这个线程上。这个线程通常称为 UI 线程。这意味着您不能调用用户界面中任意控件上的任何方法，除非在该方法的文档说明中指出可以调用。该规则的例外情况（总有文档记录）非常少而且它们之间关系也不大。请注意，以下代码是非法的：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Thread myThread;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Form1_Load(object sender, EventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread = new Thread(new ThreadStart(RunsOnWorkerThread));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread.Start();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void RunsOnWorkerThread()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label1.Text = "myThread线程调用UI控件";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>如果您在 .NET Framework 1.0 版本中尝试运行这段代码，也许会侥幸运行成功，或者初看起来是如此。这就是多线程错误中的主要问题，即它们并不会立即显现出来。甚至当出现了一些错误时，在第一次演示程序之前一切看起来也都很正常。但不要搞错 — 我刚才显示的这段代码明显违反了规则，并且可以预见，任何抱希望于&#8220;试运行时良好，应该就没有问题&#8221;的人在即将到来的调试期是会付出沉重代价的。</p>
<p>下面我们来看看有哪些方法可以解决这一问题。</p>
<p>一、System.Windows.Forms.MethodInvoker 类型是一个系统定义的委托，用于调用不带参数的方法。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Thread myThread;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Form1_Load(object sender, EventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread = new Thread(new ThreadStart(RunsOnWorkerThread));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread.Start();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void RunsOnWorkerThread()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MethodInvoker mi = new MethodInvoker(SetControlsProp);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BeginInvoke(mi);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void SetControlsProp()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label1.Text = "myThread线程调用UI控件";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>二、直接用System.EventHandle（可带参数）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Thread myThread;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Form1_Load(object sender, EventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread = new Thread(new ThreadStart(RunsOnWorkerThread));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread.Start();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void RunsOnWorkerThread()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //DoSomethingSlow();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string pList = "myThread线程调用UI控件";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label1.BeginInvoke(new System.EventHandler(UpdateUI), pList);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //直接用System.EventHandler,没有必要自定义委托</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void UpdateUI(object o, System.EventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //UI线程设置label1属性</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label1.Text = o.ToString() + "成功!";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>三、包装 Control.Invoke</p>
<p>虽然第二个方法中的代码解决了这个问题，但它相当繁琐。如果辅助线程希望在结束时提供更多的反馈信息，而不是简单地给出&#8220;Finished!&#8221;消息，则 BeginInvoke 过于复杂的使用方法会令人生畏。为了传达其他消息，例如&#8220;正在处理&#8221;、&#8220;一切顺利&#8221;等等，需要设法向 UpdateUI 函数传递一个参数。可能还需要添加一个进度栏以提高反馈能力。这么多次调用 BeginInvoke 可能导致辅助线程受该代码支配。这样不仅会造成不便，而且考虑到辅助线程与 UI 的协调性，这样设计也不好。对这些进行分析之后，我们认为包装函数可以解决这两个问题。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Thread myThread;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Form1_Load(object sender, EventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread = new Thread(new ThreadStart(RunsOnWorkerThread));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myThread.Start();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void RunsOnWorkerThread()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ////DoSomethingSlow();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 100; i++)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ShowProgress( Convert.ToString(i)+"%", i);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.Sleep(100);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void ShowProgress(string msg, int percentDone)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Wrap the parameters in some EventArgs-derived custom class:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.EventArgs e = new MyProgressEvents(msg, percentDone);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[] pList = { this, e };</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BeginInvoke(new MyProgressEventsHandler(UpdateUI), pList);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private delegate void MyProgressEventsHandler(object sender, MyProgressEvents e);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void UpdateUI(object sender, MyProgressEvents e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lblStatus.Text = e.Msg;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myProgressControl.Value = e.PercentDone;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public class MyProgressEvents : EventArgs</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string Msg;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int PercentDone;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public MyProgressEvents(string msg, int per)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Msg = msg;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PercentDone = per;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p>ShowProgress 方法对将调用引向正确线程的工作进行封装。这意味着辅助线程代码不再担心需要过多关注 UI 细节，而只要定期调用 ShowProgress 即可。</p>
<p>如果我提供一个设计为可从任何线程调用的公共方法，则完全有可能某人会从 UI 线程调用这个方法。在这种情况下，没必要调用 BeginInvoke，因为我已经处于正确的线程中。调用 Invoke 完全是浪费时间和资源，不如直接调用适当的方法。为了避免这种情况，Control 类将公开一个称为 InvokeRequired 的属性。这是&#8220;只限 UI 线程&#8221;规则的另一个例外。它可从任何线程读取，如果调用线程是 UI 线程，则返回假，其他线程则返回真。这意味着我可以按以下方式修改包装： </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void ShowProgress(string msg, int percentDone)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (InvokeRequired)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // As before</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //...</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // We're already on the UI thread just</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // call straight through.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UpdateUI(this, new MyProgressEvents(msg,PercentDone));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/jackey0517/archive/2009/09/08/4533458.aspx">http://blog.csdn.net/jackey0517/archive/2009/09/08/4533458.aspx</a></p>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/140735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2011-02-27 14:06 <a href="http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#中跨线程操作控件时Invoke和BeginInvoke 区别</title><link>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140734.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Sun, 27 Feb 2011 06:05:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140734.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/140734.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/140734.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/140734.html</trackback:ping><description><![CDATA[<p><span style="COLOR: #000000"><span>Control.Invoke 方法 (Delegate)</span><strong>:</strong>在<strong>拥有</strong>此控件的基础窗口句柄的线程上<strong>执行</strong>指定的委托。</span></p>
<p><span style="COLOR: #000000"><span>Control.BeginInvoke 方法 (Delegate)</span> :在<strong>创建</strong>控件的基础句柄所在线程上<strong>异步执行</strong>指定委托。</span></p>
<p>(一）Control的Invoke和BeginInvoke<br>我们要基于以下认识：<br>（1）Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不同的。<br>（2）Control的Invoke和BeginInvoke的参数为delegate，委托的方法是在Control的线程上执行的，也就是我们平时所说的UI线程。<br><br>我们以代码(一)来看(Control的Invoke)<br><span style="COLOR: #0000ff">private delegate void InvokeDelegate();<br>private void InvokeMethod(){<br>&nbsp;&nbsp;&nbsp;//C代码段<br>}<br>private void butInvoke_Click(object sender, EventArgs e) {<br>&nbsp;&nbsp;&nbsp;//A代码段.......<br>&nbsp;&nbsp;&nbsp;this.Invoke(new InvokeDelegate(InvokeMethod));<br>&nbsp;&nbsp;&nbsp;//B代码段......<br>}<br></span>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上<br>A------&gt;C----------------&gt;B<br>解释：(1)A在UI线程上执行完后，开始Invoke，Invoke是同步<br>(2)代码段B并不执行，而是立即在UI线程上执行InvokeMethod方法，即代码段C。<br>(3)InvokeMethod方法执行完后，代码段C才在UI线程上继续执行。<br><br>看看代码(二)，Control的BeginInvoke<br><span style="COLOR: #0000ff">private delegate void BeginInvokeDelegate();<br>private void BeginInvokeMethod(){<br>&nbsp;&nbsp;&nbsp;//C代码段<br>}<br>private void butBeginInvoke_Click(object sender, EventArgs e) {<br>&nbsp;&nbsp;&nbsp;//A代码段.......<br>&nbsp;&nbsp;&nbsp;this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod));<br>&nbsp;&nbsp;&nbsp;//B代码段......<br>}</span><br>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上<br>A-----------&gt;B---------------&gt;C<span style="COLOR: #ff0000">慎重，这个只做参考。。。。。，我也不肯定执行顺序，如果有哪位达人知道的话请告知。</span><br>解释：：(1)A在UI线程上执行完后，开始BeginInvoke，BeginInvoke是异步<br>(2)InvokeMethod方法，即代码段C不会执行，而是立即在UI线程上执行代码段B。<br>(3)代码段B执行完后(就是说butBeginInvoke_Click方法执行完后)，InvokeMethod方法，即代码段C才在UI线程上继续执行。<br><br>由此，我们知道：<br>Control的Invoke和BeginInvoke的委托方法是在主线程，即UI线程上执行的。也就是说如果你的委托方法用来取花费时间长的数据，然后更新界面什么的，千万别在UI线程上调用Control.Invoke和Control.BeginInvoke，因为这些是依然阻塞UI线程的，造成界面的假死。<br><br>那么，这个异步到底是什么意思呢?<br><br>异步是指相对于调用BeginInvoke的线程异步，而不是相对于UI线程异步，你在UI线程上调用BeginInvoke ，当然不行了。－－－－摘自"Invoke和BeginInvoke的真正涵义"一文中的评论。<br>BeginInvoke的原理是将调用的方法Marshal成消息，然后调用Win32 API中的RegisterWindowMessage()向UI窗口发送消息。－－－－摘自"Invoke和BeginInvoke的真正涵义"一文中的评论。<br><br>(二)我们用Thread来调用BeginInvoke和Invoke<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我们开一个线程，让线程执行一些耗费时间的操作，然后再用Control.Invoke和Control.BeginInvoke回到用户UI线程，执行界面更新。<br><br>代码(三)&nbsp; Thread调用Control的Invoke<br><span style="COLOR: #0000ff">private Thread invokeThread;<br>private delegate void invokeDelegate();<br>private void StartMethod(){<br>&nbsp;&nbsp; //C代码段......<br>&nbsp;&nbsp;&nbsp;Control.Invoke(new invokeDelegate(invokeMethod));<br>&nbsp; //D代码段......<br>}<br>private void invokeMethod(){<br>&nbsp; //E代码段<br>}<br>private void butInvoke_Click(object sender, EventArgs e) {<br>&nbsp;&nbsp;&nbsp;//A代码段.......<br>&nbsp;&nbsp; invokeThread = new Thread(new ThreadStart(StartMethod));<br>&nbsp;&nbsp; invokeThread.Start();<br>&nbsp;&nbsp;&nbsp;//B代码段......<br>}</span><br>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上<br>A------&gt;(Start一开始B和<span style="COLOR: #ff0000">StartMethod的</span><span style="COLOR: #ff0000">C</span>就同时执行)----&gt;(<span style="COLOR: #ff0000">C</span>执行完了，不管B有没有执行完，invokeThread把消息封送(invoke)给UI线程，然后自己等待)----&gt;UI线程处理完<span style="COLOR: #0000ff">butInvoke_Click<span style="COLOR: #000000">消息后，处理invokeThread封送过来的消息，执行invokeMethod方法，即代码段E，处理往后UI线程切换到invokeThread线程。<br>这个Control.Invoke是相对于invokeThread线程同步的，阻止了其运行。<br><img src="http://hiphotos.baidu.com/pzy4447/pic/item/211d14899583489efc1f10b0.jpg" width=958 height=610><br>解释：<br>1。UI执行A<br>2。UI开线程InvokeThread，B和C同时执行，B执行在线程UI上，C执行在线程invokeThread上。<br>3。invokeThread封送消息给UI，然后自己等待，UI处理完消息后，处理invokeThread封送的消息，即代码段E<br>4。UI执行完E后，转到线程invokeThread上，invokeThread线程执行代码段D<br><br>代码(四)&nbsp; Thread调用Control的BeginInvoke<br><span style="COLOR: #0000ff">private Thread beginInvokeThread;<br>private delegate void beginInvokeDelegate();<br>private void StartMethod(){<br>&nbsp;&nbsp; //C代码段......<br>&nbsp;&nbsp;&nbsp;Control.BeginInvoke(new beginInvokeDelegate(beginInvokeMethod));<br>&nbsp; //D代码段......<br>}<br>private void beginInvokeMethod(){<br>&nbsp; //E代码段<br>}<br>private void butBeginInvoke_Click(object sender, EventArgs e) {<br>&nbsp;&nbsp;&nbsp;//A代码段.......<br>&nbsp;&nbsp; beginInvokeThread = new Thread(new ThreadStart(StartMethod));<br>&nbsp;&nbsp; beginInvokeThread .Start();<br>&nbsp;&nbsp;&nbsp;//B代码段......<br>}<br></span>你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上<br>A在UI线程上执行-----&gt;beginInvokeThread线程开始执行，UI继续执行代码段B，并发地invokeThread执行代码段C--------------&gt;不管UI有没有执行完代码段B，这时beginInvokeThread线程把消息封送给UI，单自己并不等待，继续向下执行--------&gt;UI处理完<span style="COLOR: #0000ff">butBeginInvoke_Click<span style="COLOR: #000000">消息后，处理beginInvokeThread线程封送过来的消息。<br></span></span></span></span></p>
<p><span style="COLOR: #0000ff"><span style="COLOR: #000000"><span style="COLOR: #0000ff"><span style="COLOR: #000000"><img src="http://hiphotos.baidu.com/pzy4447/pic/item/b4f93ed1c882a179960a16b0.jpg" width=802 height=466><br>解释：<br>1。UI执行A<br>2。UI开线程beginInvokeThread，B和C同时执行，B执行在线程UI上，C执行在线程beginInvokeThread上。<br>3。beginInvokeThread封送消息给UI，然后自己继续执行代码D，UI处理完消息后，处理invokeThread封送的消息，即代码段E<br><span style="COLOR: #ff0000">有点疑问：如果UI先执行完毕，是不是有可能过了段时间beginInvokeThread才把消息封送给UI，然后UI才继续执行封送的消息E。如图浅绿的部分。</span><br><br><br>Control的BeginInvoke是相对于调用它的线程，即beginInvokeThread相对是异步的。<br>因此，我们可以想到。如果要异步取耗费长时间的数据，比如从数据库中读大量数据，我们应该这么做。<br></span></span>(1)如果你想阻止调用线程，那么调用代码(三)，代码段D删掉，C改为耗费长时间的操作，因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。<br>(2)如果你不想阻止调用线程，那么调用代码(四)，代码段D删掉，C改为耗费长时间的操作，因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。<br></span></span></p>
<p><span style="COLOR: #0000ff"><span style="COLOR: #000000">==============================以上是原帖=============================</span></span></p>
<p><span style="COLOR: #0000ff"><span style="COLOR: #000000">&nbsp;&nbsp; &nbsp; &nbsp; 我认为上面&#8220;代码二&#8221;给出的运行结果是正确的。我来做个总结：委托的同步和异步的区别，只有在多线程中才能体现的出来。以跨线程操作控件为例，采用异步时则向UI线程发送一个消息，然后该干嘛干嘛，这个消息什么时候会得到相应是不一定的。如果采用同步执行则向UI线程发送一个消息，然后一直等待，直到这个消息被相应后才接着向下执行。也就是说，在不跨线程的时候(在UI线程中操作控件)同步和异步是没有区别的，当然，不跨线程就可以直接操作控件了，没必要利用委托。</span></span></p>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/140734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2011-02-27 14:05 <a href="http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个总经理的11个经典面试问题</title><link>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140732.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Sun, 27 Feb 2011 05:11:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140732.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/140732.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140732.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/140732.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/140732.html</trackback:ping><description><![CDATA[<p>一个总经理的11个经典面试问题</p>
<p>孙子曰：&#8220;兵者，国之大事，死生之地，存亡之道，不可不察也。&#8221;当代社会，应聘一个岗位，犹如与敌国打仗。准备打仗的时间与打仗时间之比应为10：1，甚至是100：1。故，我们不得不深究也。</p>
<p>最近，自己面试了上百个大学生，觉得他们在面试的心态和技能方面急需提高，以便顺利通过这一关，进入人生的第一个职业。面试过程中，我会向应聘者发问，而应聘者的回答将成为我考虑是否接受他的重要依据。对应聘者而言，了解这些问题背后的目的至关重要。</p>
<p>问题一：&#8220;请你自我介绍一下&#8221;</p>
<p>这个问题的面试方法是：应聘者站起来用五分钟的时间面对大家进行演讲。</p>
<p>我的目的是：了解应聘者的心理承受能力、逻辑思维能力、演讲能力，而他的生平介绍却是其次的，因为，我们在他的简历中已经对其有所了解。</p>
<p>应聘者应该做到：1、介绍内容要与个人简历相一致。 2、表述方式上尽量口语化。 3、要切中要害，不谈无关、无用的内容。 4、条理要清晰，层次要分明。5、要有训练有素的演讲语气和肢体语言，这是最重要的。</p>
<p>问题二：&#8220;你有什么业余爱好？&#8221;</p>
<p>我的目的是：了解应聘者的性格、观念、心态、思维的深度等。为了深入了解应聘者的爱好程度，我会提出更加深刻的问题，比如，应聘者喜欢流行音乐，我就会问相关的问题：&#8220;您什么时候开始喜欢的？您最喜欢哪个歌手？她的演唱风格如何？她的成名曲是哪一首？您最喜欢她的哪一首歌曲？为什么？&#8221;一个真正有这方面业余爱好的应聘者应该对答如流，遗憾的是，许多应聘者不能做到。</p>
<p>有的应聘者喜欢读书，我的相关问题就更加尖锐：&#8220;您最喜欢哪一位作家？您最喜欢这个作家的哪一本书？这本书的中心思想是什么？您阅读了这本书后有什么感悟？对人生的启示又是什么？&#8221;能够应答这类问题的应聘者寥寥无几。</p>
<p>应聘者应该做到：1、事先做好这方面的准备。2、 最好不要说自己没有业余爱好。 3、 不要说自己有那些庸俗的、令人感觉不好的爱好。</p>
<p>问题三：&#8220;谈谈你的缺点&#8221;</p>
<p>我的目的是：了解应聘者是否认真思考过自己，分析过自己，反省过自己。如果一个人能认清自己的缺点，并有改进的愿望和方法，他可能是一个不可多得的人才。</p>
<p>应聘者应该做到：1、 不宜说自己没有缺点，因为人一定有缺点的，除非是神。2、不宜说出严重影响所应聘工作的缺点。 3、对于自己真正的缺点，就认真对其进行剖析，并用积极的心态去面对，去修炼。</p>
<p>问题四：&#8220;举一个人生中最失败的经历&#8221;</p>
<p>我的目的是：了解应聘者的胆量和勇气，是否陷入了选择性知觉的陷阱，是否进行了深刻的反省，是否接受了深刻的教训。</p>
<p>应聘者应该做到： 1、 不宜说自己没有失败的经历。2、 宜说明失败之前自己曾信心白倍、尽心尽力。 3、 明确说明失败是主要由主观原因导致的。 4、 失败后自己曾做了深刻的反省，很快振作起来，以更加饱满的热情面对以后的学习或工作。</p>
<p>问题五：&#8220;你为什么选择我们公司？&#8221;</p>
<p>我的目的是：了解应聘者求职的动机、愿望以及对此项工作的态度。我十分欣赏对我公司很了解的应聘者。</p>
<p>应聘者应该做到：1、 建议从行业、企业和岗位这三个角度来回答。 2、 参考答案——&#8220;我十分看好贵公司所在的行业，我认为贵公司十分重视人才，而且这项工作很适合我，相信自己一定能做好。&#8221;</p>
<p>问题六：&#8220;对这项工作，你有哪些可预见的困难？&#8221;</p>
<p>我的目的是：应聘者的预测能力，并有应对方法。绝大多数的应聘者做不到。</p>
<p>应聘者应该做到： 1、 从技术、知识、经验等方面预见到的困难。2、说出自己对困难所持有的态度：&#8220;工作中出现一些困难是正常的，也是难免的，但是只要有坚忍不拔的毅力、勤奋的学习态度，良好的合作精神以及事前周密而充分的准备，任何困难都是可以克服的。&#8221;</p>
<p>问题七：&#8220;在工作中，与上级意见不一致，你将怎么办？&#8221;</p>
<p>我的目的是：了解应聘者的执行力，人际关系的沟通能力和协调能力，对工作的责任性。</p>
<p>应聘者应该做到： 1、首先给上级以必要的、私下的解释和提醒，在无效的情况下，又不会给公司造成重大损失，我会服从上级的意见。 2、 如果上级的决定会给公司造成重大损失，而我的解释和提醒无效时，我希望能向更高层领导反映。</p>
<p>问题八：&#8220;我们为什么要录用你？&#8221;</p>
<p>我的目的是：应聘者是否能够站在招聘单位的角度来回答，善解人意。</p>
<p>应聘者应该做到：1、企业会录用这样的应聘者：基本符合条件、对这份工作感兴趣、有足够的信心。 2、说出自己的观点：&#8220;我符合贵公司的招聘条件，凭我目前掌握的知识、技能、高度的责任感、良好的适应能力及学习能力，完全能胜任这份工作。我十分希望能为贵公司服务，如果贵公司给我这个机会，我一定能成为贵公司的栋梁！&#8221;</p>
<p>问题九：&#8220;你是应届毕业生，缺乏经验，如何能胜任这项工作？&#8221;</p>
<p>我的目的是：我并不真正在乎&#8220;经验&#8221;，关键是应聘者的心态，是否有克服自身困难的信心和决心，工作是否有责任性。</p>
<p>应聘者应该做到：1、 对这个问题的回答最好要体现出应聘者的诚恳、机智、果敢及敬业。 2、说出自己的观点：&#8220;作为应届毕业生，在工作经验方面的确会有所欠缺，因此在读书期间，我一直利用各种机会在这个行业里做兼职。我也发现，实际工作远比书本知识丰富、复杂。但我有较强的责任心、适应能力和学习能力，而且比较勤奋，所以在兼职中均能圆满完成各项工作，从中获取的经验也令我受益非浅。请贵公司放心，学校所学及兼职的工作经验使我一定能胜任这个职位。&#8221;</p>
<p>问题十：&#8220;你希望与什么样的上级共事？&#8221;</p>
<p>我的目的是：通过应聘者对上级的&#8220;希望&#8221;可以判断出应聘者对自我要求的意识，这既上一个陷阱，又上一次机会。</p>
<p>应聘者应该做到：1、最好回避对上级具体的希望，多谈对自己的要求。 2、 作为刚步入社会的新人，我应该多要求自己尽快熟悉环境、适应环境，而不应该对环境提出什么要求，只要能发挥我的专长就可以了。</p>
<p>问题十一：&#8220;您在前一家公司的离职原因是什么？&#8221;</p>
<p>我的目的是：应聘者是有感恩的心态，还是有仇恨的心态。特别鄙视那些应聘者，他们用极其不良的心态来贬低自己离职的公司。</p>
<p>应聘者应该做到：1、避免把&#8220;离职原因&#8221;说得太详细、太具体。2、 不能掺杂主观的负面感受，如&#8220;太幸苦&#8221;、&#8220;人际关系复杂&#8221;、&#8220;管理太混乱&#8221;、&#8220;公司不重视人才&#8221;、&#8220;公司排斥我们某某的员工&#8221;等。 3、但也不能躲闪、回避，如&#8220;想换换环境&#8221;、&#8220;个人原因&#8221;等。 4、不能涉及自己负面的人格特征，如不诚实、懒惰、缺乏责任感、不随和等。 5、尽量使解释的理由为应聘者个人形象添彩，如&#8220;我离职是因为这家公司倒闭。我在公司工作了三年多，有较深的感情。从去年始，由于市场形势突变，公司的局面急转直下。到眼下这一步我觉得很遗憾，但还是要面对的，所以，我想重新寻找能发挥我能力的舞台。&#8221;</p>
<p>同一个面试问题并非只有一个答案，而同一个答案并不是在任何面试场合都有效，关键在于应聘者掌握了规律后，对面试的具体情况进行把握，有意识地揣摩面试官提出问题的心理背景，然后投其所好。</p>
<p>最后，我要强调最重要的一点，就是应聘者的职业道德。有一个应聘故事很能说明问题。</p>
<p>小城中最大的一家外商独资企业招聘1名技术人员的消息不胫而走，该岗位的待遇是月工资5000元，工资奖金除外，每年还可以到大洋彼岸风光一次。所以，报考者蜂拥而至。</p>
<p>七月流火， 某厂的高工坐在闷罐似的考场里，蒸腾的暑气加上躁热的心情，热汗淋漓。但是，面对考题他并不怵，外文、专业技术类考题都答得十分圆满。惟有第二张考卷的两道怪题令他头疼： "您所在的企业或曾任职过的企业经营成功的诀窍是什么?技术秘密是什么?"</p>
<p>这类题对于曾在企业搞过技术的应考者并不难，可高工手中的笔却始终高悬着，捏来攥去，迟迟落不下去。多年的职业道德在约束着他：&#8220;厂里的数百名职工还在惨淡经营，我怎能为了自己的饭碗而砸大家的饭碗呢? &#8221;他心中似翻江倒海，毅然挥笔在考卷上写下4个大字：&#8220;无可奉告。&#8221;</p>
<p>高工拖着沉重的步子向家里移动着，进门后，妻子一再追问，他才道出了答题的苦衷。全家人默默无语。</p>
<p>正当高工连日奔波，另谋职业之际，石破天惊，外商独资企业发来了录用通知。高工技压群雄，白卷夺冠，众议纷纷，成为小城一大新闻。</p>
<p>高工的职业道德多高啊！所谓职业道德，就是同人们的职业活动紧密联系的符合职业特点所要求的道德准则、道德情操与道德品质的总和，它既是对本职人员在职业活动中行为的要求，同时又是职业对社会所负的道德责任与义务。</p>
<p>为什么洁身自爱的人受人尊敬？因为他们不拿原则进行交易。透支职业道德就是拿原则做交易，这样的人和战场上的叛徒一样可怕，随时都会成为不安全隐患。因此，在你职业生涯中一定要时刻牢记：你要像保护你的生命一样遵守职业道德，永远不要犯原则性错误。<br>&nbsp;</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/andylin02/archive/2009/10/26/4728891.aspx">http://blog.csdn.net/andylin02/archive/2009/10/26/4728891.aspx</a></p>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/140732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2011-02-27 13:11 <a href="http://www.cppblog.com/xingmuxixi/archive/2011/02/27/140732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据存储</title><link>http://www.cppblog.com/xingmuxixi/archive/2010/03/17/109863.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Tue, 16 Mar 2010 17:16:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2010/03/17/109863.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/109863.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2010/03/17/109863.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/109863.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/109863.html</trackback:ping><description><![CDATA[大家都知道数据在计算机中都是按字节来储存了，1个字节等于8位（1Byte=8bit），而计算机只能识别0和1这两个数，所以根据排列，1个字节能代表256种不同的信息，即28（0和1两种可能，8位排列），比如定义一个字节大小的无符号整数（unsigned char），那么它能表示的是0～255（0~28-1）这些数，一共是256个数，因为，前面说了，一个字节只能表示256种不同的信息。别停下，还是一个字节的无符号整数，我们来进一步剖析它，0是这些数中最小的一个，我们先假设它在计算机内部就用8位二进制表示为00000000（从理论上来说也可以表示成其他不同的二进制码，只要这256个数每个数对应的二进制码都不相同就可以了），再假设1表示为00000001，2表示为00000010，3 表示为00000011，依次类推，那么最大的那个数255在8位二进制中就表示为最大的数11111111，然后，我们把这些二进制码换算成十进制看看，会发现刚好和我们假设的数是相同的，而事实上，在计算机中，无符号的整数就是按这个原理来储存的，所以告诉你一个无符号的整数的二进制码，你就可以知道这个数是多少，而且知道在计算机中，这个数本身就是以这个二进制码来储存的。比如我给你一个2个字节大小的二进制码，首先声明它表示的是无符号的整数： 00000000 00000010，我们把前面的0省略，换算一下，它表示的也是数值2，和前面不同的是，它占了2个字节的内存。不同的类型占的内存空间不同，如在我的电脑中char是1个字节，int是4个字节，long是8个字节（你的可能不同，这取决于不同的计算机设置），它们的不同之处仅仅是内存大的能表示的不同的信息多些，也就是能表示的数范围更大些（unsigned int能表示的范围是0~28*4-1），至于怎么算，其实都是一样的，直接把二进制与十进制相互转换，二进制就是它在计算机中的样子，十进制就是我们所表示的数。啊哈，原来这些都是可以计算的呀，我曾经还以为不同的计算机储存的原理是不同的，取决于商家的喜好呢，呵呵。说了这么多怎么还没有提到原码、反码和补码呀，别急别急，心急吃不了热豆腐，呵呵，因为无符号的整数根本就没有原码、反码和补码。（啊，那不是被欺骗了，5555````我告诉妈妈去，哥哥欺负我）都说了别急嘛，你就不想想我说了这么半天的无符号整数，那么有符号的整数怎么办啊？<br><br>呵呵，对，只有有符号的整数才有原码、反码和补码的！其他的类型一概没有。虽然我们也可以用二进制中最小的数去对应最小的负数，最大的也相对应，但是那样不科学，下面来说说科学的方法。还是说一个字节的整数，不过这次是有符号的啦，1个字节它不管怎么样还是只能表示256个数，因为有符号所以我们就把它表示成范围：-128-127。它在计算机中是怎么储存的呢？可以这样理解，用最高位表示符号位，如果是0表示正数，如果是1表示负数，剩下的7位用来储存数的绝对值的话，能表示27个数的绝对值，再考虑正负两种情况，27*2还是256个数。首先定义0在计算机中储存为00000000，对于正数我们依然可以像无符号数那样换算，从00000001到01111111依次表示1到127。那么这些数对应的二进制码就是这些数的原码。到这里很多人就会想，那负数是不是从10000001到11111111依次表示-1到-127，那你发现没有，如果这样的话那么一共就只有255个数了，因为10000000 的情况没有考虑在内。实际上，10000000在计算机中表示最小的负整数，就是这里的-128，而且实际上并不是从10000001到11111111 依次表示-1到-127，而是刚好相反的，从10000001到11111111依次表示-127到-1。负整数在计算机中是以补码形式储存的，补码是怎么样表示的呢，这里还要引入另一个概念——反码，所谓反码就是把负数的原码（负数的原码和和它的绝对值所对应的原码相同，简单的说就是绝对值相同的数原码相同）各个位按位取反，是1就换成0，是0就换成1，如-1的原码是00000001，和1的原码相同，那么-1的反码就是11111110，而补码就是在反码的基础上加1，即-1的补码是11111110+1=11111111，因此我们可以算出-1在计算机中是按11111111储存的。总结一下，计算机储存有符号的整数时，是用该整数的补码进行储存的，0的原码、补码都是0，正数的原码、补码可以特殊理解为相同，负数的补码是它的反码加1。下面再多举几个例子，来帮助大家理解！<br><br>十进制 &#8594; 二进制 （怎么算？要是不知道看计算机基础的书去）<br>47 &#8594; 101111<br><br>有符号的整数 原码 反码 补码<br>47 00101111 11010000 00101111（正数补码和原码相同）<br>－47 00101111 11010000 11010001（负数补码是在反码上加1）<br><br>再举个例子，学C语言的同学应该做过这道题：<br>把－1以无符号的类型输出，得什么结果？（程序如下）<br><br>#include&lt;iostream.h&gt;<br>void main()<br>{<br>short int n=-1;<br>cout&lt;&lt;(unsigned short int)n&lt;&lt;endl;<br>}<br><br>首先在我的电脑中short int类型的储存空间是2个字节，你的可能不同，我说过，这取决于你的计算机配置。它能储存28*2＝65536个不同的数据信息，如果是无符号那么它的范围是0~65535（0~216-1），如果是有符号，那么它的范围是-32768~32767（-215~215-1）。这道题目中，开始n是一个有符号的短整型变量，我们给它赋值为-1，根据我们前面所说的，它在计算机中是以补码11111111 11111111储存的，注意前面说了是2个字节。如果把它强制为无符号的短整型输出的话，那么我们就把刚才的二进制把看成无符号的整型在计算机中储存的形式，对待无符号的整型就没有什么原码、反码和补码的概念了，直接把11111111 11111111转化成十进制就是65535，其实我们一看都是一就知道它是范围中最大的一个数了。呵呵，就这么简单。你个把上面的源代码编译运行看看，如果你的电脑short int也是两个字节，那就会和我得一样的结果。你可以先用这个语句看看：cout&lt;&lt;sizeof(short int)&lt;&lt;endl;看看你的电脑里的短整型占多少的储存空间，也可以用sizeof来看其它任何类型所分配的储存空间。<br><br>最后提醒一句，关于数据如何在计算机中储存的，这里只适用于整型的数据，对于浮点型的是另一种方式，这里我们暂时就不深究了
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/109863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2010-03-17 01:16 <a href="http://www.cppblog.com/xingmuxixi/archive/2010/03/17/109863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unicode:宽字节字符集</title><link>http://www.cppblog.com/xingmuxixi/archive/2010/03/06/109007.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Fri, 05 Mar 2010 16:59:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2010/03/06/109007.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/109007.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2010/03/06/109007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/109007.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/109007.html</trackback:ping><description><![CDATA[<font face=宋体>1. 如何取得一个既包含单字节字符又包含双字节字符的字符串的字符个数？<br>可以调用Microsoft Visual C++的运行期库包含函数_mbslen来操作多字节(既包括单字节也包括双字节)字符串。<br>调用strlen函数，无法真正了解字符串中究竟有多少字符，它只能告诉你到达结尾的0之前有多少个字节。 </font>
<p>2. 如何对DBCS(双字节字符集)字符串进行操作？<br>函数 描述<br>PTSTR CharNext ( LPCTSTR ); 返回字符串中下一个字符的地址<br>PTSTR CharPrev ( LPCTSTR, LPCTSTR )； 返回字符串中上一个字符的地址<br>BOOL IsDBCSLeadByte( BYTE )； 如果该字节是DBCS字符的第一个字节，则返回非0值
<p>3. 为什么要使用Unicode？<br>(1) 可以很容易地在不同语言之间进行数据交换。<br>(2) 使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。<br>(3) 提高应用程序的运行效率。<br>Windows 2000是使用Unicode从头进行开发的，如果调用任何一个Windows函数并给它传递一个ANSI字符串，那么系统首先要将字符串转换成Unicode，然后将Unicode字符串传递给操作系统。如果希望函数返回ANSI字符串，系统就会首先将Unicode字符串转换成ANSI字符串，然后将结果返回给你的应用程序。进行这些字符串的转换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序，就能够使你的应用程序更加有效地运行。<br>Windows CE 本身就是使用Unicode的一种操作系统，完全不支持ANSI Windows函数<br>Windows 98 只支持ANSI，只能为ANSI开发应用程序。<br>Microsoft公司将COM从16位Windows转换成Win32时，公司决定需要字符串的所有COM接口方法都只能接受Unicode字符串。
<p>4. 如何编写Unicode源代码？<br>Microsoft公司为Unicode设计了WindowsAPI，这样，可以尽量减少代码的影响。实际上，可以编写单个源代码文件，以便使用或者不使用Unicode来对它进行编译。只需要定义两个宏(UNICODE和_UNICODE)，就可以修改然后重新编译该源文件。<br>_UNICODE宏用于C运行期头文件，而UNICODE宏则用于Windows头文件。当编译源代码模块时，通常必须同时定义这两个宏。
<p>5. Windows定义的Unicode数据类型有哪些？<br>数据类型 说明<br>WCHAR Unicode字符<br>PWSTR 指向Unicode字符串的指针<br>PCWSTR 指向一个恒定的Unicode字符串的指针<br>对应的ANSI数据类型为CHAR，LPSTR和LPCSTR。<br>ANSI/Unicode通用数据类型为TCHAR，PTSTR,LPCTSTR。
<p>6. 如何对Unicode进行操作？<br>字符集 特性 实例<br>ANSI 操作函数以str开头 strcpy<br>Unicode 操作函数以wcs开头 wcscpy<br>MBCS 操作函数以_mbs开头 _mbscpy<br>ANSI/Unicode 操作函数以_tcs开头 _tcscpy(C运行期库)<br>ANSI/Unicode 操作函数以lstr开头 lstrcpy(Windows函数)<br>所有新的和未过时的函数在Windows2000中都同时拥有ANSI和Unicode两个版本。ANSI版本函数结尾以A表示；Unicode版本函数结尾以W表示。Windows会如下定义：<br>#ifdef UNICODE<br>#define CreateWindowEx CreateWindowExW<br>#else<br>#define CreateWindowEx CreateWindowExA<br>#endif // !UNICODE
<p>7. 如何表示Unicode字符串常量？<br>字符集 实例<br>ANSI "string"<br>Unicode L"string"<br>ANSI/Unicode T("string")或_TEXT("string")if( szError[0] == _TEXT('J') ){}
<p>8. 为什么应当尽量使用操作系统函数？<br>这将有助于稍稍提高应用程序的运行性能，因为操作系统字符串函数常常被大型应用程序比如操作系统的外壳进程Explorer.exe所使用。由于这些函数使用得很多，因此，在应用程序运行时，它们可能已经被装入RAM。<br>如：StrCat，StrChr，StrCmp和StrCpy等。
<p>9. 如何编写符合ANSI和Unicode的应用程序？<br>(1) 将文本串视为字符数组，而不是chars数组或字节数组。<br>(2) 将通用数据类型(如TCHAR和PTSTR)用于文本字符和字符串。<br>(3) 将显式数据类型(如BYTE和PBYTE)用于字节、字节指针和数据缓存。<br>(4) 将TEXT宏用于原义字符和字符串。<br>(5) 执行全局性替换(例如用PTSTR替换PSTR)。<br>(6) 修改字符串运算问题。例如函数通常希望在字符中传递一个缓存的大小，而不是字节。这意味着不应该传递sizeof(szBuffer),而应该传递(sizeof(szBuffer)/sizeof(TCHAR)。另外，如果需要为字符串分配一个内存块，并且拥有该字符串中的字符数目，那么请记住要按字节来分配内存。这就是说，应该调用<br>malloc(nCharacters *sizeof(TCHAR)),而不是调用malloc(nCharacters)。
<p>10. 如何对字符串进行有选择的比较？<br>通过调用CompareString来实现。<br>标志 含义<br>NORM_IGNORECASE 忽略字母的大小写<br>NORM_IGNOREKANATYPE 不区分平假名与片假名字符<br>NORM_IGNORENONSPACE 忽略无间隔字符<br>NORM_IGNORESYMBOLS 忽略符号<br>NORM_IGNOREWIDTH 不区分单字节字符与作为双字节字符的同一个字符<br>SORT_STRINGSORT 将标点符号作为普通符号来处理
<p>11. 如何判断一个文本文件是ANSI还是Unicode？<br>判断如果文本文件的开头两个字节是0xFF和0xFE，那么就是Unicode，否则是ANSI。
<p>12. 如何判断一段字符串是ANSI还是Unicode？<br>用IsTextUnicode进行判断。IsTextUnicode使用一系列统计方法和定性方法，以便猜测缓存的内容。由于这不是一种确切的科学方法，因此 IsTextUnicode有可能返回不正确的结果。
<p>13. 如何在Unicode与ANSI之间转换字符串？<br>Windows函数MultiByteToWideChar用于将多字节字符串转换成宽字符串；函数WideCharToMultiByte将宽字符串转换成等价的多字节字符串。</p>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/109007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2010-03-06 00:59 <a href="http://www.cppblog.com/xingmuxixi/archive/2010/03/06/109007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>  .net中对象序列化技术浅谈[转]</title><link>http://www.cppblog.com/xingmuxixi/archive/2010/02/02/107028.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Tue, 02 Feb 2010 10:01:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2010/02/02/107028.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/107028.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2010/02/02/107028.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/107028.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/107028.html</trackback:ping><description><![CDATA[<p>序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化，它将流转换为对象。这两个过程结合起来，可以轻松地存储和传输数据。例如，可以序列化一个对象，然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。反之，反序列化根据流重新构造对象。此外还可以将对象序列化后保存到本地，再次运行的时候可以从本地文件中&#8220;恢复&#8221;对象到序列化之前的状态。<br>在.net中有提供了几种序列化的方式：<br>二进制序列化<br>XML序列化<br>SOAP序列化</p>
<p>二进制序列化<br>所谓二进制序列化，指的是对象序列化之后是二进制形式的。二进制序列化是通过BinaryFormatter类来实现的，这个类位于System.Runtime.Serialization.Formatters.Binary命名空间下。</p>
<p>XML序列化<br>所谓XML序列化，是指对象序列化之后的结果是XML形式的。保存XML序列化是通过XmlSerializer 类来实现的， 这个类位于System.Xml.Serialization命名空间下。</p>
<p>SOAP序列化<br>所谓SOAP序列化是指对象序列化之后的结果符合SOAP协议，也就是可以通过SOAP协议传输（不知道SOAP协议？百度一下吧）。SOAP序列化是通过SoapFormatter类来实现的，这个类位于System.Runtime.Serialization.Formatters.Soap命名空间下，并且需要注意需要手动添加对这个命名空间的引用，如下图所示：<br>&nbsp;</p>
<p>下面编写一个类用于序列化和反序列化，这个类的代码如下：</p>
<p>using System;&nbsp;&nbsp; <br>using System.Collections.Generic;&nbsp;&nbsp; <br>using System.Text;&nbsp;&nbsp; <br>&nbsp; <br>namespace MySerializeDemo&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; [Serializable]&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// 要序列化的对象&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// 作者：周公&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// 编写时间：2009-03-10&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public class MyObject&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //[NonSerialized]&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string name;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private DateTime birthday;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string homePlace;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 出生地&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string HomePlace&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return homePlace; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { homePlace = value; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 生日&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public DateTime Birthday&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return birthday; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { birthday = value; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 姓名&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string Name&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return name; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { name = value; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 年龄&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int Age&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return DateTime.Now.Year - birthday.Year; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// override了ToString()方法&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;returns&gt;&lt;/returns&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public override string ToString()&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Format("姓名：{0},生日：{1},出生地：{2},年龄：{3}",name,birthday,homePlace,Age);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <br>using System;<br>using System.Collections.Generic;<br>using System.Text;</p>
<p>namespace MySerializeDemo<br>{<br>&nbsp;&nbsp;&nbsp; [Serializable]<br>&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp; /// 要序列化的对象<br>&nbsp;&nbsp;&nbsp; /// 作者：周公<br>&nbsp;&nbsp;&nbsp; /// 编写时间：2009-03-10<br>&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp; public class MyObject<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //[NonSerialized]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string name;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private DateTime birthday;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string homePlace;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 出生地<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string HomePlace<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return homePlace; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { homePlace = value; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 生日<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public DateTime Birthday<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return birthday; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { birthday = value; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 姓名<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string Name<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return name; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { name = value; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 年龄<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int Age<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return DateTime.Now.Year - birthday.Year; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// override了ToString()方法<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;returns&gt;&lt;/returns&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public override string ToString()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Format("姓名：{0},生日：{1},出生地：{2},年龄：{3}",name,birthday,homePlace,Age);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; }<br>} <br>下面是分别用上面的三个类进行序列化和反序列化的代码：</p>
<p>view plaincopy to clipboardprint?<br>using System;&nbsp;&nbsp; <br>using System.Collections.Generic;&nbsp;&nbsp; <br>using System.Text;&nbsp;&nbsp; <br>using System.IO;&nbsp;&nbsp; <br>using System.Runtime.Serialization.Formatters;&nbsp;&nbsp; <br>using System.Runtime.Serialization.Formatters.Binary;&nbsp;&nbsp; <br>using System.Runtime.Serialization.Formatters.Soap;&nbsp;&nbsp; <br>using System.Xml.Serialization;&nbsp;&nbsp; <br>&nbsp; <br>namespace MySerializeDemo&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; class Program&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj = new MyObject();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.Birthday = new DateTime(1979, 11, 7);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.HomePlace = "湖北";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.Name = "周公";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("========使用BinaryFormatter类进行序列化和反序列化。====");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinarySerialize(obj);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryDeserialize("C:\\MyObject.dat");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("========使用SoapFormatter类进行序列化和反序列化。====");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SOAPSerialize(obj);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SOAPDeserialize("C:\\MyObject.soap");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("========使用XmlSerializer类进行序列化和反序列化。====");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMLSerialize(obj);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMLDeserialize("C:\\MyObject.xml");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制序列化对象&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="obj"&gt;&lt;/param&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void BinarySerialize(MyObject obj)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream("C:\\MyObject.dat", FileMode.Create, FileAccess.Write))&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryFormatter formater = new BinaryFormatter();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formater.Serialize(stream, obj);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被序列化。" + obj.ToString());&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制反序列化&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="fileName"&gt;&lt;/param&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void BinaryDeserialize(string fileName)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryFormatter formater = new BinaryFormatter();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj=(MyObject)formater.Deserialize(stream);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被反序列化。" + obj.ToString());&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制序列化对象&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="obj"&gt;&lt;/param&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void SOAPSerialize(MyObject obj)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream("C:\\MyObject.soap", FileMode.Create, FileAccess.Write))&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SoapFormatter formater = new SoapFormatter();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formater.Serialize(stream, obj);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被序列化。" + obj.ToString());&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制反序列化&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="fileName"&gt;&lt;/param&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void SOAPDeserialize(string fileName)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SoapFormatter formater = new SoapFormatter();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj = (MyObject)formater.Deserialize(stream);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被反序列化。" + obj.ToString());&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// XML序列化&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="obj"&gt;&lt;/param&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void XMLSerialize(MyObject obj)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream("C:\\MyObject.xml", FileMode.Create, FileAccess.Write))&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlSerializer serializer = new XmlSerializer(typeof(MyObject));&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; serializer.Serialize(stream, obj);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被序列化。" + obj.ToString());&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// XML反序列化&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="fileName"&gt;&lt;/param&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void XMLDeserialize(string fileName)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlSerializer serializer = new XmlSerializer(typeof(MyObject));&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj = (MyObject)serializer.Deserialize(stream);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被反序列化。" + obj.ToString());&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <br>using System;<br>using System.Collections.Generic;<br>using System.Text;<br>using System.IO;<br>using System.Runtime.Serialization.Formatters;<br>using System.Runtime.Serialization.Formatters.Binary;<br>using System.Runtime.Serialization.Formatters.Soap;<br>using System.Xml.Serialization;</p>
<p>namespace MySerializeDemo<br>{<br>&nbsp;&nbsp;&nbsp; class Program<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj = new MyObject();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.Birthday = new DateTime(1979, 11, 7);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.HomePlace = "湖北";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.Name = "周公";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("========使用BinaryFormatter类进行序列化和反序列化。====");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinarySerialize(obj);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryDeserialize("C:\\MyObject.dat");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("========使用SoapFormatter类进行序列化和反序列化。====");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SOAPSerialize(obj);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SOAPDeserialize("C:\\MyObject.soap");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("========使用XmlSerializer类进行序列化和反序列化。====");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMLSerialize(obj);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMLDeserialize("C:\\MyObject.xml");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制序列化对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="obj"&gt;&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void BinarySerialize(MyObject obj)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream("C:\\MyObject.dat", FileMode.Create, FileAccess.Write))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryFormatter formater = new BinaryFormatter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formater.Serialize(stream, obj);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被序列化。" + obj.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制反序列化<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="fileName"&gt;&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void BinaryDeserialize(string fileName)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryFormatter formater = new BinaryFormatter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj=(MyObject)formater.Deserialize(stream);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被反序列化。" + obj.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制序列化对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="obj"&gt;&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void SOAPSerialize(MyObject obj)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream("C:\\MyObject.soap", FileMode.Create, FileAccess.Write))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SoapFormatter formater = new SoapFormatter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; formater.Serialize(stream, obj);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被序列化。" + obj.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 二进制反序列化<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="fileName"&gt;&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void SOAPDeserialize(string fileName)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SoapFormatter formater = new SoapFormatter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj = (MyObject)formater.Deserialize(stream);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被反序列化。" + obj.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// XML序列化<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="obj"&gt;&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void XMLSerialize(MyObject obj)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream("C:\\MyObject.xml", FileMode.Create, FileAccess.Write))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlSerializer serializer = new XmlSerializer(typeof(MyObject));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; serializer.Serialize(stream, obj);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被序列化。" + obj.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// XML反序列化<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="fileName"&gt;&lt;/param&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void XMLDeserialize(string fileName)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlSerializer serializer = new XmlSerializer(typeof(MyObject));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyObject obj = (MyObject)serializer.Deserialize(stream);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("对象已经被反序列化。" + obj.ToString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>} <br>这个程序的运行效果如下：<br>&nbsp;<br>可见通过上面三个类都能实现将对象序列化保存，并且都能反序列化还原到对象被序列化之前的状态（这正是序列化意义所在，能保存对象运行时的状态并且还能还原）。如果运行上面的代码会在C盘根目录下创建三个文件，分别是MyObject.dat、MyObject.soap和MyObject.xml文件，因为MyObject.dat是二进制文件，所以无法查看文件的内容，但是我们可以打开MyObject.soap和MyObject.xml这两个文件来比较一下有什么区别。<br>MyObject.soap文件的后缀虽然是.soap，但是还是可以用记事本打开的，下面是MyObject.soap文件的内容：<br>view plaincopy to clipboardprint?<br>&lt;SOAP-ENV:Envelope xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>" xmlns:SOAP-ENC="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" xmlns:SOAP-ENV="<a href="http://schemas.xmlsoap.org/soap/envelope/">http://schemas.xmlsoap.org/soap/envelope/</a>" xmlns:clr="<a href="http://schemas.microsoft.com/soap/encoding/clr/1.0">http://schemas.microsoft.com/soap/encoding/clr/1.0</a>" SOAP-ENV:encodingStyle="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>"&gt;&nbsp; <br>&lt;SOAP-ENV:Body&gt;&nbsp; <br>&lt;a1:MyObject id="ref-1" xmlns:a1="<a href="http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull</a>"&gt;&nbsp; <br>&lt;name id="ref-3"&gt;周公&lt;/name&gt;&nbsp; <br>&lt;birthday&gt;1979-11-07T00:00:00.0000000+08:00&lt;/birthday&gt;&nbsp; <br>&lt;homePlace id="ref-4"&gt;湖北&lt;/homePlace&gt;&nbsp; <br>&lt;/a1:MyObject&gt;&nbsp; <br>&lt;/SOAP-ENV:Body&gt;&nbsp; <br>&lt;/SOAP-ENV:Envelope&gt;&nbsp; <br>&lt;SOAP-ENV:Envelope xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>" xmlns:SOAP-ENC="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>" xmlns:SOAP-ENV="<a href="http://schemas.xmlsoap.org/soap/envelope/">http://schemas.xmlsoap.org/soap/envelope/</a>" xmlns:clr="<a href="http://schemas.microsoft.com/soap/encoding/clr/1.0">http://schemas.microsoft.com/soap/encoding/clr/1.0</a>" SOAP-ENV:encodingStyle="<a href="http://schemas.xmlsoap.org/soap/encoding/">http://schemas.xmlsoap.org/soap/encoding/</a>"&gt;<br>&lt;SOAP-ENV:Body&gt;<br>&lt;a1:MyObject id="ref-1" xmlns:a1="<a href="http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull</a>"&gt;<br>&lt;name id="ref-3"&gt;周公&lt;/name&gt;<br>&lt;birthday&gt;1979-11-07T00:00:00.0000000+08:00&lt;/birthday&gt;<br>&lt;homePlace id="ref-4"&gt;湖北&lt;/homePlace&gt;<br>&lt;/a1:MyObject&gt;<br>&lt;/SOAP-ENV:Body&gt;<br>&lt;/SOAP-ENV:Envelope&gt; <br>MyObject.xml文件也可以用记事本打开，它的内容如下：</p>
<p>view plaincopy to clipboardprint?<br>&lt;?xml version="1.0"?&gt;&nbsp; <br>&lt;MyObject xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;&nbsp; <br>&nbsp; &lt;HomePlace&gt;湖北&lt;/HomePlace&gt;&nbsp; <br>&nbsp; &lt;Birthday&gt;1979-11-07T00:00:00&lt;/Birthday&gt;&nbsp; <br>&nbsp; &lt;Name&gt;周公&lt;/Name&gt;&nbsp; <br>&lt;/MyObject&gt;&nbsp; <br>&lt;?xml version="1.0"?&gt;<br>&lt;MyObject xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>"&gt;<br>&nbsp; &lt;HomePlace&gt;湖北&lt;/HomePlace&gt;<br>&nbsp; &lt;Birthday&gt;1979-11-07T00:00:00&lt;/Birthday&gt;<br>&nbsp; &lt;Name&gt;周公&lt;/Name&gt;<br>&lt;/MyObject&gt; <br>熟悉SOAP协议的朋友一看MyObject.soap文件的内容就知道它符合SOAP协议，MyObject.xml文件毫无疑问是一个符合XML规范的文件。</p>
<p>对代码作几点说明：<br>1、如果采用BinaryFormatter类或者SoapFormatter类来实现序列化，则一定要给类加上Serializable属性，如代码中所示：<br>view plaincopy to clipboardprint?<br>[Serializable]&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// 要序列化的对象&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// 作者：周公&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// 编写时间：2009-03-10&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; public class MyObject&nbsp; <br>[Serializable]<br>&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp; /// 要序列化的对象<br>&nbsp;&nbsp;&nbsp; /// 作者：周公<br>&nbsp;&nbsp;&nbsp; /// 编写时间：2009-03-10<br>&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp; public class MyObject <br>如果不给要序列化的对象加上这个属性，那么采用采用BinaryFormatter类或者SoapFormatter类来实现序列化时会报异常，但使用XmlSerializer 类序列化对象时可以不用这个属性。<br>2、另外，如果不想序列化某个字段，可以给其加上NonSerialized属性，这样在序列化时就不会保存这个这个字段的值了，比如不想序列化name这个字段，可以如下写代码：</p>
<p>view plaincopy to clipboardprint?<br>&#8230;//其它代码&nbsp;&nbsp; <br>//[NonSerialized]&nbsp;&nbsp; <br>private string name;&nbsp;&nbsp; <br>&#8230;//其它代码&nbsp; <br>&#8230;//其它代码<br>//[NonSerialized]<br>private string name;<br>&#8230;//其它代码 <br>再次运行刚才的程序会得到如下效果：<br>&nbsp;<br>看有黄色底线部分，因为name字段不被序列化，所以通过二进制序列化和SOAP序列化之后再反序化就得不到原来的值了。<br>3、最后还需要说明一点的是，SoapFormatter类在.net3.5开始已经过时了，微软建议使用BinaryFormatter类来序列化和反序列化了。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/zhoufoxcn/archive/2009/03/11/3978874.aspx">http://blog.csdn.net/zhoufoxcn/archive/2009/03/11/3978874.aspx</a></p>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/107028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2010-02-02 18:01 <a href="http://www.cppblog.com/xingmuxixi/archive/2010/02/02/107028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C# winform 实现(不规则)窗体或者控件的拖动</title><link>http://www.cppblog.com/xingmuxixi/archive/2010/01/27/106510.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Wed, 27 Jan 2010 02:30:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2010/01/27/106510.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/106510.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2010/01/27/106510.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/106510.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/106510.html</trackback:ping><description><![CDATA[<p>方法一:&nbsp;窗体或者控件的拖动</p>
<p>&nbsp;&nbsp;&nbsp;private Point m_MousePoint;<br>private Point m_LastPoint;</p>
<p>&nbsp; protected override void OnMouseDown(MouseEventArgs e)<br>{<br>base.OnMouseDown(e);<br>this.m_LastPoint = this.Location;<br>this.m_MousePoint = this.PointToScreen(e.Location);<br>}</p>
<p><br>protected override void OnMouseMove(MouseEventArgs e)<br>{<br>base.OnMouseMove(e);<br>if (e.Button == MouseButtons.Left)<br>{<br>Point t = this.PointToScreen(e.Location);<br>Point l = this.m_LastPoint;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l.Offset(t.X - this.m_MousePoint.X, t.Y - this.m_MousePoint.Y);<br>this.Location = l;<br>}<br>}</p>
<p>1 代码直接复制到窗体上就可以使用.</p>
<p>2 可以用到UserControl上,UserControl就成了一个可拖动的控件了</p>
<p>3 可以用到自定义控件上,例如:自定义控件继承了一个Button ,然后写上上面代码,那么这个自定义Button就可以在Form窗体上随处拖动....</p>
<p>&nbsp;方法二: 不规则窗体拖动</p>
<p>using System.Runtime.InteropServices;</p>
<p>[DllImport("user32.dll")]<br>public static extern bool ReleaseCapture();<br>[DllImport("user32.dll")]<br>public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);<br>public const int WM_SYSCOMMAND = 0x0112;<br>public const int SC_MOVE = 0xF010;<br>public const int HTCAPTION = 0x0002;</p>
<p>public void ShapedForm_MouseDown(object sender, MouseEventArgs e) <br>{ <br>ReleaseCapture();<br>SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);<br>}</p>
<p><br>方法二:比较好 ,能够画出 虚线框,跟Windows的窗体拖动一样...........</p>
<img src ="http://www.cppblog.com/xingmuxixi/aggbug/106510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2010-01-27 10:30 <a href="http://www.cppblog.com/xingmuxixi/archive/2010/01/27/106510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>servlet中调用EJB</title><link>http://www.cppblog.com/xingmuxixi/archive/2010/01/14/105669.html</link><dc:creator>醒目西西</dc:creator><author>醒目西西</author><pubDate>Thu, 14 Jan 2010 09:00:00 GMT</pubDate><guid>http://www.cppblog.com/xingmuxixi/archive/2010/01/14/105669.html</guid><wfw:comment>http://www.cppblog.com/xingmuxixi/comments/105669.html</wfw:comment><comments>http://www.cppblog.com/xingmuxixi/archive/2010/01/14/105669.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingmuxixi/comments/commentRss/105669.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingmuxixi/services/trackbacks/105669.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 文章分类:Java编程对于初学像我这样初学EJB的菜鸟来讲，EJB的配置是一件非常繁琐的事情，不堪回首啊。呵呵，今天终于明白了昨天晚上遇到的一个白痴错误，所以将一个简单的例子写下来。 我这个例子的前提是EJB已经发布成功，在servlet中对已经发布的EJB的调用。 首先已要做的就是将已发布的EJB组件的jar文件拷贝到当前Web工程的lib下，其目录结构为： EJB端： &nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/xingmuxixi/archive/2010/01/14/105669.html'>阅读全文</a><img src ="http://www.cppblog.com/xingmuxixi/aggbug/105669.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingmuxixi/" target="_blank">醒目西西</a> 2010-01-14 17:00 <a href="http://www.cppblog.com/xingmuxixi/archive/2010/01/14/105669.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>