3 SkinUI视图组件和界面编程

所有的组件都提供了两种方式来控制组件的行为。

  • 在XML布局中通过XML属性进行控制
  • 在C++程序代码中通过调用方法进行控制

SkinUI推荐使用XML布局文件,而不是C++代码来定义用户界面。实际上,不管使用哪种方式,它们控制SkinUI用户界面行为的本质是一样的。大部分时候,控制UI组件的XML属性都有对应的方法。

3.1 视图组件(CSkinView)

CSkinView是所有UI组件的基类,包含的XML属性和方法所有UI组件都可以使用。
下面是CSkinView类常用的XML属性和相关方法:

3.1.1设置组件 Id

  • 通过XML属性控制如下:
Id="1001"
  • 通过C++程序代码调用方法控制如下:
virtual void SetId(LONG nId);

3.1.2设置组件文本

  • 通过XML属性控制如下:
Text="IDS_OK"
  • 通过C++程序代码调用方法控制如下:
virtual void SetText(const tstring& strText);

3.1.3设置组件简单提示信息

  • 通过XML属性控制如下:
Tips="IDS_CLOSE_TIPS"
  • 通过C++程序代码调用方法控制如下:
virtual void SetTips(const tstring& strTips);

3.1.4设置组件复杂提示信息

  • 通过XML属性控制如下:
SkinTips="SkinTips.xml"
  • 通过C++程序代码调用方法控制如下:
virtual void SetSkinTipsLayout(const tstring& strLayout);

3.1.5设置组件复杂提示信息的偏移量

  • 通过XML属性控制如下:
SkinTipsOffset="-10,-10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetSkinTipsOffset(const CPoint& point);

3.1.6设置组件是否可见

  • 通过XML属性控制如下:
Visible="false"
  • 通过C++程序代码调用方法控制如下:
virtual void SetVisible(BOOL bVisible);

3.1.7设置组件是否可用

  • 通过XML属性控制如下:
Enable="false"
  • 通过C++程序代码调用方法控制如下:
virtual void SetEnable(BOOL bEnabled);

3.1.8设置组件是否获得焦点

  • 通过XML属性控制如下:
Focused="true"
  • 通过C++程序代码调用方法控制如下:
virtual void SetFocus(BOOL bFocus);

3.1.9设置组件前景图像

  • 通过XML属性控制如下:
Image="CheckBox.png"
  • 通过C++程序代码调用方法控制如下:
virtual void SetImage(const tstring& strImage);

3.1.10设置组件前景颜色

  • 通过XML属性控制如下:
Color="ID_COLOR_RED"
  • 通过C++程序代码调用方法控制如下:
virtual void SetColor(const tstring& strColor);

3.1.11设置组件边框颜色

  • 通过XML属性控制如下:
Border="ID_COLOR_BORDER"
  • 通过C++程序代码调用方法控制如下:
virtual void SetBorderColor(const tstring& strColor);

3.1.12设置组件背景图片

  • 通过XML属性控制如下:
BkgImage="bkg.png"
  • 通过C++程序代码调用方法控制如下:
virtual void SetBkgImage(const tstring& strImage);

3.1.13设置组件背景颜色

  • 通过XML属性控制如下:
BkgColor="ID_COLOR_BKG"
  • 通过C++程序代码调用方法控制如下:
virtual void SetBkgColor(const tstring& strColor);

3.1.14设置组件菜单

  • 通过XML属性控制如下:
Menu="EditMenu.xml"
  • 通过C++程序代码调用方法控制如下:
virtual void SetMenu(const tstring& strMenu);

3.1.15设置组件最大宽度

  • 通过XML属性控制如下:
MaxWidth="800"
  • 通过C++程序代码调用方法控制如下:
virtual void SetMaxWidth(LONG nMaxWidth);

3.1.16设置组件最大高度

  • 通过XML属性控制如下:
MaxHeight="600"
  • 通过C++程序代码调用方法控制如下:
virtual void SetMaxHeight(LONG nMaxHeight);

3.1.19设置组件模式

  • 通过XML属性控制如下:
Mode="1"
  • 通过C++程序代码调用方法控制如下:
virtual void SetMode(LONG nMode);

3.1.20设置组件接受的拖放类型

  • 通过XML属性控制如下:
Drag="File"
  • 通过C++程序代码调用方法控制如下:
virtual void SetDrag(const vector<UINT>& vecDrag);

3.1.21设置组件是否允许被拖动

  • 通过XML属性控制如下:
AllowDrag="true"
  • 通过C++程序代码调用方法控制如下:
virtual void SetAllowDrag(BOOL bAllow);

3.1.22设置组件外边距

  • 通过XML属性控制如下:
Margin="5,5,5,5"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutMargin(LayoutMargin layoutMargin);

3.1.23设置组件光标

  • 通过XML属性控制如下:
Cursor="32513"
  • 通过C++程序代码调用方法控制如下:
virtual void SetCursor(LONG nCursor);

3.1.24设置组件重绘时是否需要重绘整个窗口

  • 通过XML属性控制如下:
RedrawOwner="true"
  • 通过C++程序代码调用方法控制如下:
virtual void SetRedrawOwner(BOOL bRedrawOwner);

3.1.25设置组件重绘时是否需要重绘父组件

  • 通过XML属性控制如下:
RedrawParent="true"
  • 通过C++程序代码调用方法控制如下:
virtual void SetRedrawParent(BOOL bRedrawParent);

3.1.26设置该组件的子组件重绘时是否需要重绘该组件

  • 通过XML属性控制如下:
RedrawAllChild="true"
  • 通过C++程序代码调用方法控制如下:
virtual void SetRedrawAllChild(BOOL bRedrawAllChild);

3.1.27设置组件的布局XML文件

  • 通过XML属性控制如下:
Layout="Button.xml"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayout(const tstring& strLayout);

3.1.28设置组件布局宽度

  • 通过XML属性控制如下:
LayoutWidth="WrapContent"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutWidth(LONG nLayoutWidth);

3.1.29设置组件布局高度

  • 通过XML属性控制如下:
LayoutHeight="FillParent"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutHeight(LONG nLayoutHeight);

3.1.30设置组件相对于父组件的对齐方式

  • 通过XML属性控制如下:
LayoutAlignment="Left,Top"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignment(LayoutAlignment layoutAlignment);

3.1.31设置组件右边距兄弟组件左边的距离

  • 通过XML属性控制如下:
ToLeftOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutToLeftOf(LONG nId, LONG nOffset);

3.1.32设置组件下边距兄弟组件上边的距离

  • 通过XML属性控制如下:
ToTopOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutToTopOf(LONG nId, LONG nOffset);

3.1.33设置组件左边距兄弟组件右边的距离

  • 通过XML属性控制如下:
ToRightOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutToRightOf(LONG nId, LONG nOffset);

3.1.34设置组件上边距兄弟组件下边的距离

  • 通过XML属性控制如下:
ToBottomOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutToBottomOf(LONG nId, LONG nOffset);

3.1.35设置组件左边距兄弟组件左边的距离

  • 通过XML属性控制如下:
AlignLeftOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignLeftOf(LONG nId, LONG nOffset);

3.1.36设置组件上边距兄弟组件上边的距离

  • 通过XML属性控制如下:
AlignTopOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignTopOf(LONG nId, LONG nOffset);

3.1.37设置组件右边距兄弟组件右边的距离

  • 通过XML属性控制如下:
AlignRightOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignRightOf(LONG nId, LONG nOffset);

3.1.38设置组件下边距兄弟组件下边的距离

  • 通过XML属性控制如下:
AlignBottomOf="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignBottomOf(LONG nId, LONG nOffset);

3.1.39设置组件左边距父组件左边的距离

  • 通过XML属性控制如下:
AlignParentLeft="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignParentLeft(LONG nOffset);

3.1.40设置组件上边距父组件上边的距离

  • 通过XML属性控制如下:
AlignParentTop="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignParentTop(LONG nOffset);

3.1.41设置组件右边距父组件右边的距离

  • 通过XML属性控制如下:
AlignParentRight="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignParentRight(LONG nOffset);

3.1.42设置组件下边距父组件下边的距离

  • 通过XML属性控制如下:
AlignParentBottom="1001,10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignParentBottom(LONG nOffset);

3.1.43设置组件中心与父组件中心水平方向的距离

  • 通过XML属性控制如下:
AlignParentHorizontalCenter="10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignParentHorizontalCenter(LONG nOffset);

3.1.44设置组件中心与父组件中心垂直方向的距离

  • 通过XML属性控制如下:
AlignParentVerticalCenter="10"
  • 通过C++程序代码调用方法控制如下:
virtual void SetLayoutAlignParentVerticalCenter(LONG nOffset);

3.2 对话框组件(CSkinDialog)

对于CSkinDialog类而言,它是所有对话框的基类,因此包含的XML属性和方法是所有对话框都可以使用。
下面是CSkinDialog类常用的XML属性、相关方法及简要说明:

3.2.1设置对话框是否可以改变大小

  • 通过XML属性控制如下:
Resize="true"
  • 通过C++程序代码调用方法控制如下:
void SetResize(BOOL bResize);

3.2.2设置对话框是否可以移动

  • 通过XML属性控制如下:
AllowMove="false"
  • 通过C++程序代码调用方法控制如下:
void SetAllowMove(BOOL bAllow);

3.2.3设置对话框最小宽度

  • 通过XML属性控制如下:
MinWidth="400"
  • 通过C++程序代码调用方法控制如下:
void SetMinWidth(LONG nMinWidth);

3.2.4设置对话框最小高度

  • 通过XML属性控制如下:
MinHeight="300"
  • 通过C++程序代码调用方法控制如下:
void SetMinHeight(LONG nMinHeight);

3.2.5设置对话框默认宽度

  • 通过XML属性控制如下:
DefaultWidth="400"
  • 通过C++程序代码调用方法控制如下:
void SetDefaultWidth(LONG nDefaultWidth);

3.2.6设置对话框默认高度

  • 通过XML属性控制如下:
DefaultHeight="300"
  • 通过C++程序代码调用方法控制如下:
void SetDefaultHeight(LONG nDefaultHeight);

3.2.7设置对话框标题栏高度

  • 通过XML属性控制如下:
TitleHeight="400"
  • 通过C++程序代码调用方法控制如下:
void SetTitleHeight(LONG nTitleHeight);

3.2.8设置对话框主题高度

  • 通过XML属性控制如下:
ThemeHeight="300"
  • 通过C++程序代码调用方法控制如下:
void SetThemeHeight(LONG nThemeHeight);

3.2.9设置对话框标题

  • 通过XML属性控制如下:
Caption="400"
  • 通过C++程序代码调用方法控制如下:
void SetTitleCaption(const tstring& strCaption);

3.2.10设置对话框系统按钮

  • 通过XML属性控制如下:
SysButton="300"
  • 通过C++程序代码调用方法控制如下:
void SetSysButton(const tstring& strSysStyle);

3.1.11设置对话框是否允许毛玻璃效果

  • 通过XML属性控制如下:
OpenAreo="false"
  • 通过C++程序代码调用方法控制如下:
void OpenAreo(BOOL bOpen);

3.1.12设置对话框图标

  • 通过XML属性控制如下:
Icon="128"
  • 通过C++程序代码调用方法控制如下:
void SetTitleIcon(LONG nIconId);

3.2 界面编程

3.2.1 使用XML布局文件

SkinUI推荐使用XML布局文件来控制视图,这样不仅简单明了,而且可以将应用的视图控制逻辑从C++代码中分离出来,放入XML文件中控制,从而更好的体现逻辑与界面分离的原则。

在SkinUI应用的bin\debug\res\HelloWorld\layout\目录下定义一个文件名为【SkinDialog.xml】的布局文件。布局文件的格式如下:

<SkinDialog DefaultWidth="400" DefaultHeight="300" SysButton="CLOSE" Icon="128" Caption="IDS_CONTROL_SHOW1" Animation="SizeChange" EscCloseDialog="true">
    <SkinTextView Id="1" FontColor="ID_COLOR_TEXT" Text="IDS_CONTROL_SHOW_TEXT1" AlignParentLeft="30" AlignParentRight="30" AlignParentTop="45" LayoutHeight="24" FontStyle="ID_FONT_NORMAL"/>
</SkinDialog>

C++代码可以通过以下方式使用该布局文件:

  • 作为模态对话框的布局文件
    CSkinDialog dlg(_T("SkinDialog.xml"));
    dlg.DoModal(m_hWnd);
  • 作为非模态对话框的布局文件
    CSkinDialog* pSkinDialog = new CSkinDialog(_T("SkinDialog.xml"));
    if(pSkinDialog)
    {
        if(!pSkinDialog->Create())
        {
            delete pSkinDialog;
        }
        else
        {
            pSkinDialog->ShowWindow(SW_SHOW);
        }
    }

3.2.2 使用C++代码

虽然SkinUI推荐使用XML布局文件来控制UI界面,但是如果开发者愿意,SkinUI允许开发者完全抛弃XML布局文件,完全在C++代码中控制UI界面。如果希望在代码中控制UI界面,那么所有的UI组件都将通过new关键字创建出来,然后以合适的方式搭建在一起即可。

  • 头文件
class CMainDialog : public CSkinDialog
{
public:
    CMainDialog();
public:
    virtual void OnInitDialog();
};
  • 源文件
#include "stdafx.h"
#include "MainDialog.h"
CMainDialog::CMainDialog()
: CSkinDialog(_T("MainDialog.xml"))
{
}
void CMainDialog::OnInitDialog()
{
    CSkinDialog::OnInitDialog();
    CSkinTextView* pTextView = new CSkinTextView(this);
    if(pTextView)
    {
        pTextView->SetId(1);
        pTextView->SetFontColor(_T("ID_COLOR_TEXT"));
        pTextView->SetText(_T("IDS_CONTROL_SHOW_TEXT1"));
        pTextView->SetLayoutAlignParentLeft(30);
        pTextView->SetLayoutAlignParentRight(30);
        pTextView->SetLayoutAlignParentTop(45);
        pTextView->SetLayoutHeight(24);
        pTextView->SetFontStyle(_T("ID_FONT_NORMAL"));
    }
}

3.2.3 XML布局文件和C++代码混合

完全使用C++代码来控制UI界面不仅繁琐,而且不利于解耦。而完全使用XML布局文件来控制UI界面虽然方便、便捷,但难免有失灵活。因此,有些时候可能需要混合使用XML布局文件和代码来控制UI界面。

当混合使用XML布局文件和代码来控制UI界面时,习惯上把变化小、行为比较固定的组件放在XML布局文件中管理,而那些控制比较复杂的组件则交给C++代码来管理。

例如下面的应用,我们先在布局文件中定义一个简单的树控件,该布局文件的代码如下:

<SkinDialog DefaultWidth="400" DefaultHeight="300" SysButton="CLOSE" Icon="128" Caption="IDS_CONTROL_SHOW12" Animation="SizeChange">
    <SkinRelativeLayout AlignParentLeft="15" AlignParentRight="15" AlignParentTop="35" AlignParentBottom="15" BkgColor="ID_COLOR_WHITE" Border="ID_COLOR_LINE">
        <SkinTreeView Id="101" AlignParentLeft="1" AlignParentRight="1" AlignParentTop="1" AlignParentBottom="1" VScrollBar="VScrollBar.xml">
        </SkinTreeView>
    </SkinRelativeLayout>
</SkinDialog>

上面的布局文件只是定义了一个简单的树控件。接下来我们会在程序中获取该树控件,并往该树控件添加子节点。下面是代码:

void CTreeDialog::OnInitDialog()
{
    CSkinDialog::OnInitDialog();
    CSkinTreeView* pTreeView = static_cast<CSkinTreeView*>(GetChildById(IDC_TREEVIEW));
    if(pTreeView)
    {
        for(int64 i = 0; i < 10; ++i)
        {
            CSkinTreeItem* pRootItem = new CSkinTreeItem(pTreeView);
            if(pRootItem)
            {
                pRootItem->SetLayoutHeight(30);
                pRootItem->SetLayout(_T("TreeItem.xml"));
                pRootItem->SetImage(_T("ListItem.png"));
                pTreeView->InsertItem(NULL, pRootItem);

                for(int64 j = 0; j < 10; ++j)
                {
                    CSkinTreeItem* pTreeItem = new CSkinTreeItem(pTreeView);
                    if(pTreeItem)
                    {
                        pTreeItem->SetLayoutHeight(30);
                        pTreeItem->SetLayout(_T("TreeItem.xml"));
                        pTreeItem->SetImage(_T("ListItem.png"));
                        pTreeView->InsertItem(pRootItem, pTreeItem);
                    }
                }
            }
        }
        pTreeView->ResetSortedItem();
    }
}

以上XML布局文件和C++代码混合,得到的窗口界面截图如下:


XML布局文件和C++代码混合
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,391评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • 很多人都认为在毕业后,就会与朋友慢慢的减少联系,大部分是有吧。 可是我们五个人没有,大家现在都...
    微笑一百点阅读 127评论 0 0
  • 0、Iterator迭代器 父类引用指向子类的实现的典型应用。Snip20160724_98.png 使用 一、增...
    PanPan1127阅读 210评论 0 1