1.6 界面编程
<h2>1 使用XML布局文件</h2>
<p>SkinUI推荐使用XML布局文件来控制视图,这样不仅简单明了,而且可以将应用的视图控制逻辑从C++代码中分离出来,放入XML文件中控制,从而更好的体现逻辑与界面分离的原则。</p>
<p>在SkinUI应用的bin\debug\res\HelloWorld\layout\目录下定义一个文件名为【SkinDialog.xml】的布局文件。布局文件的格式如下:</p>
<pre><code class="language-xml">&lt;SkinDialog DefaultWidth=&quot;400&quot; DefaultHeight=&quot;300&quot; SysButton=&quot;CLOSE&quot; Icon=&quot;128&quot; Caption=&quot;IDS_CONTROL_SHOW1&quot; Animation=&quot;SizeChange&quot; EscCloseDialog=&quot;true&quot;&gt;
&lt;SkinTextView Id=&quot;1&quot; FontColor=&quot;ID_COLOR_TEXT&quot; Text=&quot;IDS_CONTROL_SHOW_TEXT1&quot; AlignParentLeft=&quot;30&quot; AlignParentRight=&quot;30&quot; AlignParentTop=&quot;45&quot; LayoutHeight=&quot;24&quot; FontStyle=&quot;ID_FONT_NORMAL&quot;/&gt;
&lt;/SkinDialog&gt;</code></pre>
<p>C++代码可以通过以下方式使用该布局文件:</p>
<ul>
<li>
<p>作为模态对话框的布局文件</p>
<pre><code class="language-c">CSkinDialog dlg(_T(&quot;SkinDialog.xml&quot;));
dlg.DoModal(m_hWnd);</code></pre>
</li>
<li>
<p>作为非模态对话框的布局文件</p>
<pre><code class="language-c">CSkinDialog* pSkinDialog = new CSkinDialog(_T(&quot;SkinDialog.xml&quot;));
if(pSkinDialog)
{
if(!pSkinDialog-&gt;Create())
{
delete pSkinDialog;
}
else
{
pSkinDialog-&gt;ShowWindow(SW_SHOW);
}
}</code></pre>
<h2>2 使用C++代码</h2>
<p>虽然SkinUI推荐使用XML布局文件来控制UI界面,但是如果开发者愿意,SkinUI允许开发者完全抛弃XML布局文件,完全在C++代码中控制UI界面。如果希望在代码中控制UI界面,那么所有的UI组件都将通过new关键字创建出来,然后以合适的方式搭建在一起即可。</p>
</li>
<li>
<p>头文件</p>
<pre><code class="language-c">class CMainDialog : public CSkinDialog
{
public:
CMainDialog();
public:
virtual void OnInitDialog();
};</code></pre>
</li>
<li>源文件
<pre><code class="language-c">#include &quot;stdafx.h&quot;
#include &quot;MainDialog.h&quot;
CMainDialog::CMainDialog()
: CSkinDialog(_T(&quot;MainDialog.xml&quot;))
{
}
void CMainDialog::OnInitDialog()
{
CSkinDialog::OnInitDialog();
CSkinTextView* pTextView = new CSkinTextView(this);
if(pTextView)
{
pTextView-&gt;SetId(1);
pTextView-&gt;SetFontColor(_T(&quot;ID_COLOR_TEXT&quot;));
pTextView-&gt;SetText(_T(&quot;IDS_CONTROL_SHOW_TEXT1&quot;));
pTextView-&gt;SetLayoutAlignParentLeft(30);
pTextView-&gt;SetLayoutAlignParentRight(30);
pTextView-&gt;SetLayoutAlignParentTop(45);
pTextView-&gt;SetLayoutHeight(24);
pTextView-&gt;SetFontStyle(_T(&quot;ID_FONT_NORMAL&quot;));
}
}</code></pre></li>
</ul>
<h2>3 XML布局文件和C++代码混合</h2>
<p>完全使用C++代码来控制UI界面不仅繁琐,而且不利于解耦。而完全使用XML布局文件来控制UI界面虽然方便、便捷,但难免有失灵活。因此,有些时候可能需要混合使用XML布局文件和代码来控制UI界面。</p>
<p>当混合使用XML布局文件和代码来控制UI界面时,习惯上把变化小、行为比较固定的组件放在XML布局文件中管理,而那些控制比较复杂的组件则交给C++代码来管理。</p>
<p>例如下面的应用,我们先在布局文件中定义一个简单的树控件,该布局文件的代码如下:</p>
<pre><code class="language-xml">&lt;SkinDialog DefaultWidth=&quot;400&quot; DefaultHeight=&quot;300&quot; SysButton=&quot;CLOSE&quot; Icon=&quot;128&quot; Caption=&quot;IDS_CONTROL_SHOW12&quot; Animation=&quot;SizeChange&quot;&gt;
&lt;SkinRelativeLayout AlignParentLeft=&quot;15&quot; AlignParentRight=&quot;15&quot; AlignParentTop=&quot;35&quot; AlignParentBottom=&quot;15&quot; BkgColor=&quot;ID_COLOR_WHITE&quot; Border=&quot;ID_COLOR_LINE&quot;&gt;
&lt;SkinTreeView Id=&quot;101&quot; AlignParentLeft=&quot;1&quot; AlignParentRight=&quot;1&quot; AlignParentTop=&quot;1&quot; AlignParentBottom=&quot;1&quot; VScrollBar=&quot;VScrollBar.xml&quot;&gt;
&lt;/SkinTreeView&gt;
&lt;/SkinRelativeLayout&gt;
&lt;/SkinDialog&gt;</code></pre>
<p>上面的布局文件只是定义了一个简单的树控件。接下来我们会在程序中获取该树控件,并往该树控件添加子节点。下面是代码:</p>
<pre><code class="language-c">void CTreeDialog::OnInitDialog()
{
CSkinDialog::OnInitDialog();
CSkinTreeView* pTreeView = static_cast&lt;CSkinTreeView*&gt;(GetChildById(IDC_TREEVIEW));
if(pTreeView)
{
for(int64 i = 0; i &lt; 10; ++i)
{
CSkinTreeItem* pRootItem = new CSkinTreeItem(pTreeView);
if(pRootItem)
{
pRootItem-&gt;SetLayoutHeight(30);
pRootItem-&gt;SetLayout(_T(&quot;TreeItem.xml&quot;));
pRootItem-&gt;SetImage(_T(&quot;ListItem.png&quot;));
pTreeView-&gt;InsertItem(NULL, pRootItem);
for(int64 j = 0; j &lt; 10; ++j)
{
CSkinTreeItem* pTreeItem = new CSkinTreeItem(pTreeView);
if(pTreeItem)
{
pTreeItem-&gt;SetLayoutHeight(30);
pTreeItem-&gt;SetLayout(_T(&quot;TreeItem.xml&quot;));
pTreeItem-&gt;SetImage(_T(&quot;ListItem.png&quot;));
pTreeView-&gt;InsertItem(pRootItem, pTreeItem);
}
}
}
}
pTreeView-&gt;ResetSortedItem();
}
}</code></pre>