home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / idfedit / main.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  18KB  |  655 lines

  1. //************************************************************************
  2. //**
  3. //**  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. //**  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  5. //**  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
  6. //**  A PARTICULAR PURPOSE.
  7. //**
  8. //**  Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
  9. //**
  10. //**  main.c
  11. //**
  12. //**  DESCRIPTION:
  13. //**     Performs window class registration, creations and message 
  14. //**     polling.
  15. //**
  16. //************************************************************************
  17.  
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <mmsystem.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23.  
  24. #define DECLARE_VARS
  25. #include "idfedit.h"
  26.  
  27. /*+ ErrorBox ()
  28.  *
  29.  *  bring up a message box with a string from the stringtable
  30.  *
  31.  *-=================================================================*/
  32.  
  33. #include <stdarg.h>
  34.  
  35. int WINAPI ErrorBox (UINT wStringID, UINT wType, ...)
  36. {
  37.    char  szFormat[512];
  38.    char  szErr[512];
  39.    int   cbSize;
  40.    va_list va;
  41.  
  42.    va_start (va, wType);
  43.    cbSize = LoadString (hInst, wStringID, szFormat, NUMELMS(szFormat));
  44.    if (!cbSize)
  45.       wsprintf (szErr, "Error %d", wStringID);
  46.    else
  47.       wvsprintf (szErr, szFormat, va);
  48.    va_end (va);
  49.  
  50.    return MessageBox (hWndMain, szErr, szApp, wType);
  51. }
  52.  
  53. /*+ GetWindowPosFromIni
  54.  *
  55.  * retrieve the window position information from IDFEDIT.ini
  56.  *
  57.  *-=================================================================*/
  58.  
  59. static TCHAR cszProfile[] = TEXT ("MsIdfEd.ini");
  60. static TCHAR cszSection[] = TEXT ("General");
  61. static TCHAR cszWindow[]  = TEXT ("Window");
  62. static TCHAR cszWindowDef[] = TEXT ("");
  63. static TCHAR cszWindowFmt[] = TEXT ("%d,%d,%d,%d");
  64.  
  65. BOOL WINAPI GetWindowPosFromIni (
  66.    LPRECT lprc)
  67.    {
  68.    TCHAR sz[100];
  69.    RECT  rcScreen;
  70.    RECT  rc;
  71.  
  72.    GetPrivateProfileString (cszSection, cszWindow, cszWindowDef,
  73.                             sz, NUMELMS (sz), cszProfile);
  74.  
  75.    if ( ! SystemParametersInfo (SPI_GETWORKAREA, 0, &rcScreen, FALSE))
  76.       {
  77.       rcScreen.top = rcScreen.left = 0;
  78.       rcScreen.right = 640;
  79.       rcScreen.bottom = 480;
  80.       }
  81.  
  82.    sscanf (sz, cszWindowFmt,
  83.            &lprc->left, &lprc->top,
  84.            &lprc->right, &lprc->bottom);
  85.  
  86.    if ( ! IntersectRect (&rc, &rcScreen, lprc))
  87.       *lprc = rcScreen;
  88.  
  89.    return ! IsRectEmpty (lprc);
  90.    }
  91.  
  92. /*+ SaveWindowPosToIni
  93.  *
  94.  * store the window position information in dragn.ini
  95.  *
  96.  *-=================================================================*/
  97.  
  98. BOOL WINAPI SaveWindowPosToIni (
  99.    LPRECT lprc)
  100.    {
  101.    TCHAR sz[100];
  102.  
  103.    wsprintf (sz, cszWindowFmt,
  104.             lprc->left,
  105.             lprc->top,
  106.             lprc->right - lprc->left,
  107.             lprc->bottom - lprc->top);
  108.  
  109.    WritePrivateProfileString (cszSection, cszWindow, sz, cszProfile);
  110.  
  111.    return TRUE;
  112.    }
  113.  
  114. /*+ AboutDlgProc()
  115.  *
  116.  *  callback function for the about dialog
  117.  *
  118.  *-=================================================================*/
  119.  
  120. BOOL CALLBACK AboutDlgProc (
  121.    HWND   hWnd,
  122.    UINT   wMsgID,
  123.    WPARAM wParam,
  124.    LPARAM lParam)
  125.    {
  126.    BOOL bRet = FALSE;
  127.                          
  128.    switch (wMsgID)
  129.    {                    
  130.       case WM_COMMAND:
  131.       {
  132.          UINT  uID     = GET_WM_COMMAND_ID(wParam, lParam);
  133.          //UINT Notify   = GET_WM_COMMAND_CMD(wParam, lParam);
  134.          //HWND hWndCtl  = GET_WM_COMMAND_HWND(wParam, lParam);
  135.  
  136.          if (uID == IDOK || uID == IDCANCEL)
  137.          {   
  138.             EndDialog(hWnd, uID);
  139.             bRet = TRUE;
  140.          }
  141.          break;
  142.       }
  143.    }
  144.       
  145.    return bRet;
  146.    }
  147.  
  148. /*+ GetActiveData
  149.  *
  150.  * helper function, gets data space from the active MDI child
  151.  * window
  152.  *
  153.  *-=================================================================*/
  154.  
  155. static LPVOID GetActiveData ()
  156.    {
  157.    if (gs.pIDF && gs.pIDF->szFile[0])
  158.       return gs.pIDF;
  159.    return NULL;
  160.    }
  161.  
  162.  
  163. /*+
  164.  *
  165.  *-======================================================================*/
  166.  
  167. STATICFN VOID WINAPI SetStandardCaption (VOID)
  168.    {
  169.    TCHAR sz[MAX_PATH + 20];
  170.    LoadString (hInst, IDS_CAPTION_BAR, sz, NUMELMS (sz));
  171.    lstrcat (sz, TEXT(" - "));
  172.    if (gs.szDefFile[0])
  173.       lstrcat (sz, gs.szDefFile);
  174.    else
  175.       {
  176.       UINT cb = lstrlen(sz);
  177.       LoadString (hInst, IDS_DEF_FILE_NAME, sz + cb, NUMELMS(sz) - cb);
  178.       }
  179.    SetWindowText (hWndMain, sz);
  180.    }
  181.  
  182. /*+ SaveAndCloseHeader
  183.  *
  184.  *-======================================================================*/
  185.  
  186. STATICFN BOOL SaveAndCloseHeader (
  187.    HWND hWnd,
  188.    BOOL bSaveAs)
  189.    {
  190.    LPIDFHEAD pIDF = gs.pIDF;
  191.    BOOL      bRet;
  192.  
  193.    if (!pIDF)
  194.       return TRUE;
  195.  
  196.    if (!pIDF->szFile[0])
  197.       bSaveAs = TRUE;
  198.  
  199.    if (pIDF->bReadOnly)
  200.    {
  201.       ErrorBox (IDS_ERR_READONLY, EB_INFO, gs.szDefFile);
  202.       bSaveAs = TRUE;
  203.    }
  204.  
  205.    if (bSaveAs)
  206.       {  
  207.       if (! PromptForIDFName(hWnd, gs.szDefFile, NULL, TRUE))
  208.          return FALSE;
  209.       }
  210.    else
  211.       lstrcpy (gs.szDefFile, pIDF->szFile);
  212.  
  213.    if (!(bRet = SaveIDFToFile (pIDF, gs.szDefFile)))
  214.       ErrorBox (IDS_ERR_SAVE, EB_ERROR, gs.szDefFile);
  215.  
  216.    SetStandardCaption();
  217.    return bRet;
  218.    }
  219.  
  220. /*+ QuerySaveChanges
  221.  *
  222.  *-======================================================================*/
  223.  
  224. BOOL QuerySaveChanges (
  225.    HWND hWnd,
  226.    BOOL bSetForeground)
  227.    {
  228.    UINT  idBtn;
  229.    DWORD dwEB = EB_YNC;
  230.  
  231.    if (!gs.pIDF)
  232.       return TRUE;
  233.  
  234.    if (bSetForeground)
  235.       dwEB |= MB_SETFOREGROUND;
  236.  
  237.    idBtn = ErrorBox (IDS_QUERY_SAVE, dwEB, gs.pIDF->szFile);
  238.    if (idBtn == IDYES)
  239.       return SaveAndCloseHeader (hWnd, FALSE);
  240.    else if (idBtn == IDCANCEL)
  241.       return FALSE;
  242.    return TRUE;
  243.    }
  244.  
  245. /*+ OpenHeader
  246.  *
  247.  *-======================================================================*/
  248.  
  249. STATICFN LONG WINAPI OpenHeader (
  250.    HWND hWnd,
  251.    BOOL bPrompt)
  252.    {
  253.    TCHAR szFile[MAX_PATH];
  254.    TCHAR szTitle[MAX_PATH];
  255.    LPIDFHEAD pIDF;
  256.  
  257.    pIDF = gs.pIDF = &gs.idf;
  258.    if (gs.idf.bChanged && ! QuerySaveChanges (hWnd, FALSE))
  259.       return 0;
  260.  
  261.    FreeIDFFile (gs.pIDF);
  262.  
  263.    szFile[0] = 0;
  264.    if (bPrompt)
  265.       {
  266.       if ( ! PromptForIDFName (hWnd, szFile, szTitle, FALSE))
  267.          return 0;
  268.  
  269.       lstrcpy (gs.szDefFile, szFile);
  270.       LoadIDFFromFile (pIDF, szFile);
  271.       }
  272.  
  273.    if (!pIDF->hWndHead)
  274.       {
  275.       RECT rc;
  276.       GetClientRect (hWnd, &rc);
  277.  
  278.       pIDF->hWndHead = CreateWindowEx (fdwExStyle | WS_EX_NOPARENTNOTIFY,
  279.                                        cszHdrClass,
  280.                                        "",
  281.                                        WS_CHILD | WS_VISIBLE,
  282.                                        0, 0, rc.right, rc.bottom,
  283.                                        hWnd,
  284.                                        (HMENU)1,
  285.                                        hInst,
  286.                                        pIDF);
  287.       }
  288.    else
  289.       {
  290.       Head_RefreshTree (pIDF->hWndHead);
  291.       }
  292.  
  293.    SetStandardCaption();
  294.  
  295.    return (LONG)pIDF->hWndHead;
  296.    }
  297.  
  298. /*+ MainCommands
  299.  *
  300.  *-=================================================================*/
  301.  
  302. LONG WINAPI MainCommands (
  303.    HWND   hWnd,
  304.    WPARAM wParam,
  305.    LPARAM lParam)
  306.    {
  307.    LONG lRet     = 1;
  308.    WORD wID      = GET_WM_COMMAND_ID (wParam, lParam);
  309.    WORD wNotify  = GET_WM_COMMAND_CMD (wParam, lParam);
  310.    HWND hWndCtl  = GET_WM_COMMAND_HWND (wParam, lParam);
  311.  
  312.    switch (wID)
  313.       {
  314.       case IDM_ABOUT:
  315.          return DialogBox (hInst,
  316.                            MAKEINTRESOURCE(IDD_ABOUT),
  317.                            hWnd,
  318.                            AboutDlgProc);
  319.          break;
  320.  
  321.       case IDM_HELP:
  322.          ErrorBox (IDS_ERR_NOHELP, MB_OK);
  323.          break;
  324.  
  325.       case IDM_FILEOPEN:
  326.          lRet = OpenHeader (hWnd, TRUE);
  327.          break;
  328.  
  329.       case IDM_FILENEW:
  330.          lRet = OpenHeader (hWnd, FALSE);
  331.          if (gs.pIDF)
  332.          {
  333.             NewIDFInstrum (gs.pIDF, NULL, "<untitled>");
  334.             gs.pIDF->bChanged = FALSE;
  335.             Head_RefreshTree (gs.pIDF->hWndHead);
  336.          }
  337.          break;
  338.  
  339.       case IDM_FILESAVE:
  340.       case IDM_FILESAVEAS:
  341.          lRet = SaveAndCloseHeader (hWnd, wID == IDM_FILESAVEAS);
  342.          if (lRet)
  343.          {
  344.             // Saving has the side effect of also closing the file
  345.             // so we need to re-open it after the save completes
  346.             //
  347.             LoadIDFFromFile (gs.pIDF, gs.szDefFile);
  348.          }
  349.          Head_RefreshTree (gs.pIDF->hWndHead);
  350.          break;
  351.  
  352.       case IDM_NEW_INSTRUMENT:
  353.          NewIDFInstrum (gs.pIDF, NULL, "<untitled>");
  354.          Head_RefreshTree (gs.pIDF->hWndHead);
  355.          break;
  356.  
  357.       case IDM_FILEEXIT:
  358.          PostMessage (hWnd, WM_CLOSE, 0, 0);
  359.          break;
  360.  
  361.       //case IDM_EDITUNDO:
  362.       //   break;
  363.  
  364.       case IDM_EDITCUT:
  365.       case IDM_EDITCOPY:
  366.          if (gs.pIDF && gs.pIDF->piSelect)
  367.             {
  368.             CopyInstrumToClip (gs.pIDF);
  369.             if (wID == IDM_EDITCUT)
  370.                DeleteInstrum (gs.pIDF);
  371.             }
  372.          break;
  373.  
  374.       case IDM_EDITPASTE:
  375.          PasteInstrum (gs.pIDF);
  376.          break;
  377.  
  378.       case IDM_EDITDELETE:
  379.          if (gs.pIDF && gs.pIDF->piSelect)
  380.             DeleteInstrum (gs.pIDF);
  381.          break;
  382.       }
  383.  
  384.    return lRet;
  385.    }
  386.  
  387. /*+ MainWndProc
  388.  *
  389.  *-=================================================================*/
  390.  
  391. LRESULT CALLBACK MainWndProc (
  392.    HWND   hWnd,
  393.    UINT   wMsgID,
  394.    WPARAM wParam,
  395.    LPARAM lParam)
  396.    {
  397.    LONG  lRet = 0;         // return value from this routine
  398.  
  399.    switch (wMsgID)
  400.       {
  401.       case WM_COMMAND:
  402.          lRet = MainCommands (hWnd, wParam, lParam);
  403.          break;
  404.  
  405.       case WM_NOTIFY:
  406.          break;
  407.  
  408.       case WM_SIZE:
  409.          if (gs.idf.hWndHead)
  410.             SetWindowPos (gs.idf.hWndHead, NULL,
  411.                           0, 0, LOWORD(lParam), HIWORD(lParam),
  412.                           SWP_NOZORDER);
  413.          break;
  414.  
  415.       case WM_CREATE:
  416.          {
  417.          // send ourselves a command to create a document window.
  418.          //
  419.          PostMessage (hWnd, WM_COMMAND, IDM_FILEOPEN, 0);
  420.          }
  421.          break;
  422.  
  423.       case WM_INITMENUPOPUP:
  424.          {
  425.          HMENU  hPopup = (HMENU)wParam;
  426.          UINT   uPos   = (UINT) LOWORD (lParam);
  427.          BOOL   fSystemMenu = HIWORD (lParam);
  428.          UINT   uFirstID;
  429.  
  430.          // if this is for the system menu, go no further.
  431.          //
  432.          if (fSystemMenu)
  433.             break;
  434.  
  435.          // if this is the 'File' popup, do menu initialization
  436.          //
  437.          uFirstID = GetMenuItemID (hPopup, 0);
  438.          if (uFirstID == IDM_FILENEW)
  439.             {
  440.             EnableMenuItem (hPopup, IDM_FILESAVE, gs.pIDF ? MF_ENABLED : MF_GRAYED);
  441.             EnableMenuItem (hPopup, IDM_FILESAVEAS, gs.pIDF ? MF_ENABLED : MF_GRAYED);
  442.             }
  443.          else if (uFirstID == IDM_EDITCUT)
  444.             {
  445.             BOOL bCanPaste = IsClipboardFormatAvailable(CF_RIFF);
  446.             BOOL bCanCut = (gs.idf.piSelect != NULL);
  447.             // BOOL bCanUndo = FALSE;
  448.  
  449.             // EnableMenuItem (hPopup, IDM_EDITUNDO, bCanUndo ? MF_ENABLED : MF_GRAYED);
  450.             EnableMenuItem (hPopup, IDM_EDITCUT, bCanCut ? MF_ENABLED : MF_GRAYED);
  451.             EnableMenuItem (hPopup, IDM_EDITDELETE, bCanCut ? MF_ENABLED : MF_GRAYED);
  452.             EnableMenuItem (hPopup, IDM_EDITCOPY, bCanCut ? MF_ENABLED : MF_GRAYED);
  453.             EnableMenuItem (hPopup, IDM_EDITPASTE, bCanPaste ? MF_ENABLED : MF_GRAYED);
  454.             }
  455.          break;
  456.          }
  457.  
  458.       case WM_CLOSE:
  459.       case WM_QUERYENDSESSION:
  460.          {
  461.          WINDOWPLACEMENT wpl;
  462.  
  463.          if (gs.idf.bChanged &&
  464.              !QuerySaveChanges (hWnd, wMsgID == WM_QUERYENDSESSION))
  465.             break;
  466.  
  467.          //
  468.          // before we shutdown, save the current size and position
  469.          // of the window to the INI file.
  470.          //
  471.          ZeroMemory (&wpl, sizeof(wpl));
  472.          wpl.length = sizeof(wpl);
  473.          GetWindowPlacement (hWnd, &wpl);
  474.  
  475.          SaveWindowPosToIni (&wpl.rcNormalPosition);
  476.  
  477.          lRet = DefWindowProc (hWnd, wMsgID, wParam, lParam);
  478.          break;
  479.          }
  480.  
  481.       case WM_DESTROY:
  482.          // close the app (by causing an exit from the message loop)
  483.          PostQuitMessage (0);
  484.          break;
  485.  
  486.       default:
  487.          lRet = DefWindowProc (hWnd, wMsgID, wParam, lParam);
  488.       }
  489.    return lRet;
  490.    }
  491.  
  492. /*+ RegClasses ()
  493.  *
  494.  *  Registers all window classes that will be
  495.  *   used in this application.
  496.  *
  497.  *  Called from WinMain
  498.  *
  499.  *  returns: the return value of the call to RegisterClass ()
  500.  *          TRUE   if successful registration
  501.  *          FALSE  if registration failed
  502.  *
  503.  *-=================================================================*/
  504.  
  505. static CONST TCHAR cszMainClass[] = "Main";
  506.  
  507. extern LRESULT WINAPI ViewWndProc (HWND, UINT, WPARAM, LPARAM);
  508.  
  509. BOOL WINAPI RegClasses (
  510.    HANDLE hInstance)
  511.    {
  512.    WNDCLASS  wc;
  513.    TCHAR     ach[2];
  514.  
  515.    LoadString(hInstance, IDS_IS_RTL, ach, sizeof(ach)/sizeof(ach[0]));
  516.    fdwExStyle = (ach[0] == '1') ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0;
  517.  
  518.    //InitCommonControls();
  519.  
  520.    // register the main window class
  521.    //
  522.    ZeroMemory (&wc, sizeof(wc));
  523.    wc.lpszClassName = cszMainClass;
  524.    wc.lpfnWndProc   = MainWndProc;
  525.    wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
  526.    wc.hIcon         = LoadIcon (hInst, MAKEINTRESOURCE (IDR_MAIN));
  527.    wc.lpszMenuName  = MAKEINTRESOURCE (IDR_MAIN);
  528.    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
  529.    wc.hInstance     = hInstance;
  530.    if (!RegisterClass (&wc))
  531.        return FALSE;
  532.  
  533.    // register the idf instrument window class
  534.    //
  535.    ZeroMemory (&wc, sizeof(wc));
  536.    wc.lpszClassName = cszHdrClass;
  537.    wc.lpfnWndProc   = HeadWndProc;
  538.    wc.style         = CS_VREDRAW | CS_HREDRAW  | CS_DBLCLKS;
  539.    wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
  540.    wc.hIcon         = LoadIcon (hInst, MAKEINTRESOURCE (IDR_MAIN));
  541.    wc.lpszMenuName  = NULL;
  542.    wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE+1);
  543.    wc.hInstance     = hInstance;
  544.    if (!RegisterClass (&wc))
  545.        return FALSE;
  546.  
  547.    ZeroMemory (&wc, sizeof(wc));
  548.    wc.lpszClassName = cszInstrumClass;
  549.    wc.lpfnWndProc   = ViewWndProc;
  550.    wc.style         = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  551.    wc.hCursor       = LoadCursor (NULL, IDC_ARROW);
  552.    wc.hIcon         = LoadIcon (hInst, MAKEINTRESOURCE (IDR_INSTRUM));
  553.    wc.lpszMenuName  = NULL;
  554.    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
  555.    wc.hInstance     = hInstance;
  556.    if (!RegisterClass (&wc))
  557.        return FALSE;
  558.  
  559.    return TRUE;
  560.    }
  561.  
  562. /*+ CreateMainWindow ()
  563.  *
  564.  *  Creates the main window for the application.
  565.  *
  566.  *  Called from WinMain
  567.  *
  568.  *  returns:  a valid window handle if CreateWindow succeeds
  569.  *            or NULL if CreateWindow Fails
  570.  *
  571.  *-=================================================================*/
  572.  
  573. HWND WINAPI CreateMainWindow (
  574.    int nCmdShow)
  575.    {
  576.    HWND   hWnd;
  577.    TCHAR  szTitle[100];
  578.    RECT   rc;
  579.  
  580.    LoadString (hInst, IDS_CAPTION_BAR, szTitle, NUMELMS (szTitle));
  581.  
  582.    // get x, y, cx, cy positions from ini files
  583.    //
  584.    if ( ! GetWindowPosFromIni (&rc))
  585.       rc.left = rc.right = CW_USEDEFAULT;
  586.  
  587.    hWnd = CreateWindowEx (fdwExStyle,        // RTL style
  588.                        cszMainClass,         // class
  589.                        szTitle,              // title
  590.                        WS_OVERLAPPEDWINDOW,
  591.                        rc.left,
  592.                        rc.top,               // position: x,y
  593.                        rc.right,
  594.                        rc.bottom,            // size: width, height
  595.                        NULL,                 // parent
  596.                        NULL,                 // menu or child id
  597.                        hInst,                // instance
  598.                        NULL);                // params to pass on to WM_CREATE
  599.  
  600.    if (hWnd)
  601.       ShowWindow (hWnd, nCmdShow);
  602.  
  603.    return hWnd;
  604.    }
  605.  
  606. /*+ WinMain ()
  607.  *
  608.  *-=================================================================*/
  609.  
  610. int WINAPI WinMain (
  611.    HINSTANCE hInstance,
  612.    HINSTANCE hPrevInstance,
  613.    LPSTR lpszCmdLine,
  614.    int nCmdShow)
  615.    {
  616.    MSG     msg;      // temp for current message
  617.    HACCEL  hAccel;
  618.  
  619.    // save off instance handle in a global. THIS MUST BE DONE FIRST!
  620.    // also load the application name into a global string
  621.    //
  622.    hInst = hInstance;
  623.    LoadString (hInst, IDS_APPNAME, szApp, NUMELMS (szApp));
  624.  
  625.    // if this is not the first instance, register the class
  626.    // if class registration fails, put up a message box and quit
  627.    if (!RegClasses (hInstance))
  628.        return ErrorBox (IDS_ERR_REGCLASSES, EB_FATAL);
  629.  
  630.    hAccel = LoadAccelerators (hInst, MAKEINTRESOURCE(IDR_MAIN));
  631.  
  632.    // create the main window and save it's window handle in a global
  633.    // if the creation fails, put up a message box and quit.
  634.    //
  635.    hWndMain = CreateMainWindow (nCmdShow);
  636.    if ( !hWndMain)
  637.       return ErrorBox (IDS_ERR_CREATEMAIN, EB_FATAL);
  638.  
  639.    // loop forever getting messages and dispatching them
  640.    // to the appropriate window.
  641.    //
  642.    while (GetMessage (&msg, NULL, 0,0))
  643.    {
  644.       if (TranslateAccelerator (hWndMain, hAccel, &msg))
  645.          continue;
  646.  
  647.       TranslateMessage (&msg);
  648.       DispatchMessage (&msg);
  649.    }
  650.  
  651.    // return the wParam of the last message (the QUIT message)
  652.    //
  653.    return msg.wParam;
  654.    }
  655.