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.

680 lines
22 KiB

  1. //THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. //ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright 1994-1996 Microsoft Corporation. All Rights Reserved.
  7. //
  8. // PROGRAM: Generic.c
  9. //
  10. // PURPOSE: Illustrates the 'minimum' functionality of a well-behaved Win32 application..
  11. //
  12. // PLATFORMS: Windows 95, Windows NT, Win32s
  13. //
  14. // FUNCTIONS:
  15. // WinMain() - calls initialization function, processes message loop
  16. // InitApplication() - Initializes window data nd registers window
  17. // InitInstance() -saves instance handle and creates main window
  18. // WindProc() Processes messages
  19. // About() - Process menssages for "About" dialog box
  20. // MyRegisterClass() - Registers the application's window class
  21. // CenterWindow() - Centers one window over another
  22. //
  23. // SPECIAL INSTRUCTIONS: N/A
  24. //
  25. #define APPNAME "Generic"
  26. // Windows Header Files:
  27. #include <windows.h>
  28. // C RunTime Header Files
  29. #include <stdlib.h>
  30. #include <malloc.h>
  31. #include <memory.h>
  32. // Local Header Files
  33. #include "generic.h"
  34. // Makes it easier to determine appropriate code paths:
  35. #if defined (WIN32)
  36. #define IS_WIN32 TRUE
  37. #else
  38. #define IS_WIN32 FALSE
  39. #endif
  40. #define IS_NT IS_WIN32 && (BOOL)(GetVersion() < 0x80000000)
  41. #define IS_WIN32S IS_WIN32 && (BOOL)(!(IS_NT) && (LOBYTE(LOWORD(GetVersion()))<4))
  42. #define IS_WIN95 (BOOL)(!(IS_NT) && !(IS_WIN32S)) && IS_WIN32
  43. // Global Variables:
  44. HINSTANCE hInst; // current instance
  45. char szAppName[100]; // Name of the app
  46. char szTitle[100]; // The title bar text
  47. // Foward declarations of functions included in this code module:
  48. ATOM MyRegisterClass(CONST WNDCLASS*);
  49. BOOL InitApplication(HINSTANCE);
  50. BOOL InitInstance(HINSTANCE, int);
  51. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  52. LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  53. BOOL CenterWindow (HWND, HWND);
  54. LPTSTR GetStringRes (int id);
  55. //
  56. // FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  57. //
  58. // PURPOSE: Entry point for the application.
  59. //
  60. // COMMENTS:
  61. //
  62. // This function initializes the application and processes the
  63. // message loop.
  64. //
  65. int APIENTRY WinMain(HINSTANCE hInstance,
  66. HINSTANCE hPrevInstance,
  67. LPSTR lpCmdLine,
  68. int nCmdShow)
  69. {
  70. MSG msg;
  71. HANDLE hAccelTable;
  72. // Initialize global strings
  73. lstrcpy (szAppName, APPNAME);
  74. LoadString (hInstance, IDS_APP_TITLE, szTitle, 100);
  75. if (!hPrevInstance) {
  76. // Perform instance initialization:
  77. if (!InitApplication(hInstance)) {
  78. return (FALSE);
  79. }
  80. }
  81. // Perform application initialization:
  82. if (!InitInstance(hInstance, nCmdShow)) {
  83. return (FALSE);
  84. }
  85. hAccelTable = LoadAccelerators (hInstance, szAppName);
  86. // Main message loop:
  87. while (GetMessage(&msg, NULL, 0, 0)) {
  88. if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
  89. TranslateMessage(&msg);
  90. DispatchMessage(&msg);
  91. }
  92. }
  93. return (msg.wParam);
  94. lpCmdLine; // This will prevent 'unused formal parameter' warnings
  95. }
  96. //
  97. // FUNCTION: MyRegisterClass(CONST WNDCLASS*)
  98. //
  99. // PURPOSE: Registers the window class.
  100. //
  101. // COMMENTS:
  102. //
  103. // This function and its usage is only necessary if you want this code
  104. // to be compatible with Win32 systems prior to the 'RegisterClassEx'
  105. // function that was added to Windows 95. It is important to call this function
  106. // so that the application will get 'well formed' small icons associated
  107. // with it.
  108. //
  109. ATOM MyRegisterClass(CONST WNDCLASS *lpwc)
  110. {
  111. HANDLE hMod;
  112. FARPROC proc;
  113. WNDCLASSEX wcex;
  114. hMod = GetModuleHandle ("USER32");
  115. if (hMod != NULL) {
  116. #if defined (UNICODE)
  117. proc = GetProcAddress (hMod, "RegisterClassExW");
  118. #else
  119. proc = GetProcAddress (hMod, "RegisterClassExA");
  120. #endif
  121. if (proc != NULL) {
  122. wcex.style = lpwc->style;
  123. wcex.lpfnWndProc = lpwc->lpfnWndProc;
  124. wcex.cbClsExtra = lpwc->cbClsExtra;
  125. wcex.cbWndExtra = lpwc->cbWndExtra;
  126. wcex.hInstance = lpwc->hInstance;
  127. wcex.hIcon = lpwc->hIcon;
  128. wcex.hCursor = lpwc->hCursor;
  129. wcex.hbrBackground = lpwc->hbrBackground;
  130. wcex.lpszMenuName = lpwc->lpszMenuName;
  131. wcex.lpszClassName = lpwc->lpszClassName;
  132. // Added elements for Windows 95:
  133. wcex.cbSize = sizeof(WNDCLASSEX);
  134. wcex.hIconSm = LoadIcon(wcex.hInstance, "SMALL");
  135. return (*proc)(&wcex);//return RegisterClassEx(&wcex);
  136. }
  137. }
  138. return (RegisterClass(lpwc));
  139. }
  140. //
  141. // FUNCTION: InitApplication(HANDLE)
  142. //
  143. // PURPOSE: Initializes window data and registers window class
  144. //
  145. // COMMENTS:
  146. //
  147. // In this function, we initialize a window class by filling out a data
  148. // structure of type WNDCLASS and calling either RegisterClass or
  149. // the internal MyRegisterClass.
  150. //
  151. BOOL InitApplication(HINSTANCE hInstance)
  152. {
  153. WNDCLASS wc;
  154. HWND hwnd;
  155. // Win32 will always set hPrevInstance to NULL, so lets check
  156. // things a little closer. This is because we only want a single
  157. // version of this app to run at a time
  158. hwnd = FindWindow (szAppName, szTitle);
  159. if (hwnd) {
  160. // We found another version of ourself. Lets defer to it:
  161. if (IsIconic(hwnd)) {
  162. ShowWindow(hwnd, SW_RESTORE);
  163. }
  164. SetForegroundWindow (hwnd);
  165. // If this app actually had any functionality, we would
  166. // also want to communicate any action that our 'twin'
  167. // should now perform based on how the user tried to
  168. // execute us.
  169. return FALSE;
  170. }
  171. // Fill in window class structure with parameters that describe
  172. // the main window.
  173. wc.style = CS_HREDRAW | CS_VREDRAW;
  174. wc.lpfnWndProc = (WNDPROC)WndProc;
  175. wc.cbClsExtra = 0;
  176. wc.cbWndExtra = 0;
  177. wc.hInstance = hInstance;
  178. wc.hIcon = LoadIcon (hInstance, szAppName);
  179. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  180. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  181. // Since Windows95 has a slightly different recommended
  182. // format for the 'Help' menu, lets put this in the alternate menu like this:
  183. if (IS_WIN95) {
  184. wc.lpszMenuName = "WIN95";
  185. } else {
  186. wc.lpszMenuName = szAppName;
  187. }
  188. wc.lpszClassName = szAppName;
  189. // Register the window class and return success/failure code.
  190. if (IS_WIN95) {
  191. return MyRegisterClass(&wc);
  192. } else {
  193. return RegisterClass(&wc);
  194. }
  195. }
  196. //
  197. // FUNCTION: InitInstance(HANDLE, int)
  198. //
  199. // PURPOSE: Saves instance handle and creates main window
  200. //
  201. // COMMENTS:
  202. //
  203. // In this function, we save the instance handle in a global variable and
  204. // create and display the main program window.
  205. //
  206. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  207. {
  208. HWND hWnd;
  209. hInst = hInstance; // Store instance handle in our global variable
  210. hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW,
  211. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  212. NULL, NULL, hInstance, NULL);
  213. if (!hWnd) {
  214. return (FALSE);
  215. }
  216. ShowWindow(hWnd, nCmdShow);
  217. UpdateWindow(hWnd);
  218. return (TRUE);
  219. }
  220. //
  221. // FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
  222. //
  223. // PURPOSE: Processes messages for the main window.
  224. //
  225. // MESSAGES:
  226. //
  227. // WM_COMMAND - process the application menu
  228. // WM_PAINT - Paint the main window
  229. // WM_DESTROY - post a quit message and return
  230. // WM_DISPLAYCHANGE - message sent to Plug & Play systems when the display changes
  231. // WM_RBUTTONDOWN - Right mouse click -- put up context menu here if appropriate
  232. // WM_NCRBUTTONUP - User has clicked the right button on the application's system menu
  233. //
  234. //
  235. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  236. {
  237. int wmId, wmEvent;
  238. PAINTSTRUCT ps;
  239. HDC hdc;
  240. POINT pnt;
  241. HMENU hMenu;
  242. BOOL bGotHelp;
  243. switch (message) {
  244. case WM_COMMAND:
  245. wmId = LOWORD(wParam); // Remember, these are...
  246. wmEvent = HIWORD(wParam); // ...different for Win32!
  247. //Parse the menu selections:
  248. switch (wmId) {
  249. case IDM_ABOUT:
  250. DialogBox(hInst, "AboutBox", hWnd, (DLGPROC)About);
  251. break;
  252. case IDM_EXIT:
  253. DestroyWindow (hWnd);
  254. break;
  255. case IDM_HELPTOPICS: // Only called in Windows 95
  256. bGotHelp = WinHelp (hWnd, APPNAME".HLP", HELP_FINDER,(DWORD)0);
  257. if (!bGotHelp)
  258. {
  259. MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
  260. szAppName, MB_OK|MB_ICONHAND);
  261. }
  262. break;
  263. case IDM_HELPCONTENTS: // Not called in Windows 95
  264. bGotHelp = WinHelp (hWnd, APPNAME".HLP", HELP_CONTENTS,(DWORD)0);
  265. if (!bGotHelp)
  266. {
  267. MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
  268. szAppName, MB_OK|MB_ICONHAND);
  269. }
  270. break;
  271. case IDM_HELPSEARCH: // Not called in Windows 95
  272. if (!WinHelp(hWnd, APPNAME".HLP", HELP_PARTIALKEY,
  273. (DWORD)(LPSTR)""))
  274. {
  275. MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
  276. szAppName, MB_OK|MB_ICONHAND);
  277. }
  278. break;
  279. case IDM_HELPHELP: // Not called in Windows 95
  280. if(!WinHelp(hWnd, (LPSTR)NULL, HELP_HELPONHELP, 0))
  281. {
  282. MessageBox (GetFocus(), GetStringRes(IDS_NO_HELP),
  283. szAppName, MB_OK|MB_ICONHAND);
  284. }
  285. break;
  286. // Here are all the other possible menu options,
  287. // all of these are currently disabled:
  288. case IDM_NEW:
  289. case IDM_OPEN:
  290. case IDM_SAVE:
  291. case IDM_SAVEAS:
  292. case IDM_UNDO:
  293. case IDM_CUT:
  294. case IDM_COPY:
  295. case IDM_PASTE:
  296. case IDM_LINK:
  297. case IDM_LINKS:
  298. default:
  299. return (DefWindowProc(hWnd, message, wParam, lParam));
  300. }
  301. break;
  302. case WM_NCRBUTTONUP: // RightClick on windows non-client area...
  303. if (IS_WIN95 && SendMessage(hWnd, WM_NCHITTEST, 0, lParam) == HTSYSMENU)
  304. {
  305. // The user has clicked the right button on the applications
  306. // 'System Menu'. Here is where you would alter the default
  307. // system menu to reflect your application. Notice how the
  308. // explorer deals with this. For this app, we aren't doing
  309. // anything
  310. return (DefWindowProc(hWnd, message, wParam, lParam));
  311. } else {
  312. // Nothing we are interested in, allow default handling...
  313. return (DefWindowProc(hWnd, message, wParam, lParam));
  314. }
  315. break;
  316. case WM_RBUTTONDOWN: // RightClick in windows client area...
  317. pnt.x = LOWORD(lParam);
  318. pnt.y = HIWORD(lParam);
  319. ClientToScreen(hWnd, (LPPOINT) &pnt);
  320. // This is where you would determine the appropriate 'context'
  321. // menu to bring up. Since this app has no real functionality,
  322. // we will just bring up the 'Help' menu:
  323. hMenu = GetSubMenu (GetMenu (hWnd), 2);
  324. if (hMenu) {
  325. TrackPopupMenu (hMenu, 0, pnt.x, pnt.y, 0, hWnd, NULL);
  326. } else {
  327. // Couldn't find the menu...
  328. MessageBeep(0);
  329. }
  330. break;
  331. case WM_DISPLAYCHANGE: // Only comes through on plug'n'play systems
  332. {
  333. SIZE szScreen;
  334. DWORD dwBitsPerPixel = (DWORD)wParam;
  335. szScreen.cx = LOWORD(lParam);
  336. szScreen.cy = HIWORD(lParam);
  337. MessageBox (GetFocus(), GetStringRes(IDS_DISPLAYCHANGED),
  338. szAppName, 0);
  339. }
  340. break;
  341. case WM_PAINT:
  342. hdc = BeginPaint (hWnd, &ps);
  343. // Add any drawing code here...
  344. EndPaint (hWnd, &ps);
  345. break;
  346. case WM_DESTROY:
  347. // Tell WinHelp we don't need it any more...
  348. WinHelp (hWnd, APPNAME".HLP", HELP_QUIT,(DWORD)0);
  349. PostQuitMessage(0);
  350. break;
  351. default:
  352. return (DefWindowProc(hWnd, message, wParam, lParam));
  353. }
  354. return (0);
  355. }
  356. //
  357. // FUNCTION: About(HWND, unsigned, WORD, LONG)
  358. //
  359. // PURPOSE: Processes messages for "About" dialog box
  360. // This version allows greater flexibility over the contents of the 'About' box,
  361. // by pulling out values from the 'Version' resource.
  362. //
  363. // MESSAGES:
  364. //
  365. // WM_INITDIALOG - initialize dialog box
  366. // WM_COMMAND - Input received
  367. //
  368. //
  369. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  370. {
  371. static HFONT hfontDlg; // Font for dialog text
  372. static HFONT hFinePrint; // Font for 'fine print' in dialog
  373. DWORD dwVerInfoSize; // Size of version information block
  374. LPSTR lpVersion; // String pointer to 'version' text
  375. DWORD dwVerHnd=0; // An 'ignored' parameter, always '0'
  376. UINT uVersionLen;
  377. WORD wRootLen;
  378. BOOL bRetCode;
  379. int i;
  380. char szFullPath[256];
  381. char szResult[256];
  382. char szGetName[256];
  383. DWORD dwVersion;
  384. char szVersion[40];
  385. DWORD dwResult;
  386. switch (message) {
  387. case WM_INITDIALOG:
  388. ShowWindow (hDlg, SW_HIDE);
  389. if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
  390. {
  391. hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0,
  392. VARIABLE_PITCH | FF_DONTCARE, "");
  393. hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0,
  394. VARIABLE_PITCH | FF_DONTCARE, "");
  395. }
  396. else
  397. {
  398. hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  399. VARIABLE_PITCH | FF_SWISS, "");
  400. hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  401. VARIABLE_PITCH | FF_SWISS, "");
  402. }
  403. CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
  404. GetModuleFileName (hInst, szFullPath, sizeof(szFullPath));
  405. // Now lets dive in and pull out the version information:
  406. dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
  407. if (dwVerInfoSize) {
  408. LPSTR lpstrVffInfo;
  409. HANDLE hMem;
  410. hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
  411. lpstrVffInfo = GlobalLock(hMem);
  412. GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
  413. // The below 'hex' value looks a little confusing, but
  414. // essentially what it is, is the hexidecimal representation
  415. // of a couple different values that represent the language
  416. // and character set that we are wanting string values for.
  417. // 040904E4 is a very common one, because it means:
  418. // US English, Windows MultiLingual characterset
  419. // Or to pull it all apart:
  420. // 04------ = SUBLANG_ENGLISH_USA
  421. // --09---- = LANG_ENGLISH
  422. // --11---- = LANG_JAPANESE
  423. // ----04E4 = 1252 = Codepage for Windows:Multilingual
  424. lstrcpy(szGetName, GetStringRes(IDS_VER_INFO_LANG));
  425. wRootLen = lstrlen(szGetName); // Save this position
  426. // Set the title of the dialog:
  427. lstrcat (szGetName, "ProductName");
  428. bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
  429. (LPSTR)szGetName,
  430. (LPVOID)&lpVersion,
  431. (UINT *)&uVersionLen);
  432. // Notice order of version and string...
  433. if (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE)
  434. {
  435. lstrcpy(szResult, lpVersion);
  436. lstrcat(szResult, " �̃o�[�W��������");
  437. }
  438. else
  439. {
  440. lstrcpy(szResult, "About ");
  441. lstrcat(szResult, lpVersion);
  442. }
  443. // -----------------------------------------------------
  444. SetWindowText (hDlg, szResult);
  445. // Walk through the dialog items that we want to replace:
  446. for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++) {
  447. GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
  448. szGetName[wRootLen] = (char)0;
  449. lstrcat (szGetName, szResult);
  450. uVersionLen = 0;
  451. lpVersion = NULL;
  452. bRetCode = VerQueryValue((LPVOID)lpstrVffInfo,
  453. (LPSTR)szGetName,
  454. (LPVOID)&lpVersion,
  455. (UINT *)&uVersionLen);
  456. if ( bRetCode && uVersionLen && lpVersion) {
  457. // Replace dialog item text with version info
  458. lstrcpy(szResult, lpVersion);
  459. SetDlgItemText(hDlg, i, szResult);
  460. }
  461. else
  462. {
  463. dwResult = GetLastError();
  464. wsprintf(szResult, GetStringRes(IDS_VERSION_ERROR), dwResult);
  465. SetDlgItemText (hDlg, i, szResult);
  466. }
  467. SendMessage (GetDlgItem (hDlg, i), WM_SETFONT,
  468. (UINT)((i==DLG_VERLAST)?hFinePrint:hfontDlg),
  469. TRUE);
  470. } // for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)
  471. GlobalUnlock(hMem);
  472. GlobalFree(hMem);
  473. } else {
  474. // No version information available.
  475. } // if (dwVerInfoSize)
  476. SendMessage (GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT,
  477. (WPARAM)hfontDlg,(LPARAM)TRUE);
  478. // We are using GetVersion rather then GetVersionEx
  479. // because earlier versions of Windows NT and Win32s
  480. // didn't include GetVersionEx:
  481. dwVersion = GetVersion();
  482. if (dwVersion < 0x80000000) {
  483. // Windows NT
  484. wsprintf (szVersion, "Microsoft Windows NT %u.%u (Build: %u)",
  485. (DWORD)(LOBYTE(LOWORD(dwVersion))),
  486. (DWORD)(HIBYTE(LOWORD(dwVersion))),
  487. (DWORD)(HIWORD(dwVersion)) );
  488. } else if (LOBYTE(LOWORD(dwVersion))<4) {
  489. // Win32s
  490. wsprintf (szVersion, "Microsoft Win32s %u.%u (Build: %u)",
  491. (DWORD)(LOBYTE(LOWORD(dwVersion))),
  492. (DWORD)(HIBYTE(LOWORD(dwVersion))),
  493. (DWORD)(HIWORD(dwVersion) & ~0x8000) );
  494. } else {
  495. // Windows 95
  496. wsprintf (szVersion, "Microsoft Windows 95 %u.%u",
  497. (DWORD)(LOBYTE(LOWORD(dwVersion))),
  498. (DWORD)(HIBYTE(LOWORD(dwVersion))) );
  499. }
  500. SetWindowText (GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
  501. ShowWindow (hDlg, SW_SHOW);
  502. return (TRUE);
  503. case WM_COMMAND:
  504. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
  505. EndDialog(hDlg, TRUE);
  506. DeleteObject (hfontDlg);
  507. DeleteObject (hFinePrint);
  508. return (TRUE);
  509. }
  510. break;
  511. }
  512. return FALSE;
  513. }
  514. //
  515. // FUNCTION: CenterWindow(HWND, HWND)
  516. //
  517. // PURPOSE: Centers one window over another.
  518. //
  519. // COMMENTS:
  520. //
  521. // In this function, we save the instance handle in a global variable and
  522. // create and display the main program window.
  523. //
  524. // This functionwill center one window over another ensuring that
  525. // the placement of the window is within the 'working area', meaning
  526. // that it is both within the display limits of the screen, and not
  527. // obscured by the tray or other framing elements of the desktop.
  528. BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
  529. {
  530. RECT rChild, rParent, rWorkArea;
  531. int wChild, hChild, wParent, hParent;
  532. int xNew, yNew;
  533. BOOL bResult;
  534. // Get the Height and Width of the child window
  535. GetWindowRect (hwndChild, &rChild);
  536. wChild = rChild.right - rChild.left;
  537. hChild = rChild.bottom - rChild.top;
  538. // Get the Height and Width of the parent window
  539. GetWindowRect (hwndParent, &rParent);
  540. wParent = rParent.right - rParent.left;
  541. hParent = rParent.bottom - rParent.top;
  542. // Get the limits of the 'workarea'
  543. bResult = SystemParametersInfo(
  544. SPI_GETWORKAREA, // system parameter to query or set
  545. sizeof(RECT),
  546. &rWorkArea,
  547. 0);
  548. if (!bResult) {
  549. rWorkArea.left = rWorkArea.top = 0;
  550. rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
  551. rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
  552. }
  553. // Calculate new X position, then adjust for workarea
  554. xNew = rParent.left + ((wParent - wChild) /2);
  555. if (xNew < rWorkArea.left) {
  556. xNew = rWorkArea.left;
  557. } else if ((xNew+wChild) > rWorkArea.right) {
  558. xNew = rWorkArea.right - wChild;
  559. }
  560. // Calculate new Y position, then adjust for workarea
  561. yNew = rParent.top + ((hParent - hChild) /2);
  562. if (yNew < rWorkArea.top) {
  563. yNew = rWorkArea.top;
  564. } else if ((yNew+hChild) > rWorkArea.bottom) {
  565. yNew = rWorkArea.bottom - hChild;
  566. }
  567. // Set it, and return
  568. return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  569. }
  570. //---------------------------------------------------------------------------
  571. //
  572. // FUNCTION: GetStringRes (int id INPUT ONLY)
  573. //
  574. // COMMENTS: Load the resource string with the ID given, and return a
  575. // pointer to it. Notice that the buffer is common memory so
  576. // the string must be used before this call is made a second time.
  577. //
  578. //---------------------------------------------------------------------------
  579. LPTSTR GetStringRes (int id)
  580. {
  581. static TCHAR buffer[MAX_PATH];
  582. buffer[0]=0;
  583. LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
  584. return buffer;
  585. }