Hi all,
First, the basics: Microstation v7, native MDL application, creating model for use with PDS v7.2
I have an application that takes an external data file and creates a 3D model in a new file. The dialog consists of two buttons to open standard dialogs, one for "select file" and the other for "create a new file from a seed". Currently, both functions use the configuration variables for the start directory, seed file folder, and standard seed file.
Most of the time, when this is run, it will be run several times from the same place by the same user. Other users will run it at the same time, but from different folder structures. The way it's currently written, users will have to traverse to UNC locations every time the application is opened.
What I want to do, and have been unable to figure out just poking around in the function reference guide, is the best way to keep track of the last selected folder, seed file, and seed file path so that it can default there in the first place. This should be separate from the standard path information when using file/open or file/create.
I've looked through the MDL examples delivered with v7 but haven't found a good example of this, but that could be because I don't know what I'm looking for.
I'd like to use the user preferences file, but without sample code I trust, I don't want to run the risk of corrupting UPFs. That might earn me a beating one evening while hiking out to my truck.
If anyone (Messrs. Summers or Chouinard?) has an example of using the UPF for that, I'd appreciate it. If not, is an external resource file the right way to go? I started with using User-level configuration variables to hold that information, but I KNOW there's a way to do it that uses UPF and I'd really prefer that way.
Thanks in advance for any help anyone can provide.
Gary Shay
Thought I should include what I've tried so far:
mdlDialog_userPrefFileOpen(&upfHandle, RSC_READWRITE);
if (mdlDialog_defFileOpen (fileName, NULL, 0, NULL, "*.dat", NULL, "Open Data File", PGM_SETTINGS_ID, upfHandle)){ mdlOutput_error("Execution halted: Make changes and click OK."); return;}else{ memset(pdIS.m_FilePath, '\0', sizeof(pdIS.m_FilePath)); strcpy(pdIS.m_FilePath, fileName);
}
I know I'm not saving the UPF. The description of the mdlDialog_defFileOpen function says that it's saved into the UPF. Not wanting to double-save, I left that part out. Perhaps foolishly, but I didn't want a chorus of "Save The File, dummy!". Although I may deserve one.
Do I need to explicitly save the user pref file? Is this why it's not working?
G
Answer Verified By: Gary Shay
Unknown said:mdlDialog_defFileOpen (fileName, NULL, 0, NULL, "*.dat", NULL, "Open Data File", PGM_SETTINGS_ID, upfHandle) The description of the mdlDialog_defFileOpen function says that it's saved into the UPF
If the last argument is NULL, it's saved to the UPF maintained by MicroStation. If you specify your own upfHandle then you're in control of that UPF. In the first instance, leave it NULL and let MicroStation do the heavy lifting. If you want to use your own UPF, then you must create that binary resource file before attempting to save data. You are responsible for managing that resource file and the memory allocated when you open it.
The help documentation fails to mention them, but you can use one of the MicroStation Default File Info Resource Ids #defined in header file deffiles.h.
If you search the delivered MDL examples, you'll find several that use the mdlDialog_defXxx functions. That's the case for MicroStation V8 at least, but I don't know what the MicroStation/J SDK delivers.
Regards, Jon Summers LA Solutions
I'm marking this as the answer because it's essentially what I had to do, although I'm still using the local userpref file, just adding a resource to it.
I created a new 'resource' structure that only uses the bits I want, specifically:
typedef struct xyzzyRsc { char fileName[MAXFILELENGTH]; char fileFilter[MAXFILELENGTH]; char defDir[MAXDIRLENGTH]; char seedFName[MAXFILELENGTH]; char seedDir[MAXDIRLENGTH]; } xyzzyRsc;
When the hook function starts, it first tries to load that resource. If it doesn't exist, the code defaults to some known values. If it does exist, it uses those values as members of the fileOpenParams structure, then opens the dialog. After returning from the dialog, the new values are saved to the user preferences file.
Here's the code. I know it needs some cleanup, but it works.
Private void xyzzy_GetWorkFile (DialogItemMessage *dimP){ char fName[MAXFILELENGTH]; char seedF[MAXFILELENGTH]; int dbReturn; DialogItem *diP; int itemIndex; int i; char defSeed[MAXFILELENGTH]; char seedDir[MAXFILELENGTH]; char *expDefSeed, *expSeedDir; RscFileHandle upfHandle; xyzzyRsc xyzzy; xyzzyRsc *xyzzyP; char pPath[MAXDIRLENGTH], pFile[MAXFILELENGTH]; FileOpenParams fileOpenParams; FileOpenExtraInfo fOpenExt;
dimP->msgUnderstood = TRUE; switch (dimP->messageType) { case DITEM_MESSAGE_BUTTON: { mdlDialog_userPrefFileOpen(&upfHandle, RSC_READWRITE); xyzzyP = mdlResource_load(upfHandle, xyzzy_SEED_RTYPE, xyzzy_SETTINGS_ID);
if (xyzzyP==NULL) { mdlSystem_getCfgVar(defSeed, "MS_DESIGNSEED", MAXFILELENGTH); mdlSystem_getCfgVar(seedDir, "MS_SEEDFILES", MAXFILELENGTH); expDefSeed=mdlSystem_expandCfgVar(defSeed); expSeedDir=mdlSystem_expandCfgVar(seedDir); split_path_file(pPath, pFile, expDefSeed); strcpy(xyzzy.seedFName, pFile); strcpy(xyzzy.seedDir, expSeedDir); strcpy(xyzzy.fileName, "ventClr.dgn"); strcpy(xyzzy.fileFilter, "*.dgn"); strcpy(xyzzy.defDir, "\\\\cad0\\proj\\");
mdlResource_add (upfHandle, xyzzy_SEED_RTYPE, xyzzy_SETTINGS_ID, &xyzzy, sizeof(xyzzyRsc), NULL);
xyzzyP = mdlResource_load(upfHandle, xyzzy_SEED_RTYPE, xyzzy_SETTINGS_ID);
// free allocated memory from expanding Config variables if (expDefSeed) free(expDefSeed); if (expSeedDir) free(expSeedDir); }
// Set up file create memset(&fileOpenParams, 0, sizeof(FileOpenParams)); memset(&fOpenExt, 0, sizeof(fOpenExt)); fileOpenParams.dialogRscH = NULL; fileOpenParams.dialogId = DIALOGID_StdFileSeedCreate; fileOpenParams.openCreate = FILELISTATTR_CREATEFROMSEED; fileOpenParams.defaultFilterP = xyzzyP->fileFilter; fileOpenParams.defaultDirP = xyzzyP->defDir; fileOpenParams.suggestedFileNameP = xyzzyP->fileName; fileOpenParams.titleP = "Create Plume Clearance Model File:"; fileOpenParams.defSeedFileNameP = xyzzyP->seedFName; fileOpenParams.defSeedDirP = xyzzyP->seedDir; fileOpenParams.defSeedFilterP = "*.dgn";
dbReturn = mdlDialog_fileOpenExt(fName, &fOpenExt, &fileOpenParams, FILEOPENEXTATTR_CENTERONSCREEN);
if (dbReturn==TRUE) // Cancel button pressed { mdlOutput_error("Execution halted: Make changes and click OK."); /* Clean up */ mdlResource_closeFile (upfHandle); return; } else { // Update defaults split_path_file(pPath, pFile, fOpenExt.seedFileName); strcpy(xyzzyP->seedFName, pFile); strcpy(xyzzyP->seedDir, pPath); split_path_file(pPath, pFile, fName); strcpy(xyzzyP->fileName, pFile); strcpy(xyzzyP->defDir, pPath); mdlResource_write(xyzzyP); mdlResource_free(xyzzyP);
strcpy(pdIS.m_WFilePath, fName); strcpy(pdIS.m_SFilePath, seedF);
mdlOutput_error(pdIS.m_WFilePath); mdlDialog_itemsSynch(dimP->db); }
/* Clean up */ mdlResource_closeFile (upfHandle);
// Set focus back to the model file name. mdlDialog_focusItemIndexSet(dimP->db, 2, FALSE);
break; } default: { dimP->msgUnderstood = FALSE; break; } }}
Thanks, Phil & Jon!
Gary
PS: Bonus points if you recognize "xyzzy".
Unknown said:typedef struct xyzzyRsc
Aha! A fan of Colossal Cave.