123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809 |
- //---------------------------------------------------------------------------------------------
- //
- // This file provides DirectDraw rendering services through FlipHELP, a programming
- // technique that allows for the rendering of non-DirectDraw-aware windows to the
- // DirectDraw GDI surface.
- //
- // Also of interest, and noted in this header, is FlipHelpES, which provides additional
- // services to FlipHELP. FlipHelpES allows for the rendering of out-of-process windows
- // (WOOPs) to the DirectDraw GDI surface. Prior to this, any activation of a window in
- // another process caused DirectDraw to minimize and mode-switch (its default behavior).
- //
- // Search on the term "fswindow" in the DirectX 6.1 SDK documentation for additional
- // details and alternative sample code.
- //
- //---------------------------------------------------------------------------------------------
- //
- // (C) Copyright 1995-1999 Microsoft Corp. All rights reserved.
- //
- // You have a royalty-free right to use, modify, reproduce and
- // distribute the Sample Files (and/or any modified version) in
- // any way you find useful, provided that you agree that
- // Microsoft has no warranty obligations or liability for any
- // Sample Application Files which are modified.
- //
- //---------------------------------------------------------------------------------------------
- #include "pch.h"
- #include "FlipHelp.h"
- //#include "FlipHelpES.h" // support for out-of-process windows (WOOPs)
- //
- // declare/define global
- //
- SIZE structSurfaceSize = {0, 0}; // DirectDraw front buffer dimensions
- //
- // declare/define module globals
- //
- static LPDIRECTDRAW2 ddObject = NULL;
- /*
- static LPDIRECTDRAWSURFACE3 ddFrontBuffer = NULL;
- static LPDIRECTDRAWSURFACE3 ddBackBuffer = NULL;
- */
- static LPDIRECTDRAWSURFACE2 ddFrontBuffer = NULL;
- static LPDIRECTDRAWSURFACE2 ddBackBuffer = NULL;
- static LPDIRECTDRAWCLIPPER ddClipper = NULL;
- static HWND hwndHelpWindow = NULL;
- static HBITMAP hwndHelpWindowBMP = NULL;
- static HWND hwndAppWindow = NULL;
- static HRESULT hrResult = 0;
- static BOOL f3Dfx = FALSE;
- static BOOL fDrawMouse = FALSE;
- static BOOL fBuffersSame = FALSE;
- static BOOL fUsingBadDriver = FALSE;
- static BOOL fStaticContent = FALSE;
- //
- // internal function prototypes
- //
- static HBITMAP CreateHelpBMP(HWND hwnd);
- static HBITMAP CreateDibBMP(HDC hdc, int w, int h, int bpp);
- static HRGN GetInvWindowRgn(HWND hwnd);
- //static LPDIRECTDRAW2 GetDDObjectFromDDSurface(LPDIRECTDRAWSURFACE3 ddSurface);
- static LPDIRECTDRAW2 GetDDObjectFromDDSurface(LPDIRECTDRAWSURFACE2 ddSurface);
- /*
- static BOOL CheckForBrokenDriver(LPDIRECTDRAWSURFACE3 pSurface);
- */
- static BOOL CheckForBrokenDriver(LPDIRECTDRAWSURFACE2 pSurface);
- static void GetOptimalDIBFormat(HDC hdc, BITMAPINFOHEADER *pbi);
- //
- // external function prototype
- //
- extern "C" int APIENTRY GetRandomRgn(HDC, HRGN, int); // GDI function to get a region from a HDC
- //---------------------------------------------------------------------------------------------
- // FlipHelp_Init() does preliminary setup of global values for FlipHelp. It should get
- // called each time DirectDraw surfaces are altered (i.e. changes to the device that
- // the client application is running under).
- //
- // Be sure to call FlipHelp_Release() prior to calling any subsequent FlipHelp_Init() calls,
- // otherwise, the reference count on the DirectDraw objects will become out of sync.
- //
- // Note that the buffers passed in are of type LPVOID. This allows DirectDraw buffers of
- // any surface interface type to be accepted. However, this function will fail if it
- // cannot get a base DirectDraw interface of type IID_IDirectDrawSurface.
- //
- // purpose: assigns local DD object and buffers, and sets globals
- // requires: handle to app window, front/back buffer pointers, initialization flags
- // returns: HRESULT
- // side effect: sets globals and attaches clipper to DD object
- //---------------------------------------------------------------------------------------------
- HRESULT FlipHelp_Init(HWND hwndApp, LPVOID FrontBuffer, LPVOID BackBuffer, DWORD dwFlags)
- {
- hrResult = S_OK;
- //
- // check for valid buffer pointers
- //
- if (FrontBuffer == NULL || BackBuffer == NULL)
- return(HR_ERR);
- //
- // make sure we're not trying to re-init (addref) our buffers
- //
- FlipHelp_Release();
- //
- // check for LPDIRECTDRAWSURFACE3 interface, return if none found
- //
- /* if (!((hrResult = ((IUnknown*)FrontBuffer)->QueryInterface(IID_IDirectDrawSurface3, (LPVOID *)&ddFrontBuffer)) == DD_OK) ||
- !((hrResult = ((IUnknown*)BackBuffer)->QueryInterface(IID_IDirectDrawSurface3, (LPVOID *)&ddBackBuffer)) == DD_OK))
- */
- if (!((hrResult = ((IUnknown*)FrontBuffer)->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&ddFrontBuffer)) == DD_OK) ||
- !((hrResult = ((IUnknown*)BackBuffer)->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&ddBackBuffer)) == DD_OK))
- {
- FlipHelp_Release();
- return(hrResult);
- }
- //
- // get handle to application window
- //
- hwndAppWindow = hwndApp;
- //
- // set flags
- //
- fDrawMouse = (BOOL)(dwFlags & FH_DRAW_MOUSE); // do we draw hardware mouse?
- fBuffersSame = (ddFrontBuffer == ddBackBuffer); // are DirectDraw buffers identical?
- f3Dfx = (BOOL)(dwFlags & FH_3DFX_HARDWARE); // are we running on 3Dfx hardware?
- //
- // check for broken drivers that do not do 555<->565 blts correctly
- //
- fUsingBadDriver = ((f3Dfx) && (!(dwFlags & FH_BITMAP_UPDATE)) && CheckForBrokenDriver(ddBackBuffer));
- //
- // if not 3Dfx, then get DirectDraw object from surface passed in
- // needed for CreateClipper() and FlipToGDISurface() calls
- //
- if ((!f3Dfx) && (!(ddObject = GetDDObjectFromDDSurface(ddFrontBuffer))))
- return(hrResult);
- //
- // get DirectDraw surface dimensions
- //
- DDSURFACEDESC ddsd;
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
- hrResult = ddBackBuffer->GetSurfaceDesc(&ddsd);
- structSurfaceSize.cx = ddsd.dwWidth;
- structSurfaceSize.cy = ddsd.dwHeight;
- return(hrResult);
- }
- //---------------------------------------------------------------------------------------------
- // FlipHelp_Begin() preps the DirectDraw surface depending on 3D hardware. It should get called
- // whenever a window (represented by the hwnd parameter) needs to be displayed under DirectDraw.
- // FlipHelp_Begin() should also get called if the window changes its content (if its static
- // content becomes dynamic, and vice-versa).
- //
- // purpose: for 3DFX, creates content image, else just flip to GDI surface
- // requires: handle to content window, 3DFX flag and if content is dynamic or static
- // returns: handle to the hwndHelpWindow, else NULL if not successful
- // side effect: creates content image or flips to GDI surface
- //---------------------------------------------------------------------------------------------
- HWND FlipHelp_Begin(HWND hwnd, BOOL bStaticContent)
- {
- //
- // if no handle passed in, assume existing content window
- //
- if (hwnd == NULL)
- {
- if ((hwnd = hwndHelpWindow) == NULL)
- return(NULL);
- }
- fStaticContent = bStaticContent;
- if (f3Dfx)
- {
- //
- // constrain cursor to DirectDraw surface
- //
- RECT rc = {0, 0, structSurfaceSize.cx, structSurfaceSize.cy};
- ClipCursor(&rc);
- //
- // clear out lingering content
- //
- if (hwndHelpWindowBMP)
- {
- DeleteObject(hwndHelpWindowBMP);
- hwndHelpWindowBMP = NULL;
- }
- //
- // need to create an image of content window just once
- //
- if (fStaticContent)
- {
- if (!FlipHelp_IsActive())
- UpdateWindow(hwnd);
- //
- // assign content window image to global
- //
- hwndHelpWindowBMP = CreateHelpBMP(hwnd);
- }
- }
- else
- {
- //
- // create a clipper (used in LPDIRECTDRAWSURFACE::Blt)
- //
- if (ddObject->CreateClipper(0, &ddClipper, NULL) == DD_OK)
- {
- hrResult = ddClipper->SetHWnd(0, hwndAppWindow);
- assert(SUCCEEDED(hrResult));
- //
- // attach the clipper here if buffers are the same
- //
- if (fBuffersSame)
- {
- hrResult = ddFrontBuffer->SetClipper(ddClipper);
- assert(SUCCEEDED(hrResult));
- }
- }
- else
- return(NULL);
- //
- // not 3DFX, so just flip to GDI so content window can be seen
- //
- hrResult = ddObject->FlipToGDISurface();
- }
- hwndHelpWindow = hwnd;
- return(hwndHelpWindow);
- }
- //---------------------------------------------------------------------------------------------
- // FlipHelp_End() deletes objects associated with the content window. Note that these are
- // objects created within this module, not objects created by the calling client (e.g. content
- // window). Call this function whenever the content window is destroyed (e.g. WM_CLOSE).
- //
- // purpose: cleans up after content window
- // requires: flag to determine if running under 3DFX
- // returns: none
- // side effect: cleans up anything associated with existing content window
- //---------------------------------------------------------------------------------------------
- void FlipHelp_End()
- {
- if (hwndHelpWindowBMP)
- {
- DeleteObject(hwndHelpWindowBMP);
- hwndHelpWindowBMP = NULL;
- }
- hwndHelpWindow = NULL;
- if (f3Dfx)
- ClipCursor(NULL);
- if (ddFrontBuffer)
- ddFrontBuffer->SetClipper(NULL);
- RELEASE(ddClipper);
- }
- //---------------------------------------------------------------------------------------------
- // FlipHelp_Update() is responsible for the actual rendering of the help content window (held
- // in global hwndHelpWindow). This function must be called each time a DirectDraw frame
- // gets rendered and FlipHelp_IsActive() returns TRUE, so it should be placed in the main
- // application's DirectDraw rendering routine. An example of this might look like the
- // following:
- //
- // void RenderFrame()
- // {
- // if (FlipHelp_IsActive())
- // {
- // FlipHelp_Update();
- // }
- // else
- // {
- // FrontBuffer->Blt(...);
- // }
- // }
- //
- // purpose: main routine to handle DirectDraw output of content window
- // requires: handle to application window and 3DFX flag
- // returns: HRESULT
- // side effect: blts/flips content window to DirectDraw surface
- //---------------------------------------------------------------------------------------------
- HRESULT FlipHelp_Update()
- {
- hrResult = 0;
- //
- // if front and back buffers are the same, then we're already drawing to display
- //
- if (fBuffersSame)
- return(hrResult);
- //
- // new multiwindow method
- //
- if (f3Dfx)
- {
- //
- // get a DC to the backbuffer on the 3Dfx (where we need to copy it)
- //
- HDC hdcBackBuffer;
- hrResult = ddBackBuffer->GetDC(&hdcBackBuffer);
- assert(SUCCEEDED(hrResult));
- if (FlipHelp_IsStatic())
- {
- //
- // if window has a complex region associated with it, be sure to include it in the draw
- //
- RECT rc;
- GetWindowRect(hwndHelpWindow, &rc);
- HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
- if (GetWindowRgn(hwndHelpWindow, hrgn) == COMPLEXREGION)
- {
- OffsetRgn(hrgn, rc.left, rc.top);
- SelectClipRgn(hdcBackBuffer, hrgn);
- }
- //
- // since the window content is static, use the existing bitmap image
- //
- HDC hdcMemory = CreateCompatibleDC(NULL);
- SelectObject(hdcMemory, hwndHelpWindowBMP);
- BitBlt(hdcBackBuffer, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), hdcMemory, 0, 0, SRCCOPY);
- DeleteDC(hdcMemory);
- SelectClipRgn(hdcBackBuffer, NULL);
- }
- else if (fUsingBadDriver)
- {
- //
- // to resolve the bad video driver situation, we must first create a bitmap, and then blt
- // to the screen, the same as is done in FlipHelp_IsStatic(), except that it must get
- // done for each successive frame
- //
- HDC hdcMemory = CreateCompatibleDC(NULL);
- HBITMAP hbm = CreateHelpBMP(hwndAppWindow);
- SelectObject(hdcMemory, hbm);
- //
- // since the window content is always changing, an image of it must
- // get created with each frame update
- //
- RECT rc;
- HRGN hrgn = GetInvWindowRgn(hwndAppWindow);
- GetRgnBox(hrgn, &rc);
- HDC hdcScreen = GetDC(NULL);
- //
- // blt from screen to memory
- //
- SelectClipRgn(hdcMemory, hrgn);
- BitBlt(hdcMemory, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), hdcScreen, rc.left, rc.top, SRCCOPY);
- SelectClipRgn(hdcMemory, NULL);
- //
- // blt from memory to backbuffer
- //
- SelectClipRgn(hdcBackBuffer, hrgn);
- BitBlt(hdcBackBuffer, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), hdcMemory, rc.left, rc.top, SRCCOPY);
- SelectClipRgn(hdcBackBuffer, NULL);
- DeleteObject(hrgn);
- DeleteObject(hdcMemory);
- DeleteObject(hbm);
- ReleaseDC(NULL, hdcScreen);
- }
- else
- {
- //
- // since the window content is always changing, an image of it must
- // get created with each frame update
- //
- RECT rc;
- HRGN hrgn = GetInvWindowRgn(hwndAppWindow);
- GetRgnBox(hrgn, &rc);
- HDC hdcScreen = GetDC(NULL);
- //
- // blt from screen directly to backbuffer
- //
- SelectClipRgn(hdcBackBuffer, hrgn);
- BitBlt(hdcBackBuffer, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), hdcScreen, rc.left, rc.top, SRCCOPY);
- SelectClipRgn(hdcBackBuffer, NULL);
- DeleteObject(hrgn);
- ReleaseDC(NULL, hdcScreen);
- }
- //
- // draw mouse cursor
- //
- if (fDrawMouse)
- {
- //
- // values for tracking changes in mouse cursor between blts
- //
- static HCURSOR MouseCursor;
- static ICONINFO IconInfo;
- HCURSOR MouseCursorCur;
- HWND hwndF = GetForegroundWindow();
- //
- // check for existence of out-of-process window (WOOP)
- // if it's the foreground window, then need to use AttachThreadInput() to
- // get back valid results of GetCursor() call
- //
- /*if (hwndF && GetWindowThreadProcessId(hwndF, NULL) == GetWindowThreadProcessId(hwndWOOP, NULL))
- {
- //
- // need to attach thread in order to allow correct return of GetCursor() call
- //
- DWORD dwWinHelpThreadId = GetWindowThreadProcessId(hwndWOOP, NULL);
- AttachThreadInput(GetCurrentThreadId(), dwWinHelpThreadId, TRUE);
- MouseCursorCur = GetCursor();
- AttachThreadInput(GetCurrentThreadId(), dwWinHelpThreadId, FALSE);
- }
- else*/
- {
- MouseCursorCur = GetCursor();
- };
- //
- // update the cursor only if it's changed
- //
- if (MouseCursorCur != MouseCursor)
- {
- MouseCursor = MouseCursorCur;
- GetIconInfo(MouseCursor, &IconInfo);
- if (IconInfo.hbmMask)
- DeleteObject(IconInfo.hbmMask);
- if (IconInfo.hbmColor)
- DeleteObject(IconInfo.hbmColor);
- };
- POINT pt;
- GetCursorPos(&pt);
- pt.x -= IconInfo.xHotspot;
- pt.y -= IconInfo.yHotspot;
- DrawIcon(hdcBackBuffer, pt.x, pt.y, MouseCursor);
- }
- hrResult = ddBackBuffer->ReleaseDC(hdcBackBuffer);
- assert(SUCCEEDED(hrResult));
- hrResult = ddFrontBuffer->Flip(NULL, DDFLIP_WAIT);
- assert(SUCCEEDED(hrResult));
- }
- else // not 3DFX hardware
- {
- //
- // create region to update
- //
- POINT ptScreen = {0, 0};
- ClientToScreen(hwndAppWindow, &ptScreen);
- RECT rc = {ptScreen.x , ptScreen.y, ptScreen.x + structSurfaceSize.cx, ptScreen.y + structSurfaceSize.cy};
- hrResult = ddFrontBuffer->SetClipper(ddClipper);
- //
- // update the surface with a blt
- //
- hrResult = ddFrontBuffer->Blt(&rc, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
- assert(SUCCEEDED(hrResult));
- };
- return(hrResult);
- }
- //---------------------------------------------------------------------------------------------
- // FlipHelp_IsActive() simply checks to see if there's a content window displayed. This check
- // should be made prior to calling FlipHelp_Update().
- //
- // purpose: checks status of help window
- // requires: none
- // returns: true/false
- // side effect: none
- //---------------------------------------------------------------------------------------------
- BOOL FlipHelp_IsActive(void)
- {
- return(hwndHelpWindow != NULL);
- }
- //---------------------------------------------------------------------------------------------
- // FlipHelp_IsStatic() checks to see whether or not the content window needs to be regularly
- // updated (its content is dynamic, such as an animation or text entry field). A static window
- // is created (an image of the window created with a call to CreateHelpBMP()) once and used
- // over and over.
- //
- // purpose: checks if help window content is static or dynamic
- // requires: none
- // returns: true/false
- // side effect: none
- //---------------------------------------------------------------------------------------------
- BOOL FlipHelp_IsStatic(void)
- {
- return(fStaticContent);
- }
- //---------------------------------------------------------------------------------------------
- // FlipHelp_Release() releases interface pointers as necessary. It should get
- // called each time DirectDraw surfaces are altered (e.g. changes to the device that
- // the client application is running under).
- //
- // purpose: decrement refcount for interfaces created in FlipHelp
- // requires: none
- // returns: none
- // side effect: releases interface pointers created in FlipHelp
- //---------------------------------------------------------------------------------------------
- void FlipHelp_Release()
- {
- RELEASE(ddObject);
- RELEASE(ddBackBuffer);
- RELEASE(ddFrontBuffer);
- }
- //---------------------------------------------------------------------------------------------
- // CreateHelpBMP() takes the hwnd of the content window, and returns a bitmap handle. Note that
- // this is an internal (not exported) function.
- //
- // purpose: creates a bitmap from hwnd (content window)
- // requires: handle to content window
- // returns: handle to updated bitmap
- // side effect: none
- //---------------------------------------------------------------------------------------------
- static HBITMAP CreateHelpBMP(HWND hwnd)
- {
- //
- // create a bitmap of the window passed in
- //
- RECT rc;
- GetWindowRect(hwnd, &rc);
- int x = rc.left;
- int y = rc.top;
- int cx = rc.right - rc.left;
- int cy = rc.bottom - rc.top;
- HDC hdcScreen = GetDC(NULL);
- HDC hdcMemory = CreateCompatibleDC(NULL);
- HBITMAP hbmBitmap = NULL;
- hbmBitmap = CreateDibBMP(hdcScreen, cx, cy, 0);
- //
- // blt the image from screen to bitmap
- //
- SelectObject(hdcMemory, hbmBitmap);
- BitBlt(hdcMemory, 0, 0, cx, cy, hdcScreen, x, y, SRCCOPY);
- DeleteDC(hdcMemory);
- ReleaseDC(NULL, hdcScreen);
- return(hbmBitmap);
- }
- //---------------------------------------------------------------------------------------------
- // CreateDibBMP() created an empty bitmap, used exclusively in CreateHelpBMP(). Note that
- // this is an internal (not exported) function.
- //
- // purpose: creates an "empty" bitmap
- // requires: dc, dimensions of image, and color depth (bits per pixel)
- // note that bpp == 0 will call into GetOptimalDIBFormat()
- // returns: handle to new bitmap
- // side effect: none
- //---------------------------------------------------------------------------------------------
- static HBITMAP CreateDibBMP(HDC hdc, int w, int h, int bpp)
- {
- LPVOID lpBits;
- struct
- {
- BITMAPINFOHEADER bi;
- DWORD ct[256];
- } dib;
- dib.bi.biSize = sizeof(BITMAPINFOHEADER);
- dib.bi.biWidth = w;
- dib.bi.biHeight = h;
- dib.bi.biBitCount = (WORD)bpp;
- dib.bi.biPlanes = 1;
- dib.bi.biCompression = 0;
- dib.bi.biSizeImage = 0;
- dib.bi.biClrUsed = 0;
- if (bpp == 0)
- {
- GetOptimalDIBFormat(hdc, &dib.bi);
- dib.bi.biBitCount = (dib.bi.biBitCount < 16 ? 16 : dib.bi.biBitCount);
- dib.bi.biWidth = w;
- dib.bi.biHeight = h;
- }
- else if (bpp == 15)
- {
- dib.bi.biBitCount = 16;
- }
- else if (bpp == 16)
- {
- dib.bi.biCompression = BI_BITFIELDS;
- dib.ct[0] = 0xf800;
- dib.ct[1] = 0x07E0;
- dib.ct[2] = 0x001F;
- };
- return(CreateDIBSection(hdc, (LPBITMAPINFO)&dib, DIB_RGB_COLORS, &lpBits, NULL, 0));
- }
- //---------------------------------------------------------------------------------------------
- // GetInvWindowRgn() get the inverse of the visible region of a window
- //
- // purpose: used to Blt the contents of a window to the 3DFX
- // requires: handle to the app window
- // returns: HRGN of non-visible region
- // side effect: none
- //---------------------------------------------------------------------------------------------
- static HRGN GetInvWindowRgn(HWND hwnd)
- {
- HRGN WinRgn;
- HRGN VisRgn;
- HRGN InvRgn;
- RECT rc;
- HDC hdc;
- //
- // get the whole window rect/rgn
- //
- GetWindowRect(hwnd, &rc);
- WinRgn = CreateRectRgnIndirect(&rc);
- //
- // get the visible region
- //
- hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS);
- VisRgn = CreateRectRgn(0, 0, 0, 0);
- GetRandomRgn(hdc, VisRgn, 4);
- ReleaseDC(hwnd, hdc);
- //
- // subtract the vis rgn from the whole window rgn, where InvRgn = WinRgn - VisRgn;
- //
- InvRgn = CreateRectRgn(0, 0, 0, 0);
- CombineRgn(InvRgn, WinRgn, VisRgn, RGN_DIFF);
- DeleteObject(WinRgn);
- DeleteObject(VisRgn);
- //
- // convert the region from screen cordinates to window cordinates
- //
- OffsetRgn(InvRgn, -rc.left, -rc.top);
- return(InvRgn);
- }
- //---------------------------------------------------------------------------------------------
- // GetDDObjectFromDDSurface() gets the DirectDraw object from a surface passed in
- //
- // purpose: gets DirectDraw object from DirectDraw surface
- // requires: pointer to DirectDraw surface
- // returns: pointer to DirectDraw object
- // side effect: none
- //---------------------------------------------------------------------------------------------
- //static LPDIRECTDRAW2 GetDDObjectFromDDSurface(LPDIRECTDRAWSURFACE3 ddSurface)
- static LPDIRECTDRAW2 GetDDObjectFromDDSurface(LPDIRECTDRAWSURFACE2 ddSurface)
- {
- LPDIRECTDRAW2 ddObject = NULL;
- LPDIRECTDRAWSURFACE2 ddSurface2 = NULL;
- hrResult = 0;
- //
- // check to make sure surface is valid
- //
- if (ddSurface == NULL)
- return(NULL);
- //
- // get the DirectDraw object, but first check for LPDIRECTDRAWSURFACE2 interface
- // needed for GetDDInterface() call
- //
- if (ddSurface->QueryInterface(IID_IDirectDrawSurface2, (LPVOID *)&ddSurface2) != DD_OK)
- return(NULL);
- hrResult = ddSurface2->GetDDInterface((LPVOID *)&ddObject);
- assert(SUCCEEDED(hrResult));
- hrResult = ddSurface2->Release();
- assert(SUCCEEDED(hrResult));
- return(ddObject);
- }
- //---------------------------------------------------------------------------------------------
- // CheckForBrokenDriver() checks for the case when the 2D video driver does not correctly
- // handle 565<->555 bitmap conversion
- //
- // purpose: side-step really bad video drivers in this world
- // requires: DirectDraw surface
- // returns: whether or not the video driver has passed the test
- // side effect: none
- //---------------------------------------------------------------------------------------------
- //static BOOL CheckForBrokenDriver(LPDIRECTDRAWSURFACE3 pSurface)
- static BOOL CheckForBrokenDriver(LPDIRECTDRAWSURFACE2 pSurface)
- {
- HDC hdcSurface = NULL, hdcScreen = NULL;
- COLORREF rgbTest = 0, rgbScreen = 0, rgbSurface = 0;
- //
- // to test for bad driver case, put a pure green pixel in the upper left corner
- // of the surface, then get it again (getting rid of the pixel so it doesn't display)
- //
- // if the pixel comes back with red or blue in it, then the test failed
- // and we have a bad driver to content with (so return TRUE)
- //
- if (pSurface->GetDC(&hdcSurface) == DD_OK)
- {
- hdcScreen = GetDC(NULL);
- //
- // get the pixel
- //
- rgbScreen = GetPixel(hdcScreen, 0, 0);
- rgbSurface= GetPixel(hdcSurface, 0, 0);
- //
- // set the pixel to green and blt it to the screen
- //
- SetPixel(hdcScreen, 0, 0, RGB(0, 255, 0));
- BitBlt(hdcSurface, 0, 0, 1, 1, hdcScreen, 0, 0, SRCCOPY);
- //
- // get the pixel from the screen
- //
- rgbTest = GetPixel(hdcSurface, 0, 0);
- //
- // put the original pixel back
- //
- SetPixel(hdcScreen, 0, 0, rgbScreen);
- SetPixel(hdcSurface, 0, 0, rgbSurface);
- ReleaseDC(NULL, hdcScreen);
- pSurface->ReleaseDC(hdcSurface);
- }
- //
- // test here to see if it there's any red or blue in the pixel
- //
- return (GetRValue(rgbTest) != 0 || GetBValue(rgbTest) != 0);
- }
- //---------------------------------------------------------------------------------------------
- // GetOptimalDIBFormat() gets the optimal DIB format for a display device. The optimal DIB
- // format is the format that exactly matches the format of the device, this is very important
- // when dealing with 16bpp modes, you need to know what bitfields to use (555 or 565 for
- // example).
- //
- // You normally use this function to get the best format to pass to CreateDIBSection().
- //
- // If you are going to use this function on a 8bpp device, you should make sure the
- // colortable contains an identity palette for optimal blt'ing
- //
- // requires: device to get format for, pointer to bitmapinfo + color table
- // returns: none
- // side effect: optimal DIB format in pbi
- // if <= 8bpp, color table will contain system palette
- // if >= 16bpp, the "table" will contain corrected BI_BITFIELDS
- //---------------------------------------------------------------------------------------------
- static void GetOptimalDIBFormat(HDC hdc, BITMAPINFOHEADER *pbi)
- {
- HBITMAP hbm;
- hbm = CreateCompatibleBitmap(hdc, 1, 1);
- ZeroMemory(pbi, sizeof(BITMAPINFOHEADER));
- pbi->biSize = sizeof(BITMAPINFOHEADER);
- pbi->biBitCount = 0;
- //
- // first call will fill in the optimal biBitCount
- //
- GetDIBits(hdc, hbm, 0, 1, NULL, (BITMAPINFO*)pbi, DIB_RGB_COLORS);
- //
- // second call will get the optimal color table, or the optimal bitfields
- //
- GetDIBits(hdc, hbm, 0, 1, NULL, (BITMAPINFO*)pbi, DIB_RGB_COLORS);
- DeleteObject(hbm);
- }
|