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.

805 lines
21 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: glscrnsv.c
  3. *
  4. * Companion file to scrnsave.c. Hooks out any changes in functionality
  5. * defined as GL_SCRNSAVE in scrnsave.c, and does general intialization.
  6. *
  7. * Copyright (c) 1996 Microsoft Corporation
  8. *
  9. \**************************************************************************/
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <stdlib.h>
  13. #include "scrnsave.h"
  14. #include "glscrnsv.h"
  15. #include "ssintrnl.hxx"
  16. #include "sswindow.hxx"
  17. #include "glscrnsv.hxx"
  18. #include "sswproc.hxx"
  19. static UINT (*KeyDownFunc)(int) = NULL;
  20. // Global ptr to screen saver instance
  21. SCRNSAVE *gpss = NULL;
  22. // Global strings.
  23. #define GEN_STRING_SIZE 64
  24. TCHAR szScreenSaverTitle[GEN_STRING_SIZE];
  25. LPCTSTR pszWindowClass = TEXT("WindowsScreenSaverClass"); // main class name
  26. LPCTSTR pszChildWindowClass = TEXT("ScreenSaverClass"); // child class name
  27. // forward declarations of internal fns
  28. static BOOL RegisterMainClass( WNDPROC wndProc, HBRUSH hbrBg, HCURSOR hCursor );
  29. static BOOL RegisterChildClass();
  30. static BOOL AttemptResolutionSwitch( int width, int height, ISIZE *pNewSize );
  31. // externs
  32. extern void InitRealScreenSave(); // scrnsave.cxx
  33. extern LRESULT WINAPI
  34. RealScreenSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  35. extern VOID UnloadPwdDLL(VOID);
  36. extern BOOL GLScreenSaverConfigureDialog( HWND hDlg, UINT msg, WPARAM wParam,
  37. LPARAM lParam ); // sswproc.cxx
  38. #ifdef SS_INITIAL_CLEAR
  39. static void InitialClear( PSSW *pssw );
  40. #endif
  41. /**************************************************************************\
  42. * GLDoScreenSave
  43. *
  44. * Runs the screen saver in the specified mode
  45. *
  46. * GL version of DoScreenSave in scrnsave.c
  47. *
  48. * Does basic init, creates initial set of windows, and starts the message
  49. * loop, which runs until terminated by some event.
  50. *
  51. \**************************************************************************/
  52. static INT_PTR
  53. GLDoScreenSave( int winType, LPARAM lParam )
  54. {
  55. MSG msg;
  56. // Create screen saver instance - this calls ss_Init()
  57. SCRNSAVE ss( winType, lParam );
  58. // Setup all the windows and start the message loop
  59. if( ss.SetupInitialWindows() )
  60. {
  61. // Send message to main window to start the drawing timer
  62. #ifdef SS_DELAYED_START_KLUGE
  63. // Kluge to work around 'window-not-ready' problem in child
  64. // preview mode - trigger off of WM_PAINT instead
  65. if( ! SS_DELAY_START(winType) )
  66. SendMessage( ss.psswMain->hwnd, SS_WM_START, 0, 0 );
  67. #else
  68. SendMessage( ss.psswMain->hwnd, SS_WM_START, 0, 0 );
  69. #endif // SS_DELAYED_START_KLUGE
  70. while( GetMessage( &msg, NULL, 0, 0 ) )
  71. {
  72. TranslateMessage( &msg );
  73. DispatchMessage( &msg );
  74. }
  75. }
  76. // We're done - screen saver exiting.
  77. // free password-handling DLL if loaded
  78. UnloadPwdDLL();
  79. return msg.wParam;
  80. }
  81. /**************************************************************************\
  82. * SCRNSAVE constructors
  83. *
  84. \**************************************************************************/
  85. SCRNSAVE::SCRNSAVE( int typeArg, LPARAM lParam )
  86. : type( typeArg ), initParam( lParam )
  87. {
  88. Init();
  89. }
  90. SCRNSAVE::SCRNSAVE( int typeArg )
  91. : type(typeArg)
  92. {
  93. initParam = 0;
  94. Init();
  95. }
  96. void
  97. SCRNSAVE::Init()
  98. {
  99. psswMain = NULL;
  100. psswGL = NULL;
  101. bResSwitch = FALSE;
  102. pssc = NULL;
  103. pssPal = NULL;
  104. flags = 0;
  105. #ifdef SS_DEBUG
  106. bDoTiming = type == SS_TYPE_NORMAL ? TRUE : FALSE;
  107. #endif
  108. // Global ptr to the screen saver instance
  109. gpss = this;
  110. // Platform detections
  111. ss_QueryOSVersion();
  112. // Initialize randomizer
  113. ss_RandInit();
  114. // Disable message boxes in GLAUX
  115. tkErrorPopups(FALSE);
  116. // Create multi-purpose black bg brush
  117. hbrBg = (HBRUSH) GetStockObject( BLACK_BRUSH );
  118. // Call client ss's init function, to get ptr to its configuration
  119. // request
  120. if( type == SS_TYPE_CONFIG ) {
  121. // This case handled differently
  122. return;
  123. }
  124. pssc = ss_Init();
  125. SS_ASSERT( pssc, "SCRNSAVE constructor failure\n" );
  126. // Set GL config structure from pssc
  127. GLc.pfFlags = 0;
  128. GLc.hrc = 0;
  129. GLc.pStretch = NULL;
  130. switch( pssc->depthType ) {
  131. case SS_DEPTH16 :
  132. GLc.pfFlags |= SS_DEPTH16_BIT;
  133. break;
  134. case SS_DEPTH32 :
  135. GLc.pfFlags |= SS_DEPTH32_BIT;
  136. break;
  137. }
  138. if( pssc->bDoubleBuf )
  139. GLc.pfFlags |= SS_DOUBLEBUF_BIT;
  140. if( pssc->bStretch )
  141. GLc.pStretch = &pssc->stretchInfo;
  142. }
  143. /**************************************************************************\
  144. * SetupInitialWindows
  145. *
  146. * Create / Configure all required windows.
  147. *
  148. \**************************************************************************/
  149. BOOL
  150. SCRNSAVE::SetupInitialWindows()
  151. {
  152. // Create the windows
  153. if( ! CreateInitialWindows() ) {
  154. SS_WARNING( "SCRNSAVE:: Couldn't create windows\n" );
  155. return FALSE;
  156. }
  157. // Initial window clear
  158. //mf: doesn't seem to be necessary now...
  159. //#define SS_INITIAL_MAIN_WINDOW_CLEAR 1
  160. #ifdef SS_INITIAL_MAIN_WINDOW_CLEAR
  161. if( type == SS_TYPE_PREVIEW ) {
  162. // Make sure the screen is cleared to black before we start drawing
  163. // anything, as sometimes the background WM_PAINT doesn't get to us right
  164. // away. This is only a problem in preview mode
  165. psswMain->GdiClear();
  166. }
  167. #endif
  168. // Configure and Init the windows, if applicable
  169. #ifdef SS_DELAYED_START_KLUGE
  170. // delay start for some configurations
  171. if( ! SS_DELAY_START(type) ) {
  172. SendMessage( psswMain->hwnd, SS_WM_INITGL, 0, 0 );
  173. }
  174. #else
  175. SendMessage( psswMain->hwnd, SS_WM_INITGL, 0, 0 );
  176. #endif // SS_DELAYED_START_KLUGE
  177. return TRUE;
  178. }
  179. /**************************************************************************\
  180. * CreateInitialWindows
  181. *
  182. * Create the intitial set of windows.
  183. *
  184. \**************************************************************************/
  185. BOOL
  186. SCRNSAVE::CreateInitialWindows()
  187. {
  188. PSSW pssw;
  189. UINT uStyle;
  190. UINT uExStyle;
  191. LPCTSTR pszWindowTitle;
  192. if( !pssc )
  193. return FALSE;
  194. // Handle any request for resolution change
  195. #define SS_RESOLUTION_SWITCH 1
  196. #ifdef SS_RESOLUTION_SWITCH
  197. if( pssc->bStretch &&
  198. (type == SS_TYPE_FULLSCREEN) &&
  199. (GetSystemMetrics(SM_CMONITORS) == 1) )
  200. {
  201. STRETCH_INFO *pStretch = &pssc->stretchInfo;
  202. ISIZE newSize;
  203. // Try and change screen resolution to match stretch size
  204. bResSwitch = AttemptResolutionSwitch( pStretch->baseWidth,
  205. pStretch->baseHeight, &newSize );
  206. // Is stretching still necessary if resolution changed ?
  207. if( bResSwitch ) {
  208. if( (newSize.width == pStretch->baseWidth) &&
  209. (newSize.height == pStretch->baseHeight) )
  210. // exact match, no stretching now necessary
  211. pssc->bStretch = FALSE;
  212. }
  213. }
  214. #endif
  215. // Currently the bitmaps used in stretch mode don't support palette
  216. // messages, so disable any stretching when in PREVIEW mode (where we
  217. // need to support palette interaction).
  218. // mf: actually this is only a consideration in 8-bit mode...
  219. if( (type == SS_TYPE_PREVIEW) && pssc->bStretch )
  220. pssc->bStretch = FALSE;
  221. // Create the main ss window
  222. if( ! CreateMainWindow() )
  223. return FALSE;
  224. #ifdef SS_INITIAL_CLEAR
  225. // If main window is transparent, can do an initial clear here before
  226. // any other windows are created or palettes modified
  227. // This is bogus on NT, as system switches to secure desktop when screen
  228. // saver kicks in automatically.
  229. InitialClear( pssw );
  230. #endif
  231. // For now, simple window environment is described by pssc, so things
  232. // like bFloater and bStretch are mutually exclusive.
  233. SS_GL_CONFIG *pGLc = &gpss->GLc;
  234. if( pssc->bFloater ) {
  235. if( !(pssw = CreateChildWindow( &pssc->floaterInfo )) )
  236. return FALSE;
  237. pssw->pGLc = pGLc;
  238. psswGL = pssw; // support old-style
  239. } else {
  240. psswMain->pGLc = pGLc;
  241. psswGL = psswMain; // support old-style
  242. }
  243. return TRUE;
  244. }
  245. /**************************************************************************\
  246. * NormalWindowScreenSaverProc
  247. *
  248. * Highest level window proc, used only in normal window (/w) mode.
  249. *
  250. \**************************************************************************/
  251. LRESULT WINAPI
  252. NormalWindowScreenSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  253. {
  254. switch( uMsg )
  255. {
  256. case WM_SETTEXT:
  257. // RealScreenSaverProc won't allow this - bypass it
  258. return ScreenSaverProc( hWnd, uMsg, wParam, lParam );
  259. case WM_CHAR:
  260. if( KeyDownFunc ) {
  261. int key = (int)wParam;
  262. (*KeyDownFunc)(key);
  263. }
  264. break;
  265. case WM_KEYDOWN:
  266. if( wParam == VK_ESCAPE ) {
  267. PostMessage( hWnd, WM_CLOSE, 0, 0l );
  268. break;
  269. } else if( KeyDownFunc ) {
  270. (*KeyDownFunc)((int)wParam);
  271. return 0;
  272. }
  273. return 0; // ??
  274. default:
  275. break;
  276. }
  277. return RealScreenSaverProc( hWnd, uMsg, wParam, lParam );
  278. }
  279. /**************************************************************************\
  280. * DoScreenSave
  281. *
  282. * Hooked out version of DoScreenSave in standard scrnsave.c
  283. *
  284. \**************************************************************************/
  285. INT_PTR
  286. DoScreenSave( HWND hwndParent )
  287. {
  288. return GLDoScreenSave( hwndParent ? SS_TYPE_PREVIEW : SS_TYPE_FULLSCREEN,
  289. (LPARAM) hwndParent );
  290. }
  291. /**************************************************************************\
  292. * DoWindowedScreenSave
  293. *
  294. * Called when screen saver invoked with /w (window mode) parameter
  295. *
  296. \**************************************************************************/
  297. INT_PTR
  298. DoWindowedScreenSave( LPCTSTR szArgs )
  299. {
  300. return GLDoScreenSave( SS_TYPE_NORMAL, (LPARAM) szArgs );
  301. }
  302. /**************************************************************************\
  303. * DoConfigBox
  304. *
  305. * Hooked out version of DoConfigBox in standard scrnsave.c
  306. *
  307. \**************************************************************************/
  308. INT_PTR
  309. DoConfigBox( HWND hwndParent )
  310. {
  311. // let the consumer register any special controls for the dialog
  312. if( !RegisterDialogClasses( hMainInstance ) )
  313. return FALSE;
  314. // Create screen saver instance
  315. SCRNSAVE ss( SS_TYPE_CONFIG );
  316. int retVal = (int)DialogBox( hMainInstance,
  317. MAKEINTRESOURCE( DLG_SCRNSAVECONFIGURE ),
  318. hwndParent, (DLGPROC)GLScreenSaverConfigureDialog );
  319. return retVal;
  320. }
  321. /**************************************************************************\
  322. * CreateMainWindow
  323. *
  324. * Creates main screen saver window based on the window type
  325. *
  326. \**************************************************************************/
  327. BOOL
  328. SCRNSAVE::CreateMainWindow()
  329. {
  330. WNDPROC wndProc;
  331. ISIZE size;
  332. UINT uStyle = 0;
  333. UINT uExStyle = 0;
  334. IPOINT2D pos;
  335. LPCTSTR pszWindowTitle;
  336. HCURSOR hCursor = NULL;
  337. HBRUSH hbrBgMain;
  338. PSSW pssw;
  339. BOOL bFailed;
  340. HWND hwndParent = NULL;
  341. int nx, ny; // window origin
  342. int ncx, ncy; // window size
  343. wndProc = RealScreenSaverProc;
  344. switch( type ) {
  345. case SS_TYPE_FULLSCREEN:
  346. {
  347. HWND hOther;
  348. // Get origin and size of virtual desktop
  349. nx = GetSystemMetrics( SM_XVIRTUALSCREEN );
  350. ny = GetSystemMetrics( SM_YVIRTUALSCREEN );
  351. ncx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
  352. ncy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
  353. //#define SS_FULLSCREEN_DEBUG 1
  354. #ifdef SS_FULLSCREEN_DEBUG
  355. // Reduce window size so we can see debugger
  356. ncx >>= 1;
  357. ncy >>= 1;
  358. #endif
  359. uStyle = WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  360. uExStyle = WS_EX_TOPMOST;
  361. pszWindowTitle = TEXT("Screen Saver"); // MUST differ from preview
  362. // if there is another NORMAL screen save instance, switch to it
  363. hOther = FindWindow( pszWindowClass, pszWindowTitle );
  364. if( hOther && IsWindow( hOther ) )
  365. {
  366. SS_DBGINFO( "SCRNSAVE::CreateMainWindow : Switching to other ss instance\n" );
  367. SetForegroundWindow( hOther );
  368. return FALSE;
  369. }
  370. InitRealScreenSave();
  371. }
  372. break;
  373. case SS_TYPE_PREVIEW:
  374. {
  375. RECT rcParent;
  376. hwndParent = (HWND) initParam;
  377. GetClientRect( hwndParent, &rcParent );
  378. fChildPreview = TRUE;
  379. ncx = rcParent.right;
  380. ncy = rcParent.bottom;
  381. nx = 0;
  382. ny = 0;
  383. uStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;
  384. pszWindowTitle = TEXT("Preview"); // MUST differ from full screen
  385. }
  386. break;
  387. case SS_TYPE_NORMAL:
  388. {
  389. // We set fChildPreview even when we're running in a normal window,
  390. // as this flag is used in scrnsave.c to differentiate from full
  391. // screen.
  392. fChildPreview = TRUE;
  393. // init size to half of (primary) screen by default
  394. ncx = GetSystemMetrics( SM_CXSCREEN ) >> 1;
  395. ncy = GetSystemMetrics( SM_CYSCREEN ) >> 1;
  396. nx = 0;
  397. ny = 0;
  398. if( initParam ) {
  399. // get size of window from args
  400. LPCTSTR szArgs = (LPCTSTR) initParam;
  401. //mf: not yet implemented
  402. }
  403. LoadString(hMainInstance, IDS_DESCRIPTION, szScreenSaverTitle,
  404. sizeof(szScreenSaverTitle) / sizeof(TCHAR));
  405. pszWindowTitle = szScreenSaverTitle; // MUST differ from preview
  406. uStyle = WS_VISIBLE | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
  407. WS_CLIPSIBLINGS;
  408. hCursor = LoadCursor( NULL, IDC_ARROW );
  409. // Wrap RealScreenSaverProc
  410. wndProc = NormalWindowScreenSaverProc;
  411. }
  412. break;
  413. default:
  414. break;
  415. }
  416. size.width = ncx;
  417. size.height = ncy;
  418. pos.x = nx;
  419. pos.y = ny;
  420. // Create SSW window wrapper
  421. pssw = new SSW( NULL, // parent
  422. &size,
  423. &pos,
  424. FALSE, // bMotion
  425. NULL // ChildSizeFunc
  426. );
  427. if( !pssw )
  428. return FALSE;
  429. // Initialize the window class and create the window
  430. #ifdef SS_INITIAL_CLEAR
  431. hbrBgMain = NULL;
  432. #else
  433. hbrBgMain = hbrBg;
  434. #endif
  435. if( !RegisterMainClass
  436. (
  437. wndProc,
  438. hbrBgMain,
  439. hCursor
  440. ) ||
  441. !pssw->CreateSSWindow
  442. (
  443. hMainInstance,
  444. uStyle,
  445. uExStyle,
  446. pszWindowTitle,
  447. wndProc,
  448. pszWindowClass,
  449. hwndParent // mf: ! hwndParentOverride
  450. ) )
  451. {
  452. delete pssw;
  453. return FALSE;
  454. }
  455. if( type != SS_TYPE_PREVIEW )
  456. #ifndef SS_DEBUG
  457. SetForegroundWindow( pssw->hwnd );
  458. #else
  459. {
  460. if( !SetForegroundWindow( pssw->hwnd ) )
  461. SS_DBGPRINT( "Main_Proc: SetForegroundWindow failed\n" );
  462. }
  463. #endif
  464. // Always configure the main window for gdi
  465. pssw->ConfigureForGdi();
  466. psswMain = pssw;
  467. return TRUE;
  468. }
  469. /**************************************************************************\
  470. * CreateChildWindow
  471. *
  472. * Creates a child window of the parent window
  473. *
  474. * This is a kind of wrapper-constructor
  475. \**************************************************************************/
  476. PSSW
  477. SCRNSAVE::CreateChildWindow( FLOATER_INFO *pFloater )
  478. {
  479. pFloater->bSubWindow = FALSE; // default is no logical subwin's
  480. // Register child window class
  481. // This only has to be done once, since so far, all child window
  482. // classes are the same
  483. if( !pFloater->bSubWindow && !RegisterChildClass() )
  484. return NULL;
  485. return CreateChildWindow( psswMain, pFloater );
  486. }
  487. PSSW
  488. SCRNSAVE::CreateChildWindow( PSSW psswParent, FLOATER_INFO *pFloater )
  489. {
  490. UINT uStyle = 0;
  491. UINT uExStyle = 0;
  492. PSSW pssw;
  493. uStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  494. // Size and position are NULL here, as the SSW will call the size
  495. // function callback in pFloater to get these and other values
  496. // Create the SSW window wrapper
  497. pssw = new SSW( psswParent, // parent
  498. NULL, // size
  499. NULL, // position
  500. pFloater->bMotion,
  501. pFloater->ChildSizeFunc
  502. );
  503. if( !pssw )
  504. return NULL;
  505. if( pFloater->bSubWindow )
  506. // Don't need to create win32 window
  507. return pssw;
  508. // Create a window
  509. if( !pssw->CreateSSWindow
  510. (
  511. hMainInstance,
  512. uStyle,
  513. 0, // uExStyle
  514. szScreenSaverTitle ,
  515. SS_ScreenSaverProc,
  516. pszChildWindowClass,
  517. NULL // hwndParentOverride
  518. ) )
  519. {
  520. delete pssw;
  521. return NULL;
  522. }
  523. return pssw;
  524. }
  525. /**************************************************************************\
  526. * RegisterMainClass
  527. *
  528. * Registers class of the main SS window
  529. \**************************************************************************/
  530. static BOOL
  531. RegisterMainClass( WNDPROC wndProc, HBRUSH hbrBg, HCURSOR hCursor )
  532. {
  533. WNDCLASS cls;
  534. cls.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
  535. cls.lpfnWndProc = wndProc;
  536. cls.cbClsExtra = 0;
  537. cls.cbWndExtra = 0;
  538. cls.hInstance = hMainInstance;
  539. cls.hIcon = LoadIcon( hMainInstance, MAKEINTATOM( ID_APP ) );
  540. cls.hCursor = hCursor;
  541. cls.hbrBackground = hbrBg;
  542. cls.lpszMenuName = (LPTSTR)NULL;
  543. cls.lpszClassName = (LPTSTR)pszWindowClass;
  544. return RegisterClass(&cls);
  545. }
  546. /**************************************************************************\
  547. * RegisterChildClass
  548. *
  549. * Registers class of a standard child window
  550. \**************************************************************************/
  551. static BOOL
  552. RegisterChildClass()
  553. {
  554. static BOOL bRegistered = FALSE;
  555. if( bRegistered )
  556. return TRUE;
  557. WNDCLASS cls;
  558. cls.style = CS_VREDRAW | CS_HREDRAW;
  559. cls.lpfnWndProc = SS_ScreenSaverProc;
  560. cls.cbClsExtra = 0;
  561. cls.cbWndExtra = 0;
  562. cls.hInstance = hMainInstance;
  563. cls.hIcon = NULL;
  564. cls.hCursor = NULL;
  565. cls.hbrBackground = NULL;
  566. cls.lpszMenuName = (LPTSTR)NULL;
  567. cls.lpszClassName = pszChildWindowClass;
  568. if( !RegisterClass(&cls) )
  569. return FALSE;
  570. // success
  571. bRegistered = TRUE;
  572. return TRUE;
  573. }
  574. /******************************Public*Routine******************************\
  575. * AttemptResolutionSwitch
  576. *
  577. * Try doing resolution switching to match or get close to the desired size.
  578. *
  579. \**************************************************************************/
  580. static BOOL
  581. AttemptResolutionSwitch( int width, int height, ISIZE *pNewSize )
  582. {
  583. BOOL bChanged = FALSE;
  584. // Try doing resolution switching to match or get close to the
  585. // desired width and height
  586. // Try switching to requested size
  587. #if 0
  588. //mf: not ready for prime time
  589. if( ss_ChangeDisplaySettings( width, height, 0 ) ) {
  590. #else
  591. if( 0 ) {
  592. // for now force failure of user request and try standard 640x480
  593. #endif
  594. bChanged = TRUE;
  595. } else {
  596. // Can't switch to requested size, try for best match
  597. // mf: !!! for now, let's play it safe and just try 640x480.
  598. width = 640;
  599. height = 480;
  600. // If screen already this size or less, leave be
  601. if( (GetSystemMetrics( SM_CXSCREEN ) <= width) &&
  602. (GetSystemMetrics( SM_CYSCREEN ) <= height) )
  603. return FALSE;
  604. //mf: use this when trying for best match
  605. // ss_QueryDisplaySettings();
  606. if( ss_ChangeDisplaySettings( width, height, 0 ) )
  607. bChanged = TRUE;
  608. }
  609. if( bChanged ) {
  610. pNewSize->width = width;
  611. pNewSize->height = height;
  612. }
  613. return bChanged;
  614. }
  615. #ifdef SS_INITIAL_CLEAR
  616. static void
  617. InitialClear( PSSW *pssw )
  618. {
  619. ss_GdiRectWipeClear( pssw->hwnd, pssw->size.width, pssw->size.height );
  620. }
  621. #endif // SS_INITIAL_CLEAR
  622. /**************************************************************************\
  623. * CloseWindows
  624. *
  625. * Close down any open windows.
  626. *
  627. * This sends a WM_CLOSE message to the top-level window if it is still open. If
  628. * the window has any children, they are also closed. For each window, the
  629. * SSW destructor is called.
  630. \**************************************************************************/
  631. void
  632. SCRNSAVE::CloseWindows()
  633. {
  634. if( psswMain ) {
  635. if( psswMain->bOwnWindow )
  636. DestroyWindow( psswMain->hwnd );
  637. else
  638. delete psswMain;
  639. }
  640. }
  641. /**************************************************************************\
  642. * SCRNSAVE destructor
  643. *
  644. \**************************************************************************/
  645. SCRNSAVE::~SCRNSAVE()
  646. {
  647. // Close any open windows (there might be some open if errors occurred)
  648. CloseWindows();
  649. if( bResSwitch ) {
  650. // Restore previous display settings
  651. ChangeDisplaySettings(NULL, CDS_FULLSCREEN);
  652. }
  653. gpss = NULL;
  654. }