質問

I draw text on the window by using ID3DXFont::DrawText. But when the window resized, the text stretched/shrank as well. I tried to calculate the percentage of window size changed, and apply to the font size, but it look really bizarre. I wonder if there is anyway to fixed the font size even window size is changed. Here's how I draw text:

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

if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
    D3DXFONT_DESC df;
    ZeroMemory(&df,sizeof(D3DXFONT_DESC));
    df.Height = 25;
    df.Width = 0;
    df.Weight = 100;
    df.MipLevels = D3DX_DEFAULT;
    df.Italic = false;
    df.CharSet = DEFAULT_CHARSET;
    df.Quality = 0;
    df.PitchAndFamily = 0;

    strcpy(df.FaceName,"Candara");
    D3DXCreateFontIndirect(g_pd3dDevice,&df,&g_font);
    RECT g_FontPosition = {0, 0, 300, 300};     
    g_font->DrawText(NULL,"Hello World",-1,&g_FontPosition,
                          DT_CENTER|DT_VCENTER,D3DCOLOR_XRGB(255,255,255));
    // End the scene
    g_pd3dDevice->EndScene();
}

g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

I tried to use SetViewport method, however it didn't work. The following code shows how I manipulate direct3d. I have stuck in this issue for quite a while and completely have no clue to solve it.

STDMETHODIMP VideoRender::InitializeD3D(VOID)
{
    HRESULT hr = E_FAIL;
    D3DDISPLAYMODE d3ddm;
    D3DCAPS9 d3dcaps;
    DWORD dwCreateFlags = D3DCREATE_FPU_PRESERVE;
    D3DPRESENT_PARAMETERS d3dpp;

    m_lpD3D = Direct3DCreate9(D3D_SDK_VERSION);
    hr = IDirect3D9_GetAdapterDisplayMode(m_lpD3D, D3DADAPTER_DEFAULT, &d3ddm);
    if (m_lpD3D == NULL)
        goto error_occured;

    hr = IDirect3D9_GetAdapterDisplayMode(m_lpD3D, D3DADAPTER_DEFAULT, &d3ddm);
    if (FAILED(hr))
        goto error_occured;

    hr = IDirect3D9_GetDeviceCaps(m_lpD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
    if (FAILED(hr))
        goto error_occured;

    if ((d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == D3DDEVCAPS_HWTRANSFORMANDLIGHT)
        dwCreateFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        dwCreateFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    if ( (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) == D3DPTFILTERCAPS_MINFLINEAR 
        && (d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR) == D3DPTFILTERCAPS_MAGFLINEAR ) {
        m_d3dfiltertype = D3DTEXF_LINEAR;
    } else
        m_d3dfiltertype = D3DTEXF_NONE;

    m_d3dformat = d3ddm.Format;

    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferCount = 1;
    d3dpp.BackBufferFormat = m_d3dformat;
    d3dpp.BackBufferWidth = m_dwWindowWidth;
    d3dpp.BackBufferHeight = m_dwWindowHeight;
    d3dpp.MultiSampleQuality = D3DMULTISAMPLE_NONE;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    hr = IDirect3D9_CreateDevice(m_lpD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hAppWindow, dwCreateFlags, &d3dpp, &m_lpDevice);
    if (FAILED(hr))
        goto error_occured;

    return S_OK;

error_occured:
    return hr;
}



STDMETHODIMP VideoRender::InitializeSwapChain(DWORD dwWidth, DWORD dwHeight)
{
    HRESULT hr = E_FAIL;
    D3DPRESENT_PARAMETERS d3dpp;
    D3DTEXTUREFILTERTYPE d3dfiltertype;
    D3DFORMAT d3dformat;
    D3DFORMAT d3dfourcc;
    D3DLOCKED_RECT LockedRect = {0};
    LPBYTE lpByte = NULL;
    LPDWORD lpdwColor = NULL;
    DWORD dwFontSize = 16;

    if (m_lpDevice == NULL)
        InitializeD3D();

    if (m_lpDevice) {
        if (dwWidth && dwHeight) {
            m_dwVideoWidth = dwWidth;
            m_dwVideoHeight = dwHeight;

            d3dfourcc = (D3DFORMAT) MAKEFOURCC('Y', 'V', '1', '2');
            d3dformat = D3DFMT_X8R8G8B8;

            ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
            d3dpp.Windowed = TRUE;
            d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
            d3dpp.BackBufferWidth = m_dwVideoWidth;
            d3dpp.BackBufferHeight = m_dwVideoHeight;
            d3dpp.BackBufferFormat = d3dformat;
            d3dpp.hDeviceWindow = m_hAppWindow;

            hr = IDirect3DDevice9_CreateAdditionalSwapChain(m_lpDevice, &d3dpp, &m_lpSwapChain);
            if (FAILED(hr))
                goto error_occured;

            hr = IDirect3DDevice9_CreateOffscreenPlainSurface(m_lpDevice, m_dwVideoWidth, m_dwVideoHeight, d3dfourcc, D3DPOOL_DEFAULT, &m_lpSurface, NULL);
            if (FAILED(hr))
                goto error_occured;

            hr = IDirect3D9_CheckDeviceFormat(m_lpD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_d3dformat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dformat);
            if (FAILED(hr))
                d3dfiltertype = D3DTEXF_NONE;
            else
                d3dfiltertype = m_d3dfiltertype;

            m_d3dfiltertype = d3dfiltertype;
            m_d3dformat = d3dformat;
            m_d3dfourcc = d3dfourcc;

            hr = IDirect3DDevice9_CreateTexture(m_lpDevice, 2048, 2048, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_lpTexture, NULL);
            IDirect3DTexture9_LockRect(m_lpTexture, 0, &LockedRect, NULL, D3DLOCK_DISCARD);
            lpByte = (LPBYTE) LockedRect.pBits;
            lpdwColor = (LPDWORD) lpByte;
            memset(lpByte, 0xff, 2048 * 2048 * 4);
            IDirect3DTexture9_UnlockRect(m_lpTexture, 0);

            hr = D3DXCreateSprite(m_lpDevice, &m_lpSprite);
            if (FAILED(hr)) {
            }

            hr = D3DXCreateFont(m_lpDevice, dwFontSize, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Consolas", &m_lpInfoFont);
            if (FAILED(hr)) {
            }

            m_bInitedSwapChain = TRUE;
        }
    }

    return S_OK;

error_occured:
    return hr;
}



STDMETHODIMP VideoRender::Update(LPBYTE lpBuffer)
{
    HRESULT hr = S_OK;
    LPDIRECT3DSURFACE9 lpBackBuffer = NULL;
    DWORD dwWidth = 0;
    DWORD dwHeight = 0;
    D3DPRESENT_PARAMETERS d3dpp;


    if (lpPluginBuffer) {
        EnterCriticalSection(&m_csSwapChain);
        if (m_lpSwapChain) {
            IDirect3DSwapChain9_GetPresentParameters(m_lpSwapChain, &d3dpp);

            hr = IDirect3DSwapChain9_GetBackBuffer(m_lpSwapChain, 0, D3DBACKBUFFER_TYPE_MONO, &lpBackBuffer);
            hr = IDirect3DDevice9_SetRenderTarget(m_lpDevice, 0, lpBackBuffer);
            hr = IDirect3DSurface9_Release(lpBackBuffer);
            hr = IDirect3DDevice9_Clear(m_lpDevice, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

            hr = IDirect3DDevice9_BeginScene(m_lpDevice);
            if (SUCCEEDED(hr)) {
                D3DLOCKED_RECT LockedRect;
                LPBYTE source = 0, dest = 0;

                ZeroMemory(&LockedRect, sizeof(D3DLOCKED_RECT));
                hr = IDirect3DSurface9_LockRect(m_lpSurface, &LockedRect, NULL, 0);
                dest = (LPBYTE) LockedRect.pBits;
                source = lpPluginBuffer->lpBuffer;
                if (SUCCEEDED(hr) && dest) {
                    /* copy image buffer to LockedRect */
                }
                IDirect3DSurface9_UnlockRect(m_lpSurface);
                hr = IDirect3DDevice9_StretchRect(m_lpDevice, m_lpSurface, lprtSrc, lpBackBuffer, lprtDest, D3DTEXF_LINEAR);

                m_lpSprite->Begin(D3DXSPRITE_ALPHABLEND);
                pos.x = 0;
                pos.y = 0;
                pos.z = 0;

                SetRect(&rt, 0, 0, 100, 100);
                m_lpInfoFont->DrawTextW(m_lpSprite, L"test", -1, &rt, DT_VCENTER, D3DCOLOR_RGBA(0, 255, 255, 0xff));
                m_lpSprite->End();
            }
            hr = IDirect3DDevice9_EndScene(m_lpDevice);
            hr = IDirect3DSwapChain9_Present(m_lpSwapChain, NULL, NULL, NULL, NULL, 0);
        }
        LeaveCriticalSection(&m_csSwapChain);
    }

    return S_OK;
}

Thanks a lot, this really help a lot.

But if I create a swap chain with different resolution backbuffer from window size (either greater or small). And rendering some images to the window, it automatically re-size the images to fit the window size. Seemed the Viewport has been changed due to different size. The drawn text would be stretched/shrank as well. Is there any way to prevent this from happening?

I want the overlay text not to be affected by anything else.

役に立ちましたか?

解決

You have to reset the Direct3D device each time the size of the window changes.

Use IDirect3DDevice9::Reset method. Remember to release all resources created in the default pool first.

You should check for WM_SIZE in window message loop in order to determine if the window's size has changed.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top