Figure 2   TippyDialog.cpp


 // TippyDialog.cpp : Defines the initialization routines for the DLL.
 //
 
 #include "stdafx.h"
 #include <afxdllx.h>
 #include "TippyDialog.h"
 #include "TippyDialogaw.h"
 
 #ifdef _PSEUDO_DEBUG
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 static AFX_EXTENSION_MODULE TippyDialogDLL = { NULL, NULL };
 
 extern "C" int APIENTRY
 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
 {
     if (dwReason == DLL_PROCESS_ATTACH)
     {
         TRACE0("TIPPYDIALOG.AWX Initializing!\n");
         
         // Extension DLL one-time initialization
         AfxInitExtensionModule(TippyDialogDLL, hInstance);
 
         // Insert this DLL into the resource chain
         new CDynLinkLibrary(TippyDialogDLL);
 
         // Register this custom AppWizard with MFCAPWZ.DLL
         SetCustomAppWizClass(&TippyDialogaw);
     }
     else if (dwReason == DLL_PROCESS_DETACH)
     {
         TRACE0("TIPPYDIALOG.AWX Terminating!\n");
     }
     return 1;   // ok
 }

Figure 3   Helper Functions for Custom Wizards

Function
Description
GetDialog
Find step dialog for a given wizard step number
ScanForAvailableLanguages
Identify languages supported by this wizard
SetCustomAppWizClass
Register wizard object with AppWizard
SetNumberOfSteps
Specify how many wizard steps will be presented
SetSupportedLanguages
Specify which languages will be supported for the current project


Figure 4   CCustomAppWiz Virtual Functions

Function
Description
Back
Get a pointer to the previous wizard step
CopyTemplate
Copy a binary template to a project file
ExitCustomAppWiz
Terminate use of the wizard object
GetPlatforms
Edit the list of platforms on which wizard's type of application can run
InitCustomAppWiz
Initialize the wizard object
LoadTemplate
Load the template resource used to generate a project file
Next
Get a pointer to the next wizard step
PostProcessTemplate
Deallocate memory used to hold a template resource
ProcessTemplate
Expand macro references in a template resource


Figure 5   CAppWizStepDlg Virtual Functions

Function
Description
Create
Override of CDialog::Create to control the default font
OnDismiss
Respond to user leaving this wizard step
PreTranslateMessage
Override of CDialog::PreTranslateMessage to handle tabbing from one step to another


Figure 6   Standard Macros

Name
Description
Root
root
Project name, without file extension and spelled exactly as the user entered it.
ROOT
Same as root, but spelled in uppercase.
Safe_root
Project name in mixed case, but with all non-alphanumeric characters removed.
safe_root
You can use SAFE_ROOT as the name of a preprocessor or C/C++ symbol.
SAFE_ROOT
Same as safe_root, but in uppercase.
FULL_DIR_PATH
The full path name of the directory where the new project will be created, including a trailing backslash.
TARGET_INTEL
These values exist in the dictionary
TARGET_MIPS
if the programmer selected the
TARGET_ALPHA
corresponding target platform from
TARGET_MAC
the list of platforms in the New
TARGET_68KMAC
Project Workspace dialog. TARGET_
TARGET_POWERMAC
INTEL corresponds to the Win32 choice. TARGET_MAC indicates that either TARGET_68KMAC or TARGET_POWERMAC was chosen.
host_cpu
Target CPU type (such as "X86").
cpu
Target CPU in a different form (such as "i86").
platform_long
Name of target platform (such as "Win32 (x86)").
platform_short
Name of target platform (such as "Win32").


Figure 9   NEWPROJ.INF Template Resource

			
 /res
 
 +MAINFRM.CPP       MainFrm.cpp
 MAINFRM.H          MainFrm.h
 +README.TXT        ReadMe.txt
 RESOURCE.H         Resource.h
 +STDAFX.CPP        StdAfx.cpp
 STDAFX.H           StdAfx.h
 ROOT.CLW           $$root$$.clw
 +ROOT.CPP          $$root$$.cpp
 ROOT.H             $$root$$.h
 +ROOT.RC           $$root$$.rc
 +DOC.CPP           $$root$$Doc.cpp
 DOC.H              $$root$$Doc.h
 +VIEW.CPP          $$root$$View.cpp
 VIEW.H             $$root$$View.h
 =ROOT.ICO          res\$$root$$.ico
 ROOT.RC2           res\$$root$$.rc2
 =DOC.ICO           res\$$root$$Doc.ico
 =TOOLBAR.BMP       res\Toolbar.bmp


Figure 10   Template Resource Prefix Characters

Prefix Character
Meaning
=
The template resource contains binary data. If you don't supply this option, the resource must contain text data.
+
The file becomes part of the project.
*
Even though you have a template resource in your wizard's resources, you want AppWizard to use the default resource by the same name from Microsoft's DLL. (You might use this feature in a "semi-custom" wizard. With * and some conditional logic, you can sometimes use your own version of a standard template and sometimes use the standard version.)


Figure 16   ROOT.CLW Template Resource


 ; CLW file contains information for the MFC ClassWizard
 
 [General Info]
 Version=1
 LastClass=CAboutBox
 LastTemplate=CDialog
 NewFileInclude1=#include "stdafx.h"
 NewFileInclude2=#include "$$root$$.h"
 LastPage=0
 
 ResourceCount=2
 Resource1=IDD_ABOUT
 Resource2=IDR_MAINMENU
 
 ClassCount=$$numclasses$$ // 3 + # window panes
 Class1=CMainWindow
 Class2=CAboutBox
 Class3=C$$Safe_root$$App
 $$paneclass$$
 
 [CLS:CMainWindow]
 Type=0
 BaseClass=CFrameWnd
 HeaderFile=mainwnd.h
 ImplementationFile=mainwnd.cpp
 LastObject=CMainWindow
 Filter=T
 VirtualFilter=fWC
 
 [DLG:IDD_ABOUT]
 Type=1
 Class=CAboutBox
 ControlCount=2
 Control1=IDOK,button,1342242817
 Control2=IDC_STATIC,static,1342308353
 
 [CLS:CAboutBox]
 Type=0
 HeaderFile=$$root$$.h
 ImplementationFile=$$root$$.cpp
 BaseClass=CDialog
 Filter=D
 LastObject=CAboutBox
 
 [CLS:C$$Safe_root$$App]
 Type=0
 HeaderFile=$$root$$.h
 ImplementationFile=$$root$$.cpp
 BaseClass=CWinApp
 LastObject=C$$Safe_root$$App
 Filter=N
 VirtualFilter=AC
 
 [MNU:IDR_MAINMENU]
 Type=1
 Class=?
 Command1=ID_APP_EXIT
 Command2=ID_APP_ABOUT
 CommandCount=2
 $$/////////////////////////////////////////////////////////
 $$IF(toolbar)
 
 [TB:IDR_MAINMENU]
 Type=1
 Class=?
 Command1=ID_FILE_NEW
 Command2=ID_FILE_OPEN
 Command3=ID_FILE_SAVE
 Command4=ID_EDIT_CUT
 Command5=ID_EDIT_COPY
 Command6=ID_EDIT_PASTE
 Command7=ID_FILE_PRINT
 Command8=ID_APP_ABOUT
 CommandCount=8
 $$ENDIF // toolbar
 $$/////////////////////////////////////////////////////////
 $$IF(treepane)
 
 [CLS:CTreePane]
 Type=0
 HeaderFile=treepane.h
 ImplementationFile=treepane.cpp
 BaseClass=CWnd
 Filter=W
 LastObject=CTreePane
 VirtualFilter=WC
 $$ENDIF // treepane
 $$/////////////////////////////////////////////////////////
 $$IF(datapane)
 
 [CLS:CDataPane]
 Type=0
 HeaderFile=datapane.h
 ImplementationFile=datapane.cpp
 BaseClass=CWnd
 Filter=W
 LastObject=CDataPane
 VirtualFilter=WC
 $$ENDIF // datapane
 $$/////////////////////////////////////////////////////////
 $$IF(stdpane)
 
 [CLS:CStdPane]
 Type=0
 HeaderFile=stdpane.h
 ImplementationFile=stdpane.cpp
 BaseClass=CWnd
 LastObject=CStdPane
 $$ENDIF // stdpane

Figure 17   OnDismiss


 BOOL CCustom1Dlg::OnDismiss()
     {                // CCustom1Dlg::OnDismiss
     if (!UpdateData(TRUE))
         return FALSE;
 
     #define d Undocaw.m_Dictionary
     #define ds(n,v) d[_T(#n)] = _T(#v)
     #define dr(n) d.RemoveKey(_T(#n))
 
     int numclasses = 0;
     CString paneclass;
 
     if (m_treepane)
         {            // tree pane included
         ds(treepane, 1);
         paneclass += csprintf("Class%d=CTreePane\n", numclasses+4);
         ++numclasses;
         }            // tree pane included
     else
         dr(treepane);
 
     if (m_datapane)
         {            // tree pane included
         ds(datapane, 1);
         paneclass += csprintf("Class%d=CDataPane\n", numclasses+4);
         ++numclasses;
         }            // tree pane included
     else
         dr(datapane);
 
     if (m_stdpane)
         {            // tree pane included
         ds(stdpane, 1);
         paneclass += csprintf("Class%d=CStdPane\n", numclasses+4);
         ++numclasses;
         }            // tree pane included
     else
         dr(stdpane);
 
     d[_T("numclasses")] = csprintf("%d", numclasses+3);
     d[_T("numpanes")] = csprintf("%d", numclasses);
     d[_T("paneclass")] = paneclass;
 
     if (numclasses > 1)
         ds(multipane, 1);
     else
         dr(multipane);
 
     if (m_toolbar)
         {            // toolbar requested
         ds(toolbar, 1);
 
         if (m_dockable)
             ds(dockable, 1);
         else
             dr(dockable);
 
         if (m_tooltips)
             ds(tooltips, 1);
         else
             dr(tooltips);
         }            // toolbar requested
     else
         {            // no toolbar requested
         dr(toolbar);
         dr(dockable);
         dr(tooltips);
         }            // no toolbar requested
 
     if (m_statusbar)
         {            // status bar requested
         ds(statusbar, 1);
 
         if (m_indicators)
             ds(indicators, 1);
         else
             dr(indicators);
         }            // status bar requested
     else
         {            // no status bar requested
         dr(statusbar);
         dr(indicators);
         }            // no status bar requested
 
     return TRUE;     // i.e., okay to dismiss dialog
     }                // CCustom1Dlg::OnDismiss

Figure A   CTippyDialog Member Functions


 BOOL CTippyDialog::OnInitDialog()
     {
     CDialog::OnInitDialog();
     theApp.m_dialog = this;
     theApp.m_tip = &m_tip;
     m_tip.Create(this);
     EnumChildWindows(m_hWnd, EnumChildProc, (LPARAM) this);
     m_tip.Activate(TRUE);
     return TRUE;
     }
 
 BOOL CALLBACK CTippyDialog::EnumChildProc(HWND hwnd, LPARAM lParam)
     {
     CTippyDialog* me = (CTippyDialog*) lParam;
     char classname[64];
     GetClassName(hwnd, classname, sizeof(classname));
     if (stricmp(classname, "STATIC") == 0)
         return TRUE;
     UINT id = GetWindowLong(hwnd, GWL_ID);
 
     TOOLINFO ti;
     memset(&ti, 0, sizeof(ti));
     ti.cbSize = sizeof(ti);
     ti.hwnd = me->m_hWnd;
     ti.uFlags = TTF_IDISHWND;
     ti.uId = (UINT) hwnd;
     ti.hinst = AfxGetResourceHandle();
     ti.lpszText = MAKEINTRESOURCE(id);
     me->m_tip.SendMessage(TTM_ADDTOOL, 0, (LPARAM) &ti);
 
     return TRUE;
     }
 
 void CTippyDialog::PostNcDestroy()
     {
     CDialog::PostNcDestroy();
     theApp.m_dialog = NULL;
     theApp.m_tip = NULL;
     }