#include <windows.h>
#include <ddraw.h>
#pragma comment(lib, "ddraw.lib")
HINSTANCE hInst = NULL;
BOOL InitInstance(HINSTANCE hInstance, LPTSTR lpCmdLine);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
BITMAP bmInfo;
LPDIRECTDRAWSURFACE lpPrimarySurface = NULL; // Primary Surface.
LPDIRECTDRAWSURFACE lpDDSOverlay = NULL; // The overlay primary.
DDPIXELFORMAT ddpfOverlayFormats = {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0xF800, 0x07e0, 0x001F, 0};// 16-bit RGB 5:6:5
void ReleaseAllObjects();
HRESULT InitDirectDraw();
BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE, LPCTSTR);
//-----------------------------------------------------------------------------
// Name: ReleaseAllObjects()
// Desc: Finished with all objects we use; release them
//-----------------------------------------------------------------------------
void ReleaseAllObjects()
{
if (lpDDSOverlay != NULL)
{
// Use UpdateOverlay() with the DDOVER_HIDE flag to remove an overlay
// from the display.
lpDDSOverlay->UpdateOverlay(NULL, lpPrimarySurface, NULL, DDOVER_HIDE, NULL);
lpDDSOverlay->Release();
lpDDSOverlay = NULL;
}
if (lpPrimarySurface != NULL)
{
lpPrimarySurface->Release();
lpPrimarySurface = NULL;
}
}
//-----------------------------------------------------------------------------
// Function: LoadImageOnToSurface
// Description:
// Loads a resource based bitmap image onto a DirectDraw surface. Can
// covert the bitmap to all RGB formats, plus a couple YUV formats.
//-----------------------------------------------------------------------------
BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE lpdds, LPCTSTR lpstrRes)
{
BOOL bRetVal = FALSE;
HDC hdcSurf = NULL;
HDC hdcImage = NULL;
HBITMAP hbitmap = NULL;
if (!lpdds) return FALSE;
//
// get surface size and format.
//
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
HRESULT ddrval = lpdds->GetSurfaceDesc(&ddsd);
if (FAILED(ddrval))
goto Exit;
hbitmap = SHLoadDIBitmap(lpstrRes);
if (hbitmap == NULL)
goto Exit;
::GetObject(hbitmap,sizeof(bmInfo),&bmInfo);
// Create a DC and associate the bitmap with it.
hdcImage = CreateCompatibleDC(NULL);
SelectObject(hdcImage, hbitmap);
ddrval = lpdds->GetDC(&hdcSurf);
if (FAILED(ddrval))
goto Exit;
if (BitBlt(hdcSurf, (ddsd.dwWidth-bmInfo.bmWidth)>>1, (ddsd.dwHeight-bmInfo.bmHeight)>>1, bmInfo.bmWidth, bmInfo.bmHeight, hdcImage, 0, 0, SRCCOPY) == FALSE)
goto Exit;
bRetVal = TRUE;
Exit:
if (hdcSurf)
lpdds->ReleaseDC(hdcSurf);
if (hdcImage)
DeleteDC(hdcImage);
if (hbitmap)
DeleteObject(hbitmap);
return bRetVal;
}
HRESULT InitDirectDraw()
{
// Create the main DirectDraw object
LPDIRECTDRAW pDD = NULL;
HRESULT hRet = DirectDrawCreate(NULL, &pDD, NULL);
if (hRet != DD_OK) return hRet;
// Get normal mode.
hRet = pDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
if (hRet != DD_OK) return hRet;
// Get a primary surface interface pointer (only needed for init.)
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hRet = pDD->CreateSurface(&ddsd, &lpPrimarySurface, NULL);
if (hRet != DD_OK) return hRet;
// See if we can support overlays.
DDCAPS ddcaps;
memset(&ddcaps, 0, sizeof(ddcaps));
ddcaps.dwSize = sizeof(ddcaps);
hRet = pDD->GetCaps(&ddcaps,NULL);
if (hRet != DD_OK) return hRet;
if (!(ddcaps.dwCaps & DDCAPS_OVERLAY))
return DD_FALSE;
// Create the overlay flipping surface. We will attempt the pixel formats
// in our table one at a time until we find one that jives.
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_FLIP | DDSCAPS_COMPLEX |
DDSCAPS_VIDEOMEMORY;
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_BACKBUFFERCOUNT |
DDSD_PIXELFORMAT;
ddsd.dwWidth = GetSystemMetrics(SM_CXSCREEN);
ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
ddsd.dwBackBufferCount = 1;
ddsd.ddpfPixelFormat = ddpfOverlayFormats;
hRet = pDD->CreateSurface(&ddsd, &lpDDSOverlay, NULL);
if (hRet != DD_OK) return hRet;
// Load the images.
if (!LoadImageOntoSurface(lpDDSOverlay, TEXT("mosquit.bmp")))
return DD_FALSE;
// Set the flags we'll send to UpdateOverlay
DWORD dwUpdateFlags = DDOVER_SHOW;
// Does the overlay hardware support source color keying?
// If so, we can hide the black background around the image.
// This probably won't work with YUV formats
DDOVERLAYFX ovfx;
memset(&ovfx, 0, sizeof(ovfx));
ovfx.dwSize = sizeof(ovfx);
if (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCOVERLAY)
{
dwUpdateFlags |= DDOVER_KEYSRCOVERRIDE | DDOVER_DDFX;
// Create an overlay FX structure so we can specify a source color key.
// This information is ignored if the DDOVER_SRCKEYOVERRIDE flag
// isn't set.
ovfx.dckSrcColorkey.dwColorSpaceLowValue=0; // black as the color key
ovfx.dckSrcColorkey.dwColorSpaceHighValue=0;
}
// Update the overlay parameters.
RECT srcRect = {0,0,ddsd.dwWidth,ddsd.dwHeight};
RECT dstRect = {0,0,ddsd.dwWidth,ddsd.dwHeight};
return lpDDSOverlay->UpdateOverlay(&srcRect, lpPrimarySurface, &dstRect, dwUpdateFlags, &ovfx);
}
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
// Perform application initialization:
if (!InitInstance (hInstance, lpCmdLine))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// It is important to call this function so that the application
// will get 'well formed' small icons associated with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW/* | CS_DBLCLKS*/;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, LPTSTR lpCmdLine)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
TCHAR *szWindowClass = L"LLX_OVERLAY";
// Initialize global strings
MyRegisterClass(hInstance, szWindowClass);
hWnd = FindWindow(szWindowClass, NULL);
if (hWnd)
{
if(wcscmp(lpCmdLine,L"-h"))
{
ShowWindow(hWnd,SW_SHOWNORMAL);
SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
if( *lpCmdLine )
{
COPYDATASTRUCT cds = { 1, 2*(wcslen( lpCmdLine ) + 1), lpCmdLine };
SendMessage( hWnd, WM_COPYDATA, NULL, (LPARAM)&cds );
}
}
else
{
ShowWindow(hWnd,SW_HIDE);
}
return FALSE;
}
hWnd = CreateWindowEx(NULL,
szWindowClass,
L"",
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
{
return FALSE;
}
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
if(InitDirectDraw()!=DD_OK)
PostMessage(hWnd,WM_CLOSE,0,0);
break;
case WM_DESTROY:
ReleaseAllObjects();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}