DirectX应用程序关闭,返回码为101

时间:2013-12-17 10:34:06

标签: c++ winapi visual-c++ directx

我有一个简单的DirectX应用程序(实际上我正在遵循一些教程)。现在我想使用生成WM_TIMER消息的计时器。

问题在于,如果我不处理WM_PAINT(因为渲染是在主循环中完成的),WM_TIMER永远不会被捕获,因为WM_PAINT优先级较高且持续泛滥使用WM_PAINT的消息处理程序。

我尝试调用BeginPaint()EndPaint()来验证窗口,我也尝试调用ValidateRect(),但问题是应用程序在1秒左右后总是关闭,返回码为101.如果没有WM_PAINT的处理,它可以正常工作,但计时器永远不会被处理。

有什么问题?

#include "stdafx.h"
#include "TransformingVertices.h"

// define the screen resolution
#define SCREEN_WIDTH  800
#define SCREEN_HEIGHT 600

// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

// global declarations
HWND g_hWnd;
LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 g_v_buffer;

int g_i = 0;
float g_angle = 0.0f;

// function prototypes
void initD3D(HWND hWnd);    // sets up and initializes Direct3D
void init_graphics(int = 0);    // copies vertex data to the VRAM
void render_frame(void);    // renders a single frame
void cleanD3D(void);    // closes Direct3D and releases memory


#define MAX_LOADSTRING 100
#define ID_10MILLIS 101

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPTSTR    lpCmdLine,
    _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_TRANSFORMINGVERTICES, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TRANSFORMINGVERTICES));

    initD3D(g_hWnd);
    init_graphics();
    SetTimer(g_hWnd,             // handle to main window 
        ID_10MILLIS,            // timer identifier 
        100,                 // interval 
        (TIMERPROC)NULL);     // no timer callback 

    // Main message loop:
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        render_frame();
    }

    cleanD3D();

    return (int)msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TRANSFORMINGVERTICES));
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TRANSFORMINGVERTICES);
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, 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, int nCmdShow)
{

    hInst = hInstance; // Store instance handle in our global variable

    g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
        50, 50, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);

    if (!g_hWnd)
    {
        return FALSE;
    }

    ShowWindow(g_hWnd, nCmdShow);
    UpdateWindow(g_hWnd);

    return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  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)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    memset(&ps, 0, sizeof(ps));
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            //DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_MOUSEWHEEL:
        g_i++;
        //g_v_buffer->Release();
        //init_graphics(g_i);
        break;
    case WM_PAINT:
        //hdc = BeginPaint(hWnd, &ps);
         //TODO: Add any drawing code here...
        //EndPaint(hWnd, &ps);
        ValidateRect(hWnd, 0);
        break;
    case WM_TIMER:
        g_angle += 0.05;
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}


// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface

    D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information

    ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use
    d3dpp.Windowed = TRUE;    // program windowed, not fullscreen
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames
    d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D

    // create a device class using this information and information from the d3dpp stuct
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
        D3DDEVTYPE_HAL,
        hWnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &d3dpp,
        &d3ddev);

    d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
    d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}

void init_graphics(int i)
{
    // create three vertices using the CUSTOMVERTEX struct built earlier
    CUSTOMVERTEX vertices[] =
    {
        {  0.0f, -3.0f , 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
        {  3.0f,  3.0f,  0.0f, D3DCOLOR_XRGB(0, 255, 0), },
        { -3.0f,  3.0f,  0.0f, D3DCOLOR_XRGB(255, 0, 0), },
    };


    d3ddev->CreateVertexBuffer(3 * sizeof(CUSTOMVERTEX), 0, CUSTOMFVF, D3DPOOL_MANAGED, &g_v_buffer, 0);

    VOID* pVoid;

    g_v_buffer->Lock(0, 0, &pVoid, 0);
    memcpy(pVoid, vertices, 3 * sizeof(CUSTOMVERTEX));
    g_v_buffer->Unlock();
}

// this is the function used to render a single frame
void render_frame(void)
{
    // clear the window to a deep blue
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, g_i * 4, g_i * 10), 1.0f, 0);

    d3ddev->BeginScene();    // begins the 3D scene

    d3ddev->SetFVF(CUSTOMFVF);
    d3ddev->SetStreamSource(0, g_v_buffer, 0, sizeof(CUSTOMVERTEX));

    D3DXMATRIX transformation;
    D3DXMATRIX rotation;
    D3DXMatrixTranslation(&transformation, 4, 0, 0);
    D3DXMatrixRotationY(&rotation, g_angle);
    //d3ddev->SetTransform(D3DTS_WORLD, &rotation);
    d3ddev->SetTransform(D3DTS_WORLD, &(rotation*transformation));

    D3DXVECTOR3 from = { 0, 0, 10.0f },
                at = { 0, 0, 0.0f },
                up = { 0, -1, 0 };
    D3DXMATRIX viewTransform;
    D3DXMatrixLookAtLH(&viewTransform, &from, &at, &up);
    d3ddev->SetTransform(D3DTS_VIEW, &viewTransform);

    D3DXMATRIX perspective;
    D3DXMatrixPerspectiveFovLH(&perspective, D3DX_PI/2.0f, ((float) SCREEN_WIDTH) / SCREEN_HEIGHT, 1.0f, 100.0f);
    d3ddev->SetTransform(D3DTS_PROJECTION, &perspective);

    d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 1);

    d3ddev->EndScene();    // ends the 3D scene

    d3ddev->Present(NULL, NULL, NULL, NULL);    // displays the created frame   
}

// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
    g_v_buffer->Release();
    d3ddev->Release();    // close and release the 3D device
    d3d->Release();    // close and release Direct3D
}

0 个答案:

没有答案