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.

575 lines
16 KiB

  1. #include "precomp.h"
  2. #include "sshndler.h"
  3. #include "ssutil.h"
  4. #include <Windowsx.h>
  5. CScreenSaverHandler::CScreenSaverHandler( HWND hWnd,
  6. UINT nFindNotifyMessage,
  7. UINT nPaintTimer,
  8. UINT nChangeTimer,
  9. UINT nToolbarTimer,
  10. HINSTANCE hInstance )
  11. : m_hWnd(hWnd),
  12. m_hInstance(hInstance),
  13. m_nFindNotifyMessage(nFindNotifyMessage),
  14. m_nPaintTimerId(nPaintTimer),
  15. m_nChangeTimerId(nChangeTimer),
  16. m_nToolbarTimerId(nToolbarTimer),
  17. m_pImageScreenSaver(NULL),
  18. m_bPaused(false),
  19. m_hFindThread(NULL),
  20. m_hFindCancel(NULL),
  21. m_bFirstImage(true),
  22. m_hwndTB(NULL),
  23. m_bToolbarVisible(false),
  24. m_LastMousePosition(NULL)
  25. {
  26. }
  27. static const TBBUTTON c_tbSlideShow[] =
  28. {
  29. // override default toolbar width for separators; iBitmap member of
  30. // TBBUTTON struct is a union of bitmap index & separator width
  31. { 0, ID_PLAYCMD, TBSTATE_ENABLED | TBSTATE_CHECKED, TBSTYLE_CHECKGROUP, {0,0}, 0, 0},
  32. { 1, ID_PAUSECMD, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, {0,0}, 0, 0},
  33. { 5, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, 0},
  34. { 2, ID_PREVCMD, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0},
  35. { 3, ID_NEXTCMD, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0},
  36. { 6, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, 0},
  37. { 7, 0, TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, 0},
  38. { 4, ID_CLOSECMD, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0},
  39. };
  40. HRESULT CScreenSaverHandler::_InitializeToolbar(HWND hwndTB,
  41. int idCold,
  42. int idHot)
  43. {
  44. HRESULT hr = S_OK;
  45. int cxBitmap = 16, cyBitmap = 16;
  46. ::SendMessage(hwndTB, CCM_SETVERSION, COMCTL32_VERSION, 0);
  47. ::SendMessage(hwndTB, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
  48. ::SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  49. ::SendMessage(hwndTB, TB_SETMAXTEXTROWS, 1, 0);
  50. // Create, fill, and assign the image list for default buttons.
  51. HBITMAP hbCold = (HBITMAP)::CreateMappedBitmap(m_hInstance,
  52. idCold,
  53. 0,
  54. NULL,
  55. 0);
  56. if(!hbCold)
  57. {
  58. hr = E_FAIL;
  59. }
  60. else
  61. {
  62. HIMAGELIST himl = ::ImageList_Create(cxBitmap,
  63. cyBitmap,
  64. ILC_COLOR8|ILC_MASK,
  65. 0,
  66. ARRAYSIZE(c_tbSlideShow));
  67. if(!himl)
  68. {
  69. hr = E_FAIL;
  70. }
  71. if( -1 == ::ImageList_AddMasked(himl, hbCold, RGB(255, 0, 255)))
  72. {
  73. hr = E_FAIL;
  74. }
  75. ::SendMessage(hwndTB, TB_SETIMAGELIST, 0, (LPARAM)himl);
  76. ::DeleteObject(hbCold);
  77. }
  78. // Create, fill, and assign the image list for hot buttons.
  79. HBITMAP hbHot = (HBITMAP)::CreateMappedBitmap(m_hInstance,
  80. idHot,
  81. 0,
  82. NULL,
  83. 0);
  84. if(!hbHot)
  85. {
  86. hr = E_FAIL;
  87. }
  88. else
  89. {
  90. HIMAGELIST himlHot = ::ImageList_Create(cxBitmap,
  91. cyBitmap,
  92. ILC_COLOR8|ILC_MASK,
  93. 0,
  94. ARRAYSIZE(c_tbSlideShow));
  95. if(!himlHot)
  96. {
  97. hr = E_FAIL;
  98. }
  99. ::ImageList_AddMasked(himlHot, hbHot, RGB(255, 0, 255));
  100. ::SendMessage(hwndTB, TB_SETHOTIMAGELIST, 0, (LPARAM)himlHot);
  101. ::DeleteObject(hbHot);
  102. }
  103. return hr;
  104. }
  105. HRESULT CScreenSaverHandler::_CreateToolbar()
  106. {
  107. HRESULT hr = S_OK;
  108. ::InitCommonControls();
  109. DWORD dwStyle = WS_CHILD | CCS_ADJUSTABLE;
  110. m_hwndTB = ::CreateWindowEx(0, TOOLBARCLASSNAME,
  111. NULL, dwStyle, 0, 0, 0, 0,
  112. m_hWnd, (HMENU) NULL, m_hInstance, NULL);
  113. if(!m_hwndTB)
  114. {
  115. hr = E_FAIL;
  116. }
  117. else
  118. {
  119. _InitializeToolbar(m_hwndTB, IDB_SLIDESHOWTOOLBAR, IDB_SLIDESHOWTOOLBARHOT);
  120. TBBUTTON tbSlideShow[ARRAYSIZE(c_tbSlideShow)];
  121. ::memcpy(tbSlideShow, c_tbSlideShow, sizeof(c_tbSlideShow));
  122. // Add the buttons, and then set the minimum and maximum button widths.
  123. ::SendMessage(m_hwndTB, TB_ADDBUTTONS,
  124. (UINT)ARRAYSIZE(c_tbSlideShow), (LPARAM)tbSlideShow);
  125. LRESULT dwSize = ::SendMessage(m_hwndTB, TB_GETBUTTONSIZE, 0, 0);
  126. RECT rcClient = {0};
  127. RECT rcToolbar = {0, 0, GET_X_LPARAM(dwSize) * ARRAYSIZE(c_tbSlideShow), GET_Y_LPARAM(dwSize)};
  128. ::GetClientRect(m_hWnd,&rcClient);
  129. ::AdjustWindowRectEx(&rcToolbar, dwStyle, FALSE, WS_EX_TOOLWINDOW);
  130. ::SetWindowPos(m_hwndTB,
  131. HWND_TOP,
  132. RECTWIDTH(rcClient)-RECTWIDTH(rcToolbar),
  133. 0,
  134. RECTWIDTH(rcToolbar),
  135. RECTHEIGHT(rcToolbar),
  136. SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
  137. ::ShowCursor(false);
  138. ::SendMessage(m_hwndTB, TB_AUTOSIZE, 0, 0);
  139. }
  140. return hr;
  141. }
  142. void CScreenSaverHandler::Initialize(void)
  143. {
  144. CWaitCursor wc;
  145. HDC hDC = ::GetDC(m_hWnd);
  146. if (hDC)
  147. {
  148. m_pImageScreenSaver = new CImageScreenSaver( m_hInstance,
  149. true );
  150. if (m_pImageScreenSaver)
  151. {
  152. m_pImageScreenSaver->SetScreenRect(m_hWnd);
  153. if (m_pImageScreenSaver->IsValid())
  154. {
  155. m_hFindCancel = ::CreateEvent( NULL, TRUE, FALSE, NULL );
  156. if (m_hFindCancel)
  157. {
  158. m_hFindThread = m_pImageScreenSaver->Initialize( m_hWnd,
  159. m_nFindNotifyMessage,
  160. m_hFindCancel );
  161. }
  162. }
  163. else
  164. {
  165. delete m_pImageScreenSaver;
  166. m_pImageScreenSaver = NULL;
  167. }
  168. }
  169. ::ReleaseDC( m_hWnd, hDC );
  170. }
  171. _CreateToolbar();
  172. }
  173. CScreenSaverHandler::~CScreenSaverHandler(void)
  174. {
  175. if (m_pImageScreenSaver)
  176. {
  177. delete m_pImageScreenSaver;
  178. m_pImageScreenSaver = NULL;
  179. }
  180. if (m_hFindCancel)
  181. {
  182. ::SetEvent(m_hFindCancel);
  183. ::CloseHandle(m_hFindCancel);
  184. m_hFindCancel = NULL;
  185. }
  186. if (m_hFindThread)
  187. {
  188. ::WaitForSingleObject( m_hFindThread, INFINITE );
  189. ::CloseHandle(m_hFindThread);
  190. m_hFindThread = NULL;
  191. }
  192. }
  193. void CScreenSaverHandler::OnPrev()
  194. {
  195. OnPause();
  196. if(m_pImageScreenSaver)
  197. {
  198. if(!m_pImageScreenSaver->ReplaceImage(false,true))
  199. {
  200. OnStop();
  201. }
  202. m_pImageScreenSaver->OnInput();
  203. }
  204. HandleTimer(m_nPaintTimerId);
  205. }
  206. void CScreenSaverHandler::OnNext()
  207. {
  208. OnPause();
  209. if(m_pImageScreenSaver)
  210. {
  211. if(!m_pImageScreenSaver->ReplaceImage(true,true))
  212. {
  213. OnStop();
  214. }
  215. m_pImageScreenSaver->OnInput();
  216. }
  217. HandleTimer(m_nPaintTimerId);
  218. }
  219. void CScreenSaverHandler::OnPause()
  220. {
  221. m_bPaused = true;
  222. if(m_hwndTB)
  223. {
  224. ::SendMessage(m_hwndTB, TB_SETSTATE, ID_PAUSECMD, (LPARAM) MAKELONG(TBSTATE_CHECKED | TBSTATE_ENABLED,0));
  225. ::SendMessage(m_hwndTB, TB_SETSTATE, ID_PLAYCMD, (LPARAM) MAKELONG(TBSTATE_ENABLED,0));
  226. }
  227. }
  228. void CScreenSaverHandler::OnStop()
  229. {
  230. ::PostMessage(m_hWnd, WM_CLOSE, 0, 0);
  231. }
  232. void CScreenSaverHandler::OnPlay()
  233. {
  234. m_bPaused = false;
  235. if(m_hwndTB)
  236. {
  237. ::SendMessage(m_hwndTB, TB_SETSTATE, ID_PAUSECMD, (LPARAM) MAKELONG(TBSTATE_ENABLED,0));
  238. ::SendMessage(m_hwndTB, TB_SETSTATE, ID_PLAYCMD, (LPARAM) MAKELONG(TBSTATE_CHECKED | TBSTATE_ENABLED,0));
  239. }
  240. if (m_pImageScreenSaver)
  241. {
  242. m_pImageScreenSaver->OnInput();
  243. if(m_pImageScreenSaver->ReplaceImage(true,true))
  244. {
  245. m_TimerPaint.Set( m_hWnd,
  246. m_nPaintTimerId,
  247. CHANGE_TIMER_INTERVAL_MSEC );
  248. }
  249. else
  250. {
  251. OnStop();
  252. }
  253. }
  254. }
  255. // turn on the toolbar window.
  256. // let the screen saver know it's on.
  257. // start the toolbar timer - which will turn it off later.
  258. HRESULT CScreenSaverHandler::_ShowToolbar(bool bShow)
  259. {
  260. HRESULT hr = S_OK;
  261. if(m_pImageScreenSaver)
  262. {
  263. m_pImageScreenSaver->ShowToolbar(bShow);
  264. }
  265. if((bShow == true) &&
  266. (m_bToolbarVisible == false))
  267. {
  268. m_bToolbarVisible = bShow;
  269. if(m_hwndTB)
  270. {
  271. ::ShowWindow(m_hwndTB, SW_SHOW);
  272. ::ShowCursor(true);
  273. m_bToolbarVisible = true;
  274. }
  275. // set timer to remove toolbar
  276. m_TimerInput.Set( m_hWnd,
  277. m_nToolbarTimerId,
  278. TOOLBAR_TIMER_DELAY );
  279. InvalidateRect(m_hwndTB,NULL,TRUE);
  280. }
  281. else if((bShow == false) &&
  282. (m_bToolbarVisible == true))
  283. {
  284. if(m_hwndTB)
  285. {
  286. ::ShowWindow(m_hwndTB, SW_HIDE);
  287. ::ShowCursor(false);
  288. m_bToolbarVisible = false;
  289. }
  290. }
  291. HandlePaint(); // repaint the frame
  292. return hr;
  293. }
  294. bool CScreenSaverHandler::HandleMouseMove(WPARAM wParam, LPARAM lParam)
  295. {
  296. if(m_LastMousePosition == NULL)
  297. {
  298. m_LastMousePosition = lParam;
  299. }
  300. else if (m_LastMousePosition != lParam)
  301. {
  302. _OnInput();
  303. m_LastMousePosition = lParam;
  304. }
  305. return false;
  306. }
  307. bool CScreenSaverHandler::HandleMouseMessage(WPARAM wParam, LPARAM lParam)
  308. {
  309. if (m_pImageScreenSaver)
  310. {
  311. m_pImageScreenSaver->OnInput();
  312. }
  313. return false;
  314. }
  315. void CScreenSaverHandler::HandleOnCommand( WPARAM wParam, LPARAM lParam)
  316. {
  317. _OnInput();
  318. switch(wParam)
  319. {
  320. case ID_PLAYCMD:
  321. OnPlay();
  322. break;
  323. case ID_PAUSECMD:
  324. OnPause();
  325. break;
  326. case ID_PREVCMD:
  327. OnPrev();
  328. break;
  329. case ID_NEXTCMD:
  330. OnNext();
  331. break;
  332. case ID_CLOSECMD:
  333. OnStop();
  334. break;
  335. }
  336. }
  337. void CScreenSaverHandler::HandleOnAppCommand( WPARAM wParam, LPARAM lParam)
  338. {
  339. _OnInput();
  340. switch(GET_APPCOMMAND_LPARAM(lParam))
  341. {
  342. case APPCOMMAND_BROWSER_BACKWARD:
  343. case APPCOMMAND_MEDIA_PREVIOUSTRACK:
  344. {
  345. OnPrev();
  346. }
  347. break;
  348. case APPCOMMAND_MEDIA_NEXTTRACK:
  349. case APPCOMMAND_BROWSER_FORWARD:
  350. {
  351. OnNext();
  352. }
  353. break;
  354. case APPCOMMAND_MEDIA_STOP:
  355. case APPCOMMAND_BROWSER_STOP:
  356. {
  357. OnStop();
  358. }
  359. break;
  360. case APPCOMMAND_MEDIA_PLAY_PAUSE:
  361. {
  362. if(m_bPaused)
  363. {
  364. OnPlay();
  365. }
  366. else
  367. {
  368. OnPause();
  369. }
  370. }
  371. break;
  372. }
  373. }
  374. void CScreenSaverHandler::_OnInput()
  375. {
  376. m_TimerInput.Set( m_hWnd, m_nToolbarTimerId, TOOLBAR_TIMER_DELAY );
  377. _ShowToolbar(true);
  378. }
  379. bool CScreenSaverHandler::HandleKeyboardMessage( UINT nMessage, WPARAM nVirtkey )
  380. {
  381. _OnInput();
  382. if (m_pImageScreenSaver)
  383. {
  384. m_pImageScreenSaver->OnInput();
  385. if (nMessage == WM_KEYDOWN)
  386. {
  387. switch (nVirtkey)
  388. {
  389. case VK_DOWN:
  390. if (nMessage == WM_KEYDOWN)
  391. {
  392. m_bPaused = !m_bPaused;
  393. if (!m_bPaused)
  394. {
  395. if (m_pImageScreenSaver)
  396. {
  397. if (m_pImageScreenSaver->ReplaceImage(true,false))
  398. {
  399. m_TimerPaint.Set( m_hWnd, m_nPaintTimerId, PAINT_TIMER_INTERVAL_MSEC );
  400. }
  401. else
  402. {
  403. OnStop();
  404. }
  405. }
  406. }
  407. }
  408. return true;
  409. case VK_LEFT:
  410. if (nMessage == WM_KEYDOWN)
  411. {
  412. OnPrev();
  413. }
  414. return true;
  415. case VK_RIGHT:
  416. if (nMessage == WM_KEYDOWN)
  417. {
  418. OnNext();
  419. }
  420. return true;
  421. case VK_ESCAPE:
  422. case VK_DELETE:
  423. if (nMessage == WM_KEYDOWN)
  424. {
  425. OnStop();
  426. }
  427. return true;
  428. }
  429. }
  430. }
  431. return false;
  432. }
  433. void CScreenSaverHandler::OnSize(WPARAM wParam, LPARAM lParam)
  434. {
  435. HandlePaint();
  436. }
  437. void CScreenSaverHandler::HandleConfigChange()
  438. {
  439. if (m_pImageScreenSaver)
  440. {
  441. m_pImageScreenSaver->SetScreenRect(m_hWnd);
  442. }
  443. }
  444. void CScreenSaverHandler::HandleTimer( WPARAM nEvent )
  445. {
  446. if (nEvent == m_nPaintTimerId)
  447. {
  448. if (m_pImageScreenSaver)
  449. {
  450. CSimpleDC ClientDC;
  451. if (ClientDC.GetDC(m_hWnd))
  452. {
  453. bool bResult = m_pImageScreenSaver->TimerTick( ClientDC );
  454. if (bResult)
  455. {
  456. m_TimerPaint.Set( m_hWnd,
  457. m_nChangeTimerId,
  458. CHANGE_TIMER_INTERVAL_MSEC );
  459. }
  460. InvalidateRect(m_hwndTB,NULL,TRUE);
  461. }
  462. }
  463. }
  464. else if (nEvent == m_nChangeTimerId)
  465. {
  466. m_TimerPaint.Kill();
  467. if (!m_bPaused && m_pImageScreenSaver)
  468. {
  469. if(m_pImageScreenSaver->ReplaceImage(true,false))
  470. {
  471. m_TimerPaint.Set( m_hWnd, m_nPaintTimerId, PAINT_TIMER_INTERVAL_MSEC );
  472. }
  473. else
  474. {
  475. // unable to find next image - so exit the screensaver.
  476. OnStop();
  477. }
  478. }
  479. }
  480. else if (nEvent == m_nToolbarTimerId)
  481. {
  482. // m_TimerInput expired - so turn off toolbar
  483. _ShowToolbar(false);
  484. }
  485. }
  486. void CScreenSaverHandler::HandlePaint(void)
  487. {
  488. if (m_pImageScreenSaver)
  489. {
  490. CSimpleDC PaintDC;
  491. if (PaintDC.BeginPaint(m_hWnd))
  492. {
  493. m_pImageScreenSaver->Paint(PaintDC);
  494. }
  495. }
  496. }
  497. void CScreenSaverHandler::HandleFindFile( CFoundFileMessageData *pFoundFileMessageData )
  498. {
  499. if (m_pImageScreenSaver)
  500. {
  501. if (pFoundFileMessageData)
  502. {
  503. bool bResult = m_pImageScreenSaver->FoundFile( pFoundFileMessageData->Name() );
  504. if (!bResult)
  505. {
  506. ::SetEvent( m_hFindCancel );
  507. }
  508. if (m_bFirstImage && m_pImageScreenSaver->Count())
  509. {
  510. // If this is our first image, start things up
  511. ::SendMessage( m_hWnd, WM_TIMER, m_nChangeTimerId, 0 );
  512. m_bFirstImage = false;
  513. }
  514. delete pFoundFileMessageData;
  515. }
  516. }
  517. }