Leaked source code of windows server 2003
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.

631 lines
23 KiB

  1. #include "priv.h"
  2. #include "CoverWnd.h"
  3. #include <ginarcid.h>
  4. #undef IDB_BACKGROUND_24
  5. #define IDB_BACKGROUND_24 0x3812
  6. #undef IDB_FLAG_24
  7. #define IDB_FLAG_24 0x3813
  8. const TCHAR g_szWindowClassName[] = TEXT("CoverWindowClass");
  9. const TCHAR g_szPleaseWaitName[] = TEXT("PleaseWaitWindowClass");
  10. #define CHUNK_SIZE 20
  11. #define IDT_KILLYOURSELF 1
  12. #define IDT_UPDATE 2
  13. #define WM_DESTORYYOURSELF (WM_USER + 0)
  14. void DimPixels(ULONG* pulSrc, int cLen, int Amount)
  15. {
  16. for (int i = cLen - 1; i >= 0; i--)
  17. {
  18. ULONG ulR = GetRValue(*pulSrc);
  19. ULONG ulG = GetGValue(*pulSrc);
  20. ULONG ulB = GetBValue(*pulSrc);
  21. ULONG ulGray = (54 * ulR + 183 * ulG + 19 * ulB) >> 8;
  22. ULONG ulTemp = ulGray * (0xff - Amount);
  23. ulR = (ulR * Amount + ulTemp) >> 8;
  24. ulG = (ulG * Amount + ulTemp) >> 8;
  25. ulB = (ulB * Amount + ulTemp) >> 8;
  26. *pulSrc = (*pulSrc & 0xff000000) | RGB(ulR, ulG, ulB);
  27. pulSrc++;
  28. }
  29. }
  30. LRESULT CALLBACK PleaseWaitWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lParam)
  31. {
  32. switch ( msg )
  33. {
  34. case WM_CREATE:
  35. {
  36. CREATESTRUCT* pCS = (CREATESTRUCT*)lParam;
  37. SetWindowLongPtr( hwnd, GWLP_USERDATA, (LPARAM) pCS->lpCreateParams );
  38. HBITMAP hbmBackground = (HBITMAP) pCS->lpCreateParams;
  39. BITMAP bm;
  40. if ( GetObject( hbmBackground, sizeof(bm), &bm ) )
  41. {
  42. RECT rc;
  43. HWND hwndParent = GetParent( hwnd );
  44. GetClientRect( hwndParent, &rc );
  45. POINT pt = {0,0};
  46. HMONITOR hmon = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
  47. if (hmon)
  48. {
  49. MONITORINFO mi = {sizeof(mi)};
  50. GetMonitorInfo(hmon, &mi);
  51. rc = mi.rcMonitor;
  52. MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rc, 2);
  53. }
  54. // Center dialog in the center of the virtual screen
  55. int x = ( rc.right - rc.left - bm.bmWidth ) / 2;
  56. int y = ( rc.bottom - rc.top - bm.bmHeight ) / 2;
  57. SetWindowPos( hwnd, NULL, x, y, bm.bmWidth, bm.bmHeight, SWP_NOZORDER | SWP_NOACTIVATE );
  58. }
  59. }
  60. return TRUE;
  61. case WM_PAINT:
  62. {
  63. HBITMAP hbmBackground = (HBITMAP) GetWindowLongPtr( hwnd, GWLP_USERDATA );
  64. PAINTSTRUCT ps;
  65. HDC hdc = BeginPaint( hwnd, &ps );
  66. BITMAP bm;
  67. if ( hbmBackground )
  68. {
  69. DWORD dwLayout = SetLayout(hdc, LAYOUT_BITMAPORIENTATIONPRESERVED);
  70. if ( GetObject( hbmBackground, sizeof(bm), &bm ) )
  71. {
  72. HDC hdcBackground = CreateCompatibleDC( hdc );
  73. if (hdcBackground)
  74. {
  75. HBITMAP hbmOld = (HBITMAP) SelectObject( hdcBackground, hbmBackground );
  76. BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcBackground, 0, 0, SRCCOPY);
  77. SelectObject( hdcBackground, hbmOld );
  78. DeleteDC( hdcBackground );
  79. }
  80. }
  81. SetLayout(hdc, dwLayout);
  82. // Don't draw more the once, no one will be on top of us
  83. DeleteObject(hbmBackground);
  84. SetWindowLongPtr( hwnd, GWLP_USERDATA, NULL );
  85. HFONT hfntSelected = NULL;
  86. HFONT hfntButton = NULL;
  87. HINSTANCE hMsGina = LoadLibrary( L"msgina.dll" );
  88. if ( hMsGina )
  89. {
  90. CHAR szPixelSize[ 32 ];
  91. if (LoadStringA(hMsGina,
  92. IDS_TURNOFF_TITLE_FACESIZE,
  93. szPixelSize,
  94. ARRAYSIZE(szPixelSize)) != 0)
  95. {
  96. LOGFONT logFont = { 0 };
  97. logFont.lfHeight = -MulDiv(atoi(szPixelSize), GetDeviceCaps(hdc, LOGPIXELSY), 72);
  98. if (LoadString(hMsGina,
  99. IDS_TURNOFF_TITLE_FACENAME,
  100. logFont.lfFaceName,
  101. LF_FACESIZE) != 0)
  102. {
  103. logFont.lfWeight = FW_BOLD;
  104. logFont.lfQuality = DEFAULT_QUALITY;
  105. hfntButton = CreateFontIndirect(&logFont);
  106. hfntSelected = static_cast<HFONT>(SelectObject(hdc, hfntButton));
  107. }
  108. }
  109. }
  110. COLORREF colorButtonText = RGB(255, 255, 255);
  111. COLORREF colorText = SetTextColor(hdc, colorButtonText);
  112. int iBkMode = SetBkMode(hdc, TRANSPARENT);
  113. WCHAR szText[MAX_PATH];
  114. szText[0] = 0;
  115. LoadString((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), IDS_PLEASEWAIT, szText, ARRAYSIZE(szText));
  116. RECT rcText;
  117. RECT rcClient;
  118. RECT rc;
  119. TBOOL(GetClientRect( hwnd, &rcClient ));
  120. TBOOL(CopyRect(&rcText, &rcClient));
  121. DWORD dwFlags = DT_HIDEPREFIX | (IS_MIRRORING_ENABLED() ? DT_RTLREADING : 0);
  122. int iPixelHeight = DrawText( hdc, szText, -1, &rcText, DT_CALCRECT | dwFlags);
  123. TBOOL(CopyRect(&rc, &rcClient));
  124. TBOOL(InflateRect(&rc, -((rc.right - rc.left - (rcText.right - rcText.left)) / 2), -((rc.bottom - rc.top - iPixelHeight) / 2)));
  125. (int)DrawText(hdc, szText, -1, &rc, dwFlags );
  126. (int)SetBkMode(hdc, iBkMode);
  127. (COLORREF)SetTextColor(hdc, colorText);
  128. if ( hfntButton )
  129. {
  130. (HGDIOBJ)SelectObject(hdc, hfntSelected);
  131. DeleteObject( hfntButton );
  132. }
  133. }
  134. EndPaint( hwnd, &ps );
  135. }
  136. break;
  137. case WM_ERASEBKGND:
  138. return TRUE;
  139. default:
  140. return DefWindowProc( hwnd, msg, wp, lParam );
  141. break;
  142. }
  143. return 0;
  144. }
  145. CDimmedWindow::CDimmedWindow (HINSTANCE hInstance) :
  146. _lReferenceCount(1),
  147. _hInstance(hInstance)
  148. {
  149. WNDCLASSEX wndClassEx;
  150. ZeroMemory(&wndClassEx, sizeof(wndClassEx));
  151. wndClassEx.cbSize = sizeof(wndClassEx);
  152. wndClassEx.lpfnWndProc = WndProc;
  153. wndClassEx.hInstance = hInstance;
  154. wndClassEx.lpszClassName = g_szWindowClassName;
  155. wndClassEx.hCursor = LoadCursor(NULL, IDC_WAIT);
  156. _atom = RegisterClassEx(&wndClassEx);
  157. wndClassEx.lpszClassName = g_szPleaseWaitName;
  158. wndClassEx.lpfnWndProc = PleaseWaitWndProc;
  159. _atomPleaseWait = RegisterClassEx(&wndClassEx);
  160. }
  161. CDimmedWindow::~CDimmedWindow (void)
  162. {
  163. if (_hwnd)
  164. {
  165. PostMessage(_hwnd, WM_DESTORYYOURSELF, 0, 0);
  166. }
  167. if (_atom != 0)
  168. {
  169. TBOOL(UnregisterClass(MAKEINTRESOURCE(_atom), _hInstance));
  170. }
  171. if (_atomPleaseWait != 0 )
  172. {
  173. TBOOL(UnregisterClass(MAKEINTRESOURCE(_atomPleaseWait), _hInstance));
  174. }
  175. }
  176. ULONG CDimmedWindow::AddRef (void)
  177. {
  178. return(InterlockedIncrement(&_lReferenceCount));
  179. }
  180. ULONG CDimmedWindow::Release (void)
  181. {
  182. ASSERTMSG(_lReferenceCount != 0, "Reference count zero in CDimmedWindow::Release");
  183. ULONG cRef = InterlockedDecrement(&_lReferenceCount);
  184. if ( 0 == cRef )
  185. {
  186. delete this;
  187. }
  188. return cRef;
  189. }
  190. DWORD CDimmedWindow::WorkerThread(IN void *pv)
  191. {
  192. ASSERT(pv);
  193. HWND hwnd = NULL;
  194. CDimmedWindow* pDimmedWindow = (CDimmedWindow*)pv;
  195. BOOL fScreenReader;
  196. bool fNoDebuggerPresent, fNoScreenReaderPresent;
  197. BOOL fUserTurnedOffWindow = SHRegGetBoolUSValue(SZ_THEMES, L"NoCoverWindow", FALSE, FALSE); // Needed for perf testing
  198. fNoDebuggerPresent = !IsDebuggerPresent();
  199. fNoScreenReaderPresent = ((SystemParametersInfo(SPI_GETSCREENREADER, 0, &fScreenReader, 0) == FALSE) || (fScreenReader == FALSE));
  200. if (fNoDebuggerPresent &&
  201. fNoScreenReaderPresent &&
  202. !fUserTurnedOffWindow)
  203. {
  204. int xVirtualScreen = GetSystemMetrics(SM_XVIRTUALSCREEN);
  205. int yVirtualScreen = GetSystemMetrics(SM_YVIRTUALSCREEN);
  206. int cxVirtualScreen = GetSystemMetrics(SM_CXVIRTUALSCREEN);
  207. int cyVirtualScreen = GetSystemMetrics(SM_CYVIRTUALSCREEN);
  208. HWND hwnd = CreateWindowEx(WS_EX_TOPMOST,
  209. g_szWindowClassName,
  210. NULL,
  211. WS_POPUP | WS_CLIPCHILDREN,
  212. xVirtualScreen, yVirtualScreen,
  213. cxVirtualScreen, cyVirtualScreen,
  214. NULL, NULL, pDimmedWindow->_hInstance, NULL);
  215. if (hwnd != NULL)
  216. {
  217. bool fDimmed;
  218. HBITMAP hbmBackground = NULL;
  219. fDimmed = false;
  220. (BOOL)ShowWindow(hwnd, SW_SHOW);
  221. TBOOL(SetForegroundWindow(hwnd));
  222. (BOOL)EnableWindow(hwnd, FALSE);
  223. SetTimer(hwnd, IDT_KILLYOURSELF, pDimmedWindow->_ulKillTimer, NULL);
  224. // Now create bitmap with background image and the windows flag
  225. HINSTANCE hShell32 = LoadLibrary( L"shell32.dll" );
  226. if ( NULL != hShell32 )
  227. {
  228. hbmBackground = (HBITMAP) LoadImage( hShell32, MAKEINTRESOURCE( IDB_BACKGROUND_24 ), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE );
  229. if (hbmBackground)
  230. {
  231. HDC hdcMem1 = CreateCompatibleDC(NULL);
  232. if (hdcMem1)
  233. {
  234. HDC hdcMem2 = CreateCompatibleDC(NULL);
  235. if (hdcMem2)
  236. {
  237. HBITMAP hbmFlag = (HBITMAP) LoadImage( hShell32, MAKEINTRESOURCE( IDB_FLAG_24 ), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE );
  238. if (hbmFlag)
  239. {
  240. HBITMAP hbmOld1 = (HBITMAP)SelectObject(hdcMem1, hbmBackground);
  241. HBITMAP hbmOld2 = (HBITMAP)SelectObject(hdcMem2, hbmFlag);
  242. BITMAP bm1;
  243. if (GetObject(hbmBackground, sizeof(bm1), &bm1))
  244. {
  245. BITMAP bm2;
  246. if (GetObject(hbmFlag, sizeof(bm2), &bm2))
  247. {
  248. BitBlt(hdcMem1, bm1.bmWidth - bm2.bmWidth - 8, 0, bm2.bmWidth, bm2.bmHeight, hdcMem2, 0, 0, SRCCOPY);
  249. }
  250. }
  251. SelectObject(hdcMem1, hbmOld1);
  252. SelectObject(hdcMem2, hbmOld2);
  253. DeleteObject(hbmFlag);
  254. }
  255. DeleteDC(hdcMem2);
  256. }
  257. DeleteDC(hdcMem1);
  258. }
  259. }
  260. FreeLibrary( hShell32 );
  261. }
  262. HWND hwndPleaseWait = CreateWindowEx( 0
  263. , g_szPleaseWaitName
  264. , NULL
  265. , WS_CHILD | WS_VISIBLE | WS_BORDER
  266. , 0
  267. , 0
  268. , 100
  269. , 100
  270. , hwnd
  271. , NULL
  272. , pDimmedWindow->_hInstance
  273. , hbmBackground // the window is responsible for freeing it.
  274. );
  275. if ( NULL == hwndPleaseWait )
  276. {
  277. DeleteObject( hbmBackground );
  278. }
  279. pDimmedWindow->_hwnd = hwnd;
  280. // This Release matches the addref during ::Create to guarantee that the object does not die before the HWND
  281. // is created.
  282. pDimmedWindow->Release();
  283. MSG msg;
  284. while (GetMessage(&msg, NULL, 0, 0))
  285. {
  286. TranslateMessage(&msg);
  287. DispatchMessage(&msg);
  288. if ((msg.message == WM_DESTORYYOURSELF) && (msg.hwnd == hwnd))
  289. {
  290. break;
  291. }
  292. }
  293. }
  294. }
  295. return (hwnd == NULL ? E_FAIL : S_OK);
  296. }
  297. HRESULT CDimmedWindow::Create (UINT ulKillTimer)
  298. {
  299. BOOL fSucceeded = FALSE;
  300. if (!_hwnd)
  301. {
  302. _ulKillTimer = ulKillTimer;
  303. AddRef();
  304. fSucceeded = SHCreateThread(CDimmedWindow::WorkerThread, (void *)this, CTF_INSIST, NULL);
  305. if (!fSucceeded)
  306. {
  307. Release();
  308. }
  309. }
  310. return fSucceeded ? S_OK : E_FAIL;
  311. }
  312. typedef struct
  313. {
  314. HDC hdcDimmed;
  315. HBITMAP hbmDimmed;
  316. HBITMAP hbmOldDimmed;
  317. HDC hdcTemp;
  318. HBITMAP hbmTemp;
  319. HBITMAP hbmOldTemp;
  320. ULONG* pulSrc;
  321. int idxSaturation;
  322. int idxChunk;
  323. int idxProgress;
  324. } DIMMEDWINDOWDATA;
  325. LRESULT CALLBACK CDimmedWindow::WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  326. {
  327. LRESULT lResult = 0;
  328. DIMMEDWINDOWDATA *pData;
  329. pData = (DIMMEDWINDOWDATA *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  330. switch (uMsg)
  331. {
  332. case WM_CREATE:
  333. {
  334. CREATESTRUCT* pCS = (CREATESTRUCT*)lParam;
  335. if (pCS)
  336. {
  337. pData = new DIMMEDWINDOWDATA;
  338. if (pData)
  339. {
  340. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pData);
  341. // On remote session we don't gray out the screen, yeah :-)
  342. if (!GetSystemMetrics(SM_REMOTESESSION))
  343. {
  344. HDC hdcWindow = GetDC(hwnd);
  345. if (hdcWindow != NULL )
  346. {
  347. pData->hdcDimmed = CreateCompatibleDC(hdcWindow);
  348. if (pData->hdcDimmed)
  349. {
  350. BITMAPINFO bmi;
  351. ZeroMemory(&bmi, sizeof(bmi));
  352. bmi.bmiHeader.biSize = sizeof(bmi);
  353. bmi.bmiHeader.biWidth = pCS->cx;
  354. bmi.bmiHeader.biHeight = pCS->cy;
  355. bmi.bmiHeader.biPlanes = 1;
  356. bmi.bmiHeader.biBitCount = 32;
  357. bmi.bmiHeader.biCompression = BI_RGB;
  358. bmi.bmiHeader.biSizeImage = 0;
  359. pData->hbmDimmed = CreateDIBSection(pData->hdcDimmed, &bmi, DIB_RGB_COLORS, (LPVOID*)&pData->pulSrc, NULL, 0);
  360. if (pData->hbmDimmed != NULL)
  361. {
  362. pData->hbmOldDimmed = (HBITMAP) SelectObject(pData->hdcDimmed, pData->hbmDimmed);
  363. pData->idxSaturation = 8;
  364. pData->idxChunk = pCS->cy / CHUNK_SIZE;
  365. }
  366. else
  367. {
  368. DeleteDC(pData->hdcDimmed);
  369. pData->hdcDimmed = NULL;
  370. }
  371. }
  372. pData->hdcTemp = CreateCompatibleDC(hdcWindow);
  373. if (pData->hdcTemp)
  374. {
  375. pData->hbmTemp = CreateCompatibleBitmap(hdcWindow, pCS->cx, pCS->cy);
  376. if (pData->hbmTemp)
  377. {
  378. pData->hbmOldTemp = (HBITMAP) SelectObject(pData->hdcTemp, pData->hbmTemp);
  379. }
  380. else
  381. {
  382. DeleteDC(pData->hdcTemp);
  383. pData->hdcTemp = NULL;
  384. }
  385. }
  386. ReleaseDC(hwnd, hdcWindow);
  387. }
  388. }
  389. if (pData->hdcDimmed)
  390. {
  391. SetTimer(hwnd, IDT_UPDATE, 30, NULL);
  392. }
  393. }
  394. }
  395. break;
  396. }
  397. case WM_DESTORYYOURSELF:
  398. {
  399. DestroyWindow(hwnd);
  400. break;
  401. }
  402. case WM_DESTROY:
  403. {
  404. if (pData)
  405. {
  406. SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
  407. KillTimer(hwnd, IDT_UPDATE);
  408. KillTimer(hwnd, IDT_KILLYOURSELF);
  409. if (pData->hdcDimmed)
  410. {
  411. SelectObject(pData->hdcDimmed, pData->hbmOldDimmed);
  412. DeleteDC(pData->hdcDimmed);
  413. pData->hdcDimmed = NULL;
  414. }
  415. if (pData->hbmDimmed)
  416. {
  417. DeleteObject(pData->hbmDimmed);
  418. pData->hbmDimmed = NULL;
  419. }
  420. if (pData->hdcTemp)
  421. {
  422. SelectObject(pData->hdcTemp, pData->hbmOldTemp);
  423. DeleteDC(pData->hdcTemp);
  424. pData->hdcTemp = NULL;
  425. }
  426. if (pData->hbmTemp)
  427. {
  428. DeleteObject(pData->hbmTemp);
  429. pData->hbmTemp = NULL;
  430. }
  431. delete pData;
  432. }
  433. break;
  434. }
  435. case WM_TIMER:
  436. if (pData)
  437. {
  438. BOOL fDestroyBitmaps = FALSE;
  439. if (wParam == IDT_KILLYOURSELF)
  440. {
  441. ShowWindow(hwnd, SW_HIDE);
  442. fDestroyBitmaps = TRUE;
  443. }
  444. else if (pData->hdcDimmed && pData->hbmDimmed)
  445. {
  446. HDC hdcWindow = GetDC(hwnd);
  447. BITMAP bm;
  448. GetObject(pData->hbmDimmed, sizeof(BITMAP), &bm);
  449. if (pData->idxChunk >= 0 )
  450. {
  451. //
  452. // In the first couple of passes, we slowly collect the screen
  453. // into our bitmap. We do this because Blt-ing the whole thing
  454. // causes the system to hang. By doing it this way, we continue
  455. // to pump messages, the UI stays responsive and it keeps the
  456. // mouse alive.
  457. //
  458. int y = pData->idxChunk * CHUNK_SIZE;
  459. if (pData->hdcTemp)
  460. {
  461. BitBlt(pData->hdcTemp, 0, y, bm.bmWidth, CHUNK_SIZE, hdcWindow, 0, y, SRCCOPY);
  462. BitBlt(pData->hdcDimmed, 0, y, bm.bmWidth, CHUNK_SIZE, pData->hdcTemp, 0, y, SRCCOPY);
  463. }
  464. else
  465. {
  466. BitBlt(pData->hdcDimmed, 0, y, bm.bmWidth, CHUNK_SIZE, hdcWindow, 0, y, SRCCOPY);
  467. }
  468. pData->idxChunk--;
  469. if (pData->idxChunk < 0)
  470. {
  471. //
  472. // We're done getting the bitmap, now reset the timer
  473. // so we slowly fade to grey.
  474. //
  475. SetTimer(hwnd, IDT_UPDATE, 250, NULL);
  476. pData->idxSaturation = 16;
  477. }
  478. }
  479. else
  480. {
  481. //
  482. // In these passes, we are making the image more and more grey and
  483. // then Blt-ing the result to the screen.
  484. //
  485. DimPixels(pData->pulSrc, bm.bmWidth * bm.bmHeight, 0xd5);
  486. BitBlt(hdcWindow, 0, 0, bm.bmWidth, bm.bmHeight, pData->hdcDimmed, 0, 0, SRCCOPY);
  487. pData->idxSaturation--;
  488. if (pData->idxSaturation <= 0) // when we hit zero, kill the timer.
  489. {
  490. KillTimer(hwnd, IDT_UPDATE);
  491. fDestroyBitmaps = TRUE;
  492. }
  493. }
  494. }
  495. if (fDestroyBitmaps)
  496. {
  497. if (pData->hdcDimmed)
  498. {
  499. SelectObject(pData->hdcDimmed, pData->hbmOldDimmed);
  500. DeleteDC(pData->hdcDimmed);
  501. pData->hdcDimmed = NULL;
  502. }
  503. if (pData->hbmDimmed)
  504. {
  505. DeleteObject(pData->hbmDimmed);
  506. pData->hbmDimmed = NULL;
  507. }
  508. if (pData->hdcTemp)
  509. {
  510. SelectObject(pData->hdcTemp, pData->hbmOldTemp);
  511. DeleteDC(pData->hdcTemp);
  512. pData->hdcTemp = NULL;
  513. }
  514. if (pData->hbmTemp)
  515. {
  516. DeleteObject(pData->hbmTemp);
  517. pData->hbmTemp = NULL;
  518. }
  519. }
  520. }
  521. break;
  522. case WM_WINDOWPOSCHANGING:
  523. {
  524. LPWINDOWPOS pwp = (LPWINDOWPOS) lParam;
  525. pwp->flags |= SWP_NOSIZE | SWP_NOMOVE;
  526. }
  527. break;
  528. case WM_PAINT:
  529. {
  530. HDC hdcPaint;
  531. PAINTSTRUCT ps;
  532. hdcPaint = BeginPaint(hwnd, &ps);
  533. TBOOL(EndPaint(hwnd, &ps));
  534. lResult = 0;
  535. break;
  536. }
  537. default:
  538. lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
  539. break;
  540. }
  541. return(lResult);
  542. }