Aros/开发者/文档/库/Intuition/BOOPSIClasses
除了 RootClass 之外,所有编写的类都将继承自此基类(rootclass)。您的类必须实现 rootclass 方法,或将这些方法的处理延迟到下一个类。
rootclass 方法 ID
OM_NEW | 创建新对象。 |
OM_DISPOSE | 删除对象。 |
OM_SET | 更改对象的属性。 |
OM_GET | 检索对象的属性值。 |
gadgetclass 必须理解这些 rootclass 方法,并引入以下方法:
GM_HITTEST | 如果被点击,则返回 GMR_GADGETHIT |
GM_RENDER | 绘制自身,处于适当的状态 |
GM_GOACTIVE | 您现在将接收输入 |
GM_HANDLEINPUT | 处理该输入 |
GM_GOINACTIVE | 无论是否出于选择,您都已完成 |
Boopsi 的 imageclass 是 Intuition 内置的标准类之一。顾名思义,它是一类 Intuition 图片。这些 boopsi 图片可以替代传统的 Image 结构(因为它们包含 Intuition Image 结构),但它们的功能更强大。通过使用 boopsi 方法,应用程序或 Intuition 可以告诉 imageclass 对象自行渲染。由于它是自行渲染(而不是 Intuition 为其渲染),因此 imageclass 对象可以自由地渲染它想要的任何内容(在合理的范围内)。例如,boopsi 图片对象可以根据当前显示分辨率自行渲染,或者根据应用程序请求的任何大小进行缩放。
Imageclass 定义了一些它自身的方法,imageclass 的子类必须实现这些方法或将其传递给它们的超类。
IM_DRAW IM_HITTEST IM_ERASEFRAME IM_MOVE IM_ERASE IM_DRAWFRAME IM_HITFRAME IM_FRAMEBOX
您创建了一个新的 boopsi 类,它是 Intuition 的 IMAGECLASS 的子类(例如这个位图类),在 IM_DRAW 方法中,您可以以您想要的方式进行绘画。如果您从数据类型对象中获得了一些位图,请使用 BltBitMapRastPort() 与其一起使用,如果您拥有某些块状像素数组,请使用 WritePixelArray()。
请参阅 compiler/coolimages/imageclass.c
从 IMAGECLASS 派生的类创建的对象可以传递给 DrawImage()。
您可以使用 IMAGECLASS 的对象(或 IMAGECLASS 的子类)作为小部件的 GadgetRender(等等)(无论该小部件是旧式小部件还是 boopsi 小部件)。您也可以将该对象强制转换为 (struct Image *),因为实例数据在开头包含一个 struct Image。
我所说的这种新的图片类与您已经在 AOS 上所做的并不不同(使用 Reaction/Classact bitmap.image 类,它也是 IMAGECLASS 的子类)。AROS 没有那个类,因此要么需要编写它(它是一个类似于 colorwheel.gadget 的外部类),要么在您的程序中直接编写一个简化的类重新实现 == 我指的是新的图片类,它不需要做太多,只需要在 IM_DRAW 中进行一些使用 BltBitMapRastPort() 或类似方法的 blitting(如果您已经在其他地方加载图片/数据类型对象,否则您也可以在新图片类的 OM_NEW 中进行加载)。
以下方法适用于 4 色 IFF 图片。我假设我可以对 V42 数据类型位图的平面进行 CopyMem 操作。
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/datatypes.h>
#include <datatypes/pictureclass.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static struct Window *window;
static struct RastPort *win_rp;
static struct Image *img;
static struct Image *load_image(CONST_STRPTR);
static void clean_exit(CONST_STRPTR s);
static void handle_events(void);
int main(void)
{
window = OpenWindowTags(NULL,
WA_Left, 50,
WA_Top, 70,
WA_Width, 400,
WA_Height, 350,
WA_Title, "Load Image",
WA_Activate, TRUE,
WA_SmartRefresh, TRUE,
WA_NoCareRefresh, TRUE,
WA_GimmeZeroZero, TRUE,
WA_CloseGadget, TRUE,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW,
TAG_END);
if (! window) clean_exit("Can't open windown");
win_rp = window->RPort;
img = load_image("test.iff");
DrawImage(win_rp, img, 50, 50);
handle_events();
clean_exit(NULL);
return 0;
}
static struct Image *load_image(CONST_STRPTR name)
{
struct Image *newimage = NULL;
UBYTE *pixeldata = NULL;
Object *dto = NULL;
struct BitMapHeader *bmh = NULL;
struct BitMap *bm = NULL;
WORD width, height, depth;
LONG size;
if ((dto = NewDTObject((APTR)name,
PDTA_Remap, FALSE,
PDTA_DestMode, PMODE_V42,
TAG_DONE)) == NULL)
{
puts("Can't open datatype");
goto cleanup;
}
if (GetDTAttrs(dto, PDTA_BitMapHeader, &bmh, PDTA_BitMap, &bm, TAG_DONE) != 2)
{
puts("Can't get bitmapheader and bitmap");
goto cleanup;
}
width = bmh->bmh_Width;
height = bmh->bmh_Height;
depth = bmh->bmh_Depth;
size = ((width + 16) / 16) * height * depth * 2; // Bytes
printf("width %d height %d depth %d size %dn", width, height, depth, size);
if ((pixeldata = AllocVec(size, MEMF_ANY)) == NULL)
{
puts("Can't allocate memory for pixeldata");
goto cleanup;
}
if ((newimage = AllocVec(sizeof (struct Image), MEMF_ANY | MEMF_CLEAR)) == NULL)
{
puts("Can't allocate memory for struct Image");
goto cleanup;
}
WORD blocksize = ((width + 16) / 16) * height * 2;
UBYTE *ptr = pixeldata;
UBYTE d;
for (d = 0; d < depth; d++)
{
CopyMem(bm->Planes[d], ptr, blocksize);
ptr += blocksize;
}
newimage->ImageData = pixeldata;
newimage->Width = width;
newimage->Height = height;
newimage->PlanePick = (1 << depth) - 1;
newimage->Depth = depth;
if (dto) DisposeDTObject(dto);
return newimage;
cleanup:
FreeVec(pixeldata);
FreeVec(newimage);
if (dto) DisposeDTObject(dto);
return NULL;
}
static void handle_events(void)
{
struct IntuiMessage *imsg;
struct MsgPort *port = window->UserPort;
BOOL terminated = FALSE;
while (!terminated)
{
Wait(1L << port->mp_SigBit);
if ((imsg = (struct IntuiMessage *)GetMsg(port)) != NULL)
{
switch (imsg->Class)
{
case IDCMP_CLOSEWINDOW:
terminated = TRUE;
break;
}
ReplyMsg((struct Message *)imsg);
}
}
}
static void clean_exit(CONST_STRPTR s)
{
if (s) PutStr(s);
FreeVec(img->ImageData);
FreeVec(img);
if (window) CloseWindow(window);
exit(0);
}
必须理解 rootclass 方法 ID,但也理解以下方法:
ICM_SETLOOP ICM_CLEARLOOP ICM_CHECKLOOP - to manage a loop inhibition for broadcasted messages. They increment, decrement, and return the value of that counter
ICA_Target ICA_Map