.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、执行该程序后显示的对话框如下: