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.

491 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ANIMATE.CPP
  4. //
  5. /*
  6. This class is responsible for the animations in the busy dialogs such as the
  7. merge index dialog.
  8. REVIEW: Could we use the commctrl animation control instead?
  9. */
  10. // needed for those pesky pre-compiled headers
  11. #include "header.h"
  12. #include <windows.h>
  13. #include "animate.h" // Animate class
  14. #include "resource.h"
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static const char THIS_FILE[] = __FILE__;
  18. #endif
  19. static const char txtAnimateClassName[] = "Help_Animation";
  20. static const WCHAR wtxtAnimateClassName[] = L"Help_Animation";
  21. typedef struct {
  22. int left;
  23. int top;
  24. int cx;
  25. int cy;
  26. } WRECT;
  27. void STDCALL GetWindowWRect(HWND hwnd, WRECT* prc)
  28. {
  29. ASSERT(IsValidWindow(hwnd));
  30. GetWindowRect(hwnd, (PRECT) prc);
  31. // Convert right and bottom into width and height
  32. prc->cx -= prc->left;
  33. prc->cy -= prc->top;
  34. }
  35. const int CX_DRAWAREA = 40;
  36. const int CY_DRAWAREA = 40;
  37. const int CX_BOOK = 36;
  38. const int CY_BOOK = 36;
  39. const int C_BOOKS = 5;
  40. const int X_BOOK = 0;
  41. const int Y_BOOK = (CY_DRAWAREA - CY_BOOK);
  42. const int CX_PEN = 15;
  43. const int CY_PEN = 20;
  44. const int C_PENS = 3;
  45. const int X_PEN = 18;
  46. const int Y_PEN = 2;
  47. const int CX_STROKE = 1;
  48. const int CY_STROKE = 2;
  49. const int C_HORZ_STROKES = 10;
  50. const int C_VERT_STROKES = 4;
  51. const int C_PEN_STROKES = (C_HORZ_STROKES * C_VERT_STROKES);
  52. const int C_PAUSE_FRAMES = 0;
  53. const int C_FRAMES = (C_PEN_STROKES + C_BOOKS + C_PAUSE_FRAMES);
  54. const int ANIMATE_INCREMENTS = 100;
  55. const COLORREF clrPenA = RGB(128, 128, 128);
  56. const COLORREF clrPenB = RGB(128, 0, 128);
  57. const int MAX_CNT_LINE = 1024;
  58. const int VPAD = 62;
  59. const int HPAD = 30;
  60. static VOID _fastcall PointFromStroke(int xStroke, int yStroke, POINT* lppt);
  61. #define SafeDeleteDC( hDC ) if( hDC ) { DeleteDC( hDC ); hDC = NULL; }
  62. #define SafeDeleteObject( hObj ) if( hObj ) { DeleteObject( hObj ); hObj = NULL; }
  63. LRESULT CALLBACK StatusWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  64. {
  65. // remove escape keys
  66. #if 0
  67. MSG msg2;
  68. if( PeekMessage( &msg2, hwnd, 0, 0, PM_NOREMOVE ) ) {
  69. if( msg2.message == WM_KEYDOWN || msg2.message == WM_KEYUP ) {
  70. if( msg2.wParam == VK_ESCAPE ) {
  71. PeekMessage( &msg2, hwnd, 0, 0, PM_REMOVE );
  72. }
  73. }
  74. }
  75. #endif
  76. if(g_bWinNT5)
  77. return DefWindowProcW(hwnd, msg, wParam, lParam);
  78. else
  79. return DefWindowProc(hwnd, msg, wParam, lParam);
  80. }
  81. class Animate
  82. {
  83. public:
  84. Animate();
  85. ~Animate(void);
  86. void STDCALL NextFrame(void);
  87. void SetPosition(int x, int y) { m_xPos = x; m_yPos = y; };
  88. BOOL STDCALL CreateStatusWindow(HWND hwndParent, int idTitle);
  89. HWND m_hWndParent;
  90. HWND m_hWnd;
  91. protected:
  92. HBITMAP m_hBmpTemp;
  93. HDC m_hDCBmp;
  94. HBITMAP m_hBmpIml;
  95. int m_iFrame;
  96. int m_xPos;
  97. int m_yPos;
  98. DWORD m_oldTickCount;
  99. DWORD m_originalTickCount;
  100. BOOL m_fShown;
  101. };
  102. static Animate* g_pAnimationWindow = NULL;
  103. BOOL STDCALL StartAnimation(int idTitle, HWND hWnd )
  104. {
  105. ASSERT(!g_pAnimationWindow);
  106. if( g_pAnimationWindow )
  107. return FALSE;
  108. g_pAnimationWindow = new Animate();
  109. if( !hWnd )
  110. if( !(hWnd = GetActiveWindow()) )
  111. hWnd = GetDesktopWindow();
  112. if (!g_pAnimationWindow->CreateStatusWindow( hWnd, idTitle)) {
  113. delete g_pAnimationWindow;
  114. g_pAnimationWindow = NULL;
  115. return FALSE;
  116. }
  117. return TRUE;
  118. }
  119. void STDCALL NextAnimation(void)
  120. {
  121. if (g_pAnimationWindow)
  122. g_pAnimationWindow->NextFrame();
  123. }
  124. void STDCALL StopAnimation(void)
  125. {
  126. if (g_pAnimationWindow)
  127. delete g_pAnimationWindow;
  128. g_pAnimationWindow = NULL;
  129. }
  130. BOOL STDCALL Animate::CreateStatusWindow(HWND hWndParent, int idTitle)
  131. {
  132. int width;
  133. WORD lang = PRIMARYLANGID(_Module.m_Language.GetUiLanguage());
  134. if(g_bWinNT5)
  135. {
  136. WNDCLASSW wc;
  137. SIZE sSize;
  138. ZeroMemory(&wc, sizeof(wc));
  139. // Register Main window class
  140. wc.hInstance = _Module.GetModuleInstance();
  141. wc.style = CS_BYTEALIGNWINDOW | CS_CLASSDC;
  142. wc.lpfnWndProc = StatusWndProc;
  143. wc.lpszClassName = wtxtAnimateClassName;
  144. wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  145. wc.hIcon = LoadIcon(_Module.GetResourceInstance(), "Icon!HTMLHelp");
  146. if (!RegisterClassW(&wc))
  147. return FALSE;
  148. WRECT rc;
  149. m_hWndParent = hWndParent;
  150. GetWindowWRect(m_hWndParent, &rc);
  151. const WCHAR *psz = GetStringResourceW(idTitle);
  152. int len = wcslen(psz);
  153. HDC hdc = GetDC(hWndParent);
  154. GetTextExtentPoint32W(hdc, psz, len, (LPSIZE)&sSize);
  155. ReleaseDC(m_hWndParent, hdc);
  156. width = sSize.cx;
  157. if(lang == LANG_JAPANESE || lang == LANG_CHINESE || lang == LANG_KOREAN)
  158. width+=100;
  159. if (width < CX_BOOK)
  160. width = CX_BOOK;
  161. if ( 0 /*!fIsThisNewShell4*/ )
  162. width += HPAD;
  163. #ifdef BIDI
  164. m_hWnd = CreateWindowExW(WS_EX_WINDOWEDGE | /* WS_EX_TOPMOST | */
  165. (fForceLtr ? 0 : WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR),
  166. wtxtAnimateClassName, psz, WS_POPUP | WS_BORDER | WS_CAPTION,
  167. rc.left + rc.cx / 2 - width / 2,
  168. rc.top + rc.cy / 2 - CY_BOOK / 2 + HPAD,
  169. width + GetSystemMetrics(SM_CXBORDER) * 2 + 2,
  170. CY_BOOK + GetSystemMetrics(SM_CYBORDER) * 2 + VPAD +
  171. GetSystemMetrics(SM_CYCAPTION),
  172. (IsWindowVisible(m_hWndParent)) ? m_hWndParent : NULL,
  173. NULL, hInsNow, NULL);
  174. #else
  175. m_hWnd = CreateWindowExW(WS_EX_WINDOWEDGE /* | WS_EX_TOPMOST*/,
  176. wtxtAnimateClassName, psz, WS_POPUP | WS_BORDER | WS_CAPTION,
  177. rc.left + rc.cx / 2 - width / 2,
  178. rc.top + rc.cy / 2 - CY_BOOK / 2 + HPAD,
  179. width + GetSystemMetrics(SM_CXBORDER) * 2 + 2,
  180. CY_BOOK + GetSystemMetrics(SM_CYBORDER) * 2 + VPAD +
  181. GetSystemMetrics(SM_CYCAPTION),
  182. (IsWindowVisible(m_hWndParent)) ? m_hWndParent : NULL,
  183. NULL, _Module.GetModuleInstance(), NULL);
  184. #endif
  185. }
  186. else
  187. {
  188. WNDCLASS wc;
  189. SIZE sSize;
  190. ZeroMemory(&wc, sizeof(wc));
  191. // Register Main window class
  192. wc.hInstance = _Module.GetModuleInstance();
  193. wc.style = CS_BYTEALIGNWINDOW | CS_CLASSDC;
  194. wc.lpfnWndProc = StatusWndProc;
  195. wc.lpszClassName = (LPCSTR) txtAnimateClassName;
  196. wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  197. wc.hIcon = LoadIcon(_Module.GetResourceInstance(), "Icon!HTMLHelp");
  198. if (!RegisterClass(&wc))
  199. return FALSE;
  200. WRECT rc;
  201. m_hWndParent = hWndParent;
  202. GetWindowWRect(m_hWndParent, &rc);
  203. HDC hdc = GetDC(m_hWndParent);
  204. PSTR psz = (PSTR) GetStringResource(idTitle);
  205. GetTextExtentPoint32(hdc, psz, (int)strlen(psz), (LPSIZE)&sSize);
  206. width = sSize.cx;
  207. if(lang == LANG_JAPANESE || lang == LANG_CHINESE || lang == LANG_KOREAN)
  208. width+=100;
  209. if (width < CX_BOOK)
  210. width = CX_BOOK;
  211. if ( 0 /*!fIsThisNewShell4*/ )
  212. width += HPAD;
  213. ReleaseDC(m_hWndParent, hdc);
  214. #ifdef BIDI
  215. m_hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | /* WS_EX_TOPMOST | */
  216. (fForceLtr ? 0 : WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR),
  217. (LPCSTR) txtAnimateClassName, psz, WS_POPUP | WS_BORDER | WS_CAPTION,
  218. rc.left + rc.cx / 2 - width / 2,
  219. rc.top + rc.cy / 2 - CY_BOOK / 2 + HPAD,
  220. width + GetSystemMetrics(SM_CXBORDER) * 2 + 2,
  221. CY_BOOK + GetSystemMetrics(SM_CYBORDER) * 2 + VPAD +
  222. GetSystemMetrics(SM_CYCAPTION),
  223. (IsWindowVisible(m_hWndParent)) ? m_hWndParent : NULL,
  224. NULL, hInsNow, NULL);
  225. #else
  226. m_hWnd = CreateWindowEx(WS_EX_WINDOWEDGE /* | WS_EX_TOPMOST*/,
  227. (LPCSTR) txtAnimateClassName, psz, WS_POPUP | WS_BORDER | WS_CAPTION,
  228. rc.left + rc.cx / 2 - width / 2,
  229. rc.top + rc.cy / 2 - CY_BOOK / 2 + HPAD,
  230. width + GetSystemMetrics(SM_CXBORDER) * 2 + 2,
  231. CY_BOOK + GetSystemMetrics(SM_CYBORDER) * 2 + VPAD +
  232. GetSystemMetrics(SM_CYCAPTION),
  233. (IsWindowVisible(m_hWndParent)) ? m_hWndParent : NULL,
  234. NULL, _Module.GetModuleInstance(), NULL);
  235. #endif
  236. }
  237. ASSERT(m_hWnd);
  238. SetPosition((width - CX_BOOK) / 2, VPAD / 4);
  239. EnableWindow( m_hWndParent, FALSE );
  240. if (!m_hWnd) {
  241. UnregisterClass((LPCSTR)txtAnimateClassName, _Module.GetModuleInstance());
  242. return FALSE;
  243. }
  244. m_fShown = FALSE;
  245. return TRUE;
  246. }
  247. ///////////////////////////// ANIMATE CLASS ///////////////////////////////
  248. Animate::Animate()
  249. {
  250. m_hDCBmp = NULL;
  251. m_hWnd = NULL;
  252. m_originalTickCount = GetTickCount();
  253. m_hWndParent = NULL;
  254. m_hBmpTemp = NULL;
  255. m_hBmpIml = NULL;
  256. }
  257. Animate::~Animate(void)
  258. {
  259. SafeDeleteDC( m_hDCBmp )
  260. SafeDeleteObject( m_hBmpTemp );
  261. SafeDeleteObject( m_hBmpIml );
  262. EnableWindow( m_hWndParent, TRUE );
  263. if (m_hWnd) {
  264. DestroyWindow(m_hWnd);
  265. m_hWnd = NULL;
  266. UnregisterClass((LPCSTR) txtAnimateClassName, _Module.GetModuleInstance());
  267. }
  268. }
  269. /***************************************************************************
  270. FUNCTION: AnimFrame
  271. PURPOSE: Displays one frame of the "build index" animation
  272. in the specified device context.
  273. PARAMETERS:
  274. hdc
  275. x
  276. y
  277. RETURNS:
  278. COMMENTS:
  279. MODIFICATION DATES:
  280. 04-Nov-1993 [niklasb]
  281. ***************************************************************************/
  282. void PASCAL Animate::NextFrame(void)
  283. {
  284. DWORD curTickCount = GetTickCount();
  285. if (curTickCount - m_oldTickCount < ANIMATE_INCREMENTS)
  286. return;
  287. m_oldTickCount = curTickCount;
  288. // Delay showing the window for one second. If we get done before then,
  289. // then there's no need to have gone to all the trouble.
  290. if (!m_fShown) {
  291. if (curTickCount - m_originalTickCount < 1000)
  292. return;
  293. HBITMAP hbmBooks = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDBMP_BOOK));
  294. HBITMAP hbmPens = LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDBMP_PENS));
  295. HDC hdcTemp = CreateCompatibleDC(NULL);
  296. m_hDCBmp = CreateCompatibleDC(NULL);
  297. HBITMAP hbmpOldBook = NULL;
  298. m_hBmpTemp = NULL;
  299. if (m_hDCBmp) {
  300. hbmpOldBook = (HBITMAP)SelectObject(m_hDCBmp, hbmBooks);
  301. m_hBmpTemp = CreateCompatibleBitmap(m_hDCBmp, CX_DRAWAREA, CY_DRAWAREA);
  302. }
  303. if (!hbmBooks || !hbmPens || !m_hBmpTemp || !m_hDCBmp || !hdcTemp) {
  304. if (hbmpOldBook)
  305. SelectObject(m_hDCBmp, hbmpOldBook);
  306. SafeDeleteObject( hbmpOldBook );
  307. SafeDeleteObject( hbmBooks );
  308. SafeDeleteObject( hbmPens );
  309. SafeDeleteDC( hdcTemp );
  310. return;
  311. }
  312. m_hBmpIml = CreateCompatibleBitmap(m_hDCBmp, CX_DRAWAREA * C_FRAMES, CY_DRAWAREA);
  313. HBITMAP hbmpOldTemp = (HBITMAP) SelectObject(hdcTemp, m_hBmpTemp);
  314. HBITMAP hbmpOldBmp = (HBITMAP) SelectObject(m_hDCBmp, hbmBooks);
  315. // Create the frames in which the pen scribbles on the open book.
  316. m_iFrame = 0;
  317. for (int y = 0; y < C_VERT_STROKES; y++) {
  318. for (int x = 0; x < C_HORZ_STROKES; x++) {
  319. // Show the book on a white background.
  320. PatBlt(hdcTemp, 0, 0, CX_DRAWAREA, CY_DRAWAREA, WHITENESS);
  321. SelectObject(m_hDCBmp, hbmBooks);
  322. BitBlt(hdcTemp, X_BOOK, Y_BOOK, CX_BOOK, CY_BOOK, m_hDCBmp,
  323. (C_BOOKS - 1) * CX_BOOK, 0, SRCCOPY);
  324. // Add in the scribbled "text".
  325. POINT pt;
  326. for (int yDraw = 0; yDraw < y; yDraw++) {
  327. for (int xDraw = 0; xDraw < C_HORZ_STROKES; xDraw++) {
  328. PointFromStroke(xDraw, yDraw, &pt);
  329. SetPixel(hdcTemp, pt.x, pt.y + CY_PEN - 1,
  330. (xDraw & 1) ? clrPenA : clrPenB);
  331. }
  332. }
  333. for (int xDraw = 0; xDraw <= x; xDraw++) {
  334. PointFromStroke(xDraw, y, &pt);
  335. SetPixel(hdcTemp, pt.x, pt.y + CY_PEN - 1,
  336. (xDraw & 1) ? clrPenA : clrPenB);
  337. }
  338. // Add in the pen using the SRCAND operation.
  339. SelectObject(m_hDCBmp, hbmPens);
  340. BitBlt(hdcTemp, pt.x, pt.y, CX_PEN, CY_PEN, m_hDCBmp,
  341. (m_iFrame & 1) ? CX_PEN : (m_iFrame & 2) * CX_PEN, 0, SRCAND);
  342. SelectObject(m_hDCBmp, m_hBmpIml);
  343. BitBlt(m_hDCBmp, m_iFrame * CX_DRAWAREA, 0, CX_DRAWAREA, CY_DRAWAREA,
  344. hdcTemp, 0, 0, SRCCOPY);
  345. m_iFrame++;
  346. }
  347. }
  348. // Blast a white background into the temporary bitmap, and
  349. // select the books bitmap.
  350. PatBlt(hdcTemp, 0, 0, CX_DRAWAREA, CY_DRAWAREA, WHITENESS);
  351. // Add the frames for the page turning (from the books bitmap).
  352. for (int iBook = 0; iBook < C_BOOKS; iBook++) {
  353. SelectObject(m_hDCBmp, hbmBooks);
  354. BitBlt(hdcTemp, X_BOOK, Y_BOOK, CX_BOOK, CY_BOOK,
  355. m_hDCBmp, iBook * CX_BOOK, 0, SRCCOPY);
  356. SelectObject(m_hDCBmp, m_hBmpIml);
  357. BitBlt(m_hDCBmp, m_iFrame * CX_DRAWAREA, 0, CX_DRAWAREA, CY_DRAWAREA,
  358. hdcTemp, 0, 0, SRCCOPY);
  359. m_iFrame++;
  360. }
  361. SelectObject(hdcTemp, hbmpOldTemp);
  362. m_iFrame = 0;
  363. if (hbmpOldBook)
  364. SelectObject(m_hDCBmp, hbmpOldBook);
  365. SafeDeleteObject(hbmpOldBook);
  366. SafeDeleteObject(hbmBooks);
  367. SafeDeleteObject(hbmPens);
  368. SafeDeleteDC( hdcTemp );
  369. m_fShown = TRUE;
  370. ShowWindow(m_hWnd, SW_NORMAL);
  371. }
  372. ASSERT(IsValidWindow(m_hWnd));
  373. HDC hdc = GetDC(m_hWnd);
  374. HBITMAP hbmpOld = (HBITMAP) SelectObject(m_hDCBmp, m_hBmpIml);
  375. BitBlt(hdc, m_xPos, m_yPos, CX_DRAWAREA, CY_DRAWAREA, m_hDCBmp,
  376. m_iFrame * CX_DRAWAREA, 0, SRCCOPY);
  377. SelectObject(m_hDCBmp, hbmpOld);
  378. ReleaseDC(m_hWnd, hdc);
  379. // Next time draw the next frame.
  380. if (++m_iFrame > C_FRAMES) {
  381. m_iFrame = 0;
  382. }
  383. }
  384. static VOID FASTCALL PointFromStroke(int xStroke, int yStroke, POINT* lppt)
  385. {
  386. int cx = (C_HORZ_STROKES / 2) - xStroke;
  387. lppt->x = X_PEN + xStroke * CX_STROKE;
  388. lppt->y = Y_PEN + yStroke * CY_STROKE + cx * cx / 10;
  389. }