Thursday, February 28, 2013

Using Application.ShowModalDialog()? Be Careful

When it comes to display a custom dialog box we developed in AutoCAD (assuming we use System.Windows.Forms.Form), we all know that Autodesk wants you use Application.ShowModalDialog/ShowModelessDialog() instead of Form.ShowDialog()/Show().

The documentation from ObjectARX SDK only cited that using Form.Show()/ShowDialog() can cause AutoCAD behaving unexpectedly. It also points out one of the BENEFIT of using Application.ShowModalDialog()/ShowModelessDialog() is that AutoCAD remembers the dialog box' location and size when it is closed.

Well, it may be a benefit in an AutoCAD work environment where nothing changes once a user is assigned to use that computer. For me, this benefit has been minor or big disasters quite a few times!

Here are 2 typical cases that made me not very happy.

Case One.

In one of my project, when I I doing my final test run before a demo, since I use dual-monitor computer (who still doesn't?) I left AutoCAD showing in one screen and the dialog box in the other when the dialog box is closed.

Next day for the demo, I connected my computer to the projector. Naturally, it only has one screen played on the wall. When demo started, I was very confidently start my application. Why shouldn't I? I just test it many times. The application is supposed to pop up a dialog box. To my surprise, as soon as I entered my command, nothing happens and AutoCAD does not responding. OK, somehow the damn Widows freezes AutoCAD for some reason. It happens, right? So, I went to Task Manager to kill the AutoCAD process and tried it again. The same thing. One can imagine how embarrassing it was with coworkers in whole office sitting in meeting room for your demo and you cannot get the damn thing run. It was a bit fortunate I had something else to show that day, so that I did not have to quit the demo with nothing being talked.

Of course, it was the unexpected surprise hit my mind too hard that I did not realize the AutoCAD appearing to be frozen was because the dialog box was shown off the screen (e.g. in a non-existent second screen, thanks to AutoCAD so diligently remembered the dialog box' previous location and restored it there, even there was no extra screen). Since it is modal dialog box, thus AutoCAD shown on the main screen (the only screen at the time) appeared frozen.

Many of the uses of my applications uses a laptop. They may run AutoCAD (and may applications) with the laptop only, or with the laptop docked at their desk with multiple monitors. When using multiple monitor, user tend to move dialog box to one screen and AutoCAD main window in another. So, user often runs into this situation and think my application somehow crashes AutoCAD and seek help from me.

The immediate cure for this issue, if you do know it is because of a dialog box showing off screen, is to press "ALT+SPACE" and then press "M" key, following by pressing arrow key to move the invisible dialog box, or by holding mouse left key down and moving it around, until the dialog box can be seen on the screen.

Case Two.

I was in a project development. There was a dialog box. After a debugging run, AutoCAD dutifully remembered the dialog box' location and its size. However, at some point in the development, I decided to change the form's size to add more controls. So, I rearranged the form's layout (making it larger than previously. Now I run the application again, AutoCAD insisted to show the form in its previous size, thus part of the form was cut of. Since the form's border was set "FixedSingle" and/or "FixedDialog", not "Sizeable", I could not resize the form and close with it being in correct size. therefore AutoCAD would keep showing the form partially. See picture below.

AutoCAD shows this:


While the form should be:


I figured it is not uncommon as CAD application developer that you design a form, do some debugging run and then you change the size of the same form. In this case, I really do not need AutoCAD remember the form's size. Well, I could rename the form, I can fool AutoCAD to think it is a new form, so that AutoCAD would not set its size to previously remembered size. But it is a bit silly each time you change a form's size, you need to rename it.

So, I tried change the form's border type to "Sizeable", so in next debugging run, I can resize the form to proper size and hope AutoCAD remembers it. Then I change the form's border type back to "FixedSingle/Fixed3d/FixedDialog" again and run the project, in hoping now AutoCAD should use the correct form size. To my surprise, AutoCAD still uses the size when the form was in the fixed border type.

OK, short of renaming my form (I really do not want to), the only way I can get my form shown correctly, is to set the form's size in Form.Shown event handler with code. Note, the code that set form's size only works when Form's Shown event fires and thereafter. If you place the code in the form's constructor or in the Form.Load event handler, AutoCAD still force its remembered size/location. Obviously, Autodesk does the form location/size restoration after the form is loaded but right before it is shown.

So, what I have learned from this Application.ShowModalDialog() issue?

1. It is a bug for letting a dialog box be restored in a off-screen location. When AutoCAD tries to restore the form's previous location, it should check if the remembered location is off all available screens, if yes, it should show the dialog box based on the form's "StartPosition" property in the primary screen.

2. If we want to override AutoCAD and set the form's location/size with our code, the code should be in Form.Shown event handler. But I do wish the Application.ShowModalDialog/ShowModelessDialog() had a overload method where we can set flag to ask AutoCAD not to restore previous location/size.

3. I tried to use code in the Form.Shown event handler to get my form shown correctly and then close the form in the hope that AutoCAD now remembers the correct form size. At this point I removed the code in Form.Shown event handler, hoping now AutoCAD would restore the form in correct size. I ran the application again. AutoCAD still shows the form in its originally remembered size again, Apparently, for each form, if the form's border is fixed type, AutoCAD only remember its size the first time when the form shows (but it does remember form location each time the form is closed). So I have to keep the size setting code in Form.Shown events, unless I rename the form, or clean up my Windows account profile, both I reluctant to do.

6 comments:

  1. I would hope there is a safer way, but you can find the stored setting for you forms in the registry at this location -
    HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R19.0\ACAD-B000:409\Profiles\<>\Dialogs\LayerManager where R19.0 is the Autocad Version (in his case 2013), ACAD-B000:409 is the Autocad flavour (in this case civil 3d), <> is your profile name you were running under and LayerManager is the dialogue name the settings are stored for.

    If you delete the key for that dialogue, autocad will open the dialogue next time in the default position.

    ReplyDelete
  2. I have been through this issue a few years a go, I was the only one with dual screen setup. It may sound silly, but when dealing with floating modal forms I have learned to code size and position through code and to set the "StartPosition" property to CenterScreen.

    ReplyDelete
  3. Application.ShowModalDialog() does have an override for not restoring/saving the previous state:

    ShowModalDialog( IntPtr owner, Form formToShow, [MarshalAs(UnmanagedType.U1)] bool persistSizeAndPosition );

    If persistSizeAndPosition == false, it simply places the form in the upper left hand corner of the screen, center of screen, or center of parent as per the form setting.

    Also, in the case where the form is being cut off, set a minimum size for your form and ShowModalDialog will respect it, holding the upper left point and expanding the dialog to fit the minimum size.

    As for creating the dialog off screen, that is just standard AutoCAD behaviour and often happens with the built in dialogs. I don't think anyone likes it, but you had better get used to it if you switch between screen configurations.

    ReplyDelete
  4. How can I learn new CAD programs if I don't have the money to take a course at a college?

    Solidworks Price

    ReplyDelete
  5. Hi,

    AutoCAD not will show the form cuted if you change the property.

    AutoScaleMode=None

    Regards

    ReplyDelete