DirectDraw Tutorial 1

DirectDraw Tutorial 1

创建窗口并显示图片

    

一、处理窗口消息和消息泵
         下面是一个基本的win32程序,我们的主要工作是修改消息响应和消息泵的结构,该程序包含一个菜单系统,但是并没有对他的消息做任何的响应,注意程序的结构和消息处理。
 
//This is a simple directdraw window and use ddutil to display a bitmap
//use dx8.0
// main.cpp
 
#include <windows.h>
 
#include "resource.h"
#include "comfunc.h"        //the file include all necessary function and variables
 
//if need redraw the window
BOOL g_bActive     = FALSE;
 
//this is a part of window
LRESULT CALLBACK WndProc(HWND hwnd,
                         UINT uMsg,
                         WPARAM wParam,
                         LPARAM lParam
                         )
{
    switch(uMsg)
    {
         //if this window has a menu system you must process WM_PAINT message to
         //redraw the area be covered by menu
    case WM_PAINT:
        // Update the screen if we need to refresh. This case occurs
        // when in windowed mode and the window is behind others.
        // The app will not be active, but it will be visible.
        if( g_pDisplay )
        {
            //try to display the a next frame
            if( Render() == DDERR_SURFACELOST )
            {
                //if the surfaces were lost, then restore and try again
                RestoreSurfaces();
                Render();
            }
        }
        break; // Continue with default processing to validate the region
    case WM_MOVE:
        //the client area of window is changed so we must update it
        if( g_pDisplay )
            g_pDisplay->UpdateBounds();
        return 0;
    case WM_SIZE:
        //if the window is hide or minimized don't update
        if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
            g_bActive = FALSE;
        else
            g_bActive = TRUE;
        if( g_pDisplay )
            g_pDisplay->UpdateBounds();
        break;
    case WM_EXITMENULOOP:
        // Ignore time spent in menu
        g_dwLastTick = timeGetTime();
        break;
    case WM_EXITSIZEMOVE:
        // Ignore time spent resizing
        g_dwLastTick = timeGetTime();
        break;
    case WM_DESTROY:
        // Cleanup and close the app
        FreeDirectDraw();
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc( hwnd, uMsg, wParam, lParam );
}
 
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow
                   )
{
    HWND hwnd;
    WNDCLASSEX wc;
 
         //this is a simple WNDCLASSEX structure
    memset( &wc, 0, sizeof(wc) );
    wc.cbSize = sizeof( wc );
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor( NULL, IDC_ARROW);
    wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
    wc.lpszMenuName = MAKEINTRESOURCE( IDR_MENU );
    wc.lpszClassName = L"DDWindow";
 
    RegisterClassEx( &wc );
 
         //because dimension of the window created by CreateWindowEx function
         //include the caption menu and frame,
         //so the important thing is resize your window,
    DWORD dwFrameWidth      = GetSystemMetrics( SM_CXSIZEFRAME );
    DWORD dwFrameHeight     = GetSystemMetrics( SM_CYSIZEFRAME );
    DWORD dwMenuHeight      = GetSystemMetrics( SM_CYMENU );
    DWORD dwCaptionHeight   = GetSystemMetrics( SM_CYCAPTION );
 
         //the actual width and height
    DWORD dwWindowWidth     = WINDOW_WIDTH + dwFrameWidth * 2;
    DWORD dwWindwoHeight    = WINDOW_HEIGHT + dwFrameHeight * 2
        + dwMenuHeight + dwCaptionHeight;
 
    hwnd = CreateWindowEx(0, L"DDWindow", L"DirectDraw1-CreateWindow",
       WS_OVERLAPPEDWINDOW ,
       CW_USEDEFAULT, 0,
       dwWindowWidth,
       dwWindwoHeight,
       NULL, NULL, hInstance, NULL );
 
    ShowWindow( hwnd, nCmdShow);
    UpdateWindow( hwnd );
 
    //ok directdraw
    if( FAILED( InitDirectDraw( hwnd ) ) )
    {
        MessageBox( hwnd, TEXT("DirectDraw Init Failed."),
            TEXT("DirectDraw1"), MB_ICONERROR | MB_OK );
        return false;
    }
 
    g_dwLastTick = timeGetTime();
         //end
 
    MSG msg;
    while(1)
    {
        // Look for messages, if none are found then
        // update the state and display it
        if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
        {
            if(0 == GetMessage( &msg, NULL, 0, 0 ) )
                // WM_QUIT was posted, so exit
                return (int)msg.wParam;
            // Translate and dispatch the message
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
                   //not message in the thread's queue, so we do our draw things
        else
        {
            if( g_bActive )
            {
                if( FAILED( Update( hwnd ) ) )
                {
                    SAFE_DELETE( g_pDisplay );
                    MessageBox( hwnd, TEXT("Update failed."),
                        TEXT("DirectDraw1"),
                        MB_ICONERROR | MB_OK );
                    return FALSE;
                }
            }
            else
            {
                // Make sure we go to sleep if we have nothing else to do
                WaitMessage();
                // Ignore time spent inactive
                g_dwLastTick = timeGetTime();
            }
        }
    }
 
    return 0;
}
 
 
二、DirectDraw初始化和处理函数
 
#pragma once
 
//this file include all important function to draw bitmap in my window
//Class CDisplay and CSurface come from ddutil you can find it in DX8.0
 
//you can get this head file from dx8.0 sample folder
#include "../ddutil/ddutil.h"
#include "../ddutil/dxutil.h"
 
//timeGetTime()
#pragma comment(lib, "Winmm.lib")
#pragma comment( lib, "ddraw" )
#pragma comment( lib, "dxguid" )
 
CDisplay* g_pDisplay = NULL;
CSurface* g_pBackground = NULL;
CSurface* g_pLogo = NULL;
 
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define LOGOWIDTH 128
#define LOGOHEIGHT 128
 
DWORD g_dwLastTick;
 
//d3d8math.h
static D3DXVECTOR2 dvPos;
static D3DXVECTOR2 dvVel;
 
static float incr = 100;
 
HRESULT InitDirectDraw( HWND hWnd )
{
    LPDIRECTDRAWPALETTE pDDPal = NULL;
    HRESULT hr;
 
    g_pDisplay = new CDisplay();
    if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd,
        WINDOW_WIDTH, WINDOW_HEIGHT ) ) )
    {
        MessageBox( hWnd, TEXT("Failed initializeing DirectDraw."),
            TEXT("DirectDraw1"), MB_ICONERROR | MB_OK );
        return hr;
    }
 
    if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_BK ) ) ) )
        return hr;
 
    g_pDisplay->SetPalette( pDDPal );
 
    SAFE_RELEASE( pDDPal );
 
    // Create a surface, and draw a bitmap resource on it.
    if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pBackground,
        MAKEINTRESOURCE( IDB_BK ), WINDOW_WIDTH, WINDOW_HEIGHT )))
        return hr;
 
    if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pLogo,
        MAKEINTRESOURCE( IDB_LOGO ), LOGOWIDTH, LOGOHEIGHT )))
        return hr;
 
    dvVel.x = 100;
    dvVel.y = 100;
 
    return S_OK;
}
 
VOID FreeDirectDraw()
{
    SAFE_DELETE( g_pLogo );
    SAFE_DELETE( g_pBackground );
    SAFE_DELETE( g_pDisplay );
}
 
HRESULT Render()
{
    HRESULT hr;
   
    g_pDisplay->Clear(0);
        
         //i have changed the name of Blt function to DefBltFast but didn't modify it
    g_pDisplay->DefBltFast(0, 0, g_pBackground );
 
    g_pDisplay->DefBltFast(dvPos.x, dvPos.y, g_pLogo );
 
    if( FAILED( hr = g_pDisplay->Present()))
        return hr;
    return S_OK;
}
 
HRESULT RestoreSurfaces()
{
    LPDIRECTDRAWPALETTE pDDPal = NULL;
    HRESULT hr;
   
    if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces()))
        return hr;
    if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_BK ) ) ) )
        return hr;
    g_pDisplay->SetPalette( pDDPal );
   
    SAFE_RELEASE( pDDPal );
 
 
    if( FAILED( hr = g_pBackground->DrawBitmap( MAKEINTRESOURCE( IDB_BK ),
        WINDOW_WIDTH, WINDOW_HEIGHT ) ) )
        return hr;
 
    if( FAILED( hr = g_pLogo->DrawBitmap( MAKEINTRESOURCE( IDB_LOGO ),
        LOGOWIDTH, LOGOHEIGHT )))
        return hr;
    return S_OK;
 
}
 
HRESULT Update( HWND hWnd )
{
    //::OutputDebugString(TEXT("Update/n"));
    HRESULT hr;
 
    DWORD dwCurrTick = timeGetTime();
    DWORD dwTickDiff = dwCurrTick - g_dwLastTick;
 
    if( dwTickDiff == 0 ) return S_OK;
 
    g_dwLastTick = dwCurrTick;
 
    dvPos += dvVel * dwTickDiff / 1000.0f;
 
    if( dvPos.x > WINDOW_WIDTH - LOGOWIDTH || dvPos.x < 0 )
    {
        dvVel.x = - dvVel.x;
        dvPos.x += dvVel.x * dwTickDiff / 1000.0f;
    }
    if( dvPos.y > WINDOW_HEIGHT - LOGOHEIGHT || dvPos.y < 0 )
    {
        dvVel.y = - dvVel.y;
        dvPos.y += dvVel.y * dwTickDiff / 1000.0f;
    }
 
    // Check the cooperative level before rendering
    if( FAILED( hr = g_pDisplay->GetDirectDraw()->TestCooperativeLevel()))
    {
        switch( hr )
        {
        case DDERR_EXCLUSIVEMODEALREADYSET:
            Sleep( 10 );
            return S_OK;
       
        case DDERR_WRONGMODE:
            FreeDirectDraw();
            return InitDirectDraw( hWnd );
        }
        return hr;
    }
 
    if( FAILED( hr = Render() ) )
    {
        if( hr != DDERR_SURFACELOST )
            return hr;
        RestoreSurfaces();
    }
    return S_OK;
}
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值