MAINIT.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:38k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (C) 1993 - 1997  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. //  mainit.c
  13. //
  14. //  Description:
  15. //
  16. //
  17. //  History:
  18. //       9/21/93
  19. //
  20. //==========================================================================;
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include <mmsystem.h>
  24. #include <commdlg.h>
  25. #include "mixapp.h"
  26. #include "debug.h"
  27. //
  28. //
  29. //
  30. TCHAR       gszAppProfile[]     = TEXT("mixapp.ini");
  31. TCHAR       gszSecConfig[]      = TEXT("Configuration");
  32. TCHAR       gszKeyOptions[]     = TEXT("Options");
  33. TCHAR       gszFormatOptions[]  = TEXT("%u");
  34. TCHAR       gszKeyWindow[]      = TEXT("Window");
  35. TCHAR       gszKeyFont[]        = TEXT("Font");
  36. //==========================================================================;
  37. //
  38. //
  39. //
  40. //
  41. //==========================================================================;
  42. //--------------------------------------------------------------------------;
  43. //
  44. //  BOOL AppProfileWriteBytes
  45. //
  46. //  Description:
  47. //      This function writes a raw structure of bytes to the application's
  48. //      ini section that can later be retrieved using AppProfileReadBytes.
  49. //      This gives an application the ability to write any structure to
  50. //      the ini file and restore it later--very useful.
  51. //
  52. //      NOTE! Starting with Windows for Workgroups 3.1 there are two new
  53. //      profile functions that provide the same functionality of this
  54. //      function. Specifically, these functions are GetPrivateProfileStruct
  55. //      and WritePrivateProfileStruct. These new functions are provided
  56. //      by the Common Controls DLL. The prototypes are as follows:
  57. //
  58. //      BOOL GetPrivateProfileStruct
  59. //      (
  60. //          LPSTR       szSection,
  61. //          LPSTR       szKey,
  62. //          LPBYTE      lpStruct,
  63. //          UINT        uSizeStruct,
  64. //          LPSTR       szFile
  65. //      );
  66. //
  67. //      BOOL WritePrivateProfileStruct
  68. //      (
  69. //          LPSTR       szSection,
  70. //          LPSTR       szKey,
  71. //          LPBYTE      lpStruct,
  72. //          UINT        uSizeStruct,
  73. //          LPSTR       szFile
  74. //      );
  75. //
  76. //      If you are building an application that is for Window for Workgroups
  77. //      or newer versions of Windows, you will probably want to use the
  78. //      above functions.
  79. //
  80. //  Arguments:
  81. //      PTSTR pszSection: Pointer to section for the stored data.
  82. //
  83. //      PTSTR pszKey: Pointer to key name for the stored data.
  84. //
  85. //      LPBYTE pbStruct: Pointer to the data to be saved.
  86. //
  87. //      UINT cbStruct: Count in bytes of the data to store.
  88. //
  89. //  Return (BOOL):
  90. //      The return value is TRUE if the function is successful. It is FALSE
  91. //      if it fails.
  92. //
  93. //  History:
  94. //       3/10/93
  95. //
  96. //--------------------------------------------------------------------------;
  97. BOOL FNGLOBAL AppProfileWriteBytes
  98. (
  99.     PTSTR                   pszSection,
  100.     PTSTR                   pszKey,
  101.     LPBYTE                  pbStruct,
  102.     UINT                    cbStruct
  103. )
  104. {
  105.     static TCHAR achNibbleToChar[] =
  106.     {
  107.         '0', '1', '2', '3', '4', '5', '6', '7',
  108.         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
  109.     };
  110.     #define     NIBBLE2CHAR(x)      (achNibbleToChar[x])
  111.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  112.     LPTSTR      psz;
  113.     LPTSTR      pch;
  114.     UINT        cchTemp;
  115.     BOOL        fAllocated;
  116.     BOOL        fReturn;
  117.     BYTE        b;
  118.     BYTE        bChecksum;
  119.     //
  120.     //  if pbStruct is NULL, then erase the key from the ini file, otherwise
  121.     //  format the raw bytes into a hex string and write that out...
  122.     //
  123.     fAllocated = FALSE;
  124.     psz        = NULL;
  125.     if (NULL != pbStruct)
  126.     {
  127.         //
  128.         //  check if the quick buffer can be used for formatting the output
  129.         //  text--if it cannot, then alloc space for it. note that space
  130.         //  must be available for an ending checksum byte (2 bytes for high
  131.         //  and low nibble) as well as a null terminator.
  132.         //
  133.         psz     = (LPTSTR)ach;
  134.         cchTemp = cbStruct * 2 + 3;
  135.         if (cchTemp > SIZEOF(ach))
  136.         {
  137.             psz = (LPTSTR)GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  138.             if (NULL == psz)
  139.                 return (FALSE);
  140.             fAllocated = TRUE;
  141.         }
  142.         //
  143.         //  step through all bytes in the structure and convert it to
  144.         //  a string of hex numbers...
  145.         //
  146.         bChecksum = 0;
  147.         for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  148.         {
  149.             //
  150.             //  grab the next byte and add into checksum...
  151.             //
  152.             bChecksum = (BYTE) (bChecksum + (b = *pbStruct));
  153.             *pch++ = NIBBLE2CHAR((b >> (BYTE)4) & (BYTE)0x0F);
  154.             *pch++ = NIBBLE2CHAR(b & (BYTE)0x0F);
  155.         }
  156.         //
  157.         //  add the checksum byte to the end and null terminate the hex
  158.         //  dumped string...
  159.         //
  160.         *pch++ = NIBBLE2CHAR((bChecksum >> (BYTE)4) & (BYTE)0x0F);
  161.         *pch++ = NIBBLE2CHAR(bChecksum & (BYTE)0x0F);
  162.         *pch   = '';
  163.     }
  164.     //
  165.     //  write the string of hex bytes out to the ini file...
  166.     //
  167.     fReturn = WritePrivateProfileString(pszSection, pszKey, psz, gszAppProfile);
  168.     //
  169.     //  free the temporary buffer if one was allocated (lots of bytes!)
  170.     //
  171.     if (fAllocated)
  172.         GlobalFreePtr(psz);
  173.     return (fReturn);
  174. } // AppProfileWriteBytes
  175. //--------------------------------------------------------------------------;
  176. //
  177. //  BOOL AppProfileReadBytes
  178. //
  179. //  Description:
  180. //      This function reads a previously stored structure of bytes from
  181. //      the application's ini file. This data must have been written with
  182. //      the AppProfileWriteBytes function--it is checksumed to keep bad
  183. //      data from blowing up the application.
  184. //
  185. //      NOTE! Starting with Windows for Workgroups 3.1 there are two new
  186. //      profile functions that provide the same functionality of this
  187. //      function. Specifically, these functions are GetPrivateProfileStruct
  188. //      and WritePrivateProfileStruct. These new functions are provided
  189. //      by the Common Controls DLL. The prototypes are as follows:
  190. //
  191. //      BOOL GetPrivateProfileStruct
  192. //      (
  193. //          LPSTR       szSection,
  194. //          LPSTR       szKey,
  195. //          LPBYTE      lpStruct,
  196. //          UINT        uSizeStruct,
  197. //          LPSTR       szFile
  198. //      );
  199. //
  200. //      BOOL WritePrivateProfileStruct
  201. //      (
  202. //          LPSTR       szSection,
  203. //          LPSTR       szKey,
  204. //          LPBYTE      lpStruct,
  205. //          UINT        uSizeStruct,
  206. //          LPSTR       szFile
  207. //      );
  208. //
  209. //      If you are building an application that is for Window for Workgroups
  210. //      or newer versions of Windows, you will probably want to use the
  211. //      above functions.
  212. //
  213. //  Arguments:
  214. //      PTSTR pszSection: Pointer to section that contains the data.
  215. //
  216. //      PTSTR pszKey: Pointer to key that contains the data.
  217. //
  218. //      LPBYTE pbStruct: Pointer to buffer to receive the data.
  219. //
  220. //      UINT cbStruct: Number of bytes expected.
  221. //
  222. //  Return (BOOL):
  223. //      The return value is TRUE if the function is successful. It is FALSE
  224. //      if the function fails (bad checksum, missing key, etc).
  225. //
  226. //  History:
  227. //       3/10/93
  228. //
  229. //--------------------------------------------------------------------------;
  230. BOOL FNGLOBAL AppProfileReadBytes
  231. (
  232.     PTSTR                   pszSection,
  233.     PTSTR                   pszKey,
  234.     LPBYTE                  pbStruct,
  235.     UINT                    cbStruct
  236. )
  237. {
  238.     //
  239.     //  note that the following works for both upper and lower case, and
  240.     //  will return valid values for garbage chars
  241.     //
  242.     #define CHAR2NIBBLE(ch) (BYTE)( ((ch) >= '0' && (ch) <= '9') ?  
  243.                                 (BYTE)((ch) - '0') :                
  244.                                 ((BYTE)(10 + (ch) - 'A') & (BYTE)0x0F) )
  245.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  246.     LPTSTR      psz;
  247.     LPTSTR      pch;
  248.     UINT        cchTemp;
  249.     UINT        u;
  250.     BOOL        fAllocated;
  251.     BOOL        fReturn;
  252.     BYTE        b;
  253.     BYTE        bChecksum;
  254.     TCHAR       ch;
  255.     //
  256.     //  add one the the number of bytes needed to accomodate the checksum
  257.     //  byte placed at the end by AppProfileWriteBytes...
  258.     //
  259.     cbStruct++;
  260.     //
  261.     //  check if the quick buffer can be used for retrieving the input
  262.     //  text--if it cannot, then alloc space for it. note that there must
  263.     //  be space available for the null terminator (the +1 below).
  264.     //
  265.     fAllocated = FALSE;
  266.     psz        = (LPTSTR)ach;
  267.     cchTemp    = cbStruct * 2 + 1;
  268.     if (cchTemp > SIZEOF(ach))
  269.     {
  270.         psz = (LPTSTR)GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  271.         if (NULL == psz)
  272.             return (FALSE);
  273.         fAllocated = TRUE;
  274.     }
  275.     //
  276.     //  read the hex string... if it is not the correct length, then assume
  277.     //  error and return.
  278.     //
  279.     fReturn = FALSE;
  280.     u = (UINT)GetPrivateProfileString(pszSection, pszKey, gszNull,
  281.                                       psz, cchTemp, gszAppProfile);
  282.     if ((cbStruct * 2) == u)
  283.     {
  284.         bChecksum = 0;
  285.         for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  286.         {
  287.             ch = *pch++;
  288.             b  = (BYTE) (CHAR2NIBBLE(ch) << (BYTE)4);
  289.             ch = *pch++;
  290.             b |= CHAR2NIBBLE(ch);
  291.             //
  292.             //  if this is not the final byte (the checksum byte), then
  293.             //  store it and accumulate checksum..
  294.             //
  295.             if (cbStruct != 1)
  296.                 bChecksum = (BYTE) (bChecksum + (*pbStruct = b));
  297.         }
  298.         //
  299.         //  check the last byte read against the checksum that we calculated
  300.         //  if they are not equal then return error...
  301.         //
  302.         fReturn = (bChecksum == b);
  303.     }
  304.     //
  305.     //  free the temporary buffer if one was allocated (lots of bytes!)
  306.     //
  307.     if (fAllocated)
  308.         GlobalFreePtr(psz);
  309.     return (fReturn);
  310. } // AppProfileReadBytes
  311. //--------------------------------------------------------------------------;
  312. //
  313. //  DWORD AppGetWindowsVersion
  314. //
  315. //  Description:
  316. //      This function returns the version of Windows that the application
  317. //      is running on plus some platform information.
  318. //
  319. //  Arguments:
  320. //      PTSTR pach: Options pointer to buffer to receive text string of
  321. //      the Windows version and platform.
  322. //
  323. //  Return (LRESULT):
  324. //      The return value will be the version and platform information of
  325. //      the current operating system in the following format:
  326. //
  327. //      0xPPPPMMRR where:
  328. //
  329. //      MM      :   major version of Windows
  330. //      RR      :   minor version (revision) of Windows
  331. //      PPPP    :   the platform the application is running on which
  332. //                  the HIWORD() is RESERVED except for the high bit:
  333. //                      high bit is 0 = Windows NT
  334. //                      high bit is 1 = Win32s/Windows 3.1
  335. //
  336. //
  337. //--------------------------------------------------------------------------;
  338. LRESULT FNLOCAL AppGetWindowsVersion
  339. (
  340.     PTSTR                   pszEnvironment,
  341.     PTSTR                   pszPlatform
  342. )
  343. {
  344.     BYTE    bVerWinMajor;
  345.     BYTE    bVerWinMinor;
  346.     UINT    uVerEnv;
  347.     DWORD   dw;
  348.     LRESULT lr;
  349.     dw = GetVersion();
  350.     //
  351.     //  massage the version information into something intelligent
  352.     //
  353.     //
  354.     bVerWinMajor = LOBYTE(LOWORD(dw));
  355.     bVerWinMinor = HIBYTE(LOWORD(dw));
  356.     uVerEnv      = HIWORD(dw);
  357.     lr = MAKELPARAM(((UINT)bVerWinMajor << 8) | bVerWinMinor, uVerEnv);
  358.     //
  359.     //  if caller wants the environment string version...
  360.     //
  361.     if (NULL != pszEnvironment)
  362.     {
  363.         static TCHAR    szFormatVersion[]   = TEXT("Win32 Version %u.%.2u");
  364.         wsprintf(pszEnvironment, szFormatVersion,
  365.                  bVerWinMajor, bVerWinMinor);
  366.     }
  367.     //
  368.     //  if caller wants the platform string version...
  369.     //
  370.     if (NULL != pszPlatform)
  371.     {
  372.         static TCHAR    szFormatPlatform[]  = TEXT("%s%u, %u Processor(s)");
  373.         static TCHAR    szProcessorIntel[]  = TEXT("Intel ");
  374.         static TCHAR    szProcessorMIPS[]   = TEXT("MIPS R");
  375.         static TCHAR    szProcessorAlpha[]  = TEXT("DEC Alpha ");
  376.         static TCHAR    szProcessorDunno[]  = TEXT("Dunno zYz");
  377.         SYSTEM_INFO sysinfo;
  378.         PTSTR       pszProcessor;
  379.         //
  380.         //  this is absolutely silly. one would think that the dwOemId member
  381.         //  would provide something useful like the processor class... but
  382.         //  no, it doesn't--it is always 0.
  383.         //
  384.         GetSystemInfo(&sysinfo);
  385.         switch (sysinfo.dwProcessorType)
  386.         {
  387.             case PROCESSOR_INTEL_386:
  388.             case PROCESSOR_INTEL_486:
  389.                 pszProcessor = szProcessorIntel;
  390.                 break;
  391.             case PROCESSOR_MIPS_R4000:
  392.                 pszProcessor = szProcessorMIPS;
  393.                 break;
  394.             case PROCESSOR_ALPHA_21064:
  395.                 pszProcessor = szProcessorAlpha;
  396.                 break;
  397.             default:
  398.                 pszProcessor = szProcessorDunno;
  399.                 break;
  400.         }
  401.         //
  402.         //
  403.         //
  404.         wsprintf(pszPlatform, szFormatPlatform, (LPSTR)pszProcessor,
  405.                  sysinfo.dwProcessorType, sysinfo.dwNumberOfProcessors);
  406.     }
  407.     //
  408.     //  return the result
  409.     //
  410.     return (lr);
  411. } // AppGetWindowsVersion()
  412. //--------------------------------------------------------------------------;
  413. //
  414. //  HFONT AppChooseFont
  415. //
  416. //  Description:
  417. //      This function is a wrapper for the ChooseFont() common dialog.
  418. //      The purpose of this function is to let the user choose a font that
  419. //      looks good to them--regardless of how stupid it really looks.
  420. //
  421. //  Arguments:
  422. //      HWND hwnd: Handle to parent window for chooser dialog.
  423. //
  424. //      HFONT hfont: Handle to current font (default for chooser dialog).
  425. //
  426. //      PLOGFONT plf: Pointer to optional LOGFONT structure to receive a
  427. //      copy of the LOGFONT information for the newly chosen font.
  428. //
  429. //  Return (HFONT):
  430. //      The return value is the newly chosen font. If no new font was chosen
  431. //      then the return value is NULL.
  432. //
  433. //--------------------------------------------------------------------------;
  434. HFONT FNGLOBAL AppChooseFont
  435. (
  436.     HWND                    hwnd,
  437.     HFONT                   hfont,
  438.     PLOGFONT                plf
  439. )
  440. {
  441.     LOGFONT             lf;
  442.     CHOOSEFONT          cf;
  443.     BOOL                f;
  444.     HFONT               hfontNew;
  445.     //
  446.     //  get the font info for the current font...
  447.     //
  448.     GetObject(hfont, sizeof(LOGFONT), (LPVOID)&lf);
  449.     //
  450.     //  fill in the choosefont structure
  451.     //
  452.     cf.lStructSize  = sizeof(CHOOSEFONT);
  453.     cf.hwndOwner    = hwnd;
  454.     cf.hDC          = NULL;
  455.     cf.Flags        = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT;
  456.     cf.lCustData    = 0;
  457.     cf.lpfnHook     = NULL;
  458.     cf.hInstance    = NULL;
  459.     cf.nFontType    = SCREEN_FONTTYPE;
  460.     cf.lpLogFont    = (LPLOGFONT)&lf;
  461.     //
  462.     //  splash a dialog into the user's face..
  463.     //
  464.     hfontNew = NULL;
  465.     f = ChooseFont(&cf);
  466.     if (f)
  467.     {
  468.         //
  469.         //  create the new font..
  470.         //
  471.         hfontNew = CreateFontIndirect(&lf);
  472.         if (NULL == hfontNew)
  473.             return (NULL);
  474.         //
  475.         //  copy the logfont structure if caller wants it
  476.         //
  477.         if (NULL != plf)
  478.             *plf = lf;
  479.     }
  480.     //
  481.     //  return the new font (if one was chosen)
  482.     //
  483.     return (hfontNew);
  484. } // AppChooseFont()
  485. //==========================================================================;
  486. //
  487. //  Misc rarely used application dialogs and stuff...
  488. //
  489. //
  490. //==========================================================================;
  491. //--------------------------------------------------------------------------;
  492. //
  493. //  BOOL AboutDlgProc
  494. //
  495. //  Description:
  496. //      This dialog procedure is used for the ubiquitous about box.
  497. //
  498. //  Arguments:
  499. //      HWND hwnd: Handle to window.
  500. //
  501. //      UINT uMsg: Message being sent to the window.
  502. //
  503. //      WPARAM wParam: Specific argument to message.
  504. //
  505. //      LPARAM lParam: Specific argument to message.
  506. //
  507. //  Return (BOOL):
  508. //      The return value is specific to the message that was received. For
  509. //      the most part, it is FALSE if this dialog procedure does not handle
  510. //      a message.
  511. //
  512. //  History:
  513. //       1/ 2/93
  514. //
  515. //--------------------------------------------------------------------------;
  516. BOOL CALLBACK AboutDlgProc
  517. (
  518.     HWND                    hwnd,
  519.     UINT                    uMsg,
  520.     WPARAM                  wParam,
  521.     LPARAM                  lParam
  522. )
  523. {
  524.     HWND                hwndT;
  525.     PTSTR               pach;
  526.     UINT                u;
  527.     switch (uMsg)
  528.     {
  529.         case WM_INITDIALOG:
  530.             //
  531.             //  display some OS version information
  532.             //
  533.             //
  534.             pach = (PTSTR)LocalAlloc(LPTR, APP_MAX_STRING_RC_BYTES);
  535.             if (NULL == pach)
  536.                 return (TRUE);
  537.             AppGetWindowsVersion(pach, NULL);
  538.             hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_OS);
  539.             SetWindowText(hwndT, pach);
  540.             AppGetWindowsVersion(NULL, pach);
  541.             hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_PLATFORM);
  542.             SetWindowText(hwndT, pach);
  543.             LocalFree((HLOCAL)pach);
  544.             return (TRUE);
  545.         case WM_COMMAND:
  546.             u = GET_WM_COMMAND_ID(wParam, lParam);
  547.             if ((IDOK == u) || (IDCANCEL == u))
  548.             {
  549.                 EndDialog(hwnd, (IDOK == u));
  550.             }
  551.             break;
  552.     }
  553.     return (FALSE);
  554. } // AboutDlgProc()
  555. //==========================================================================;
  556. //
  557. //  Initialization and exit code...
  558. //
  559. //
  560. //==========================================================================;
  561. //--------------------------------------------------------------------------;
  562. //
  563. //  BOOL MixAppChooseFont
  564. //
  565. //  Description:
  566. //      This function lets the user choose a new font for the script window.
  567. //      After a new font is chosen, the font structure is stored to the
  568. //      .ini file so it can be restored on the next run of this application.
  569. //
  570. //  Arguments:
  571. //      HWND hwnd: Handle to main window.
  572. //
  573. //  Return (BOOL):
  574. //      The return value is TRUE if a new font was chosen. It is FALSE if
  575. //      the user canceled the operation.
  576. //
  577. //  History:
  578. //       2/ 7/93
  579. //
  580. //--------------------------------------------------------------------------;
  581. BOOL FNGLOBAL MixAppChooseFont
  582. (
  583.     HWND                    hwnd
  584. )
  585. {
  586.     LOGFONT             lf;
  587.     HWND                hlb;
  588.     HFONT               hfont;
  589.     HFONT               hfontNew;
  590.     //
  591.     //  get the current font and pass it to the choose font dialog
  592.     //
  593.     hlb   = GetDlgItem(hwnd, IDD_APP_LIST_LINES);
  594.     hfont = GetWindowFont(hlb);
  595.     hfontNew = AppChooseFont(hwnd, hfont, &lf);
  596.     if (NULL == hfontNew)
  597.         return (FALSE);
  598.     //
  599.     //  select the new font into the script window and delete the old one
  600.     //
  601.     TlbSetFont(gptlbLines, hfontNew, TRUE);
  602.     DeleteFont(hfont);
  603.     //
  604.     //  save the complete description of the chosen font so there can be
  605.     //  no strangness in the font mapping next run. this is overkill, but
  606.     //  it works...
  607.     //
  608.     AppProfileWriteBytes(gszSecConfig, gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  609.     return (TRUE);
  610. } // MixAppChooseFont()
  611. //--------------------------------------------------------------------------;
  612. //
  613. //  BOOL MixAppSettingsRestore
  614. //
  615. //  Description:
  616. //      This function restores state information for the application. This
  617. //      function is called just after the main window is created (it has
  618. //      not been ShowWindow()'d). This function will generate the call
  619. //      to ShowWindow before returning.
  620. //
  621. //  Arguments:
  622. //      HWND hwnd: Handle to main window that has just been created but
  623. //      not shown.
  624. //
  625. //      int nCmdShow: The state that the application window should show as.
  626. //
  627. //  Return (BOOL):
  628. //      The return value is always TRUE.
  629. //
  630. //  History:
  631. //      05/11/93
  632. //
  633. //--------------------------------------------------------------------------;
  634. BOOL FNLOCAL MixAppSettingsRestore
  635. (
  636.     HWND                    hwnd,
  637.     int                     nCmdShow
  638. )
  639. {
  640.     WINDOWPLACEMENT     wp;
  641.     HFONT               hfont;
  642.     LOGFONT             lf;
  643.     RECT                rc;
  644.     RECT                rcWindow;
  645.     POINT               pt;
  646.     int                 n;
  647.     BOOL                f;
  648.     //
  649.     //  restore the user's preferred font.
  650.     //
  651.     hfont = NULL;
  652.     f = AppProfileReadBytes(gszSecConfig, gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  653.     if (f)
  654.     {
  655.         hfont = CreateFontIndirect(&lf);
  656.     }
  657.     if (NULL == hfont)
  658.     {
  659.         hfont = GetStockFont(SYSTEM_FONT);
  660.     }
  661.     TlbSetFont(gptlbLines, hfont, TRUE);
  662.     //
  663.     //  grab the stored window position and size from the .ini file...
  664.     //  there must be four arguments stored or the entry is considered
  665.     //  invalid.
  666.     //
  667.     f = AppProfileReadBytes(gszSecConfig, gszKeyWindow,
  668.                             (LPBYTE)&rcWindow, sizeof(rcWindow));
  669.     if (f)
  670.     {
  671.         //
  672.         //  to make sure the user can always get at the window, check to
  673.         //  see if the midpoint of the caption is visible--if it is not,
  674.         //  then default to the default position used when creating the
  675.         //  window.
  676.         //
  677.         n = (rcWindow.right - rcWindow.left) / 2;
  678.         pt.x = (n + rcWindow.left);
  679.         n = GetSystemMetrics(SM_CYCAPTION) / 2 + GetSystemMetrics(SM_CXFRAME);
  680.         pt.y = (n + rcWindow.top);
  681.         GetWindowRect(GetDesktopWindow(), &rc);
  682.         if (PtInRect(&rc, pt))
  683.         {
  684.             //
  685.             //  fill out the window placement structure--default the
  686.             //  maximized and minimized states to default placement by
  687.             //  getting its current placement.
  688.             //
  689.             wp.length = sizeof(wp);
  690.             GetWindowPlacement(hwnd, &wp);
  691.             wp.showCmd          = nCmdShow;
  692.             wp.rcNormalPosition = rcWindow;
  693.             SetWindowPlacement(hwnd, &wp);
  694.             return (TRUE);
  695.         }
  696.     }
  697.     //
  698.     //  show defaulted and succeed
  699.     //
  700.     ShowWindow(hwnd, nCmdShow);
  701.     return (TRUE);
  702. } // MixAppSettingsRestore()
  703. //--------------------------------------------------------------------------;
  704. //
  705. //  BOOL MixAppSettingsSave
  706. //
  707. //  Description:
  708. //      This function saves the current state information for the application.
  709. //      It is called just before the main window is closed (destroyed); or
  710. //      as Windows is exiting (query end session).
  711. //
  712. //      Note that this function should not destroy any resources--it can
  713. //      be called at any time to save a snapshot of the application state.
  714. //
  715. //  Arguments:
  716. //      HWND hwnd: Handle to main window that will be destroyed shortly.
  717. //
  718. //  Return (BOOL):
  719. //      The return value is always TRUE.
  720. //
  721. //  History:
  722. //      05/11/93
  723. //
  724. //--------------------------------------------------------------------------;
  725. BOOL FNLOCAL MixAppSettingsSave
  726. (
  727.     HWND                    hwnd
  728. )
  729. {
  730.     WINDOWPLACEMENT     wp;
  731.     PRECT               prc;
  732.     BOOL                f;
  733.     //
  734.     //  save the current window placement--only store the size and location
  735.     //  of the restored window. maximized and minimized states should
  736.     //  remain defaulted on the next invocation of this application.
  737.     //
  738.     wp.length = sizeof(wp);
  739.     f = GetWindowPlacement(hwnd, &wp);
  740.     if (f)
  741.     {
  742.         prc = &wp.rcNormalPosition;
  743.         DPF(1, "WindowPlacement: show=%d, minX=%d, minY=%d, maxX=%d, maxY=%d",
  744.              wp.showCmd, wp.ptMinPosition.x, wp.ptMinPosition.y,
  745.              wp.ptMaxPosition.x, wp.ptMaxPosition.y);
  746.         DPF(1, "                 normX=%d, normY=%d, normW=%d, normH=%d",
  747.              prc->left, prc->top, prc->right, prc->bottom);
  748.         //
  749.         //  save the _bounding rectangle_ of the restored window state...
  750.         //
  751.         AppProfileWriteBytes(gszSecConfig, gszKeyWindow, (LPBYTE)prc, sizeof(*prc));
  752.     }
  753.     //
  754.     //  succeed
  755.     //
  756.     return (TRUE);
  757. } // MixAppSettingsSave()
  758. //--------------------------------------------------------------------------;
  759. //
  760. //  LRESULT AppCreate
  761. //
  762. //  Description:
  763. //      This function is called to handle the WM_CREATE message for the
  764. //      application's window. The application should finish the creation
  765. //      of the window (create controls, allocate resources, etc). The
  766. //      window has not been displayed (CreateWindow[Ex] has not returned).
  767. //
  768. //  Arguments:
  769. //      HWND hwnd: Handle to the window that is in the process of being
  770. //      created.
  771. //
  772. //      LPCREATESTRUCT pcs: Pointer to a CREATESTRUCT that contains info
  773. //      about the window being created.
  774. //
  775. //  Return (LRESULT):
  776. //      The return value should be nonzero if the application wishes to
  777. //      let the window finish being created. A return of zero tells
  778. //      CreateWindow[Ex] to fail the creation of the window.
  779. //
  780. //  History:
  781. //      11/ 8/92
  782. //
  783. //--------------------------------------------------------------------------;
  784. LRESULT FNGLOBAL AppCreate
  785. (
  786.     HWND                    hwnd,
  787.     LPCREATESTRUCT          pcs
  788. )
  789. {
  790.     extern TCHAR       gszLineFormatTitle[];
  791.     DPF(1, "AppCreate(hwnd=%Xh, cs.x=%d, cs.y=%d, cs.cx=%d, cs.cy=%d)",
  792.             hwnd, pcs->x, pcs->y, pcs->cx, pcs->cy);
  793.     //
  794.     //  create the driver selection listbox
  795.     //
  796.     gptlbLines = TlbCreate(hwnd, IDD_APP_LIST_LINES, NULL);
  797.     if (NULL == gptlbLines)
  798.         return (0L);
  799.     TlbSetTitleAndTabs(gptlbLines, gszLineFormatTitle, FALSE);
  800.     //
  801.     //  default to device id zero... a real app would allow configuration
  802.     //  and set to previous selection. but this is not a real app.
  803.     //
  804.     ghmx = MixAppNewDevice(hwnd, NULL, 0);
  805.     if (NULL == ghmx)
  806.     {
  807.         //
  808.         //  must be having a very bad day..
  809.         //
  810.         return (0L);
  811.     }
  812.     //
  813.     //
  814.     //
  815.     MixAppRefreshLineList(hwnd, gptlbLines);
  816.     //
  817.     //  return nonzero to succeed the creation of the window
  818.     //
  819.     return (1L);
  820. } // AppCreate()
  821. //--------------------------------------------------------------------------;
  822. //
  823. //  LRESULT AppQueryEndSession
  824. //
  825. //  Description:
  826. //      This function handles the WM_QUERYENDSESSION. This message is sent
  827. //      by USER when ExitWindows has been called to end the Windows session.
  828. //      This function can stop Windows from exiting if it is not convenient
  829. //      for Windows to end.
  830. //
  831. //      Giving the user the option to save modified data before continueing
  832. //      with the shutdown of Windows is a good idea.
  833. //
  834. //      Telling Windows to continue with the exit procedure does not
  835. //      necessarily mean Windows will exit. All applications are queried
  836. //      for shutdown approval. When the actual decision is made on whether
  837. //      Windows will exit, WM_ENDSESSION will be sent with the result.
  838. //
  839. //  Arguments:
  840. //      HWND hwnd: Handle to window that received the message.
  841. //
  842. //  Return (LRESULT):
  843. //      Returns zero to STOP Windows from exiting. Returns non-zero to
  844. //      allows windows to shut down.
  845. //
  846. //  History:
  847. //       2/ 9/93
  848. //
  849. //--------------------------------------------------------------------------;
  850. LRESULT FNGLOBAL AppQueryEndSession
  851. (
  852.     HWND                    hwnd
  853. )
  854. {
  855.     DPF(1, "AppQueryEndSession(hwnd=%Xh)", hwnd);
  856.     //
  857.     //  tell Windows to proceed with the shutdown process!
  858.     //
  859.     return (1L);
  860. } // AppQueryEndSession()
  861. //--------------------------------------------------------------------------;
  862. //
  863. //  LRESULT AppEndSession
  864. //
  865. //  Description:
  866. //      This function is called to handle the WM_ENDSESSION message. This
  867. //      message is generated after the application answers the
  868. //      WM_QUERYENDSESSION message. The purpose of the WM_ENDSESSION
  869. //      message is to tell the application if Windows will be exiting
  870. //      (TRUE  == fEndSession) or the end session was canceled by an
  871. //      application (FALSE == fEndSession).
  872. //
  873. //  Arguments:
  874. //      HWND hwnd: Handle to window that received the message.
  875. //
  876. //      BOOL fEndSession: TRUE if Windows is exiting. FALSE if the end
  877. //      session was canceled.
  878. //
  879. //  Return (LRESULT):
  880. //      Returns zero if the message is processed. Note that an application
  881. //      cannot halt the termination of Windows from this message--the
  882. //      WM_QUERYENDSESSION is the only message that allows that behaviour.
  883. //      If fEndSession is TRUE, Windows *WILL* exit--whether you like it
  884. //      or not.
  885. //
  886. //  History:
  887. //       2/ 9/93
  888. //
  889. //--------------------------------------------------------------------------;
  890. LRESULT FNGLOBAL AppEndSession
  891. (
  892.     HWND                    hwnd,
  893.     BOOL                    fEndSession
  894. )
  895. {
  896.     DPF(1, "AppEndSession(hwnd=%Xh, fEndSession=%d)", hwnd, fEndSession);
  897.     //
  898.     //  we processed the message, return zero..
  899.     //
  900.     return (0L);
  901. } // AppEndSession()
  902. //--------------------------------------------------------------------------;
  903. //
  904. //  LRESULT AppClose
  905. //
  906. //  Description:
  907. //      This function handles the WM_CLOSE message for the application.
  908. //      If the application should close, DestroyWindow() must be called
  909. //      by this function. Otherwise the application will not close.
  910. //
  911. //  Arguments:
  912. //      HWND hwnd: Handle to window that generated the WM_CLOSE message.
  913. //
  914. //  Return (LRESULT):
  915. //      There return value is zero. The DestroyWindow function will have
  916. //      been called if the application should actually close.
  917. //
  918. //  History:
  919. //       2/ 6/93
  920. //
  921. //--------------------------------------------------------------------------;
  922. LRESULT FNGLOBAL AppClose
  923. (
  924.     HWND                    hwnd
  925. )
  926. {
  927.     HWND                hlb;
  928.     HFONT               hfont;
  929.     MMRESULT            mmr;
  930.     DPF(1, "AppClose(hwnd=%Xh)", hwnd);
  931.     //
  932.     //  save any settings that should be saved on app termination...
  933.     //
  934.     MixAppSettingsSave(hwnd);
  935.     //
  936.     //  if the Shift key is held down during the close message, then just
  937.     //  save the current state but don't destroy the window... this is
  938.     //  useful if the user does not want to exit the app and rerun it
  939.     //  to make sure the state is saved--just before the user does something
  940.     //  that may crash Windows or something..
  941.     //
  942.     if (GetKeyState(VK_SHIFT) < 0)
  943.     {
  944.         return (0L);
  945.     }
  946.     //
  947.     //  destroy the font we are using... before deleting the font, select
  948.     //  the system font back into the script window so the font won't
  949.     //  be 'in use' anymore.
  950.     //
  951.     hlb = GetDlgItem(hwnd, IDD_APP_LIST_LINES);
  952.     hfont = GetWindowFont(hlb);
  953.     SetWindowFont(hlb, NULL, FALSE);
  954.     DeleteFont(hfont);
  955.     //
  956.     //
  957.     //
  958.     if (NULL != ghmx)
  959.     {
  960.         mmr = mixerClose(ghmx);
  961.         if (MMSYSERR_NOERROR != mmr)
  962.         {
  963.             AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  964.                       "mixerClose() failed on hmx=%.04Xh, mmr=%u!",
  965.                       ghmx, mmr);
  966.         }
  967.         ghmx = NULL;
  968.     }
  969.     gptlbLines->hlb = NULL;
  970.     TlbDestroy(gptlbLines);
  971.     gptlbLines = NULL;
  972.     //
  973.     //  make the window close and terminate the application
  974.     //
  975.     DestroyWindow(hwnd);
  976.     return (0L);
  977. } // AppClose()
  978. //==========================================================================;
  979. //
  980. //
  981. //
  982. //
  983. //==========================================================================;
  984. //--------------------------------------------------------------------------;
  985. //
  986. //  BOOL AppInit
  987. //
  988. //  Description:
  989. //      This function is called to initialize a new instance of the
  990. //      application. We want to parse our command line, create our window,
  991. //      allocate resources, etc.
  992. //
  993. //      The arguments passed to this function are exactly the same as
  994. //      those passed to WinMain.
  995. //
  996. //  Arguments:
  997. //      HINSTANCE hinst: Identifies the current instance of the
  998. //      application.
  999. //
  1000. //      HINSTANCE hinstPrev: Identifies the previous instance of the
  1001. //      application (NULL if first instance). For Win 32, this argument
  1002. //      is _always_ NULL.
  1003. //
  1004. //      LPTSTR pszCmdLine: Points to null-terminated unparsed command line.
  1005. //      If the application is compiled for Unicode, then this argument is
  1006. //      ignored.
  1007. //
  1008. //      int nCmdShow: How the main window for the application is to be
  1009. //      shown by default.
  1010. //
  1011. //  Return (HWND):
  1012. //      Returns the newly created handle to the applications main window.
  1013. //      This handle is NULL if something went wrong and tells the application
  1014. //      to exit immediately.
  1015. //
  1016. //  History:
  1017. //      11/ 8/92
  1018. //
  1019. //--------------------------------------------------------------------------;
  1020. HWND FNGLOBAL AppInit
  1021. (
  1022.     HINSTANCE               hinst,
  1023.     HINSTANCE               hinstPrev,
  1024.     LPTSTR                  pszCmdLine,
  1025.     int                     nCmdShow
  1026. )
  1027. {
  1028.     LRESULT CALLBACK AppWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  1029.     HWND                hwnd;
  1030.     WNDCLASS            wc;
  1031.     UINT                cMixerDevs;
  1032.     DPF(1, "AppInit(hinst=%Xh, hinstPrev=%Xh, pszCmdLine='%s', nCmdShow=%d)",
  1033.             hinst, hinstPrev, pszCmdLine, nCmdShow);
  1034.     LoadString(hinst, IDS_APP_NAME, gszAppName, SIZEOF(gszAppName));
  1035.     //
  1036.     //  WARNING DANGER WARNING DANGER WARNING DANGER WARNING DANGER WARNING
  1037.     //
  1038.     //      BEFORE calling any other mixer API's, we must call the
  1039.     //      mixerGetNumDevs() function to let the mixer thunk library
  1040.     //      dynamically link to all the mixer API's!
  1041.     //
  1042.     //  WARNING DANGER WARNING DANGER WARNING DANGER WARNING DANGER WARNING
  1043.     //
  1044.     cMixerDevs = mixerGetNumDevs();
  1045.     if (0 == cMixerDevs)
  1046.     {
  1047.         AppMsgBox(NULL, MB_OK | MB_ICONEXCLAMATION,
  1048.                   "There are no mixer devices installed. This application is useless.");
  1049.         return (NULL);
  1050.     }
  1051.     //
  1052.     //  determine whether a new window class needs to be registered for
  1053.     //  this application. for Win 16, this only needs to be done for the
  1054.     //  first instance of the application created. for Win 32, this must
  1055.     //  be done for EVERY instance of the application.
  1056.     //
  1057.     if (NULL == hinstPrev)
  1058.     {
  1059.         wc.style         = CS_HREDRAW | CS_VREDRAW;
  1060.         wc.lpfnWndProc   = (WNDPROC)AppWndProc;
  1061.         wc.cbClsExtra    = 0;
  1062.         wc.cbWndExtra    = 0;
  1063.         wc.hInstance     = hinst;
  1064.         wc.hIcon         = LoadIcon(hinst, ICON_APP);
  1065.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  1066.         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  1067.         wc.lpszMenuName  = MENU_APP;
  1068.         wc.lpszClassName = gszAppName;
  1069.         if (!RegisterClass(&wc))
  1070.             return (NULL);
  1071.     }
  1072.     //
  1073.     //  create the application's main window
  1074.     //
  1075.     //  style bits available:
  1076.     //      WS_EX_ACCEPTFILES   :  will receive WM_DROPFILES messages
  1077.     //      WS_EX_DLGMODALFRAME :  creates window with double border
  1078.     //      WS_EX_NOPARENTNOTIFY:  won't receive WM_PARENTNOTIFY messages
  1079.     //      WS_EX_TOPMOST       :  puts window in topmost space
  1080.     //      WS_EX_TRANSPARENT   :  a very bizarre style indeed (Win 16 only)
  1081.     //
  1082.     hwnd = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
  1083.                           gszAppName,
  1084.                           gszAppName,
  1085.                           WS_OVERLAPPEDWINDOW,
  1086.                           APP_WINDOW_XOFFSET,
  1087.                           APP_WINDOW_YOFFSET,
  1088.                           APP_WINDOW_WIDTH,
  1089.                           APP_WINDOW_HEIGHT,
  1090.                           NULL,
  1091.                           NULL,
  1092.                           hinst,
  1093.                           NULL);
  1094.     if (NULL == hwnd)
  1095.         return (NULL);
  1096. #ifdef UNICODE
  1097.     //
  1098.     //  the application--which is different than the pszCmdLine argument
  1099.     //  passed through WinMain()...
  1100.     //
  1101.     //  so, skip over the command name to get to the argument string
  1102.     //
  1103.     pszCmdLine = GetCommandLine();
  1104.     if (NULL != pszCmdLine)
  1105.     {
  1106.         while (('' != *pszCmdLine) && (' ' != *pszCmdLine++))
  1107.             ;
  1108.     }
  1109. #endif
  1110.     //
  1111.     //
  1112.     //
  1113.     //
  1114.     MixAppSettingsRestore(hwnd, nCmdShow);
  1115.     //
  1116.     //  finally, get the window displayed and return success
  1117.     //
  1118.     //  the ShowWindow call is made during MixAppInit
  1119.     //
  1120. //  ShowWindow(hwnd, nCmdShow);
  1121. //  UpdateWindow(hwnd);
  1122.     return (hwnd);
  1123. } // AppInit()
  1124. //--------------------------------------------------------------------------;
  1125. //
  1126. //  int AppExit
  1127. //
  1128. //  Description:
  1129. //      This function is called just before the application exits from
  1130. //      WinMain. Its purpose is to clean up any resources that were allocated
  1131. //      for running the application: brushes, heaps, etc..
  1132. //
  1133. //  Arguments:
  1134. //      HINSTANCE hinst: Identifies the current instance of the
  1135. //      application that is exiting.
  1136. //
  1137. //      int nResult: The result of the WM_QUIT message (in wParam of the
  1138. //      MSG structure. This argument will usually be 0 (even if the message
  1139. //      loop was never entered).
  1140. //
  1141. //  Return (int):
  1142. //      The return value is usually nResult--be we give this function the
  1143. //      opportunity to modify its value.
  1144. //
  1145. //  History:
  1146. //      11/ 8/92
  1147. //
  1148. //--------------------------------------------------------------------------;
  1149. int FNGLOBAL AppExit
  1150. (
  1151.     HINSTANCE               hinst,
  1152.     int                     nResult
  1153. )
  1154. {
  1155.     DPF(1, "AppExit(hinst=%Xh, nResult=%d)", hinst, nResult);
  1156.     //
  1157.     //
  1158.     //
  1159.     //
  1160.     return (nResult);
  1161. } // AppExit()