Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1767 lines
50 KiB

  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) 1992 - 1994 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // aainit.c
  13. //
  14. // Description:
  15. // This file contains initialization and termination code for the
  16. // application (as well as some rarely used stuff).
  17. //
  18. //
  19. //==========================================================================;
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <mmsystem.h>
  23. #include <commdlg.h>
  24. #ifndef WIN32
  25. #include <shellapi.h>
  26. #endif
  27. #include <mmreg.h>
  28. #include <msacm.h>
  29. #include <stdarg.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <memory.h>
  34. #include "acmthunk.h"
  35. #include "appport.h"
  36. #include "acmapp.h"
  37. #include "debug.h"
  38. //
  39. //
  40. //
  41. TCHAR gszSecConfig[] = TEXT("Configuration");
  42. TCHAR gszKeyOptions[] = TEXT("Options");
  43. TCHAR gszFormatOptions[] = TEXT("%u");
  44. TCHAR gszKeyWindow[] = TEXT("Window");
  45. TCHAR gszKeyFont[] = TEXT("Font");
  46. TCHAR gszKeyInitialDirOpen[] = TEXT("InitialDirOpen");
  47. TCHAR gszKeyInitialDirSave[] = TEXT("InitialDirSave");
  48. TCHAR gszKeyLastSaveFile[] = TEXT("LastSaveFile");
  49. //==========================================================================;
  50. //
  51. // Application helper functions and rarely called stuff...
  52. //
  53. //
  54. //==========================================================================;
  55. //--------------------------------------------------------------------------;
  56. //
  57. // DWORD AppGetWindowsVersion
  58. //
  59. // Description:
  60. // This function returns the version of Windows that the application
  61. // is running on plus some platform information.
  62. //
  63. // Arguments:
  64. // PTSTR pach: Options pointer to buffer to receive text string of
  65. // the Windows version and platform.
  66. //
  67. // Return (LRESULT):
  68. // The return value will be the version and platform information of
  69. // the current operating system in the following format:
  70. //
  71. // 0xPPPPMMRR where:
  72. //
  73. // MM : major version of Windows
  74. // RR : minor version (revision) of Windows
  75. // PPPP : the platform the application is running on which
  76. // will be one of the following:
  77. //
  78. // #ifdef WIN32
  79. // the HIWORD() is RESERVED except for the high bit:
  80. // high bit is 0 = Windows NT
  81. // high bit is 1 = Win32s/Windows 3.1
  82. // #else
  83. // 0xMMRR = Major and Minor version of [MS-]DOS
  84. // GetWinFlags() & 0x8000 = Windows on OS/2 (WLO)
  85. // GetWinFlags() & 0x4000 = Windows on Windows NT (WOW)
  86. // #endif
  87. //
  88. //
  89. //--------------------------------------------------------------------------;
  90. LRESULT FNGLOBAL AppGetWindowsVersion
  91. (
  92. PTSTR pszEnvironment,
  93. PTSTR pszPlatform
  94. )
  95. {
  96. BYTE bVerWinMajor;
  97. BYTE bVerWinMinor;
  98. UINT uVerEnv;
  99. DWORD dw;
  100. LRESULT lr;
  101. dw = GetVersion();
  102. //
  103. // massage the version information into something intelligent
  104. //
  105. //
  106. bVerWinMajor = LOBYTE(LOWORD(dw));
  107. bVerWinMinor = HIBYTE(LOWORD(dw));
  108. uVerEnv = HIWORD(dw);
  109. lr = MAKELPARAM(((UINT)bVerWinMajor << 8) | bVerWinMinor, uVerEnv);
  110. //
  111. // if caller wants the environment string version...
  112. //
  113. if (NULL != pszEnvironment)
  114. {
  115. //
  116. //
  117. //
  118. #ifdef WIN32
  119. {
  120. static TCHAR szFormatVersion[] = TEXT("%s Version %u.%.2u");
  121. static TCHAR szEnvWinNT[] = TEXT("Windows NT");
  122. static TCHAR szEnvWin32s[] = TEXT("Win32s");
  123. wsprintf(pszEnvironment, szFormatVersion,
  124. (LPSTR)((0x8000 & uVerEnv) ? szEnvWin32s : szEnvWinNT),
  125. bVerWinMajor, bVerWinMinor);
  126. }
  127. #else
  128. {
  129. #ifndef WF_WINNT
  130. #define WF_WINNT 0x4000
  131. #define WF_WLO 0x8000
  132. #endif
  133. #ifndef WF_CPUMASK
  134. #define WF_CPUMASK 0xFC000000
  135. #define WF_CPU_X86 0
  136. #define WF_CPU_R4000 1
  137. #define WF_CPU_ALPHA 2
  138. #define WF_CPU_CLIPPER 3
  139. #define WF_CPU_POWERPC 4
  140. #endif
  141. static TCHAR szFormatSubSys[]= TEXT("Windows Version %u.%.2u (%s%s)\n%s Subsystem, DOS Version %u.%.2u");
  142. static TCHAR szFormatDOS[] = TEXT("Windows Version %u.%.2u (%s%s)\nDOS Version %u.%.2u");
  143. static TCHAR szSubSysWLO[] = TEXT("WLO");
  144. static TCHAR szSubSysWOW[] = TEXT("WOW");
  145. static TCHAR szModeEnhanced[]= TEXT("Enhanced");
  146. static TCHAR szModeStandard[]= TEXT("Standard");
  147. static TCHAR szEnvPaging[] = TEXT(", Paging");
  148. DWORD dwWinFlags;
  149. PTSTR pszMode;
  150. BYTE bVerEnvMajor = HIBYTE(LOWORD(uVerEnv));
  151. BYTE bVerEnvMinor = LOBYTE(LOWORD(uVerEnv));
  152. dwWinFlags = GetWinFlags();
  153. pszMode = (dwWinFlags & WF_ENHANCED) ? szModeEnhanced : szModeStandard;
  154. if (dwWinFlags & (WF_WLO | WF_WINNT))
  155. {
  156. wsprintf(pszEnvironment, szFormatSubSys, bVerWinMajor, bVerWinMinor,
  157. (LPSTR)pszMode,
  158. (LPSTR)((dwWinFlags & WF_PAGING) ? szEnvPaging : gszNull),
  159. (LPSTR)((dwWinFlags & WF_WINNT) ? szSubSysWOW : szSubSysWLO),
  160. bVerEnvMajor, bVerEnvMinor);
  161. }
  162. else
  163. {
  164. wsprintf(pszEnvironment, szFormatDOS, bVerWinMajor, bVerWinMinor,
  165. (LPSTR)pszMode,
  166. (LPSTR)((dwWinFlags & WF_PAGING) ? szEnvPaging : gszNull),
  167. bVerEnvMajor, bVerEnvMinor);
  168. }
  169. }
  170. #endif
  171. }
  172. //
  173. // if caller wants the platform string version...
  174. //
  175. if (NULL != pszPlatform)
  176. {
  177. #ifdef WIN32
  178. {
  179. GetEnvironmentVariable(TEXT("PROCESSOR_IDENTIFIER"), pszPlatform, APP_MAX_STRING_RC_BYTES);
  180. }
  181. #else
  182. {
  183. static TCHAR szPlat286[] = TEXT("80286");
  184. static TCHAR szPlat386[] = TEXT("80386");
  185. static TCHAR szPlat486[] = TEXT("i486");
  186. static TCHAR szPlatR4000[] = TEXT("MIPS R4000, Emulation: ");
  187. static TCHAR szPlatAlpha21064[] = TEXT("Alpha 21064, Emulation: ");
  188. static TCHAR szPlatPPC[] = TEXT("PowerPC, Emulation: ");
  189. static TCHAR szPlatClipper[] = TEXT("Clipper, Emulation: ");
  190. static TCHAR szPlat80x87[] = TEXT(", 80x87");
  191. DWORD dwWinFlags;
  192. dwWinFlags = GetWinFlags();
  193. pszPlatform[0] = '\0';
  194. if (dwWinFlags & (WF_WLO | WF_WINNT))
  195. {
  196. switch ((dwWinFlags & WF_CPUMASK) >> 26)
  197. {
  198. case WF_CPU_X86:
  199. break;
  200. case WF_CPU_R4000:
  201. lstrcpy(pszPlatform, szPlatR4000);
  202. break;
  203. case WF_CPU_ALPHA:
  204. lstrcpy(pszPlatform, szPlatAlpha21064);
  205. break;
  206. case WF_CPU_POWPERPC:
  207. lstrcpy(pszPlatform, szPlatPPC);
  208. break;
  209. case WF_CPU_CLIPPER:
  210. lstrcpy(pszPlatform, szPlatClipper);
  211. break;
  212. }
  213. }
  214. if (dwWinFlags & WF_CPU286)
  215. lstrcat(pszPlatform, szPlat286);
  216. else if (dwWinFlags & WF_CPU386)
  217. lstrcat(pszPlatform, szPlat386);
  218. else if (dwWinFlags & WF_CPU486)
  219. lstrcat(pszPlatform, szPlat486);
  220. if (dwWinFlags & WF_80x87)
  221. lstrcat(pszPlatform, szPlat80x87);
  222. }
  223. #endif
  224. }
  225. //
  226. // return the result
  227. //
  228. return (lr);
  229. } // AppGetWindowsVersion()
  230. //--------------------------------------------------------------------------;
  231. //
  232. // LRESULT AppWinIniChange
  233. //
  234. // Description:
  235. // This function is responsible for handling the WM_WININICHANGE
  236. // message. This message is sent when modifications have been made
  237. // to WIN.INI (from SystemParametersInfo() or other sources).
  238. //
  239. // An application should re-enumerate system metrics (GetSystemMetrics)
  240. // and system color (GetSystemColors) information that it has cached.
  241. // Note that checking the section that was modified should be done if
  242. // some enumerations are time consuming.
  243. //
  244. // Arguments:
  245. // HWND hwnd: Handle to window that generated the WM_INITMENUPOPUP
  246. // message.
  247. //
  248. // LPCTSTR pszSection: Pointer to section name that has been modified
  249. // in WIN.INI. Note that this argument might be NULL (sent by apps
  250. // that were written incorrectly!). If it is NULL, then this application
  251. // should re-enumerate ALL metrics, colors, etc.
  252. //
  253. // Return (LRESULT):
  254. // The return value is zero if the message is processed.
  255. //
  256. //
  257. //--------------------------------------------------------------------------;
  258. LRESULT FNGLOBAL AppWinIniChange
  259. (
  260. HWND hwnd,
  261. LPCTSTR pszSection
  262. )
  263. {
  264. DPF(1, "AppWinIniChanged(hwnd=%Xh, pszSection='%s')",
  265. hwnd, (NULL == pszSection) ? TEXT("(null)") : pszSection);
  266. //
  267. // we processed the message...
  268. //
  269. return (0L);
  270. } // AppWinIniChange()
  271. //--------------------------------------------------------------------------;
  272. //
  273. // HFONT AppChooseFont
  274. //
  275. // Description:
  276. // This function is a wrapper for the ChooseFont() common dialog.
  277. // The purpose of this function is to let the user choose a font that
  278. // looks good to them--regardless of how bad it really looks.
  279. //
  280. // Arguments:
  281. // HWND hwnd: Handle to parent window for chooser dialog.
  282. //
  283. // HFONT hfont: Handle to current font (default for chooser dialog).
  284. //
  285. // PLOGFONT plf: Pointer to optional LOGFONT structure to receive a
  286. // copy of the LOGFONT information for the newly chosen font.
  287. //
  288. // Return (HFONT):
  289. // The return value is the newly chosen font. If no new font was chosen
  290. // then the return value is NULL.
  291. //
  292. //
  293. //--------------------------------------------------------------------------;
  294. HFONT FNGLOBAL AppChooseFont
  295. (
  296. HWND hwnd,
  297. HFONT hfont,
  298. PLOGFONT plf
  299. )
  300. {
  301. LOGFONT lf;
  302. CHOOSEFONT cf;
  303. BOOL f;
  304. HFONT hfontNew;
  305. //
  306. // get the font info for the current font...
  307. //
  308. GetObject(hfont, sizeof(LOGFONT), (LPVOID)&lf);
  309. //
  310. // fill in the choosefont structure
  311. //
  312. cf.lStructSize = sizeof(CHOOSEFONT);
  313. cf.hwndOwner = hwnd;
  314. cf.hDC = NULL;
  315. cf.Flags = CF_SCREENFONTS |
  316. CF_INITTOLOGFONTSTRUCT |
  317. CF_FIXEDPITCHONLY |
  318. CF_FORCEFONTEXIST;
  319. cf.lCustData = 0;
  320. cf.lpfnHook = NULL;
  321. cf.hInstance = NULL;
  322. cf.nFontType = SCREEN_FONTTYPE;
  323. cf.lpLogFont = (LPLOGFONT)&lf;
  324. //
  325. // splash a dialog into the user's face..
  326. //
  327. hfontNew = NULL;
  328. f = ChooseFont(&cf);
  329. if (f)
  330. {
  331. //
  332. // create the new font..
  333. //
  334. hfontNew = CreateFontIndirect(&lf);
  335. if (NULL == hfontNew)
  336. return (NULL);
  337. //
  338. // copy the logfont structure if caller wants it
  339. //
  340. if (NULL != plf)
  341. *plf = lf;
  342. }
  343. //
  344. // return the new font (if one was chosen)
  345. //
  346. return (hfontNew);
  347. } // AppChooseFont()
  348. //--------------------------------------------------------------------------;
  349. //
  350. // BOOL AppProfileWriteBytes
  351. //
  352. // Description:
  353. // This function writes a raw structure of bytes to the application's
  354. // ini section that can later be retrieved using AppProfileReadBytes.
  355. // This gives an application the ability to write any structure to
  356. // the ini file and restore it later--very useful.
  357. //
  358. // NOTE! Starting with Windows for Workgroups 3.1 there are two new
  359. // profile functions that provide the same functionality of this
  360. // function. Specifically, these functions are GetPrivateProfileStruct
  361. // and WritePrivateProfileStruct. These new functions are provided
  362. // by the Common Controls DLL. The prototypes are as follows:
  363. //
  364. // BOOL GetPrivateProfileStruct
  365. // (
  366. // LPSTR szSection,
  367. // LPSTR szKey,
  368. // LPBYTE lpStruct,
  369. // UINT uSizeStruct,
  370. // LPSTR szFile
  371. // );
  372. //
  373. // BOOL WritePrivateProfileStruct
  374. // (
  375. // LPSTR szSection,
  376. // LPSTR szKey,
  377. // LPBYTE lpStruct,
  378. // UINT uSizeStruct,
  379. // LPSTR szFile
  380. // );
  381. //
  382. // If you are building an application that is for Window for Workgroups
  383. // or newer versions of Windows, you will probably want to use the
  384. // above functions.
  385. //
  386. // Arguments:
  387. // PTSTR pszSection: Pointer to section for the stored data.
  388. //
  389. // PTSTR pszKey: Pointer to key name for the stored data.
  390. //
  391. // LPBYTE pbStruct: Pointer to the data to be saved.
  392. //
  393. // UINT cbStruct: Count in bytes of the data to store.
  394. //
  395. // Return (BOOL):
  396. // The return value is TRUE if the function is successful. It is FALSE
  397. // if it fails.
  398. //
  399. //
  400. //--------------------------------------------------------------------------;
  401. BOOL FNGLOBAL AppProfileWriteBytes
  402. (
  403. PTSTR pszSection,
  404. PTSTR pszKey,
  405. LPBYTE pbStruct,
  406. UINT cbStruct
  407. )
  408. {
  409. static TCHAR achNibbleToChar[] =
  410. {
  411. '0', '1', '2', '3', '4', '5', '6', '7',
  412. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
  413. };
  414. #define NIBBLE2CHAR(x) (achNibbleToChar[x])
  415. TCHAR ach[APP_MAX_STRING_RC_CHARS];
  416. LPTSTR psz;
  417. LPTSTR pch;
  418. UINT cchTemp;
  419. BOOL fAllocated;
  420. BOOL fReturn;
  421. BYTE b;
  422. BYTE bChecksum;
  423. //
  424. // if pbStruct is NULL, then erase the key from the ini file, otherwise
  425. // format the raw bytes into a hex string and write that out...
  426. //
  427. fAllocated = FALSE;
  428. psz = NULL;
  429. if (NULL != pbStruct)
  430. {
  431. //
  432. // check if the quick buffer can be used for formatting the output
  433. // text--if it cannot, then alloc space for it. note that space
  434. // must be available for an ending checksum byte (2 bytes for high
  435. // and low nibble) as well as a null terminator.
  436. //
  437. psz = (LPTSTR)ach;
  438. cchTemp = cbStruct * 2 + 3;
  439. if (cchTemp > SIZEOF(ach))
  440. {
  441. psz = (LPTSTR)GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  442. if (NULL == psz)
  443. return (FALSE);
  444. fAllocated = TRUE;
  445. }
  446. //
  447. // step through all bytes in the structure and convert it to
  448. // a string of hex numbers...
  449. //
  450. bChecksum = 0;
  451. for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  452. {
  453. //
  454. // grab the next byte and add into checksum...
  455. //
  456. bChecksum += (b = *pbStruct);
  457. *pch++ = NIBBLE2CHAR((b >> (BYTE)4) & (BYTE)0x0F);
  458. *pch++ = NIBBLE2CHAR(b & (BYTE)0x0F);
  459. }
  460. //
  461. // add the checksum byte to the end and null terminate the hex
  462. // dumped string...
  463. //
  464. *pch++ = NIBBLE2CHAR((bChecksum >> (BYTE)4) & (BYTE)0x0F);
  465. *pch++ = NIBBLE2CHAR(bChecksum & (BYTE)0x0F);
  466. *pch = '\0';
  467. }
  468. //
  469. // write the string of hex bytes out to the ini file...
  470. //
  471. fReturn = WritePrivateProfileString(pszSection, pszKey, psz, gszAppProfile);
  472. //
  473. // free the temporary buffer if one was allocated (lots of bytes!)
  474. //
  475. if (fAllocated)
  476. GlobalFreePtr(psz);
  477. return (fReturn);
  478. } // AppProfileWriteBytes
  479. //--------------------------------------------------------------------------;
  480. //
  481. // BOOL AppProfileReadBytes
  482. //
  483. // Description:
  484. // This function reads a previously stored structure of bytes from
  485. // the application's ini file. This data must have been written with
  486. // the AppProfileWriteBytes function--it is checksumed to keep bad
  487. // data from blowing up the application.
  488. //
  489. // NOTE! Starting with Windows for Workgroups 3.1 there are two new
  490. // profile functions that provide the same functionality of this
  491. // function. Specifically, these functions are GetPrivateProfileStruct
  492. // and WritePrivateProfileStruct. These new functions are provided
  493. // by the Common Controls DLL. The prototypes are as follows:
  494. //
  495. // BOOL GetPrivateProfileStruct
  496. // (
  497. // LPSTR szSection,
  498. // LPSTR szKey,
  499. // LPBYTE lpStruct,
  500. // UINT uSizeStruct,
  501. // LPSTR szFile
  502. // );
  503. //
  504. // BOOL WritePrivateProfileStruct
  505. // (
  506. // LPSTR szSection,
  507. // LPSTR szKey,
  508. // LPBYTE lpStruct,
  509. // UINT uSizeStruct,
  510. // LPSTR szFile
  511. // );
  512. //
  513. // If you are building an application that is for Window for Workgroups
  514. // or newer versions of Windows, you will probably want to use the
  515. // above functions.
  516. //
  517. // Arguments:
  518. // PTSTR pszSection: Pointer to section that contains the data.
  519. //
  520. // PTSTR pszKey: Pointer to key that contains the data.
  521. //
  522. // LPBYTE pbStruct: Pointer to buffer to receive the data.
  523. //
  524. // UINT cbStruct: Number of bytes expected.
  525. //
  526. // Return (BOOL):
  527. // The return value is TRUE if the function is successful. It is FALSE
  528. // if the function fails (bad checksum, missing key, etc).
  529. //
  530. //
  531. //--------------------------------------------------------------------------;
  532. BOOL FNGLOBAL AppProfileReadBytes
  533. (
  534. PTSTR pszSection,
  535. PTSTR pszKey,
  536. LPBYTE pbStruct,
  537. UINT cbStruct
  538. )
  539. {
  540. //
  541. // note that the following works for both upper and lower case, and
  542. // will return valid values for garbage chars
  543. //
  544. #define CHAR2NIBBLE(ch) (BYTE)( ((ch) >= '0' && (ch) <= '9') ? \
  545. (BYTE)((ch) - '0') : \
  546. ((BYTE)(10 + (ch) - 'A') & (BYTE)0x0F) )
  547. TCHAR ach[APP_MAX_STRING_RC_CHARS];
  548. LPTSTR psz;
  549. LPTSTR pch;
  550. UINT cchTemp;
  551. UINT u;
  552. BOOL fAllocated;
  553. BOOL fReturn;
  554. BYTE b;
  555. BYTE bChecksum;
  556. TCHAR ch;
  557. //
  558. // add one the the number of bytes needed to accomodate the checksum
  559. // byte placed at the end by AppProfileWriteBytes...
  560. //
  561. cbStruct++;
  562. //
  563. // check if the quick buffer can be used for retrieving the input
  564. // text--if it cannot, then alloc space for it. note that there must
  565. // be space available for the null terminator (the +1 below).
  566. //
  567. fAllocated = FALSE;
  568. psz = (LPTSTR)ach;
  569. cchTemp = cbStruct * 2 + 1;
  570. if (cchTemp > SIZEOF(ach))
  571. {
  572. psz = (LPTSTR)GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  573. if (NULL == psz)
  574. return (FALSE);
  575. fAllocated = TRUE;
  576. }
  577. //
  578. // read the hex string... if it is not the correct length, then assume
  579. // error and return.
  580. //
  581. fReturn = FALSE;
  582. u = (UINT)GetPrivateProfileString(pszSection, pszKey, gszNull,
  583. psz, cchTemp, gszAppProfile);
  584. if ((cbStruct * 2) == u)
  585. {
  586. bChecksum = 0;
  587. for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  588. {
  589. ch = *pch++;
  590. b = CHAR2NIBBLE(ch) << (BYTE)4;
  591. ch = *pch++;
  592. b |= CHAR2NIBBLE(ch);
  593. //
  594. // if this is not the final byte (the checksum byte), then
  595. // store it and accumulate checksum..
  596. //
  597. if (cbStruct != 1)
  598. bChecksum += (*pbStruct = b);
  599. }
  600. //
  601. // check the last byte read against the checksum that we calculated
  602. // if they are not equal then return error...
  603. //
  604. fReturn = (bChecksum == b);
  605. }
  606. //
  607. // free the temporary buffer if one was allocated (lots of bytes!)
  608. //
  609. if (fAllocated)
  610. GlobalFreePtr(psz);
  611. return (fReturn);
  612. } // AppProfileReadBytes
  613. //==========================================================================;
  614. //
  615. // Startup and shutdown code...
  616. //
  617. //
  618. //==========================================================================;
  619. //--------------------------------------------------------------------------;
  620. //
  621. // BOOL AcmAppChooseFont
  622. //
  623. // Description:
  624. // This function lets the user choose a new font for the script window.
  625. // After a new font is chosen, the font structure is stored to the
  626. // .ini file so it can be restored on the next run of this application.
  627. //
  628. // Arguments:
  629. // HWND hwnd: Handle to main window.
  630. //
  631. // Return (BOOL):
  632. // The return value is TRUE if a new font was chosen. It is FALSE if
  633. // the user canceled the operation.
  634. //
  635. //
  636. //--------------------------------------------------------------------------;
  637. BOOL FNGLOBAL AcmAppChooseFont
  638. (
  639. HWND hwnd
  640. )
  641. {
  642. LOGFONT lf;
  643. HWND hedit;
  644. HFONT hfont;
  645. HFONT hfontNew;
  646. hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
  647. //
  648. // get the current font and pass it to the choose font dialog
  649. //
  650. hfont = GetWindowFont(hedit);
  651. hfontNew = AppChooseFont(hwnd, hfont, &lf);
  652. if (NULL == hfontNew)
  653. return (FALSE);
  654. //
  655. // select the new font into the window and delete the old one
  656. //
  657. SetWindowFont(hedit, hfontNew, TRUE);
  658. DeleteFont(hfont);
  659. ghfontApp = hfontNew;
  660. //
  661. // save the complete description of the chosen font so there can be
  662. // no strangness in the font mapping next run. this is overkill, but
  663. // it works...
  664. //
  665. AppProfileWriteBytes(gszSecConfig, gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  666. return (TRUE);
  667. } // AcmAppChooseFont()
  668. //--------------------------------------------------------------------------;
  669. //
  670. // BOOL AcmAppSettingsRestore
  671. //
  672. // Description:
  673. // This function restores state information for the application. This
  674. // function is called just after the main window is created (it has
  675. // not been ShowWindow()'d). This function will generate the call
  676. // to ShowWindow before returning.
  677. //
  678. // Arguments:
  679. // HWND hwnd: Handle to main window that has just been created but
  680. // not shown.
  681. //
  682. // int nCmdShow: The state that the application window should show as.
  683. //
  684. // Return (BOOL):
  685. // The return value is always TRUE.
  686. //
  687. //
  688. //--------------------------------------------------------------------------;
  689. BOOL FNLOCAL AcmAppSettingsRestore
  690. (
  691. HWND hwnd,
  692. int nCmdShow
  693. )
  694. {
  695. WINDOWPLACEMENT wp;
  696. LOGFONT lf;
  697. RECT rc;
  698. RECT rcWindow;
  699. POINT pt;
  700. int n;
  701. BOOL f;
  702. //
  703. // restore the previous Options state...
  704. //
  705. gfuAppOptions = GetPrivateProfileInt(gszSecConfig, gszKeyOptions,
  706. gfuAppOptions, gszAppProfile);
  707. //
  708. // restore the user's preferred font.
  709. //
  710. ghfontApp = GetStockFont(ANSI_FIXED_FONT);
  711. f = AppProfileReadBytes(gszSecConfig, gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  712. if (f)
  713. {
  714. HFONT hfont;
  715. hfont = CreateFontIndirect(&lf);
  716. if (NULL != hfont)
  717. {
  718. ghfontApp = hfont;
  719. }
  720. }
  721. SetWindowFont(GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY), ghfontApp, FALSE);
  722. //
  723. //
  724. //
  725. GetPrivateProfileString(gszSecConfig, gszKeyInitialDirOpen, gszNull,
  726. gszInitialDirOpen, SIZEOF(gszInitialDirOpen),
  727. gszAppProfile);
  728. GetPrivateProfileString(gszSecConfig, gszKeyInitialDirSave, gszNull,
  729. gszInitialDirSave, SIZEOF(gszInitialDirSave),
  730. gszAppProfile);
  731. GetPrivateProfileString(gszSecConfig, gszKeyLastSaveFile, gszNull,
  732. gszLastSaveFile, SIZEOF(gszLastSaveFile),
  733. gszAppProfile);
  734. //
  735. // grab the stored window position and size from the .ini file...
  736. // there must be four arguments stored or the entry is considered
  737. // invalid.
  738. //
  739. f = AppProfileReadBytes(gszSecConfig, gszKeyWindow,
  740. (LPBYTE)&rcWindow, sizeof(rcWindow));
  741. if (f)
  742. {
  743. //
  744. // to make sure the user can always get at the window, check to
  745. // see if the midpoint of the caption is visible--if it is not,
  746. // then default to the default position used when creating the
  747. // window.
  748. //
  749. n = (rcWindow.right - rcWindow.left) / 2;
  750. pt.x = (n + rcWindow.left);
  751. n = GetSystemMetrics(SM_CYCAPTION) / 2 + GetSystemMetrics(SM_CXFRAME);
  752. pt.y = (n + rcWindow.top);
  753. GetWindowRect(GetDesktopWindow(), &rc);
  754. if (PtInRect(&rc, pt))
  755. {
  756. //
  757. // fill out the window placement structure--default the
  758. // maximized and minimized states to default placement by
  759. // getting its current placement.
  760. //
  761. wp.length = sizeof(wp);
  762. GetWindowPlacement(hwnd, &wp);
  763. wp.showCmd = nCmdShow;
  764. #if 0
  765. wp.rcNormalPosition = rcWindow;
  766. #else
  767. n = rcWindow.right - rcWindow.left;
  768. wp.rcNormalPosition.right = wp.rcNormalPosition.left + n;
  769. n = rcWindow.bottom - rcWindow.top;
  770. wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + n;
  771. #endif
  772. SetWindowPlacement(hwnd, &wp);
  773. return (TRUE);
  774. }
  775. }
  776. //
  777. // show defaulted and succeed
  778. //
  779. ShowWindow(hwnd, nCmdShow);
  780. return (TRUE);
  781. } // AcmAppSettingsRestore()
  782. //--------------------------------------------------------------------------;
  783. //
  784. // BOOL AcmAppSettingsSave
  785. //
  786. // Description:
  787. // This function saves the current state information for the application.
  788. // It is called just before the main window is closed (destroyed); or
  789. // as Windows is exiting (query end session).
  790. //
  791. // Note that this function should not destroy any resources--it can
  792. // be called at any time to save a snapshot of the application state.
  793. //
  794. // Arguments:
  795. // HWND hwnd: Handle to main window that will be destroyed shortly.
  796. //
  797. // Return (BOOL):
  798. // The return value is always TRUE.
  799. //
  800. //
  801. //--------------------------------------------------------------------------;
  802. BOOL FNLOCAL AcmAppSettingsSave
  803. (
  804. HWND hwnd
  805. )
  806. {
  807. TCHAR ach[APP_MAX_STRING_RC_CHARS];
  808. WINDOWPLACEMENT wp;
  809. PRECT prc;
  810. BOOL f;
  811. //
  812. // save the current option settings--note that we ALWAYS turn off the
  813. // debug logging option so the app doesn't try to OutputDebugString
  814. // unexpectedly during the next session...
  815. //
  816. gfuAppOptions &= ~APP_OPTIONSF_DEBUGLOG;
  817. if (GetPrivateProfileInt(gszSecConfig, gszKeyOptions, 0, gszAppProfile) != gfuAppOptions)
  818. {
  819. wsprintf(ach, gszFormatOptions, gfuAppOptions);
  820. WritePrivateProfileString(gszSecConfig, gszKeyOptions, ach, gszAppProfile);
  821. }
  822. //
  823. //
  824. //
  825. //
  826. WritePrivateProfileString(gszSecConfig, gszKeyInitialDirOpen,
  827. gszInitialDirOpen, gszAppProfile);
  828. WritePrivateProfileString(gszSecConfig, gszKeyInitialDirSave,
  829. gszInitialDirSave, gszAppProfile);
  830. WritePrivateProfileString(gszSecConfig, gszKeyLastSaveFile,
  831. gszLastSaveFile, gszAppProfile);
  832. //
  833. // save the current window placement--only store the size and location
  834. // of the restored window. maximized and minimized states should
  835. // remain defaulted on the next invocation of this application.
  836. //
  837. wp.length = sizeof(wp);
  838. f = GetWindowPlacement(hwnd, &wp);
  839. if (f)
  840. {
  841. prc = &wp.rcNormalPosition;
  842. //
  843. // save the _bounding rectangle_ of the restored window state...
  844. //
  845. AppProfileWriteBytes(gszSecConfig, gszKeyWindow, (LPBYTE)prc, sizeof(*prc));
  846. }
  847. //
  848. // succeed
  849. //
  850. return (TRUE);
  851. } // AcmAppSettingsSave()
  852. //--------------------------------------------------------------------------;
  853. //
  854. // BOOL AcmAppShutdown
  855. //
  856. // Description:
  857. // This function is called to gracefully shut down the application.
  858. // If the application should not be closed, a FALSE value is returned.
  859. // This function is called for WM_CLOSE and WM_QUERYENDSESSION
  860. // messages...
  861. //
  862. // Arguments:
  863. // HWND hwnd: Handle to main window.
  864. //
  865. // PACMAPPFILEDESC paafd: Pointer to current file description.
  866. //
  867. // Return (BOOL):
  868. // Returns TRUE if the application can proceed with close. Returns
  869. // FALSE if the application should NOT be closed.
  870. //
  871. //
  872. //--------------------------------------------------------------------------;
  873. BOOL FNGLOBAL AcmAppShutdown
  874. (
  875. HWND hwnd,
  876. PACMAPPFILEDESC paafd
  877. )
  878. {
  879. BOOL f;
  880. //
  881. // check if the script has been modified without saving. if the user
  882. // cancels the operation, then we will NOT close the application.
  883. //
  884. f = AcmAppFileSaveModified(hwnd, paafd);
  885. if (!f)
  886. return (FALSE);
  887. //
  888. //
  889. //
  890. if (NULL != ghadidNotify)
  891. {
  892. acmDriverRemove(ghadidNotify, 0L);
  893. ghadidNotify = NULL;
  894. }
  895. //
  896. // save any settings that should be saved on app termination...
  897. //
  898. AcmAppSettingsSave(hwnd);
  899. //
  900. // allow closing of application...
  901. //
  902. return (TRUE);
  903. } // AcmAppShutdown()
  904. //--------------------------------------------------------------------------;
  905. //
  906. // BOOL AcmAppInit
  907. //
  908. // Description:
  909. //
  910. //
  911. // Arguments:
  912. //
  913. //
  914. // Return (BOOL):
  915. //
  916. //
  917. //--------------------------------------------------------------------------;
  918. BOOL FNLOCAL AcmAppInit
  919. (
  920. HWND hwnd,
  921. PACMAPPFILEDESC paafd,
  922. LPTSTR pszCmdLine,
  923. int nCmdShow
  924. )
  925. {
  926. BOOL f;
  927. DWORD dwVersion;
  928. //
  929. // !!! VERY IMPORTANT !!!
  930. //
  931. // the ACM may or may not be installed. this application is using
  932. // the ACMTHUNK.C file to dynamically link to the ACM. if the
  933. // acmThunkInitialize() API fails, then the ACM is *NOT* installed
  934. // and none of the API's should be used.
  935. //
  936. // if the ACM *is* installed, then the version MUST be at least
  937. // V2.00 for the API's to be available (earlier versions do not
  938. // supply the API we need).
  939. //
  940. acmThunkInitialize();
  941. dwVersion = acmGetVersion();
  942. if (0x0200 <= HIWORD(dwVersion))
  943. {
  944. MMRESULT mmr;
  945. gfAcmAvailable = TRUE;
  946. mmr = acmDriverAdd(&ghadidNotify,
  947. ghinst,
  948. (LPARAM)(UINT)hwnd,
  949. WM_ACMAPP_ACM_NOTIFY,
  950. ACM_DRIVERADDF_NOTIFYHWND);
  951. if (MMSYSERR_NOERROR != mmr)
  952. {
  953. DPF(0, "!AppCreate: acmDriverAdd failed to add notify window! mmr=%u", mmr);
  954. }
  955. }
  956. else
  957. {
  958. if (0L == dwVersion)
  959. {
  960. AppMsgBoxId(NULL, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  961. IDS_ERROR_ACM_NOT_PRESENT);
  962. }
  963. else
  964. {
  965. AppMsgBoxId(NULL, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  966. IDS_ERROR_ACM_TOO_OLD,
  967. HIWORD(dwVersion) >> 8,
  968. HIWORD(dwVersion) & 0x00FF);
  969. }
  970. gfAcmAvailable = FALSE;
  971. }
  972. //
  973. //
  974. //
  975. AcmAppSettingsRestore(hwnd, nCmdShow);
  976. //
  977. // strip the command line..
  978. //
  979. if (NULL != pszCmdLine)
  980. {
  981. while (('\0' != *pszCmdLine) && (' ' == *pszCmdLine))
  982. pszCmdLine++;
  983. }
  984. //
  985. // if there is a command line, assume it is a filename for a script
  986. // and try to open it. otherwise, just initialize the script window.
  987. //
  988. if ((NULL != pszCmdLine) && ('\0' != *pszCmdLine))
  989. {
  990. //
  991. // attempt to open the specified file..
  992. //
  993. lstrcpy(paafd->szFilePath, pszCmdLine);
  994. f = AcmAppFileOpen(hwnd, paafd);
  995. if (f)
  996. {
  997. AppTitle(hwnd, paafd->szFileTitle);
  998. AcmAppDisplayFileProperties(hwnd, paafd);
  999. }
  1000. else
  1001. {
  1002. //
  1003. // opening the command line file was untriumphant..
  1004. //
  1005. AppMsgBoxId(hwnd, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1006. IDS_ERROR_OPEN_FAILED, (LPSTR)paafd->szFilePath);
  1007. paafd->szFilePath[0] = '\0';
  1008. paafd->szFileTitle[0] = '\0';
  1009. AppFileNew(hwnd, paafd, FALSE);
  1010. }
  1011. }
  1012. else
  1013. {
  1014. AppFileNew(hwnd, paafd, FALSE);
  1015. }
  1016. return (TRUE);
  1017. } // AcmAppInit()
  1018. //--------------------------------------------------------------------------;
  1019. //
  1020. // BOOL AcmAppExit
  1021. //
  1022. // Description:
  1023. //
  1024. //
  1025. // Arguments:
  1026. //
  1027. //
  1028. // Return (BOOL):
  1029. //
  1030. //
  1031. //
  1032. //--------------------------------------------------------------------------;
  1033. BOOL FNGLOBAL AcmAppExit
  1034. (
  1035. void
  1036. )
  1037. {
  1038. acmThunkTerminate();
  1039. return (TRUE);
  1040. } // AcmAppExit()
  1041. //==========================================================================;
  1042. //
  1043. // Initialization and exit code...
  1044. //
  1045. //
  1046. //==========================================================================;
  1047. //--------------------------------------------------------------------------;
  1048. //
  1049. // BOOL AppRegisterPenApp
  1050. //
  1051. // Description:
  1052. // This function is used to register and de-register an application
  1053. // as being 'Pen Enhanced.' If the Windows installation is Pen enabled
  1054. // then this function allows the RC Manager to replace all 'Edit'
  1055. // controls with 'HEdit' controls.
  1056. //
  1057. // This function must be called to register the application BEFORE
  1058. // creating any edit controls.
  1059. //
  1060. // Arguments:
  1061. // BOOL fRegister: If this argument is TRUE, the app is registered
  1062. // with the RC Manager as being Pen aware. If this argument is FALSE
  1063. // the app is de-registered.
  1064. //
  1065. // Return (BOOL):
  1066. // The return value is TRUE if Windows for Pen Computing is installed
  1067. // on the system. The return value is FALSE if the Windows installation
  1068. // is not Pen enabled.
  1069. //
  1070. //
  1071. //--------------------------------------------------------------------------;
  1072. BOOL FNLOCAL AppRegisterPenApp
  1073. (
  1074. BOOL fRegister
  1075. )
  1076. {
  1077. #define RPA_DEFAULT 0x0001
  1078. typedef void (FAR PASCAL *PENWINREGISTERPROC)(UINT, BOOL);
  1079. static char szRegPenApp[] = "RegisterPenApp";
  1080. static PENWINREGISTERPROC pfnRegPenApp = NULL;
  1081. HINSTANCE hinstPenWin;
  1082. //
  1083. // check if Windows for Pen Computing is installed--and if it is,
  1084. // dyna-link to the RegisterPenApp() function.
  1085. //
  1086. // if Pens are not supported, then return FALSE.
  1087. //
  1088. if (NULL == pfnRegPenApp)
  1089. {
  1090. hinstPenWin = (HINSTANCE)GetSystemMetrics(SM_PENWINDOWS);
  1091. if (NULL == hinstPenWin)
  1092. return (FALSE);
  1093. pfnRegPenApp = (PENWINREGISTERPROC)GetProcAddress(hinstPenWin, szRegPenApp);
  1094. if (NULL == pfnRegPenApp)
  1095. return (FALSE);
  1096. }
  1097. //
  1098. // either enable or disable the RC Manager's Pen meathooks..
  1099. //
  1100. (*pfnRegPenApp)(RPA_DEFAULT, fRegister);
  1101. return (TRUE);
  1102. } // AppRegisterPenApp()
  1103. //--------------------------------------------------------------------------;
  1104. //
  1105. // LRESULT AppCreate
  1106. //
  1107. // Description:
  1108. // This function is called to handle the WM_CREATE message for the
  1109. // applications window. The application should finish the creation
  1110. // of the window (create controls, allocate resources, etc). The
  1111. // window has not been displayed (CreateWindow[Ex] has not returned).
  1112. //
  1113. // Arguments:
  1114. // HWND hwnd: Handle to the window that is in the process of being
  1115. // created.
  1116. //
  1117. // LPCREATESTRUCT pcs: Pointer to a CREATESTRUCT that contains info
  1118. // about the window being created.
  1119. //
  1120. // Return (LRESULT):
  1121. // The return value should be nonzero if the application wishes to
  1122. // let the window finish being created. A return of zero tells
  1123. // CreateWindow[Ex] to fail the creation of the window.
  1124. //
  1125. //
  1126. //--------------------------------------------------------------------------;
  1127. LRESULT FNGLOBAL AppCreate
  1128. (
  1129. HWND hwnd,
  1130. LPCREATESTRUCT pcs
  1131. )
  1132. {
  1133. static TCHAR szEdit[] = TEXT("edit");
  1134. HWND hedit;
  1135. DPF(1, "AppCreate(hwnd=%Xh, cs.x=%d, cs.y=%d, cs.cx=%d, cs.cy=%d)",
  1136. hwnd, pcs->x, pcs->y, pcs->cx, pcs->cy);
  1137. //
  1138. // create the driver selection listbox
  1139. //
  1140. hedit = CreateWindow(szEdit, gszNull,
  1141. ES_LEFT | ES_MULTILINE | WS_TABSTOP |
  1142. ES_AUTOVSCROLL | ES_AUTOHSCROLL |
  1143. ES_NOHIDESEL | WS_BORDER | WS_VSCROLL | WS_HSCROLL |
  1144. WS_VISIBLE | WS_CHILD | ES_READONLY,
  1145. 0, 0, 0, 0, hwnd, (HMENU)IDD_ACMAPP_EDIT_DISPLAY,
  1146. pcs->hInstance, NULL);
  1147. if (NULL == hedit)
  1148. return (0L);
  1149. //
  1150. // return nonzero to succeed the creation of the window
  1151. //
  1152. return (1L);
  1153. } // AppCreate()
  1154. //--------------------------------------------------------------------------;
  1155. //
  1156. // LRESULT AppQueryEndSession
  1157. //
  1158. // Description:
  1159. // This function handles the WM_QUERYENDSESSION. This message is sent
  1160. // by USER when ExitWindows has been called to end the Windows session.
  1161. // This function can stop Windows from exiting if it is not convenient
  1162. // for Windows to end.
  1163. //
  1164. // Giving the user the option to save modified data before continueing
  1165. // with the shutdown of Windows is a good idea.
  1166. //
  1167. // Telling Windows to continue with the exit procedure does not
  1168. // necessarily mean Windows will exit. All applications are queried
  1169. // for shutdown approval. When the actual decision is made on whether
  1170. // Windows will exit, WM_ENDSESSION will be sent with the result.
  1171. //
  1172. // Arguments:
  1173. // HWND hwnd: Handle to window that received the message.
  1174. //
  1175. // Return (LRESULT):
  1176. // Returns zero to STOP Windows from exiting. Returns non-zero to
  1177. // allows windows to shut down.
  1178. //
  1179. //
  1180. //--------------------------------------------------------------------------;
  1181. LRESULT FNGLOBAL AppQueryEndSession
  1182. (
  1183. HWND hwnd
  1184. )
  1185. {
  1186. BOOL f;
  1187. DPF(1, "AppQueryEndSession(hwnd=%Xh)", hwnd);
  1188. //
  1189. // attempt to shut down--if this fails (user canceled it, etc) then
  1190. // do NOT allow the Windows to exit.
  1191. //
  1192. f = AcmAppShutdown(hwnd, &gaafd);
  1193. if (!f)
  1194. return (0L);
  1195. //
  1196. // tell Windows to proceed with the shutdown process!
  1197. //
  1198. return (1L);
  1199. } // AppQueryEndSession()
  1200. //--------------------------------------------------------------------------;
  1201. //
  1202. // LRESULT AppEndSession
  1203. //
  1204. // Description:
  1205. // This function is called to handle the WM_ENDSESSION message. This
  1206. // message is generated after the application answers the
  1207. // WM_QUERYENDSESSION message. The purpose of the WM_ENDSESSION
  1208. // message is to tell the application if Windows will be exiting
  1209. // (TRUE == fEndSession) or the end session was canceled by an
  1210. // application (FALSE == fEndSession).
  1211. //
  1212. // Arguments:
  1213. // HWND hwnd: Handle to window that received the message.
  1214. //
  1215. // BOOL fEndSession: TRUE if Windows is exiting. FALSE if the end
  1216. // session was canceled.
  1217. //
  1218. // Return (LRESULT):
  1219. // Returns zero if the message is processed. Note that an application
  1220. // cannot halt the termination of Windows from this message--the
  1221. // WM_QUERYENDSESSION is the only message that allows that behaviour.
  1222. // If fEndSession is TRUE, Windows *WILL* exit--whether you like it
  1223. // or not.
  1224. //
  1225. //
  1226. //--------------------------------------------------------------------------;
  1227. LRESULT FNGLOBAL AppEndSession
  1228. (
  1229. HWND hwnd,
  1230. BOOL fEndSession
  1231. )
  1232. {
  1233. DPF(1, "AppEndSession(hwnd=%Xh, fEndSession=%d)", hwnd, fEndSession);
  1234. //
  1235. // we processed the message, return zero..
  1236. //
  1237. return (0L);
  1238. } // AppEndSession()
  1239. //--------------------------------------------------------------------------;
  1240. //
  1241. // LRESULT AppClose
  1242. //
  1243. // Description:
  1244. // This function handles the WM_CLOSE message for the application.
  1245. // If the application should close, DestroyWindow() must be called
  1246. // by this function. Otherwise the application will not close.
  1247. //
  1248. // Arguments:
  1249. // HWND hwnd: Handle to window that generated the WM_CLOSE message.
  1250. //
  1251. // Return (LRESULT):
  1252. // There return value is zero. The DestroyWindow function will have
  1253. // been called if the application should actually close.
  1254. //
  1255. //--------------------------------------------------------------------------;
  1256. LRESULT FNGLOBAL AppClose
  1257. (
  1258. HWND hwnd
  1259. )
  1260. {
  1261. HWND hedit;
  1262. HFONT hfont;
  1263. BOOL f;
  1264. //
  1265. // if the Shift key is held down during the close message, then just
  1266. // save the current state but don't destroy the window... this is
  1267. // useful if the user does not want to exit the app and rerun it
  1268. // to make sure the state is saved--just before the user does something
  1269. // that may crash Windows or something..
  1270. //
  1271. if (GetKeyState(VK_SHIFT) < 0)
  1272. {
  1273. //
  1274. // save any settings that should be saved on app termination...
  1275. //
  1276. AcmAppSettingsSave(hwnd);
  1277. return (0L);
  1278. }
  1279. //
  1280. // attempt to shut down--if this fails (user canceled it, etc) then
  1281. // do NOT allow the window to be destroyed.
  1282. //
  1283. f = AcmAppShutdown(hwnd, &gaafd);
  1284. if (!f)
  1285. return (0L);
  1286. //
  1287. // destroy the font we are using... before deleting the font, select
  1288. // the system font back into the window so the font won't be 'in use'
  1289. // anymore.
  1290. //
  1291. hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
  1292. hfont = GetWindowFont(hedit);
  1293. SetWindowFont(hedit, NULL, FALSE);
  1294. DeleteFont(hfont);
  1295. ghfontApp = NULL;
  1296. //
  1297. // make the window close and terminate the application
  1298. //
  1299. DestroyWindow(hwnd);
  1300. return (0L);
  1301. } // AppClose()
  1302. //--------------------------------------------------------------------------;
  1303. //
  1304. // BOOL AppInit
  1305. //
  1306. // Description:
  1307. // This function is called to initialize a new instance of the
  1308. // application. We want to parse our command line, create our window,
  1309. // allocate resources, etc.
  1310. //
  1311. // The arguments passed to this function are exactly the same as
  1312. // those passed to WinMain.
  1313. //
  1314. // Arguments:
  1315. // HINSTANCE hinst: Identifies the current instance of the
  1316. // application.
  1317. //
  1318. // HINSTANCE hinstPrev: Identifies the previous instance of the
  1319. // application (NULL if first instance). For Win 32, this argument
  1320. // is _always_ NULL.
  1321. //
  1322. // LPTSTR pszCmdLine: Points to null-terminated unparsed command line.
  1323. // If the application is compiled for Unicode, then this argument is
  1324. // ignored.
  1325. //
  1326. // int nCmdShow: How the main window for the application is to be
  1327. // shown by default.
  1328. //
  1329. // Return (HWND):
  1330. // Returns the newly created handle to the applications main window.
  1331. // This handle is NULL if something went wrong and tells the application
  1332. // to exit immediately.
  1333. //
  1334. //
  1335. //--------------------------------------------------------------------------;
  1336. HWND FNGLOBAL AppInit
  1337. (
  1338. HINSTANCE hinst,
  1339. HINSTANCE hinstPrev,
  1340. LPTSTR pszCmdLine,
  1341. int nCmdShow
  1342. )
  1343. {
  1344. HWND hwnd;
  1345. WNDCLASS wc;
  1346. DPF(1, "AppInit(hinst=%Xh, hinstPrev=%Xh, pszCmdLine='%s', nCmdShow=%d)",
  1347. hinst, hinstPrev, pszCmdLine, nCmdShow);
  1348. LoadString(hinst, IDS_APP_NAME, gszAppName, SIZEOF(gszAppName));
  1349. LoadString(hinst, IDS_FILE_UNTITLED, gszFileUntitled, SIZEOF(gszFileUntitled));
  1350. //
  1351. // determine whether a new window class needs to be registered for
  1352. // this application. for Win 16, this only needs to be done for the
  1353. // first instance of the application created. for Win 32, this must
  1354. // be done for EVERY instance of the application.
  1355. //
  1356. if (NULL == hinstPrev)
  1357. {
  1358. wc.style = CS_HREDRAW | CS_VREDRAW;
  1359. wc.lpfnWndProc = (WNDPROC)AppWndProc;
  1360. wc.cbClsExtra = 0;
  1361. wc.cbWndExtra = 0;
  1362. wc.hInstance = hinst;
  1363. wc.hIcon = LoadIcon(hinst, ICON_APP);
  1364. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  1365. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  1366. wc.lpszMenuName = MENU_APP;
  1367. wc.lpszClassName = gszAppName;
  1368. if (!RegisterClass(&wc))
  1369. return (NULL);
  1370. }
  1371. //
  1372. // if Windows for Pen Computing is installed, then allow the RC
  1373. // Manager to replace all edit controls created from this point on
  1374. // with hedit controls
  1375. //
  1376. AppRegisterPenApp(TRUE);
  1377. //
  1378. // create the application's main window
  1379. //
  1380. // style bits available:
  1381. // WS_EX_ACCEPTFILES : will receive WM_DROPFILES messages
  1382. // WS_EX_DLGMODALFRAME : creates window with double border
  1383. // WS_EX_NOPARENTNOTIFY: won't receive WM_PARENTNOTIFY messages
  1384. // WS_EX_TOPMOST : puts window in topmost space
  1385. // WS_EX_TRANSPARENT : a very bizarre style indeed (Win 16 only)
  1386. //
  1387. hwnd = CreateWindowEx(WS_EX_ACCEPTFILES | WS_EX_NOPARENTNOTIFY,
  1388. gszAppName,
  1389. gszAppName,
  1390. WS_OVERLAPPEDWINDOW,
  1391. APP_WINDOW_XOFFSET,
  1392. APP_WINDOW_YOFFSET,
  1393. APP_WINDOW_WIDTH,
  1394. APP_WINDOW_HEIGHT,
  1395. NULL,
  1396. NULL,
  1397. hinst,
  1398. NULL);
  1399. if (NULL == hwnd)
  1400. return (NULL);
  1401. #ifdef UNICODE
  1402. //
  1403. // GetCommandLine() returns a pointer to our command line. but this
  1404. // command line includes the complete command line used to launch
  1405. // the application--which is different than the pszCmdLine argument
  1406. // passed through WinMain()...
  1407. //
  1408. // so, skip over the command name to get to the argument string
  1409. //
  1410. pszCmdLine = GetCommandLine();
  1411. if (NULL != pszCmdLine)
  1412. {
  1413. while (('\0' != *pszCmdLine) && (' ' != *pszCmdLine++))
  1414. ;
  1415. }
  1416. #endif
  1417. //
  1418. //
  1419. //
  1420. //
  1421. AcmAppInit(hwnd, &gaafd, pszCmdLine, nCmdShow);
  1422. //
  1423. // finally, get the window displayed and return success
  1424. //
  1425. // the ShowWindow call is made during AcmAppInit
  1426. //
  1427. // ShowWindow(hwnd, nCmdShow);
  1428. // UpdateWindow(hwnd);
  1429. return (hwnd);
  1430. } // AppInit()
  1431. //--------------------------------------------------------------------------;
  1432. //
  1433. // int AppExit
  1434. //
  1435. // Description:
  1436. // This function is called just before the application exits from
  1437. // WinMain. Its purpose is to clean up any resources that were allocated
  1438. // for running the application: brushes, heaps, etc..
  1439. //
  1440. // Arguments:
  1441. // HINSTANCE hinst: Identifies the current instance of the
  1442. // application that is exiting.
  1443. //
  1444. // int nResult: The result of the WM_QUIT message (in wParam of the
  1445. // MSG structure. This argument will usually be 0 (even if the message
  1446. // loop was never entered).
  1447. //
  1448. // Return (int):
  1449. // The return value is usually nResult--be we give this function the
  1450. // opportunity to modify its value.
  1451. //
  1452. //
  1453. //--------------------------------------------------------------------------;
  1454. int FNGLOBAL AppExit
  1455. (
  1456. HINSTANCE hinst,
  1457. int nResult
  1458. )
  1459. {
  1460. DPF(1, "AppExit(hinst=%Xh, nResult=%d)", hinst, nResult);
  1461. AcmAppExit();
  1462. //
  1463. // if Windows for Pen Computing is installed, then de-register the
  1464. // application so the RC Manager knows we will no longer need its
  1465. // services...
  1466. //
  1467. AppRegisterPenApp(FALSE);
  1468. return (nResult);
  1469. } // AppExit()
  1470. //==========================================================================;
  1471. //
  1472. // Misc rarely used application dialogs and stuff...
  1473. //
  1474. //
  1475. //==========================================================================;
  1476. //--------------------------------------------------------------------------;
  1477. //
  1478. // BOOL AboutDlgProc
  1479. //
  1480. // Description:
  1481. // This dialog procedure is used for the ubiquitous about box.
  1482. //
  1483. // Arguments:
  1484. // HWND hwnd: Handle to window.
  1485. //
  1486. // UINT uMsg: Message being sent to the window.
  1487. //
  1488. // WPARAM wParam: Specific argument to message.
  1489. //
  1490. // LPARAM lParam: Specific argument to message.
  1491. //
  1492. // Return (BOOL):
  1493. // The return value is specific to the message that was received. For
  1494. // the most part, it is FALSE if this dialog procedure does not handle
  1495. // a message.
  1496. //
  1497. //
  1498. //--------------------------------------------------------------------------;
  1499. BOOL FNEXPORT AboutDlgProc
  1500. (
  1501. HWND hwnd,
  1502. UINT uMsg,
  1503. WPARAM wParam,
  1504. LPARAM lParam
  1505. )
  1506. {
  1507. HWND hwndT;
  1508. PTSTR pach;
  1509. UINT u;
  1510. switch (uMsg)
  1511. {
  1512. case WM_INITDIALOG:
  1513. //
  1514. // display some OS version information
  1515. //
  1516. //
  1517. pach = (PTSTR)LocalAlloc(LPTR, APP_MAX_STRING_RC_BYTES);
  1518. if (NULL == pach)
  1519. return (TRUE);
  1520. AppGetWindowsVersion(pach, NULL);
  1521. hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_OS);
  1522. SetWindowText(hwndT, pach);
  1523. AppGetWindowsVersion(NULL, pach);
  1524. hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_PLATFORM);
  1525. SetWindowText(hwndT, pach);
  1526. LocalFree((HLOCAL)pach);
  1527. return (TRUE);
  1528. case WM_COMMAND:
  1529. u = GET_WM_COMMAND_ID(wParam, lParam);
  1530. if ((IDOK == u) || (IDCANCEL == u))
  1531. {
  1532. EndDialog(hwnd, (IDOK == u));
  1533. }
  1534. break;
  1535. }
  1536. return (FALSE);
  1537. } // AboutDlgProc()