Archive | MDL RSS for this section

Upgrade or Re-write and Tech Manager Overload

by Mark Stefanchuk,

I have been working with an old MDL application that needs to be upgraded from MicroStation version 8.5 to the latest release. Ideally, I might want to re-write this app using the latest development tools so I can take advantage of the latest IDE, more easily integrate with supporting systems, and better support future maintenance efforts. As a technology manager however, there are other things to consider like training, testing, and deployment. If I keep the application within the MDL framework I eliminate end user re-training. This means the users are up and running as soon as you deliver the updated application. Testing and deployment issues on the other hand will still exist. But, if I just update the MDL I can keep the deployment the same and focus the testing on only the features that have been changed or fixed. I might also add some regression testing to check for the unexpected.  The result though, is less time spent and users are up and running sooner than later.

So, when would I re-write? If I have a choice and the technology doesn’t force the re-write then it would happen after I have satisfied the basic end user workflow with an upgrade. This assumes of course that I have the bandwidth on my team to support the re-write effort. Which leads me to another issue – tech manager overload.

Many of us work on our own, we don’t have a team. We develop, train, support, and configure. And, often we’re expected to design too! There’s no time during the work week to do the things that will make you a better technology manager, or make your CAD system perform better. To that I say, then you need help. And typically I get back, yes, but I’m not going to get it.

Really? Some of you will never be convinced, but for those who might I have a recommendation. Document all of the things you do on a day-to-day basis, and even those things you do weekly, monthly, or only a few times per year. Put time estimates to each of these tasks and account for where your time is spent during the week. You will see immediately if you have too much work to do. You will likely identify things you do that should be done by someone else, and things that simply aren’t important. Share this with your boss.

I can’t tell you how many times I’ve had the boss of a tech manager say they had no idea that he/she was doing that much work. But, I work hard, everyone says so. Sure, but they think they work hard too, and frankly they don’t really care until they don’t get what they want. That sounds harsh, but it’s human nature. The reality is that they don’t know how much you have to do for them. This includes your boss.

There are a number of reasons workload increases. One of the main causes is that we agree to take on tasks and responsibilities that add to that daily workload without any oversight or governance. We never ask if the new feature, process, or technology being requested adding value to our business or is it just a nice to have? And, we don’t look at how the new technology will impact our workload. We never, or rarely say no. We just do it, because for some reason we just assume we’re suppose to, it makes us feel good to help, be the hero, or worse, we assume someone else is keeping track of how much work we’re doing. I can assure you, if you aren’t telling anyone, no one knows.

It’s up to you to keep track and apply some system oversight. You’re the technology manager – ask why implementing the users request is important and have a good understanding of how it will impact your workload. Don’t just do it. Have a plan to support and maintain the request even if it seems small. And, share with your boss. Some bosses are just bad bosses – get a new job. But, most are reasonable and will get you the resources you need to effectively support your end users. They can only do that if they have visibility into your workload. Show them how much you are expected to do and you will get help.

About Mark Stefanchuk:
 Mark is a VP and senior consultant with CAD Management Resources, Inc. He divides his time between developing innovative custom software solutions and helping clients navigate complex design automation environments. If you would like to find out how he can assist you with your design technology he can be reached by contacting us at

Managing Usability

by Mark Stefanchuk,

[Update: Be sure to check out Kim’s comment – a great alternative using the F1 key and choose none. Thanks Kim!]

I’ve been debating whether or not to share this with my MicroStation peeps. I hesitate because I don’t like to admit that sometimes I don’t adjust to change as quickly as I should, but also because this example has some conflict with features in MicroStation V8i that we wouldn’t introduce normally, especially if we don’t have to. What am I talking about?

Earlier this year I was working with a client helping them upgrade from MicroStation 2004 to V8i SS2. Not as big of a jump from V7 to V8, but big enough. Things were missing and commands didn’t work the same way. Years ago we could rely on commands that were in the previous version to work the same way in the new version. Today, it’s not that way. And seriously, there are good reasons for change, like productivity gains. I’m all for that. In this case however, it was clear that the user base missed some of the key operations that made MicroStation, well MicroStation and not AutoCAD.

For example, in older versions of MicroStation when you were done with a selection created using power selector you would use the right mouse button to deselect (reset). In V8i you just use the right mouse button (a datapoint in the view). That’s seems pretty easy. But if you have been drafting for years using the same workflow not being able to use something so simple as the reset button to deselect a selection set can be really frustrating.

Now, I was the consultant and I really wanted my client to be happy so I fixed it. I built an MDL application that would watch for reset. When the user clicks reset any active selection set would be removed. The command is very primitive, but I thought I would share in case you might have a similar issue. There’s not much to it – comments below.

#include    <mdl.h> 
#include    <tcb.h> 
#include    <dlogitem.h> 
#include    <dlogids.h> 
#include    <rscdefs.h> 
#include    <mdlerrs.h> 
#include    <userfnc.h> 
#include    <global.h> 
#include    <mselems.h> 
#include    <accudraw.h> 
#include    <cexpr.h> 
#include    <math.h> 
#include    <string.h>

#include    "ps_resetcmd.h" 
#include    "ps_reset.h" 
#include    "fdf.fdf"

int goFlag; // a flag to watch for active commands that might conflict
// the event watcher
Private int monitorQueue ( Inputq_element *queueElementP ) 
    char sCmd[256];         
    sprintf(sCmd, "%S", mdlState_getCurrentCommandName());     

    // Element Selection Active     
    if (strcmp(sCmd, "Element Selection") == 0)
        goFlag = 0;  

    // a quick a dirty way to watch for active command - be careful with upgrades because this might not be
    // supported in the future. - not very elegant but it works - I'm a little bull headed that way.
    if ((strcmp(sCmd, "Dimension Element") == 0) || (strcmp(sCmd, "Dimension Linear Size") == 0) 
        ||   (strcmp(sCmd, "Dimension Angle Size") == 0) || (strcmp(sCmd, "Dimension Ordinates") == 0) 
        ||   (strcmp(sCmd, "Change Dimension") == 0) ||   (strcmp(sCmd, "Drop Dimension Element") == 0)
        ||   (strcmp(sCmd, "Dimension Size Perpendicular to Points") == 0) ||   (strcmp(sCmd, "Dimension Diameter") == 0) 
        ||   (strcmp(sCmd, "Label Point Coordinate") == 0) || (strcmp(sCmd, "Dimension Symmetric") == 0) 
        ||   (strcmp(sCmd, "Dimension Half") == 0) || (strcmp(sCmd, "Dimension Chamfer Angle") == 0) 
        ||   (strcmp(sCmd, "Dimension Diameter Perpendicular") == 0) || (strcmp(sCmd, "Dimension Radius (Extended Leader)") == 0) 
        ||   (strcmp(sCmd, "Place Center Mark") == 0) || (strcmp(sCmd, "Dimension Radius") == 0) 
        ||   (strcmp(sCmd, "Dimension Arc Distance") == 0))  
        goFlag = 1; // the active command is a dim command so dont deselect on reset
       goFlag = 0; // ok to reset - conflict mitigated  

    // user clicked reset and conflict minimized so go for it
    if (queueElementP->hdr.cmdtype == RESET)  
        if (goFlag == 0)    
            mdlInput_sendKeyin ("powerselector deselect", 0, 0, NULL);
    return INPUT_ACCEPT;

// command entry
int main () 
    RscFileHandle   rfHandle;  
    goFlag = 0;

    mdlResource_openFile (&rfHandle, NULL, FALSE);

    if (mdlParse_loadCommandTable (NULL) == NULL)  
        mdlOutput_rscPrintf (MSG_ERROR, NULL, 0, 4);

    mdlInput_setMonitorFunction (MONITOR_ALL, monitorQueue);
    return  SUCCESS; 

The conflict was created by sending a command, i.e. powerselector deselect, when commands that you didn’t want to terminate using reset were active – like dimension commands. The easiest way to work around this was to set a flag. If one of the dimension commands is active then don’t deselect on reset. The code and compiled is on Put the ma in your mdlapps folder so it will load when MicroStation is loaded. You can also use the keyin mdl load ps_reset to load this app.

About Mark Stefanchuk: Mark is a VP and senior consultant with CAD Management Resources, Inc. He divides his time between developing innovative custom software solutions and helping clients navigate complex design automation environments. If you would like to find out how he can assist you with your design technology he can be reached by contacting us at

MicroStation Cell Copy VBA

by Mark Stefanchuk,

I’ve had several requests to update the cell copy MDL example I wrote for MicroStation SE. Thanks to Amos from Jacobs Engineering for the push earlier this year.

I had updated the MDL shortly after the first V8 release and it continued to work through V8 2004. More recent versions of MicroStation however, have introduced several changes that break this old command. Instead of just updating the MDL code, I decided to take a different approach.

The new version is written in VBA, which really simplifies the code and approach. Using the VBA IDE (integrated development environment), creating user forms (dialog boxes) is faster and easier than in MDL. And if you don’t know how to do something in VBA a quick web search will tell you how. So, for CAD managers who are pressed for time this is definitely the way to go.

The new program operates essentially like the old one. Load the source library into the left listbox. Load the destination library into the right listbox. Highlight the cells from the source library you want to add to the destination library and click the arrow button that points to the destination listbox. Click the Add button located at the bottom of the destination library listbox.

You can find a download link to the new version on our cadgurus page. The code is not locked – something I’m likely going to get grief for – “why are you giving away the store…” – “… because I like these cad manager types…”. And, as always these are examples that come with limited validation and error checking, so use at your own risk. Create backups of your libraries before modifying them with CellCopy, and be careful with the delete option. It will remove all cells from the library and you won’t be able to get them back if you haven’t first backed up the original.*

This is a MicroStation VBA. So you can load it using the “VBA Load (path + vba name)” key-in, for example “VBA LOAD C:\temp\cellcopy.mvba”. I usually use the VBA Project Manager so I can browse for the program and then set the Auto-Load option. (from the pull down menu, Utilities > Macro > Project Manager).

There are a couple of key coding points to make.

1) To copy the cells I use the information provided in the dialog box – the source and destination locations. The cell names are gathered by indexing the  destination listbox and grabbing the highlighted cell names. If the cell name is already in the library then the program will skip it.

2) Delete Cells (advanced) – I didn’t find a method in VBA to delete the cells, but I did find one in the MDL reference. This MDL function requires that you pass a pointer for the cell name string. How do you do that?!

This MicroStation V8i Bentley Community page refers to the undocumented VBA function VarPtr. It says that you should use this to pass a pointer of your char* or void*. The MDL function I used was mdlCell_deleteInLibrary and the MDL Funtion Reference says to pass a type of MSWChar const*. So, when I used VarPtr, the function didn’t work – it returned a cell not found error. Ok.

The same VarPtr discussion on the Bentley Community says to look at for more information. Here you will find several other undocumented pointer functions including StrPtr. This one works. Yay. The indexing logic for delete is the same as it is for copy and deleting cells requires these four lines.

One more thing about the example – the Windows Open File Dialog (browse for cell library) helper code (unmodified) can be found on la-solutions web site. Bookmark this site, especially if you are developing programs for MicroStation – there are plenty of great programming examples here.

* If you want to share cell copy with others on your team, but you don’t want them to be able to delete cells then just hide the delete button. You can turn off it’s visible property and/or you can just set the enabled property to false.

About Mark Stefanchuk: Mark is a senior consultant with CAD Management Resources, Inc. He divides his time between developing innovative custom software solutions and helping clients navigate complex design automation environments. If you would like to find out how he can assist you with your design technology he can be reached by contacting us at