📄 mosquito.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//-----------------------------------------------------------------------------
// File: Mosquito.cpp
//
// Desc: Mosquito is a DirectDraw sample application that demonstates the
// use of video overlay. It creates a flipable overlay, loads a small
// animation into the various back buffers, then flips the buffers as
// it moves the overlay around the screen. Press F12 or ESC to quit.
//
//-----------------------------------------------------------------------------
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
#include <windows.h>
#include <ddraw.h>
#include "resource.h"
//-----------------------------------------------------------------------------
// Local definitions
//-----------------------------------------------------------------------------
#define NAME TEXT("MosquitoWndClass")
#define TITLE TEXT("Mosquito")
#define BUG_WIDTH 320
#define BUG_HEIGHT 200
#ifdef UNDER_CE
#define RAND_INT(x) (Random() % x)
#else
#define RAND_INT(x) (rand()*x/RAND_MAX)
#endif
#define RANDOM_VELOCITY() (int)(((RAND_INT(5)+3)*2))
//-----------------------------------------------------------------------------
// Default settings
//-----------------------------------------------------------------------------
#define TIMER_ID 1
#define TIMER_RATE 200
//-----------------------------------------------------------------------------
// Global data
//-----------------------------------------------------------------------------
LPDIRECTDRAW4 g_pDD = NULL; // DirectDraw object
LPDIRECTDRAWSURFACE4 g_pDDSPrimary = NULL; // Primary Surface.
LPDIRECTDRAWSURFACE4 g_pDDSOverlay = NULL; // The overlay primary.
BOOL g_bActive = FALSE; // Is application active?
// Overlay position and velocity data.
int g_nOverlayXPos, g_nOverlayYPos;
int g_nOverlayXVel, g_nOverlayYVel;
int g_nOverlayWidth, g_nOverlayHeight;
DWORD g_dwOverlayXPositionAlignment;
// Our instance handle.
HINSTANCE g_hInstance;
//-----------------------------------------------------------------------------
// Local data
//-----------------------------------------------------------------------------
static TCHAR szImg1[] = TEXT("IDB_BUGIMAGE1");
static TCHAR szImg2[] = TEXT("IDB_BUGIMAGE2");
static TCHAR szImg3[] = TEXT("IDB_BUGIMAGE3");
// These are the pixel formats this app supports. Most display adapters
// with overlay support will recognize one or more of these formats.
// We start with YUV format, then work down to RGB. (All 16 bpp.)
static DDPIXELFORMAT ddpfOverlayFormats[] = {
{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('Y','U','Y','V'),0,0,0,0,0}, // YUYV
{sizeof(DDPIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00, 0x03e0, 0x001F, 0}, // 16-bit RGB 5:5:5
{sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0xF800, 0x07e0, 0x001F, 0} // 16-bit RGB 5:6:5
};
#define PF_TABLE_SIZE 4
static RECT rs;
static RECT rd;
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void ReleaseAllObjects(void);
HRESULT InitFail(HWND, HRESULT, LPCTSTR, ...);
HRESULT RestoreAllSurfaces();
void MoveOverlay();
long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM);
BOOL CopyBitmapToYUVSurface(LPDIRECTDRAWSURFACE4, HBITMAP);
BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE4, LPCTSTR);
HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE4, LPDDSURFACEDESC2, LPVOID);
HRESULT LoadBugImages();
HRESULT InitApp(HINSTANCE hInstance, int nCmdShow);
//-----------------------------------------------------------------------------
// Name: ReleaseAllObjects()
// Desc: Finished with all objects we use; release them
//-----------------------------------------------------------------------------
static void
ReleaseAllObjects(void)
{
if (g_pDDSOverlay != NULL)
{
// Use UpdateOverlay() with the DDOVER_HIDE flag to remove an overlay
// from the display.
g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL);
g_pDDSOverlay->Release();
g_pDDSOverlay = NULL;
}
if (g_pDDSPrimary != NULL)
{
g_pDDSPrimary->Release();
g_pDDSPrimary = NULL;
}
if (g_pDD != NULL)
{
g_pDD->Release();
g_pDD = NULL;
}
}
//-----------------------------------------------------------------------------
// Name: InitFail()
// Desc: This function is called if an initialization function fails
//-----------------------------------------------------------------------------
#define PREFIX TEXT("MOSQUITO: ")
#define PREFIX_LEN 10
static HRESULT
InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)
{
TCHAR szBuff[128];
va_list vl;
va_start(vl, szError);
wsprintf(szBuff, PREFIX);
wvsprintf(szBuff + PREFIX_LEN, szError, vl);
wsprintf(szBuff + wcslen(szBuff), TEXT("\r\n"));
ReleaseAllObjects();
OutputDebugString(szBuff);
DestroyWindow(hWnd);
va_end(vl);
return hRet;
}
#undef PREFIX_LEN
#undef PREFIX
//-----------------------------------------------------------------------------
// Name: RestoreAllSurfaces
// Desc: Called in case we lose our surface's vram.
//-----------------------------------------------------------------------------
static HRESULT
RestoreAllSurfaces()
{
HRESULT hRet;
// Try Restoring the primary surface.
hRet = g_pDDSPrimary->Restore();
if (hRet != DD_OK)
return hRet;
// Try Restoring the overlay surface.
hRet = g_pDDSOverlay->Restore();
if (hRet != DD_OK)
return hRet;
// Reload the images.
hRet = LoadBugImages();
if (hRet != DD_OK)
return hRet;
// Show the overlay.
hRet = g_pDDSOverlay->UpdateOverlay(&rs, g_pDDSPrimary, &rd, DDOVER_SHOW, NULL);
return hRet;
}
//-----------------------------------------------------------------------------
// Name: MoveOverlay()
// Desc: Called on the timer, this function moves the overlay around the
// screen, periodically calling flip to animate the mosquito.
//-----------------------------------------------------------------------------
static void
MoveOverlay()
{
HRESULT hRet;
DWORD dwXAligned;
// Add the current velocity vectors to the position.
g_nOverlayXPos += g_nOverlayXVel;
g_nOverlayYPos += g_nOverlayYVel;
// Check to see if this new position puts the overlay off the edge of the screen.
// SetOverlayPosition() won't like that.
// Have we gone off the left edge?
if (g_nOverlayXPos < 0) {
g_nOverlayXPos = 0;
g_nOverlayXVel = RANDOM_VELOCITY();
}
// Have we gone off the right edge?
if ((g_nOverlayXPos+g_nOverlayWidth) > GetSystemMetrics(SM_CXSCREEN)){
g_nOverlayXPos = GetSystemMetrics(SM_CXSCREEN) - g_nOverlayWidth;
g_nOverlayXVel = -RANDOM_VELOCITY();
}
// Have we gone off the top edge?
if (g_nOverlayYPos < 0) {
g_nOverlayYPos = 0;
g_nOverlayYVel = RANDOM_VELOCITY();
}
// Have we gone off the bottom edge?
if ( (g_nOverlayYPos+g_nOverlayHeight) > GetSystemMetrics(SM_CYSCREEN)) {
g_nOverlayYPos = GetSystemMetrics(SM_CYSCREEN) - g_nOverlayHeight;
g_nOverlayYVel = -RANDOM_VELOCITY();
}
// We need to check for any alignment restrictions on the X position.
if (g_dwOverlayXPositionAlignment)
dwXAligned = g_nOverlayXPos - g_nOverlayXPos % g_dwOverlayXPositionAlignment;
else
dwXAligned = g_nOverlayXPos;
// Set the overlay to it's new position.
hRet = g_pDDSOverlay->SetOverlayPosition(dwXAligned, g_nOverlayYPos);
if (hRet == DDERR_SURFACELOST)
{
if (FAILED(RestoreAllSurfaces()))
return;
}
// Flip.
while (TRUE)
{
hRet = g_pDDSOverlay->Flip(NULL, 0);
if (hRet == DD_OK)
break;
if (hRet == DDERR_SURFACELOST)
{
hRet = RestoreAllSurfaces();
if (hRet != DD_OK)
break;
}
if (hRet != DDERR_WASSTILLDRAWING)
break;
}
}
//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: The Main Window Procedure
//-----------------------------------------------------------------------------
long FAR PASCAL
WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
#ifdef UNDER_CE
case WM_ACTIVATE:
#else
case WM_ACTIVATEAPP:
#endif
// Pause if minimized or not the top window
g_bActive = (wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE);
return 0L;
case WM_KILLFOCUS:
// We do not allow anyone else to have the keyboard focus until
// we are done.
SetFocus(hWnd);
return 0L;
case WM_DESTROY:
// Clean up and close the app
ReleaseAllObjects();
PostQuitMessage(0);
return 0L;
case WM_KEYDOWN:
// Handle any non-accelerated key commands
switch (wParam)
{
case VK_ESCAPE:
case VK_F12:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0L;
}
break;
case WM_TIMER:
// Update and flip surfaces
if (g_bActive && TIMER_ID == wParam)
{
MoveOverlay();
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
//-----------------------------------------------------------------------------
// Function: CopyBitmapToYUVSurface
// Description:
// Copies an RGB GDI bitmap to a YUV surface. Both bitmap and surface
// must be a multiple of 2 pixels in width for the supported YUV formats.
// The following formats are supported:
// YUYV
// UYVY
//
// The "YUYV" YUV pixel format looks like this:
// As a series of BYTES: [Y0][U][Y1][V] (reverse it for a DWORD)
//
// The "UYVY" YUV pixel format looks like this:
// As a series of BYTES: [U][Y0][V][Y1] (reverse it for a DWORD)
//
// As you can see, both formats pack two pixels into a single DWORD. The
// pixels share U and V components and have separate Y components.
//
// Returns: TRUE if successful, otherwise FALSE.
//-----------------------------------------------------------------------------
static BOOL
CopyBitmapToYUVSurface(LPDIRECTDRAWSURFACE4 lpDDSurf, HBITMAP hbm)
{
HDC hdcImage;
HRESULT ddrval;
DDSURFACEDESC2 ddsd;
DWORD x, y, dwWidth, dwHeight;
LONG lPitch;
LPBYTE pSurf;
DWORD dwBytesInRow;
COLORREF color;
BYTE R,G,B, Y0,Y1,U,V;
BOOL bRet = FALSE;
if (hbm == NULL || lpDDSurf == NULL)
return FALSE;
//
// select bitmap into a memoryDC so we can use it.
//
hdcImage = CreateCompatibleDC(NULL);
SelectObject(hdcImage, hbm);
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
// Lock down the surface so we can modify it's contents.
ddrval=lpDDSurf->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL);
if (FAILED(ddrval))
goto CleanUp;
dwWidth=ddsd.dwWidth;
dwHeight=ddsd.dwHeight;
lPitch=ddsd.lPitch;
pSurf=(LPBYTE)ddsd.lpSurface;
dwBytesInRow=ddsd.dwWidth*2;
// Go through the image 2 pixels at a time and convert to YUV
for(y=0; y<dwHeight; y++)
{
for(x=0; x<dwWidth; x+=2)
{
// The equations for color conversion used here, probably aren't
// exact, but they seem to do an OK job.
color=GetPixel(hdcImage, x,y);
R=GetRValue(color);
G=GetGValue(color);
B=GetBValue(color);
Y0= (BYTE)(0.29*R + 0.59*G + 0.14*B);
U= (BYTE)(128.0 - 0.14*R - 0.29*G + 0.43*B);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -