﻿<?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++博客-λ-calculus（惊愕到手了欧耶，GetBlogPostIds.aspx）-随笔分类-GacUI</title><link>http://www.cppblog.com/vczh/category/17975.html</link><description>【QQ：343056143】【Email：vczh@163.com】【新浪微博：http://weibo.com/vczh】</description><language>zh-cn</language><lastBuildDate>Sun, 20 Jan 2013 04:22:43 GMT</lastBuildDate><pubDate>Sun, 20 Jan 2013 04:22:43 GMT</pubDate><ttl>60</ttl><item><title>自从昨天我发现VS2012可以编译出支持XP的代码之后，我决定在GacUI里面全面使用C++11新功能</title><link>http://www.cppblog.com/vczh/archive/2013/01/20/197421.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sun, 20 Jan 2013 03:39:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2013/01/20/197421.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/197421.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2013/01/20/197421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/197421.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/197421.html</trackback:ping><description><![CDATA[<div>昨天研究发现，只要安装了Update 1的Visual Studio 2012也可以编译出支持XP的程序了。为了让GacUI可以顺利运行在XP上（虽然现在因为两个api还不能），我一直试图让GacUI兼容VS2010。VS2010对lambda的支持的bug很多，所以导致GacUI无法全面使用C++11来开发。但是现在VS2012也可以编译出支持XP的程序了，这就意味着，我使用C++11再也不用受到束缚了，啊哈哈哈哈哈。</div><img src ="http://www.cppblog.com/vczh/aggbug/197421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2013-01-20 11:39 <a href="http://www.cppblog.com/vczh/archive/2013/01/20/197421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++使用Uniscribe进行文字自动换行的计算和渲染</title><link>http://www.cppblog.com/vczh/archive/2012/11/06/194817.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Tue, 06 Nov 2012 14:34:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/11/06/194817.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/194817.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/11/06/194817.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/194817.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/194817.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Uniscribe是Windows 2000以来就存在于WinAPI中的一个库。这个库能够提供给我们关于字符串渲染的很多信息，譬如说哪里可以换行啦，渲染的时候字符的顺序应该是什么样子啦，还有每一个字符的大小什么的。关于Uniscribe的资料可以在http://msdn.microsoft.com/en-us/library/windows/desktop/dd374091(v=vs.85).as...&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/11/06/194817.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/194817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-11-06 22:34 <a href="http://www.cppblog.com/vczh/archive/2012/11/06/194817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个在GacUI上直接使用GDI或者Direct2D进行绘图操作的小demo</title><link>http://www.cppblog.com/vczh/archive/2012/11/05/194696.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Mon, 05 Nov 2012 15:14:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/11/05/194696.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/194696.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/11/05/194696.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/194696.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/194696.html</trackback:ping><description><![CDATA[<p><font color="#000000"><span style="color: #000000">由于接下去要用</span></font><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd374091(v=vs.85).aspx" target="_blank"><u>uniscribe</u></a><font color="#000000"><span style="color: #000000">（这是一个可以告诉我们在渲染一个超长unicode字符串的时候，什么地方可以换行，什么地方要换顺序，什么字符要用一种神奇的方法来渲染之类的库）做可以插入图片和其它乱七八糟东西的rich text box，为了更方便做实验，而且也考虑到很多软件也需要直接绘图的功能，所以我写了这么两个Demo：</span></font></p>
<p><font color="#000000"><span style="color: #000000">1、Rendering.RawAPI.GDI（</span></font><a title="http://www.gaclib.net/Demos/Rendering.RawAPI.GDI/Demo.html" href="http://www.gaclib.net/Demos/Rendering.RawAPI.GDI/Demo.html" target="_blank"><u>http://www.gaclib.net/Demos/Rendering.RawAPI.GDI/Demo.html</u></a><font color="#000000"><span style="color: #000000">）</span><br /><span style="color: #000000">2、Rendering.RawAPI.Direct2D（</span></font><a title="http://www.gaclib.net/Demos/Rendering.RawAPI.Direct2D/Demo.html" href="http://www.gaclib.net/Demos/Rendering.RawAPI.Direct2D/Demo.html" target="_blank"><u>http://www.gaclib.net/Demos/Rendering.RawAPI.Direct2D/Demo.html</u></a><font color="#000000"><span style="color: #000000">）</span></font></p>
<p><font color="#000000"><span style="color: #000000">由于这两个Demo很像，而且Direct2D的比较复杂，所以我在这里介绍一下这个Direct2D的demo。</span></font></p>
<p><font color="#000000"><span style="color: #000000">在Demo里面可以看到，我们可以使用GuiGDIElement或者GuiDirect2DElement来进行手工的绘图操作。这两个Element的使用有限制。当GacUI使用GDI绘图（SetupWindowsGDIRenderer）的时候才可以使用GuiGDIElement，对于Direct2D也是一样的。在使用它们进行绘图的时候，坐标用的是窗口的坐标。但是GacUI会在绘制的时候先加入一个clip，这样我们在绘制的时候就算绘制出了边界，也不会有任何不好的影响。而且这个clip的矩形范围会在渲染事件触发的时候给出。在这里我们先来看一下Direct2D的demo。</span></font></p>
<p><font color="#000000"><span style="color: #000000">首先，整个程序的框架是这样子的：</span></font></p>
<p><font color="#666666">#include "..\..\Public\Source\GacUI.h"<br />#include &lt;math.h&gt;<br />#include &lt;Windows.h&gt;</font></p>
<p><font color="#666666">int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp; // SetupWindowsDirect2DRenderer() is required for GuiDirect2DElement<br />&nbsp;&nbsp;&nbsp; return SetupWindowsDirect2DRenderer();<br />}</font></p>
<p><font color="#666666">class Direct2DWindow : public GuiWindow<br />{<br />protected:</font></p>
<p><font color="#666666">&nbsp;&nbsp;&nbsp; // arguments.rt is ID2D1RenderTarget.<br />&nbsp;&nbsp;&nbsp; void element_Rendering(GuiGraphicsComposition* sender, GuiDirect2DElementEventArgs&amp; arguments)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; }</font></p>
<p><font color="#666666">&nbsp;&nbsp;&nbsp; // The render target is going to be destroyed, any binded resources should be released.<br />&nbsp;&nbsp;&nbsp; void element_BeforeRenderTargetChanged(GuiGraphicsComposition* sender, GuiDirect2DElementEventArgs&amp; arguments)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; }</font></p>
<p><font color="#666666">&nbsp;&nbsp;&nbsp; // The new render target is prepared, any binded resources are allowed to recreate now.<br />&nbsp;&nbsp;&nbsp; void element_AfterRenderTargetChanged(GuiGraphicsComposition* sender, GuiDirect2DElementEventArgs&amp; arguments)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; }<br />public:<br />&nbsp;&nbsp;&nbsp; Direct2DWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :GuiWindow(GetCurrentTheme()-&gt;CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetText(L"Rendering.RawAPI.Direct2D");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SetClientSize(Size(640, 480));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetBoundsComposition()-&gt;SetPreferredMinSize(Size(640, 480));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br /></font><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000"><strong>GuiDirect2DElement* element=GuiDirect2DElement::Create();<br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000"><strong>element-&gt;Rendering.AttachMethod(this, &amp;Direct2DWindow::element_Rendering);<br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000"><strong>element-&gt;BeforeRenderTargetChanged.AttachMethod(this, &amp;Direct2DWindow::element_BeforeRenderTargetChanged);<br /></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>element-&gt;AfterRenderTargetChanged.AttachMethod(this, &amp;Direct2DWindow::element_AfterRenderTargetChanged);</strong></font></p>
<p><font color="#666666">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GuiBoundsComposition* composition=new GuiBoundsComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; composition-&gt;SetAlignmentToParent(Margin(0, 0, 0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; composition-&gt;SetOwnedElement(element);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetContainerComposition()-&gt;AddChild(composition);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />};</font></p>
<p><font color="#666666">void GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp; Direct2DWindow window;<br />&nbsp;&nbsp;&nbsp; GetApplication()-&gt;Run(&amp;window);<br />}</font></p>
<p><font color="#000000">在构造函数里面，我们创建了一个GuiDirect2DElement，然后把它放进一个会自动充满整个窗口的composition里面。然后我们需要监听三个事件（GDI只有一个，就是Rendering）：<br />1、Rendering。这个事件在窗口被绘制的时候调用。GacUI才用了一个低功耗的方法让程序不断的绘制自己，所以我们并不需要担心&#8220;如何刷新窗口&#8221;的这个问题。<br />2、BeforeRenderTargetChanged。在这个时候我们要清理掉我们创建出来的资源，譬如说画刷等等。<br />3、AfterRenderTargetChanged。在这个时候我们要建立一些绘图资源，譬如说画刷等等。</font></p>
<p><font color="#000000">为什么下面两个函数那么蛋疼呢？因为Direct2D的类似画刷这样的东西，是必须跟一个ID2D1RenderTarget绑定在一起的，不同的render target之间的画刷不能共享。而且那个可怜的render target还有可能会失效，这个时候GacUI就要重新创建他们。所以无论如何，都必须监听这三个对象，除非我们只用GuiDirect2DElement来渲染文字（因为文字相关的资源是IDWriteFactory控制的，跟render target无关）。</font></p>
<p><font color="#000000">在这个Demo里面，我们要画的是一个会动的钟。在这个钟里面我们要绘制4种线形：边框、时针、分针、秒针。因此我们需要4个不同的ID2D1SolidColorBrush。由于操作COM对象的时候总要去记得操作那个引用计数，特别的麻烦，而且还容易忘掉。所以我特地为大家提供了一个叫做ComPtr的东西。所以我们就可以这么声明、创建和释放他们：</font></p>
<p><font color="#666666">ComPtr&lt;ID2D1SolidColorBrush&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; borderBrush;<br />ComPtr&lt;ID2D1SolidColorBrush&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; secondBrush;<br />ComPtr&lt;ID2D1SolidColorBrush&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minuteBrush;<br />ComPtr&lt;ID2D1SolidColorBrush&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hourBrush;<br /><br />// The render target is going to be destroyed, any binded resources should be released.<br />void element_BeforeRenderTargetChanged(GuiGraphicsComposition* sender, GuiDirect2DElementEventArgs&amp; arguments)<br />{<br />&nbsp;&nbsp;&nbsp; borderBrush=0;<br />&nbsp;&nbsp;&nbsp; secondBrush=0;<br />&nbsp;&nbsp;&nbsp; minuteBrush=0;<br />&nbsp;&nbsp;&nbsp; hourBrush=0;<br />}</font></p>
<p><font color="#666666">// The new render target is prepared, any binded resources are allowed to recreate now.<br />void element_AfterRenderTargetChanged(GuiGraphicsComposition* sender, GuiDirect2DElementEventArgs&amp; arguments)<br />{<br />&nbsp;&nbsp;&nbsp; ID2D1SolidColorBrush* brush;<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brush=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arguments.rt-&gt;CreateSolidColorBrush(D2D1::ColorF(0.0f, 0.0f, 0.0f), D2D1::BrushProperties(), &amp;brush);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; borderBrush=brush;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brush=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arguments.rt-&gt;CreateSolidColorBrush(D2D1::ColorF(0.0f, 0.0f, 1.0f), D2D1::BrushProperties(), &amp;brush);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; secondBrush=brush;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brush=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arguments.rt-&gt;CreateSolidColorBrush(D2D1::ColorF(0.0f, 1.0f, 0.0f), D2D1::BrushProperties(), &amp;brush);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minuteBrush=brush;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brush=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arguments.rt-&gt;CreateSolidColorBrush(D2D1::ColorF(1.0f, 0.0f, 0.0f), D2D1::BrushProperties(), &amp;brush);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hourBrush=brush;<br />&nbsp;&nbsp;&nbsp; }<br />}</font></p>
<p><font color="#000000">想必大家都应该看清楚了。Before和After事件里面，GacUI都会提供用来绘图的ID2D1RenderTarget，这个时候必须正确的创建和释放资源。只要这些资源都建立了起来，那么剩下的就只有把一个时钟画出来了。画一个时钟还是很容易的，只需要那么几行代码就行了：</font></p>
<p>static const int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Radius=200;<br />static const int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LongScale=10;<br />static const int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ShortScale=5;<br />static const int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SecondLength=180;<br />static const int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MinuteLength=150;<br />static const int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HourLength=120;</p>
<p>float GetAngle(float second)<br />{<br />&nbsp;&nbsp;&nbsp; return (second-15.0f)*3.1416f/30.0f;<br />}</p>
<p>void DrawLine(ID2D1RenderTarget* rt, ComPtr&lt;ID2D1SolidColorBrush&gt; brush, float angle, int width, int startLength, int endLength, int x, int y)<br />{<br />&nbsp;&nbsp;&nbsp; float s=sin(angle);<br />&nbsp;&nbsp;&nbsp; float c=cos(angle);<br />&nbsp;&nbsp;&nbsp; float x1=(c*startLength)+(float)(x+Radius);<br />&nbsp;&nbsp;&nbsp; float y1=(s*startLength)+(float)(y+Radius);<br />&nbsp;&nbsp;&nbsp; float x2=(c*endLength)+(float)(x+Radius);<br />&nbsp;&nbsp;&nbsp; float y2=(s*endLength)+(float)(y+Radius);<br />&nbsp;&nbsp;&nbsp; rt-&gt;DrawLine(D2D1::Point2F(x1, y1), D2D1::Point2F(x2, y2), brush.Obj(), (float)width);<br />}</p>
<p>// arguments.rt is ID2D1RenderTarget.<br />void element_Rendering(GuiGraphicsComposition* sender, GuiDirect2DElementEventArgs&amp; arguments)<br />{<br />&nbsp;&nbsp;&nbsp; int w=arguments.bounds.Width();<br />&nbsp;&nbsp;&nbsp; int h=arguments.bounds.Height();<br />&nbsp;&nbsp;&nbsp; int x=arguments.bounds.Left()+(w-Radius*2)/2;<br />&nbsp;&nbsp;&nbsp; int y=arguments.bounds.Left()+(h-Radius*2)/2;</p>
<p>&nbsp;&nbsp;&nbsp; arguments.rt-&gt;DrawEllipse(D2D1::Ellipse(D2D1::Point2F((float)(x+Radius), (float)(y+Radius)), (float)Radius, (float)Radius), borderBrush.Obj());<br />&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;60;i++)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int scale=i%5==0?LongScale:ShortScale;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float angle=GetAngle((float)i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawLine(arguments.rt, borderBrush, angle, 1, Radius-scale, Radius, x, y);<br />&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; DateTime dt=DateTime::LocalTime();<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float angle=GetAngle(dt.hour*5+dt.minute/12.0f+dt.second/720.0f);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawLine(arguments.rt, hourBrush, angle, 5, 0, HourLength, x, y);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float angle=GetAngle(dt.minute+dt.second/60.0f);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawLine(arguments.rt, minuteBrush, angle, 3, 0, MinuteLength, x, y);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float angle=GetAngle((float)dt.second);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawLine(arguments.rt, secondBrush, angle, 1, 0, SecondLength, x, y);<br />&nbsp;&nbsp;&nbsp; }<br />}</p>
<p><font color="#000000">然后我们就获得了下图：（LiveWrite真是太好了，cppblog的傻逼编辑器每次插入图片都会插入到一个诡异的位置中去）</font></p>
<p><a href="http://www.cppblog.com/images/cppblog_com/vczh/Windows-Live-Writer/GacUI_1405F/DXGUI_58_2.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="DXGUI_58" border="0" alt="DXGUI_58" src="http://www.cppblog.com/images/cppblog_com/vczh/Windows-Live-Writer/GacUI_1405F/DXGUI_58_thumb.jpg" width="660" height="522" /></a></p>
<p><font color="#000000">这样我们就完成了一个时钟的制作了，而且也学会了如何在GacUI里面直接使用GDI和Direct2D绘图了。</font></p><img src ="http://www.cppblog.com/vczh/aggbug/194696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-11-05 23:14 <a href="http://www.cppblog.com/vczh/archive/2012/11/05/194696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI 0.4.0.0 发布啦</title><link>http://www.cppblog.com/vczh/archive/2012/10/19/193525.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Fri, 19 Oct 2012 06:16:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/10/19/193525.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/193525.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/10/19/193525.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/193525.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/193525.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要:     昨晚终于发布了GacUI 0.4.0.0，也就是第五个release了。现在GacUI的源代码可以在三个地方找到，分别是：<br>    Codeplex：http://gac.codeplex.com<br>    Github：https://github.com/vczh/gac<br>    主页：http://www.gaclib.net<br><br>    这两个月在开发GacUI的对象的反射系统之外，一直在做Windows 8的皮肤。现在的GacUI已经拥有了两个皮肤，一个是模仿Windows 7的，另一个是模仿Windows 8的。GacUI在启动的时候，会根据Windows的版本来自己选择要用哪个皮肤做缺省皮肤。使用g::NewXXX()函数创建的控件都会直接使用当前的皮肤（如果没有用SetCurrentTheme替换掉的话，就是缺省皮肤）来创建控件，否则，直接new控件类的话，要传入一个创建好的皮肤对象。<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/10/19/193525.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/193525.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-10-19 14:16 <a href="http://www.cppblog.com/vczh/archive/2012/10/19/193525.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI与设计模式（二）——渲染系统</title><link>http://www.cppblog.com/vczh/archive/2012/10/08/193031.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Mon, 08 Oct 2012 15:40:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/10/08/193031.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/193031.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/10/08/193031.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/193031.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/193031.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">所有关于渲染的部分的代码可以在</span><span lang="EN-US"><font face="Calibri"><a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank"><span lang="EN-US"><font face="Calibri"><span>http://gac.codeplex.com</span></font></span></a></font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">下载下来之后，在</span><span lang="EN-US"><font face="Calibri">\Libraries\GacUI\Source\GraphicsElement</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">目录下面找到。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">整个渲染系统的主要思想就是，图元（</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsElement</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）和渲染器（</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsRenderer</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）分开，而且粒度根据性能的要求粗细都有。为什么要这么设计呢？在前言里面说过，不同的渲染设备，譬如</span><span lang="EN-US"><font face="Calibri">GDI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">和</span><span lang="EN-US"><font face="Calibri">DirectX</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，需要的渲染策略和</span><span lang="EN-US"><font face="Calibri">cache</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">资源的方法都不太一样。因此为了让各个渲染设备的渲染器可以充分自定义渲染的策略，于是做出了这样的设计。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">但是具体是怎么做的呢？在</span><span lang="EN-US"><font face="Calibri">GacUI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">里面，首先可以用</span><span lang="EN-US"><font face="Calibri">GetGuiGraphicsResourceManager</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">来获取一个全局的资源管理器（</span><span lang="EN-US"><font face="Calibri">GuiGraphicsResourceManager</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）对象。这个对象的主要作用就是注册各种创建图元和渲染器的工厂对象。为了让整个渲染系统运行起来，首先我们要把各种图元工厂（</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsElementFactory</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）注册进去。每一个图元工厂有自己的一个全局的名字。这样当你把一个图元工厂注册金资源管理器之后，从此就可以用图元的名字从资源管理器里面取出注册进去的图元工厂对象了。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">其次，因为在运行的时候，每一个图元对象都会在内部保存一个专门给这个图元对象用的渲染器对象，具体的渲染设备的渲染器可以在这个渲染器对象里面</span><span lang="EN-US"><font face="Calibri">cache</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">一些资源，就可以达到为某个图元</span><span lang="EN-US"><font face="Calibri">cache</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">特殊的资源的目的了。因此为了给图元对象创建合适的渲染器对象，我们还需要将图元工厂的名字和一个渲染器工厂（</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsRendererFactory</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）关联起来。当这一步完成之后，我们就可以通过下面的代码来给一个图元关联上正确的渲染器对象：</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">IGuiGraphicsElement* element = xxxx;<br />IGuiGraphicsElementFactory* elementFactory = element-&gt;GetFactory();<br />IGuiGraphicsRendererFactory* rendererFactory = GetGuiGraphicsResourceManager()<br /><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;-&gt;</span>GetRendererFactory(elementFactory-&gt;GetElementTypeName());<br />IGuiGraphicsRenderer* renderer = rendererFactory-&gt;Create();<br />renderer-&gt;Initialize(element);</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">这样我们就从一个</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsElement</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">对象构造出了对应的</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsRenderer</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">对象，并且将这个渲染器对象和这个图元对象关联了起来。这一步完成之后，渲染器对象就会开始根据需要</span><span lang="EN-US"><font face="Calibri">cache</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">被关联的图元对象所需要的资源。然后我们只需要把渲染器对象的指针告诉图元对象，那么图元对象就可以在自己被更新的时候，通过调用</span><span lang="EN-US"><font face="Calibri">renderer-&gt;OnELementStateChanged()</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">适当通知一下渲染器对象，而且也可以用</span><span lang="EN-US"><font face="Calibri">renderer-&gt;GetMinSize()</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">来说的显示这个图元所需要的最小的矩形尺寸了。为什么尺寸要通过渲染器来计算呢？主要是因为具体怎么渲染是渲染器来控制的，所以尺寸当然也是需要让渲染其计算的，其中一个例子就是文字渲染了。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">接下来就是如何规划图元的问题了。目前</span><span lang="EN-US"><font face="Calibri">GacUI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">所有的图元如下所示：</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">Gui3DBorderElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">Gui3DSplitterElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiGradientBackgroundElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiImageFrameElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiPolygonElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiRoundBorderElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiSolidBackgroundElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiSolidBorderElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiSolidLabelElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><font face="Calibri">GuiColorizedTextElement</font></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">我们可以看到，大部分的图元都是很简单的。</span><span lang="EN-US"><font face="Calibri">GuiSolidLabelElement</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">就稍微复杂一点，具有了一些诸如自动换行啊省略号这样的设置。而最复杂的就是</span><span lang="EN-US"><font face="Calibri">GuiColorizedTextElement</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">了，里面按行保存了文本之后，还按行给每一个字符分配了存放颜色的缓冲区，然后实现了字符串修改的时候缓冲区的分配释放更新等操作。为什么不设计一个</span><span lang="EN-US"><font face="Calibri">GuiCharElement</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，而是做成了这两个东西呢？因为在普遍情况下，渲染器都支持对复杂的文字一次性渲染完成，如果我们把每一个字符都设计成一个图元，让排版引擎去渲染字符串的话，性能低下不说，效果可能还不如渲染器自己渲染出来的好。关于这里的一个典型的例子就是</span><span lang="EN-US"><font face="Calibri">Windows</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">所支持的可以连笔的</span><span lang="EN-US"><font face="Calibri">OpenType</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">技术了。另一个原因就是，在开发着色文本框的时候，如果所有的渲染过程不包含在一个图元，而是分散在各个字符图元的话，那更新文字和颜色的时候，无疑十分浪费内存，并且操作起来非常的麻烦，为了灵活性牺牲了太多的性能，得不偿失。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">说完了图元和渲染器，最后一个要介绍的就是渲染目标对象（</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsRenderTarget</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）了。尽管渲染目标可以指向很多种地方，但是在一般情况下，渲染目标所指向的都是一个窗口的客户区域（</span><span lang="EN-US"><font face="Calibri">client area</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">）。尽管在设计上这样看起来仅仅是很自然，但是实际上这么一个对象却是必须的，因为</span><span lang="EN-US"><font face="Calibri">Direct2D</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的一个</span><span lang="EN-US"><font face="Calibri">render target</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">创建出来的画刷等资源不能直接用在另一个</span><span lang="EN-US"><font face="Calibri">render target</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">上面，而且当</span><span lang="EN-US"><font face="Calibri">render target</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">挂掉的时候，那些资源要全部干掉，重新创建</span><span lang="EN-US"><font face="Calibri">render target</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">，并且重新创建资源。这一步作为一个</span><span lang="EN-US"><font face="Calibri">bug</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">登记在了</span><span lang="EN-US"><font face="Calibri">GacUI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">里面，还没实现，所以现在</span><span lang="EN-US"><font face="Calibri">Direct2D</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">渲染的时候，把窗口最小化再打开，有时候会变黑。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">渲染目标对象的另一个功能就是计算</span><span lang="EN-US"><font face="Calibri">clipping</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">了。在形成父子关系的排版对象绑定的图元在渲染的时候，子图元是不能超出父排版对象的矩形范围的。而且鉴于大量的对象可能处于不可见的位置，所以外围的驱动渲染的代码要在渲染对象完全被</span><span lang="EN-US"><font face="Calibri">clip</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">没了的时候（譬如说在一个具有滚动条的容器里面，一个因为滚动条的关系看不见的按钮），停止渲染看不见的那颗子树，加速渲染过程。而且各个渲染设备也需要处理类似于一个文字只有上半部分能看见这样的情形。所以排版对象就可以通过提供他自己的矩形范围给渲染目标对象，从而让渲染目标对象自己计算可见的矩形范围，从而配合整个渲染流程的进行。鉴于有一部分的渲染器需要的资源是从渲染目标对象来的，因此</span><span lang="EN-US"><font face="Calibri">IGuiGraphicsRenderer</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">还有一个叫做</span><span lang="EN-US"><font face="Calibri">SetRenderTarget</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的函数，用于在渲染对象发生变化的时候，譬如说因为窗口最小化从而造成</span><span lang="EN-US"><font face="Calibri">Direct2D</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的</span><span lang="EN-US"><font face="Calibri">render target</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的时效，需要重新创建的时候，通知每一个图元绑定的渲染器说，整个渲染目标对象已经换掉了，一些资源可能要重新创建。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">当然在这里需要提出的就是，在</span><span lang="EN-US"><font face="Calibri">GacUI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的</span><span lang="EN-US"><font face="Calibri">GDI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">和</span><span lang="EN-US"><font face="Calibri">Direct2D</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">渲染器的实现里面，是有一些依靠引用计数全局</span><span lang="EN-US"><font face="Calibri">cache</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的资源。譬如说在同一个渲染目标对象里面渲染的两个同样颜色的矩形，他在内部使用的具体的画刷就不会真的重复创建两次。尽管</span><span lang="EN-US"><font face="Calibri">GDI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">和</span><span lang="EN-US"><font face="Calibri">Direct2D</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的策略不同，</span><span lang="EN-US"><font face="Calibri">GDI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的画刷是全局的，而</span><span lang="EN-US"><font face="Calibri">Direct2D</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的话刷只对一个</span><span lang="EN-US"><font face="Calibri">render target</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">有效，</span><span lang="EN-US"><font face="Calibri">GacUI</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">还是提供了一个通用的资源</span><span lang="EN-US"><font face="Calibri">cache</font></span><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">算法模板，让实现类似的功能更加方便。</span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span lang="EN-US"><o:p><font face="Calibri">&nbsp;</font></o:p></span></p>
<p style="margin: 0cm 0cm 0pt" class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">有关渲染系统的内容就说到这里了，下一篇文章将会具体讲排版对象的内容。</span></p><img src ="http://www.cppblog.com/vczh/aggbug/193031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-10-08 23:40 <a href="http://www.cppblog.com/vczh/archive/2012/10/08/193031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI与设计模式（一）——前言</title><link>http://www.cppblog.com/vczh/archive/2012/09/18/191105.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Tue, 18 Sep 2012 06:31:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/09/18/191105.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/191105.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/09/18/191105.html#Feedback</comments><slash:comments>24</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/191105.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/191105.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 10pt"><span style="font-family: 宋体">说起</span>GacUI（<a style="text-decoration: underline" href="http://www.gaclib.net" target="_blank">www.gaclib.net</a>，<a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">gac.codeplex.com</a>）<span style="font-family: 宋体">，其实这个想法在我还在上大三的时候就已经有了。但是由于经验不足，在当时并没能够把这个东西给做出来，直到去年（</span>2011<span style="font-family: 宋体">）的国庆节为止。想想到现在也做了快一年了，</span>GacUI<span style="font-family: 宋体">也可以用来写一些不是特别残暴的</span>C++GUI<span style="font-family: 宋体">程序了。前几天有人问道，为什么在</span>PC<span style="font-family: 宋体">都快完蛋了并且大部分</span>GUI<span style="font-family: 宋体">都已经用</span>C#<span style="font-family: 宋体">来做的时候，我还要做这个东西呢？其实，这有两个原因：第一个我喜欢折腾</span>C++<span style="font-family: 宋体">；第二个</span>C++<span style="font-family: 宋体">好像也没什么特别好的</span>GUI<span style="font-family: 宋体">，因此也想尝试一下，如果做成了就维护下去，做不成了好歹还可以提高自己的水平，总之是不会浪费时间的。所以我就在想，</span>GacUI<span style="font-family: 宋体">写到现在也快一年了，并且我最近也看到</span>cppblog<span style="font-family: 宋体">上面有几个人也想搞搞</span>GUI<span style="font-family: 宋体">，因此我想把</span>GacUI<span style="font-family: 宋体">的一些设计思想，和我得到这些思想的过程写出来，顺便也介绍一下</span>GacUI<span style="font-family: 宋体">的架构，让一些有兴趣的人（特别是装配脑袋）也可以来折腾折腾。</span></p>
<p style="margin: 0cm 0cm 10pt">GacUI<span style="font-family: 宋体">的架构的最重要一点就是要跨平台。当然这不一定意味着我将来一定会把</span>GacUI<span style="font-family: 宋体">移植到别的什么操作系统去，但至少</span>Windows<span style="font-family: 宋体">的</span>Classic Desktop<span style="font-family: 宋体">和</span>Metro<span style="font-family: 宋体">的两套</span>API<span style="font-family: 宋体">就毫无相似之处，同时搞定他们，也算是跨平台了。而且就算是基于同一种</span>API<span style="font-family: 宋体">，上面还有不同的渲染器的</span>API<span style="font-family: 宋体">，譬如说</span>GDI<span style="font-family: 宋体">，譬如说</span>Direct2D<span style="font-family: 宋体">，他们也是截然不同。</span>GacUI<span style="font-family: 宋体">的设计至少要可以屏蔽掉他们的区别。当然，这在技术上有一个很好的方法来保证，就是</span>GacUIIncludes.h<span style="font-family: 宋体">里面不包含</span>Windows.h<span style="font-family: 宋体">的任何内容&#8212;&#8212;因此至少在头文件里面，所有的东西都是跟</span>Windows<span style="font-family: 宋体">无关的。当然在非</span>GUI<span style="font-family: 宋体">的部分，我们还是需要</span>Windows.h<span style="font-family: 宋体">的，并且有些人喜欢对</span>GacUI<span style="font-family: 宋体">做点</span>hack<span style="font-family: 宋体">的操作，因此我还是在</span>GacUI.h<span style="font-family: 宋体">里面提供了几个额外的依赖于</span>Windows.h<span style="font-family: 宋体">的函数来暴露一些内部细节。那这样如何跨</span>Classic Desktop<span style="font-family: 宋体">和</span>Metro<span style="font-family: 宋体">呢？有一个简单的方法，就是可以在编译的时候给些宏开关，譬如说</span>GACUI_WINDOWS_CLASSIC_DESKTOP<span style="font-family: 宋体">（缺省）或者</span>GACUI_WINDOWS_METRO<span style="font-family: 宋体">之类的东西，来屏蔽掉不需要的部分。当然这部分在移植到</span>Metro<span style="font-family: 宋体">之前我不会加进去。</span></p>
<p style="margin: 0cm 0cm 10pt"><span style="font-family: 宋体">基于这个想法，如果大家阅读了</span>GacUI<span style="font-family: 宋体">的代码的话，会发现在文件</span>\Libraries\GacUI\Source\NativeWindow\GuiNativeWindow.h<span style="font-family: 宋体">里面定义了一个</span>INativeController<span style="font-family: 宋体">接口，而且目前只有</span>Windows Classic Desktop<span style="font-family: 宋体">一个实现。</span>INativeController<span style="font-family: 宋体">的内容很多，提供了跟具体的平台有关的操作，譬如说读写图片文件啦、创建消灭窗口啦、显示器操作啦、还有各种其他的输入输出等等。实现一个从头</span>INativeController<span style="font-family: 宋体">还是比较繁琐的，因为</span>GUI<span style="font-family: 宋体">这种对操作系统重度依赖的东西，想剥离开来，就会发现他依赖了一大坨</span>API<span style="font-family: 宋体">。这也解释了为什么</span>INativeController<span style="font-family: 宋体">的各个</span>XXXService<span style="font-family: 宋体">函数返回的对象的方法的总和有上百个。不过从</span>Classic Desktop<span style="font-family: 宋体">移植到</span>Metro<span style="font-family: 宋体">还是相对比较简单的，因为大部分内容还是可以共享的。</span></p>
<p style="margin: 0cm 0cm 10pt"><span style="font-family: 宋体">其次就是渲染器了。渲染器跟平台是交叉依赖的。譬如说</span>OpenGL<span style="font-family: 宋体">在</span>linux<span style="font-family: 宋体">上和</span>Classic Desktop<span style="font-family: 宋体">上都可以用，</span>Direct2D<span style="font-family: 宋体">在</span>Classic Desktop<span style="font-family: 宋体">上和</span>Metro<span style="font-family: 宋体">上都可以用，</span>GDI<span style="font-family: 宋体">只能在</span>Classic Desktop<span style="font-family: 宋体">上面用。因此这就是为什么我最终没有把渲染器也写在</span>INativeController<span style="font-family: 宋体">里面，而是把渲染器整个给屏蔽掉了，根本没有在</span>GacUIIncludes.h<span style="font-family: 宋体">里面给出他的接口。但是考虑到</span>GacUI<span style="font-family: 宋体">是一个支持换肤的</span>GUI<span style="font-family: 宋体">库，因此肯定需要让皮肤来自己决定如何绘图。后来我就想了一个办法，把渲染器的结构整个拿掉，替换成各种各样的图元（</span>IGuiGraphicsElement<span style="font-family: 宋体">）。所谓的图元就是类似于方形啊，圆形啊，填充啊，渐变啊，文字之类的东西。皮肤自己把图元按照一定的排版关系（在下文中有描述）拼装好，然后</span>GacUI<span style="font-family: 宋体">内部的一个小系统会利用</span>Bridge<span style="font-family: 宋体">和</span>Abstract Factory<span style="font-family: 宋体">两个模式的结合体（参考</span>\Libraries\GacUI\Source\GraphicsElement\GuiGraphicsElement.h<span style="font-family: 宋体">）来为这些图元分配好渲染器对象（</span>IGuiGraphicsRenderer<span style="font-family: 宋体">）。然后图元和渲染器之间用了</span>Listener<span style="font-family: 宋体">模式在交换信息。这样的好处是，当图元受到改动的时候，这个图元对象的专用渲染器对象可以选择</span>cache<span style="font-family: 宋体">一些信息，然后在窗口渲染的时候，只需要访问所有的渲染器对象（在排版对象</span>GuiGraphicsComposition<span style="font-family: 宋体">的组合项形成了一棵树），让他们渲染自己就可以了。</span></p>
<p style="margin: 0cm 0cm 10pt"><span style="font-family: 宋体">图元包含了所有需要渲染的数据，但是唯独没有把尺寸写进去，因为尺寸这种东西不应该让渲染器来负责，而应该让排版对象来负责。排版对象自己是一棵树，然后节点根节点之间有一些关系，这样就可以实现堆栈排版、表格排版、对齐（到某一些边上的）排版等等具体的排版算法。一个排版对象可以放置一个图元对象并让这个图元充满他，所以显而易见，有一些排版对象仅仅是用来计算尺寸的中间结果，上面不一定有图元对象的。当渲染开始的时候，排版对象首先跟图元对象获取数据，然后递归计算好整棵排版树的尺寸，最后把尺寸交给附着在上面的图元对象的专用渲染器对象来渲染。</span></p>
<p style="margin: 0cm 0cm 10pt"><span style="font-family: 宋体">大家可能会想，如果渲染一次都需要调用成千上万个虚函数的话，会不会性能低下啊？当然编译成</span>Release<span style="font-family: 宋体">运行会发现</span>GacUI<span style="font-family: 宋体">的性能还是相当高的。原因有两个。第一个是我对排版对象做了一些优化。举个例子，一个对象的尺寸至少要大于所有子对象的尺寸，这个事情计算起来是相当快的，不需要做</span>cache<span style="font-family: 宋体">。但是一个表格排版里面的所有小格子会互相挤来挤去，这个东西计算起来相当复杂（复杂度大越是平方，而且系数也不笑），所以结果要做</span>cache<span style="font-family: 宋体">。但是什么时候需要重新计算呢？度量方法很简单，就是每一个格子的最小尺寸发生了变化的时候。而且事实上大部分皮肤都是用表格来排版的，所以等于说大部分结果都有</span>cache<span style="font-family: 宋体">。所以排版部分的尺寸在每一次渲染的时候只需要做一些小计算就可以了。复杂的排版每一个排版对象相互之间都是有关系的，一个排版对象发生了变化，有可能导致另一个排版对象的尺寸需要修改，所以最简单的方法就是，不保存尺寸，每一次都直接重新算一次就可以了。在这个基础上，表格排版做一下</span>cache<span style="font-family: 宋体">，整个计算过程就会变得飞快。所以尽管每一次拖动窗口，或者鼠标滑过一次窗口，都要进行相当多的计算，但是因为有一个智能的</span>cache<span style="font-family: 宋体">，使得不仅运算速度变快，而且在添加新的排版对象类型的时候也根本不需要考虑自己会不会被</span>cache<span style="font-family: 宋体">的问题，开发起来也相当愉悦。</span></p>
<p style="margin: 0cm 0cm 10pt"><span style="font-family: 宋体">所以上面的三大模块（操作系统</span>API<span style="font-family: 宋体">隔离、渲染器、排版对象）已经足以让我在系统里面开一个窗口然后在上面放各种各样的东西了，譬如说组合成一个非常接近</span>Windows7<span style="font-family: 宋体">的按钮外观的一个矢量图。那控件要怎么办呢？其实一个控件，就是通过接收用户的输入，对一个排版对象上承载的一大堆图元进行更改。用户的输入和控件（</span>GuiControl<span style="font-family: 宋体">）本身的状态进行互动，然后控件把状态的变更提交给控件的皮肤（</span>GuiControl::IStyleController<span style="font-family: 宋体">），最后皮肤通过修改图元来把状态变更最终展现给用户。一个典型的例子就是，在使用</span>Windows7<span style="font-family: 宋体">皮肤的时候，鼠标移动到按钮上面去，他会触发一个动画慢慢变成蓝色。</span></p>
<p style="margin: 0cm 0cm 10pt">GacUI<span style="font-family: 宋体">的大体架构就是这个样子了。在接下来的几篇文章里面，我会详细介绍每一个子系统的内部结构，顺带做以下代码导读，大家敬请期待。</span></p> <img src ="http://www.cppblog.com/vczh/aggbug/191105.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-09-18 14:31 <a href="http://www.cppblog.com/vczh/archive/2012/09/18/191105.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>终于点了ASP.NET MVC3的技能树了</title><link>http://www.cppblog.com/vczh/archive/2012/07/10/182499.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Mon, 09 Jul 2012 18:27:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/07/10/182499.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/182499.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/07/10/182499.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/182499.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/182499.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 为了给自己写的C++ GUI库做宣传，在几个月前我决定要给他做一个网站，经历了这几个月不断的重构，现在网站的架构终于定型了。考虑到在这之前我几乎没有开发网站的经验，所以在这里做点小总结来介绍自己一路走来发生的事情。<br /><br />&nbsp;&nbsp;&nbsp; 一开始为了制作这个网站购买了万网的域名和一个很便宜的一年500块钱的空间。这个空间支持低版本的asp.net，不过当时还没学会这方面的东西。后来我就开始学习HTML和CSS，然后做出了几个页面。不同的浏览器有不同的bug，导致HTML和CSS搞起来相当复杂，特别是div和float的结合，更是焦头烂额。后来索性整个网页都用表格布局。虽然表格布局并不是什么流行的做法，但是鉴于GacUI的网站并没有多么复杂的内容，因此最后这么做，避开了很多跨浏览器的问题。当然以后如果网页内容变得太复杂的话总是要改回div的吧。对于常年写图形和编译器方面的我来说，刚开始深入接触HTM和CSS的时候就对他的杂乱无章所震惊。使用programming language领域的经验和标准来看，HTML、CSS和Javascript作为编程的工具实在是烂到不能再烂了。不过事物的存在总是有其合理性的，纵观这三样东西的发展和历史，我们会发现其过程充满了各种巧合，而且当初这些东西在发明的时候就仅仅是为了解决一些简单的问题。如今流行了，就跟COBOL、Java和C语言一样，全世界的程序员都只能接受其不可忽视的弱点而就这么开发下去了。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;在熟悉了简单的HTML和CSS之后，我就开始给GacUI做网站了。这个网站的主要目的就是用来介绍GacUI的特点、展示一些Demo、告诉人们如何下载并使用，最后就是提供一个在线文档。文档就跟MSDN一样，当然搜索功能还不存在。刚开始就遇到了美工问题。技能书都点在了系统软件上，自己的美工自然是连自己都不能满足的。后来找了几个例子，看来看去觉得还是<a style="text-decoration: underline" href="http://www.codeplex.com" target="_blank">http://www.codeplex.com</a>最顺眼。但是它的代码复杂到吐血，我便只好依样画葫芦，自己慢慢复刻。最后复刻的结果还是令我比较满意的。在做完了导航条之后，我就发现了一个问题。如果不使用如今的框架来做网页，而采用手写的方法来生成HTML文件的话，势必是无法DIY的。不过那个时候还没有意识到这个问题的严重性，于是就采用了简单粗暴的复制代码的方法来做好那五个页面。这也为我之后转向Windows Azure埋下了伏笔。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;之后做Demo的展示页面比较顺利。因为目前展示Demo的方法就是先贴效果图，然后贴C++代码，十分的简单粗暴。于是立刻就遇到了一个新的障碍，要如何写一个类似MSDN的HTML文档。其实这件事情跟做网站本身是没什么关系的，但是自从决定了要提供在线文档之后，这个问题也就无法避免了。C++生成文档地方法之前略有研究，毕竟关于这个功能的一个简单的原型就是我跟几个朋友在大一的时候参加学校的软件竞赛的作品。后来还考虑过诸如Doxygen这样的工具。但是由于Doxygen生成的文档很难调整风格，使其整体融入我的网站的样式里，因此最终就放弃了。然后我便想起了Visual Studio的XML注释功能。在略为研究之后，我便给我的整个GacUI的类库的public class编写了XML注释。当我最终要执行生成文档的这一步的时候，我才发现所有的工具都不支持原生C++程序和XML注释的文档生成功能。不过想来其实也有道理。Visual Studio在编译了XML注释之后提供的一个xml文件只包含符号和注释的对应关系。至于符号究竟是什么内容，则完全没有。因此.net的程序是怎么生成文档的呢？自然是利用反射了。C++的苦逼就在这里啊，除了直接写代码，就没有任何方法。但是写了这么多的XML文档要放弃实在是太可惜了，所以我就不断的找呀找，然后发现Visual Studio在安装的时候提供了一个叫做DIA的库，可以让我阅读pdb文件！<br /><br />&nbsp;&nbsp;&nbsp; 这让我欣喜若狂啊。既然Visual C++的调试器可以通过阅读pdb就得到了一切的信息（看那个完美的调试器界面就知道了！），那我自然也可以从pdb里面找到所有东西的。抱着这个想法，我开始研究原生C++的pdb文件的符号的语义结构，后来就把我的经验写成了这两篇博客：<a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2012/03/10/167538.html" target="_blank">http://www.cppblog.com/vczh/archive/2012/03/10/167538.html</a>和<a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2012/03/10/167539.html" target="_blank">http://www.cppblog.com/vczh/archive/2012/03/10/167539.html</a>。虽然PDB并没有包含模板类的直接信息，不过这暂时不成问题，因为GacUI的大部分类也不是模板类。经过了这些研究，我就得到了一个相当于静态反射的功能了。之所以说是静态，是因为我没办法跟.net程序一样通过反射来调用函数。但是这对于生成文档来说已经足够了。后来我做了一件事情，就是写了个程序，读pdb获得所有的符号dump出一份xml，然后再写一个程序把xml里面的符号和Visual Studio产生的那个XML总注释文件的符号联系起来（这个过程有点复杂，因为两边的表示方法不一样&#8230;&#8230;），得到了一份既包含符号的完整内容又包含对应的注释的这么个几十M的XML文件。之后我设计了一个简单的文档格式，写了个程序把那个几十M的XML文件转换成用那个简单的文档格式表达的文档。之所以这样做是考虑到将来说不定除了HTML还要生成其他格式的文档，于是就做了那么个程序可读的中间格式。最后一步当然是读这些文件产生HTML文件了。整个流程如下所示：<br /><br />&nbsp;&nbsp;&nbsp; PDB（VC++编译器提供） -&gt; Symbols.XML （因为DIA是一个COM组件，所以这一步我用C++写，下面所有的步骤都用C#写。C#用起来还是更容易啊&#8230;&#8230;）<br />&nbsp;&nbsp;&nbsp; Symbols.XML + Comment.XML（VC++编译器提供） -&gt;&nbsp;FullSymbols.XML<br />&nbsp;&nbsp;&nbsp; FullSymbols.XML -&gt; *.docitem.txt<br />&nbsp;&nbsp;&nbsp; *.docitem.txt -&gt; *.html<br /><br />&nbsp;&nbsp;&nbsp; 经过了这些步骤，我就得到了整整一个文件夹的一千五百多个HTML文件了。然后我把这些文件跟我的网站合并在一起上传，就得到了第一个版本的GacUI网站了：<a style="text-decoration: underline" href="http://www.gaclib.net" target="_blank">http://www.gaclib.net</a>。当然现在已经看不到第一个版本的网站了。做完这些步骤之后，我就暂停了下来，继续开发GacUI。一边开发一边产生Demo，添加Demo页面，产生新的文档，消灭一些没用的函数的文档。写代码的时候还比较容易，再把代码的更改反映到这个网站的时候，就体现出了手写纯静态网站的弱点：维护起来真TMD麻烦啊！虽然上面的这些步骤已经被我合并到了一个bat文件，每次双击就能自动完成，但是修改Demo页面的时候还是人肉的。这让我十分不爽。<br /><br />&nbsp;&nbsp;&nbsp; 一个偶然的机会，我用了信用卡注册了一个Windows Azure的空间。这个空间其实并不powerful，只给了我相当于六颗CPU的计算能力。不过用来做这个网站已经足够了。想到每次修改网站都要复制HTML代码，修改了结构的话还要动所有的HTML文件，烦了大概一个月之后我就下定决心要把HTML做成动态生成的。在看了Windows Azure的一些介绍之后，我觉得ASP.NET MVC3加上Windows Azure的简单存储功能十分适合用来作这种东西。<br /><br />&nbsp;&nbsp;&nbsp; 刚开始接触MVC3还是让我觉得比较困难，不过最大的困难还是在于理解router的机制那里。GacUI的网站内容简单，所以并不需要ASP.NET的其他高级技术。结果所有的困难都出现在router机制里面。在经过了两天的学习之后，我初步的掌握了它的使用方法。MVC3的router基本上就是一个pattern matching的过程，把你的url映射到一个对controller的调用上面。你不仅可以映射controller的类名和函数名，还可以从url抽取一些参数。在掌握了它的原理之后，操作router的感觉就跟写haskell一样，又直接又清爽。接下来就是razor模板的事情。从programming language的观点上看，razor是一个设计的相当出色地模板语言。第一个特点就是和宿主语言C#融合的十分紧密，第二个特点就是几乎一点语法噪音都没有。用过原始asp和php的人都知道代码里面充满了&lt;%%&gt;是一件十分令人讨厌的事情。每一处代码和HTML的切换都要&lt;%%&gt;，整个文件一眼望去就是一坨屎。razor很好地解决了这个问题。他采用了复杂的判断方法来分辨哪些东西是C#，哪些东西是HTML。小部分C#和HTML的切换至需要一个@符号就搞定了，大部分的切换都是自动的。虽然偶尔razor会有分析错误的情况，但是他仍然提供了@:操作符来让我们workaround这个分析过程。整个模板语言下来毫无语法噪音，写起来十分直接，十分干净。<br /><br />&nbsp;&nbsp;&nbsp; 在网站差不多做完之后，我往生成HTML文档的程序添加了一个功能：生成一个包含HTML文档内容和元数据的XML。然后我写了一个程序把这一大堆XML灌入了Windows Azure的Blob Storage里面。Blob Storage就跟一个硬盘一样，可以用来存放大量的不需要计算（SQL数据库就属于那种需要计算的）数据。然后我给每一个文档页面建立了一个统一的Model，Model里面包含了&#8220;读取和分析这些XML文件&#8221;的功能，controller则做一个简单的转发，最后在model里面把所有被Model标记出来的需要改写的URL都用@Url.Action来处理。在这个过程中我学到了一个razor的小技巧：虽然不是很安全，但是在razor里面使用MvcHtmlString可以绕过html encoding的功能，把存储在变量里面的HTML代码直接嵌进页面。这么用的时候需要有清醒的意识。<br /><br />&nbsp;&nbsp;&nbsp; 如今GacUI终于有了镜像网站：<a style="text-decoration: underline" href="http://asia.gaclib.net/" target="_blank">http://asia.gaclib.net</a>和<a style="text-decoration: underline" href="http://us.gaclib.net/" target="_blank">http://us.gaclib.net</a>了。万网的破烂空间自然不可能直接访问Windows Azure Storage了。所以我采用了一个看起来比较傻逼的方法。首先我修改好网站之后，上传到EastAsia和West US两个服务器，然后我写了一个程序再把每一个生成好的HTML页面下载下来。下载的过程其实就和写爬虫差不多，每获得一个新的HTML文件就去分析里面的链接，然后继续下载。写完了之后我发现这个小程序还有了发现死链的功能，直接找出了网站代码的几个bug。下载完之后FTP到万网的空间里面。这个服务器在杭州。因此网站就有三个服务器了。<br /><br />&nbsp;&nbsp;&nbsp; 整个过程零零碎碎耗费了大约半年的时间，都是利用每天下班后的时间完成的。自己又点了技能树的一个新子树，涨了点经验值，觉得这些经验对于某些人来说可能还有参考的价值，于是就写了这篇博客，大家共勉。</div><img src ="http://www.cppblog.com/vczh/aggbug/182499.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-07-10 02:27 <a href="http://www.cppblog.com/vczh/archive/2012/07/10/182499.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：模拟Windows7资源管理器</title><link>http://www.cppblog.com/vczh/archive/2012/06/05/177552.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Mon, 04 Jun 2012 17:15:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/06/05/177552.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/177552.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/06/05/177552.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/177552.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/177552.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; GacUI的ListView支持Windows 7资源管理器的六种View，并且在默认的皮肤下表现的跟资源管理器十分类似。这个Demo也使用了一些Shell API来获得资源管理器使用的文件的图标、文件类型的字符串等等。完整的代码可以在http://www.gaclib.net/Demos/Controls.ListView.ViewSwitching/Dem...&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/06/05/177552.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/177552.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-06-05 01:15 <a href="http://www.cppblog.com/vczh/archive/2012/06/05/177552.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：列表的虚拟模式，不需要为每一个列表项分配内存的一种显示方法</title><link>http://www.cppblog.com/vczh/archive/2012/05/30/176834.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Wed, 30 May 2012 15:19:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/30/176834.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/176834.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/30/176834.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/176834.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/176834.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>的所有列表控件都支持虚拟模式。虚拟模式是一种不需要为每一个列表项分配内存的一种显示方法。在开始的时候，需要高速列表一共有多少个列表项。之后，列表控件在渲染的时候，会跟数据源要求获取某一个下标所包含的数据，并且在这个数据一直处于屏幕上的时候，只会跟数据源获取一次。完整的代码可以在<a style="text-decoration: underline" href="http://www.gaclib.net/Demos/Controls.ListBox.VirtualMode/Demo.html" target="_blank">http://www.gaclib.net/Demos/Controls.ListBox.VirtualMode/Demo.html</a>看到。先上图：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_40.jpg" width="496" height="518" /><br /><br />&nbsp;&nbsp;&nbsp; 先看创建界面的代码。一般来说，所有可以随着窗口的变化自动排版的控件组织方法，都是使用一个或多个GuiTableComposition来实现的。<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;VirtualModeWindow&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiWindow<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiVirtualTextList</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonIncrease;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDecrease;<br />&nbsp;&nbsp;&nbsp;&nbsp;DataSource</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataSource;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonIncrease_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataSource</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetCount(dataSource</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Count()</span><span style="color: #000000">+</span><span style="color: #000000">100000</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonDecrease_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataSource</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetCount(dataSource</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Count()</span><span style="color: #000000">-</span><span style="color: #000000">100000</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;VirtualModeWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:GuiWindow(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Controls.ListBox.VirtualMode</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiTableComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;table</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiTableComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowsAndColumns(</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetCellPadding(</span><span style="color: #000000">3</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">1.0</span><span style="color: #000000">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">1.0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(table);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataSource</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;DataSource;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiVirtualTextList(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateTextListStyle(),&nbsp;GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateTextListItemStyle(),&nbsp;dataSource);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetHorizontalAlwaysVisible(</span><span style="color: #0000ff">false</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonIncrease</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonIncrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Increase&nbsp;100000&nbsp;Items</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonIncrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonIncrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">VirtualModeWindow::buttonIncrease_Clicked);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonIncrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDecrease</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDecrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Decrease&nbsp;100000&nbsp;Items</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDecrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDecrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">VirtualModeWindow::buttonDecrease_Clicked);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonDecrease</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;set&nbsp;the&nbsp;preferred&nbsp;minimum&nbsp;client&nbsp;size</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetPreferredMinSize(Size(</span><span style="color: #000000">480</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">480</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;call&nbsp;this&nbsp;to&nbsp;calculate&nbsp;the&nbsp;size&nbsp;immediately&nbsp;if&nbsp;any&nbsp;indirect&nbsp;content&nbsp;in&nbsp;the&nbsp;table&nbsp;changes<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;that&nbsp;the&nbsp;window&nbsp;can&nbsp;calcaulte&nbsp;its&nbsp;correct&nbsp;size&nbsp;before&nbsp;calling&nbsp;the&nbsp;MoveToScreenCenter()</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">ForceCalculateSizeImmediately();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;move&nbsp;to&nbsp;the&nbsp;screen&nbsp;center</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};</span></div><br />&nbsp;&nbsp;&nbsp; GuiVirtualTextList就是只有虚拟模式的GuiTextList。事实上GuiVirtualTextList是GuiTextList的基类，而GuiTextList.GetItems()返回的对象也是一个数据源。因此非虚拟模式其实也是通过虚拟模式来实现的。在数据比较少的时候，非虚拟模式操作起来十分的简单，而在数据比较多的时候，虚拟模式可以带来很好的性能。上面的代码创建了一个DataSource类来做数据源，并且有一个SetCount的函数用来更改列表里面的数量的总量，然后每一个列表项的内容都是Item xxx。这是怎么做到的呢？我们来看数据源的代码：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;DataSource&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;list::ItemProviderBase,&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;list::TextItemStyleProvider::ITextItemView<br />{<br /></span><span style="color: #0000ff">protected</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count;<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;DataSource()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:count(</span><span style="color: #000000">100000</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;SetCount(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;newCount)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #000000">0</span><span style="color: #000000">&lt;=</span><span style="color: #000000">newCount)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;oldCount</span><span style="color: #000000">=</span><span style="color: #000000">count;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count</span><span style="color: #000000">=</span><span style="color: #000000">newCount;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this-&gt;InvokeOnItemModified(affected-items-start,&nbsp;affected-items-count,&nbsp;new-items-count);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this&nbsp;function&nbsp;notifies&nbsp;the&nbsp;list&nbsp;control&nbsp;to&nbsp;update&nbsp;it's&nbsp;content&nbsp;and&nbsp;scroll&nbsp;bars</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(oldCount</span><span style="color: #000000">&lt;</span><span style="color: #000000">newCount)<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;insert</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">InvokeOnItemModified(oldCount,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;newCount</span><span style="color: #000000">-</span><span style="color: #000000">oldCount);<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;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(oldCount</span><span style="color: #000000">&gt;</span><span style="color: #000000">newCount)<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;delete</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">InvokeOnItemModified(newCount,&nbsp;oldCount</span><span style="color: #000000">-</span><span style="color: #000000">newCount,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;GuiListControl::IItemProvider</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;Count()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;count;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;IDescriptable</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;RequestView(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;WString</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;identifier)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(identifier</span><span style="color: #000000">==</span><span style="color: #000000">list::TextItemStyleProvider::ITextItemView::Identifier)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(identifier</span><span style="color: #000000">==</span><span style="color: #000000">GuiListControl::IItemPrimaryTextView::Identifier)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;ReleaseView(IDescriptable</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;view)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;list::TextItemStyleProvider::ITextItemView</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;WString&nbsp;GetText(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;itemIndex)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">Item&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">itow(itemIndex</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;GetChecked(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;itemIndex)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;DataSource&nbsp;don't&nbsp;support&nbsp;check&nbsp;state</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;SetCheckedSilently(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;itemIndex,&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;value)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;DataSource&nbsp;don't&nbsp;support&nbsp;check&nbsp;state</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;GuiListControl::IItemPrimaryTextView</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;WString&nbsp;GetPrimaryTextViewText(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;itemIndex)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;GetText(itemIndex</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;ContainsPrimaryText(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;itemIndex)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};</span></div><br />&nbsp;&nbsp;&nbsp; 对于GuiVirtualTextList来说，只需要实现vl::presentation::controls::list::TextItemStyleProvider::ITextItemView就可以了。GacUIIncludes.h里面已经有了using namespace vl::presentation::controls，所以在这里只需要从list::开始写。list::TextItemStyleProvider::ITextItemView还要求实现GuiListControl::IItemPrimaryTextView。在目前的GacUI里面，IItemPrimaryTextView是专门为下拉框准备的。因为下拉框允许接受任何一种列表对象当做下拉内容，所以GacUI的列表数据源默认都要求实现IItemPrimaryTextView。<br /><br />&nbsp;&nbsp;&nbsp; 实现数据源的时候，其实并不要求数据源类继承自ITextItemView和IItemPrimaryTextView。因为GacUI都是通过RequestView来获取一个View的接口指针的，代码如上。实现这两个View也很简单，在这里就不赘述了。<br /><br />&nbsp;&nbsp;&nbsp; GuiTextList就介绍到这里了，接下来的几个Demo都将是关于ListView的。下一个Demo是ListView山寨Windows 7的资源管理器界面，可以在<a style="text-decoration: underline" href="http://www.gaclib.net/Demos/Controls.ListView.ViewSwitching/Demo.html" target="_blank">http://www.gaclib.net/Demos/Controls.ListView.ViewSwitching/Demo.html</a>看到。具体内容将在下一篇博客中阐述。</div><img src ="http://www.cppblog.com/vczh/aggbug/176834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-30 23:19 <a href="http://www.cppblog.com/vczh/archive/2012/05/30/176834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：列表控件内容的排序和移动，以及Linq for C++</title><link>http://www.cppblog.com/vczh/archive/2012/05/26/176247.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sat, 26 May 2012 05:54:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/26/176247.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/176247.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/26/176247.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/176247.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/176247.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 趁此机会做个广告，http://www.gaclib.net终于上线啦！&nbsp;&nbsp;&nbsp; GacUI的列表控件的第二个Demo是关于列表项的多选的。跟Windows一样，我们可以通过鼠标和方向键，配合CTRL和SHIFT选择列表的多个内容。因此这次我实现了一个简单的&#8220;名字选择窗口&#8221;，就跟QQ邀请好友入群的界面一样...&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/05/26/176247.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/176247.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-26 13:54 <a href="http://www.cppblog.com/vczh/archive/2012/05/26/176247.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：简单文本列表操作</title><link>http://www.cppblog.com/vczh/archive/2012/05/23/175926.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Wed, 23 May 2012 12:42:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/23/175926.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/175926.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/23/175926.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/175926.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/175926.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>在结束了文本框的介绍之后，开始进入列表的介绍。列表内容丰富，包含各种预定义的列表控件、用来显示和操作大量对象的虚拟模式、MVC分离、修改列表样式等内容。今天先从文本列表的简单操作开始。这个Demo展示了如何对列表进行添加和删除。窗口里面有一个列表，然后有添加和删除两个按钮，分别用于把文本框的内容添加到列表内，和删除掉选中的列表项的。在这个Demo里面只允许列表项单选，并且水平滚动条默认不出现。先看图：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_38.jpg" width="496" height="518" /><br /><br />&nbsp;&nbsp;&nbsp; 空间如何布局，我就不再赘述了，明显是一个四行三列的表格。代码如下：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\Public\Source\GacUIIncludes.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;for&nbsp;SortedList,&nbsp;CopyFrom&nbsp;and&nbsp;Select</span><span style="color: #008000"><br /></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000">&nbsp;vl::collections;<br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;SetupWindowsDirect2DRenderer();<br />}<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;NameEditorWindow&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiWindow<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiTextList</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiSinglelineTextBox</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAdd;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonAdd_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;specified&nbsp;name&nbsp;at&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;list&nbsp;box</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetItems().Add(textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetText());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SelectAll();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFocus();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonRemove_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;remove&nbsp;the&nbsp;selected&nbsp;items&nbsp;using&nbsp;item&nbsp;index</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetItems().RemoveAt(listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetSelectedItems()[</span><span style="color: #000000">0</span><span style="color: #000000">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;listBox_SelectionChanged(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;disable&nbsp;the&nbsp;button&nbsp;if&nbsp;no&nbsp;item&nbsp;is&nbsp;selected</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetEnabled(listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetSelectedItems().Count()</span><span style="color: #000000">&gt;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;NameEditorWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:GuiWindow(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Controls.ListBox.NameEditor</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiTableComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;table</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiTableComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowsAndColumns(</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetCellPadding(</span><span style="color: #000000">3</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">1.0</span><span style="color: #000000">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">1.0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(table);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">=</span><span style="color: #000000">g::NewTextList();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetHorizontalAlwaysVisible(</span><span style="color: #0000ff">false</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SelectionChanged.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">NameEditorWindow::listBox_SelectionChanged);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiLabel</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;label</span><span style="color: #000000">=</span><span style="color: #000000">g::NewLabel();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Name&nbsp;to&nbsp;add:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(label</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">=</span><span style="color: #000000">g::NewTextBox();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetPreferredMinSize(Size(</span><span style="color: #000000">120</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">23</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAdd</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAdd</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Add</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAdd</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAdd</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">NameEditorWindow::buttonAdd_Clicked);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonAdd</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Delete</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetEnabled(</span><span style="color: #0000ff">false</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">NameEditorWindow::buttonRemove_Clicked);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;set&nbsp;the&nbsp;preferred&nbsp;minimum&nbsp;client&nbsp;size</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetPreferredMinSize(Size(</span><span style="color: #000000">480</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">480</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;call&nbsp;this&nbsp;to&nbsp;calculate&nbsp;the&nbsp;size&nbsp;immediately&nbsp;if&nbsp;any&nbsp;indirect&nbsp;content&nbsp;in&nbsp;the&nbsp;table&nbsp;changes<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;that&nbsp;the&nbsp;window&nbsp;can&nbsp;calcaulte&nbsp;its&nbsp;correct&nbsp;size&nbsp;before&nbsp;calling&nbsp;the&nbsp;MoveToScreenCenter()</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">ForceCalculateSizeImmediately();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;move&nbsp;to&nbsp;the&nbsp;screen&nbsp;center</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiWindow</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;window</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;NameEditorWindow;<br />&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Run(window);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;window;<br />}</span></div><br />&nbsp;&nbsp;&nbsp; 这里需要注意的几点就是，为了实现在列表没有选中内容的时候禁用删除按钮，我们需要监听GuiTextList::SelectionChanged事件。核心的代码就是下面这几行：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonAdd_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;specified&nbsp;name&nbsp;at&nbsp;the&nbsp;end&nbsp;of&nbsp;the&nbsp;list&nbsp;box</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetItems().Add(textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetText());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SelectAll();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFocus();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonRemove_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;remove&nbsp;the&nbsp;selected&nbsp;items&nbsp;using&nbsp;item&nbsp;index</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetItems().RemoveAt(listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetSelectedItems()[</span><span style="color: #000000">0</span><span style="color: #000000">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;listBox_SelectionChanged(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;disable&nbsp;the&nbsp;button&nbsp;if&nbsp;no&nbsp;item&nbsp;is&nbsp;selected</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonRemove</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetEnabled(listBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetSelectedItems().Count()</span><span style="color: #000000">&gt;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br />&nbsp;&nbsp;&nbsp; GuiTextList控件的GetItems函数返回所有的列表项。这个对象有Add、Insert、Clear、IndexOf、Remove、RemoveAt、Contains、Count等函数，可以用来操作列表项。GuiTextList还有GetSelectedItems函数（其实是定义在GuiSelectableListControl里面的），可以用来获得所有选中的列表项的下标（从0开始）。每当列表内容被修改的时候，GetSelectedItems的结果就会被自动清空。<br /><br />&nbsp;&nbsp;&nbsp; 下一个Demo将是关于如何处理允许多选的列表的操作方法。</div><img src ="http://www.cppblog.com/vczh/aggbug/175926.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-23 20:42 <a href="http://www.cppblog.com/vczh/archive/2012/05/23/175926.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：文本框高亮（三，完）上下文相关着色</title><link>http://www.cppblog.com/vczh/archive/2012/05/20/175475.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sun, 20 May 2012 08:41:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/20/175475.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/175475.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/20/175475.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/175475.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/175475.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 这是<a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>关于文本框高亮的最后一个Demo了。这个Demo是关于XML着色的。XML着色比起C++着色更难，主要是因为在类似&lt;book name="C++ Primer"&gt;这样的代码里面，book和name的颜色不一样，&lt;和book的颜色也不一样（参考Visual Studio）。这种时候单纯依靠正则表达式来区分颜色是不够的，我们还需要引入一个新的状态机。这个状态机只有三个状态，用来区分tag name，attribute name和text三种颜色。状态机是手写的，并且GacUI提供了一个回调来写这个只有寥寥几行状态机。先看图：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_37.jpg" /><br /><br />&nbsp;&nbsp;&nbsp; 跟C++一样，XML着色首先是由正则表达式组成的。XML的正则表达式比较简单，只有符号、name、字符串、CData、注释和其它一些简单的东西：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;XmlColorizer&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiTextBoxRegexColorizer<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;XmlColorizer()<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text::ColorEntry&nbsp;entry</span><span style="color: #000000">=</span><span style="color: #000000">win7::Win7GetTextBoxTextColor();<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetDefaultColor(entry);<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">128</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">/&lt;!--([^/-]|-[^/-]|--[^&gt;])*--/&gt;</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">128</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">);<br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">/&lt;!/[CDATA/[([^/]]|/][^/]]|/]/][^&gt;])*/]/]/&gt;</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">\</span><span style="color: #000000">"</span><span style="color: #000000">[</span><span style="color: #000000">^</span><span style="color: #000000">\</span><span style="color: #000000">"</span><span style="color: #000000">]*\</span><span style="color: #000000">""</span><span style="color: #000000">,&nbsp;entry);</span><span style="color: #000000"><br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000"></span><span style="color: #000000"><br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">);<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">[&lt;&gt;=]</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">255</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">[a-zA-Z0-9_/-:]+</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br /></span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">24</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">163</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">21</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">21</span><span style="color: #000000">);<br /></span><span style="color: #008080">25</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddExtraToken(entry);<br /></span><span style="color: #008080">26</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">27</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Setup();<br /></span><span style="color: #008080">28</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">29</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">30</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;ColorizeTokenContextSensitive(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;text,&nbsp;vint&nbsp;start,&nbsp;vint&nbsp;length,&nbsp;vint</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;token,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;contextState)</span><span style="color: #0000ff">override</span><span style="color: #000000"><br /></span><span style="color: #008080">31</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">32</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img alt="" src="http://www.cppblog.com/Images/dot.gif" /><br /></span><span style="color: #008080">33</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">34</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">35</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;GetContextStartState()</span><span style="color: #0000ff">override</span><span style="color: #000000"><br /></span><span style="color: #008080">36</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">37</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img alt="" src="http://www.cppblog.com/Images/dot.gif" /><br /></span><span style="color: #008080">38</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">39</span>&nbsp;<span style="color: #000000">};</span></div><br />&nbsp;&nbsp;&nbsp; 其次要对三种地方的[a-zA-Z0-9_/-:]进行着色。Tag的名字用褐色，attribute的名字用红色，而普通文本用黑色。因此我们可以做一个状态机，初始状态为0。如果读进了&lt;，状态变成1。1遇到了一个Tag名字之后变为2。从2开始所有的名字就只能是attribute的名字了。我们只考虑正确的情况，错误的代码着色出了问题不仅没有坏处，还可以提醒程序员有什么地方写错了。之后遇到了&gt;变回0，在0的状态下所有的东西都是普通文本，所以名字就都是黑色的。因此上面ColorizeTokenContextSensitive函数中就需要填入这个逻辑。GetContextStartState返回0，作为第一行的起始状态。代码如下：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;ColorizeTokenContextSensitive(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;text,&nbsp;vint&nbsp;start,&nbsp;vint&nbsp;length,&nbsp;vint</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;token,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;contextState)</span><span style="color: #0000ff">override</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;0&nbsp;&lt;&nbsp;1&nbsp;name&nbsp;2&nbsp;att&nbsp;&gt;&nbsp;0</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">switch</span><span style="color: #000000">(token)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(length</span><span style="color: #000000">==</span><span style="color: #000000">1</span><span style="color: #000000">)<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">switch</span><span style="color: #000000">(text[start])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">&lt;</span><span style="color: #000000">'</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contextState</span><span style="color: #000000">=</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">&gt;</span><span style="color: #000000">'</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contextState</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">4</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">switch</span><span style="color: #000000">(contextState)<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;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;token</span><span style="color: #000000">=-</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;token</span><span style="color: #000000">=</span><span style="color: #000000">5</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contextState</span><span style="color: #000000">=</span><span style="color: #000000">2</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<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;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;GetContextStartState()</span><span style="color: #0000ff">override</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br />&nbsp;&nbsp;&nbsp; 这个函数里面有几个魔法数字，其实都是关于Token的编号的。构造函数里面我们使用AddToken将一个颜色关联到正则表达式上，使用AddExtraToken创建一个没有正则表达式关联的颜色。所以在这个状态机里面，所有的颜色都用Token的序号来表示。无论是使用AddToken还是AddExtraToken，第一个颜色编号为0，第二个颜色编号为1。因此case 3指的是[&lt;&gt;=]，而case 4指的是[a-zA-Z0-9_/-:]+。而case 4里面的token=5则表示在状态为1的时候，名字都用AddExtraToken指定的那个褐色进行染色。缺省的名字（也就是id为4的token）是红色，所以不需要对contextState为2的时候进行处理。<br /><br />&nbsp;&nbsp;&nbsp; 这样我们就完成了XML的着色。GacUI接下来的几个Demo将会是关于ListBox、ListView和TreeView的，敬请期待。</div><img src ="http://www.cppblog.com/vczh/aggbug/175475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-20 16:41 <a href="http://www.cppblog.com/vczh/archive/2012/05/20/175475.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：文本框高亮（二）</title><link>http://www.cppblog.com/vczh/archive/2012/05/18/175259.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Thu, 17 May 2012 17:03:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/18/175259.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/175259.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/18/175259.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/175259.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/175259.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>终于把<a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2012/05/12/174609.html" target="_blank">上一篇文章</a>中提到的自动采用正则表达式进行高亮的Demo做出来了。这次实现的是C++ colorizer。而XML colorizer不仅需要正则表达式，还需要一个人工维护的状态，这个等到下一个Demo再提及。先看图<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_36.jpg" width="960" height="1040" /><br /><br />&nbsp;&nbsp;&nbsp; 在不需要人工维护状态，仅通过正则表达式就可以着色的时候，编写一个colorizer变得十分的简单。这个Colorizer虽然不是一定非得通过继承来实现，但是这个Demo还是使用了继承。首先编写一个类，继承自GuiTextBoxRegexColorizer，然后在构造函数里面填写下面的代码：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;CppColorizer&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiTextBoxRegexColorizer<br />{<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;CppColorizer()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text::ColorEntry&nbsp;entry</span><span style="color: #000000">=</span><span style="color: #000000">win7::Win7GetTextBoxTextColor();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetDefaultColor(entry);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">128</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">/d+(./d*)?([eE][+/-]?/d+)?</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">163</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">21</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">21</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">\</span><span style="color: #000000">"</span><span style="color: #000000">([</span><span style="color: #000000">^</span><span style="color: #000000">\</span><span style="color: #000000">"</span><span style="color: #000000">]|\\\\/.)*\</span><span style="color: #000000">""</span><span style="color: #000000">,&nbsp;entry);</span><span style="color: #000000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">128</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">////[^\r\n]*</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">///*(//|[*]*[^*//])*/*+//</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.normal.text</span><span style="color: #000000">=</span><span style="color: #000000">Color(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">#[a-zA-Z0-9_]*</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;entry);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(CppKeywords,&nbsp;entry);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToken(L</span><span style="color: #000000">"</span><span style="color: #000000">[a-zA-Z0-9_]+</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;GetDefaultColor());<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Setup();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};</span></div><br />&nbsp;&nbsp;&nbsp; 然后只需要把它绑定到文本框里面就可以了。在这个Demo里面，我们在下拉框的事件里面添加下面的代码：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;comboSelector_SelectedIndexChanged(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">switch</span><span style="color: #000000">(comboSelector</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetSelectedIndex())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">:（略）<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">:（略）<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">case</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColorizer(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CppColorizer);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">#include&nbsp;&lt;iostream&gt;\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">using&nbsp;namespace&nbsp;std;\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">int&nbsp;main()\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">{\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">\t//This&nbsp;is&nbsp;a&nbsp;comment\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">\t/**This*is/another\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">\tcomment**/\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">\tcout&lt;&lt;\</span><span style="color: #000000">"</span><span style="color: #000000">Hello,&nbsp;world</span><span style="color: #000000">!</span><span style="color: #000000">\</span><span style="color: #000000">"</span><span style="color: #000000">&lt;&lt;endl;\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">\treturn&nbsp;0;\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">}\r\n</span><span style="color: #000000">"</span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">default</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColorizer(</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br />&nbsp;&nbsp;&nbsp; 当然这样是不完整的，因为CppColorizer里面还有一个CppKeywords的常量。这实际上是一个正则表达式，里面用&#8220;|&#8221;字符把所有C++的关键字连了起来。内容抄自MSDN的C++ Language Reference：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;&nbsp;1</span>&nbsp;<span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;wchar_t</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;CppKeywords</span><span style="color: #000000">=</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;2</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__abstract|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;3</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__alignof|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;4</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__asm|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;5</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__assume|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;6</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__based|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;7</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__box|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;8</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__cdecl|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;&nbsp;9</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__declspec|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;10</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__delegate|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;11</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__event|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;12</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__except|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;13</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__fastcall|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;14</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__finally|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;15</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__forceinline|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;16</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__gc|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;17</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__hook|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;18</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__identifier|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;19</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__if_exists|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;20</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__if_not_exists|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;21</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__inline|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;22</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__int16|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;23</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__int32|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;24</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__int64|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;25</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__int8|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;26</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__interface|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;27</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__leave|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;28</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__m128d|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;29</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__m128|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;30</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__m128i|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;31</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__m64|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;32</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__multiple_inheritance|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;33</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__nogc|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;34</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__noop|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;35</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__pin|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;36</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__property|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;37</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__raise|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;38</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__sealed|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;39</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__single_inheritance|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;40</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__stdcall|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;41</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__super|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;42</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__try|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;43</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__except|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;44</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__finally|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;45</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__try_cast|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;46</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__unaligned|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;47</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__unhook|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;48</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__uuidof|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;49</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__value|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;50</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__virtual_inheritance|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;51</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__w64|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;52</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__wchar_t|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;53</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">wchar_t|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;54</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">abstract|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;55</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">array|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;56</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">bool|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;57</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">break|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;58</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">case|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;59</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">catch|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;60</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">char|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;61</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">class|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;62</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">const_cast|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;63</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">const|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;64</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">continue|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;65</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">decltype|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;66</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">default|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;67</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">delegate|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;68</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">delete|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;69</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">do|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;70</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">double|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;71</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">dynamic_cast|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;72</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">else|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;73</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">enum|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;74</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">event|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;75</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">explicit|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;76</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">extern|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;77</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">false|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;78</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">finally|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;79</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">float|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;80</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">for|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;81</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">friend|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;82</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">gcnew|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;83</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">generic|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;84</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">goto|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;85</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">if|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;86</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">initonly|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;87</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">inline|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;88</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">int|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;89</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">interface|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;90</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">interior_ptr|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;91</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">literal|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;92</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">long|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;93</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">mutable|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;94</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">namespace|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;95</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">new|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;96</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">new|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;97</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">nullptr|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;98</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">operator|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;99</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">private|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">100</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">property|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">101</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">property|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">102</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">protected|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">103</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">public|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">104</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">register|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">105</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">reinterpret_cast|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">106</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">return|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">107</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">sealed|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">108</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">short|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">109</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">signed|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">110</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">sizeof|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">111</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">static_assert|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">112</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">static_cast|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">113</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">static|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">114</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">struct|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">115</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">switch|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">116</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">template|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">117</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">this|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">118</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">__thiscall|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">119</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">throw|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">120</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">true|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">121</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">try|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">122</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">typedef|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">123</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">typeid|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">124</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">typeid|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">125</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">typename|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">126</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">union|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">127</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">unsigned|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">128</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">using|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">129</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">virtual|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">130</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">void|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">131</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">volatile|</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">132</span>&nbsp;<span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">while</span><span style="color: #000000">"</span><span style="color: #000000">;</span></div><br />&nbsp;&nbsp;&nbsp; 使用GacUI为文本框着色已经变得如此简单。</div><img src ="http://www.cppblog.com/vczh/aggbug/175259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-18 01:03 <a href="http://www.cppblog.com/vczh/archive/2012/05/18/175259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：文本框高亮（一）</title><link>http://www.cppblog.com/vczh/archive/2012/05/12/174609.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Fri, 11 May 2012 16:58:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/12/174609.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/174609.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/12/174609.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/174609.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/174609.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; GacUI的高亮Demo做了一半。现在的进度是，可以手写着色器的状态转换函数，但是自动从正则表达式产生着色器的状态转换函数部分还没有集成进GacUI。这篇博客还是照旧，看图、看Demo代码，说着色原理。&nbsp;&nbsp;&nbsp; 这次的Demo要做一个可以动态切换着色器的小程序，里面包含INI、XML和C++三种着色器。现在只实现了INI一中，手写的...&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/05/12/174609.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/174609.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-12 00:58 <a href="http://www.cppblog.com/vczh/archive/2012/05/12/174609.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：文本框基本应用</title><link>http://www.cppblog.com/vczh/archive/2012/05/05/173764.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sat, 05 May 2012 10:37:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/05/173764.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/173764.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/05/173764.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/173764.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/173764.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; GacUI添加了一个新的Demo。这个Demo用了几个按钮（之所以不用菜单是因为不想让Demo一下子包含太多新东西）来实现剪贴板操作、只读控制和行跳转等功能。在剪贴板里面的内容是文字的时候，Paste按钮会被Enable。这个过程是自动的，也就是说，你在画图里面复制了一个图片，这个按钮也会变灰。Cut和Copy按钮仅在文本框有文字被选中的时候可用，因此相应了文...&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/05/05/173764.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/173764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-05 18:37 <a href="http://www.cppblog.com/vczh/archive/2012/05/05/173764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：标签页</title><link>http://www.cppblog.com/vczh/archive/2012/05/01/173349.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Tue, 01 May 2012 07:28:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/05/01/173349.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/173349.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/05/01/173349.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/173349.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/173349.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>新增了一个Demo。这里模拟了一个简单到过头了的编辑程序。界面是一个标签页，第一页里面只有一个按钮：Add Page。点中了他之后，其它页包含一个用来关掉自己的按钮，和一个多行的文本框。<br /><br />&nbsp;&nbsp;&nbsp; 这个Demo要展示的其中一个问题是，在按下关闭按钮的时候，由于那个Page会被移除并删除，会导致按钮自己也被删除。但是事件发生过后，实际上还有很多事情要做的。所以这里展示了如何使用GacUI进行&#8220;延迟执行&#8221;，在事件结束之后再删除自己。为了方便，这个Demo使用了C++11（但是库的实现并不依赖与C++11）。先上图：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_32.jpg" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_33.jpg" width="656" height="518" /><br /><br />&nbsp;&nbsp;&nbsp; 然后我们来看代码：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\Public\Source\GacUIIncludes.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;SetupWindowsDirect2DRenderer();<br />}<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;TextBoxPage&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiTabPage<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;pageCounter;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closeButton;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiMultilineTextBox</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;textBox;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;closeButton_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;deleteing&nbsp;the&nbsp;tab&nbsp;page&nbsp;will&nbsp;also&nbsp;delete&nbsp;the&nbsp;button,&nbsp;because&nbsp;the&nbsp;button&nbsp;is&nbsp;in&nbsp;the&nbsp;page<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;when&nbsp;an&nbsp;event&nbsp;is&nbsp;processing,&nbsp;the&nbsp;button&nbsp;is&nbsp;not&nbsp;going&nbsp;to&nbsp;be&nbsp;deleted<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;because&nbsp;there&nbsp;are&nbsp;many&nbsp;works&nbsp;to&nbsp;do&nbsp;after&nbsp;this&nbsp;event<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;and&nbsp;maybe&nbsp;someone&nbsp;has&nbsp;already&nbsp;added&nbsp;another&nbsp;event&nbsp;handler&nbsp;to&nbsp;this&nbsp;button<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;it&nbsp;use&nbsp;GetApplication()-&gt;InvokeInMainThread&nbsp;to&nbsp;send&nbsp;a&nbsp;function&nbsp;to&nbsp;the&nbsp;queue<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;that&nbsp;this&nbsp;function&nbsp;will&nbsp;be&nbsp;executed&nbsp;after&nbsp;this&nbsp;input&nbsp;message&nbsp;(an&nbsp;input&nbsp;message&nbsp;raises&nbsp;multiple&nbsp;events)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;to&nbsp;the&nbsp;user,&nbsp;this&nbsp;page&nbsp;is&nbsp;closed&nbsp;after&nbsp;cliking&nbsp;this&nbsp;button</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">InvokeInMainThread([</span><span style="color: #0000ff">this</span><span style="color: #000000">]()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;remove&nbsp;the&nbsp;page&nbsp;and&nbsp;delete&nbsp;it</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetOwnerTab()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">RemovePage(</span><span style="color: #0000ff">this</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;OnPageContainerReady(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;a&nbsp;table&nbsp;to&nbsp;place&nbsp;a&nbsp;button&nbsp;and&nbsp;a&nbsp;text&nbsp;box</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiTableComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;table</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiTableComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowsAndColumns(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">1.0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">1.0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetCellPadding(</span><span style="color: #000000">2</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<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;&nbsp;closeButton</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closeButton</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Close&nbsp;Me!</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;closeButton</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">TextBoxPage::closeButton_Clicked);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(closeButton</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<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;&nbsp;textBox</span><span style="color: #000000">=</span><span style="color: #000000">g::NewMultilineTextBox();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">You&nbsp;can&nbsp;input&nbsp;several&nbsp;lines&nbsp;of&nbsp;text&nbsp;here.\r\nThis&nbsp;is&nbsp;a&nbsp;multiple&nbsp;line&nbsp;text&nbsp;box.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(textBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainer()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(table);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;TextBoxPage()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:closeButton(</span><span style="color: #000000">0</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;,textBox(</span><span style="color: #000000">0</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PageContainerReady.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">TextBoxPage::OnPageContainerReady);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Page&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">itow(</span><span style="color: #000000">++</span><span style="color: #000000">pageCounter));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">TextBoxPage()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;TextBoxPage::pageCounter</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;TextBoxPageWindow&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiWindow<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiTab</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabControl;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiTabPage</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controlPanelPage;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAddPage;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonAddPage_Clicked(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;when&nbsp;the&nbsp;button&nbsp;is&nbsp;clicked,&nbsp;it&nbsp;creates&nbsp;a&nbsp;new&nbsp;TextBoxPage&nbsp;and&nbsp;adds&nbsp;it&nbsp;to&nbsp;the&nbsp;tab&nbsp;control</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TextBoxPage</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;page</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TextBoxPage;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabControl</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreatePage(page);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabControl</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSelectedPage(page);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;TextBoxPageWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:GuiWindow(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Controls.Tab.TextBoxPage</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetPreferredMinSize(Size(</span><span style="color: #000000">640</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">480</span><span style="color: #000000">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;a&nbsp;tab&nbsp;control</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabControl</span><span style="color: #000000">=</span><span style="color: #000000">g::NewTab();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabControl</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(tabControl);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;the&nbsp;first&nbsp;page&nbsp;is&nbsp;a&nbsp;control&nbsp;panel</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controlPanelPage</span><span style="color: #000000">=</span><span style="color: #000000">tabControl</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreatePage();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controlPanelPage</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Control&nbsp;Panel</span><span style="color: #000000">"</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;a&nbsp;button&nbsp;to&nbsp;the&nbsp;control&nbsp;panel</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAddPage</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAddPage</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Add&nbsp;a&nbsp;tab&nbsp;page</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonAddPage</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">TextBoxPageWindow::buttonAddPage_Clicked);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controlPanelPage</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainer()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetInternalMargin(Margin(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controlPanelPage</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainer()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonAddPage);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">ForceCalculateSizeImmediately();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">TextBoxPageWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiWindow</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;window</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TextBoxPageWindow();<br />&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Run(window);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;window;<br />}</span></div><br />&nbsp;&nbsp;&nbsp; 那一大段的注释，就是在讲延迟执行的事情。看过C++11的人都知道，lambda expression实际上就是一个functor。在旧C++里面，调用InvokeInMainThread的时候，要么可以传一个void(*)(void*)和void*，要么可以传一个带operator()()的struct。在新C++里面，直接把lambda expression写在里面就好了。<br /><br />&nbsp;&nbsp;&nbsp; 如果不使用延迟执行，在事件发生的时候把自己删掉，会导致Access Violation的发生，因为接下来要访问的对象被你删掉了。如果使用延迟执行，就可以在input message处理完之后，执行删除的代码。这样一切都是好的。<br /><br />&nbsp;&nbsp;&nbsp; 下一个Demo就是关于文本框的操作，再下一个Demo是关于如何做用来显示代码的高亮文本框的事情。敬请期待，啊哈哈哈。<br /></div><img src ="http://www.cppblog.com/vczh/aggbug/173349.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-05-01 15:28 <a href="http://www.cppblog.com/vczh/archive/2012/05/01/173349.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：多选框和单选框</title><link>http://www.cppblog.com/vczh/archive/2012/04/27/172964.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Fri, 27 Apr 2012 14:02:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/04/27/172964.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/172964.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/04/27/172964.html#Feedback</comments><slash:comments>25</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/172964.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/172964.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank"><span style="font-size: 14pt">GacUI</span></a>发布了一个新的Demo。这个Demo是关于多选框和单选框的。跟Windows一样，直接创建出来的单选框其实是不会互斥的，除非你把他们放进同一个group里面。界面是左右各一个group box，使用table来保证两边的尺寸都一样大。每一个group box里面放三个按钮，而且每一个group box的最小尺寸都取决于两边所有6按钮中最长的那个按钮。每一边的三个按钮使用stack来排列成像一个列表一样。左边是多选框，右边是单选框。现在先上图：<br /><br />&nbsp;&nbsp;&nbsp; 第一张是刚打开的时候，窗口的尺寸自动变化到能显示所有内容的最小的尺寸。尽管因为文字的关系，左边的按钮比右边的短，但是table可以控制两个group box一样大，并且共享最小尺寸。<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_30.jpg" width="400" height="174" /><br /><br />&nbsp;&nbsp;&nbsp; 然后改变窗口的尺寸，按钮始终靠左上角，两个group box则保持一样大。<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_31.jpg" width="500" height="256" /><br /><br />&nbsp;&nbsp;&nbsp; 大家已经看了前面的三个demo，所以有些东西其实已经不需要重复解释了。先上代码：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\Public\Source\GacUIIncludes.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;SetupWindowsDirect2DRenderer();<br />}<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;CheckAndRadioWindow&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiWindow<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;CreateButtons(</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;WString</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;groupName,&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;WString</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;buttonName,&nbsp;</span><span style="color: #0000ff">bool</span><span style="color: #000000">&nbsp;checkBox,&nbsp;GuiSelectableButton::GroupController</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;groupController)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiControl</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;groupBox</span><span style="color: #000000">=</span><span style="color: #000000">g::NewGroupBox();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;all&nbsp;child&nbsp;controls&nbsp;should&nbsp;at&nbsp;least&nbsp;10&nbsp;pixels&nbsp;away&nbsp;from&nbsp;the&nbsp;group&nbsp;box</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetInternalMargin(Margin(</span><span style="color: #000000">10</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;dock&nbsp;the&nbsp;group&nbsp;box&nbsp;to&nbsp;fill&nbsp;the&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(groupName);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;button&nbsp;to&nbsp;the&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;a&nbsp;stack&nbsp;to&nbsp;layout&nbsp;the&nbsp;3&nbsp;buttons&nbsp;from&nbsp;top&nbsp;to&nbsp;bottom&nbsp;shown&nbsp;like&nbsp;a&nbsp;list</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiStackComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;stack</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiStackComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetDirection(GuiStackComposition::Vertical);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetPadding(</span><span style="color: #000000">6</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groupBox</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(stack);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;buttons</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">3</span><span style="color: #000000">;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiSelectableButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;button</span><span style="color: #000000">=</span><span style="color: #000000">checkBox</span><span style="color: #000000">?</span><span style="color: #000000">g::NewCheckBox():g::NewRadioButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(buttonName</span><span style="color: #000000">+</span><span style="color: #000000">itow(i</span><span style="color: #000000">+</span><span style="color: #000000">1</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(groupController)<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetGroupController(groupController);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiStackItemComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;stackItem</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiStackItemComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(stackItem);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stackItem</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(button</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;cell;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;CheckAndRadioWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:GuiWindow(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Controls.Button.CheckAndRadio</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;limit&nbsp;the&nbsp;size&nbsp;that&nbsp;the&nbsp;window&nbsp;should&nbsp;always&nbsp;show&nbsp;the&nbsp;whole&nbsp;content&nbsp;without&nbsp;cliping&nbsp;it</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;a&nbsp;table&nbsp;to&nbsp;layout&nbsp;the&nbsp;2&nbsp;group&nbsp;boxes</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiTableComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;table</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiTableComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;make&nbsp;the&nbsp;table&nbsp;to&nbsp;have&nbsp;2&nbsp;rows</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowsAndColumns(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::MinSizeOption());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">0.5</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">0.5</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;dock&nbsp;the&nbsp;table&nbsp;to&nbsp;fill&nbsp;the&nbsp;window</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">4</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetCellPadding(</span><span style="color: #000000">6</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;table&nbsp;to&nbsp;the&nbsp;window;</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(table);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;group&nbsp;box&nbsp;for&nbsp;check&nbsp;boxes</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #000000">CreateButtons(L</span><span style="color: #000000">"</span><span style="color: #000000">Check&nbsp;Boxes</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;a&nbsp;check&nbsp;box&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this&nbsp;cell&nbsp;is&nbsp;the&nbsp;left&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;group&nbsp;box&nbsp;for&nbsp;radio&nbsp;buttons</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;a&nbsp;group&nbsp;controller&nbsp;to&nbsp;group&nbsp;those&nbsp;radio&nbsp;buttons&nbsp;together<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;that&nbsp;select&nbsp;a&nbsp;radio&nbsp;button&nbsp;will&nbsp;unselect&nbsp;the&nbsp;previous&nbsp;one&nbsp;automatically</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiSelectableButton::GroupController</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;groupController</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiSelectableButton::MutexGroupController;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddComponent(groupController);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #000000">CreateButtons(L</span><span style="color: #000000">"</span><span style="color: #000000">Radio&nbsp;buttons</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">This&nbsp;is&nbsp;a&nbsp;radio&nbsp;button&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">,&nbsp;groupController);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this&nbsp;cell&nbsp;is&nbsp;the&nbsp;right&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;call&nbsp;this&nbsp;to&nbsp;calculate&nbsp;the&nbsp;size&nbsp;immediately&nbsp;if&nbsp;any&nbsp;indirect&nbsp;content&nbsp;in&nbsp;the&nbsp;table&nbsp;changes<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;that&nbsp;the&nbsp;window&nbsp;can&nbsp;calcaulte&nbsp;its&nbsp;correct&nbsp;size&nbsp;before&nbsp;calling&nbsp;the&nbsp;MoveToScreenCenter()</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">ForceCalculateSizeImmediately();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;move&nbsp;to&nbsp;the&nbsp;screen&nbsp;center</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">CheckAndRadioWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiWindow</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;window</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CheckAndRadioWindow();<br />&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Run(window);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;window;<br />}</span></div><br />&nbsp;&nbsp;&nbsp; 需要关心的就是第二次调用CreateButtons函数，用来构造单选按钮的时候，穿进去的最后一个参数。GuiSelectableButton::GroupController类是一个虚类，用来控制选中状况。而预定义的MutexGroupController则可以控制连接到的所有GuiSelectionButton并保证他们互斥。如果需要更加复杂的情况，譬如说&#8220;最多只能选中N个按钮&#8221;这样的，则自己集成一个group controller就可以了。在创建了一个group controller，要调用GuiWindow::AddComponent保持他的生命周期，然后使用GuiSelectableButton::SetGroupController来帮顶一个按钮和一个group controller。<br /><br />&nbsp;&nbsp;&nbsp; 这个demo就介绍到这里了，下一个将是关于tab控件和文本框的demo。</div><img src ="http://www.cppblog.com/vczh/aggbug/172964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-04-27 22:02 <a href="http://www.cppblog.com/vczh/archive/2012/04/27/172964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI新Demo：按钮和排版</title><link>http://www.cppblog.com/vczh/archive/2012/04/25/172755.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Wed, 25 Apr 2012 10:46:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/04/25/172755.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/172755.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/04/25/172755.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/172755.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/172755.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今天为<a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>写了一个新的Demo，展示了一些可以自动排版的按钮。主要的设想就是在窗口上放一个表格，分成两行两列。上面的按钮占满一整行，下面两个单元格放两个按钮。然后就可以设置每个行和列占整个表格的比例，在这个Demo里面都设置成50%。这样每当窗口缩放的时候，按钮的位置也会随之重新排版。然后设置表格充满整个窗口，这样窗口的最小值就会被表格的内容所限定，这样试图把窗口缩小的时候，就会有一个最小的尺寸限制着，至始至终保证所有的东西都可以显示出来，不会因为窗口太小而只显示一半。按钮也是同样，可以设置它必须显示所有的文字。所有的过程一旦配置好之后，计算尺寸的时候所有的操作都会自动做，程序员不需要为窗口的Resize事件写任何代码。<br /><br />&nbsp;&nbsp;&nbsp; 下面先放图。<br /><br />&nbsp;&nbsp;&nbsp; 第一个图是窗口刚刚打开的时候的样子。因为Demo里面没有设置窗口的尺寸，所以一上来就自动变成了最小的尺寸&#8212;&#8212;并且刚好可以显示所有的内容。<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_28.jpg" width="488" height="131" /><br /><br />&nbsp;&nbsp;&nbsp; 第二个图是窗口放大之后的样子。Disable按钮被按下了，所以上面的按钮就变灰。<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_29.jpg" width="607" height="348" /><br /><br />&nbsp;&nbsp;&nbsp; 这个Demo使用了Direct2D渲染器，所有的绘制过程都十分高速。而且表格的尺寸计算也是经过优化的，在拖放窗口的时候十分流畅。事实上按钮的渐变啊、边框啊、文字等等也是借助表格排版的。由于尺寸计算过于复杂，除了表格之外整个框架都不保存控件的尺寸，所有的东西都在需要的时候&#8212;&#8212;譬如说渲染的时候，譬如说计算鼠标点中的位置&#8212;&#8212;的那一刻才开始算。因此无论是鼠标滑过，或者是窗口拖放，都拼命地执行很多虚函数。可见C++的虚函数的性能之高，几乎永远都不会成为程序的瓶颈。下面来看代码：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\Public\Source\GacUIIncludes.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;SetupWindowsDirect2DRenderer();<br />}<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;EnableDisableWindow&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiWindow<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiButton</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonEnable_OnClick(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetEnabled(</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;buttonDisable_OnClick(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetEnabled(</span><span style="color: #0000ff">false</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;EnableDisableWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:GuiWindow(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Controls.Button.EnableDisable</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;limit&nbsp;the&nbsp;size&nbsp;that&nbsp;the&nbsp;window&nbsp;should&nbsp;always&nbsp;show&nbsp;the&nbsp;whole&nbsp;content&nbsp;without&nbsp;cliping&nbsp;it</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;create&nbsp;a&nbsp;table&nbsp;to&nbsp;layout&nbsp;the&nbsp;3&nbsp;buttons</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiTableComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;table</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiTableComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;make&nbsp;the&nbsp;table&nbsp;to&nbsp;have&nbsp;2&nbsp;rows</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowsAndColumns(</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">0.5</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetRowOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">0.5</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">0.5</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetColumnOption(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;GuiCellOption::PercentageOption(</span><span style="color: #000000">0.5</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;dock&nbsp;the&nbsp;table&nbsp;to&nbsp;fill&nbsp;the&nbsp;window</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">10</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;table&nbsp;to&nbsp;the&nbsp;window;</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetContainerComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(table);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;target&nbsp;button</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this&nbsp;cell&nbsp;is&nbsp;the&nbsp;top&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Enable&nbsp;or&nbsp;disable&nbsp;me&nbsp;using&nbsp;the&nbsp;buttons&nbsp;below!</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;ensure&nbsp;that&nbsp;the&nbsp;buttonTarget&nbsp;display&nbsp;the&nbsp;whole&nbsp;text</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;dock&nbsp;the&nbsp;button&nbsp;to&nbsp;fill&nbsp;the&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;button&nbsp;to&nbsp;the&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;enable&nbsp;button</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this&nbsp;cell&nbsp;is&nbsp;the&nbsp;bottom&nbsp;left&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Enable</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">EnableDisableWindow::buttonEnable_OnClick);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonEnable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;add&nbsp;the&nbsp;disable&nbsp;button</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GuiCellComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;cell</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GuiCellComposition;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(cell);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;this&nbsp;cell&nbsp;is&nbsp;the&nbsp;bottom&nbsp;right&nbsp;cell</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetSite(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable</span><span style="color: #000000">=</span><span style="color: #000000">g::NewButton();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Disable</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAlignmentToParent(Margin(</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Clicked.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">EnableDisableWindow::buttonDisable_OnClick);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cell</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(buttonDisable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;change&nbsp;the&nbsp;button&nbsp;font</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontProperties&nbsp;font;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font</span><span style="color: #000000">=</span><span style="color: #000000">buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetFont();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.size</span><span style="color: #000000">=</span><span style="color: #000000">20</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonTarget</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonEnable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buttonDisable</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;call&nbsp;this&nbsp;to&nbsp;calculate&nbsp;the&nbsp;size&nbsp;immediately&nbsp;if&nbsp;any&nbsp;indirect&nbsp;content&nbsp;in&nbsp;the&nbsp;table&nbsp;changes<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;so&nbsp;that&nbsp;the&nbsp;window&nbsp;can&nbsp;calcaulte&nbsp;its&nbsp;correct&nbsp;size&nbsp;before&nbsp;calling&nbsp;the&nbsp;MoveToScreenCenter()</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table</span><span style="color: #000000">-&gt;</span><span style="color: #000000">UpdateCellBounds();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;update&nbsp;the&nbsp;size</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetBounds(Rect());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;move&nbsp;to&nbsp;the&nbsp;screen&nbsp;center</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">-&gt;</span><span style="color: #000000">MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">EnableDisableWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiWindow</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;window</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;EnableDisableWindow();<br />&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Run(window);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;window;<br />}</span></div><br />&nbsp;&nbsp;&nbsp; 代码里面充满了注释，而且主要的内容也在上面介绍了，在这里我就不罗嗦了。所有的代码都可以在<a href="http://gac.codeplex.com">http://gac.codeplex.com</a>中，下载最新的代码，然后在Libraries\GacUI\GacUIDemo\GacUIDemo.sln下面找到。<img src ="http://www.cppblog.com/vczh/aggbug/172755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-04-25 18:46 <a href="http://www.cppblog.com/vczh/archive/2012/04/25/172755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：使用Label控件模仿超链接</title><link>http://www.cppblog.com/vczh/archive/2012/04/24/172638.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Tue, 24 Apr 2012 10:37:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/04/24/172638.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/172638.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/04/24/172638.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/172638.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/172638.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; 今天我给<a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>添加了一个新Demo。我发现写Demo也是一个测试的过程，可以用来检验类库提供的API是否够完整。前面这两个Demo都促使我往类库里面加入了新的函数。这次的Demo是用Label控件来模仿超链接。下载最新代码之后，可以在&#8220;Libraries\GacUI\GacUIDemo\GacUIDemo.sln&#8221;下面找到最新的Demo代码。<br /><br />&nbsp;&nbsp;&nbsp; 为了模仿超链接，我们要做两件事情。第一件事情就是鼠标悬浮在Label上的时候需要显示出手的光标图，第二件事情就是在鼠标进入Label的时候显示下划线，离开的时候去掉下划线。因此我们需要监听三个事件，分别是MouseEnter，MouseLeave和LeftButtonDown。下面是Demo的图：<br /><br />&nbsp;&nbsp;&nbsp; 上图：鼠标在Label外。下图：鼠标在Label内。单击Label的时候会打开浏览器。<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_27.jpg" width="316" height="486" /><br /><br />&nbsp;&nbsp;&nbsp; 代码如下：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\Public\Source\GacUIIncludes.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;SetupWindowsDirect2DRenderer();<br />}<br /><br /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HyperlinkWindow&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;GuiWindow<br />{<br /></span><span style="color: #0000ff">private</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiLabel</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;labelHyperlink_OnMouseEnter(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontProperties&nbsp;font</span><span style="color: #000000">=</span><span style="color: #000000">labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetFont();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.underline</span><span style="color: #000000">=</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;labelHyperlink_OnMouseLeave(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontProperties&nbsp;font</span><span style="color: #000000">=</span><span style="color: #000000">labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetFont();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.underline</span><span style="color: #000000">=</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;labelHyperlink_OnLeftButtonDown(GuiGraphicsComposition</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;sender,&nbsp;GuiMouseEventArgs</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;arguments)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShellExecute(NULL,&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">OPEN</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;L</span><span style="color: #000000">"</span><span style="color: #000000">http://www.cppblog.com/vczh</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;NULL,&nbsp;NULL,&nbsp;SW_SHOWNORMAL);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />&nbsp;&nbsp;&nbsp;&nbsp;HyperlinkWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:GuiWindow(GetCurrentTheme()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">CreateWindowStyle())<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Controls.Label.Hyperlink</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetClientSize(Size(</span><span style="color: #000000">300</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">200</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MoveToScreenCenter();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">=</span><span style="color: #000000">g::NewLabel();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">http://www.cppblog.com/vczh</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetTextColor(Color(</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">255</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontProperties&nbsp;font;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.fontFamily</span><span style="color: #000000">=</span><span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">Segoe&nbsp;UI</span><span style="color: #000000">"</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.size</span><span style="color: #000000">=</span><span style="color: #000000">18</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.antialias</span><span style="color: #000000">=</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INativeCursor</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;hand</span><span style="color: #000000">=</span><span style="color: #000000">GetCurrentController()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">ResourceService()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetSystemCursor(INativeCursor::Hand);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetBoundsComposition()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetAssociatedCursor(hand);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetEventReceiver()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">mouseEnter.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">HyperlinkWindow::labelHyperlink_OnMouseEnter);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetEventReceiver()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">mouseLeave.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">HyperlinkWindow::labelHyperlink_OnMouseLeave);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labelHyperlink</span><span style="color: #000000">-&gt;</span><span style="color: #000000">GetEventReceiver()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">leftButtonDown.AttachMethod(</span><span style="color: #0000ff">this</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">HyperlinkWindow::labelHyperlink_OnLeftButtonDown);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddChild(labelHyperlink);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">HyperlinkWindow()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiWindow</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;window</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HyperlinkWindow();<br />&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Run(window);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;window;<br />}</span></div><br />&nbsp;&nbsp;&nbsp; 这里展示的主要是监听事件的方法。在使用control-&gt;GetEventReceiver()-&gt;event的时候，可以使用Attach、AttachMethod、AttachFunction和AttachLambda。AttachLambda传入一个functor，在C++11里面可以直接使用lambda表达式。在这里使用AttachMethod给一个事件绑定类成员函数。C++运行类成员函数的时候，不仅需要参数，还需要一个this对象，所以AttachMethod有两个参数，使用方法在Demo里面已经展现出来了。<br /><br />&nbsp;&nbsp;&nbsp; 在这里还引入了GetCurrentController函数。GetCurrentController返回的INativeController对象抽象了所有需要的操作系统的功能，其中获得一个光标的对象就封装在了ResourceService里面。INativeController还包含了很多其他的Service，这个留在以后的Demo展示。</div> <img src ="http://www.cppblog.com/vczh/aggbug/172638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-04-24 18:37 <a href="http://www.cppblog.com/vczh/archive/2012/04/24/172638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI文档已经全部写完，进入制作Demo阶段</title><link>http://www.cppblog.com/vczh/archive/2012/04/23/172511.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Mon, 23 Apr 2012 15:37:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/04/23/172511.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/172511.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/04/23/172511.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/172511.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/172511.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今晚终于把<a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>所有该加上的XML注释都加上了，开始做起了Demo。需要做的Demo大概有几十个，除了每个控件要那么几个以外，还有一些其他功能，譬如换皮肤换风格啊，使用不同的渲染器啊，移植到Direct3D上什么的，好多啊，即将写到手软。今天写了第一个Demo，是一个helloworld程序。创建一个GacUI程序是一件很容易的事情，首先下载<a style="text-decoration: underline" href="http://gac.codeplex.com/SourceControl/changeset/changes/89589" target="_blank"><a style="text-decoration: underline" href="http://gac.codeplex.com/SourceControl/changeset/changes/89589" target="_blank">GacUI</a>的最新代码</a>（在有了Release之后会有更好的文件组织和html文档），然后将&#8220;Libraries\GacUI\Public\Source&#8221;下面的5个文件添加进建好的Visual C++的Windows工程里面，然后开始写main函数：<br /><br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\Public\Source\GacUIIncludes.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;SetupWindowsDirect2DRenderer();<br />}<br /><br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GuiMain()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiWindow</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;window</span><span style="color: #000000">=</span><span style="color: #000000">g::NewWindow();<br />&nbsp;&nbsp;&nbsp;&nbsp;window</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Hello,&nbsp;world!</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;window</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetClientSize(Size(</span><span style="color: #000000">640</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">480</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;window</span><span style="color: #000000">-&gt;</span><span style="color: #000000">MoveToScreenCenter();<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;GuiControl</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;label</span><span style="color: #000000">=</span><span style="color: #000000">g::NewLabel();<br />&nbsp;&nbsp;&nbsp;&nbsp;label</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetText(L</span><span style="color: #000000">"</span><span style="color: #000000">Welcome&nbsp;to&nbsp;GacUI&nbsp;Library!</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FontProperties&nbsp;font;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.fontFamily</span><span style="color: #000000">=</span><span style="color: #000000">L</span><span style="color: #000000">"</span><span style="color: #000000">Segoe&nbsp;UI</span><span style="color: #000000">"</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.size</span><span style="color: #000000">=</span><span style="color: #000000">40</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font.antialias</span><span style="color: #000000">=</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;label</span><span style="color: #000000">-&gt;</span><span style="color: #000000">SetFont(font);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;window</span><span style="color: #000000">-&gt;</span><span style="color: #000000">AddChild(label);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;GetApplication()</span><span style="color: #000000">-&gt;</span><span style="color: #000000">Run(window);<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;window;<br />}</span></div><br />&nbsp;&nbsp;&nbsp; Main函数里面需要选择渲染器，这里选的是Direct2D。如果要选择GDI，则调用SetupWindowsGDIRenderer。至于void GuiMain(void)函数则是类库自己的要求，一定要有那么一个，因为SetupWindowsDirect2DRenderer（或GDI）最终会进行一大段初始化工作之后调用一个声明了却没有实现的void GuiMain(void)函数，所以一个合法的GacUI工程需要包含void GuiMain(void)的实现，也就是上面这样。<br /><br />&nbsp;&nbsp;&nbsp; 然后接下来的就是普通的工作了，创建一个GuiWindow，加点东西，Run一下当主窗口。当主窗口被关掉的时候Run函数就会结束，这个时候进行一下必要的清理，程序就可以结束了。运行之后就是下面这个样子：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_26.jpg" width="656" height="518" /><br /><br />&nbsp;&nbsp;&nbsp; 至此HelloWorld的Demo就结束了。<br /><br /><img src ="http://www.cppblog.com/vczh/aggbug/172511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-04-23 23:37 <a href="http://www.cppblog.com/vczh/archive/2012/04/23/172511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>成功从VC++的XML注释生成静态html文档</title><link>http://www.cppblog.com/vczh/archive/2012/04/01/169794.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sun, 01 Apr 2012 08:43:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/04/01/169794.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/169794.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/04/01/169794.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/169794.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/169794.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp; <a style="text-decoration: underline" href="http://gac.codeplex.com" target="_blank">GacUI</a>的类库说明文档已经可以生成了！利用了<a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2012/03/10/167539.html" target="_blank">之前的这篇博客</a>描述的pdb信息抽取并和XML注释合并的技术，成功写了一系列工具来从这些信息里面生成静态html文档。现在的XML注释只写了1/3，所以生成的文档还不全。<br /><br />&nbsp;&nbsp;&nbsp; 之所以做这个工具，而不用Doxygen，是因为Visual&nbsp;C++对XML注释有着良好的支持。如果你为你的代码写了XML注释，那么在智能提示里面还可以看到成员的文档。但是这个形式的注释并不是Doxygen所接受的，而微软或其它开源工具对XML注释生成文档的工具仅限于.net程序（包括C++/CLI）。本来GacUI的release所提供的代码是几个压缩过的cpp和h文件，所以可以用一个C++/CLI工程去编译这个代码从而使用那些软件来产生文档的。不过本着造福大众兼磨练自己的精神，就写了一个专门针对VC++的Native C++工程编译产生的xml注释文件和pdb文件抽取数据合成文档的工具。<br /><br />&nbsp;&nbsp;&nbsp; 下面是文档的截图：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_25.jpg" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_24.jpg" /><br /><br /></p>
<p>&nbsp;&nbsp;&nbsp; 文档生成工具的代码已经提交到了Gac Library（<a href="http://gac.codeplex.com" target="_blank">http://gac.codeplex.com</a>）上面。目前的话，只需要打开&lt;root&gt;\Libraries\GacUI\GacUISrc\GacUISrc.sln，使用debug编译之后，运行&lt;root&gt;\Libraries\GacUI\Public\Release.bat，就会在Temp\StaticHtmpDoc\目录下面产生一系列的html文件。目前这个文档的根节点是reference_gacui.html文件。</p>
<p>&nbsp;&nbsp;&nbsp; 在Release.bat里面可以看出，我使用了&lt;root&gt;\Common\Tools\下面的几个exe程序来读pdb、读xml注释并生成静态html文档。在与exe同名的目录下面，有这些工具的源代码。目前这个工具还不能处理模板类的xml注释，这个功能不久之后就会加上去。</p><img src ="http://www.cppblog.com/vczh/aggbug/169794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-04-01 16:43 <a href="http://www.cppblog.com/vczh/archive/2012/04/01/169794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI开源了！</title><link>http://www.cppblog.com/vczh/archive/2012/03/24/168813.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sat, 24 Mar 2012 10:31:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/03/24/168813.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/168813.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/03/24/168813.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/168813.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/168813.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 我最终还是给GacUI专门申请了一个codeplex的项目主页：<a href="http://gac.codeplex.com">http://gac.codeplex.com</a>。Vczh Library++ 3.0上面上传的代码大多是实验产品，相比把GacUI也放在上面发布不太合适，所以开了一个新项目。新的项目使用MS-PL协议。MS-PL的协议跟BSD、MIT和Apache等协议几乎是一样的，除了&#8220;他人不得用MS-PL协议的代码申请专利&#8221;。这是一个避免纠纷的好方法。<br /><br />&nbsp;&nbsp;&nbsp; GacUI现在还没全部完成。目前正在制作文档和教程。文档应该要么是html要么是pdf，教程会跟文档合并到一起去。GacUI大体上还是能用，不过目前处于alpha状态。<br />&nbsp;&nbsp;&nbsp; 已经完成的功能有：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、GDI和Direct2D渲染器<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、皮肤系统<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、各种基于MVVM模式设计的控件<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、可切换的窗口系统。我目前只提供了一个用Windows窗口做窗口骨架的provider，如果你们高兴的话也可以去写一个虚拟的，然后就可以选择Direct2D渲染器，最后合并到游戏里面。<br />&nbsp;&nbsp;&nbsp; 还没完成的功能有：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、按键操作。目前只有文本框接受按键，列表和菜单什么的还没有，快捷键功能也还没有。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、基本对话框的支持。这个我应该不会自己做，而是使用API提供的打开保存文件对话框什么的。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、更加高级的控件，譬如Ribbon、VisualStudio那样子的Docking等等。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、其它。<br />&nbsp;&nbsp;&nbsp; 在这次完成基本的文档和教程之后，将会继续开发GacUI剩余的部分。<br /><br />&nbsp;&nbsp;&nbsp; 之前的实验，让我最终采用代码方式来发布GacUI，并且用抓取PDB地方法，结合Visual C++提供的XML注释来生成文档的reference部分。GacUI虽然文件上百，不过我已经写了一个代码生成器，将他们合并成了3个h文件和2个cpp：Vczh Library++3.0的公共部分一个cpp；GacUI的部分一个cpp。这有利于我将来继续提供脚本引擎或者其他东西，可以共享代码一起编译。现在使用GacUI，只需要将这5个文件添加进工程就好了。而且cpp只有两个，所以如果项目使用预编译头（precompiled header）的话，给这两个cpp分别加上#include "stdafx.h"也将十分简单。 <img src ="http://www.cppblog.com/vczh/aggbug/168813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-03-24 18:31 <a href="http://www.cppblog.com/vczh/archive/2012/03/24/168813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>合并Visual Studio本地C++XML注释文档和PDB的符号内容</title><link>http://www.cppblog.com/vczh/archive/2012/03/10/167539.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sat, 10 Mar 2012 01:04:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/03/10/167539.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/167539.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/03/10/167539.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/167539.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/167539.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要:     终于到了激动人心的时刻了。今天的博客内容将永远消除Visual Studio的本地C++XML注释编译出来的XML文档没有办法生成可读文档的根本原因。<br><br>    首先介绍一下C++的XML注释。在启用注释之前，我们必须先去工程属性里面，把[C/C++ -> Output Files -> Generate Xml Documentation Files]设置成Yes。这样我们就可以在C++的类啊函数上面写XML注释，然后被编译成一份带有符号链接的XML注释集合。这里先给一个GacUI的XML注释的例子：&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/03/10/167539.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/167539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-03-10 09:04 <a href="http://www.cppblog.com/vczh/archive/2012/03/10/167539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用VS API开发一个PDB Dumper并且可以在没装VS2010的计算机上运行</title><link>http://www.cppblog.com/vczh/archive/2012/03/10/167538.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Fri, 09 Mar 2012 22:43:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/03/10/167538.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/167538.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/03/10/167538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/167538.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/167538.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要:     GacUI到了撰写文档的时候了。虽然GacUI本身的功能还没有全部完成，但是发布一个alpha版还是可以的。因此GacUI需要一份文档。自从.net语言支持XML注释生成文档之后，Visual Studio的本地C++也支持使用XML注释了。只要打开了[工程属性 -> C/C++ -> Output Files -> Generate XML Documentation Files]之后，Visual Studio会在编译本地C++工程之后，将所有的XML注释收集起来，放在和可执行文件同一个目录下的<ProjectName.xml>里面。然后我就尝试bing了一下有没有从C++的XML文档生成可读文档的工具，结果发现只有.net才支持。<br><br>    后来我稍微研究了一下（详细内容将会在下一篇博客透露），发现之所以没人写这个工具，是因为只有.net的可执行文件才包含足够多的元数据，而且这些元数据是必须的，否则无法生成一个完整的文档。举个例子，虽然<ProjectName.xml>包含了xml注释和该注释所在的符号，但是却没有包含该符号的结构信息。结果你试图生成一个函&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/03/10/167538.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/167538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-03-10 06:43 <a href="http://www.cppblog.com/vczh/archive/2012/03/10/167538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最终还是决定直接以源代码方式发布GacUI了</title><link>http://www.cppblog.com/vczh/archive/2012/02/29/166814.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Wed, 29 Feb 2012 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/02/29/166814.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/166814.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/02/29/166814.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/166814.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/166814.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在制作GacUI读pdb生成代码的过程中，感受到了C++语言设计和dll的需求之间的鸿沟。对于一个充分利用了C++各种功能的类库来说，制作成dll具有非常大的困难，特别是在函数返回POD（Plain Old Data）的引用，和输入输出带有泛型的类上面。所以现在还是决定以源代码的方式来发布GacUI。但是pdb生成代码并没有白做，因为反射还是存在的。但是因为GacUI一共有48000行代码，80多个源代码文件，直接发布使用起来总是不方便。所以我写了个小工具，根据xml的配置来将源代码合并成少数几个比较大的代码文件。这样使用的时候，只需要直接把几个cpp拖进工程里面，就可以使用了。而且根据之前发布的一个投票，似乎大家也最喜欢这种方法。因此这次的决定，仅仅删掉了作为backup plan的dll方法。<br><br>这里我给出小工具的代码和配置文件。这个配置文件是基于GacUI做出来的，不过大家可以修改它，以便用于自己的工程上面：&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/02/29/166814.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/166814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-02-29 21:34 <a href="http://www.cppblog.com/vczh/archive/2012/02/29/166814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI从pdb生成反射和dll接口首战告捷</title><link>http://www.cppblog.com/vczh/archive/2012/02/22/166191.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Tue, 21 Feb 2012 18:33:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/02/22/166191.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/166191.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/02/22/166191.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/166191.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/166191.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp; 从pdb读取类声明花了很久，从类声明产生反射和dll接口花的时间更久啊，很多细节问题需要解决。文章的代码已经保存在了Vczh Library++3.0（\Tools\Release\SideProjects\GacUI\GacUI.sln）。&nbsp;&nbsp;&nbsp; 反射和dll接口的工作进行了一半。现在把类、函数、属性和各种类型都声称了出来，但是...&nbsp;&nbsp;<a href='http://www.cppblog.com/vczh/archive/2012/02/22/166191.html'>阅读全文</a><img src ="http://www.cppblog.com/vczh/aggbug/166191.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-02-22 02:33 <a href="http://www.cppblog.com/vczh/archive/2012/02/22/166191.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用VisualStudio完成自动化C++代码生成和编译工作（GacUI）</title><link>http://www.cppblog.com/vczh/archive/2012/01/14/164167.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Sat, 14 Jan 2012 06:09:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/01/14/164167.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/164167.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/01/14/164167.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/164167.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/164167.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; GacUI终于进入制作dll的阶段了。昨天上传了一个新的工程，在<a style="text-decoration: underline" href="http://vlpp.codeplex.com" target="_blank">Vczh Library++3.0</a>（E:\Codeplex\vlpp\Workspace\Tools\Release\SideProjects\GacUI\GacUI.sln）。这里面一共有三个工程，有两个是工具，一个是dll。<br /><br />&nbsp;&nbsp;&nbsp; 为了编译出带反射的控件库，因此每一个控件都可以获得一个ITypeDescriptor对象。但是控件库一共有几十个类上千个函数，我不可能一个一个去实现的（请想想实现IDispatcher的时候）。根据<a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2012/01/11/164003.html" target="_blank">上一篇博客</a>讨论过技术，我将使用一个程序来读pdb生成C++代码。详细的计划如下：<br /><br />&nbsp;&nbsp;&nbsp; 1：制作一个_GacPDB工程。这是一个exe，但是是没用的，唯一的用处就是他引用了GacUI.dll所需要的所有源代码，然后靠编译器产生PDB文件。<br />&nbsp;&nbsp;&nbsp; 2：制作一个_TranslatePDBtoXML工程。这是一个exe，从PDB抽取类声明。<br />&nbsp;&nbsp;&nbsp; 3：制作一个_TranslateXMltoCode。顾名思义，不过现在还没做，原理是一样的。<br />&nbsp;&nbsp;&nbsp; 4：GacUI.dll。这个dll包含了所有的控件的实现，还有_TranslateXMLtoCode产生的所有代码。<br /><br />&nbsp;&nbsp;&nbsp; 现在我的目标是，先编译_Translate*工程，然后编译_GacPDB产生pdb后自动调用它们，生成代码结束之后开始合并编译GacUI.dll。所有的这些东西都需要在VisualStudio的&#8220;Rebuild Solution&#8221;里面完成。为了完成这个目标，我创建这些工程之后，按照下面的方法修改了工程属性：
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">_TranslatePDBtoXML:<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;post&nbsp;build&nbsp;action:<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copy&nbsp;$(ProjectDir)msdia100.dll&nbsp;$(SolutionDir)$(Configuration)\msdia100.dll<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">_GenPDB:<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;references:<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_TranslatePDBtoXML<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;post&nbsp;build&nbsp;action:<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$(SolutionDir)$(Configuration)\_TranslatePDBtoXML.exe&nbsp;$(SolutionDir)Debug\_GenPDB.pdb&nbsp;$(SolutionDir)_GenPDB.xml<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">GacUI:<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;references:<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_GenPDB</span></div><br />&nbsp;&nbsp;&nbsp; 1：工程A引用了工程B的话，那么只有当B完全编译好之后才会编译A。因此上面的配置将阻止三个工程平行编译，强制他们按照_TranslatePDBtoXML、_GenPDB和GacUI的顺序来。<br />&nbsp;&nbsp;&nbsp; 2：_TranslatePDBtoXML编译好之后，会把它依赖的msdia100.dll复制到编译出来的exe旁边，以供接下来调用。<br />&nbsp;&nbsp;&nbsp; 3：_GenPDB编译好之后，pdb已经产生了。这个时候它会自动调用上一步编译出来的_TranslatePDBtoXML，读取pdb，输出xml<br />&nbsp;&nbsp;&nbsp; 4：（接下来要做的）调用_TranslateXMLtoCode，输入xml，输出C++代码<br />&nbsp;&nbsp;&nbsp; 5：这个时候，生成的C++代码已经就绪了，所以开始编译GacUI。<br /><br />&nbsp;&nbsp;&nbsp; 附加的好处还有一个。因为_GenPDB引用了GacUI的cpp，所以当GacUI的源代码修改的时候，_GenPDB也会感应到，从而在下次编译GacUI的时候先开始编译_GenPDB。并且因为GacUI依赖了_GenPDB，所以_GenPDB仍然会先编译。而且这种依赖关系是无害的，因为_GenPDB没有输出lib，因此GacUI.dll在运行的时候完全不需要_GenPDB.exe的存在。<br /><br />&nbsp;&nbsp;&nbsp; 好了。那把一个个的cpp文件添加到_GenPDB也是在太麻烦了，所以我投机取巧了一下：
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiApplication.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiBasicControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiListControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiTextControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\GuiWindowControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiComboControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiContainerControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiListViewControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiMenuControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiTextListControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\ExtendedControls\GuiTreeViewControls.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\Styles\GuiCommonStyles.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Controls\Styles\GuiWin7Styles.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsComposition.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsElement.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsEventReceiver.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsHost.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\GraphicsElement\GuiGraphicsTextElement.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">23</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\NativeWindow\GuiNativeWindow.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">24</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\NativeWindow\Windows\WinNativeWindow.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">25</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">26</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Candidate\GUI\GUI\Reflection\GuiTypeDescriptor.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">27</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">28</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Basic.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">29</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Exception.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">30</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\String.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">31</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Threading.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">32</span>&nbsp;<span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">..\..\..\..\..\Library\Collections\Operation.cpp</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">33</span>&nbsp;<span style="color: #000000"></span><span style="color: #008000">//</span><span style="color: #008000">---------------------------------------------------------------</span><span style="color: #008000"><br /></span><span style="color: #008080">34</span>&nbsp;<span style="color: #008000"></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">Windows.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">35</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">36</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CALLBACK&nbsp;WinMain(HINSTANCE&nbsp;hInstance,&nbsp;HINSTANCE&nbsp;hPrevInstance,&nbsp;LPSTR&nbsp;lpCmdLine,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;CmdShow)<br /></span><span style="color: #008080">37</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">38</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br /></span><span style="color: #008080">39</span>&nbsp;<span style="color: #000000">}</span></div></div><br />&nbsp;&nbsp;&nbsp; 啊哈哈哈哈（拖走<br /><br />&nbsp;&nbsp;&nbsp; VisualStudio的功能是强大的。只要善于使用，或者配合MSBuild，所起到的威力将毫不亚于某些著名工具链。而且VisualStudio编译器产生的文件，基本上VisualStudio都有提供API供你阅读，所以也可以做很多事情，譬如我这篇文章说的这样，充当了一个编译器的扩展，而且完美集成。<img src ="http://www.cppblog.com/vczh/aggbug/164167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-01-14 14:09 <a href="http://www.cppblog.com/vczh/archive/2012/01/14/164167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++反射实现方法设想（GacUI）</title><link>http://www.cppblog.com/vczh/archive/2012/01/11/164003.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Wed, 11 Jan 2012 11:39:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/01/11/164003.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/164003.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/01/11/164003.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/164003.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/164003.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; C++的反射一直是一个很多人都在做的事情。不过今天我终于有了一个简单的想法，当然只对VC++编译出来的程序有效。首先看下面的一个单元测试：<br /><br />&nbsp;&nbsp;&nbsp; 如果我们有下面的代码： 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;A{};<br /></span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;B:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;A{};<br /></span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;A{};<br /></span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;D:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;B,&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;C{};<br /></span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;E:</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;A{};<br /></span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;F:</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;A{};<br /></span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;G:</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;E,&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;F{};</span></div>&nbsp;&nbsp;&nbsp; 那么下面的事情一定会发生： 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;d;<br /></span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;da1</span><span style="color: #000000">=</span><span style="color: #000000">static_cast</span><span style="color: #000000">&lt;</span><span style="color: #000000">B</span><span style="color: #000000">&amp;&gt;</span><span style="color: #000000">(d);<br /></span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;da2</span><span style="color: #000000">=</span><span style="color: #000000">static_cast</span><span style="color: #000000">&lt;</span><span style="color: #000000">C</span><span style="color: #000000">&amp;&gt;</span><span style="color: #000000">(d);<br /></span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(</span><span style="color: #000000">&amp;</span><span style="color: #000000">da1</span><span style="color: #000000">!=&amp;</span><span style="color: #000000">da2);<br /></span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;G&nbsp;g;<br /></span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;ga1</span><span style="color: #000000">=</span><span style="color: #000000">static_cast</span><span style="color: #000000">&lt;</span><span style="color: #000000">E</span><span style="color: #000000">&amp;&gt;</span><span style="color: #000000">(g);<br /></span><span style="color: #008080">8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;A</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;ga2</span><span style="color: #000000">=</span><span style="color: #000000">static_cast</span><span style="color: #000000">&lt;</span><span style="color: #000000">F</span><span style="color: #000000">&amp;&gt;</span><span style="color: #000000">(g);<br /></span><span style="color: #008080">9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(</span><span style="color: #000000">&amp;</span><span style="color: #000000">ga1</span><span style="color: #000000">==&amp;</span><span style="color: #000000">ga2);</span></div><br />&nbsp;&nbsp;&nbsp; 对于这种virtual继承的事情，到这里还是很容易理解的。那现在我们来更进一步： 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Base<br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;size;<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Base()<br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:size(</span><span style="color: #000000">0</span><span style="color: #000000">)<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;};<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;template</span><span style="color: #000000">&lt;</span><span style="color: #000000">typename&nbsp;T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Derived&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">virtual</span><span style="color: #000000">&nbsp;Base<br /></span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Derived()<br /></span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(size</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(T))&nbsp;size</span><span style="color: #000000">=</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(T);<br /></span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;};<br /></span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;H&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Derived</span><span style="color: #000000">&lt;</span><span style="color: #000000">H</span><span style="color: #000000">&gt;</span><span style="color: #000000">{};<br /></span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;I&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;H,&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Derived</span><span style="color: #000000">&lt;</span><span style="color: #000000">I</span><span style="color: #000000">&gt;</span><span style="color: #000000">{};<br /></span><span style="color: #008080">24</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;J&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;I,&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Derived</span><span style="color: #000000">&lt;</span><span style="color: #000000">J</span><span style="color: #000000">&gt;</span><span style="color: #000000">{};</span></div><br />&nbsp;&nbsp;&nbsp; 首先，H、I和J都各自拥有自己的唯一的一个Base。J虽然继承了Derived&lt;H&gt;、Derived&lt;I&gt;和Derived&lt;J&gt;，但是始终只拥有一个Base。因为Base是virtual继承的。<br /><br />&nbsp;&nbsp;&nbsp; 其次，sizeof(Derived&lt;T&gt;)&gt;sizeof(Base)始终是成立的，因为Base的virtual继承导致了Derived&lt;T&gt;里面至少要保存一个指向Base（或者可以用来找到Base）的指针。这个条件很重要，因为这导致了sizeof(J)&gt;sizeof(I)这个条件是恒成立的。<br /><br />&nbsp;&nbsp;&nbsp; 好了，那么来看J。由于C++并没有规定多重继承的时候，几个父类的构造函数的顺序是什么，所以我们需要sizeof(J)&gt;sizeof(I)这个条件。为什么呢？看Derived类的构造函数&#8212;&#8212;它之让sizeof(T)更大的数据覆盖Base里面的数据。<br /><br />&nbsp;&nbsp;&nbsp; 所以我们就可以确定下面的事情： 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;H</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;h</span><span style="color: #000000">=</span><span style="color: #000000">H();<br /></span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;H</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">I();<br /></span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;H</span><span style="color: #000000">&amp;</span><span style="color: #000000">&nbsp;j</span><span style="color: #000000">=</span><span style="color: #000000">J();<br /></span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(h.size</span><span style="color: #000000">&lt;</span><span style="color: #000000">i.size);<br /></span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(i.size</span><span style="color: #000000">&lt;</span><span style="color: #000000">j.size);<br /></span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(h.size</span><span style="color: #000000">==</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(H));<br /></span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(i.size</span><span style="color: #000000">==</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(I));<br /></span><span style="color: #008080">8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST_ASSERT(j.size</span><span style="color: #000000">==</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(J));</span></div><br />&nbsp;&nbsp;&nbsp; 无论J的三个Derived&lt;T&gt;的构造函数谁先执行，最后能够留下来的Base里面的数据肯定是Derived&lt;J&gt;里面的数据。讲到这里应该很清楚了。如果读者还没想到这跟反射有什么关系的话，那么请想一下，如果Base除了size以外，还有一个ITypeDescriptor** typeDescriptor;成员。然后Derived改成这样： 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #000000">typename&nbsp;T</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Derived&nbsp;:&nbsp;<img alt="" src="http://www.cppblog.com/Images/dot.gif" /><br /></span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000"></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br /></span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;ITypeDescriptor</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;type;<br /></span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #000000"><br /></span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Derived()<br /></span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(<img alt="" src="http://www.cppblog.com/Images/dot.gif" />){size</span><span style="color: #000000">=</span><span style="color: #0000ff">sizeof</span><span style="color: #000000">(T);&nbsp;typeDescriptor</span><span style="color: #000000">=&amp;</span><span style="color: #000000">type;}<br /></span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">};</span></div><br />&nbsp;&nbsp;&nbsp; 那么不管你的J拿到手里的类型是什么，哪怕是const H&amp; j，那么j.typeDescriptor肯定就是&amp;Derived&lt;J&gt;::type;<br /><br />&nbsp;&nbsp;&nbsp; 到这里还没有跟VC++有关系的东西。假设ITypeDescriptor是一个足够代表反射功能的高级接口的话，那么我们要怎么实现它呢？我们自己来按照字符串去调用各种函数什么的去实现它肯定麻烦到死了。但是如果大家还记的我前面的<a style="text-decoration: underline" href="http://www.cppblog.com/vczh/archive/2011/12/30/163200.html" target="_blank">这篇博客文章</a>的话，那么大家肯定想到了，我们可以写一个程序来替我们读pdb生成ITypeDescriptor的代码，还有把具体的对象赋值进Derived&lt;T&gt;::type里面去的一个初始化函数！啊哈哈哈！当然pdb只能是从Visual C++编译出来的，就算不是，也至少只能是Windows上面的。不过对GacUI来说并无所谓。因为我只要把GacUI在VisualStudio里面编译生成反射的代码，这个生成之后的代码我还是能放到其他地方编译的。到时候我只要连同这段代码一并发布就好了。<br /><br />&nbsp;&nbsp;&nbsp; 当然，这个程序不仅仅可以帮我实现ITypeDescriptor，还可以帮我实现C语言和C++语言的dll接口的实现，因为dll里面肯定不能暴露模板的。下面就仅需要我去把它做出来就可以了。至此，我们让一个类支持反射的代价很低&#8212;&#8212;只要让他继承自Derived&lt;自己&gt;就好了。<br /></div><img src ="http://www.cppblog.com/vczh/aggbug/164003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-01-11 19:39 <a href="http://www.cppblog.com/vczh/archive/2012/01/11/164003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI完成可自定义格式的ComboBox</title><link>http://www.cppblog.com/vczh/archive/2012/01/04/163578.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Wed, 04 Jan 2012 14:24:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2012/01/04/163578.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/163578.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2012/01/04/163578.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/163578.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/163578.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; GacUI今天完成了可自定义格式的ComboBox。ComboBox分为两种，一种是空空如也全部要自己做的只提供下拉功能的GuiComboBoxBase，另一种是在构造函数接受一个GuiSelectableListControl从而自动将列表与ComboBox关联起来的GuiComboBoxListControl。因为列表控件是MVC和virtual mode的混合体，所以如果要自动把列表的文本显示到ComboBox上面去的话，那么加进去的基类为GuiSelectableListControl（预定义的所有列表控件的基类都是这个，包括TreeView）所提供的ItemProvider必须实现一个GuiListControl::IItemPrimaryTextView的View。当然，没有这个View也可以，因为ComboBox同时也可以让你自定义&#8220;选中列表&#8221;的显示方法&#8212;&#8212;不一定非的是一个字符串，也可以是图片啊色块什么的。<br /><br />&nbsp;&nbsp;&nbsp; 最新的代码可以在<a style="text-decoration: underline" href="http://vlpp.codeplex.com" target="_blank">Vczh Library++3.0</a>（Candidate\GUI\GuiDemo\GuiDemo.sln）中找到，运行结果如图所示：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_23.jpg" width="602" height="265" /><br /><br />&nbsp;&nbsp;&nbsp; 这个ComboBox之所以直接跟GuiListControl结合起来，还是归功于GuiListControl的MVC和virtual mode混合功能的设计。GuiListControl可以自定义数据源、数据显示样式、数据排列算法以及坐标轴的。其中数据源运行时可修改但是不可直接替换对象。每一种数据显示样式都可以要求数据源提供某种固定格式的View。譬如list::TextItemStyleProvider就要求数据源提供list::TextItemStyleProvider::ITextItemView，ListView的六种样式共享list::ListViewItemStyleProvider::IListViewItemView。如果你需要设计新的view，或者为已知的数据源提供view，可以简单的继承那个数据源类并override它的RequestView和ReleaseView方法。这样View就成为了数据源和数据显示样式中间的一个媒介。不同的数据显示样式可以共享View，不同的数据源也可以提供相通的View，这样他们之间的耦合就解除了。用户可以根据各自的性能要求来实现View。<br /><br />&nbsp;&nbsp;&nbsp; 举个例子，你直接从文件读出来的一个巨大的struct数组，要求你转换成一个一个的object显然是太浪费性能了。在这种情况下，你只需要实现一个GuiListControl::IItemProvider并提供具体的View的实现，就可以让列表控件仅仅在需要显示数据的时候，才使用index来向View获取具体的数据内容。这可以大大提高性能，而且甚至可以在可能的情况下实现&#8220;一边拖滚动条，一边异步加载数据&#8221;这样的高级操作。<br /><br />&nbsp;&nbsp;&nbsp; 更多的ComboBox样式会在接下来提供到Demo里面去，可能会有ColorPicker或者FontPicker等等，如果时间充足的话。 <img src ="http://www.cppblog.com/vczh/aggbug/163578.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2012-01-04 22:24 <a href="http://www.cppblog.com/vczh/archive/2012/01/04/163578.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GacUI Demo：PDB Viewer（分析pdb文件并获取C++类声明的详细内容）</title><link>http://www.cppblog.com/vczh/archive/2011/12/30/163200.html</link><dc:creator>陈梓瀚(vczh)</dc:creator><author>陈梓瀚(vczh)</author><pubDate>Fri, 30 Dec 2011 12:12:00 GMT</pubDate><guid>http://www.cppblog.com/vczh/archive/2011/12/30/163200.html</guid><wfw:comment>http://www.cppblog.com/vczh/comments/163200.html</wfw:comment><comments>http://www.cppblog.com/vczh/archive/2011/12/30/163200.html#Feedback</comments><slash:comments>20</slash:comments><wfw:commentRss>http://www.cppblog.com/vczh/comments/commentRss/163200.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/vczh/services/trackbacks/163200.html</trackback:ping><description><![CDATA[<div>&nbsp;&nbsp;&nbsp; GacUI为了实现把界面序列化和反序列化到XML，必然要有类似反射一样的功能。但是C++却没有反射，现在想到的方法就是，把编译后的pdb文件拿出来。因为控件不是模板类，所以数据都可以直接获取。pdb文件包含了所有函数的信息，还有被实例化后的模板类和模板函数的信息。因此只需要使用IDiaDataSource（Visual Studio提供的COM组件）读取pdb的类声明之后，把信息整理并输出到一个xml里面，然后就可以用C#编写linq to xml的程序去分析并生成支持C++反射的一系列周边代码了。这样就自动让C++其中一部分必要的类获得反射的功能，代价就是每一次修改完代码之后，要记得非人肉地更新自动生成的代码。<br /><br />&nbsp;&nbsp;&nbsp; 不过为了更加形象的展示pdb的内容，我使用GacUI的带Virtual Mode的TreeView打开pdb填充。这里面有两个view，第一个是pdb，第二个是整理后的class view。显示pdb的GuiTreeView控件展示了如何通过提供一个数据源，从而实现&#8220;展开的时候再从pdb文件里面读取信息&#8221;的技术。而class view则是通过提供一个数据源来将一个文件中的xml读取到内存并显示出来，但是避免new那些暂时还不需要显示出来的TreeViewNode对象。代码放在<a style="text-decoration: underline" href="http://vlpp.codeplex.com" target="_blank">Vczh Library++ 3.0</a>（Candidate\GUI\GUIDemo\GUIDemo.sln）。现在先上图：<br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_21.jpg" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/vczh/DXGUI_22.jpg" width="1010" height="665" /><br /><br />&nbsp;&nbsp;&nbsp; 解析PDB的关键代码在DumpPDB.cpp文件中，大家只需要下载代码并阅读即可。所有的内容都可以从MSDN搜索IDiaDataSource获得，但是运行的话则需要有这个COM组件，一般要求安装Visual Studio。下面解释一下一段C++代码。这是上面那个按钮的回调函数。这个回调函数做了下面几件事情<br />&nbsp;&nbsp;&nbsp; 1、将Button和TagPage都Disable<br />&nbsp;&nbsp;&nbsp; 2、利用线程池异步将PDB的内容保存到XML文件中（一秒钟）<br />&nbsp;&nbsp;&nbsp; 3、第2步完成之后，发一个消息回到GUI线程，自动显示第二个TagPage<br />&nbsp;&nbsp;&nbsp; 4、异步将XML读取到内存。在这里我没有使用延迟读取技术，所以我直接创建了大约几百万个字符串，需要五秒钟<br />&nbsp;&nbsp;&nbsp; 5、第4步完成之后，发一个消息回到GUI线程吗，将创建好的内存中的XML格式显示在TreeView里<br /><br />&nbsp;&nbsp;&nbsp; 这些异步操作来往十分复杂，但是借助C++0x就可以描述得十分清晰。GacUI的实现并没有使用C++0x，但是仍然可以为使用C++0x的那部分用户提供一些更加优化的接口。因此这些复杂的步骤最后就写成了：<br />
<p><span style="color: red"><strong>buttonDump-&gt;Clicked.AttachLambda</strong></span>([=](GuiGraphicsComposition* sender, GuiEventArgs&amp; arguments)<br />{<br />&nbsp;&nbsp;&nbsp; INativeController* controller=GetCurrentController();<br />&nbsp;&nbsp;&nbsp; tabControl-&gt;GetPages()[0]-&gt;GetContainer()-&gt;SetEnabled(false);<br />&nbsp;&nbsp;&nbsp; buttonDump-&gt;SetEnabled(false);<br />&nbsp;&nbsp;&nbsp; buttonDump-&gt;SetText(L"Dumping...");<br />&nbsp;&nbsp;&nbsp; buttonDump-&gt;GetRelatedControlHost()-&gt;GetBoundsComposition()-&gt;SetAssociatedCursor(controller-&gt;GetSystemCursor(INativeCursor::LargeWaiting));</p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: red"><strong>ThreadPoolLite::QueueLambda</strong></span>([=]()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dumppdb::DumpPdbToXml(diaSymbol, L"..\\Debug\\GuiDemo.xml");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red"><strong>GetApplication()-&gt;InvokeLambdaInMainThread</strong></span>([=]()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tabControl-&gt;GetPages()[0]-&gt;GetContainer()-&gt;SetEnabled(true);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tabControl-&gt;SetSelectedPage(tabControl-&gt;GetPages()[1]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buttonDump-&gt;SetText(L"Loading GuiDemo.xml in the class view...");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red"><strong>ThreadPoolLite::QueueLambda</strong></span>([=]()<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; FileStream fileStream(L"..\\Debug\\GuiDemo.xml", FileStream::ReadOnly);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CacheStream cacheStream(fileStream, 1048576);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BomDecoder decoder;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DecoderStream decoderStream(cacheStream, decoder);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StreamReader reader(decoderStream);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ptr&lt;TreeElement&gt; xml=LoadXmlRawDocument(reader).Cast&lt;TreeElement&gt;();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red"><strong>GetApplication()-&gt;InvokeLambdaInMainThreadAndWait</strong></span>([=]()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buttonDump-&gt;SetText(L"GuiDemo.xml dumpped.");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buttonDump-&gt;GetRelatedControlHost()-&gt;GetBoundsComposition()-&gt;SetAssociatedCursor(controller-&gt;GetDefaultSystemCursor());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GuiTreeView* treeControl=new GuiTreeView(new win7::Win7TreeViewProvider, CreateProviderFromXml(xml));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeControl-&gt;GetBoundsComposition()-&gt;SetAlignmentToParent(Margin(0, 0, 0, 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeControl-&gt;SetVerticalAlwaysVisible(false);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; treeControl-&gt;SetHorizontalAlwaysVisible(false);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tabControl-&gt;GetPages()[1]-&gt;GetContainer()-&gt;GetContainerComposition()-&gt;AddChild(treeControl-&gt;GetBoundsComposition());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp; });<br />});</p><br />&nbsp;&nbsp;&nbsp; buttonDump-&gt;Clicked.AttachLambda的意思是将一个满足C++0x标准的lambda表达式当成一个事件处理程序绑定到一个时间上。ThreadPoolLite::QueueLambda则是将一个lambda表达式放进Windows内核实现的内存池进行异步调用。GetApplication()-&gt;InvokeLambdaInMainThread(AndWait)则是在别的线程里将一个lambda表达式放到GUI线程（一般是主线程）中运行。如果调用了Wait的版本，则这个函数会一直等到该lambda表达式在主线程执行完了才会返回。如果大家关心实现的话，可以去Candidate\GUI\GUI\NativeWindow\Windows\WinNativeWindow.cpp文件里查看。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<strong>大家可以想象，在古老的不支持lambda表达式的C++版本里面，要实现这个过程，这个函数将被拆散成多少函数。为了传递很多复杂的对象，要写多少个临时的struct，new多少内存碎片才能将异步回调函数的参数做成Windows所希望的DWORD(__stdcall*)(void*)格式。为了把一部分事情放回到GUI线程做（我们都知道GUI库不值得为了线程安全而做很多浪费性能的事情），得实现多少私有的Win32消息，subclass多少东西才能最终做到。这一切在GacUI中都简化了。<br /></strong><br />&nbsp;&nbsp;&nbsp; 接下来将会研究如何利用pdb里面的信息让跟GacUI有关的对象支持反射的具体细节。元旦就先休息了，啊哈哈哈。<br /></div><img src ="http://www.cppblog.com/vczh/aggbug/163200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/vczh/" target="_blank">陈梓瀚(vczh)</a> 2011-12-30 20:12 <a href="http://www.cppblog.com/vczh/archive/2011/12/30/163200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>