//---------------------------------------------------------------------------------------------
//
// 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);
}