⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mosquito.cpp

📁 Windows Mobile6 DDraw案例应用
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//-----------------------------------------------------------------------------
// 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"
#include "winuserm.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
//-----------------------------------------------------------------------------
LPDIRECTDRAW                g_pDD = NULL;             // DirectDraw object
LPDIRECTDRAWSURFACE         g_pDDSPrimary = NULL;     // Primary Surface.
LPDIRECTDRAWSURFACE         g_pDDSOverlay = NULL;     // The overlay primary.
BOOL                        g_bActive = FALSE;        // Is application active?
int                         g_RotationAngles = 0;     // Supported rotation angles.
int                         g_CurrentAngle = 0;       // Current rotation angle.
LPCTSTR                     g_szErrorMessage = NULL;  // Error message to display.
// 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");
static const TCHAR          szDDrawError[] = TEXT("DirectDraw Error");
static const TCHAR          szDDrawFailedMsg[] = TEXT("DirectDrawCreate failed.");
static const TCHAR          szSetCooperativeFailMsg[] = TEXT("SetCooperativeLevel failed.");
static const TCHAR          szNoOverlaysMsg[] = TEXT("Overlays are not supported in hardware!");
static const TCHAR          szCreateOverlayFailMsg[] = TEXT("Unable to create overlay surface!");
static const TCHAR          szLoadOverlayFailMsg[] = TEXT("Unable to load images to overlay surface!");
static const TCHAR          szShowOverlayFailMsg[] = TEXT("Unable to show overlay surface!");
static const TCHAR          szNoFlipSurfacesMsg[] =TEXT("Display driver doesn't support flipping surfaces.");
static const TCHAR          szEnumAttachedSurfacesFailMsg[] = TEXT("EnumAttachedSurfaces failed.");
static const TCHAR          szCreateSurfaceFailMsg[] = TEXT("CreateSurface failed.");
static const TCHAR          szSetTimerFailMsg[] = TEXT("SetTimer failed.");
static const TCHAR          szGetCapsFailMsg[] = TEXT("GetCaps FAILED");

// 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 (sizeof(ddpfOverlayFormats) / sizeof(ddpfOverlayFormats[0]))

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(LPDIRECTDRAWSURFACE, HBITMAP);
BOOL LoadImageOntoSurface(LPDIRECTDRAWSURFACE, LPCTSTR);
HRESULT WINAPI EnumSurfacesCallback(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, 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
//-----------------------------------------------------------------------------
static HRESULT
InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)
{
    ReleaseAllObjects();
    DestroyWindow(hWnd);
    g_szErrorMessage = szError;
    return hRet;
}

//-----------------------------------------------------------------------------
// 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)
{
    int                         NewAngle;
    DEVMODE                     DevMode;

    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_ACTION:
                    PostMessage(hWnd, WM_CLOSE, 0, 0);
                    return 0L;

                case VK_RIGHT:
                
                    // Rotate to the "next" angle.

                    if (g_CurrentAngle >= 0 && g_RotationAngles >= 0) {

                        NewAngle = g_CurrentAngle;

                        do
                        {
                            NewAngle <<= 1;

                            if (NewAngle == DMDO_0)
                            {
                                NewAngle = DMDO_90;
                            }

                            if (NewAngle > DMDO_270)
                            {
                                NewAngle = DMDO_0;
                            }
                        } while (!(NewAngle & g_RotationAngles) && (NewAngle != DMDO_0));

                        memset(&DevMode, 0, sizeof (DevMode));
                        DevMode.dmSize               = sizeof (DevMode);
                        DevMode.dmFields             = DM_DISPLAYORIENTATION;
                        DevMode.dmDisplayOrientation = NewAngle;

                        if (DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &DevMode, NULL, CDS_RESET, NULL)) {

                            g_CurrentAngle = NewAngle;

                            RestoreAllSurfaces();
                        }
                    }
                    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(LPDIRECTDRAWSURFACE lpDDSurf, HBITMAP hbm)
{
    HDC                 hdcImage;
    HRESULT             ddrval;
    DDSURFACEDESC       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_WAITNOTBUSY, NULL);
    if (FAILED(ddrval))
        goto CleanUp;

    dwWidth=ddsd.dwWidth;
    dwHeight=ddsd.dwHeight;
    lPitch=ddsd.lPitch;
    pSurf=(LPBYTE)ddsd.lpSurface;
    dwBytesInRow=ddsd.dwWidth*2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -