Sign in to follow this  
SRAX

GDI Color Key issue

Recommended Posts

(OS: Win32, Language: C++, API: DirectX, Compiler: Mingw32) I just recently started working on a 2D fighter. I had never worked with sprites or anything similar before, and I figured a tutorial on DirectX was a good place to start. From the tutorial here. I was able to learn quite a bit, and I liked the C++ Class that he created enough I decided I was going to use it. The problem came when it was time to start combining elements. This code draws the background regardless of what is passed to the dwColorKey argument of cSurface::Create. The only exception is that pure black works (although the message board on that site suggests white may work as well). As I understand what is on the MSDN pages for the functions the author used, it should work. On an interesting note, in cSurface::LoadBitmap the call to StretchBlt (at least on my computer) does not seem to perfectly copy the colors from one surface to another. In the example I used, the color 0,128,192 on hdcImage became 0,130,198 on hdc. I tried to account for that by adjusting the keyed color to that one. I also suspected this may be an issue: ddck.dwColorSpaceLowValue = dwColorKey; ddck.dwColorSpaceHighValue = 0; Changing the HighValue to dwColorKey did not fix the problem, though. This problem came up a few times on the board for the page I got this from, but always the people solved the problem by painting the background pure black. That is not a valid option for me, though. Thank you in advance for any help. http://www.codeproject.com/directx/basicdd.asp cSurface.h:
#ifndef CSURFACE_H
#define CSURFACE_H

#include <windows.h>
#include <ddraw.h>

class cSurface
{
    public:
        //cSurface ();
        BOOL Create ( LPDIRECTDRAW7, int, int, COLORREF );
        BOOL LoadBitmap(HINSTANCE, HBITMAP &, int, int, 
            int, int);
        BOOL LoadBitmap(HINSTANCE, char *, int, int,
            int, int );
        BOOL Draw (LPDIRECTDRAWSURFACE7, int, int, int, int, int, int );
        int GetHeight ();
        int GetWidth ();
        void Destroy ();
    protected:
        COLORREF m_ColorKey;
        UINT m_Height;
        UINT m_Width;
        LPDIRECTDRAWSURFACE7 m_pSurface;
        struct m_Info
        {
            HINSTANCE m_hInstance;
            UINT m_nResource;
            int m_iX;
            int m_iY;
            int m_iWidth;
            int m_iHeight;
        };
        struct m_Info m_srcInfo;
};

#endif


Excerpts from cSurface.cpp:
BOOL cSurface::Create(LPDIRECTDRAW7 hDD, int nWidth, int nHeight, 
                      COLORREF dwColorKey)
{
    DDSURFACEDESC2    ddsd;
    HRESULT        hRet;
    DDCOLORKEY          ddck;


    ZeroMemory( &ddsd, sizeof( ddsd ) );

    ddsd.dwSize = sizeof( ddsd );
    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
    
    ddsd.dwWidth  = nWidth;
    ddsd.dwHeight = nHeight;

    hRet = hDD->CreateSurface(&ddsd, &m_pSurface, NULL );
    if( hRet != DD_OK )
    {
        
    if(hRet == DDERR_OUTOFVIDEOMEMORY)
    {
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
                  DDSCAPS_SYSTEMMEMORY;
    
    hRet = hDD->CreateSurface(&ddsd, &m_pSurface, NULL );
    }

    if( hRet != DD_OK )
    {
        return FALSE;
    }
    }


    if((int)dwColorKey != -1)
    {
    ddck.dwColorSpaceLowValue = dwColorKey;
    ddck.dwColorSpaceHighValue = 0;
    m_pSurface->SetColorKey(DDCKEY_SRCBLT, &ddck);
    }

    m_ColorKey = dwColorKey;
    m_Width  = nWidth;
    m_Height = nHeight;

    return TRUE;
}

BOOL cSurface::LoadBitmap(HINSTANCE hInst, UINT nRes, int nX, int nY, 
                          int nWidth, int nHeight)
{
    HDC                     hdcImage;
    HDC                     hdc;
    BITMAP                  bm;
    DDSURFACEDESC2          ddsd;
    HRESULT                 hr;

    HBITMAP    hbm;

    hbm = (HBITMAP) LoadImage(hInst, MAKEINTRESOURCE(nRes), 
                              IMAGE_BITMAP, nWidth, nHeight, 0L);

    if (hbm == NULL || m_pSurface == NULL)
        return FALSE;

    // Make sure this surface is restored.
    m_pSurface->Restore();

    // Select bitmap into a memoryDC so we can use it.
    hdcImage = CreateCompatibleDC(NULL);
    if (!hdcImage)
        return FALSE;

    SelectObject(hdcImage, hbm);

    // Get size of the bitmap
    GetObject(hbm, sizeof(bm), &bm);

    if(nWidth == 0)
    nWidth = bm.bmWidth;
    
    if(nHeight == 0)
    nHeight = bm.bmHeight;
    
    // Get size of surface.
    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
    m_pSurface->GetSurfaceDesc(&ddsd);

    if ((hr = m_pSurface->GetDC(&hdc)) == DD_OK)
    {
        StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, 
                   nX, nY, nWidth, nHeight, SRCCOPY);
        m_pSurface->ReleaseDC(hdc);
    }
    DeleteDC(hdcImage);

    m_srcInfo.m_hInstance = hInst;
    m_srcInfo.m_nResource = nRes;
    m_srcInfo.m_iX          = nX;
    m_srcInfo.m_iY          = nY;
    m_srcInfo.m_iWidth    = nWidth;
    m_srcInfo.m_iHeight      = nHeight;
    
    return TRUE;
}

BOOL cSurface::Draw(LPDIRECTDRAWSURFACE7 lpDest, int iDestX, int iDestY, 
                    int iSrcX, int iSrcY, int nWidth, int nHeight)
{
    RECT    rcRect;
    HRESULT    hRet;

    if(nWidth == 0)
        nWidth = m_Width;

    if(nHeight == 0)
        nHeight = m_Height;

    rcRect.left   = iSrcX;
    rcRect.top    = iSrcY;
    rcRect.right  = nWidth  + iSrcX;
    rcRect.bottom = nHeight + iSrcY;

    while(1)
    {
        if((int)m_ColorKey < 0)
        {
            hRet = lpDest->BltFast(iDestX, iDestY, m_pSurface, 
                                   &rcRect,  DDBLTFAST_NOCOLORKEY);
        }
        else
        {
            hRet = lpDest->BltFast(iDestX, iDestY, m_pSurface, 
                                   &rcRect,  DDBLTFAST_SRCCOLORKEY);
        }

        if(hRet == DD_OK)
            break;

        if(hRet == DDERR_SURFACELOST)
        {
            Restore();
        }
        else
        {
            if(hRet != DDERR_WASSTILLDRAWING)
                return FALSE;
        }
    }

    return TRUE;
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this