C++ Builder 的 PME 架构

C++ Builder 参考手册C++ Builder 的 PME 架构


__property, __closure, __published, 经常能看到 C++ Builder 这些关键字,都有什么作用呢?

PME 是 property-method-event (属性-方法-事件) 的缩写,这是 C++ Builder 控件实现的基础,__property, __closure, __published 是为了实现控件的属性和事件扩充的 C++ 关键字。属性、方法和事件都是类的成员,其中:

  • 属性:就像一个成员变量,读和写这个属性可以对应这个类的两个函数;
  • 方法:就是类的成员函数;
  • 事件:是回调函数指针,与普通的函数指针不同,这是指向成员函数的指针。

一. 属性 (property)

__property 类型 名称 = { 参数 };
__property 类型 名称[类型1] = { 参数 };
__property 类型 名称[类型1][类型2] = { 参数 };

__property 名称;
__property 名称= { 参数 };

项目 说明
类型 属性的变量类型
名称 属性的名称,相当于变量名
类型1,类型2 数组属性的下标的变量类型
参数 包含以下表格里的至少一个参数项,项目间用逗号 "," 隔开
参数项 说明
read = FGet 读取属性,FGet 为成员变量或成员函数
write = FSet 写入属性,FSet 为成员变量或成员函数
index = n 这个属性是一个数组属性中的一个元素,n 是下标值
stored = b 控件:是否把这个属性值存到 .dfm 或 .fmx 里面
default = v 控件:这个属性的默认值 = v
nodefault 控件:这个属性没有默认值
  • 类型:从使用者的角度看,属性就像是类的成员变量,这是这个变量的变量类型。如果不写类型,那么这个属性必须是类继承过来的,这个属性和父类的同名属性的类型相同。
  • 名称:从使用者的角度看,属性就像是类的成员变量,这是这个变量的变量名。
  • 类型1,类型2:数组属性的下标的变量类型。
  • read = FGet | 读取属性,FGet 为成员变量或成员函数
  • write = FSet | 写入属性,FSet 为成员变量或成员函数
  • index = n | 这个属性是一个数组属性中的一个元素,n 是下标值
  • stored = b | 控件:是否把这个属性值存到 .dfm 或 .fmx 里面
  • default = v | 控件:这个属性的默认值 = v
  • nodefault | 控件:这个属性没有默认值

例1: 让一个变量只读

下面代码里面的 TTest 类的 FValue 值由于放在了 private: 里面,所以在类的外面只能通过 Value 属性读取,用 SetValue 函数赋值。

class TTest
{
private:
    int FValue;

public:
    __property int Value = { read = FValue };

    void SetValue(int i)
    {
        FValue = i;
    }
    TTest()
    {
        FValue = 0;
    }
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TTest t;
    t.SetValue(10);
    ShowMessage(t.Value);
}

例2: 属性的读写分别使用两个不同的函数

class TTest1
{
private:
    UnicodeString sMyText;

    UnicodeString FGetText(void)
    {
        return sMyText;
    }
    void FSetText(UnicodeString s)
    {
        sMyText = s;
    }
public:
    __property UnicodeString Text = { read = FGetText, write = FSetText };
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TTest1 t;
    t.Text = L"Hsuanlu";
    ShowMessage(t.Text);
}

对于给成员变量来说,这样的属性似乎没有什么实际意义,但是对于控件来说,并不一定是给成员变量赋值,比如给 TEdit 编辑框的 Text 属性赋值,会执行把文字显示在编辑框里面的函数,读取 TEdit 编辑框的 Text 属性值,会从编辑框里面读取文字。

例3:数组属性

class TTest1
{
private:
    UnicodeString sMyText;

    UnicodeString FGetText(void)
    {
        return sMyText;
    }
    void FSetText(UnicodeString s)
    {
        sMyText = s;
    }
    wchar_t FGetChar(int iIndex)
    {
        if(iIndex >= 1 && iIndex <= sMyText.Length())
            return sMyText[iIndex];
        return 0;
    }
    void FSetChar(int iIndex, wchar_t c)
    {
        if(iIndex >= 1 && iIndex <= sMyText.Length())
            sMyText[iIndex] = c;
    }
public:
    __property UnicodeString Text      = { read = FGetText, write = FSetText };
    __property wchar_t       Char[int] = { read = FGetChar, write = FSetChar };
    __property wchar_t       Ch01      = { read = FGetChar, index = 1 };
    __property wchar_t       Ch02      = { read = FGetChar, index = 2 };
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TTest1 t;
    t.Text = L"Hsuanlu";
    Memo1->Lines->Add(t.Text);
    Memo1->Lines->Add(t.Char[4]);
    Memo1->Lines->Add(t.Ch02);
}
运行结果

二. 方法 (method)

方法是类的成员函数,不需要什么特殊说明。

三. 事件 (event)

事件也是一种属性,属性的类型为 __closure 指针,即指向成员函数的函数指针。
事件是作用是让回调函数使用类的成员函数,而不是全局函数或静态成员。

__closure 关键字是修饰指针的,说明这个指针指向成员函数,例如:
void (__closure *pFunc)(int i);
这里的 (__closure *函数名) 都要写在括号里面。
这样的写法是错误的:void __closure (*pFunc)(int i);

例子:

class TMyControl
{
public:
    typedef void __fastcall (__closure *TMyEvent)(TMyControl *Sender, UnicodeString s);

private:
    UnicodeString FText;
    TMyEvent FEvent;

    UnicodeString FGetText(void)
    {
        return FText;
    }
    void FSetText(UnicodeString s)
    {
        FText = s;
    }

public:
    __property UnicodeString Text  = { read = FGetText , write = FSetText };
    __property TMyEvent      Event = { read = FEvent   , write = FEvent   };

    void __fastcall MyMethod(void)
    {
        if(FEvent)
            FEvent(this, FText);
    }
    TMyControl()
    {
        FEvent = NULL;
    }
};

class TMyTest
{
private:
    void __fastcall MyEvent(TMyControl *Sender, UnicodeString s)
    {
        ShowMessage(L"TMyTest::MyEvent:\r\n" + s);
    }

public:
    TMyControl Control;

    TMyTest()
    {
        Control.Event = MyEvent;
    }
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TMyTest t;
    t.Control.Text = L"Hello Hsuanlu!";
    t.Control.MyMethod();
}

运行结果:

运行结果

四. 用于控件类的 __published 关键字

从 TComponent 继承的类可以安装在 C++ Builder 控件面板上,这样的类除了 public:、protected:、private: 之外,还扩充了 __published: ,写在 __published: 里面的都是属性和事件,这些属性和事件安装在控件的属性页面和事件页面上。

控件的属性页面
控件的事件页面

相关:


C++ Builder 参考手册C++ Builder 的 PME 架构

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

推荐阅读更多精彩内容