Support Statement: Sample Migration of CommonDialog to Winforms
Overview
The CommonDialog control is a one-to-many migration: In COM, the CommonDialog control is a "jack of all trades" has a complex interface supporting several use cases. In .NET, there are several different Dialog components (PrintDialog, OpenDialog, SaveDialog, ColorDialog, FontDialog) and you use the one you need depending on the desire use case.
In addition, the COM CommonDialog was an "invisible control". It could be placed on a VB6 form and declared in logic. In .NET, the Common Dialog is a set of Components.
Sample Application Analysis
The following is an example of analysis on the nature of CommonDialog usage in a typical application.
The following VBPs use MSComDlg:
- ic_FuncLib
- devOPOSposprn
- ic_Company
- ic_RptsFinancial
- ic_RptsGeneral
- appmain
The following API elements are used (from Reference report):
MemType MemClas MemName refs ------------------------------ ------------------------------ ------------------------------ ----------- Lib_Method ICommonDialog ShowColor 1 Lib_Method ICommonDialog ShowSave 1 Lib_EnumEntry ColorConstants cdlCCRGBInit 1 GUI_Property CommonDialog Filter 1 Lib_Property ICommonDialog InitDir 2 Coclass MSComDlg CommonDialog 3 Lib_EnumEntry FileOpenConstants cdlOFNHideReadOnly 1 Lib_Property ICommonDialog CancelError 8 Lib_Property ICommonDialog Filter 7 Lib_Property ICommonDialog FilterIndex 2 Lib_Method ICommonDialog ShowOpen 4 Lib_Property ICommonDialog PrinterDefault 2 Lib_EnumEntry PrinterConstants cdlPDSelection 1 GUI_Control CommonDialog _ctor 6 Lib_Property ICommonDialog Color 2 Lib_EnumEntry FileOpenConstants cdlOFNFileMustExist 1 Lib_Method ICommonDialog ShowPrinter 2 Lib_EnumEntry PrinterConstants cdlPDAllPages 1 Lib_Property ICommonDialog Flags 6 Lib_Property ICommonDialog hDC 1 Lib_EnumEntry PrinterConstants cdlPDNoPageNums 1 Lib_Property ICommonDialog FileName 10
ShowSave, ShowColor, ShowOpen, and ShowPrinter are used. The CommonDialog class declared both in GUI and Logic.
There are 8 methods that use CommonDialg:
Srcname LocName locmemb memName ------------------- ------------------- ------------------------ -------------- appmain frmUpgrade abtnManual_Click ShowOpen ic_RptsGeneral IcAcctPrintStmnt abtnPrintResults_Click ShowPrinter devOPOSposprn pnlLoadPix cmdLoad1_Click ShowOpen devOPOSposprn pnlLoadPix cmdLoad2_Click ShowOpen ic_Company IcCompanyMainSystem GetColor ShowColor ic_FuncLib clsFuncLib OpenFileDialog ShowOpen ic_FuncLib clsFuncLib SaveAsDialog ShowSave ic_FuncLib clsFuncLib SetDefaultPrinter ShowPrinter
Notice that each instance of CommonDialog is used for only one type of Show operation. This simplifies things and means we can migrate each instance to a specific .NET replacement.
Migrating CommonDialog to different Winforms Common dialog components
The migration has three steps:
1) Declare the different types and add migration rules map them to .NET replacement. These rules will be placed in a RefactorLibrary, comdlg32.ocx.WinForms.Refactor.xml. A copy of this file is attached to the gmStudio Extensions page. Notice that some of the API members are marked with migStatus=NotImplemented which will result in their being commented out in the translated logic.
<RefactorLibrary> <!-- Description: rules to assist with upgrading MSComDlg.CommonDialog to Winforms Dialog components This RefactorLibrary "extends" the CommonDialg base class with new coclasses to represent the different possible .NET targets. The upgrade solution must indicate which of these is extended types is used in different situations. This may be done with a fixtype commands or gmSL. Some additional cleanup may be needed which may be easily done with Author/Fix or manual edits after translation. --> <Refactor id="[comdlg32.ocx]" > <Migrate migName="System.Windows.Forms" libType="Internal" location="DoNotDeclare" AssemblyName="Remove.CommonDialog" /> <Migrate id="CommonDialog" migName="CommonDialog" Role="Define" /> <Migrate id="ICommonDialog.DialogTitle" migName="Title" /> <Migrate id="ICommonDialog.InitDir" migName="InitialDirectory" /> <Migrate id="ICommonDialog.Flags" migName="Options" migStatus="NotImplemented" /> <Migrate id="ICommonDialog.CancelError" migStatus="NotImplemented" /> <Migrate id="ICommonDialog.ShowOpen" migName="ShowDialog" /> <Migrate id="ICommonDialog.ShowSave" migName="ShowDialog" /> <Migrate id="ICommonDialog.ShowColor" migName="ShowDialog" /> <Migrate id="ICommonDialog.ShowFont" type="Variant" migName="ShowDialog" /> <Migrate id="ICommonDialog.ShowPrinter" migName="ShowDialog" /> <Migrate id="ICommonDialog.ShowHelp" migName="ShowDialog" /> <Migrate id="ICommonDialog.PrinterDefault" migStatus="NotImplemented" /> <Extend id="CommonDialog"> <coclass id="ColorDialog"/> <coclass id="FontDialog"/> <coclass id="HelpDialog"/> <coclass id="OpenFileDialog" /> <coclass id="PrintDialog"/> <coclass id="SaveFileDialog"/> </Extend> <Migrate id="ColorDialog" migName="ColorDialog" role="define" /> <Migrate id="OpenFileDialog" migName="OpenFileDialog" role="define" /> <Migrate id="PrintDialog" migName="PrintDialog" role="define" /> <Migrate id="SaveFileDialog" migName="SaveFileDialog" role="define" /> <migClass id="NetControl.CommonDialog" migName="Remove.CommonDialog" parent="CommonDialog"> <!-- no designer code for this component --> </migClass> <migClass id="NetControl.ColorDialog" migName="Remove.ColorDialog" parent="ColorDialog"> <!-- no designer code for this component --> </migClass> <migClass id="NetControl.OpenFileDialog" migName="Remove.OpenFileDialog" parent="OpenFileDialog"> <!-- no designer code for this component --> </migClass> <migClass id="NetControl.PrintDialog" migName="Remove.PrintDialog" parent="PrintDialog"> <!-- no designer code for this component --> </migClass> <migClass id="NetControl.SaveFileDialog" migName="Remove.SaveFileDialog" parent="SaveFileDialog"> <!-- no designer code for this component --> </migClass> </Refactor> </RefactorLibrary>
2) For each CommonDialog instance in the source, specify the custom type to use when migrating it. There are several ways to do this. These rules will be placed in a ScriptRules file, ComDlg32.ocx.Rules.xml.
<ScriptRules> <!-- Description: ScriptRules to migrate MSComDlg.CommonDialog to Winforms Common Dialog classes --> <ScriptRule id="comdlg32.OCX" Condition="%TaskTag%=~(upg)"> <Option> <Registry type="MigFile" source="comdlg32.OCX" target="comdlg32.OCX.WinForms.Refactor" /> </Option> <Compile Condition="%SrcName%=='ic_FuncLib'"> <Refactor errorStatus="Warn"> <FixType identifier="ic_FuncLib.clsFuncLib.OpenFileDialog.cDlg" type="MSComDlg.OpenFileDialog" /> <FixType identifier="ic_FuncLib.clsFuncLib.SaveAsDialog.cDlg" type="MSComDlg.SaveFileDialog" /> <FixType identifier="ic_FuncLib.clsFuncLib.SetDefaultPrinter.cDlg" type="MSComDlg.PrintDialog" /> </Refactor> </Compile> <Author Condition="%SrcName%=='ic_FuncLib'"> <Fix host="ic_FuncLib" name="PostEdit"> <Replace status="active" name="Cleanup Common Dialog instance"> <OldBlock><![CDATA[this.cmDlg = new System.Windows.Forms.CommonDialog();]]></OldBlock> </Replace> </Fix> </Author> <Compile Condition="%SrcName%=~'devOPOSposprn|appmain'"> <Fix host="%SrcName%" name="PreEdit"> <Replace status="active" name="Migrate CommonDialog as OpenFileDialog"> <OldBlock><![CDATA[Begin MSComDlg.CommonDialog]]></OldBlock> <NewBlock><![CDATA[Begin MSComDlg.OpenFileDialog]]></NewBlock> </Replace> </Fix> </Compile> <Compile Condition="%SrcName%=='ic_Company'"> <Fix host="%SrcName%" name="PreEdit"> <Replace status="active" name="Migrate CommonDialog as ColorDialog"> <OldBlock><![CDATA[Begin MSComDlg.CommonDialog CommonDialog1]]></OldBlock> <NewBlock><![CDATA[Begin MSComDlg.ColorDialog CommonDialog1]]></NewBlock> </Replace> </Fix> </Compile> <Compile Condition="%SrcName%=='ic_RptsFinancial'"> <Fix host="%SrcName%" name="PreEdit"> <Replace status="active" name="Remove unused CommonDialog"> <OldBlock><![CDATA[ Begin MSComDlg.CommonDialog CommonDialog1 ... End ]]></OldBlock> </Replace> </Fix> </Compile> <Compile Condition="%SrcName%=='ic_RptsGeneral'"> <Fix host="ic_RptsGeneral" name="PreEdit"> <Replace status="active" name="Migrate CommonDialog as PrintDialog"> <OldBlock><![CDATA[Begin MSComDlg.CommonDialog CommonDialog1]]></OldBlock> <NewBlock><![CDATA[Begin MSComDlg.PrintDialog CommonDialog1]]></NewBlock> </Replace> </Fix> </Compile> <Author Condition="%SrcName%=='ic_FuncLib|devOPOSposprn'"> <Fix host="%SrcName%" name="PostEdit"> <Replace status="active" name="Cleanup Spurious new from control"> <OldBlock><![CDATA[this.cmDlg = new System.Windows.Forms.CommonDialog();]]></OldBlock> </Replace> </Fix> </Author> </ScriptRule> </ScriptRules>
3) Load your ScriptRules using a command in your translation script (line 76):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Migration.tran.xml ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ... 72 <ScriptRule id="SYSINFO.OCX" FileName="..\usr\SysInfo.ocx.Rules.xml" /> 73 <ScriptRule id="mswinsck.ocx" FileName="..\usr\mswinsck.ocx.Rules.xml" /> 74 <ScriptRule id="msado15.dll" FileName="..\usr\msado15.dll.Custom.Rules.xml" /> 75 <ScriptRule id="RICHTX32.ocx" FileName="..\usr\RICHTX32.OCX.Rules.xml" /> > 76 <ScriptRule id="comdlg32.ocx" FileName="..\usr\comdlg32.ocx.Rules.xml" /> 77 <ScriptRule id="ieframe.dll" FileName="..\usr\ieframe.dll.Rules.xml" /> 78 <ScriptRule id="mscomm32.ocx" FileName="..\usr\mscomm32.ocx.Rules.xml" /> 79 80 <Compile Project="%SrcPath%" Resx="%ResxFolder%"/> ...