<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[【我的天空】技术资源服务站]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[http://www.escdns.com]]></description>
<link>http://hi.baidu.com/stresume</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[Win7 RC 旗舰版序列号]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/a085a4b716d8a9fe31add1e9.html]]></link>
        <description><![CDATA[
		
		windows7RC全部十个 key<br>
32位<br>
Product key: TQ32R-WFBDM-GFHD2-QGVMH-3P9GC<br>
Product key: 6JKV2-QPB8H-RQ893-FW7TM-PBJ73<br>
Product key: 4HJRK-X6Q28-HWRFY-WDYHJ-K8HDH<br>
Product key: QXV7B-K78W2-QGPR6-9FWH9-KGMM7<br>
Product key: GG4MQ-MGK72-HVXFW-KHCRF-KW6KY<br>
<br>
64位<br>
<br>
Product key: 482XP-6J9WR-4JXT3-VBPP6-FQF4M<br>
Product key: RFFTV-J6K7W-MHBQJ-XYMMJ-Q8DCH<br>
Product key: D9RHV-JG8XC-C77H2-3YF6D-RYRJ9<br>
Product key: 7XRCQ-RPY28-YY9P8-R6HD8-84GH3<br>
Product key: JYDV8-H8VXG-74RPT-6BJPB-X42V4<br>
<br>
32位<br>
Product key: TQ32R-WFBDM-GFHD2-QGVMH-3P9GC<br>
Product key: 6JKV2-QPB8H-RQ893-FW7TM-PBJ73<br>
Product key: 4HJRK-X6Q28-HWRFY-WDYHJ-K8HDH<br>
Product key: QXV7B-K78W2-QGPR6-9FWH9-KGMM7<br>
Product key: GG4MQ-MGK72-HVXFW-KHCRF-KW6KY<br>
<br>
64位<br>
<br>
Product key: 482XP-6J9WR-4JXT3-VBPP6-FQF4M<br>
Product key: RFFTV-J6K7W-MHBQJ-XYMMJ-Q8DCH<br>
Product key: D9RHV-JG8XC-C77H2-3YF6D-RYRJ9<br>
Product key: 7XRCQ-RPY28-YY9P8-R6HD8-84GH3<br>
Product key: JYDV8-H8VXG-74RPT-6BJPB-X42V4 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%CF%B5%CD%B3%B9%DC%C0%ED">系统管理</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/a085a4b716d8a9fe31add1e9.html#comment">查看评论</a>]]></description>
        <pubDate>2009年11月11日 星期三  17:19</pubDate>
        <category><![CDATA[系统管理]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/a085a4b716d8a9fe31add1e9.html</guid>
</item>

<item>
        <title><![CDATA[更改VS2005中默认的测试浏览器]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/755382ee1e5798232df5343f.html]]></link>
        <description><![CDATA[
		
		<p style="text-indent: 2em">如何更改vs2005测试默认浏览器</p>
<p style="text-indent: 2em">更改方法：</p>
<p style="text-indent: 2em"><strong><font color="#ff0000">打开 C:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\VisualStudio\8.0\browsers.xml</font></strong></p>
<p style="text-indent: 2em">&lt;?xml version=&quot;1.0&quot; ?&gt;</p>
<p style="text-indent: 2em">- &lt;BrowserInfo&gt;</p>
<p style="text-indent: 2em">- &lt;Browser&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;Name&gt;firefox.exe&lt;/Name&gt;</p>
<p style="text-indent: 2em">&lt;Path&gt;&quot;F:\PROGRA~1\MOZILL~1\FIREFOX.EXE&quot;&lt;/Path&gt;</p>
<p style="text-indent: 2em">&lt;Resolution&gt;0&lt;/Resolution&gt;</p>
<p style="text-indent: 2em">&lt;IsDefault&gt;False&lt;/IsDefault&gt;</p>
<p style="text-indent: 2em">&lt;/Browser&gt;</p>
<p style="text-indent: 2em">- &lt;Browser&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;Name&gt;Microsoft Internet Explorer&lt;/Name&gt;</p>
<p style="text-indent: 2em">&lt;Path&gt;&quot;C:\Program Files\Internet Explorer\iexplore.exe&quot;&lt;/Path&gt;</p>
<p style="text-indent: 2em">&lt;Resolution&gt;0&lt;/Resolution&gt;</p>
<p style="text-indent: 2em">&lt;IsDefault&gt;True&lt;/IsDefault&gt;</p>
<p style="text-indent: 2em">- &lt;DDE&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;Service&gt;IExplore&lt;/Service&gt;</p>
<p style="text-indent: 2em">&lt;TopicOpenURL&gt;WWW_OpenURL&lt;/TopicOpenURL&gt;</p>
<p style="text-indent: 2em">&lt;ItemOpenURL&gt;&quot;%s&quot;,,0xffffffff,3,,,,&lt;/ItemOpenURL&gt;</p>
<p style="text-indent: 2em">&lt;TopicActivate&gt;WWW_Activate&lt;/TopicActivate&gt;</p>
<p style="text-indent: 2em">&lt;ItemActivate&gt;0xffffffff,0&lt;/ItemActivate&gt;</p>
<p style="text-indent: 2em">&lt;/DDE&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;/Browser&gt;</p>
<p style="text-indent: 2em">- &lt;InternalBrowser&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;Resolution&gt;0&lt;/Resolution&gt;</p>
<p style="text-indent: 2em">&lt;IsDefault&gt;False&lt;/IsDefault&gt;</p>
<p style="text-indent: 2em">&lt;/InternalBrowser&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;/BrowserInfo&gt;、</p>
<p style="text-indent: 2em">将第一个&lt;Browser&gt;结点,也就是firefox的&lt;IsDefault&gt;改为 False ,将 IExplore 的一个改为True</p>
<p style="text-indent: 2em">或者直接删除此文件</p>
<p style="text-indent: 2em">当然也可以直接将现在使用的浏览器路径加到文件中，设置IsDefault属性为Ｔｒｕｅ就ｏｋ了</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/asp%2Enet%BC%BC%CA%F5">asp.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/755382ee1e5798232df5343f.html#comment">查看评论</a>]]></description>
        <pubDate>2009年11月10日 星期二  16:12</pubDate>
        <category><![CDATA[asp.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/755382ee1e5798232df5343f.html</guid>
</item>

<item>
        <title><![CDATA[C#中FileSystemWatcher控件实现文件监控]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/80361c55d6c07aceb745ae88.html]]></link>
        <description><![CDATA[
		
		<strong>  FileSystemWatcher</strong>
<p>可以使用FileSystemWatcher组件监视文件系统，并对文件系统的改变作出反应。通过使用FileSystemWatcher组件，在特定的文件或目录被创建、修改或删除时，可以快速和便捷地启动业务流程。</p>
<p>例如，如果一组用户在合作处理一个存储在服务器共享目录下的文档时，可以使用FileSystemWatcher组件编写应用程序来监视对共享目录的更改情况。当检测到更改时，该组件可以运行处理过程，通过电子邮件通知每个用户。</p>
<p>可以配置组件来监视整个目录及其内容，或特定目录下一个特定的文件或一组文件。若要监视所有文件中的更改，应将Filter属性设置为空字符串（&quot;&quot;）；若要监视特定的文件，应将Filter属性设置为该文件的文件名（例如，若要监视文件MyDoc.txt中的更改，将Filter属性设置为&quot;MyDoc.txt&quot;）；也可以监视特定文件类型中的更改，例如若要监视文本文件中的更改，将Fillter属性设置为&quot;*.txt&quot;。</p>
<p>【提示】不要忽略隐藏文件。</p>
<p>可监视目录或文件中的若干种更改。例如，可监视文件或目录的Attributes、LastWrite的日期和时间或Size的更改。通过将 FileSystemWatcher.NotifyFilter属性设置为NotifyFilters中的某个值，就可以实现这个目标。</p>
<p>还可以监视文件或目录的重命名、删除或创建。例如，若要监视文本文件的重命名，可将Filter属性设置为&quot;*.txt&quot;，并调用一个WaitForChanged方法，并设置该方法中WatcherChangeTypes的值为Renamed。</p>
<p>下面举例说明。创建一个FileSystemWatche组件来监视运行时指定的目录。组件被设置用来监视LastWrite和 LastAccess时间的更改，以及目录中文本文件的创建、删除或重命名。如果文件被更改、创建或删除，则文件的路径就会被输出到控制台。当一个文件被重命名时，旧的和新的路径都被输出到控制台。</p>
<p>【实例7-7】  使用FileSystemWatche组件来监视运行时指定的目录。</p>
<pre><ol><li><span><span>using System;  </span></span></li><li><span>using System.IO;  </span></li><li><span>public</span><span> </span><span>class</span><span> watcher  </span></li><li><span>{  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> Main(string[] args)  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp; {  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//如果没有指定目录，则退出程序 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>if</span><span>(args.Length!=</span><span>1</span><span>)  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//显示调用程序的正确方法 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span>&quot;usage:Watcher.exe(directory)&quot;</span><span>);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>return</span><span>;  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//创建一个新的FileSystemWatcher并设置其属性 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileSystemWatcher watcher=</span><span>new</span><span> FileSystemWatcher();  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.Path=args[O];  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>/*监视LastAcceSS和LastWrite时间的更改以及文件或目录的重命名*/</span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.NotifyFilter=NotifyFilters.LastAccess | NotifyFilters.LastWrite |  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NotifyFilters.FileName | NotifyFilters.DirectoryName;  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//只监视文本文件 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.Filter=</span><span>&quot;*.txt&quot;</span><span>;  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//添加事件句柄 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//当由FileSystemWatcher所指定的路径中的文件或目录的 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//大小、系统属性、最后写时间、最后访问时间或安全权限 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//发生更改时，更改事件就会发生 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.Changed +=</span><span>new</span><span> FileSystemEventHandler(On<wbr></wbr>Changed);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//由FileSystemWatcher所指定的路径中文件或目录被创建时，创建事件就会发生 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.Created +=</span><span>new</span><span> FileSystemEventHandler(On<wbr></wbr>Changed);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//当由FileSystemWatcher所指定的路径中文件或目录被删除时，删除事件就会发生 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.Deleted +=</span><span>new</span><span> FileSystemEventHandler(On<wbr></wbr>Changed) ;  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//当由FileSystemWatcher所指定的路径中文件或目录被重命名时，重命名事件就会发生 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.Renamed +=</span><span>new</span><span> RenamedEventHandler(On<wbr></wbr>Renamed);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//开始监视 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; watcher.EnableRaisingEvents=</span><span>true</span><span>;  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//等待用户退出程序 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span>&quot;Press\'q\' to quit the sample.&quot;</span><span>);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>while</span><span>(Console.Read()!=</span><span>'q'</span><span>);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp; }  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//定义事件处理程序 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> On<wbr></wbr>Changed(object sender,FileSystemEventArgs e)  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp; {  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//指定当文件被更改、创建或删除时要做的事 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span>&quot;file:&quot;</span><span>+e.FullPath+</span><span>&quot;&quot;</span><span>+e.ChangeType);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp; }  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> On<wbr></wbr>Renamed(object sender,RenamedEventArgs e)  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp; {  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>//指定当文件被重命名时发生的动作 </span><span> </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span>&quot;Fi]e:{0} renamed to{1}&quot;</span><span>,e.OldFullPath,e.FullPath);  </span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp; }  </span></li><li><span>源文地址：<a href="http://www.escdns.com/Html/9961.html">http://www.escdns.com/Html/9961.html</a></span></li></ol></pre> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/80361c55d6c07aceb745ae88.html#comment">查看评论</a>]]></description>
        <pubDate>2009年11月04日 星期三  23:28</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/80361c55d6c07aceb745ae88.html</guid>
</item>

<item>
        <title><![CDATA[www.escdns.com jquery教程之表单验证--胡振强]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/4a1b910127f60edc277fb5f4.html]]></link>
        <description><![CDATA[
		
		<p>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</a>&quot;&gt;<br>
&lt;html xmlns=&quot;<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>&quot;&gt;<br>
&lt;head&gt;<br>
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=gb2312&quot; /&gt;<br>
&lt;title&gt;www.escdns.com jquery教程之表单验证--胡振强&lt;/title&gt;<br>
&lt;style type=&quot;text/css&quot;&gt;<br>
*{line-height:25px;font-size:14px;}<br>
form{border:1px solid #CCC;background-color:#FFF;padding:5px;margin:0;width:800px;}<br>
label{width:100px;text-align:right;}<br>
.high{color:#FF0000;}<br>
.error{color:#FF0000;background-color:#E8E8E8;border:1px solid #CCC;padding:3px 0;}<br>
.ok{color:Green;}<br>
&lt;/style&gt;<br>
&lt;script type=&quot;text/javascript&quot; src=&quot;jscript/jquery-1.3.1.js&quot;&gt;&lt;/script&gt;<br>
&lt;script type=&quot;text/javascript&quot;&gt;<br>
$(function(){<br>
var chemail=/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;<br>
$(&quot;input.required&quot;).each(function(){<br>
&nbsp;&nbsp;  var $txt=&quot;&lt;span class='high'&gt;*&lt;/span&gt;&quot;;<br>
&nbsp;&nbsp;  $(this).parent().append($txt);<br>
})<br>
$(&quot;form input.required&quot;).blur(function(){<br>
&nbsp;&nbsp;  var $parent=$(this).parent();<br>
&nbsp;&nbsp;  if($(this).is(&quot;#username&quot;))<br>
&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;  $(this).parent().find(&quot;.error&quot;).remove();<br>
&nbsp;&nbsp;&nbsp;  $(this).parent().find(&quot;.ok&quot;).remove();<br>
&nbsp;&nbsp;&nbsp;  if(this.value==&quot;&quot;||this.value.length&lt;6){<br>
&nbsp;&nbsp;&nbsp;&nbsp;  $parent.append(&quot;&lt;span class='error'&gt;用户名不合法，要求长度大于6&lt;/span&gt;&quot;);<br>
&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;&nbsp;  else<br>
&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;  $parent.append(&quot;&lt;span class='ok'&gt;用户名输入正确！&lt;/span&gt;&quot;);<br>
&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;  if($(this).is(&quot;#email&quot;))<br>
&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;  $(this).parent().find(&quot;.error&quot;).remove();<br>
&nbsp;&nbsp;&nbsp;  $(this).parent().find(&quot;.ok&quot;).remove();<br>
&nbsp;&nbsp;&nbsp;  if(this.value==&quot;&quot;||!chemail.test(this.value))<br>
&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;  $parent.append(&quot;&lt;span class='error'&gt;邮箱地址不合法！&lt;/span&gt;&quot;);<br>
&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;&nbsp;  else<br>
&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;  $parent.append(&quot;&lt;span class='ok'&gt;邮箱输入合法！&lt;/span&gt;&quot;);<br>
&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;  }<br>
})<br>
$(&quot;input.required&quot;).keyup(function(){<br>
&nbsp;&nbsp;  $(this).triggerHandler(&quot;blur&quot;);<br>
}).focus(function(){<br>
&nbsp;&nbsp;  $(this).triggerHandler(&quot;blur&quot;);<br>
})<br>
$(&quot;#send&quot;).click(function(){<br>
&nbsp;&nbsp;  $(&quot;form input.required&quot;).trigger(&quot;blur&quot;);<br>
&nbsp;&nbsp;  var errNumber=$(&quot;form .error&quot;).length;<br>
&nbsp;&nbsp;  if(errNumber)<br>
&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;  return false;&nbsp;&nbsp;<br>
&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;  else<br>
&nbsp;&nbsp;&nbsp;  return true;<br>
})<br>
})<br>
&lt;/script&gt;<br>
&lt;/head&gt;</p>
<p>&lt;body&gt;<br>
&lt;form method=&quot;post&quot; action=&quot;&quot;&gt;<br>
&lt;div class=&quot;int&quot;&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;label for=&quot;username&quot;&gt;用户名:&lt;/label&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &lt;input type=&quot;text&quot; id=&quot;username&quot; class=&quot;required&quot;/&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;/div&gt;<br>
&lt;div class=&quot;int&quot;&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;label for=&quot;email&quot;&gt;邮箱:&lt;/label&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &lt;input type=&quot;text&quot; id=&quot;email&quot; class=&quot;required&quot;/&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;/div&gt;<br>
&lt;div class=&quot;int&quot;&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;label for=&quot;personinfo&quot;&gt;个人资料:&lt;/label&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &lt;input type=&quot;text&quot; id=&quot;personinfo&quot;/&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;/div&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;div class=&quot;sub&quot;&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;input type=&quot;submit&quot; value=&quot;提交&quot; id=&quot;send&quot;/&gt;&lt;input type=&quot;reset&quot; value=&quot;重置&quot; id=&quot;res&quot;/&gt;<br>
&nbsp;&nbsp;&nbsp;  &lt;/div&gt;<br>
&lt;/form&gt;<br>
&lt;/body&gt;<br>
&lt;/html&gt;</p>
<p>文章出处：<a href="http://www.escdns.com/Html/9960.html">http://www.escdns.com/Html/9960.html</a></p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/script%BC%BC%CA%F5">script技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/4a1b910127f60edc277fb5f4.html#comment">查看评论</a>]]></description>
        <pubDate>2009年11月01日 星期日  22:40</pubDate>
        <category><![CDATA[script技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/4a1b910127f60edc277fb5f4.html</guid>
</item>

<item>
        <title><![CDATA[线程间操作无效: 从不是创建控件“textBox4”的线程访问它]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/c0dca0fd077b521c09244d4b.html]]></link>
        <description><![CDATA[
		
		<p>public long str1, str2, str3, str4, str5, sum=0,sum1=0;</p>
<p>public void button1_Click(object sender, EventArgs e) <br>
{</p>
<p>Thread.CurrentThread.Name = &quot;主线程 &quot;;</p>
<p>Thread objThreadOne = new Thread(new ThreadStart(fun1));</p>
<p>objThreadOne.Name = &quot;子线程 1 &quot;;</p>
<p>Thread objThreadTwo = new Thread(new ThreadStart(fun2));</p>
<p>objThreadTwo.Name = &quot;子线程 2 &quot;;</p>
<p>objThreadOne.Start();</p>
<p>objThreadTwo.Start();</p>
<p><br>
objThreadOne.Priority = ThreadPriority.Highest;</p>
<p><br>
} <br>
void fun1() <br>
{ <br>
str1 = long.Parse(textBox1.Text); <br>
str2 = long.Parse(textBox2.Text); <br>
lock(this)</p>
<p>for (long i = str1; i &lt;= str2; i++) <br>
{ <br>
sum = sum + i;</p>
<p>} <br>
textBox4.Text = sum1.ToString();</p>
<p><br>
} <br>
void fun2() <br>
{ <br>
str1 = long.Parse(textBox1.Text); <br>
str2 = long.Parse(textBox2.Text);</p>
<p>lock (this)</p>
<p>for (long i = str2; i &lt;= str1; i--) <br>
{ <br>
sum1 = sum1 + i;</p>
<p>} <br>
textBox5.Text = sum1.ToString();</p>
<p><br>
}</p>
<p>private void button2_Click(object sender, EventArgs e) <br>
{ <br>
textBox4.Text = &quot; &quot;; <br>
textBox1.Text = &quot; &quot;; <br>
textBox2.Text = &quot; &quot;; <br>
str1 = 0; <br>
str2 = 0; <br>
sum = 0; <br>
}</p>
<p>报错线程间操作无效: 从不是创建控件&ldquo;textBox4&rdquo;的线程访问它。</p>
<p> </p>
<p>解决方法有两种，但是推荐第二种方法：</p>
<p>1、System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;</p>
<p>2、</p>
<p>因为你这个控件是主线程创建的,它依附于创建窗体的主线程.因此,要在子线程去访问占资源的类型,我们需要跨线程调用.textBox4.InvokeRequire用于判断是否需要跨线程,返回True为需要跨线程,此时你需要定义一个委托类来将一个含赋值语句的方法封装起来,通过textBox4.Invoke来调用这个委托.代码如下: <br>
public delegate void SetTextHandler(string text); <br>
private void SetText(string text) <br>
{ <br>
if(textBox4.InvokeRequired==true) <br>
{ <br>
SetTextHandler set=new SetTextHandler(SetText);//委托的方法参数应和SetText一致 <br>
textBox4.Invoke(set,new object[]{text}); //此方法第二参数用于传入方法,代替形参text <br>
} <br>
else <br>
{ <br>
textBox4.Text=text; <br>
}</p>
<p>} <br>
那么fun2函数可以改写成: <br>
void fun2() <br>
{ <br>
str1 = long.Parse(textBox1.Text); <br>
str2 = long.Parse(textBox2.Text);</p>
<p>lock (this)</p>
<p>for (long i = str2; i &lt;= str1; i--) <br>
{ <br>
sum1 = sum1 + i;</p>
<p>} <br>
SetText( sum1.ToString());</p>
<p><br>
} <br>
注意那两句 str1 = long.Parse(textBox1.Text);也需要写成委托形式,读取数据的方法和赋值的方法类型.</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/c0dca0fd077b521c09244d4b.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月30日 星期五  15:49</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/c0dca0fd077b521c09244d4b.html</guid>
</item>

<item>
        <title><![CDATA[如何跨越线程调用窗体上的控件＂线程间操作无效: 从不是创建控件“GroupBox1”的线程访问它。]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/5263154f17ec753cafc3ab4b.html]]></link>
        <description><![CDATA[
		
		<p>今天用线程操作，操作结束需要对窗体属性进行设置，结果提示＂线程间操作无效: 从不是创建控件&ldquo;GroupBox1&rdquo;的线程访问它。＂以下方法可以解决．</p>
<p> </p>
<p>用户不喜欢反应慢的程序。在执行耗时较长的操作时，使用多线程是明智之举，它可以提高程序 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 = &quot;myThread线程调用UI控件&quot;;</p>
<p>&nbsp;&nbsp;&nbsp;  }</p>
<p>如果您在 .NET Framework 1.0 版本中尝试运行这段代码，也许会侥幸运行成功，或者初看起来是如此。这就是多线程错误中的主要问题，即它们并不会立即显现出来。甚至当出现了一些错误时，在第一次演示程序之前一切看起来也都很正常。但不要搞错 &mdash; 我刚才显示的这段代码明显违反了规则，并且可以预见，任何抱希望于&ldquo;试运行时良好，应该就没有问题&rdquo;的人在即将到来的调试期是会付出沉重代价的。</p>
<p> </p>
<p>下面我们来看看有哪些方法可以解决这一问题。</p>
<p><br>
一、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 = &quot;myThread线程调用UI控件&quot;;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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 = &quot;myThread线程调用UI控件&quot;;</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() + &quot;成功!&quot;;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }</p>
<p><br>
三、包装 Control.Invoke</p>
<p>虽然第二个方法中的代码解决了这个问题，但它相当繁琐。如果辅助线程希望在结束时提供更多的反馈信息，而不是简单地给出&ldquo;Finished!&rdquo;消息，则 BeginInvoke 过于复杂的使用方法会令人生畏。为了传达其他消息，例如&ldquo;正在处理&rdquo;、&ldquo;一切顺利&rdquo;等等，需要设法向 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)+&quot;%&quot;, 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> </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;&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 的属性。这是&ldquo;只限 UI 线程&rdquo;规则的另一个例外。它可从任何线程读取，如果调用线程是 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>参考：</p>
<p><a href="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/misMultithreading.mspx?mfr=true">http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/misMultithreading.mspx?mfr=true</a></p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/5263154f17ec753cafc3ab4b.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月30日 星期五  15:47</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/5263154f17ec753cafc3ab4b.html</guid>
</item>

<item>
        <title><![CDATA[解决&#34;从不是创建控件的线程访问它&#34;]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/b231baafdec621c67cd92a4a.html]]></link>
        <description><![CDATA[
		
		<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在默认情况下,C#不准许在一个线程中直接访问或操作另一线程中创建的控件,这是因为访问windows窗体控件本质上是不安全的。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  大家知道线程之间是可以同时运行的，那么如果有两个或多个线程同时操作某一控件的某状态，则极有可能使该控件的某受控制的状态进入一种无所适从的境地。那么如何解决这个突显的矛盾呢？</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这里我推荐的是使用代理。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  为了区别是否是创建该控件的线程访问该控件,Windows窗体控件中的每个控件都有一个InvokeRequired属性,这个属性就是用来检查本控件是否被其他线程调用的属性,当被创建该线程外的线程调用的时候InvokeRequired就为true。有了这个属性我们就可以利用它来做判断了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  光判断出是否被其他线程调用是没有用的，所以windows窗体控件中还有一个Invoke方法可以帮我们完成其他线程对控件的调用。结合代理的使用就可以很好的完成我们的目标了。下面是实现的思路代码：</p>
<p>delegate void AppendStringDelegate(string str);</p>
<p>private void AppendString(string str)<br>
{</p>
<p>&nbsp;&nbsp;  if(xxxx.InvokeRequird)<br>
&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  AppendStringDelegate dd=new AppendStringDelegate(AppendString);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  xxxx.Invoked(dd,new object[]{str});<br>
&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;  else<br>
&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  xxxx.Text+=str;<br>
&nbsp;&nbsp;  }<br>
}</p>
<p>上面这段代码通过代理实现了从其他线程对xxxx.Text的操作；</p>
<p>还有一种方法用于阻止错误：<br>
Control.CheckForIllegalCrossThreadCalls = false;<br>
线程开始的时候加这么一句，OK，看不到错误了~<br>
啥都能用了~<br>
但：这种方法只是简单的将错误提示禁用了，仍然存在跨线程调用控件的问题。为此可能造成两个线程同时或者循环改变该控件的状态导致线程死锁。 <br>
Invoke方法是同步的方法，所以执行过程是有先后顺序的，所以就不会出现那个异常了</p>
<p>所以最好使用Invoke；<br>
用委托，在05里，每个控件都有个InvokeRequired的属性~<br>
判断一下是不是true，是的话进行Invoke操作的，完事了~</p>
<p>//建立个委托<br>
private delegate string returnStrDelegate();</p>
<p>//搞个最简单滴取值滴方法~<br>
private string returnSchool()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return CB_School.SelectedValue.ToString();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }</p>
<p>//判断一下是不是该用Invoke滴~，不是就直接返回~<br>
private string returnCB(returnStrDelegate myDelegate)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  if (this.InvokeRequired)<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;  return (string)this.Invoke(myDelegate);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  else<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;  return myDelegate();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }</p>
<p>//别的线程里的调用哇~<br>
string _school = returnCB(returnSchool);</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/b231baafdec621c67cd92a4a.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月30日 星期五  15:47</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/b231baafdec621c67cd92a4a.html</guid>
</item>

<item>
        <title><![CDATA[线程间操作无效: 从不是创建控件“xxx”的线程访问它]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/4956ee190301b470dab4bd48.html]]></link>
        <description><![CDATA[
		
		<p>在WinForm中，直接使用自己创建的线程去使用窗体中的控件，是不安全的，不允许这样操作，以用委托的方式进行处理：<br>
<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  delegate void WriteLabelText(string str, Color color);<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  private void showSqlConnResult(string msg, Color color)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.labelSqlConnStatus.Text = msg;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.labelSqlConnStatus.ForeColor = color;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.buttonTestSqlConn.Enabled = true;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  private void threadTestConn()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  string result = &quot;连接数据库成功。&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Color color = Color.Green;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(this.textBoxSqlConnString.Text.Trim());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  try<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;  conn.Open();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  conn.Close();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  catch (Exception E)<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;  result = E.Message;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  color = Color.Red;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  WriteLabelText wt = new WriteLabelText(showSqlConnResult);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.Invoke(wt, result, color);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  private void buttonTestSqlConn_Click(object sender, EventArgs e)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.buttonTestSqlConn.Enabled = false;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.labelSqlConnStatus.ForeColor = Color.Blue;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  this.labelSqlConnStatus.Text = &quot;正在测试连接数据库……&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(this.threadTestConn));<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  thread.Start();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/4956ee190301b470dab4bd48.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月30日 星期五  15:44</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/4956ee190301b470dab4bd48.html</guid>
</item>

<item>
        <title><![CDATA[CSS解决浮动产生的问题，CSS清除浮动出现的问题]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/7b21d9fc641c0888b901a07a.html]]></link>
        <description><![CDATA[
		
		<p>css常用的清除浮动<br>
说明：使用xhtml+css布局经常性地会使用到float，很多邪门的事儿都有可能是浮动在作怪，那么清除浮动就是必须要做的，而且随时性地对父级元素清除浮动的做法也被认为是书写CSS的良好习惯之一。<br>
常用的清除浮动的方法有以下三种:</p>
<p>此为未清除浮动源代码，运行代码无法查看到父级元素浅黄色背景。</p>
<p>&lt;style type=&rdquo;text/css&rdquo;&gt;<br>
&lt;!&ndash;<br>
*{margin:0;padding:0;}<br>
body{font:36px bold; color:#F00; text-align:center;}<br>
#layout{background:#FF9;}<br>
#left{float:left;width:20%;height:200px;background:#DDD;line-height:200px;}<br>
#right{float:right;width:30%;height:80px;background:#DDD;line-height:80px;}<br>
&ndash;&gt;<br>
&lt;/style&gt;<br>
&lt;div id=&rdquo;layout&rdquo;&gt;<br>
&lt;div id=&rdquo;left&rdquo;&gt;Left&lt;/div&gt;<br>
&lt;div id=&rdquo;right&rdquo;&gt;Right&lt;/div&gt;<br>
&lt;/div&gt;<br>
未清除浮动前如图所示：</p>
<p> </p>
<p><br>
三种清除浮动方法如下：</p>
<p>1、使用空标签清除浮动。我用了很久的一种方法，空标签可以是div标签，也可以是P标签。我习惯用&lt;P&gt;，够简短，也有很多人用&lt;hr&gt;，只是需要另外为其清除边框，但理论上可以是任何标签。这种方式是在需要清除浮动的父级元素内部的所有浮动元素后添加这样一个标签清除浮动，并为其定义CSS代码：clear:both。此方法的弊端在于增加了无意义的结构元素。</p>
<p>ps:&lt;br clear=&rdquo;all&rdquo;/&gt;也可以实现效果，但不清楚使用哪个比较好。呵呵</p>
<p>&lt;style type=&rdquo;text/css&rdquo;&gt;<br>
&lt;!&ndash;<br>
*{margin:0;padding:0;}<br>
body{font:36px bold; color:#F00; text-align:center;}<br>
#layout{background:#FF9;}<br>
#left{float:left;width:20%;height:200px;background:#DDD;line-height:200px;}<br>
#right{float:right;width:30%;height:80px;background:#DDD;line-height:80px;}<br>
.clr{clear:both;} <br>
&ndash;&gt;<br>
&lt;/style&gt;<br>
&lt;div id=&rdquo;layout&rdquo;&gt;<br>
&lt;div id=&rdquo;left&rdquo;&gt;Left&lt;/div&gt;<br>
&lt;div id=&rdquo;right&rdquo;&gt;Right&lt;/div&gt;<br>
&lt;p class=&rdquo;clr&rdquo;&gt; &lt;/p&gt;<br>
&lt;/div&gt;</p>
<p>2、使用overflow属性。此方法有效地解决了通过空标签元素清除浮动而不得不增加无意代码的弊端。使用该方法是只需在需要清除浮动的元素中定义CSS属性：overflow:auto，即可！&rdquo;zoom:1″用于兼容IE6。</p>
<p>&lt;style type=&rdquo;text/css&rdquo;&gt;<br>
&lt;!&ndash;<br>
*{margin:0;padding:0;}<br>
body{font:36px bold; color:#F00; text-align:center;}<br>
#layout{background:#FF9;overflow:auto;zoom:1;}<br>
#left{float:left;width:20%;height:200px;background:#DDD;line-height:200px;}<br>
#right{float:right;width:30%;height:80px;background:#DDD;line-height:80px;}<br>
&ndash;&gt;<br>
&lt;/style&gt;<br>
&lt;div id=&rdquo;layout&rdquo;&gt;<br>
&lt;div id=&rdquo;left&rdquo;&gt;Left&lt;/div&gt;<br>
&lt;div id=&rdquo;right&rdquo;&gt;Right&lt;/div&gt;<br>
&lt;/div&gt;</p>
<p>3、使用after伪对象清除浮动。该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置height:0，否则该元素会比实际高出若干像素；二、content属性是必须的，但其值可以为空，蓝色理想讨论该方法的时候content属性的值设为&rdquo;.&rdquo;，但我发现为空亦是可以的。</p>
<p>&lt;style type=&rdquo;text/css&rdquo;&gt;<br>
&lt;!&ndash;<br>
*{margin:0;padding:0;}<br>
body{font:36px bold; color:#F00; text-align:center;}<br>
#layout{background:#FF9;}<br>
#layout:after{display:block;clear:both;content:&rdquo;&quot;;visibility:hidden;height:0;}<br>
#left{float:left;width:20%;height:200px;background:#DDD;line-height:200px;}<br>
#right{float:right;width:30%;height:80px;background:#DDD;line-height:80px;}<br>
&ndash;&gt;<br>
&lt;/style&gt;<br>
&lt;div id=&rdquo;layout&rdquo;&gt;<br>
&lt;div id=&rdquo;left&rdquo;&gt;Left&lt;/div&gt;<br>
&lt;div id=&rdquo;right&rdquo;&gt;Right&lt;/div&gt;<br>
&lt;/div&gt;<br>
清除浮动后如图所示：</p>
<p> </p>
<p>此三种方法各有利弊，使用时应择优选择，比较之下第二种方法更为可取。</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/div%26%2347%3Bcss%D1%F9%CA%BD">div&#47;css样式</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/7b21d9fc641c0888b901a07a.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月30日 星期五  15:26</pubDate>
        <category><![CDATA[div&#47;css样式]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/7b21d9fc641c0888b901a07a.html</guid>
</item>

<item>
        <title><![CDATA[CSS样式使用技巧]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/41096decadedb4db2f2e2179.html]]></link>
        <description><![CDATA[
		
		<p>1、使用CSS缩写<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  使用缩写可以帮助减少你CSS文件的大小，更加容易阅读。CSS缩写的主要规则请参看《常用CSS缩写语法总结》，这里就不展开描述，简单一例如，在定义body的padding时可以用：<br>
body { padding: 36pt 24pt 36pt; }</p>
<p>2、明确定义单位，除非值为0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  忘记定义尺寸的单位是CSS新手普遍的错误。在HTML中你可以只写width=&quot;100&quot;，但是在CSS中，你必须给一个准确的单位，比如：width:100px width:100em。只有两个例外情况可以不定义单位：行高和0值。除此以外，其他值都必须紧跟单位，注意，不要在数值和单位之间加空格。</p>
<p>3、区分大小写<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当在XHTML中使用CSS，CSS里定义的元素名称是区分大小写的。为了避免这种错误，我建议所有的定义名称都采用小写。class和id的值在HTML和XHTML中也是区分大小写的，如果你一定要大小写混合写，请仔细确认你在CSS的定义和XHTML里的标签是一致的。</p>
<p>4、取消class和id前的元素限定<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当你写给一个元素定义class或者id，你可以省略前面的元素限定，因为ID在一个页面里是唯一的，而class可以在页面中多次使用。你限定某个元素毫无意义。例如：<br>
div#content { /* declarations */ } <br>
fieldset.details { /* declarations */ } <br>
可以写成：<br>
#content { /* declarations */ } <br>
.details { /* declarations */ } <br>
这样可以节省一些字节。</p>
<p>5、默认值<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  通常padding的默认值为0，background-color的默认值是transparent。但是在不同的浏览器默认值可能不同。如果怕有冲突，可以在样式表一开始就先定义所有元素的margin和padding值都为0，像这样：<br>
* { <br>
margin:0; <br>
padding:0; <br>
}</p>
<p>6、不需要重复定义可继承的值<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  CSS中，子元素自动继承父元素的属性值，象颜色、字体等，已经在父元素中定义过的，在子元素中可以直接继承，不需要重复定义。但是要注意，浏览器可能用一些默认值覆盖你的定义。</p>
<p>7、最近优先原则<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  如果对同一个元素的定义有多种，以最接近(最小一级)的定义为最优先，例如有这么一段代码<br>
&lt;p class=&rdquo;update&rdquo;&gt;Update: Lorem ipsum dolor set&lt;/p&gt;<br>
在CSS文件中，你已经定义了元素p，又定义了一个class&quot;update&quot;<br>
p { <br>
margin:1em 0; <br>
font-size:1em; <br>
color:#333; <br>
} <br>
.update { <br>
font-weight:bold; <br>
color:#600; <br>
} <br>
这两个定义中，class=&quot;update&quot;将被使用，因为class比p更近。你可以查阅W3C的《 Calculating a selector&rsquo;s specificity》 了解更多。</p>
<p>8、多重class定义<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  一个标签可以同时定义多个class。例如：我们先定义两个样式，第一个样式背景为#666；第二个样式有10px的边框。<br>
.one{width:200px;background:#666;}<br>
.two{border:10px solid #F00;} <br>
在页面代码中，我们可以这样调用:<br>
&lt;div class=&quot;one two&quot;&gt;&lt;/div&gt; <br>
这样最终的显示效果是这个div既有#666的背景，也有10px的边框。</p>
<p>9、使用子选择器(descendant selectors)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  CSS初学者不知道使用子选择器是影响他们效率的原因之一。子选择器可以帮助你节约大量的class定义。我们来看下面这段代码：<br>
&lt;div id=&quot;subnav&quot;&gt; <br>
&lt;ul&gt; <br>
&nbsp;&nbsp;&nbsp;  &lt;li class=&quot;subnavitem&quot;&gt;&lt;a href=&quot;#&quot; class=&quot;subnavitem&quot;&gt;Item 1&lt;/a&gt;&lt;/li&gt;&gt; <br>
&nbsp;&nbsp;&nbsp;  &lt;li class=&quot;subnavitemselected&quot;&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &lt;a href=&quot;#&quot; class=&quot;subnavitemselected&quot;&gt;Item 2&lt;/a&gt; <br>
&nbsp;&nbsp;&nbsp;  &lt;/li&gt; <br>
&nbsp;&nbsp;&nbsp;  &lt;li class=&quot;subnavitem&quot;&gt;&lt;a href=&quot;#&quot; class=&quot;subnavitem&quot;&gt;Item 3&lt;/a&gt;&lt;/li&gt;<br>
&lt;/ul&gt; <br>
&lt;/div&gt; <br>
这段代码的CSS定义是：<br>
div#subnav ul { /* Some styling */ } <br>
div#subnav ul li.subnavitem { /* Some styling */ } <br>
div#subnav ul li.subnavitem a.subnavitem { /* Some styling */ } <br>
div#subnav ul li.subnavitemselected { /* Some styling */ } <br>
div#subnav ul li.subnavitemselected a.subnavitemselected { /* Some styling */ } <br>
你可以用下面的方法替代上面的代码：<br>
&lt;ul id=&quot;subnav&quot;&gt;<br>
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Item 1&lt;/a&gt;&lt;/li&gt;<br>
&lt;li class=&quot;sel&quot;&gt;&lt;a href=&quot;#&quot;&gt;Item 2&lt;/a&gt;&lt;/li&gt;<br>
&lt;li&gt; &lt;a href=&quot;#&quot;&gt;Item 3&lt;/a&gt;&lt;/li&gt;<br>
&lt;/ul&gt; <br>
样式定义是：<br>
#subnav { /* Some styling */ } <br>
#subnav li { /* Some styling */ } <br>
#subnav a { /* Some styling */ } <br>
#subnav .sel { /* Some styling */ } <br>
#subnav .sel a { /* Some styling */ } <br>
用子选择器可以使你的代码和CSS更加简洁、更加容易阅读。</p>
<p>10、不需要给背景图片路径加引号<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  为了节省字节，我建议不要给背景图片路径加引号，因为引号不是必须的。例如：<br>
background:url(&quot;images/***.gif&quot;) #333; <br>
可以写为：<br>
background:url(images/***.gif) #333; <br>
如果你加了引号，反而可能会引起一些浏览器的错误。</p>
<p>11、组选择器(Group selectors)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当一些元素类型、class或者id都有共同的一些属性，你就可以使用组选择器来避免多次的重复定义。这可以节省不少字节。例如：定义所有标题的字体、颜色和margin，你可以这样写：<br>
h1,h2,h3,h4,h5,h6 { <br>
font-family:&quot;Lucida Grande&quot;,Lucida,Arial,Helvetica,sans-serif; <br>
color:#333;<br>
margin:1em 0; <br>
} <br>
如果在使用时，有个别元素需要定义独立样式，你可以再加上新的定义，可以覆盖老的定义，例如：<br>
h1 { font-size:2em; } <br>
h2 { font-size:1.6em; }</p>
<p>12、用正确的顺序指定链接的样式<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当你用CSS来定义链接的多个状态样式时，要注意它们书写的顺序，正确的顺序是：:link、:visited、:hover 、:active。抽取第一个字母是&quot;LVHA&quot;，你可以记忆成&quot;LoVe HAte&quot;(喜欢讨厌)，&ldquo;爱与恨&rdquo;。为什么这么定义，可以参考Eric Meyer的《Link Specificity》。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  如果你的用户需要用键盘来控制，需要知道当前链接的焦点，你还可以定义:focus属性。:focus属性的效果也取决与你书写的位置，如果你希望聚焦元素显示:hover效果，你就把:focus写在:hover前面；如果你希望聚焦效果替代:hover效果，你就把:focus放在:hover后面。</p>
<p>13、横向居中(centering)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这是一个简单的技巧，但是值得再说一遍，因为我看见太多的新手问题都是问这个：CSS如何横向居中？你需要定义元素的宽，并且定义横向的margin，如果你的布局包含在一个层(容器)中。你可以这样定义使它横向居中：<br>
#wrap { <br>
width:760px; /* 修改为你的层的宽度 */ <br>
margin:0 auto; <br>
} <br>
可能这样还不够，关于居中问题出现的原因和解决方法的原理可见&ldquo;兼容性问题&rdquo;一节中的&ldquo;居中(centering)&rdquo;。</p>
<p>14、清除浮动<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  一个非常常见的CSS问题，定位使用浮动的时候，下面的层被浮动的层所覆盖，或者层里嵌套的子层超出了外层的范围。通常的解决办法是在浮动层后面添加一个额外元素，例如一个div或者一个br，并且定义它的样式为clear: both。这个办法有一点牵强，幸运的是还有一个好办法可以解决，参看这篇文章《How To Clear Floats Without Structural Markup》，也可以简单通过浏览器兼容问题一节的&ldquo;万能 float 闭合&rdquo;来做个大概了解。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  上面2种方法可以很好解决浮动超出的问题，但是如果当你真的需要对层或者层里的对象进行clear的时候怎么办？一种简单的方法就是用overflow属性，这个方法最初的发表在《Simple Clearing of Floats》，又在《Clearance》和《Super simple clearing floats》中被广泛讨论。<br>
上面哪一种clear方法更适合你，要看具体的情况，这里不再展开论述。另外关于float的应用，一些优秀的文章已经说得很清楚，推荐你阅读：《Floatutorial》、《Containing Floats》和《Float Layouts》。</p>
<p>15、导入(Import)和隐藏CSS<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  因为老版本浏览器不支持CSS，一个通常的做法是使用@import技巧来把CSS隐藏起来。例如：<br>
@import url(&quot;main.CSS&quot;); <br>
然而，这个方法对IE4不起作用，则可以采用这样的写法：<br>
@import &quot;main.CSS&quot;; <br>
这样就可以在IE4中也隐藏CSS了，而且还节省了5个字节。想了解@import语法的详细说明，可以看这里《centricle&rsquo;s CSS filter chart》。</p>
<p>16、针对IE的优化<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  有些时候，你需要对IE浏览器的bug定义一些特别的规则，这里有太多的CSS技巧(hacks)，我只使用其中的两种方法，不管微软在即将发布的IE7 beta版里是否更好的支持CSS，这两种方法都是最安全的。另外，在CSS Hack一文中对此将会有更详细的描述。<br>
(1).注释的方法 <br>
(a)在IE中隐藏一个CSS定义，你可以使用子选择器(child selector):<br>
Html &gt; body p { <br>
/* 定义内容 */ <br>
} <br>
(b)下面这个写法只有IE浏览器可以理解(对其他浏览器都隐藏) <br>
* html p { <br>
/* declarations */ <br>
} <br>
(c)还有些时候，你希望IE/Win有效而IE/Mac隐藏，你可以使用&quot;反斜线&quot;技巧：<br>
/* \*/ <br>
* html p { <br>
declarations <br>
} <br>
/* */ <br>
(2).条件注释(conditional comments)的方法 <br>
另外一种方法，我认为比CSS　Hacks更加经得起考验就是采用微软的私有属性条件注释(conditional comments)。用这个方法你可以给IE单独定义一些样式，而不影响主样式表的定义。就象这样：<br>
&lt;!--[if IE]&gt; <br>
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/CSS&quot; href=&quot;ie.CSS&quot; /&gt; <br>
&lt;![endif]--&gt;</p>
<p>17、调试技巧：层有多大？<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  当调试CSS发生错误，你就要象排版工人，逐行分析CSS代码。我通常在出问题的层上定义一个背景颜色，这样就能很明显看到层占据多大空间。有些人建议用border，一般情况也是可以的，但问题是，有时候border 会增加元素的尺寸，border-top和boeder-bottom会破坏纵向margin的值，所以使用background更加安全些。 <br>
另外一个经常出问题的属性是outline。outline看起来象boeder，但不会影响元素的尺寸或者位置。只有少数浏览器支持outline属性，我所知道的只有Safari、OmniWeb和Opera。</p>
<p>18、CSS代码书写样式<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在写CSS代码的时候，对于缩进、断行、空格，每个人有每个人的书写习惯。在经过不断实践后，下面是一种比较好的书写样式：<br>
selector1,<br>
selector2 { <br>
property:value; <br>
} <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在这中书写方法中，当使用联合定义时，通常将每个选择器单独写一行，这样方便在CSS文件中找到它们。在最后一个选择器和大括号{之间加一个空格，每个定义也单独写一行，分号直接在属性值后，不要加空格。而且在每个属性值后面都加分号，虽然规则上允许最后一个属性值后面可以不写分号，但是如果你要加新样式时容易忘记补上分号而产生错误，所以还是都加比较好。最后，关闭的大括号}单独写一行。空格和换行有助与阅读。</p>
<p>19、要定义自定义固定高度<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  定义网页的高度等于窗口高度（例如QQ空间），仅需要在html,body添加height:100%,之后再在div层添加height:100%就OK了。<br>
body { margin:0px;}<br>
html,body { height: 100%;}<br>
div#left { background-color:skyblue; width:500px; height:100%;}</p>
<p>20、UL、LI的水平排布<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在CSS布局中，ul,li的运用是非常常见的。配合DIV与CSS，创建无表格布局。如何让LI中的元素水平排列就成了一个问题，可如下实现：<br>
ul{ list-style-type:none; width:100%;}<br>
ul li{ width:80px; float:left;}</p>
<p>21、在页面中实现精确定位置<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  怎么样在页面中实现精确定位呢？这可能是CSS一个很大的作用。如下代码可实现这个功能：<br>
&lt;div style=&quot;position:absolute;top:150px;width:200px;height:200px;<br>
background-color:red&quot;&gt;写入相应内容&lt;/div&gt;<br>
上面的代码解释为：<br>
position:absolute 表示位置是absolute(绝对)，还有一个是relative（相对）；<br>
top:150px 表示内容显示在离顶部150px的地方，还有是left:150px 表示内容显示在离左边150px的地方；<br>
width:200px;height:200px; 表示内容能显示的区域大小；<br>
background-color:red 表示整个区域是红色的；</p>
<p>22、加入特殊效果<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  CSS定位的剪切(clip)、溢出(voerflow)和可见性(visibility)的属性使WEB设计者很容易地为页面加入特殊效果。在下面的例子中，建立了一个&lt;span&gt;元素调用隐藏类。在浏览器里是看不到这个文本的，但是可以注意到下面的一行字为它在屏幕上留了一个空间。下一个元素调用了溢出类。&quot;容器&quot;比文本要小，所以这里多余文本被切除了。最后的两个元素演示了裁剪属性。最后的对象直接被放置在它前一个之上，但是被裁剪成一个小一点的尺寸；因此，前一个元素显示出来了。<br>
&lt;html&gt;&lt;head&gt;<br>
&lt;style type=&quot;text/CSS&quot;&gt;<br>
&lt;!--<br>
.hidden {position:relative;visibility:hidden}<br>
.overflow {<br>
position:absolute;top:210px;left:60px;width:40px;height:40px;<br>
background-color:yellow;overflow:hidden}<br>
.plain {<br>
position:absolute;top:200px;left:200px;width:150px;height:150px;<br>
background-color:#eeeeee;}<br>
.clip {<br>
position:absolute;top:200px;left:200px;width:150px;height:150px;<br>
background-color:blue;clip:rect(25px 125px 125px 25px);}<br>
--&gt;<br>
&lt;/style&gt;<br>
&lt;/head&gt;<br>
&lt;body&gt;<br>
&lt;span class=&quot;hidden&quot;&gt;<br>
This text is invisible on the page&lt;/span&gt;but this text is affected by the invisible item's flow.<br>
&lt;div class=&quot;overflow&quot;&gt;This is way too much text for the little box that we have designated.The overflow property will hide it.&lt;/div&gt;<br>
&lt;div class=&quot;plain&quot;&gt;This text is covered by the blue square that follows.But since the square is clipped,some of this text shows through.&lt;/div&gt;<br>
&lt;div class=&quot;clip&quot;&gt;This text is yellow on a blue square,but it is getting cut off by clipping&lt;/div&gt;<br>
&lt;/body&gt;&lt;/html&gt;</p>
<p>23、颜色和背景属性<br>
body {background-color:yellow}<br>
h1 {background-color:red}<br>
上面的语句指整个页面的背景色为黄色，h1中的背景色为红色。<br>
body {background-image:url(back.jpg)}<br>
P {background-image:none}<br>
上面的语句指页面的背景图片是back.jpg，P中没有背景图片，当然你也可以加入背景图片。<br>
body {background:red url(back.jpg);background-repeat:repeat-y}<br>
上面的语句指页面为红色(如果没有背景图片时)，而且背景图片垂直排列。<br>
注意:repeat-x指水平排列，repeat-y指垂直排列,no-repeat指不重复。<br>
body {<br>
background:red url(back.jpg);<br>
background-repeat:repeat-y;<br>
background-attachment:scroll;<br>
}<br>
注意:background-attachment:fixed 表示背景图片永远静止，文字在背景上面&quot;流动&quot;；<br>
background-attachment:scroll 表示背景图片随着页面上的文字一起&quot;流动&quot;；<br>
body {background:url(back.jpg) right top} /*right top=100% 0% */；<br>
body {background:url(back.jpg) top center} /*top center=50% 0% */； <br>
body {background:url(back.jpg) center} /*center=50% 50% */； <br>
body {background:url(back.jpg) bottom} /* bottom=50% 100% */。</p>
<p>24、图片位置放置<br>
当文字和图片在同一行内出现时，可用如下方式调整文字的方位。<br>
文字在图片下方： img {vertical-align:baseline}<br>
文字在图片中间： img {vertical-align:middle} <br>
文字在图片上方： img {vertical-align:text-top}</p>
<p>25、图片边框的颜色<br>
border-color属性：<br>
img {border-color:red} 指四个边框色都是红色。<br>
img {border-color:red blue} 指上，下边框是红色，左右边框是蓝色。<br>
img {border-color:red blue yellow} 指上边框是红色，左右边框是蓝色，下边框是黄色。<br>
img {border-color:red blue yellow green} 指上，右，下，左边框分别是红色，蓝色，黄色和绿色。<br>
border-style属性：<br>
h1 {border-style:solid} 指边框为实线，none指没有边框，边框不显示，dotted指边框的样式为由短线组成的虚线，double指边框线为双线，双线再加上它们之间的空白部分的宽度就等于border-width设置的宽度，groove指3D沟槽状的边框，inset指3D内嵌边框，outset指3D外嵌边框。<br>
h1 {border-style:solid} 指四个边框都是实线。<br>
h1 {border-style:solid dotted} 指下，左边框值缺少，则取对边上，右值。<br>
h1 {border-style:solid dotted double} 指左边框缺少，则取右侧的边框值。<br>
h1 {border-style:solid dotted double ridge} 指四个边框都有值，按上，右，下，左分。<br>
再看这句话：<br>
&lt;img id=sample src=lu.gif border=9 style=&quot;filter:blur(strength=50) flipv()&quot;&gt;<br>
上面这句话表示这幅图片使用指定的像素值50设置模糊效果，并且图片垂直翻转。</p>
<p>26、字符上下颜色<br>
你有没有见过在字符的上面或下面有相应的边框，还有色彩，用border-top就可以实现。<br>
h1 {border-top:thick solid blue} <br>
这是指元素顶端边框的样式是蓝色的实边框线。相应的还有border-left，border-right，border-bottom。</p>
<p>27、自动换行<br>
（1）对于Div<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在IE中，可以使用white-space:normal; word-break:break-all;这里前者是遵循标准。如：<br>
#wrap{white-space:normal; width:200px; }<br>
或者：<br>
#wrap{word-break:break-all;width:200px;}<br>
&lt;div id=&quot;wrap&quot;&gt;ddd1111111111111111111111111111111111&lt;/div&gt;<br>
在Firefox中，可以使用white-space:normal; word-break:break-all;overflow:hidden;同样的Firefox下也没有很好的实现方法，只能隐藏或者加滚动条，当然不加滚动条效果更好。<br>
#wrap{white-space:normal; width:200px; overflow:auto;}<br>
或者：<br>
#wrap{word-break:break-all;width:200px; overflow:auto; }<br>
&lt;div id=&quot;wrap&quot;&gt;ddd1111111111111111111111111111111111111111&lt;/div&gt;<br>
（2）对于Table<br>
a）.在IE中可以使用样式table-layout:fixed； <br>
&lt;style&gt;<br>
.tb{table-layout:fixed}<br>
&lt;/style&gt;<br>
&lt;table class=&quot;tb&quot; width=&quot;80&quot;&gt;<br>
&lt;tr&gt;&lt;td&gt;abcdefghigklmnopqrstuvwxyz 1234567890&lt;/td&gt;&lt;/tr&gt;<br>
&lt;/table&gt;<br>
也可以使用样式table-layout:fixed与nowrap 。<br>
&lt;style&gt;<br>
.tb {table-layout:fixed}<br>
&lt;/style&gt;<br>
&lt;table class=&quot;tb&quot; width=&quot;80&quot;&gt;<br>
&lt;tr&gt;&lt;td nowrap&gt;abcdefghigklmnopqrstuvwxyz 1234567890&lt;/td&gt;&lt;/tr&gt;<br>
&lt;/table&gt;<br>
或者在使用百分比固定td大小情况下使用样式table-layout:fixed与nowrap <br>
&lt;style&gt;<br>
.tb{table-layout:fixed}<br>
&lt;/style&gt;<br>
&lt;table class=&quot;tb&quot; width=80&gt;<br>
&lt;tr&gt;<br>
&lt;td width=25% nowrap&gt;abcdefghigklmnopqrstuvwxyz 1234567890&lt;/td&gt;<br>
&lt;td nowrap&gt;abcdefghigklmnopqrstuvwxyz 1234567890&lt;/td&gt;<br>
&lt;/tr&gt;<br>
&lt;/table&gt;<br>
B）.Firefox中，在使用百分比固定td大小情况下使用样式table-layout:fixed与nowrap,并且使用div 。<br>
&lt;style&gt;<br>
.tb {table-layout:fixed}<br>
.td {overflow:hidden;}<br>
&lt;/style&gt;<br>
&lt;table class=tb width=80&gt;<br>
&lt;tr&gt;&lt;td width=25% class=td nowrap&gt;<br>
&lt;div&gt;abcdefghigklmnopqrstuvwxyz 1234567890&lt;/div&gt;&lt;/td&gt;<br>
&lt;td class=td nowrap&gt;<br>
&lt;div&gt;abcdefghigklmnopqrstuvwxyz 1234567890&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;<br>
&lt;/table&gt;<br>
这里单元格宽度一定要用百分比定义。</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/div%26%2347%3Bcss%D1%F9%CA%BD">div&#47;css样式</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/41096decadedb4db2f2e2179.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月30日 星期五  15:26</pubDate>
        <category><![CDATA[div&#47;css样式]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/41096decadedb4db2f2e2179.html</guid>
</item>

<item>
        <title><![CDATA[C#验证控件的使用方法]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/7c32f3ddf4c5e1e576c63882.html]]></link>
        <description><![CDATA[
		
		<p><span class="oblog_text">C#验证控件的使用方法<br>
ASP.NET为开发人员提供了一整套完整的服务器控件来验证用户输入的信息是否有效。这些控件如下：<br>
<wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>1、RequiredFieldValidator：验证一个必填字段，如果这个字段没填，那么，将不能提交信息。</span></p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>2、CompareValidator：比较验证。比较两个字段值是否相等，如密码和确认密码两个字段是否相等；比较一个字段与一个具体的值。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>3、RangeValidator：范围验证。验证一个字段是否在某个范围中，如成绩字段要是0~100范围中。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>4、RegularExpressionValidat<wbr></wbr>or：正则表达式验证。它根据正则表达式来验证用户输入字段的格式是否合法，如电子邮件、身份证、电话号码等。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>5、CustomValidator：在运行定制的客户端JavaScript或VBScript函数时，可以使用这个控件。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>那么，如何使用验证控件呢？</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>1、使用Visual Studio .NET 2003 命令提示工具运行aspnet_regiis -c命令复制ASP.NET客户端脚本文件。</p>
<p><wbr></wbr></p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>2、把验证控件放在要验证的控件右边。如图</p>
<p><wbr></wbr></p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>3、修改验证控件的ControlToValidate属性为要验证的控件名。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>4、把验证控件的ErrorMessage属性修改更具体的错误描述信息，如&ldquo;请输入正确的电子邮件密码&rdquo;、&ldquo;密码不一致&rdquo;、&ldquo;必填字段&rdquo;等。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>5、如果是使用RequiredFieldValidator必填验证控件，到这步就OK了。但是，如果使用的是其它几个控件，还需要作以下设置：</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>A、CompareValidator控件，比较两个控件的值，要设置ControlToCompare、Operator和Type属性。如果是要比较一个控件和一个具体的值，需要修改ValueToCompare、Operator和Type属性。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>B、RangeValidator控件，分别在MinimunValue和MaximumValue属性中设置最小值和最大值，还需要把Type属性改为Currency或Integer。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>C、RegularExpress控件：通过ValidationExpress属性，从列表中选择一个新的正则表达式。</p>
<p><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>最后，需要注意的是，每一个字段都可以使用多个不周类型的验证控件进行验证。</p>
<p><br>
现在ASP.NET，你不但可以轻松的实现对用户输入的验证，而且，还可以选择验证在服务器端进行还是在客户端进行，再也不必考虑那么多了，程序员们可以将重要精力放在主程序的设计上了。</p>
<p>ASP.NET公有六种验证控件，分别如下：</p>
<p>控件名 <wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr><wbr></wbr>功能描叙</p>
<p>RequiredFieldValidator（必须字段验证） 用于检查是否有输入值</p>
<p>CompareValidator（比较验证） 按设定比较两个输入</p>
<p>RangeValidator（范围验证） 输入是否在指定范围</p>
<p>RegularExpressionValidator（正则表达式验证） 正则表达式验证控件</p>
<p>CustomValidator（自定义验证） 自定义验证控件</p>
<p>ValidationSummary（验证总结） 总结验证结果</p>
<p>下面，我们来看这些控件的使用：</p>
<p>一、RequiredFieldValidator（必须字段验证）的使用</p>
<p>RequiredFieldValidator控件使用的标准代码如下：</p>
<p>＜ASP:RequiredFieldValidator id=&quot;Validator_Name&quot; Runat=&quot;Server&quot;</p>
<p>　ControlToValidate=&quot;要检查的控件名&quot;</p>
<p>　ErrorMessage=&quot;出错信息&quot;</p>
<p>　Display=&quot;Static|Dymatic|None&quot;</p>
<p>　＞</p>
<p>　占位符</p>
<p>＜/ASP: RequiredFieldValidator ＞</p>
<p>在以上标准代码中：</p>
<p>ControlToValidate：表示要进行检查控件ID；</p>
<p>ErrorMessage：表示当检查不合法时，出现的错误信息；</p>
<p>Display：错误信息的显示方式；Static表示控件的错误信息在页面中占有肯定位置；Dymatic表示控件错误信息出现时才占用页面控件；None表示错误出现时不显示，但是可以在ValidatorSummary中显示；</p>
<p>占位符：表示Display为Static时，错误信息占有&quot;占位符&quot;那么大的页面空间；</p>
<p>现在，让我们看一个实例：</p>
<p>＜ASP:TextBox id=&quot;txtName&quot; RunAt=&quot;Server&quot;/＞</p>
<p>＜ASP:RequiredFieldValidator id=&quot;Validator1&quot; Runat=&quot;Server&quot;</p>
<p>　ControlToValidate=&quot;txtName&quot;</p>
<p>　ErrorMessage=&quot;姓名必须输入&quot;</p>
<p>　Display=&quot;Static&quot;＞</p>
<p>*姓名必须输入</p>
<p>＜/ASP:RequiredFieldValidator＞</p>
<p>在以上例子中，检查txtName控件是否有输入，如果没有，显示错误信息&quot;姓名必须输入&quot;。是不是很简单？</p>
<p>注意：以上代码和下面其他控件的代码最好放入Form中，和ASP中不一样的是，Form最好写为这样：</p>
<p>＜Form RunAt=&quot;Server&quot;＞</p>
<p>其他代码</p>
<p>＜/Form＞　</p>
<p>这样，Form在服务器端执行，提交才会有效；</p>
<p>二、CompareValidator（比较验证）控件</p>
<p>比较控件比较两个控件的输入是否符合程序设定，大家不要把比较仅仅理解为&quot;相等&quot;，尽管相等是用的最多的，其实，这里的比较包括范围很广，大家看标准代码就会明白。</p>
<p>比较控件的标准代码如下：</p>
<p>＜ASP:CompareValidator id=&quot;Validator_ID&quot; RunAt=&quot;Server&quot;</p>
<p>ControlToValidate=&quot;要验证的控件ID&quot;</p>
<p>errorMessage=&quot;错误信息&quot;</p>
<p>ControlToCompare=&quot;要比较的控件ID&quot;</p>
<p>type=&quot;String|Integer|Double|DateTime|Currency&quot;</p>
<p>operator=&quot;Equal|NotEqual|GreaterThan|GreaterTanEqual|LessThan|LessThanEqual|DataTypeCheck&quot;</p>
<p>Display=&quot;Static|Dymatic|None&quot;</p>
<p>＞</p>
<p>占位符</p>
<p>＜/ASP:CompareValidator＞</p>
<p>在以上标准代码中：</p>
<p>Type表示要比较的控件的数据类型；</p>
<p>Operator表示比较操作（也就是刚才说的为什么比较不仅仅是&quot;相等&quot;的原因），这里，比较有7种方式；</p>
<p>其他属性和RequiredFieldValidator相同；</p>
<p>在这里，要注意ControlToValidate和ControlToCompare的区别，如果operate为GreateThan，那么，必须ControlToCompare大于ControlToValidate才是合法的，这下，应该明白它们两者的意义了吧？例子程序请参考RequiredFieldValidator控件，对照标准代码自己设计。</p>
<p>三、RangeValidator（范围验证）控件</p>
<p>验证输入是否在一定范围，范围用MaximumValue（最大）和MinimunVlaue来确定，标准代码如下：</p>
<p>＜ASP:RangeValidator id=&quot;Vaidator_ID&quot; Runat=&quot;Server&quot;</p>
<p>controlToValidate=&quot;要验证的控件ID&quot;</p>
<p>type=&quot;Integer&quot;</p>
<p>MinimumValue=&quot;最小值&quot;</p>
<p>MaximumValue=&quot;最大值&quot;</p>
<p>errorMessage=&quot;错误信息&quot;</p>
<p>Display=&quot;Static|Dymatic|None&quot;</p>
<p>＞</p>
<p>占位符</p>
<p>＜/ASP:RangeValidator＞</p>
<p>在以上代码中：</p>
<p>用MinimumValue和MaximumValue来界定控件输入值得范围，用type来定义控件输入值的类型。</p>
<p>四、RegularExpresionValidator（正则表达式）控件</p>
<p>正则表达式验证控件的功能非常强大，你可以自己容易构造验证方式，我们先来看看标准代码：</p>
<p>＜ASP:RegularExpressionValidat<wbr></wbr>or id=&quot;Validator_ID&quot; RunAt=&quot;Server&quot;</p>
<p>ControlToValidate=&quot;要验证控件名&quot;</p>
<p>ValidationExpression=&quot;正则表达式&quot;</p>
<p>errorMessage=&quot;错误信息&quot;</p>
<p>display=&quot;Static&quot;</p>
<p>＞</p>
<p>占位符</p>
<p>＜/ASP:RegularExpressionValidator＞</p>
<p>在以上标准代码中，ValidationExpression是重点，现在来看看它的构造：</p>
<p>在ValidationExpression中，不同的字符表示不同的含义：</p>
<p>&quot;.&quot;表示任意字符；</p>
<p>&quot;*&quot;表示和其他表达式一起，表示容易组合；</p>
<p>&quot;[A-Z]&quot;表示任意大写字母；</p>
<p>&quot;\d&quot;表示容易一个数字；</p>
<p>注意，在以上表达式中，引号不包括在内；</p>
<p>举例：</p>
<p>　正则表达式：&quot;.*[A-Z]&quot;表示数字开头的任意字符组合其后接一个大写字母。</p>
<p>五、ValidationSummary（验证总结）控件</p>
<p>该控件收集本页的所有验证错误信息，并可以将它们组织以后再显示出来。其标准代码如下：</p>
<p>＜ASP:ValidationSummary id=&quot;Validator_ID&quot; RunAT=&quot;Server&quot;</p>
<p>HeaderText=&quot;头信息&quot;</p>
<p>ShowSummary=&quot;True|False&quot;</p>
<p>DiaplayMode=&quot;List|BulletList|SingleParagraph&quot;</p>
<p>＞</p>
<p>＜/ASP: ValidationSummary ＞　</p>
<p>在以上标准代码中，HeadText相当于表的HeadText，DisplayMode表示错误信息显示方式：List相当于HTML中的<br>
；BulletList相当于HTML中的＜LI＞；SingleParegraph表示错误信息之间不作如何分割；</p>
<p>六、CustomValidator（自定义验证）控件</p>
<p>该控件用自定义的函数界定验证方式，其标准代码如下：</p>
<p>＜ASP:CustomValidator id=&quot;Validator_ID&quot; RunAt=&quot;Server&quot;</p>
<p>controlToValidate=&quot;要验证的控件&quot;</p>
<p>onServerValidateFunction=&quot;验证函数&quot;</p>
<p>errorMessage=&quot;错误信息&quot;</p>
<p>Display=&quot;Static|Dymatic|None&quot;</p>
<p>＞</p>
<p>占位符</p>
<p>＜/ASP: CustomValidator ＞</p>
<p>以上代码中，用户必须定义一个函数来验证输入。</p>
<p>七、总结</p>
<p>ASP.NET验证控件已经介绍完了，大家可以发现它们的功能很强大，再也不要为验证而烦恼了。当然，以上介绍并不是特别详细，细微的地方，还请大家自己阅读微软的SDK。</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/asp%2Enet%BC%BC%CA%F5">asp.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/7c32f3ddf4c5e1e576c63882.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月24日 星期六  17:07</pubDate>
        <category><![CDATA[asp.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/7c32f3ddf4c5e1e576c63882.html</guid>
</item>

<item>
        <title><![CDATA[ADO.NET中的对象模型]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/ccfdf0cd152aef5b0fb345d1.html]]></link>
        <description><![CDATA[
		
		<p dir="ltr" style="margin-right: 0px"><span style="color: red">Connection对象：</span>与数据源建立连接，连接sql server7.0 或更新版本数据库用SqlConnection,连接OLEDB数据源使用OledbConnection.</p>
<p><span style="color: red">Command 对象</span>：对数据源执行SQL命令并返回结果，SQL Server7.0或更新版本用SqlCommand，OLE DB数据源使用OledbCommand.</p>
<p><span style="color: red">DataReader对象：</span> 读取数据源的数据，只能将数据源的数据从头到尾依次读出，Sql server7.0或以上版本使用SqlDataReader,Oledb数据源使用OledbReader</p>
<p><span style="color: red">DataAdapter对象：</span>对数据源执行操作并返回结果，在DataSet与数据源之间建立通信,将数据源中的数据写入DataSet ,或根据DataSet中的数据必定数据源。Sql server7.0或以上版本使用SqlDataAdapter,Oledb 数据源使用OledbAdpater.<br>
<br>
<span style="color: red">DataSet对象：</span>&nbsp;&nbsp;&nbsp;&nbsp;  服务器内存中的数据库<br>
<br>
<span style="color: red">DataView对象:</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  用于显示DataSet中的数据</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/ccfdf0cd152aef5b0fb345d1.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月24日 星期六  16:02</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/ccfdf0cd152aef5b0fb345d1.html</guid>
</item>

<item>
        <title><![CDATA[影响网站访问量的19个因素]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/2f8fc23fda87cac87d1e7141.html]]></link>
        <description><![CDATA[
		
		　　1、网站未做充分的调研工作，不清楚自己的目标顾客群就匆忙上马; <br>
<br>
　　2、网站发起人从个人兴趣出发，目标群体过小; <br>
<br>
　　3、目标群体上网时间短，缺乏网络经验; <br>
<br>
　　4、网页内容单调，无法提起浏览者的兴趣; <br>
<br>
　　5、定位雷同，扎堆现象严重; <br>
<br>
　　6、未能给首次访问者留下深刻印象，找不到再次访问的理由; <br>
<br>
　　7、不能提供有价值的内容和热门话题; <br>
<br>
　　8、域名与网站名称不对应，或者难以记忆，不便于输入; <br>
<br>
　　9、导航结构安排不合理，页面结构混乱; <br>
<br>
　　10、网页中常出现死链接，影响阅读; <br>
<br>
　　11、缺乏内容来源，更新速度慢; <br>
<br>
　　12、交互性不强，无法粘住浏览者; <br>
<br>
　　13、页面设计不够专业，象个人主页; <br>
<br>
　　14、未在搜索引擎登记; <br>
<br>
　　15、未做搜索排名、竞价广告; <br>
<br>
　　16、登记搜索引擎，或者购买搜索排名、竞价广告时，选择关键字未从浏览者的角度出发; <br>
<br>
　　17、新网站未做网上、网下的推广广告; <br>
<br>
　　18、合作伙伴少，没有在行业门户网站登记; <br>
<br>
　　19、未与同类相关网站建立联盟关系，未建立友情链接。 <br> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/seo%D3%C5%BB%AF">seo优化</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/2f8fc23fda87cac87d1e7141.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月23日 星期五  11:28</pubDate>
        <category><![CDATA[seo优化]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/2f8fc23fda87cac87d1e7141.html</guid>
</item>

<item>
        <title><![CDATA[SqlHelper中使用事务示例]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/7c32f3ddfe96fbe576c638fd.html]]></link>
        <description><![CDATA[
		
		<p>SqlHelper可以回滚事务，但是我觉得事务还是存储过程本身来解决比较好：<br>
DBTransaction = CS.BeginTransaction();<br>
SqlHelper.ExecuteNonQuery(DBTransaction, CommandType.StoredProcedure, &quot;pro_T_Accredit_Create&quot;, arParams);</p>
<p>p_intOutPut = Convert.ToInt32(arParams[3].Value.ToString());</p>
<p>if(p_intOutPut &lt; 0)<br>
{<br>
DBTransaction.Rollback(); //--回退事务<br>
}</p>
<p>另外附采用存储过程回滚</p>
<p>CREATE PROCEDURE 。。。<br>
@idint<br>
。。。。<br>
as<br>
declare 。。。<br>
begin transaction<br>
insert 。。。<br>
delete 。。。<br>
if @@error &lt;&gt; 0 rollback transaction<br>
commit transaction<br>
GO</p>
<p>比较ASP回滚：<br>
标题 在ASP中使用事务控制 julyclyde（原作）</p>
<p>关键字 ASP,事务,COM+ <br>
作者系2月份微软社区之星Microsoft China Community Star<br>
在编程中，经常需要使用事务。所谓事务，就是一系列必须都成功的操作，只要有一步操作失败，所有其他的步骤也必须撤销。比如用ASP开发一个网络硬盘系统，其用户注册部分要做的事有：</p>
<p>将用户信息记入数据库 <br>
为用户开个文件夹用于存储 <br>
初始化用户操作日志</p>
<p>这三步必须使用事务，否则万一磁盘操作失败，而没有撤销数据库操作，就会造成只能登陆而不能操作的&ldquo;死用户&rdquo;现象。<br>
由于数据库系统特殊的发展历史，小至Access，大到DB2,无不带有事务支持。因此上述步骤可以如下表示：<br>
On Error Resume Next<br>
第一步：<br>
在事务环境下把用户信息记入数据库<br>
If Err Then<br>
关闭连接<br>
退出<br>
Else<br>
第二步：创建文件夹<br>
If Err Then<br>
回滚第一步数据库操作，退出<br>
Else<br>
第三步：在事务环境下操作日志数据库<br>
If Err Then<br>
回滚第一步操作，删除第二步建立的文件夹<br>
退出<br>
End If<br>
End If<br>
End If<br>
提交第一步数据库操作的事务<br>
提交第二步数据库操作的事务<br>
End</p>
<p><br>
每一步都需要进行判断，如果失败，还需要手工回滚前面多步操作，使程序变得复杂、难懂。如果今后更新了程序，增加其他步骤，还需要嵌套更多层的If...Else...End If，使程序流程更加复杂。</p>
<p>正确的解决办法是使用ASP的事务控制功能。IIS通过和MTS服务联系，可以控制多种支持事务的系统，当程序发出&ldquo;失败&rdquo;的信号时，所有支持事务的系统均将自动回滚，即使操作已经正式完成；对不支持事务的操作也提供了方便的手工回滚方式。上面的例子用ASP事务控制功能重写如下：</p>
<p>&lt;%@ TRANSACTION = Required %&gt;<br>
On Error Resume Next</p>
<p>Set Conn=Server.CreateObject(&quot;ADODB.Connection&quot;)<br>
Conn.Open ....<br>
Conn.Execute &quot;INSERT....&quot;<br>
Conn.Close<br>
Set Conn=Nothing</p>
<p>Set Conn2=Server.CreateObject(&quot;ADODB.Connection&quot;)<br>
Conn2.Open ....<br>
Conn2.Execute &quot;INSERT....&quot;<br>
Conn2.Close<br>
Set Conn2=Nothing</p>
<p>Set FSO=Server.CreateObject(&quot;Scripting.FilesystemObject&quot;)<br>
FSO.CreateFolder &quot;....&quot;</p>
<p>If Err Then<br>
ObjectContext.SetAbort '通知所有支持事务的组件回滚，并运行手工回滚代码<br>
Else<br>
ObjectContext.SetComplete<br>
End If<br>
Set FSO=Nothing</p>
<p>Sub OnTransactionAbort<br>
Response.Write &quot;错误&quot;<br>
FSO.DeleteFile Server.Mappath(&quot;a.txt&quot;) 'FSO的手工回滚&mdash;&mdash;删除文件夹<br>
End Sub<br>
Sub OnTransactionCommit<br>
Response.Write &quot;胜利完成任务&quot;<br>
End Sub<br>
%&gt;</p>
<p>第一行的&lt;%@ TRANSACTION = Required %&gt;表示这一页ASP文件需要MTS的事务支持。中间的各个操作都按普通顺序书写，而不用考虑回滚问题。在程序最后判断是否有错误。如果有，调用ObjectContext的SetAbort方法，IIS会通过MTS服务通知所有支持事务的组件回滚（主要是数据库），并且运行Sub OnTransactionAbort对不支持事务的操作手工回滚；如果没有发生错误，调用ObjectContext的SetComplete方法，则会运行Sub OnTransactionCommit来显示成功的消息。<br>
整个ASP程序不需要为判断错误和回滚操作书写多余的代码，只须在最后进行判断，即使今后增加了多步操作，也只需要在Sub OnTransactionAbort中进行控制即可，非常方便，程序员可以专注于过程编写而不是书写纠错代码。<br>
其实ASP还提供了许多更有用的功能，等着我们使用，千万不要以为ASP使用脚本语言，功能就一定弱。</p>
<p><br>
比较ADO回滚：<br>
&lt;% <br>
'Asp中使用事务 <br>
Set conn=Server.CreateObject(&quot;ADODB.Connection&quot;) <br>
conn.Open &quot;course_dsn&quot;,&quot;course_user&quot;,&quot;course_password&quot; <br>
conn.begintrans '开始事务</p>
<p>sql=&quot;delete from user_info&quot; <br>
set rs=server.createobject(&quot;adodb.recordset&quot;) <br>
rs.open sql,conn,3,3 <br>
if conn.errors.count&gt;0 then '有错误发生 <br>
conn.rollbacktrans '回滚 <br>
set rs=nothing <br>
conn.close <br>
set conn=nothing <br>
response.write &quot;交易失败，回滚至修改前的状态！&quot; <br>
response.end <br>
else <br>
conn.committrans '提交事务 <br>
set rs=nothing <br>
conn.close <br>
set conn=nothing <br>
response.write &quot;交易成功！&quot; <br>
response.end <br>
end if <br>
%&gt; <br>
 <br>
 <br>
 <br>
 <br>
 <br>
 <br>
 </p>
<p><br>
SqlHelper最开始出现好像是在Microsoft PetShop 作为DAL层的核心。</p>
<p>另外关于SqlDataReader，我感觉这个东西和ADO里面的RecordSet类似，就是需要Close.<br>
如果做为参数和返回值传递是比较危险的，因为你要传出去就Close(),而究竟在哪里关闭容易被以往和忽略，所以我觉得还是用强类型的DataSet做为参数和返回值传递纪录集比较好。</p>
<p>据说下面的写法不用Close也会自动资源回收，不知道真的假的：</p>
<p>using(SqlDataReader reader=SqlHelper.ExecuteReader(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql))<br>
{<br>
if(reader.Read())<br>
{ <br>
SqlParameter[]&nbsp;&nbsp;&nbsp;  signOnParms&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  GetSignOnParameters();  <br>
SqlParameter[]&nbsp;&nbsp;&nbsp;  accountParms&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  GetAccountParameters();  <br>
SqlParameter[]&nbsp;&nbsp;&nbsp;  profileParms&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  GetProfileParameters();  <br>
&nbsp;&nbsp;  <br>
signOnParms[0].Value&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  acc.UserId;  <br>
signOnParms[1].Value&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  acc.Password;  <br>
&nbsp;&nbsp;  <br>
SetAccountParameters(accountParms,&nbsp;&nbsp;&nbsp;  acc);  <br>
SetProfileParameters(profileParms,&nbsp;&nbsp;&nbsp;  acc);  <br>
&nbsp;&nbsp;  <br>
  using&nbsp;&nbsp;&nbsp;  (SqlConnection&nbsp;&nbsp;&nbsp;  conn&nbsp;&nbsp;  =&nbsp;&nbsp;  new&nbsp;&nbsp;&nbsp;  SqlConnection(SQLHelper.CONN_STRING_NON_DTC))&nbsp;&nbsp;  {  <br>
&nbsp;&nbsp;  conn.Open();  <br>
  using&nbsp;&nbsp;&nbsp;  (SqlTransaction&nbsp;&nbsp;&nbsp;  trans&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  conn.BeginTransaction())&nbsp;&nbsp;  {  <br>
  try&nbsp;&nbsp;  {  <br>
&nbsp;&nbsp;  SQLHelper.ExecuteNonQuery(trans,&nbsp;&nbsp;&nbsp;  CommandType.Text,&nbsp;&nbsp;&nbsp;  SQL_INSERT_SIGNON,&nbsp;&nbsp;&nbsp;  signOnParms);  <br>
&nbsp;&nbsp;  SQLHelper.ExecuteNonQuery(trans,&nbsp;&nbsp;&nbsp;  CommandType.Text,&nbsp;&nbsp;&nbsp;  SQL_INSERT_ACCOUNT,&nbsp;&nbsp;&nbsp;  accountParms);  <br>
&nbsp;&nbsp;  SQLHelper.ExecuteNonQuery(trans,&nbsp;&nbsp;&nbsp;  CommandType.Text,&nbsp;&nbsp;&nbsp;  SQL_INSERT_PROFILE,&nbsp;&nbsp;&nbsp;  profileParms);  <br>
&nbsp;&nbsp;  trans.Commit();  <br>
&nbsp;&nbsp;  <br>
&nbsp;&nbsp;  }catch&nbsp;&nbsp;  {  <br>
&nbsp;&nbsp;  trans.Rollback();  <br>
  throw;  <br>
&nbsp;&nbsp;  }  <br>
&nbsp;&nbsp;  }  <br>
&nbsp;&nbsp;  }</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/7c32f3ddfe96fbe576c638fd.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月22日 星期四  11:46</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/7c32f3ddfe96fbe576c638fd.html</guid>
</item>

<item>
        <title><![CDATA[SqlHelper使用详解]]></title>
        <link><![CDATA[http://hi.baidu.com/stresume/blog/item/9bd7e1032f09cbe608fa93fd.html]]></link>
        <description><![CDATA[
		
		<p>SqlHelper 类实现详细信息<br>
SqlHelper 类用于通过一组静态方法来封装数据访问功能。该类不能被继承或实例化，因此将其声明为包含专用构造函数的不可继承类。</p>
<p>在 SqlHelper 类中实现的每种方法都提供了一组一致的重载。这提供了一种很好的使用 SqlHelper 类来执行命令的模式，同时为开发人员选择访问数据的方式提供了必要的灵活性。每种方法的重载都支持不同的方法参数，因此开发人员可以确定传递连接、事务和参数信息的方式。在 SqlHelper 类中实现的方法包括：</p>
<p>ExecuteNonQuery。此方法用于执行不返回任何行或值的命令。这些命令通常用于执行数据库更新，但也可用于返回存储过程的输出参数。 <br>
ExecuteReader。此方法用于返回 SqlDataReader 对象，该对象包含由某一命令返回的结果集。 <br>
ExecuteDataset。此方法返回 DataSet 对象，该对象包含由某一命令返回的结果集。 <br>
ExecuteScalar。此方法返回一个值。该值始终是该命令返回的第一行的第一列。 <br>
ExecuteXmlReader。此方法返回 FOR XML 查询的 XML 片段。 <br>
除了这些公共方法外，SqlHelper 类还包含一些专用函数，用于管理参数和准备要执行的命令。不管客户端调用什么样的方法实现，所有命令都通过 SqlCommand 对象来执行。在 SqlCommand 对象能够被执行之前，所有参数都必须添加到 Parameters 集合中，并且必须正确设置 Connection、CommandType、CommandText 和 Transaction 属性。SqlHelper 类中的专用函数主要用于提供一种一致的方式，以便向 SQL Server 数据库发出命令，而不考虑客户端应用程序调用的重载方法实现。SqlHelper 类中的专用实用程序函数包括：</p>
<p>AttachParameters：该函数用于将所有必要的 SqlParameter 对象连接到正在运行的 SqlCommand。 <br>
AssignParameterValues：该函数用于为 SqlParameter 对象赋值。 <br>
PrepareCommand：该函数用于对命令的属性（如连接、事务环境等）进行初始化。 <br>
ExecuteReader：此专用 ExecuteReader 实现用于通过适当的 CommandBehavior 打开 SqlDataReader 对象，以便最有效地管理与阅读器关联的连接的有效期。</p>
<p>SqlHelper体验谈：</p>
<p>以下载自CEOCIO(MVP/CSDN_WEB开发版主)的Blog:</p>
<p>微软提供的Data Access Application Block中的SQLHelper类中封装了最常用的数据操作，各个使用者调用他而写的代码也有很大区别。</p>
<p>对于一个返回DataSet的方法我原来是这样写的：</p>
<p>public DataSet GetDepartmentMemberList(int departmentID)<br>
{<br>
try<br>
{<br>
string sql = &quot;OA_Department_GetDepartment_Members&quot;;<br>
string conn = ConfigurationSettings.AppSettings[&quot;strConnection&quot;];<br>
SqlParameter[] p = <br>
{<br>
SqlHelper.MakeInParam(&quot;@departmentID&quot;,SqlDbType.Int,4,departmentID)<br>
};<br>
DataSet ds = SqlHelper.ExecuteDataset(conn,CommandType.StoredProcedure,sql,p);<br>
return ds;<br>
}<br>
catch(System.Data.SqlClient.SqlException er)<br>
{<br>
throw new Exception(er.Message);<br>
}<br>
}</p>
<p>现在我是这样来写的：</p>
<p>//连接字符串<br>
private string _connectionString = ConfigurationSettings.AppSettings[&quot;strConnection&quot;];<br>
public string ConnectionString<br>
{<br>
get {return this._connectionString;}<br>
set {this._connectionString = value;}<br>
}</p>
<p>public DataSet GetNewsToIndexPage(int NewsTypeID)<br>
{<br>
return GetDataSet(&quot;yzb_GetNewsToIndexPage&quot;,GetNewsToIndexPage_Parameters(NewsTypeID));<br>
}</p>
<p>//设置存储过程参数<br>
private SqlParameter[] GetNewsToIndexPage_Parameters(int NewsTypeID)<br>
{</p>
<p>SqlParameter[] p = <br>
{<br>
SqlHelper.MakeInParam(&quot;@NewsTypeID&quot;,SqlDbType.Int,4,NewsTypeID)<br>
};<br>
return p;<br>
}</p>
<p>//这里才真正调用SqlHelper<br>
private DataSet GetDataSet(string sql, params SqlParameter[] p)<br>
{<br>
return SqlHelper.ExecuteDataset(ConnectionString,CommandType.StoredProcedure,sql,p);<br>
}<br>
代码更加灵活，更加安全了：P</p>
<p>做为一个懒人，大笨狼我经常这样写：</p>
<p>System.Data.DataTable dt=SqlHelper.ExecuteDataset(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql).Tables[0];</p>
<p>直接返回DataTable， 返回表集合基本不用，只返回一个table用于绑定。</p>
<p>string conn = ConfigurationSettings.AppSettings[&quot;strConnection&quot;]; <br>
我写在SqlHelper.CONN_STRING_NON_DTC里面</p>
<p>MakeInParam代码烦琐，如果查询输入条件不可能有组合SQL, <br>
我直接exec pronamr paraargs</p>
<p>如果查询输入条件存在安全问题，或者带返回参数 <br>
再用SqlParameter[] queryParam=new SqlParameter[] { <br>
new SqlParameter(&quot;@UserID&quot;,SqlDbType.Int) <br>
}; <br>
queryParam[0].Value=this.UserID;</p>
<p><br>
组合sql语句用到@和string.Format技巧.例如：<br>
<a href="mailto:sql=@&quot;UPDATE">sql=@&quot;UPDATE</a> Test_User_Statistic<br>
SET <br>
Test_User_Statistic.[IsQualified]={0}, <br>
Test_User_Statistic.[Reason]='{1}'<br>
WHERE UserID={2}&quot; ;<br>
sql= string.Format(sql,IsQualified,Reason,userID);<br>
SqlHelper.ExecuteNonQuery(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql);</p>
<p>其中sql语句可以借助SQL的查询分析器生成。<br>
这么干要保证安全，如果有输入漏洞，建议还是用SqlParameter[]缓存参数，因为它会把攻击性的代码，比如带单引号分号的，当作普通字符处理。 <br>
 <br>
 <br>
 <br>
 </p>
<p>果失败，还需要手工回滚前面多步操作，使程序变得复杂、难懂。如果今后更新了程序，增加其他步骤，还需要嵌套更多层的If...Else...End If，使程序流程更加复杂。</p>
<p>正确的解决办法是使用ASP的事务控制功能。IIS通过和MTS服务联系，可以控制多种支持事务的系统，当程序发出&ldquo;失败&rdquo;的信号时，所有支持事务的系统均将自动回滚，即使操作已经正式完成；对不支持事务的操作也提供了方便的手工回滚方式。上面的例子用ASP事务控制功能重写如下：</p>
<p>&lt;%@ TRANSACTION = Required %&gt;<br>
On Error Resume Next</p>
<p>Set Conn=Server.CreateObject(&quot;ADODB.Connection&quot;)<br>
Conn.Open ....<br>
Conn.Execute &quot;INSERT....&quot;<br>
Conn.Close<br>
Set Conn=Nothing</p>
<p>Set Conn2=Server.CreateObject(&quot;ADODB.Connection&quot;)<br>
Conn2.Open ....<br>
Conn2.Execute &quot;INSERT....&quot;<br>
Conn2.Close<br>
Set Conn2=Nothing</p>
<p>Set FSO=Server.CreateObject(&quot;Scripting.FilesystemObject&quot;)<br>
FSO.CreateFolder &quot;....&quot;</p>
<p>If Err Then<br>
ObjectContext.SetAbort '通知所有支持事务的组件回滚，并运行手工回滚代码<br>
Else<br>
ObjectContext.SetComplete<br>
End If<br>
Set FSO=Nothing</p>
<p>Sub OnTransactionAbort<br>
Response.Write &quot;错误&quot;<br>
FSO.DeleteFile Server.Mappath(&quot;a.txt&quot;) 'FSO的手工回滚&mdash;&mdash;删除文件夹<br>
End Sub<br>
Sub OnTransactionCommit<br>
Response.Write &quot;胜利完成任务&quot;<br>
End Sub<br>
%&gt;</p>
<p>第一行的&lt;%@ TRANSACTION = Required %&gt;表示这一页ASP文件需要MTS的事务支持。中间的各个操作都按普通顺序书写，而不用考虑回滚问题。在程序最后判断是否有错误。如果有，调用ObjectContext的SetAbort方法，IIS会通过MTS服务通知所有支持事务的组件回滚（主要是数据库），并且运行Sub OnTransactionAbort对不支持事务的操作手工回滚；如果没有发生错误，调用ObjectContext的SetComplete方法，则会运行Sub OnTransactionCommit来显示成功的消息。<br>
整个ASP程序不需要为判断错误和回滚操作书写多余的代码，只须在最后进行判断，即使今后增加了多步操作，也只需要在Sub OnTransactionAbort中进行控制即可，非常方便，程序员可以专注于过程编写而不是书写纠错代码。<br>
其实ASP还提供了许多更有用的功能，等着我们使用，千万不要以为ASP使用脚本语言，功能就一定弱。</p>
<p><br>
比较ADO回滚：<br>
&lt;% <br>
'Asp中使用事务 <br>
Set conn=Server.CreateObject(&quot;ADODB.Connection&quot;) <br>
conn.Open &quot;course_dsn&quot;,&quot;course_user&quot;,&quot;course_password&quot; <br>
conn.begintrans '开始事务</p>
<p>sql=&quot;delete from user_info&quot; <br>
set rs=server.createobject(&quot;adodb.recordset&quot;) <br>
rs.open sql,conn,3,3 <br>
if conn.errors.count&gt;0 then '有错误发生 <br>
conn.rollbacktrans '回滚 <br>
set rs=nothing <br>
conn.close <br>
set conn=nothing <br>
response.write &quot;交易失败，回滚至修改前的状态！&quot; <br>
response.end <br>
else <br>
conn.committrans '提交事务 <br>
set rs=nothing <br>
conn.close <br>
set conn=nothing <br>
response.write &quot;交易成功！&quot; <br>
response.end <br>
end if <br>
%&gt; <br>
 <br>
 <br>
 <br>
 <br>
 <br>
 <br>
 </p>
<p><br>
SqlHelper最开始出现好像是在Microsoft PetShop 作为DAL层的核心。</p>
<p>另外关于SqlDataReader，我感觉这个东西和ADO里面的RecordSet类似，就是需要Close.<br>
如果做为参数和返回值传递是比较危险的，因为你要传出去就Close(),而究竟在哪里关闭容易被以往和忽略，所以我觉得还是用强类型的DataSet做为参数和返回值传递纪录集比较好。</p>
<p>据说下面的写法不用Close也会自动资源回收，不知道真的假的：</p>
<p>using(SqlDataReader reader=SqlHelper.ExecuteReader(SqlHelper.CONN_STRING_NON_DTC,CommandType.Text,sql))<br>
{<br>
if(reader.Read())<br>
{</p>
<p>SqlParameter[]&nbsp;&nbsp;&nbsp;  signOnParms&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  GetSignOnParameters();  <br>
SqlParameter[]&nbsp;&nbsp;&nbsp;  accountParms&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  GetAccountParameters();  <br>
SqlParameter[]&nbsp;&nbsp;&nbsp;  profileParms&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  GetProfileParameters();  <br>
&nbsp;&nbsp;  <br>
signOnParms[0].Value&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  acc.UserId;  <br>
signOnParms[1].Value&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  acc.Password;  <br>
&nbsp;&nbsp;  <br>
SetAccountParameters(accountParms,&nbsp;&nbsp;&nbsp;  acc);  <br>
SetProfileParameters(profileParms,&nbsp;&nbsp;&nbsp;  acc);  <br>
&nbsp;&nbsp;  <br>
  using&nbsp;&nbsp;&nbsp;  (SqlConnection&nbsp;&nbsp;&nbsp;  conn&nbsp;&nbsp;  =&nbsp;&nbsp;  new&nbsp;&nbsp;&nbsp;  SqlConnection(SQLHelper.CONN_STRING_NON_DTC))&nbsp;&nbsp;  {  <br>
&nbsp;&nbsp;  conn.Open();  <br>
  using&nbsp;&nbsp;&nbsp;  (SqlTransaction&nbsp;&nbsp;&nbsp;  trans&nbsp;&nbsp;  =&nbsp;&nbsp;&nbsp;  conn.BeginTransaction())&nbsp;&nbsp;  {  <br>
  try&nbsp;&nbsp;  {  <br>
&nbsp;&nbsp;  SQLHelper.ExecuteNonQuery(trans,&nbsp;&nbsp;&nbsp;  CommandType.Text,&nbsp;&nbsp;&nbsp;  SQL_INSERT_SIGNON,&nbsp;&nbsp;&nbsp;  signOnParms);  <br>
&nbsp;&nbsp;  SQLHelper.ExecuteNonQuery(trans,&nbsp;&nbsp;&nbsp;  CommandType.Text,&nbsp;&nbsp;&nbsp;  SQL_INSERT_ACCOUNT,&nbsp;&nbsp;&nbsp;  accountParms);  <br>
&nbsp;&nbsp;  SQLHelper.ExecuteNonQuery(trans,&nbsp;&nbsp;&nbsp;  CommandType.Text,&nbsp;&nbsp;&nbsp;  SQL_INSERT_PROFILE,&nbsp;&nbsp;&nbsp;  profileParms);  <br>
&nbsp;&nbsp;  trans.Commit();  <br>
&nbsp;&nbsp;  <br>
&nbsp;&nbsp;  }catch&nbsp;&nbsp;  {  <br>
&nbsp;&nbsp;  trans.Rollback();  <br>
  throw;  <br>
&nbsp;&nbsp;  }  <br>
&nbsp;&nbsp;  }  <br>
&nbsp;&nbsp;  }</p> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/stresume/blog/category/%2Enet%BC%BC%CA%F5">.net技术</a>&nbsp;<a href="http://hi.baidu.com/stresume/blog/item/9bd7e1032f09cbe608fa93fd.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月22日 星期四  11:46</pubDate>
        <category><![CDATA[.net技术]]></category>
        <author><![CDATA[stresume]]></author>
		<guid>http://hi.baidu.com/stresume/blog/item/9bd7e1032f09cbe608fa93fd.html</guid>
</item>


</channel>
</rss>