数据类型库-AmigaOS文档Wiki

2020-11-30 05:29:04

跳转至导航跳转至搜索DataTypes库的目的是提供用于以面向对象的方式处理数据的工具。面向对象的方法意味着您的应用程序可以使用多种数据文件标准,而不必担心每个标准的复杂细节。相反,您只需要了解库的简单约定。

DataTypes库基于Intuition的BOOPSI工具构建(BOOPSI是基本的面向对象的Intuition编程系统的缩写)。尽管不是必需的,但在尝试使用DataTypes库之前了解一下BOOPSI的工作原理非常有帮助。尽管不是必需的,但一定要熟悉面向对象的理论和实践。

由于库使用TagItem结构将参数传递给函数,因此您必须先了解TagItem的工作方式,然后才能调用库函数。有关TagItem的更多信息,请参考实用程序库。

在软件开发中,术语“数据类型”或“数据类型”通常在一般意义上使用,而AmigaOS数据类型框架则建立了相当特殊的上下文。为了避免可能的混淆,本文档使用大写拼写来表示作为所述框架一部分的组件和编程实体,例如:DataTypes库,DataType子类,DataType对象,Picture DataType等。

支持跨各种类型的数据(文本,声音,图像,动画等)的多种文件格式。以简单的方式加载数据,而无需编写专用的加载器代码!

简单一致地处理多种数据标准。了解了如何使用DataTypes库处理一种类型的数据后,您将发现以相同的方式处理其他类型的数据。

剪贴板支持。数据类型库为Amiga的剪贴板设备提供了一致且易于使用的界面,以鼓励应用程序之间的数据共享。

直觉小工具支持。由于DataTypes库是使用BOOPSI实现的,因此它处理的数据对象也可以视为小工具。小工具操作可以在Intuition任务上下文中的数据对象上执行,与其他BOOPSI小工具相同。

自动从一种格式转换为另一种格式。 DataTypes库的未来版本将支持其他类型的数据对象。从一种格式到另一种格式的转换将由库自动处理。

验证。例如,您可以轻松地检查文件是否为有效的JPEG(AIFF,AmigaGuide等)。

如果您以前从未使用过面向对象的系统,则用于描述DataTypes库的术语可能会有些混乱。例如,库支持的数据种类分为类和子类。术语“类”在这里以一种熟悉的方式使用。类的成员仅具有一组公共属性。子类的成员具有父类(超类)的所有属性以及该子类特定的其他属性。 (每个子类可以进一步细分为子子类,依此类推。)

类或子类的实际实例称为对象。术语“对象”是适当的,因为通常我们希望忽略每个个案的细节,而专注于根据对象的类来处理对象。在上面的示例中,雏菊对象可以运行并且可以挤奶。可以用一个对象执行的操作称为方法,并且称该对象继承了其父类的方法和其他属性(反过来,它继承了其父类的方法和属性,如果有的话)。

datatypes.library实现了所有其他DataType类都从其继承的datatypes类。下面的BOOPSI类图说明了各种DataTypes类如何相互关联。

下面列出的示例程序演示了如何对ILBM和8SVX类对象执行一些基本方法。

DataType类除了支持的方法(操作)外,还具有其他属性。对于每个属性,在DataTypes库中定义了一个对应的TagItem,可用于检查或设置特定对象中的该属性。例如,图片对象具有显示模式属性。控制此属性的标记名为PDTA_ModeID,并在Autodoc文件picture_dtc.doc中进行了描述。有关所有类属性的完整列表,请参见每个类的Autodoc文件(如表1所示)。

包含文件中的类属性描述也具有一组指示该属性适用性的代码。代码如下:

在您实际尝试使用DataTypes库之前,这些代码似乎有些神秘。 N和U代码尤其适用于想要实现自己的对象类的特殊应用程序,这是本文讨论范围之外的高级主题。

如果所有这些新概念看起来有些令人生畏,请放心; DataTypes库使用常规的C语言函数调用来完成工作。下面列出了您最常使用的电话。注意,对于DataTypes库的这些基本功能中的每一个,在Intuition库中都有一个等效的BOOPSI调用。

获取DataTypes对象支持的方法的列表。写入,复制和选择是对象可能支持的方法的示例。

获取DataType对象支持的触发方法的列表。诸如“播放”,“暂停”和“恢复”之类的操作是对象可能支持的触发方法的示例。

获取DataTypes文本ID的本地化文本字符串。对于获取本地化的错误消息很有用。

释放对象以及通过DisposeDTObject()使用的所有内存或其他资源。

DataTypes库函数调用使用了许多结构。本文中没有太多总结。但是,这是相关包含文件的列表,其中包含类用户感兴趣的结构定义。

这些包含文件中的两个最重要的定义出现在中。数据类型库函数(和Intuition中的BOOPSI函数)一起使用的对象定义如下:

由于我们希望将对象视为黑匣子,并且实际上并不关心它们的实现方式,因此此定义非常合适。当使用对象执行方法时,用于标识该方法的参数为Msg结构,定义如下:

有些方法不仅需要方法标识符,还需要更多信息。此类方法具有包含文件中定义的自定义结构。但是,所有方法结构均以包含方法ID的字段开头。

NewDTObjectA()返回的指针是指向BOOPSI对象的指针。与其他BOOPSI对象一样,DataType对象是“黑匣子”,在不使用提供的接口的情况下,请勿窥视和戳戳。

要创建DataType对象,NewDTObjectA()需要知道从何处获取用于创建对象的数据。默认情况下,名称被视为文件名。

attrs标记列表是标记/值对的列表,每个标记/值对都包含属性的初始值。 中定义了许多可在创建时使用的属性。

源数据在剪贴板中。名称是单位编号。例如,(APTR)0,表示剪贴板单元为零。

可以代替名称字段使用。如果源类型是DTST_FILE,则句柄必须是有效的BPTR文件句柄。如果源类型为DTST_CLIPBOARD,则句柄必须为有效的IFFHandle。

可用于指定用于处理数据的类。数据必须是指向有效DataType的指针。仅在尝试创建没有源数据或可以由多个类处理的新对象时才应使用此方法(例如,可以用于强制对象由AmigaGuide类处理)。

如果存在此标记,则数据必须是指定的类型,否则对象创建将失败,并显示ERROR_OBJECT_WRONG_TYPE。例如,声音编辑器可以使用它来确保只能加载声音。

在创建时可以指定其他属性,但这些属性取决于要创建的对象的数据类型。有关更多属性,请参见头文件。

指定小工具的左边缘相对于包含窗口的右边缘。

指定小工具的上边缘相对于包含窗口的下边缘。

指定小工具的宽度相对于包含窗口的宽度。

指定小工具相对于包含窗口高度的高度。

为了使应用程序能够从DataType对象接收信息,它必须为该对象发出的通知属性设置一个目标。

获取通知的常用方法是设置ICTARGET_IDCMP的ICA_TARGET,以便应用程序将通过IDCMP_IDCMPUPDATE直觉消息类接收属性。但是也可以将另一个BOOPSI对象设置为接收者。

如果NewDTObjectA()成功,它将返回一个指向DataType对象的指针。否则,它返回NULL,并且可以使用IoErr()获取失败原因。有关更多信息,请参见Autodocs中的datatypes.library。

为了将DataType对象嵌入窗口中,有必要询问该对象的最小环境是什么。例如,由于重映射代码不能处理重映射HAM图片,因此必须将它们显示在HAM屏幕上,因此不能将其添加到非HAM屏幕上的窗口中。

ULONG modeid = INVALID_ID; LONG nomwidth,nomheight; BOOL useScreen = FALSE; struct dtFrameBox dtf; struct FrameInfo星期五; / *获取我们感兴趣的属性* / IDataTypes-> GetDTAttrs(dto,/ *获取模式ID * / PDTA_ModeID,&modeid,/ *获取所需的大小* / DTA_NominalHoriz,&nomwidth,DTA_NominalVert,&nomheight,TAG_END); / *清除结构* / IUtility-> ClearMem(&dtf,sizeof(struct dtFrameBox)); IUtility-> ClearMem(&fri,sizeof(struct FrameInfo)); / *填写消息* / dtf。方法ID = DTM_FRAMEBOX; dtf dtf_FrameInfo =&fri; dtf。 dtf_ContentsInfo =&fri; dtf。 dtf_SizeFrameInfo = sizeof(struct FrameInfo); / *执行框架方法* / if(IDataTypes-> DoDTMethodA(dto,NULL,NULL,(Msg)&dtf)){/ *检查对象是否需要HAM屏幕* /如果(fri.fri_PropertyFlags&DIPF_IS_HAM) {IDOS-> Printf(“ HAM \ n”); useScreen = TRUE; } / *检查对象是否需要ExtraHalfBrite屏幕* /否则(fri。fri_PropertyFlags&DIPF_IS_EXTRAHALFBRITE){IDOS-> Printf(“ ExtraHalfBrite \ n”); useScreen = TRUE; } / *安全检查以查看是否需要屏幕* /否则(((fri。fri_PropertyFlags == 0)&&(modeid&0x800)&&(modeid!= INVALID_ID)){IDOS-> Printf(“ ModeID = 0x %08lx \ n“,modeid); useScreen = TRUE; }}其他{/ *不需要特殊环境,可以附加到任何屏幕模式* /}

必须使用DataTypes的AddDTObject()函数将DataType对象添加到窗口。

此函数会将DataTypes对象添加到指定窗口的现有小工具列表中。 pos的建议值为-1,这将导致将DataType对象添加到列表的末尾。

不应使用WA_Gadgets属性将属性添加到OpenWindowTagList()或使用AddGList()函数来添加DataType对象。如果使用AddDTObject()以外的任何方法,则DataTypes要求有一些特殊信息,这些特殊信息将无法获得。

当将DataType对象添加到窗口时,将调用该对象的布局方法。布局可能需要一段时间才能执行,在这种情况下,对象将产生一个异步处理布局的进程。为了刷新对象的视觉信息,有必要从对象中获取IDCMP_IDCMPUPDATE消息并在收到DTA_Sync属性时刷新对象。

对象* dto; struct IntuiMessage * imsg; struct Window * win; ULONG sigr; struct TagItem * tstate,* tags; ULONG tidata; ULONG errnum;布尔= TRUE; / *设置DataType对象的相关属性* / IDataTypes-> SetDTAttrs(dto,NULL,NULL,// *设置对象的尺寸* / GA_Left,win-> BorderLeft,GA_Top,win-> BorderTop,GA_Width,win ->宽度-胜利-> BorderLeft-胜利-> BorderRight,GA_Height,胜利->高度-胜利-> BorderTop-胜利-> BorderBottom,/ *确保我们从*对象* / ICA_TARGET,ICTARGET_IDCMP,TAG_END接收IDCMP_IDCMPUPDATE消息); / *将对象添加到窗口* / IDataTypes-> AddDTObject(win,NULL,dto,-1); / *刷新DataType对象* / IDataTypes-> RefreshDTObjects(dto,win,NULL,NULL); / *继续前进,直到(被告知){/ *等待事件* / sigr = IExec-> Wait((1L UserPort-> mp_SigBit)| SIGBREAKF_CTRL_C}; / *如果(sigr&SIGBREAKF_CTRL_C)= FALSE,我们是否收到了中断信号* /; / *提取直觉消息* / while(imsg =(struct IntuiMessage *)IExec-> GetMsg(win-> UserPort)){/ *处理每条消息* /切换(imsg-> Class){case IDCMP_IDCMPUPDATE:/ *获取一个指向属性列表的指针* / tstate = tags =(struct TagItem *)imsg-> IAddress; / *逐步浏览属性列表* / while(tag = IUtility-> NextTagItem(&tstate)){tidata = tag-> ti_Data;开关(tag-> ti_Tag){/ *更改为繁忙状态* / case DTA_Busy:if(tidata)IIntuition-> SetWindowPointer(win,WA_BusyPointer,TRUE,TAG_END);否则IIntuition-> SetWindowPointer(win,WA_Pointer,NULL,TAG_END);休息; / *错误消息* / case DTA_ErrorLevel:if(tidata){errnum = IUtility-> GetTagData(DTA_ErrorNumber,NULL,tags); IDOS-> PrintErrorMsg(errnum,(STRPTR)选项[OPT_NAME]);中断; / *刷新时间* /情况DTA_Sync:/ *刷新DataType对象* / IDataTypes-> RefreshDTObjects(dto,win,NULL,NULL);休息;打破; } / *处理完消息,因此回复它* / IExec-> ReplyMsg((struct Message *)imsg); }}

这是从窗口列表中删除DataType对象的唯一方法。不支持使用RemoveGList(),也不支持手动删除对象。

对象属性不一定是静态的。应用程序可以要求对象使用SetDTAttrs()函数设置某些属性。

返回值是特定于DataType对象的,但通常非零值意味着需要在视觉上刷新该对象。

以下片段说明了如何使用SetDTAttrsA()的VarArgs版本设置DataType对象的当前最高值。

这将导致DataType对象更新其垂直和水平顶部值。如果对象已添加到窗口,则显示将相应更新。

请注意,在DataType对象上调用SetGadgetAttrs()或SetAttrs()是不可行的。

DataTypes函数GetDTAttrsA()用于从DataType对象获取属性列表的值。

attrs是TAG_END终止的属性数组。每对数据元素包含该属性的存储变量的地址。

该函数将返回一个数字,该数字指示它能够获取的属性数量。例如,如果请求的四个属性和GetDTAttrs返回四个,那么将获得所有属性。

下面的代码片段说明了如何使用GetDTAttrsA()的VarArgs形式获取DataTypes对象的当前最高值。

龙topv,toph;如果(IDataTypes-> GetDTAttrs(dto,DTA_TopVert,&topv,DTA_TopHoriz,&toph,TAG_END)== 2){IDOS-> Printf(“ Top:Vertical =%ld,horizo​​ntal =%ld \ n”,topv,toph); } else {IDOS-> Printf(“无法获得最高值\ n”); }

此处列出的示例程序应阐明到目前为止讨论的一些概念。假设您有一个通讯程序,并且想添加为铃音(Ctrl-G)播放用户指定的8SVX示例文件的功能。下面的程序显示了如何使用DataTypes库播放声音。

在此程序中,对象属于8SVX类(Sound DataType的子类)。使用该对象执行的方法名为DTM_TRIGGER(在Autodoc文件sound_dtc.doc中进行了描述)。 DTM_TRIGGER方法(类型设置为STM_PLAY)使采样的声音在Amiga的音频硬件上播放。由于DTM_TRIGGER方法除了方法ID外还需要其他信息,因此使用dtTrigger结构。此结构在中定义。

请注意,如果在将来的AmigaOS版本中增强了声音数据类型以支持其他类型的声音文件,则此处提供的代码将自动支持新类型。本示例需要文件名和声音文件的路径。

/ *仅从CLI运行。 * / #include #include / *这包括我们需要的其他文件* / #include / *系统功能的原型* / #include #include #include Printf(“也提供文件名。\ n”);返回RETURN_FAIL; }结构库* IntuitionBase = IExec-> OpenLibrary(“ intuition.library”,50); IIntuition =(结构体IntuitionIFace *)IExec-> GetInterface(IntuitionBase,“ main”,1,NULL);结构库* DataTypesBase = IExec-> OpenLibrary(“ datatypes.library”,50); IDataTypes =(struct DataTypesIFace *)IExec-> GetInterface(DataTypesBase,“ main”,1,NULL); if(IIntuition!= NULL && IDataTypes!= NULL){/ *尝试从命令行中指定的用户* / / *的文件名中创建8svx声音对象。有关可能的错误* / / *返回的列表,请参见Autodocs for NewDTObjectA()。组ID标记* / / *将仅允许接受声音数据类型的呼叫。* /如果(dtobject = IDataTypes-> NewDTObject(argv [1],DTA_GroupID,GID_SOUND,TAG_END)){mydtt。 MethodID = DTM_TRIGGER; / *填写dtTrigger结构* / mydtt。 dtt_GInfo = NULL; mydtt。 dtt_Function = STM_PLAY; mydtt。 dtt_Data = NULL; / *与8svx一起使用的DTM_TRIGGER方法的返回值* / / *在V39中未定义Sound DataType。在将来的Amiga操作系统版本中,这可能会更改* / / *。 * / uint32 dores = IDataTypes-> DoDTMethodA(dtobject,NULL,NULL,&mydtt); //让8svx声音结束播放。另一种方法是使用// // SDTA_SignalTask​​和SDTA_SignalBit找出//完成播放的时间。 IExec->等待(SIGBREAKF_CTRL_C); IDataTypes-> DisposeDTObject(dtobject); } else IDOS-> Printf(“无法创建新对象或者不是声音数据文件\ n”); } else IDOS-> Printf(“无法打开接口\ n”); IExec-> DropInterface((结构接口*)IDataTypes); IExec-> CloseLibrary(DataTypesBase);