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.

403 lines
13 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: FSWindow
  3. //
  4. // Desc: This code will allow you to update a window in DirectDraw full-screen
  5. // exclusive mode on a device that doesn't support GDI. They will also
  6. // handle devices that do support GDI.
  7. //
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation. All rights reserved.
  10. //-----------------------------------------------------------------------------
  11. #ifndef WIN32_LEAN_AND_MEAN
  12. #define WIN32_LEAN_AND_MEAN
  13. #endif
  14. //-----------------------------------------------------------------------------
  15. // Include files
  16. //-----------------------------------------------------------------------------
  17. #include "dconfigp.h"
  18. //-----------------------------------------------------------------------------
  19. // Local definitions
  20. //-----------------------------------------------------------------------------
  21. static IDirectDraw7 *ddObject = NULL;
  22. static IDirectDrawSurface7 *ddFrontBuffer = NULL;
  23. static IDirectDrawSurface7 *ddBackBuffer = NULL;
  24. static IDirectDrawClipper *ddClipper = NULL;
  25. static SIZE structSurfaceSize = {0, 0};
  26. static BOOL bNonGDI = FALSE;
  27. static HWND hwndFSWindow = NULL;
  28. static HBITMAP hwndFSWindowBMP = NULL;
  29. static HWND hwndAppWindow = NULL;
  30. //-----------------------------------------------------------------------------
  31. // Name: CreateDibBMP()
  32. // Desc: Created an empty bitmap, used exclusively in CreateBMPFromWindow().
  33. // Note that this is an internal (not exported) function.
  34. //-----------------------------------------------------------------------------
  35. static HBITMAP
  36. CreateDibBMP(HDC hdc, int w, int h, unsigned short bpp)
  37. {
  38. LPVOID lpBits;
  39. struct
  40. {
  41. BITMAPINFOHEADER bi;
  42. DWORD ct[256];
  43. } dib;
  44. dib.bi.biSize = sizeof(BITMAPINFOHEADER);
  45. dib.bi.biWidth = w;
  46. dib.bi.biHeight = h;
  47. dib.bi.biBitCount = bpp;
  48. dib.bi.biPlanes = 1;
  49. dib.bi.biCompression = 0;
  50. dib.bi.biSizeImage = 0;
  51. dib.bi.biClrUsed = 0;
  52. if (bpp == 15)
  53. {
  54. dib.bi.biBitCount = 16;
  55. }
  56. else
  57. if (bpp == 16)
  58. {
  59. dib.bi.biCompression = BI_BITFIELDS;
  60. dib.ct[0] = 0xF800;
  61. dib.ct[1] = 0x07E0;
  62. dib.ct[2] = 0x001F;
  63. }
  64. return CreateDIBSection(hdc, (LPBITMAPINFO) & dib, DIB_RGB_COLORS, &lpBits,
  65. NULL, 0);
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Name: CreateBMPFromWindow()
  69. // Desc: Takes the hwnd of the content window, and returns a bitmap handle.
  70. // Note that this is an internal (not exported) function.
  71. //-----------------------------------------------------------------------------
  72. static HBITMAP
  73. CreateBMPFromWindow(HWND hwnd)
  74. {
  75. RECT rc;
  76. int x;
  77. int y;
  78. int cx;
  79. int cy;
  80. HDC hdcScreen;
  81. HDC hdcMemory;
  82. HBITMAP hbmBitmap;
  83. // Create a bitmap of the window passed in
  84. GetWindowRect(hwnd, &rc);
  85. x = rc.left;
  86. y = rc.top;
  87. cx = rc.right - rc.left;
  88. cy = rc.bottom - rc.top;
  89. hdcScreen = GetDC(NULL);
  90. hdcMemory = CreateCompatibleDC(NULL);
  91. hbmBitmap = CreateDibBMP(hdcScreen, cx, cy, 16);
  92. // BLT the image from screen to bitmap
  93. SelectObject(hdcMemory, hbmBitmap);
  94. BitBlt(hdcMemory, 0, 0, cx, cy, hdcScreen, x, y, SRCCOPY);
  95. DeleteDC(hdcMemory);
  96. ReleaseDC(NULL, hdcScreen);
  97. return hbmBitmap;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Name: FSWindow_Init()
  101. // Desc: Does preliminary setup of global values for FSWindow. It should get
  102. // called each time DirectDraw surfaces are altered (i.e. changes to the
  103. // device that the client application is running under).
  104. //-----------------------------------------------------------------------------
  105. void
  106. FSWindow_Init(HWND hwndApp, IDirectDraw7 *dd, IDirectDrawSurface7 *FrontBuffer,
  107. IDirectDrawSurface7 *BackBuffer)
  108. {
  109. DDSURFACEDESC2 ddsd;
  110. DDCAPS ddcaps;
  111. // Save handle to application window
  112. hwndAppWindow = hwndApp;
  113. ZeroMemory(&ddcaps, sizeof(ddcaps));
  114. ddcaps.dwSize = sizeof(ddcaps);
  115. dd->GetCaps(&ddcaps, NULL);
  116. if (ddcaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED)
  117. bNonGDI = FALSE;
  118. else
  119. bNonGDI = TRUE;
  120. // Save DirectDraw object passed in
  121. ddObject = dd;
  122. // Save buffers passed in
  123. ddFrontBuffer = FrontBuffer;
  124. ddBackBuffer = BackBuffer;
  125. // Get DirectDraw surface dimensions
  126. ZeroMemory(&ddsd, sizeof(ddsd));
  127. ddsd.dwSize = sizeof(ddsd);
  128. ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
  129. ddBackBuffer->GetSurfaceDesc(&ddsd);
  130. structSurfaceSize.cx = ddsd.dwWidth;
  131. structSurfaceSize.cy = ddsd.dwHeight;
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Name: FSWindow_Begin()
  135. // Desc: Prepairs the DirectDraw surface depending on 3D hardware. It should
  136. // get called whenever a window (represented by the hwnd parameter) needs
  137. // to be displayed under DirectDraw. FSWindow_Begin() should also get
  138. // called if the window changes its content (if its static content
  139. // becomes dynamic, and vice-versa).
  140. //-----------------------------------------------------------------------------
  141. HWND
  142. FSWindow_Begin(HWND hwnd, BOOL bStaticContent)
  143. {
  144. RECT rc;
  145. // If no handle passed in, assume existing content window
  146. if (hwnd == NULL)
  147. hwnd = hwndFSWindow;
  148. if (hwnd == NULL)
  149. return NULL;
  150. if (bNonGDI)
  151. {
  152. // Constrain cursor to DirectDraw surface
  153. rc.left =0;
  154. rc.top = 0;
  155. rc.right = structSurfaceSize.cx;
  156. rc.bottom = structSurfaceSize.cy;
  157. ClipCursor(&rc);
  158. // Clear out lingering content
  159. if (hwndFSWindowBMP)
  160. DeleteObject(hwndFSWindowBMP);
  161. hwndFSWindowBMP = NULL;
  162. // Need to create an image of content window just once
  163. if (bStaticContent)
  164. {
  165. if (!FSWindow_IsActive())
  166. UpdateWindow(hwnd);
  167. // Assign content window image to global
  168. hwndFSWindowBMP = CreateBMPFromWindow(hwnd);
  169. }
  170. }
  171. else
  172. {
  173. //Create a clipper (used in IDirectDrawSurface::Blt call)
  174. if (ddObject->CreateClipper(0, &ddClipper, NULL) == DD_OK)
  175. ddClipper->SetHWnd(0, hwndAppWindow);
  176. // Normal GDI device, so just flip to GDI so content window can be seen
  177. ddObject->FlipToGDISurface();
  178. }
  179. hwndFSWindow = hwnd;
  180. return hwndFSWindow;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Name: FSWindow_End()
  184. // Desc: Deletes objects associated with the content window. Note that these
  185. // are objects created within this module, not objects created by the
  186. // calling client (e.g. content window). Call this function whenever the
  187. // content window is destroyed (e.g. WM_CLOSE).
  188. //-----------------------------------------------------------------------------
  189. void
  190. FSWindow_End()
  191. {
  192. if (hwndFSWindow)
  193. hwndFSWindow = NULL;
  194. if (hwndFSWindowBMP)
  195. DeleteObject(hwndFSWindowBMP);
  196. hwndFSWindowBMP = NULL;
  197. if (bNonGDI)
  198. ClipCursor(NULL);
  199. // Get rid of clipper object
  200. if (ddClipper)
  201. {
  202. ddClipper->Release();
  203. ddClipper = NULL;
  204. }
  205. }
  206. //-----------------------------------------------------------------------------
  207. // Name: FSWindow_Update()
  208. // Desc: Is responsible for the actual rendering of the content window
  209. // (held in global hwndFSWindow). This function must be called each
  210. // time a DirectDraw frame gets rendered and FSWindow_IsActive() returns
  211. // TRUE, so it should be placed in the main application's DirectDraw
  212. // rendering routine. An example of this might look like the following:
  213. //
  214. // void RenderFrame()
  215. // {
  216. // if (FSWindow_IsActive())
  217. // FSWindow_Update();
  218. // else
  219. // FrontBuffer->Blt(...);
  220. // }
  221. //-----------------------------------------------------------------------------
  222. void
  223. FSWindow_Update()
  224. {
  225. POINT pt;
  226. RECT rc;
  227. int x;
  228. int y;
  229. int cx;
  230. int cy;
  231. HDC hdcScreen;
  232. HDC hdcBackBuffer;
  233. HRGN hrgn;
  234. HDC hdcMemory;
  235. static HCURSOR MouseCursor;
  236. static ICONINFO IconInfo;
  237. HCURSOR MouseCursorCur;
  238. if (bNonGDI)
  239. {
  240. GetWindowRect(hwndFSWindow, &rc);
  241. x = rc.left;
  242. y = rc.top;
  243. cx = rc.right - rc.left;
  244. cy = rc.bottom - rc.top;
  245. // Get a DC to the screen (where our window is) and
  246. // Get a DC to the backbuffer on the non-GDI device (where we need to copy it)
  247. hdcScreen = GetDC(NULL);
  248. ddBackBuffer->GetDC(&hdcBackBuffer);
  249. // If window has a complex region associated with it, be sure to include it in the draw
  250. hrgn = CreateRectRgn(0, 0, 0, 0);
  251. if (GetWindowRgn(hwndFSWindow, hrgn) == COMPLEXREGION)
  252. {
  253. OffsetRgn(hrgn, rc.left, rc.top);
  254. SelectClipRgn(hdcBackBuffer, hrgn);
  255. }
  256. // If content window is static (no animations, roll-overs, etc.) then
  257. // create a dc for the bitmap and blt to the back buffer
  258. if (FSWindow_IsStatic())
  259. {
  260. hdcMemory = CreateCompatibleDC(NULL);
  261. SelectObject(hdcMemory, hwndFSWindowBMP);
  262. BitBlt(hdcBackBuffer, x, y, cx, cy, hdcMemory, 0, 0, SRCCOPY);
  263. DeleteDC(hdcMemory);
  264. }
  265. else
  266. {
  267. // Special case for potentially quirky non-GDI drivers
  268. #if 0
  269. // If content is dynamic (updated each frame), always grab the screen copy
  270. // by calling CreateBMPFromWindow to update image held in Bitmap
  271. HDC hdcMemory = CreateCompatibleDC(NULL);
  272. HBITMAP Bitmap = CreateBMPFromWindow(hwndFSWindow);
  273. SelectObject(hdcMemory, Bitmap);
  274. BitBlt(hdcBackBuffer, x, y, cx, cy, hdcMemory, 0, 0, SRCCOPY);
  275. DeleteDC(hdcMemory);
  276. DeleteObject(Bitmap);
  277. #else
  278. // Do a blt directly from the windows screen to the backbuffer
  279. BitBlt(hdcBackBuffer, x, y, cx, cy, hdcScreen, x, y, SRCCOPY);
  280. #endif
  281. }
  282. // Remove clipping region and clean up
  283. SelectClipRgn(hdcBackBuffer, NULL);
  284. DeleteObject(hrgn);
  285. // Now draw the mouse on the backbuffer
  286. MouseCursorCur = GetCursor();
  287. if (MouseCursorCur != MouseCursor)
  288. {
  289. MouseCursor = MouseCursorCur;
  290. GetIconInfo(MouseCursor, &IconInfo);
  291. if (IconInfo.hbmMask)
  292. DeleteObject(IconInfo.hbmMask);
  293. if (IconInfo.hbmColor)
  294. DeleteObject(IconInfo.hbmColor);
  295. }
  296. GetCursorPos(&pt);
  297. pt.x -= IconInfo.xHotspot;
  298. pt.y -= IconInfo.yHotspot;
  299. DrawIcon(hdcBackBuffer, pt.x, pt.y, MouseCursor);
  300. ddBackBuffer->ReleaseDC(hdcBackBuffer);
  301. ReleaseDC(NULL, hdcScreen);
  302. ddFrontBuffer->Flip(NULL, DDFLIP_WAIT);
  303. }
  304. else
  305. {
  306. // GDI hardware
  307. // Update the surface with a blt
  308. ddFrontBuffer->SetClipper(ddClipper);
  309. ddFrontBuffer->Blt(NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
  310. }
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Name: FSWindow_IsActive()
  314. // Desc: Simply checks to see if there's a content window displayed. This check
  315. // should be made prior to calling FSWindow_Update().
  316. //-----------------------------------------------------------------------------
  317. BOOL
  318. FSWindow_IsActive(void)
  319. {
  320. return (hwndFSWindow != NULL);
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Name: FSWindow_IsStatic()
  324. // Desc: Checks to see whether or not the content window needs to be regularly
  325. // updated (its content is dynamic, such as an animation or text entry
  326. // field). A static window is created (an image of the window created
  327. // with a call to CreateBMPFromWindow()) once and used over and over.
  328. //-----------------------------------------------------------------------------
  329. BOOL
  330. FSWindow_IsStatic(void)
  331. {
  332. return (hwndFSWindowBMP != NULL);
  333. }