.r(resource的缩写,即资源的意思)对话框是nativeCode(本机代码)C++,即MDL,原生的写界面的方法。其有方便之处也有不方便之处。对于在一个.r对话框中如何显示一个图片,则需要如下较为复杂的步骤。
1、头文件.h中定义相关的资源ID。比如:
#define DIALOGID_DisplayImage 5 #define GENERICID_DisplayImage 2 #define HOOKITEMID_DisplayImage 5
【说明】:保证每一类资源的id编号不同即可。比如,以上定义中对话框ID和对话框条目(item,等同于Windows中的控件的概念)钩子ID不属于一类,所以,它们两个都定义为5没有问题。
2、资源文件.r中定义如下对话框和一个通用条目。
DialogBoxRsc DIALOGID_DisplayImage =
{
DIALOGATTR_DEFAULT, 31.0*XC, 15.0*YC, NOHELP, LHELPCMD, NOHOOK, NOPARENTID,
"Display Image Demo",
{
{ { 1.5*XC, 0.5*YC, 28.0*XC, 14*YC }, Generic, GENERICID_DisplayImage, ON, 0, "", "" },
}}
extendedIntAttributes
{{
{EXTINTATTR_DLOGATTRS, DIALOGATTRX_NOMINIMIZEBOX}
}
};
DItem_GenericRsc GENERICID_DisplayImage =
{
NOHELP, MHELP, HOOKITEMID_DisplayImage, NOARG
};
【说明】:①该对话框中仅含有一个通用条目(generic item),该条目没有任何默认动作,其动作完全依靠条目钩函数来控制;②为了取消对话框标题栏右侧的最下化按钮,使用了对话框的扩展属性DIALOGATTRX_NOMINIMIZEBOX。请密切注意如何给对话框添加扩展属性,这里的写法比较怪异;③给通用条目增加了钩函数ID的定义,通过该HOOKITEMID_DisplayImage去关联实际的钩函数displayImage_genericHook。
3、在源代码文件.cpp中增加如下代码:
void displayImage(WCharCP unparsed)
{
MSDialog::Open(NULL, DIALOGID_DisplayImage);
}
void displayImage_genericHook(DialogItemMessageP dimP)
{
DialogItemP diP = dimP->dialogItemP;
RawItemHdrP riP = diP->rawItemP;
dimP->msgUnderstood = TRUE;
switch (dimP->messageType)
{
case DITEM_MESSAGE_INIT:
{
BeFileName fullFileSpec;
WString image(L"D:\\Foo-src\\MDL.CE\\File\\images\\path2.bmp");
dimP->u.init.initFailed = TRUE;
if (SUCCESS != mdlFile_find(&fullFileSpec, image.GetWCharCP(), NULL, NULL))
{
mdlDialog_dmsgsPrint(L"Problem with image");
dimP->u.init.initFailed = FALSE;
break;
}
byte* rgbBufferP = NULL;
Point2d itemSize;
itemSize.x = diP->rect.corner.x - diP->rect.origin.x + 1;
itemSize.y = diP->rect.corner.y - diP->rect.origin.y + 1;
if (SUCCESS == mdlImage_readFileToRGB(&rgbBufferP, NULL, fullFileSpec, ImageFileFormat::IMAGEFILE_BMP, &itemSize))
{
// Store a pointer to the image in the generic item's userDataP member variable
riP->userDataP = rgbBufferP;
dimP->u.init.initFailed = FALSE;
}
break;
}
case DITEM_MESSAGE_DRAW:
{
Int32 i, rowLength;
byte *redP, *greenP, *blueP;
// Get image pointer from generic item's userDataP member variable
if (redP = (byte*)riP->userDataP)
{
rowLength = diP->rect.corner.x - diP->rect.origin.x + 1;
greenP = redP + rowLength;
blueP = greenP + rowLength;
for (i = diP->rect.origin.y; i <= diP->rect.corner.y; i++)
{
mdlDither_drawRow(dimP->db, diP->rect.origin.x, diP->rect.corner.x, i, redP, greenP, blueP);
redP += 3 * rowLength;
greenP += 3 * rowLength;
blueP += 3 * rowLength;
}
}
mdlDialog_rectDrawEdge (dimP->db, &diP->rect, TRUE);
break;
}
case DITEM_MESSAGE_DESTROY:
{
byte* tempBufferP = (byte*)riP->userDataP;
dlmSystem_mdlFree(tempBufferP);
break;
}
default:
dimP->msgUnderstood = FALSE;
break;
}
}
/*--------------------------------------------------------
| MdlMain
+-------------------------------------------------------*/
DialogHookInfo uHooks[] =
{
{ HOOKITEMID_DisplayImage, (PFDialogHook)displayImage_genericHook},
};
extern "C" DLLEXPORT void MdlMain(int, WCharCP[])
{
mdlResource_openFile (&g_rscFileH, NULL, RSC_READONLY);
mdlSystem_registerCommandNumbers (cmdNumbers);
mdlParse_loadCommandTable(NULL);
mdlDialog_hookPublish(sizeof(uHooks) / sizeof(DialogHookInfo), uHooks);
......
}
【说明】:①在MdlMain中通过调用mdlDialog_hookPublish发布了一个全局钩函数名和钩函数ID的对照表uHooks,因而将资源文件中的HOOKITEMID_DisplayImage和源代码中的函数displayImage_genericHook对应了起来;②函数入口是displayImage,在该函数中调用MSDialog::Open打开了我们的对话框DIALOGID_DisplayImage。你需要用一个命令和该函数关联(以上代码没有详细描述这一部分)。或者简单起见,你可以直接在MdlMain中去调用它;③displayImage_genericHook中在获得条目初始化消息DITEM_MESSAGE_INIT时调用函数mdlImage_readFileToRGB读取了一个指定的bmp文件到内存中,指针为条目下的userDataP;④displayImage_genericHook中在获得条目绘制消息DITEM_MESSAGE_DRAW时调用函数mdlDither_drawRow将内存中的像素点绘制到了通用条目上;⑤displayImage_genericHook中在获得条目销毁消息DITEM_MESSAGE_DESTROY时调用dlmSystem_mdlFree释放了内存。
4、执行该程序后显示的对话框如下: