如何刷新图形以避免黑屏?

Posted

技术标签:

【中文标题】如何刷新图形以避免黑屏?【英文标题】:How to refresh the graphics to avoid black screen? 【发布时间】:2013-10-12 15:05:31 【问题描述】:

当我最小化我的 directx 框架并打开任务管理然后回到框架。它给了我黑屏。我应该如何修改我的代码来修复这个缺陷?

GraphicsClass.h

#ifndef _GRAPHICSCLASS_H_
#define _GRAPHICSCLASS_H_


//////////////
// INCLUDES //
//////////////
#include <d3dx9.h>
#include <assert.h>
#include <string>
using namespace std;


/////////////
// GLOBALS //
/////////////
const bool FULL_SCREEN           = false;
const unsigned int SCREEN_WIDTH  = 1280;
const unsigned int SCREEN_HEIGHT = 720;



////////////////////////////////////////////////////////////////////////////////
// Class name: GraphicsClass
////////////////////////////////////////////////////////////////////////////////
class GraphicsClass

public:
    GraphicsClass( HWND hwnd );
    ~GraphicsClass();
    void SetPath( const string& loadFolder );

    void BeginFrame();
    void EndFrame();

    void Load( IDirect3DTexture9*& texture, string imgName, int imgWidth, int imgHeight );
    void setFont(ID3DXFont*& font, char* fontName, int fontHeight);

    void SourceRect( RECT& sourceRect, int left, int right, int top, int bottom );

    void DrawText( ID3DXFont*& font, LPCSTR string, int charNum, RECT& SourceRect, DWORD format, D3DCOLOR color );
    void Draw( IDirect3DTexture9* texture );
    void Draw( IDirect3DTexture9* texture, float posX, float posY );
    void Draw( IDirect3DTexture9* texture, RECT& sourceRect, float posX, float posY );

private:
    string              path;
    HRESULT             result;
    ID3DXSprite*        pSprite;
    IDirect3D9*         pDirect3D;
    IDirect3DDevice9*   pDevice;
;


#endif

GraphicsClass.cpp

#include "GraphicsClass.h"

GraphicsClass::GraphicsClass( HWND hwnd )

    pDirect3D = Direct3DCreate9( D3D_SDK_VERSION );

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed              = TRUE;
    d3dpp.SwapEffect            = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat      = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferCount       = 1;
    d3dpp.BackBufferWidth       = SCREEN_WIDTH;
    d3dpp.BackBufferHeight      = SCREEN_HEIGHT;
    d3dpp.hDeviceWindow         = hwnd;
    //d3dpp.PresentationInterval  = D3DPRESENT_INTERVAL_ONE;

    result = pDirect3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, 
     D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
    assert( !FAILED(result) );

    result = D3DXCreateSprite( pDevice, &pSprite );
    assert( !FAILED(result) );



GraphicsClass::~GraphicsClass()

    //  Release and clean up sprite
    pSprite->Release();
    pSprite = NULL;



void GraphicsClass::SetPath( const string& path )

    this->path = path;



void GraphicsClass::BeginFrame()

    pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 255, 255, 255 ), 1.0f, 0 );
    pDevice->BeginScene(); 

    //  Specify alpha blend will ensure that the sprite will render the background with alpha.
    pSprite->Begin( D3DXSPRITE_ALPHABLEND );



void GraphicsClass::EndFrame()

    //  End sprite drawing
    pSprite->End();

    pDevice->EndScene();
    pDevice->Present( NULL, NULL, NULL, NULL );



void GraphicsClass::Load( IDirect3DTexture9*& texture, string imgName, int imgWidth, int imgHeight )

    string fullPath;
    fullPath = path + imgName;

    result = D3DXCreateTextureFromFileEx( pDevice, fullPath.c_str(), imgWidth, imgHeight, 
    D3DX_DEFAULT, NULL, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, 
    D3DX_DEFAULT, D3DX_DEFAULT, NULL, 
    NULL, NULL, &texture );



void GraphicsClass::setFont(ID3DXFont*& font, char* fontName, int fontHeight)

    result = D3DXCreateFont(pDevice, fontHeight, 0, 0, 1, false,
    DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, DEFAULT_QUALITY,
    DEFAULT_PITCH | FF_DONTCARE, fontName, &font);



void GraphicsClass::SourceRect( RECT& sourceRect, int left, int right, int top, int bottom )

    sourceRect.left     = left;
    sourceRect.right    = right;
    sourceRect.top      = top;
    sourceRect.bottom   = bottom;



void GraphicsClass::DrawText( ID3DXFont*& font, LPCSTR string, int charNum, RECT& SourceRect, DWORD format, D3DCOLOR color)

    font->DrawText(pSprite, string, charNum, &SourceRect, format, color);



void GraphicsClass::Draw( IDirect3DTexture9* texture )

    pSprite->Draw( texture, NULL, NULL, &D3DXVECTOR3( 0, 0, 0 ), D3DCOLOR_XRGB( 255, 255, 255 ) );



void GraphicsClass::Draw( IDirect3DTexture9* texture, float posX, float posY )

    pSprite->Draw( texture, NULL, NULL, &D3DXVECTOR3( posX, posY, 0 ), D3DCOLOR_XRGB( 255, 255, 255 ) ); 



void GraphicsClass::Draw( IDirect3DTexture9* texture, RECT& sourceRect, float posX, float posY )

    pSprite->Draw( texture, &sourceRect, NULL, &D3DXVECTOR3( posX, posY, 0 ), D3DCOLOR_XRGB( 255, 255, 255 ) );

系统类.cpp

void SystemClass::InitializeWindows()

    WNDCLASSEX wc;
    DEVMODE dmScreenSettings;

    int screenWidth, screenHeight;
    int posX, posY;


    // Get an external pointer to this object
    ApplicationHandle = this;

    // Get the instance of this application
    m_hinstance = GetModuleHandle( NULL );

    // Give the application a name
    m_applicationName = "Zero DirectX Framework";

    // Setup the windows class with default settings
    wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc      = WndProc;
    wc.cbClsExtra       = 0;
    wc.cbWndExtra       = 0;
    wc.hInstance        = m_hinstance;
    wc.hIcon            = LoadIcon( NULL, IDI_WINLOGO );
    wc.hIconSm          = wc.hIcon;
    wc.hCursor          = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground    = (HBRUSH)GetStockObject( BLACK_BRUSH );
    wc.lpszMenuName     = NULL;
    wc.lpszClassName    = m_applicationName;
    wc.cbSize           = sizeof( WNDCLASSEX );

    // Register the window class
    RegisterClassEx( &wc );

    // Determine the resolution of the clients desktop screen
    screenWidth  = GetSystemMetrics( SM_CXSCREEN );
    screenHeight = GetSystemMetrics( SM_CYSCREEN );

    // Setup the screen settings depending on whether it is running in full screen or in windowed mode
    if ( FULL_SCREEN )
    
        // If full screen set the screen to maximum size of the users desktop and 32bit
        memset( &dmScreenSettings, 0, sizeof(dmScreenSettings) );
        dmScreenSettings.dmSize         = sizeof(dmScreenSettings);
        dmScreenSettings.dmPelsWidth    = (unsigned long)screenWidth;
        dmScreenSettings.dmPelsHeight   = (unsigned long)screenHeight;
        dmScreenSettings.dmBitsPerPel   = 32;
        dmScreenSettings.dmFields       = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        // Change the display settings to full screen
        ChangeDisplaySettings( &dmScreenSettings, CDS_FULLSCREEN );

        // Set the position of the window to the top left corner
        posX = posY = 0;

        // Create the window with the screen settings and get the handle to it
        m_hwnd = CreateWindowEx( WS_EX_APPWINDOW, m_applicationName, m_applicationName, 
        WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
        posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);

        SetMenu( m_hwnd, NULL );
    
    else
    
        // If windowed then set it to 800x600 resolution
        screenWidth  = 1280;
        screenHeight = 768;

        // Place the window in the middle of the screen
        posX = ( GetSystemMetrics( SM_CXSCREEN ) - screenWidth ) / 2;
        posY = ( GetSystemMetrics( SM_CYSCREEN ) - screenHeight) / 2;

        m_hwnd = CreateWindowEx( 0, m_applicationName, m_applicationName, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, 
        posX, posY, screenWidth, screenHeight, 
        NULL, NULL, m_hinstance, NULL );
    

    // Bring the window up on the screen and set it as main focus
    ShowWindow( m_hwnd, SW_SHOW );
    SetForegroundWindow( m_hwnd );
    SetFocus( m_hwnd );

    // Hide the mouse cursor
    ShowCursor(true);

【问题讨论】:

msdn.microsoft.com/en-us/library/windows/desktop/… 【参考方案1】:

您没有处理when device is lost 的情况,这是(可能)在这种情况下发生的情况。

基本上,在渲染任何东西之前你应该test cooperative level,如果它返回D3DERR_DEVICELOST,不要不绘制任何东西。如果返回D3DERR_DEVICENOTRESET,则应该reset设备,如果返回0(D3DERR_OK或使用SUCCEEDED宏),则继续绘制框架。

重置设备时,它会丢失所有不在D3DPOOL_MANAGED 中的资源,您需要重新创建它们或重新加载它们。您可以在调用 IDirect3DDevice9::Reset 之前释放所有着色器和 id3dx 对象(如 ID3DXFont),然后在成功重置调用后重新创建它们。

未能处理“丢失的设备”意味着您将无法在全屏运行时使用 alt-tab 键,切换显示模式可能会“破坏它”。在您的情况下,黑屏很可能出于同样的原因发生。

【讨论】:

已解决。我使用 pSprite -> OnLostDevice(); pDevice -> 重置( &d3dpp ); pSprite -> OnResetDevice();

以上是关于如何刷新图形以避免黑屏?的主要内容,如果未能解决你的问题,请参考以下文章

如何避免 BigQuery 中的 Power BI 增量刷新重复查询?

如何在同一位置刷新div,避免重复行

AOC27g2怎么设置成高刷新率屏幕就黑屏呢

如何避免在带有 Swift 4 的 iOS 11 中使用带有刷新控件的 @objc?

打开电脑玩一段时间把所有窗口关完,桌面刷新很慢,注消一下桌面刷新就跟开机一样了,为何呢?

php如何避免刷新页面重复提交