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.

646 lines
18 KiB

  1. /* DBACKP.CPP
  2. **
  3. ** Copyright (C) Microsoft, 1997, All Rights Reserved.
  4. **
  5. ** window class to display a preview of the screen background,
  6. ** complete with rudimentary palette handling and stretching
  7. ** of bitmaps to fit the preview screen.
  8. **
  9. ** this can be replaced with a static bitmap control only
  10. ** if palettes can also be handled by the control.
  11. **
  12. */
  13. #include "stdafx.h"
  14. #pragma hdrstop
  15. #define GWW_INFO 0
  16. #define CXYDESKPATTERN 8
  17. BOOL g_bInfoSet = FALSE;
  18. HBITMAP g_hbmPreview = NULL; // the bitmap used for previewing
  19. HBITMAP g_hbmDefault = NULL; // default bitmap
  20. HBITMAP g_hbmWall = NULL; // bitmap image of wallpaper
  21. HDC g_hdcWall = NULL; // memory DC with g_hbmWall selected
  22. HDC g_hdcMemory = NULL; // memory DC
  23. HPALETTE g_hpalWall = NULL; // palette that goes with hbmWall bitmap
  24. HBRUSH g_hbrBack = NULL; // brush for the desktop background
  25. IThumbnail *g_pthumb = NULL; // Html to Bitmap converter
  26. DWORD g_dwWallpaperID = 0; // ID to identify which bitmap we received
  27. #define WM_HTML_BITMAP (WM_USER + 100)
  28. #define WM_ASYNC_BITMAP (WM_HTML_BITMAP + 1)
  29. HPALETTE PaletteFromDS(HDC hdc)
  30. {
  31. DWORD adw[257];
  32. int i,n;
  33. n = GetDIBColorTable(hdc, 0, 256, (LPRGBQUAD)&adw[1]);
  34. adw[0] = MAKELONG(0x300, n);
  35. for (i=1; i<=n; i++)
  36. adw[i] = RGB(GetBValue(adw[i]),GetGValue(adw[i]),GetRValue(adw[i]));
  37. if (n == 0)
  38. return NULL;
  39. else
  40. return CreatePalette((LPLOGPALETTE)&adw[0]);
  41. }
  42. typedef struct{
  43. HWND hwnd;
  44. HBITMAP hbmp;
  45. DWORD id;
  46. WPARAM flags;
  47. TCHAR szFile[MAX_PATH];
  48. } ASYNCWALLPARAM, * PASYNCWALLPARAM;
  49. DWORD CALLBACK UpdateWallProc(LPVOID pv)
  50. {
  51. ASSERT(pv);
  52. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) pv;
  53. pawp->hbmp = (HBITMAP)LoadImage(NULL, pawp->szFile,
  54. IMAGE_BITMAP, 0, 0,
  55. LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  56. if (pawp->hbmp)
  57. {
  58. // if all is good, then the window will handle cleaning up
  59. if (IsWindow(pawp->hwnd) && PostMessage(pawp->hwnd, WM_ASYNC_BITMAP, 0, (LPARAM)pawp))
  60. return TRUE;
  61. DeleteObject(pawp->hbmp);
  62. }
  63. LocalFree(pawp);
  64. return TRUE;
  65. }
  66. const GUID CLSID_HtmlThumbnailExtractor = {0xeab841a0, 0x9550, 0x11cf, 0x8c, 0x16, 0x0, 0x80, 0x5f, 0x14, 0x8, 0xf3};
  67. DWORD CALLBACK UpdateWallProcHTML(LPVOID pv)
  68. {
  69. if (SUCCEEDED(CoInitialize(NULL)))
  70. {
  71. ASSERT(pv);
  72. if (pv)
  73. {
  74. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) pv;
  75. IPersistFile *ppf;
  76. HRESULT hr = CoCreateInstance(CLSID_HtmlThumbnailExtractor, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPersistFile, &ppf));
  77. if (SUCCEEDED(hr))
  78. {
  79. hr = ppf->Load(pawp->szFile, STGM_READ);
  80. if (SUCCEEDED(hr))
  81. {
  82. IExtractImage *pei= NULL;
  83. hr = ppf->QueryInterface(IID_PPV_ARG(IExtractImage, &pei));
  84. if (SUCCEEDED(hr))
  85. {
  86. DWORD dwPriority = 0;
  87. DWORD dwFlags = IEIFLAG_SCREEN | IEIFLAG_OFFLINE;
  88. WCHAR szLocation[MAX_PATH];
  89. SIZEL rgSize = {MON_DX, MON_DY};
  90. hr = pei->GetLocation(szLocation, ARRAYSIZE(szLocation), &dwPriority, &rgSize, SHGetCurColorRes(), &dwFlags);
  91. if (SUCCEEDED(hr))
  92. {
  93. HBITMAP hbm;
  94. hr = pei->Extract(&hbm);
  95. if (SUCCEEDED(hr))
  96. {
  97. if (!SendMessage(pawp->hwnd, WM_HTML_BITMAP, pawp->id, (LPARAM)hbm))
  98. {
  99. DeleteObject(hbm);
  100. }
  101. }
  102. }
  103. pei->Release();
  104. }
  105. }
  106. ppf->Release();
  107. }
  108. LocalFree(pawp);
  109. }
  110. CoUninitialize();
  111. }
  112. return TRUE;
  113. }
  114. void LoadWallpaperAsync(LPCTSTR pszFile, HWND hwnd, DWORD dwID, WPARAM flags, BOOL bHTML)
  115. {
  116. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) LocalAlloc(LPTR, SIZEOF(ASYNCWALLPARAM));
  117. if (pawp)
  118. {
  119. pawp->hwnd = hwnd;
  120. pawp->flags = flags;
  121. pawp->id = dwID;
  122. StrCpyN(pawp->szFile, pszFile, SIZECHARS(pawp->szFile));
  123. if (!bHTML)
  124. {
  125. if (!SHQueueUserWorkItem(UpdateWallProc, pawp, 0, (DWORD_PTR)0, (DWORD_PTR *)NULL, NULL, 0))
  126. LocalFree(pawp);
  127. }
  128. else
  129. {
  130. if (!SHQueueUserWorkItem(UpdateWallProcHTML, pawp, 0, (DWORD_PTR)0, (DWORD_PTR *)NULL, NULL, 0))
  131. LocalFree(pawp);
  132. }
  133. }
  134. }
  135. void _InitPreview(void)
  136. {
  137. if( g_hbmPreview )
  138. DeleteObject( g_hbmPreview );
  139. g_hbmPreview = LoadMonitorBitmap();
  140. }
  141. void _BuildPattern(void)
  142. {
  143. WCHAR wszBuf[MAX_PATH];
  144. HBITMAP hbmTemp;
  145. COLORREF clrOldBk, clrOldText;
  146. HBRUSH hbr = NULL;
  147. WORD patbits[CXYDESKPATTERN] = {0, 0, 0, 0, 0, 0, 0, 0};
  148. // get rid of old brush if there was one
  149. if (g_hbrBack)
  150. DeleteObject(g_hbrBack);
  151. g_pActiveDesk->GetPattern(wszBuf, ARRAYSIZE(wszBuf), 0);
  152. if (wszBuf[0] != 0L)
  153. {
  154. LPTSTR pszPatternBuf;
  155. #ifndef UNICODE
  156. CHAR szTemp[MAX_PATH];
  157. SHUnicodeToAnsi(wszBuf, szTemp, ARRAYSIZE(szTemp));
  158. pszPatternBuf = szTemp;
  159. #else
  160. pszPatternBuf = wszBuf;
  161. #endif
  162. PatternToWords(pszPatternBuf, patbits);
  163. hbmTemp = CreateBitmap(8, 8, 1, 1, patbits);
  164. if (hbmTemp)
  165. {
  166. g_hbrBack = CreatePatternBrush(hbmTemp);
  167. DeleteObject(hbmTemp);
  168. }
  169. }
  170. else
  171. {
  172. g_hbrBack = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
  173. }
  174. if (!g_hbrBack)
  175. {
  176. g_hbrBack = (HBRUSH)GetStockObject(BLACK_BRUSH);
  177. }
  178. clrOldText = SetTextColor(g_hdcMemory, GetSysColor(COLOR_BACKGROUND));
  179. clrOldBk = SetBkColor(g_hdcMemory, GetSysColor(COLOR_WINDOWTEXT));
  180. hbr = (HBRUSH)SelectObject(g_hdcMemory, g_hbrBack);
  181. PatBlt(g_hdcMemory, MON_X, MON_Y, MON_DX, MON_DY, PATCOPY);
  182. SelectObject(g_hdcMemory, hbr);
  183. SetTextColor(g_hdcMemory, clrOldText);
  184. SetBkColor(g_hdcMemory, clrOldBk);
  185. }
  186. void _InitWall(void)
  187. {
  188. if (g_hbmWall)
  189. {
  190. SelectObject(g_hdcWall, g_hbmDefault);
  191. DeleteObject(g_hbmWall);
  192. g_hbmWall = NULL;
  193. if (g_hpalWall)
  194. {
  195. DeleteObject(g_hpalWall);
  196. g_hpalWall = NULL;
  197. }
  198. }
  199. }
  200. void _GetWallpaperAsync(HWND hwnd, WPARAM flags)
  201. {
  202. WCHAR wszWallpaper[INTERNET_MAX_URL_LENGTH];
  203. LPTSTR pszWallpaper;
  204. g_pActiveDesk->GetWallpaper(wszWallpaper, ARRAYSIZE(wszWallpaper), 0);
  205. #ifndef UNICODE
  206. CHAR szWallpaper[ARRAYSIZE(wszWallpaper)];
  207. SHUnicodeToAnsi(wszWallpaper, szWallpaper, ARRAYSIZE(szWallpaper));
  208. pszWallpaper = szWallpaper;
  209. #else
  210. pszWallpaper = wszWallpaper;
  211. #endif
  212. g_dwWallpaperID++;
  213. if (!*pszWallpaper || !lstrcmpi(pszWallpaper, g_szNone))
  214. return;
  215. {
  216. if (IsNormalWallpaper(pszWallpaper))
  217. {
  218. LoadWallpaperAsync(pszWallpaper, hwnd, g_dwWallpaperID, flags, FALSE);
  219. }
  220. else
  221. {
  222. if(IsWallpaperPicture(pszWallpaper))
  223. {
  224. // This is a picture (GIF, JPG etc.,)
  225. // We need to generate a small HTML file that has this picture
  226. // as the background image.
  227. //
  228. // Compute the filename for the Temporary HTML file.
  229. //
  230. GetTempPath(ARRAYSIZE(wszWallpaper), pszWallpaper);
  231. lstrcat(pszWallpaper, PREVIEW_PICTURE_FILENAME);
  232. #ifndef UNICODE
  233. SHAnsiToUnicode(szWallpaper, wszWallpaper, ARRAYSIZE(wszWallpaper));
  234. #endif
  235. //
  236. // Generate the preview picture html file.
  237. //
  238. g_pActiveDesk->GenerateDesktopItemHtml(wszWallpaper, NULL, 0);
  239. }
  240. //
  241. // Will cause a WM_HTML_BITMAP to get sent to us.
  242. //
  243. LoadWallpaperAsync(pszWallpaper, hwnd, g_dwWallpaperID, flags, TRUE);
  244. }
  245. }
  246. }
  247. void _DrawWall(HBITMAP hbm, WPARAM flags)
  248. {
  249. int dxWall; // size of wallpaper
  250. int dyWall;
  251. BITMAP bm;
  252. // init the global
  253. g_hbmWall = hbm;
  254. SelectObject(g_hdcWall, g_hbmWall); // bitmap stays in this DC
  255. GetObject(g_hbmWall, sizeof(bm), &bm);
  256. TraceMsg(TF_ALWAYS, "for bitmap %08X we have bpp=%d and planes=%d", g_hbmWall, bm.bmBitsPixel, bm.bmPlanes);
  257. if (GetDeviceCaps(g_hdcMemory, RASTERCAPS) & RC_PALETTE)
  258. {
  259. if (bm.bmBitsPixel * bm.bmPlanes > 8)
  260. g_hpalWall = CreateHalftonePalette(g_hdcMemory);
  261. else if (bm.bmBitsPixel * bm.bmPlanes == 8)
  262. g_hpalWall = PaletteFromDS(g_hdcWall);
  263. else
  264. g_hpalWall = NULL; //!!! assume 1 or 4bpp images dont have palettes
  265. }
  266. GetObject(g_hbmWall, sizeof(bm), &bm);
  267. if(flags & BP_EXTERNALWALL)
  268. {
  269. //For external wallpapers, we ask the image extractor to generate
  270. // bitmaps the size that we want to show (NOT the screen size).
  271. dxWall = MON_DX;
  272. dyWall = MON_DY;
  273. }
  274. else
  275. {
  276. dxWall = MulDiv(bm.bmWidth, MON_DX, GetDeviceCaps(g_hdcMemory, HORZRES));
  277. dyWall = MulDiv(bm.bmHeight, MON_DY, GetDeviceCaps(g_hdcMemory, VERTRES));
  278. }
  279. if (dxWall < 1) dxWall = 1;
  280. if (dyWall < 1) dyWall = 1;
  281. if (g_hpalWall)
  282. {
  283. SelectPalette(g_hdcMemory, g_hpalWall, TRUE);
  284. RealizePalette(g_hdcMemory);
  285. }
  286. IntersectClipRect(g_hdcMemory, MON_X, MON_Y, MON_X + MON_DX, MON_Y + MON_DY);
  287. SetStretchBltMode(g_hdcMemory, COLORONCOLOR);
  288. if (flags & BP_TILE)
  289. {
  290. int i;
  291. StretchBlt(g_hdcMemory, MON_X, MON_Y, dxWall, dyWall,
  292. g_hdcWall, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  293. for (i = MON_X+dxWall; i < (MON_X + MON_DX); i+= dxWall)
  294. BitBlt(g_hdcMemory, i, MON_Y, dxWall, dyWall, g_hdcMemory, MON_X, MON_Y, SRCCOPY);
  295. for (i = MON_Y; i < (MON_Y + MON_DY); i += dyWall)
  296. BitBlt(g_hdcMemory, MON_X, i, MON_DX, dyWall, g_hdcMemory, MON_X, MON_Y, SRCCOPY);
  297. }
  298. else
  299. {
  300. //We want to stretch the Bitmap to the preview monitor size ONLY for new platforms.
  301. if (flags & BP_STRETCH)
  302. {
  303. //Stretch the bitmap to the whole preview monitor.
  304. dxWall = MON_DX;
  305. dyWall = MON_DY;
  306. }
  307. //Center the bitmap in the preview monitor
  308. StretchBlt(g_hdcMemory, MON_X + (MON_DX - dxWall)/2, MON_Y + (MON_DY - dyWall)/2,
  309. dxWall, dyWall, g_hdcWall, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  310. }
  311. // restore dc
  312. SelectPalette(g_hdcMemory, (HPALETTE)GetStockObject(DEFAULT_PALETTE), TRUE);
  313. SelectClipRgn(g_hdcMemory, NULL);
  314. }
  315. /*--------------------------------------------------------------------
  316. ** Build the preview bitmap.
  317. **
  318. ** both the pattern and the bitmap are drawn each time, but
  319. ** if the flags dictate the need, new pattern and bitmap
  320. ** globals are built as needed.
  321. **--------------------------------------------------------------------*/
  322. void NEAR PASCAL BuildPreviewBitmap(HWND hwnd, HBITMAP hbmp, WPARAM flags)
  323. {
  324. _InitPreview();
  325. HBITMAP hbmOld = (HBITMAP)SelectObject(g_hdcMemory, g_hbmPreview);
  326. _BuildPattern();
  327. _InitWall();
  328. /*
  329. ** now, position the wallpaper appropriately
  330. */
  331. if (hbmp)
  332. {
  333. // use the one that was passed in
  334. _DrawWall(hbmp, flags);
  335. }
  336. else
  337. {
  338. // this means that we need to set up the stuff
  339. // to get the bmp ASYNC
  340. _GetWallpaperAsync(hwnd, flags);
  341. }
  342. SelectObject(g_hdcMemory, hbmOld);
  343. }
  344. BOOL NEAR PASCAL BP_CreateGlobals(HWND hwnd)
  345. {
  346. HDC hdc;
  347. hdc = GetDC(NULL);
  348. g_hdcWall = CreateCompatibleDC(hdc);
  349. g_hdcMemory = CreateCompatibleDC(hdc);
  350. ReleaseDC(NULL, hdc);
  351. g_hbmPreview = LoadMonitorBitmap();
  352. HBITMAP hbm;
  353. hbm = CreateBitmap(1, 1, 1, 1, NULL);
  354. g_hbmDefault = (HBITMAP)SelectObject(g_hdcMemory, hbm);
  355. SelectObject(g_hdcMemory, g_hbmDefault);
  356. DeleteObject(hbm);
  357. HRESULT hr = E_FAIL;
  358. hr = CoCreateInstance(CLSID_Thumbnail, NULL, CLSCTX_INPROC_SERVER, IID_IThumbnail, (void **)&g_pthumb);
  359. if(SUCCEEDED(hr))
  360. {
  361. g_pthumb->Init(hwnd, WM_HTML_BITMAP);
  362. }
  363. if (!g_hdcWall || !g_hbmPreview || !SUCCEEDED(hr))
  364. return FALSE;
  365. else
  366. return TRUE;
  367. }
  368. void NEAR PASCAL BP_DestroyGlobals(void)
  369. {
  370. if (g_hbmPreview)
  371. {
  372. DeleteObject(g_hbmPreview);
  373. g_hbmPreview = NULL;
  374. }
  375. if (g_hbmWall)
  376. {
  377. SelectObject(g_hdcWall, g_hbmDefault);
  378. DeleteObject(g_hbmWall);
  379. g_hbmWall = NULL;
  380. }
  381. if (g_hpalWall)
  382. {
  383. SelectPalette(g_hdcWall, (HPALETTE)GetStockObject(DEFAULT_PALETTE), TRUE);
  384. DeleteObject(g_hpalWall);
  385. g_hpalWall = NULL;
  386. }
  387. if (g_hdcWall)
  388. {
  389. DeleteDC(g_hdcWall);
  390. g_hdcWall = NULL;
  391. }
  392. if (g_hbrBack)
  393. {
  394. DeleteObject(g_hbrBack);
  395. g_hbrBack = NULL;
  396. }
  397. if (g_hdcMemory)
  398. {
  399. DeleteDC(g_hdcMemory);
  400. g_hdcMemory = NULL;
  401. }
  402. if (g_hbmDefault)
  403. {
  404. DeleteObject(g_hbmDefault);
  405. g_hbmDefault = NULL;
  406. }
  407. if (g_pthumb)
  408. {
  409. g_pthumb->Release();
  410. g_pthumb = NULL;
  411. }
  412. }
  413. void InvalidateBackPrevContents(HWND hwnd)
  414. {
  415. BITMAP bm;
  416. RECT rc;
  417. //
  418. // Only invalidate the "screen" part of the monitor bitmap.
  419. //
  420. GetObject(g_hbmPreview, SIZEOF(bm), &bm);
  421. GetClientRect(hwnd, &rc);
  422. rc.left = ( rc.right - bm.bmWidth ) / 2 + MON_X;
  423. rc.top = ( rc.bottom - bm.bmHeight ) / 2 + MON_Y;
  424. rc.right = rc.left + MON_DX;
  425. rc.bottom = rc.top + MON_DY;
  426. InvalidateRect(hwnd, &rc, FALSE);
  427. }
  428. LRESULT BackPreviewWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  429. {
  430. PAINTSTRUCT ps;
  431. BITMAP bm;
  432. RECT rc;
  433. HBITMAP hbmOld;
  434. HPALETTE hpalOld;
  435. switch(message)
  436. {
  437. case WM_CREATE:
  438. if (!BP_CreateGlobals(hWnd))
  439. return -1L;
  440. break;
  441. case WM_DESTROY:
  442. MSG msg;
  443. BP_DestroyGlobals();
  444. while (PeekMessage(&msg, hWnd, WM_HTML_BITMAP, WM_ASYNC_BITMAP, PM_REMOVE))
  445. {
  446. if ( msg.lParam )
  447. {
  448. if (msg.message == WM_ASYNC_BITMAP)
  449. {
  450. // clean up this useless crap
  451. DeleteObject(((PASYNCWALLPARAM)(msg.lParam))->hbmp);
  452. LocalFree((PASYNCWALLPARAM)(msg.lParam));
  453. }
  454. else // WM_HTML_BITMAP
  455. DeleteObject((HBITMAP)msg.lParam);
  456. }
  457. }
  458. break;
  459. case WM_SETBACKINFO:
  460. if (g_hbmPreview)
  461. {
  462. BuildPreviewBitmap(hWnd, NULL, wParam);
  463. g_bInfoSet = TRUE;
  464. InvalidateBackPrevContents(hWnd);
  465. }
  466. break;
  467. case WM_ASYNC_BITMAP:
  468. if (lParam)
  469. {
  470. PASYNCWALLPARAM pawp = (PASYNCWALLPARAM) lParam;
  471. ASSERT(pawp->hbmp);
  472. if (pawp->id == g_dwWallpaperID)
  473. {
  474. BuildPreviewBitmap(hWnd, pawp->hbmp, pawp->flags);
  475. InvalidateBackPrevContents(hWnd);
  476. }
  477. else
  478. {
  479. // clean up this useless crap
  480. DeleteObject(pawp->hbmp);
  481. LocalFree(pawp);
  482. }
  483. }
  484. break;
  485. case WM_HTML_BITMAP:
  486. {
  487. // may come through with NULL if the image extraction failed....
  488. if (wParam == g_dwWallpaperID && lParam)
  489. {
  490. BuildPreviewBitmap(hWnd, (HBITMAP)lParam, BP_EXTERNALWALL);
  491. InvalidateBackPrevContents(hWnd);
  492. // Take ownership of bitmap
  493. return 1;
  494. }
  495. // Bitmap for something no longer selected
  496. return 0;
  497. }
  498. case WM_PALETTECHANGED:
  499. if ((HWND)wParam == hWnd)
  500. break;
  501. //fallthru
  502. case WM_QUERYNEWPALETTE:
  503. if (g_hpalWall)
  504. InvalidateRect(hWnd, NULL, FALSE);
  505. break;
  506. case WM_PAINT:
  507. BeginPaint(hWnd,&ps);
  508. if (g_hbmPreview && g_bInfoSet)
  509. {
  510. hbmOld = (HBITMAP)SelectObject(g_hdcMemory, g_hbmPreview);
  511. if (g_hpalWall)
  512. {
  513. hpalOld = SelectPalette(ps.hdc, g_hpalWall, FALSE);
  514. RealizePalette(ps.hdc);
  515. }
  516. GetObject(g_hbmPreview, sizeof(bm), &bm);
  517. GetClientRect(hWnd, &rc);
  518. rc.left = ( rc.right - bm.bmWidth ) / 2;
  519. rc.top = ( rc.bottom - bm.bmHeight ) / 2;
  520. BitBlt(ps.hdc, rc.left, rc.top, bm.bmWidth, bm.bmHeight, g_hdcMemory,
  521. 0, 0, SRCCOPY);
  522. if (g_hpalWall)
  523. {
  524. SelectPalette(ps.hdc, hpalOld, TRUE);
  525. RealizePalette(ps.hdc);
  526. }
  527. SelectObject(g_hdcMemory, hbmOld);
  528. }
  529. EndPaint(hWnd,&ps);
  530. return 0;
  531. }
  532. return DefWindowProc(hWnd,message,wParam,lParam);
  533. }
  534. BOOL RegisterBackPreviewClass()
  535. {
  536. WNDCLASS wc;
  537. if (!GetClassInfo(HINST_THISDLL, c_szBackgroundPreview2, &wc))
  538. {
  539. wc.style = 0;
  540. wc.lpfnWndProc = BackPreviewWndProc;
  541. wc.cbClsExtra = 0;
  542. wc.cbWndExtra = 0;
  543. wc.hInstance = HINST_THISDLL;
  544. wc.hIcon = NULL;
  545. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  546. wc.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
  547. wc.lpszMenuName = NULL;
  548. wc.lpszClassName = c_szBackgroundPreview2;
  549. if (!RegisterClass(&wc))
  550. return FALSE;
  551. }
  552. return TRUE;
  553. }