Figure 1   File Extensions in a Resource Template


STRINGTABLE PRELOAD DISCARDABLE 
BEGIN
 IDR_MYDOCTYPE "MyApp\nMyApp\nMyApp Document\nMyApp Files (*.dib,*.tif,*.pcx)\n.dib;*.tif;*.pcx\n\n"
END


Figure 3   File Open Dialog


 ////////////////////////////////////////////////////////////////
 // TabDlg 1997 Microsoft Systems Journal. 
 // If this program works, it was written by Paul DiLascia.
 // If not, I don't know who wrote it.
 //
 // TabDlg illustrates how to make a dialog with dynamic TAB order
 // and that handles the RETURN key.
 //
 
 #include <afxwin.h>         // MFC core and standard components
 #include <afxext.h>         // MFC extensions
 #include <afxpriv.h>        // for WM_KICKIDLE
 #include <stdlib.h>         // for random number generator fns
 #include "resource.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 //////////////////
 // Dialog class that alters the TAB sequence and handles
 // the RETURN key.
 //
 class CTabDialog : public CDialog {
    HACCEL m_hAccel;                     // dialog accelerators
    BOOL   m_bRandomTabOrder;            // do random TAB order?
 public:
    CTabDialog();
    virtual BOOL OnInitDialog();
    virtual BOOL PreTranslateMessage(MSG* pMsg);
 
    // Message/command handlers
    afx_msg LRESULT OnKickIdle(WPARAM wp, LPARAM lp);
    afx_msg void OnChangeTabs();
    afx_msg void OnReturn();
    afx_msg void OnUpdateChangeTabs(CCmdUI* pCmdUI);
    afx_msg BOOL OnNextPrevField(UINT nCmdID);
    DECLARE_MESSAGE_MAP()
 };
 
 ////////////////////////////////////////////////////////////////
 // Application class
 //
 class CApp : public CWinApp {
 public:
    CApp() { }
    virtual BOOL InitInstance();
 } theApp;
 
 /////////////////
 // Initialize: just run the dialog and quit.
 //
 BOOL CApp::InitInstance()
 {
    srand(time(NULL)); // seed random number generator
    
    CTabDialog dlg;
    int nResponse = dlg.DoModal();
    if (nResponse == IDOK) {
       // TODO: handle case when the dialog is dismissed with OK
    } else if (nResponse == IDCANCEL) {
       // TODO: handle case when the dialog is dismissed with Cancel
    }
 
    // Since the dialog has been closed, return FALSE so that we exit the
    // application, rather than start the application's message pump.
    return FALSE;
 }
 
 
 ////////////////////////////////////////////////////////////////
 // CTabDialog
 //
 BEGIN_MESSAGE_MAP(CTabDialog, CDialog)
    ON_MESSAGE(WM_KICKIDLE,       OnKickIdle)
    ON_COMMAND(ID_CHANGE_TABS,    OnChangeTabs)
    ON_COMMAND(ID_RETURN,         OnReturn)
    ON_COMMAND_EX(ID_NEXT_FIELD,  OnNextPrevField)
    ON_COMMAND_EX(ID_PREV_FIELD,  OnNextPrevField)
    ON_UPDATE_COMMAND_UI(ID_CHANGE_TABS, OnUpdateChangeTabs)
 END_MESSAGE_MAP()
 
 //////////////////
 // Construct dialog: set everything to zero or NULL.
 //
 CTabDialog::CTabDialog() : CDialog(IDD_DIALOG1)
 {
    m_hAccel = NULL;
    m_bRandomTabOrder = FALSE;
 }
 
 //////////////////
 // Possibly translate accelerator key.
 //
 BOOL CTabDialog::PreTranslateMessage(MSG* pMsg)
 {
    if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) {
       // Translate the message using accelerator table
       ASSERT(m_hAccel);
       return ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg);
    }
    return CDialog::PreTranslateMessage(pMsg);
 }
 
 //////////////////
 // Handle idle message: update dialog controls. This is required to make
 // the idle update command UI mechanism work for a dialog.
 //
 LRESULT CTabDialog::OnKickIdle(WPARAM wp, LPARAM lCount)
 {
    UpdateDialogControls(this, TRUE);
    return 0;
 }
 
 /////////////////
 // Initialize dialog: load accelerators and set initial focus.
 //
 BOOL CTabDialog::OnInitDialog()
 {
    m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(),
       MAKEINTRESOURCE(IDD_DIALOG1));
    ASSERT(m_hAccel);
    GotoDlgCtrl(GetDlgItem(IDC_EDIT1));
    return FALSE; // because I have set the focus
 }
 
 //////////////////
 // Scramble/unscramble tab order
 //
 void CTabDialog::OnChangeTabs()
 {
    m_bRandomTabOrder = !m_bRandomTabOrder;
 }
 
 //////////////////
 // Update name of Scramble/unscramble button
 //
 void CTabDialog::OnUpdateChangeTabs(CCmdUI* pCmdUI)
 {
    pCmdUI->SetText(m_bRandomTabOrder ?
       "Unscramble &TAB Order" : "Scramble &TAB Order");
 }
 
 /////////////////
 // Handle Return (Enter) key
 //
 void CTabDialog::OnReturn()
 {
    OnNextPrevField(ID_NEXT_FIELD);
 }
 
 /////////////////
 // Go to next or previous field
 //
 BOOL CTabDialog::OnNextPrevField(UINT nCmdID)
 {
    CWnd* pWnd = CWnd::GetFocus();
    if (m_bRandomTabOrder) {
       static int controls[] = { IDC_EDIT1,
          IDC_EDIT2, IDC_EDIT3, IDC_COMBO1, ID_CHANGE_TABS, IDOK, IDCANCEL };
       const NCONTROLS = sizeof(controls)/sizeof(int);
 
       // Select a random control that's different from the current one.
       int nIDCtrl;
       while ((nIDCtrl = controls[rand() % NCONTROLS]) == pWnd->GetDlgCtrlID())
          ; // same as current, try another
       pWnd = GetDlgItem(nIDCtrl);
 
    } else 
       // Normal next/prev using dialog's TAB order.
       pWnd = GetNextDlgTabItem(pWnd, nCmdID==ID_PREV_FIELD);
 
    ASSERT(pWnd);
    GotoDlgCtrl(pWnd);
    return TRUE;
 }

Figure 6   Functions for Navigating Dialog Controls

CWnd Function
CWnd* GetNextDlgTabItem(CWnd* pWndCtl,
                           BOOL bPrevious = FALSE)
Gets the next child control in the dialog's tab order.
CDialog Functions (These take care of highlighting edit text, and so on.)
void CDialog::NextDlgCtrl()
Move to next control
void CDialog::PrevDlgCtrl()
Move to previous control
void CDialog::GotoDlgCtrl(CWnd* pWndCtrl)
Move to specified control


Figure 7   AfxRegisterWndClass


 //////////////////
 // How to register your own window class without CS_HREDRAW and CS_VREDRAW
 //
 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
 {
    cs.lpszClass = AfxRegisterWndClass(
       CS_DBLCLKS,                       // if you need double-clicks
       NULL,                             // no cursor (use default)
       NULL,                             // no background brush
       AfxGetApp()->LoadIcon(IDR_MAINFRAME)); // app icon
    ASSERT(cs.lpszClass);
 
    return CFrameWnd::PreCreateWindow(cs);
 }