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.

480 lines
13 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. preview.c
  5. Abstract:
  6. This module contains the code for console preview window
  7. Author:
  8. Therese Stowell (thereses) Feb-3-1992 (swiped from Win3.1)
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /* ----- Equates ----- */
  14. #define PREVIEW_HSCROLL 0x01
  15. #define PREVIEW_VSCROLL 0x02
  16. /* ----- Prototypes ----- */
  17. void AspectPoint(
  18. RECT* rectPreview,
  19. POINT* pt);
  20. LONG AspectScale(
  21. LONG n1,
  22. LONG n2,
  23. LONG m);
  24. /* ----- Globals ----- */
  25. POINT NonClientSize;
  26. RECT WindowRect;
  27. DWORD PreviewFlags;
  28. VOID
  29. UpdatePreviewRect(VOID)
  30. /*++
  31. Update the global window size and dimensions
  32. --*/
  33. {
  34. POINT MinSize;
  35. POINT MaxSize;
  36. POINT WindowSize;
  37. PFONT_INFO lpFont;
  38. HMONITOR hMonitor;
  39. MONITORINFO mi;
  40. /*
  41. * Get the font pointer
  42. */
  43. lpFont = &FontInfo[CurrentFontIndex];
  44. /*
  45. * Get the window size
  46. */
  47. MinSize.x = (GetSystemMetrics(SM_CXMIN)-NonClientSize.x) / lpFont->Size.X;
  48. MinSize.y = (GetSystemMetrics(SM_CYMIN)-NonClientSize.y) / lpFont->Size.Y;
  49. MaxSize.x = GetSystemMetrics(SM_CXFULLSCREEN) / lpFont->Size.X;
  50. MaxSize.y = GetSystemMetrics(SM_CYFULLSCREEN) / lpFont->Size.Y;
  51. WindowSize.x = max(MinSize.x, min(MaxSize.x, gpStateInfo->WindowSize.X));
  52. WindowSize.y = max(MinSize.y, min(MaxSize.y, gpStateInfo->WindowSize.Y));
  53. /*
  54. * Get the window rectangle, making sure it's at least twice the
  55. * size of the non-client area.
  56. */
  57. WindowRect.left = gpStateInfo->WindowPosX;
  58. WindowRect.top = gpStateInfo->WindowPosY;
  59. WindowRect.right = WindowSize.x * lpFont->Size.X + NonClientSize.x;
  60. if (WindowRect.right < NonClientSize.x * 2) {
  61. WindowRect.right = NonClientSize.x * 2;
  62. }
  63. WindowRect.right += WindowRect.left;
  64. WindowRect.bottom = WindowSize.y * lpFont->Size.Y + NonClientSize.y;
  65. if (WindowRect.bottom < NonClientSize.y * 2) {
  66. WindowRect.bottom = NonClientSize.y * 2;
  67. }
  68. WindowRect.bottom += WindowRect.top;
  69. /*
  70. * Get information about the monitor we're on
  71. */
  72. hMonitor = MonitorFromRect(&WindowRect, MONITOR_DEFAULTTONEAREST);
  73. mi.cbSize = sizeof(mi);
  74. GetMonitorInfo(hMonitor, &mi);
  75. gcxScreen = mi.rcWork.right - mi.rcWork.left;
  76. gcyScreen = mi.rcWork.bottom - mi.rcWork.top;
  77. /*
  78. * Convert window rectangle to monitor relative coordinates
  79. */
  80. WindowRect.right -= WindowRect.left;
  81. WindowRect.left -= mi.rcWork.left;
  82. WindowRect.bottom -= WindowRect.top;
  83. WindowRect.top -= mi.rcWork.top;
  84. /*
  85. * Update the display flags
  86. */
  87. if (WindowSize.x < gpStateInfo->ScreenBufferSize.X) {
  88. PreviewFlags |= PREVIEW_HSCROLL;
  89. } else {
  90. PreviewFlags &= ~PREVIEW_HSCROLL;
  91. }
  92. if (WindowSize.y < gpStateInfo->ScreenBufferSize.Y) {
  93. PreviewFlags |= PREVIEW_VSCROLL;
  94. } else {
  95. PreviewFlags &= ~PREVIEW_VSCROLL;
  96. }
  97. }
  98. VOID
  99. InvalidatePreviewRect(HWND hWnd)
  100. /*++
  101. Invalidate the area covered by the preview "window"
  102. --*/
  103. {
  104. RECT rectWin;
  105. RECT rectPreview;
  106. /*
  107. * Get the size of the preview "screen"
  108. */
  109. GetClientRect(hWnd, &rectPreview);
  110. /*
  111. * Get the dimensions of the preview "window" and scale it to the
  112. * preview "screen"
  113. */
  114. rectWin.left = WindowRect.left;
  115. rectWin.top = WindowRect.top;
  116. rectWin.right = WindowRect.left + WindowRect.right;
  117. rectWin.bottom = WindowRect.top + WindowRect.bottom;
  118. AspectPoint(&rectPreview, (POINT*)&rectWin.left);
  119. AspectPoint(&rectPreview, (POINT*)&rectWin.right);
  120. /*
  121. * Invalidate the area covered by the preview "window"
  122. */
  123. InvalidateRect(hWnd, &rectWin, FALSE);
  124. }
  125. VOID
  126. PreviewPaint(
  127. PAINTSTRUCT* pPS,
  128. HWND hWnd
  129. )
  130. /*++
  131. Paints the font preview. This is called inside the paint message
  132. handler for the preview window
  133. --*/
  134. {
  135. RECT rectWin;
  136. RECT rectPreview;
  137. HBRUSH hbrFrame;
  138. HBRUSH hbrTitle;
  139. HBRUSH hbrOld;
  140. HBRUSH hbrClient;
  141. HBRUSH hbrBorder;
  142. HBRUSH hbrButton;
  143. HBRUSH hbrScroll;
  144. HBRUSH hbrDesktop;
  145. POINT ptButton;
  146. POINT ptScroll;
  147. HDC hDC;
  148. HBITMAP hBitmap;
  149. HBITMAP hBitmapOld;
  150. COLORREF rgbClient;
  151. /*
  152. * Get the size of the preview "screen"
  153. */
  154. GetClientRect(hWnd, &rectPreview);
  155. /*
  156. * Get the dimensions of the preview "window" and scale it to the
  157. * preview "screen"
  158. */
  159. rectWin = WindowRect;
  160. AspectPoint(&rectPreview, (POINT*)&rectWin.left);
  161. AspectPoint(&rectPreview, (POINT*)&rectWin.right);
  162. /*
  163. * Compute the dimensions of some other window components
  164. */
  165. ptButton.x = GetSystemMetrics(SM_CXSIZE);
  166. ptButton.y = GetSystemMetrics(SM_CYSIZE);
  167. AspectPoint(&rectPreview, &ptButton);
  168. ptButton.y *= 2; /* Double the computed size for "looks" */
  169. ptScroll.x = GetSystemMetrics(SM_CXVSCROLL);
  170. ptScroll.y = GetSystemMetrics(SM_CYHSCROLL);
  171. AspectPoint(&rectPreview, &ptScroll);
  172. /*
  173. * Create the memory device context
  174. */
  175. hDC = CreateCompatibleDC(pPS->hdc);
  176. hBitmap = CreateCompatibleBitmap(pPS->hdc,
  177. rectPreview.right,
  178. rectPreview.bottom);
  179. hBitmapOld = SelectObject(hDC, hBitmap);
  180. /*
  181. * Create the brushes
  182. */
  183. hbrBorder = CreateSolidBrush(GetSysColor(COLOR_ACTIVEBORDER));
  184. hbrTitle = CreateSolidBrush(GetSysColor(COLOR_ACTIVECAPTION));
  185. hbrFrame = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME));
  186. hbrButton = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  187. hbrScroll = CreateSolidBrush(GetSysColor(COLOR_SCROLLBAR));
  188. hbrDesktop = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
  189. rgbClient = GetNearestColor(hDC, ScreenBkColor(gpStateInfo));
  190. hbrClient = CreateSolidBrush(rgbClient);
  191. /*
  192. * Erase the clipping area
  193. */
  194. FillRect(hDC, &(pPS->rcPaint), hbrDesktop);
  195. /*
  196. * Fill in the whole window with the client brush
  197. */
  198. hbrOld = SelectObject(hDC, hbrClient);
  199. PatBlt(hDC, rectWin.left, rectWin.top,
  200. rectWin.right - 1, rectWin.bottom - 1, PATCOPY);
  201. /*
  202. * Fill in the caption bar
  203. */
  204. SelectObject(hDC, hbrTitle);
  205. PatBlt(hDC, rectWin.left + 3, rectWin.top + 3,
  206. rectWin.right - 7, ptButton.y - 2, PATCOPY);
  207. /*
  208. * Draw the "buttons"
  209. */
  210. SelectObject(hDC, hbrButton);
  211. PatBlt(hDC, rectWin.left + 3, rectWin.top + 3,
  212. ptButton.x, ptButton.y - 2, PATCOPY);
  213. PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptButton.x,
  214. rectWin.top + 3,
  215. ptButton.x, ptButton.y - 2, PATCOPY);
  216. PatBlt(hDC, rectWin.left + rectWin.right - 4 - 2 * ptButton.x - 1,
  217. rectWin.top + 3,
  218. ptButton.x, ptButton.y - 2, PATCOPY);
  219. SelectObject(hDC, hbrFrame);
  220. PatBlt(hDC, rectWin.left + 3 + ptButton.x, rectWin.top + 3,
  221. 1, ptButton.y - 2, PATCOPY);
  222. PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptButton.x - 1,
  223. rectWin.top + 3,
  224. 1, ptButton.y - 2, PATCOPY);
  225. PatBlt(hDC, rectWin.left + rectWin.right - 4 - 2 * ptButton.x - 2,
  226. rectWin.top + 3,
  227. 1, ptButton.y - 2, PATCOPY);
  228. /*
  229. * Draw the scrollbars
  230. */
  231. SelectObject(hDC, hbrScroll);
  232. if (PreviewFlags & PREVIEW_HSCROLL) {
  233. PatBlt(hDC, rectWin.left + 3,
  234. rectWin.top + rectWin.bottom - 4 - ptScroll.y,
  235. rectWin.right - 7, ptScroll.y, PATCOPY);
  236. }
  237. if (PreviewFlags & PREVIEW_VSCROLL) {
  238. PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptScroll.x,
  239. rectWin.top + 1 + ptButton.y + 1,
  240. ptScroll.x, rectWin.bottom - 6 - ptButton.y, PATCOPY);
  241. if (PreviewFlags & PREVIEW_HSCROLL) {
  242. SelectObject(hDC, hbrFrame);
  243. PatBlt(hDC, rectWin.left + rectWin.right - 5 - ptScroll.x,
  244. rectWin.top + rectWin.bottom - 4 - ptScroll.y,
  245. 1, ptScroll.y, PATCOPY);
  246. PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptScroll.x,
  247. rectWin.top + rectWin.bottom - 5 - ptScroll.y,
  248. ptScroll.x, 1, PATCOPY);
  249. }
  250. }
  251. /*
  252. * Draw the interior window frame and caption frame
  253. */
  254. SelectObject(hDC, hbrFrame);
  255. PatBlt(hDC, rectWin.left + 2, rectWin.top + 2,
  256. 1, rectWin.bottom - 5, PATCOPY);
  257. PatBlt(hDC, rectWin.left + 2, rectWin.top + 2,
  258. rectWin.right - 5, 1, PATCOPY);
  259. PatBlt(hDC, rectWin.left + 2, rectWin.top + rectWin.bottom - 4,
  260. rectWin.right - 5, 1, PATCOPY);
  261. PatBlt(hDC, rectWin.left + rectWin.right - 4, rectWin.top + 2,
  262. 1, rectWin.bottom - 5, PATCOPY);
  263. PatBlt(hDC, rectWin.left + 2, rectWin.top + 1 + ptButton.y,
  264. rectWin.right - 5, 1, PATCOPY);
  265. /*
  266. * Draw the border
  267. */
  268. SelectObject(hDC, hbrBorder);
  269. PatBlt(hDC, rectWin.left + 1, rectWin.top + 1,
  270. 1, rectWin.bottom - 3, PATCOPY);
  271. PatBlt(hDC, rectWin.left + 1, rectWin.top + 1,
  272. rectWin.right - 3, 1, PATCOPY);
  273. PatBlt(hDC, rectWin.left + 1, rectWin.top + rectWin.bottom - 3,
  274. rectWin.right - 3, 1, PATCOPY);
  275. PatBlt(hDC, rectWin.left + rectWin.right - 3, rectWin.top + 1,
  276. 1, rectWin.bottom - 3, PATCOPY);
  277. /*
  278. * Draw the exterior window frame
  279. */
  280. SelectObject(hDC, hbrFrame);
  281. PatBlt(hDC, rectWin.left, rectWin.top,
  282. 1, rectWin.bottom - 1, PATCOPY);
  283. PatBlt(hDC, rectWin.left, rectWin.top,
  284. rectWin.right - 1, 1, PATCOPY);
  285. PatBlt(hDC, rectWin.left, rectWin.top + rectWin.bottom - 2,
  286. rectWin.right - 1, 1, PATCOPY);
  287. PatBlt(hDC, rectWin.left + rectWin.right - 2, rectWin.top,
  288. 1, rectWin.bottom - 1, PATCOPY);
  289. /*
  290. * Copy the memory device context to the screen device context
  291. */
  292. BitBlt(pPS->hdc, 0, 0, rectPreview.right, rectPreview.bottom,
  293. hDC, 0, 0, SRCCOPY);
  294. /*
  295. * Clean up everything
  296. */
  297. SelectObject(hDC, hbrOld);
  298. SelectObject(hDC, hBitmapOld);
  299. DeleteObject(hbrBorder);
  300. DeleteObject(hbrFrame);
  301. DeleteObject(hbrTitle);
  302. DeleteObject(hbrClient);
  303. DeleteObject(hbrButton);
  304. DeleteObject(hbrScroll);
  305. DeleteObject(hbrDesktop);
  306. DeleteObject(hBitmap);
  307. DeleteDC(hDC);
  308. }
  309. LRESULT
  310. PreviewWndProc(
  311. HWND hWnd,
  312. UINT wMessage,
  313. WPARAM wParam,
  314. LPARAM lParam
  315. )
  316. /*
  317. * PreviewWndProc
  318. * Handles the preview window
  319. */
  320. {
  321. PAINTSTRUCT ps;
  322. LPCREATESTRUCT lpcs;
  323. RECT rcWindow;
  324. int cx;
  325. int cy;
  326. switch (wMessage) {
  327. case WM_CREATE:
  328. /*
  329. * Figure out space used by non-client area
  330. */
  331. SetRect(&rcWindow, 0, 0, 50, 50);
  332. AdjustWindowRect(&rcWindow, WS_OVERLAPPEDWINDOW, FALSE);
  333. NonClientSize.x = rcWindow.right - rcWindow.left - 50;
  334. NonClientSize.y = rcWindow.bottom - rcWindow.top - 50;
  335. /*
  336. * Compute the size of the preview "window"
  337. */
  338. UpdatePreviewRect();
  339. /*
  340. * Scale the window so it has the same aspect ratio as the screen
  341. */
  342. lpcs = (LPCREATESTRUCT)lParam;
  343. cx = lpcs->cx;
  344. cy = AspectScale(gcyScreen, gcxScreen, cx);
  345. if (cy > lpcs->cy) {
  346. cy = lpcs->cy;
  347. cx = AspectScale(gcxScreen, gcyScreen, cy);
  348. }
  349. MoveWindow(hWnd, lpcs->x, lpcs->y, cx, cy, TRUE);
  350. break;
  351. case WM_PAINT:
  352. BeginPaint(hWnd, &ps);
  353. PreviewPaint(&ps, hWnd);
  354. EndPaint(hWnd, &ps);
  355. break;
  356. case CM_PREVIEW_UPDATE:
  357. InvalidatePreviewRect(hWnd);
  358. UpdatePreviewRect();
  359. /*
  360. * Make sure the preview "screen" has the correct aspect ratio
  361. */
  362. GetWindowRect(hWnd, &rcWindow);
  363. cx = rcWindow.right - rcWindow.left;
  364. cy = AspectScale(gcyScreen, gcxScreen, cx);
  365. if (cy != rcWindow.bottom - rcWindow.top) {
  366. SetWindowPos(hWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  367. }
  368. InvalidatePreviewRect(hWnd);
  369. break;
  370. default:
  371. return DefWindowProc(hWnd, wMessage, wParam, lParam);
  372. }
  373. return 0L;
  374. }
  375. /* AspectScale
  376. * Performs the following calculation in LONG arithmetic to avoid
  377. * overflow:
  378. * return = n1 * m / n2
  379. * This can be used to make an aspect ration calculation where n1/n2
  380. * is the aspect ratio and m is a known value. The return value will
  381. * be the value that corresponds to m with the correct apsect ratio.
  382. */
  383. LONG AspectScale(
  384. LONG n1,
  385. LONG n2,
  386. LONG m)
  387. {
  388. LONG Temp;
  389. Temp = n1 * m + (n2 >> 1);
  390. return Temp / n2;
  391. }
  392. /* AspectPoint
  393. * Scales a point to be preview-sized instead of screen-sized.
  394. */
  395. void AspectPoint(
  396. RECT* rectPreview,
  397. POINT* pt)
  398. {
  399. pt->x = AspectScale(rectPreview->right, gcxScreen, pt->x);
  400. pt->y = AspectScale(rectPreview->bottom, gcyScreen, pt->y);
  401. }