﻿<?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++博客-Welcome to ErranLi's Blog!-随笔分类-dotNet</title><link>http://www.cppblog.com/erran/category/15116.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 19 May 2012 23:44:11 GMT</lastBuildDate><pubDate>Sat, 19 May 2012 23:44:11 GMT</pubDate><ttl>60</ttl><item><title>进程间通讯：消息（.net app 与 mfc dll）</title><link>http://www.cppblog.com/erran/archive/2012/05/19/175360.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 19 May 2012 01:27:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2012/05/19/175360.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/175360.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2012/05/19/175360.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/175360.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/175360.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp; http://www.cppblog.com/erran/archive/2012/05/19/175360.html&nbsp;C#消息处理函数引用&nbsp;&nbsp; /// &lt;summary&gt;&nbsp;/// &lt;para&gt;    版    权 : Copyright (c) 20010-2011 &lt;/para&...&nbsp;&nbsp;<a href='http://www.cppblog.com/erran/archive/2012/05/19/175360.html'>阅读全文</a><img src ="http://www.cppblog.com/erran/aggbug/175360.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2012-05-19 09:27 <a href="http://www.cppblog.com/erran/archive/2012/05/19/175360.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>  C#中结构体与字节流互相转换 </title><link>http://www.cppblog.com/erran/archive/2011/06/29/149751.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Wed, 29 Jun 2011 08:50:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2011/06/29/149751.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/149751.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2011/06/29/149751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/149751.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/149751.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p><br />一、c#结构体<br />&nbsp;<br />1、定义与C++对应的C#结构体</p>
<p>&nbsp;<br />在c#中的结构体不能定义指针，不能定义字符数组，只能在里面定义字符数组的引用。 <br />C++的消息结构体如下： <br />//消息格式 4+16+4+4= 28个字节 <br />struct cs_message<br />{ <br />&nbsp;&nbsp;&nbsp; u32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd_type; <br />&nbsp;&nbsp;&nbsp; char username[16]; <br />&nbsp;&nbsp;&nbsp; u32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dstID; <br />&nbsp;&nbsp;&nbsp; u32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srcID; <br />};<br />&nbsp;<br />C#定义的结构体如下:<br />&nbsp;<br />[StructLayout(LayoutKind.Sequential, Pack = 1)]<br />public struct my_message <br />{ <br />&nbsp;&nbsp;&nbsp; public UInt32&nbsp; cmd_type;</p>
<p>&nbsp;&nbsp;&nbsp; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]<br />&nbsp;&nbsp;&nbsp; public string username;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; public UInt32&nbsp; dstID;</p>
<p>&nbsp;&nbsp;&nbsp; public UInt32&nbsp; srcID;</p>
<p>&nbsp;&nbsp;&nbsp; public my_message(string s)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd_type = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; username = s;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dstID = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srcID = 0;<br />&nbsp;&nbsp;&nbsp; } <br />}<br />&nbsp;<br />在C++的头文件定义中，使用了 #pragma pack 1 字节按1对齐，所以C#的结构体也必须要加上对应的特<br />性，LayoutKind.Sequential属性让结构体在导出到非托管内存时按出现的顺序依次布局,而对于C++的<br />char数组类型，C#中可以直接使用string来对应，当然了，也要加上封送的特性和长度限制。 </p>
<p>2、结构体与byte[]的互相转换<br />&nbsp;<br />定义一个类，里面有2个方法去实现互转：<br />&nbsp;<br />public class Converter <br />{ <br />&nbsp;&nbsp;&nbsp; public Byte[] StructToBytes(Object structure) <br />&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Int32 size = Marshal.SizeOf(structure); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(size); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IntPtr buffer = Marshal.AllocHGlobal(size); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Marshal.StructureToPtr(structure, buffer, false); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Byte[] bytes = new Byte[size]; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Marshal.Copy(buffer, bytes, 0, size); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bytes; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Marshal.FreeHGlobal(buffer); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public Object BytesToStruct(Byte[] bytes, Type strcutType) <br />&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Int32 size = Marshal.SizeOf(strcutType); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IntPtr buffer = Marshal.AllocHGlobal(size); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Marshal.Copy(bytes, 0, buffer, size); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Marshal.PtrToStructure(buffer, strcutType); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; finally <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Marshal.FreeHGlobal(buffer); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />&nbsp;&nbsp;&nbsp; } <br />}<br />&nbsp;<br />3、测试结果：<br />&nbsp;<br />static void Main(string[] args) <br />{ <br />&nbsp;&nbsp;&nbsp; //定义转换类的一个对象并初始化 <br />&nbsp;&nbsp;&nbsp; Converter Convert = new Converter();</p>
<p>&nbsp;&nbsp;&nbsp; //定义消息结构体 <br />&nbsp;&nbsp;&nbsp; my_message m; </p>
<p>&nbsp;&nbsp;&nbsp; //初始化消息结构体 <br />&nbsp;&nbsp;&nbsp; m = new my_message("yanlina"); <br />&nbsp;&nbsp;&nbsp; m.cmd_type = 1633837924; <br />&nbsp;&nbsp;&nbsp; m.srcID = 1633837924; <br />&nbsp;&nbsp;&nbsp; m.dstID = 1633837924;</p>
<p>&nbsp;&nbsp;&nbsp; //使用转换类的对象的StructToBytes方法把m结构体转换成Byte <br />&nbsp;&nbsp;&nbsp; Byte[] message = Convert.StructToBytes(m); <br />&nbsp;&nbsp;&nbsp; //使用转换类的对象的BytesToStruct方法把Byte转换成m结构体 <br />&nbsp;&nbsp;&nbsp; my_message n = (my_message)Convert.BytesToStruct(message, m.GetType()); <br />&nbsp;&nbsp;&nbsp; //输出测试 <br />&nbsp;&nbsp;&nbsp; Console.WriteLine(Encoding.ASCII.GetString(message)); <br />&nbsp;&nbsp;&nbsp; Console.WriteLine(n.username); <br />}<br />&nbsp;<br />结构体的size是28个字节和c++的结构体一样，同时可以将结构体和字节数组互转，方便UDP的发送和接收。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<br /><a href="http://blog.csdn.net/huxiangyang4/archive/2010/08/31/5853247.aspx">http://blog.csdn.net/huxiangyang4/archive/2010/08/31/5853247.aspx</a></p><img src ="http://www.cppblog.com/erran/aggbug/149751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2011-06-29 16:50 <a href="http://www.cppblog.com/erran/archive/2011/06/29/149751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c#值类型 引用类型</title><link>http://www.cppblog.com/erran/archive/2010/10/09/129220.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 09 Oct 2010 09:10:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2010/10/09/129220.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/129220.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2010/10/09/129220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/129220.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/129220.html</trackback:ping><description><![CDATA[<p>&nbsp;传值 值类型存放在栈中，直接访问。如果有：int a=0;int b=a;就产生了两个栈中对象。<br />引用类型需要在堆中显式分配，且不能直接访问，需要在栈中分配一个栈中对象(C++叫指针，C#叫引用)指向其堆中对象。<br />如果：<br />StringBuilder strb = new StringBuilder();<br />StringBuilder strb2 = strb;<br />则在堆中只有一个堆中对象，只是栈中有两个栈中对象指向堆中对象。<br />可以看出：每个变量都是一个栈中对象。不管是值类型还是引用类型，只是值类型的栈中对象就是其内容，而引用类型的栈中对象只是一个指向堆中对象的地址。 <br />参数传递分值传递和引用传递两种。<br />通常，在没有显式指出ref和out时都是值传递。</p>
<p>值传递：传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)<br />引用传递：传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)<br />现在用例子来说明传值跟传地址的不同：</p>
<p><br />private void button2_Click(object sender, System.EventArgs e)<br />...{<br />&nbsp; StringBuilder strb1 = new StringBuilder();<br />&nbsp; StringBuilder strb2 = new StringBuilder();<br />&nbsp; Test1(strb1);<br />&nbsp; Test2(ref strb2);<br />&nbsp; string str1 = strb1.ToString(); //str1值:"A"<br />&nbsp; string str2 = strb2.ToString(); //str2值:"BC"<br />}</p>
<p>void Test1(StringBuilder strb)<br />...{<br />&nbsp; //strb和strb1是两个栈中对象，但指向相同的地址，这个操作是改变堆中对象<br />&nbsp; strb.Append("A");</p>
<p>&nbsp; //这里将strb指向一个新的堆中对象，所以后面的操作与strb1指向的栈中对象无关<br />&nbsp; strb = new StringBuilder("B");<br />&nbsp; strb.Append("C");<br />}</p>
<p>void Test2(ref StringBuilder strb)<br />...{<br />&nbsp; //这里的strb和strb2是同一个栈中对象，所以改变strb的值使其指向另一个对象也等于改变strb2<br />&nbsp; strb = new StringBuilder("B");<br />&nbsp; strb.Append("C");<br />} <br /></p><img src ="http://www.cppblog.com/erran/aggbug/129220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2010-10-09 17:10 <a href="http://www.cppblog.com/erran/archive/2010/10/09/129220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GDI,CxImage,GDI+之比较</title><link>http://www.cppblog.com/erran/archive/2010/10/09/129219.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 09 Oct 2010 09:08:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2010/10/09/129219.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/129219.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2010/10/09/129219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/129219.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/129219.html</trackback:ping><description><![CDATA[<p>&nbsp;<br />GDI:</p>
<p><br />常用的绘图方式，但是压缩算法太差，大图压缩失真严重，并且支持图片类型太少,支持bmp.<br />一些绘图方法参考另一文章:图片镂空算法集合</p>
<p><br />CxImage:</p>
<p>是一个开源库，功能强大，其官方主页<a href="http://www.xdp.it/cximage/">http://www.xdp.it/cximage/</a><br />常用的5种:bmp,gif,png,jpg,ico<br />其他类型:tif,tga,pcx,wbmp,wmf,jp2,jpc,pgx,pnm,ras,jbg,mng,ska,raw <br />CxImage压缩算法较好，绘图速度快,4400*3000左右像素图片，容量3M左右，压缩到50*50，在快速拉动图片，并移动时，一点也不卡。</p>
<p>&nbsp;VS7.1环境配置<br />&nbsp;lib路径:在工程配置-&amp;gt;连接器-&amp;gt;常规-&amp;gt;附加目录库<br />&nbsp;加载lib:在工程配置-&amp;gt;连接器-&amp;gt;输入-&amp;gt;附加依赖项 <br />&nbsp;cximage.lib<br />&nbsp;jasper.lib<br />&nbsp;jbig.lib<br />&nbsp;Jpeg.lib<br />&nbsp;png.lib<br />&nbsp;Tiff.lib<br />&nbsp;zlib.lib<br />&nbsp;mng.lib<br />&nbsp;libdcr.lib</p>
<p>&nbsp;头文件路径:在工程配置c/c++-&amp;gt;常规-&amp;gt;附加包含目录<br />&nbsp;使用：只需要包含"xImage.h"</p>
<p>&nbsp;CxImage image;<br />&nbsp;image.Load()，CreateFromHBITMAP()等函数导入图片<br />&nbsp;image.Stretch(HDC,x,y,width,height);</p>
<p>GDI+:</p>
<p><br />同样功能强大，支持：bmp,jpg,gif,tiff,png.图片转换之前的算法应该是最好的，用大图去压缩，图片效果明显要比前两者好。<br />但是画大图时，速度太慢.比如以上4400*3000的图片，压缩到50*50,画图时间竟然是0.15秒，如果放在快速更新，或者移动的处理时，明显会延迟.</p>
<p><br />&nbsp;使用前，需要在APP文件中初使化GDI+<br />&nbsp;DWORD m_gdiplusToken;<br />&nbsp;CGameApp::InitInstance()<br />&nbsp;{<br />&nbsp;&nbsp; Gdiplus::GdiplusStartupInput gdiplusStartupInput;<br />&nbsp; Gdiplus::GdiplusStartup(&amp;amp;m_gdiplusToken, &amp;amp;gdiplusStartupInput, NULL);<br />&nbsp;} <br />&nbsp;int&nbsp; CGameApp::ExistInstance()<br />&nbsp;{<br />&nbsp; Gdiplus::GdiplusShutdown(m_gdiplusToken);<br />&nbsp; return 0;<br />&nbsp;}</p>
<p>&nbsp;Bitmap * pBmp = Bitmap::FromHBITMAP() 或者 Bitmap::FromFile() 等函数导入图片<br />&nbsp;Graphics gr(HDC);<br />&nbsp;gr.DrawImage(pBmp,x,y,Width,Height);</p>
<p>总结：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、一般绘图用GDI<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、需要不同类型的图片格式，并且要快速绘图的用CxImage<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、需要不同类型的图片格式，且要高质量图片效果的用GDI+</p>
<p>本文来自：<a href="http://blog.csdn.net/xuweiqun/archive/2009/07/20/4363627.aspx">http://blog.csdn.net/xuweiqun/archive/2009/07/20/4363627.aspx</a></p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/erran/aggbug/129219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2010-10-09 17:08 <a href="http://www.cppblog.com/erran/archive/2010/10/09/129219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】 c#值类型和引用类型的比较</title><link>http://www.cppblog.com/erran/archive/2010/10/09/129217.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 09 Oct 2010 09:07:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2010/10/09/129217.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/129217.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2010/10/09/129217.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/129217.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/129217.html</trackback:ping><description><![CDATA[<p>转载自 alva7864最终编辑 alva7864在C#中有两种类型的数据，一种是值类型数据，一种是引用类型数据。在编码的时候区分这两种类型数据，可以 避免一些细小的编码错误。 </p>
<p>首先说说什么类型是值类型，例如：int、float、bool之类的基础类型，以及用struct定义 的类型，如：DateTime。除此外，如 string，数组，以及用class定义的类型等都是引用类型。对于C#来说，很难罗列出所有类型进行一一分别，这需要自己在编码过程中进行分析总结。 <br />&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了更好地说明两种类型之间的区别，借用如下的表格来说明:</p>
<p>&nbsp; 值类型 引用类型 <br />内存分配地点 分配在栈中 分配在堆中 <br />效率 效率高，不需要地址转换 效率低，需要进行地址转换 <br />内存回收 使用完后，立即回收 使用完后，不是立即回收，等待GC回收 <br />赋值操作 进行复制，创建一个同值新对象 只是对原有对象的引用 <br />函数参数与返回值 是对象的复制 是原有对象的引用，并不产生新的对象 <br />类型扩展 不易扩展 容易扩展，方便与类型扩展 </p>
<p><br />通过如上细致对比，大家对于值类型和引用类型有个清楚的概念。</p>
<p>不过，无论是对于值类型还是引用类型来说，对于其作为函数参数或者返回值的时候，都是容易犯错误的地方。</p>
<p>对于值类型来说，当其 作为函数参数的时候，希望在函数中被修改，那么直接如下操作是不能被修改的:</p>
<p>public void Increment( int i )&nbsp;&nbsp;&nbsp; <br />{&nbsp;&nbsp;&nbsp; <br />　 i++;&nbsp;&nbsp;&nbsp; <br />}&nbsp;&nbsp; </p>
<p>要想在函数中对传进去的参数做真正的修改，需要借助于ref这个关键字，那么正确的形式如下: </p>
<p>public void Increment( ref int i )&nbsp;&nbsp;&nbsp; <br />{&nbsp;&nbsp;&nbsp; <br />　i++;&nbsp;&nbsp;&nbsp; <br />}&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也就是说，如果需要在函数中对值类型参数进行修改，需要用ref或者out进行标识才能真正实现。</p>
<p>而对于引用 类型来说，当其作为函数参数的时候，它所遇到的情况恰恰与值类型相反，即不希望在函数中被修改，举例如下:</p>
<p>public void AddValue( MyType typValue )&nbsp;&nbsp;&nbsp; <br />{&nbsp;&nbsp;&nbsp; <br />　typValue.Count = typValue.Count + 15;&nbsp;&nbsp;&nbsp; <br />}&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于对于引用类型对象来说，其的赋值操作只是对原有对象的引用，因此在函数对其修改，实际上是直接修改了原有对象数据，这是很多 情况不希望发生的（这里例如对数组或者DataTable操作这类）。</p>
<p>为了防止这种事发生，需要给此类型提供clone函数。例如对 于如上的类型，可以入下实现 :</p>
<p>public class MyType:ICloneable&nbsp;&nbsp;&nbsp; <br />{&nbsp;&nbsp;&nbsp; <br />　private int nCount = 0;&nbsp;&nbsp;&nbsp; <br />　public int Count&nbsp;&nbsp;&nbsp; <br />　{&nbsp;&nbsp;&nbsp; <br />　　set{ nCount = value;}&nbsp;&nbsp;&nbsp; <br />　　get{ return nCount;}&nbsp;&nbsp;&nbsp; <br />　}&nbsp;&nbsp;&nbsp; <br />　public MyType()&nbsp;&nbsp;&nbsp; <br />　{}&nbsp;&nbsp;&nbsp; <br />　public MyType( int Value)&nbsp;&nbsp;&nbsp; <br />　{&nbsp;&nbsp;&nbsp; <br />　　nCount = Value;&nbsp;&nbsp;&nbsp; <br />　}&nbsp;&nbsp;&nbsp; <br />　#region ICloneable Members&nbsp;&nbsp;&nbsp; <br />　public object Clone()&nbsp;&nbsp;&nbsp; <br />　{&nbsp;&nbsp;&nbsp; <br />　　// TODO: Add MyType.Clone implementation&nbsp;&nbsp;&nbsp; <br />　　return new MyType( nCount );&nbsp;&nbsp;&nbsp; <br />　}&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />　#endregion&nbsp;&nbsp;&nbsp; <br />}&nbsp;&nbsp; </p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp; 那么在调用的时候，用当前的对象的clone作为参数即可。</p>
<p>不过对于引用类型来说，提供一个clone函数不是一 件容易的事情，尤其出现引用类型嵌套的时候，所以说去实现一个完全clone功能是件很费事又不讨好的活，这也就是在论坛中常说的深copy和浅copy 的问题。话虽如此，如果对于前面所说的有个大概了解，相信实现也不是不可能。</p>
<p>在C#中，尤其自己定义类型的时候，常常由于是用 struct来定义还是用class来定义，即是定义一个值类型还是一个引用类型呢。在这本书上给了几个判定条件，如果如下几点都满足的话，建议用 struct来定义为值类型，否则用class定义为引用类型。</p>
<p>&nbsp;</p>
<p>&lt;!--[if !supportLists]--&gt;1． &lt;!--[endif]--&gt;这个类型是否主要为了数据存储；<br />&lt;!--[if !supportLists]--&gt;2． &lt;!--[endif]--&gt;是否只通过属性来访问对象的数据成员；<br />&lt;!--[if !supportLists]--&gt;3． &lt;!--[endif]--&gt;这个类型是否不会有子类型；<br />&lt;!--[if !supportLists]--&gt;4． &lt;!--[endif]--&gt;在程序处理的时候不会把这个类型对象通过多态来处理。 <br /></p><img src ="http://www.cppblog.com/erran/aggbug/129217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2010-10-09 17:07 <a href="http://www.cppblog.com/erran/archive/2010/10/09/129217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c#画笔Pen自定义线的帽子</title><link>http://www.cppblog.com/erran/archive/2010/10/09/129215.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 09 Oct 2010 09:05:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2010/10/09/129215.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/129215.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2010/10/09/129215.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/129215.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/129215.html</trackback:ping><description><![CDATA[<p>c#画笔Pen自定义线的帽子&nbsp; <br />&nbsp;<br />1.using System;<br />2.using System.Collections.Generic;<br />3.using System.ComponentModel;<br />4.using System.Data;<br />5.using System.Drawing;<br />6.using System.Text;<br />7.using System.Windows.Forms;<br />8.using System.Drawing.Drawing2D;<br />9.10.namespace WindowsApplication2<br />11.{<br />12.&nbsp;&nbsp;&nbsp; public partial class Form11 : Form<br />13.&nbsp;&nbsp;&nbsp; {<br />14.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Form11()<br />15.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />16.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InitializeComponent();<br />17.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />18.19.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void button1_Click(object sender, EventArgs e)<br />20.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />21.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pen pen1 = new Pen(Color.Blue, 12);<br />22.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pen1.EndCap = LineCap.Custom;<br />23.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pen1.CustomEndCap = new AdjustableArrowCap(5f, 5f, true);<br />24.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Graphics g1 = this.CreateGraphics();<br />25.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g1.DrawLine(pen1, 10, 100, 100,100);<br />26.27.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />28.&nbsp;&nbsp;&nbsp; }<br />29.}</p>
<p>&nbsp;</p><img src ="http://www.cppblog.com/erran/aggbug/129215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2010-10-09 17:05 <a href="http://www.cppblog.com/erran/archive/2010/10/09/129215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> GDI+的核心：Graphics类</title><link>http://www.cppblog.com/erran/archive/2010/10/09/129213.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 09 Oct 2010 09:02:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2010/10/09/129213.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/129213.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2010/10/09/129213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/129213.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/129213.html</trackback:ping><description><![CDATA[<p>&nbsp;GDI+的核心：Graphics类</p>
<p><br />（1）The Graphics class provides methods for drawing lines, curves, figures, images, and text. A Graphics object stores attributes of the display device and attributes of the items to be drawn.【msdn】</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Graphics是一个device context和你的drawing conetent之间的一个中介。它存储了device context的相关属性，以及drawing content的属性。这样，它就能用自己的方法把drawing content&#8220;映射&#8221;到device content 之上。</p>
<p>（2）GDI+的核心是Graphics类，包含了显示、绘图等功能。它提供了四个构造函数：<br />&nbsp;&nbsp; Graphics::Graphics(Image*)<br />&nbsp;&nbsp; Graphics::Graphics(HDC)<br />&nbsp;&nbsp; Graphics::Graphics(HDC,HANDLE)<br />&nbsp;&nbsp; Graphics::Graphics(HWND,BOOL)</p>
<p>&nbsp;&nbsp; 构造函数1从image对象创建一个Graphics类。这种方式允许你在打开某张，或者生成某张位图之后，应用Grapgics的方法对改位图进行操作。</p>
<p>&nbsp;&nbsp; 构造函数2从一个传统的HDC获取一个Graphics对象，把传统的在HDC完成的操作接手过来。也就是当要画直线，曲线，图形等时，采用这种构造函数。</p>
<p>&nbsp;&nbsp; 后面两种构造函数这里不说了！</p>
<p>（3）如果读者有GDI编程经验的话，应该会联想起CDC::CreateCompatibleDC和CBitmap::<br />CreateCompatibleBitmap吧？再列举Graphics中有代表性的用于绘图的成员函数：<br />&nbsp;&nbsp; Graphics::DrawArc(Pen*,INT,INT,INT,INT,REAL,REAL)<br />&nbsp;&nbsp; Graphics::DrawBeziers(Pen*,Point*,INT)<br />&nbsp;&nbsp; Graphics::DrawClosedCurve(Pen*,Point*,INT)<br />&nbsp;&nbsp; Graphics::DrawCurve(Pen*,Point*,INT)<br />&nbsp;&nbsp; Graphics::DrawEllipse(Pen*,Rect&amp;amp;)<br />&nbsp;&nbsp; Graphics::DrawImage(Image*,RectF&amp;amp;)<br />&nbsp;&nbsp; Graphics::DrawLine(Pen*,Point&amp;amp;,Point&amp;amp;)<br />&nbsp;&nbsp; Graphics::DrawPie(Pen*,Rect&amp;amp;,REAL,REAL)<br />&nbsp;&nbsp; Graphics::DrawPolygon(Pen*,Point*,INT*)<br />&nbsp;&nbsp; Graphics::DrawRectangle(Pen*,Rect&amp;amp;)<br />&nbsp;&nbsp; 是不是非常象CDC？从这里大家也能猜出一点Graphics类和CDC类的异同吧！简单的说，Graphics的层次更高一些，封装的更好。</p>
<p><br />2&nbsp; GDI+的几个特点：</p>
<p>&nbsp;&nbsp; （1）传统的GDI编程最痛苦的是什么？是不停的CreateObject，SeleteObject，DeleteObject&#8212;&#8212;代码繁琐，一不小心还会内存泄露&#8230;&#8230;现在GDI+结束了这一切，就凭这一个理由，也足够我们转向GDI+了，呵呵。从上面的几个成员函数可以看出来，每个绘图动作都指定了画笔、刷子或者Image，完全抛弃了SelectObject的概念。</p>
<p>&nbsp;&nbsp; （2）GDI+里面的颜色更加丰富，全面支持32位色，从Color类的构造函数就可以看出来：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color::Color(BYTE a, BYTE r, BYTE g, BYTE b);其中a就是透明度。</p>
<p>&nbsp;&nbsp; （3）GDI+里的所有函数都只接受Unicode字符串，编写代码的时候需要注意这一点。</p>
<p><br />本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/keyouan2008/archive/2010/08/13/5809519.aspx">http://blog.csdn.net/keyouan2008/archive/2010/08/13/5809519.aspx</a></p><img src ="http://www.cppblog.com/erran/aggbug/129213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2010-10-09 17:02 <a href="http://www.cppblog.com/erran/archive/2010/10/09/129213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>