   ddraw - confused about size of surfaces
  I've been experimenting so much I think I've confused myself (not hard to do!). I'm using DirectX in windowed mode and I'm trying to display various bitmaps and text to my window. Here's the issues I'm having:1. TextOut() prints to areas outside of my window. Possible surface sizing problem?2. I can't scale a bitmap to a larger size. When I try, BltFast() returns an 'Invalid Rect' error. You'd think that was specific enough, but I've been messing with the sizes of the surfaces and I can't get it to work. It only seems to work when the size of the surface exactly matches the size of the bitmap. Seems like I'm trying to use the same surface for all my images when I should be using one for my background and one for my other images. For those who are keeping score, this is for my blackjack game for which I have already posted a few times :)Here's my graphics code:#ifndef GRAPHICS#define GRAPHICS#include <iomanip>#include <cstdlib> #include <ctime> #include <iostream>#include <windows.h>namespace Graphics{#include <ddraw.h>#include "ddutil.h"#include "nsblackjack.h"#pragma comment (lib, "winmm.lib")#pragma comment (lib, "dxguid.lib")#pragma comment (lib, "ddraw.lib")using namespace nsblackjack ;// directdraw stuffLPDIRECTDRAW7    lpDD= NULL;   // dd objectLPDIRECTDRAWSURFACE7  lpPrimary= NULL;   // dd primary surfaceLPDIRECTDRAWSURFACE7  lpBackBuffer  = NULL;   // dd back surfaceLPDIRECTDRAWPALETTE   lpddpal= NULL;   // a pointer to the created dd paletteLPDIRECTDRAWCLIPPER   lpddclipper= NULL;   // dd clipperPALETTEENTRYpalette[256]; // color palettePALETTEENTRYsave_palette[256]; // used to save palettesDDSURFACEDESC2   ddsd;    // a direct draw surface description structDDBLTFXddbltfx; // used to fillDDSCAPS2    ddscaps; // a direct draw surface capabilities structHRESULTddrval;  // result back from dd callsDWORD  start_clock_count = 0;  // used for timing#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }#define WINDOW_WIDTH 560 #define WINDOW_HEIGHT 450LPDIRECTDRAWSURFACE7 lpDDSBitmap ;// Surface containing our background.LPDIRECTDRAWSURFACE7 lpA;// Surface containing our sprites.LPDIRECTDRAWSURFACE7 lpSprites;// Initialise DirectDraw and go to full screen mode.bool InitDirectDraw(HWND hwnd){  // create the main DirectDraw object  DirectDrawCreateEx( NULL, (VOID**)&lpDD, IID_IDirectDraw7, NULL );  // using DDSCL_NORMAL means we will coexist with GDI    ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );    if( ddrval != DD_OK )    {   lpDD->Release();   return(false);    }    memset( &ddsd, 0, sizeof(ddsd) );    ddsd.dwSize = sizeof( ddsd );    ddsd.dwFlags = DDSD_CAPS;    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;ddsd.dwWidth = WINDOW_WIDTH ; ddsd.dwHeight = WINDOW_HEIGHT;    // The primary surface is not a page flipping surface this time    ddrval = lpDD->CreateSurface( &ddsd, &lpPrimary, NULL );    if( ddrval != DD_OK )    {   lpDD->Release();   return(false);    }    // Create a clipper to ensure that our drawing stays inside our window    ddrval = lpDD->CreateClipper( 0, &lpddclipper, NULL );    if( ddrval != DD_OK )    {   lpPrimary->Release();   lpDD->Release();   return(false);    }    // setting it to our hwnd gives the clipper the coordinates from our window    ddrval = lpddclipper->SetHWnd( 0, hwnd );    if( ddrval != DD_OK )    {   lpddclipper-> Release();   lpPrimary->Release();   lpDD->Release();   return(false);    }    // attach the clipper to the primary surface    ddrval = lpPrimary->SetClipper( lpddclipper );    if( ddrval != DD_OK )    {   lpddclipper-> Release();   lpPrimary->Release();   lpDD->Release();   return(false);    }memset( &ddsd, 0, sizeof(ddsd) );    ddsd.dwSize = sizeof( ddsd );    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;    ddsd.dwWidth = WINDOW_WIDTH ;    ddsd.dwHeight = WINDOW_HEIGHT ;// create the backbuffer separately    ddrval = lpDD->CreateSurface( &ddsd, &lpBackBuffer, NULL );    if( ddrval != DD_OK )    {   lpddclipper-> Release();   lpPrimary->Release();   lpDD->Release();   return(false);    }    return(true);}/* * Creates a DirectDraw palette for a given bitmap on disk. * The parameter szBitmap is the file name of the bitmap. * */IDirectDrawPalette * DDLoadPalette(IDirectDraw7 *pdd, LPCSTR szBitmap){    IDirectDrawPalette* ddpal;    int i;    int n;    int fh;    PALETTEENTRY ape[256];    if (szBitmap && (fh = _lopen(szBitmap, OF_READ)) != -1)    {   BITMAPFILEHEADER bf;   BITMAPINFOHEADER bi;   _lread(fh, &bf, sizeof(bf));   _lread(fh, &bi, sizeof(bi));   _lread(fh, ape, sizeof(ape));   _lclose(fh);   if (bi.biSize != sizeof(BITMAPINFOHEADER))  n = 0;   else if (bi.biBitCount > 8)  n = 0;   else if (bi.biClrUsed == 0)  n = 1 << bi.biBitCount;   else  n = bi.biClrUsed; // // a DIB color table has its colors stored BGR not RGB // so flip them around. //   for(i=0; i<n; i++ )   {  BYTE r = ape.peRed;  ape.peRed = ape.peBlue;  ape.peBlue = r;   }    }    if (pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL) != DD_OK)    {   return NULL;    } else {   return ddpal;    }}/* * Creates a DirectDraw Surface of a specified size * This surface will be in video memory if enough is * available, otherwise it will be created in system memory */IDirectDrawSurface7 * CreateOffScreenSurface(IDirectDraw7 *pdd, int dx, int dy){    DDSURFACEDESC2 ddsd;    IDirectDrawSurface7 *pdds;    //    // create a DirectDrawSurface for this bitmap    //    ZeroMemory(&ddsd, sizeof(ddsd));    ddsd.dwSize = sizeof(ddsd);    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;    ddsd.dwWidth = dx;    ddsd.dwHeight = dy;if (pdd == NULL)return NULL ;    if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)    {   return NULL;    } else {   return pdds;    }}/* * This function copies a previously loaded bitmap into a DirectDraw surface. * Notice that we can obtain a GDI style device context for a * DirectDraw surface, with which to BitBlt the bitmap into the * surface. */HRESULT DDCopyBitmap(IDirectDrawSurface7 *pdds, HBITMAP hbm, int dx, int dy){    HDC hdcImage;    HDC hdc;    HRESULT hr;    HBITMAP hbmOld;    //    // select bitmap into a memoryDC so we can use it.    //    hdcImage = CreateCompatibleDC(NULL);    hbmOld = (HBITMAP)SelectObject(hdcImage, hbm);    if ((hr = pdds->GetDC(&hdc)) == DD_OK)    {   BitBlt(hdc, 0, 0, dx, dy, hdcImage, 0, 0, SRCCOPY);   pdds->ReleaseDC(hdc);    }    SelectObject(hdcImage, hbmOld);    DeleteDC(hdcImage); return hr;}/* * Function to create an offscreen surface and load a bitmap from * disk into it. The szBitmap field is the filename of the Bitmap. */IDirectDrawSurface7 * DDLoadBitmap(IDirectDraw7 *pdd, LPCSTR szBitmap){    HBITMAP hbm;    BITMAP bm;    IDirectDrawSurface7 *pdds;    // LoadImage has some added functionality in Windows 95 that allows    // you to load a bitmap from a file on disk.    hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0,    LR_LOADFROMFILE|LR_CREATEDIBSECTION);    if (hbm == NULL)   return NULL;    GetObject(hbm, sizeof(bm), &bm); // get size of bitmap   /*    * create a DirectDrawSurface for this bitmap    * source to function CreateOffScreenSurface() follows immediately    */    pdds = CreateOffScreenSurface(pdd, bm.bmWidth, bm.bmHeight);    if (pdds) {   DDCopyBitmap(pdds, hbm, bm.bmWidth, bm.bmHeight);    }    DeleteObject(hbm);    return pdds;} //bool Flip(HWND hwnd, int x, int y, int h, int w)bool Flip(HWND hwnd, int x, int y, int w, int h){    HRESULT ddrval;    RECT rcRectSrc;    RECT rcRectDest;    POINT p;// first we need to figure out where on the primary surface our window lives    p.x = x; p.y = y;//p.x = 0; p.y = 0;    ClientToScreen(hwnd, &p);    GetClientRect(hwnd, &rcRectDest);rcRectDest.bottom = h ;rcRectDest.right = w ;    OffsetRect(&rcRectDest, p.x, p.y);SetRect(&rcRectSrc, 0, 0, w, h);//SetRect(&rcRectSrc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);    ddrval = lpPrimary->Blt( &rcRectDest, lpBackBuffer, &rcRectSrc, DDBLT_WAIT, NULL);    return (ddrval == DD_OK);}int Draw_Text_GDI(HWND hwnd, char *text, int x,int y,int color){// this function draws the sent text on the sent surface // using color index as the color in the paletteHDC xdc; // the working dc// get the dc from surfaceif (FAILED(lpPrimary->GetDC(&xdc)))   return(0);// set the colors for the text upSetTextColor(xdc,RGB(palette.peRed,palette.peGreen,palette.peBlue) );<span class="cpp-comment">// set background mode to transparent so black isn't copied</span>SetBkMode(xdc, TRANSPARENT);<span class="cpp-comment">// draw the text a</span>TextOut(xdc,x,y,text,(<span class="cpp-keyword">int</span>)strlen(text));<span class="cpp-comment">// release the dc</span>lpPrimary-&gt;ReleaseDC(xdc);<span class="cpp-comment">//Flip(hwnd, x,y, strlen(text), 8);</span><span class="cpp-comment">// return success</span><span class="cpp-keyword">return</span>(<span class="cpp-number">1</span>);} <span class="cpp-comment">// end Draw_Text_GDI</span> };<span class="cpp-directive">#endif</span></pre></div><!–ENDSCRIPT–>Here's the main function that draws stuff:<!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre> <span class="cpp-keyword">void</span> drawImg(LPCSTR szBitmap, HWND hwnd, <span class="cpp-keyword">int</span> x, <span class="cpp-keyword">int</span> y, <span class="cpp-keyword">int</span> w, <span class="cpp-keyword">int</span> h){<span class="cpp-keyword">if</span> ( (lpDDSBitmap = DDLoadBitmap(lpDD, szBitmap)) == NULL )   <span class="cpp-keyword">return</span> ;lpddpal = DDLoadPalette(lpDD, szBitmap); <span class="cpp-comment">// Call the function above to load the palette</span><span class="cpp-keyword">if</span> (lpddpal)    lpPrimary-&gt;SetPalette(lpddpal); <span class="cpp-comment">// this sets the palette for the primary surface</span>RECT rcFrom;<span class="cpp-comment">//SetRect(&amp;rcFrom, 0, 0, 73, 97);</span>SetRect(&amp;rcFrom, <span class="cpp-number">0</span>, <span class="cpp-number">0</span>, w, h);ddrval = lpBackBuffer-&gt;BltFast( <span class="cpp-number">0</span>, <span class="cpp-number">0</span>, lpDDSBitmap, &amp;rcFrom,  DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);<span class="cpp-keyword">int</span> i;<span class="cpp-keyword">switch</span>(ddrval){<span class="cpp-keyword">case</span> DDERR_EXCEPTION    :{i = <span class="cpp-number">0</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_GENERIC   :{i = <span class="cpp-number">1</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_INVALIDOBJECT   :{i = <span class="cpp-number">2</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_INVALIDPARAMS   :{i = <span class="cpp-number">3</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_INVALIDRECT   :{i = <span class="cpp-number">4</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_NOBLTHW   :{i = <span class="cpp-number">5</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_SURFACEBUSY   :{i = <span class="cpp-number">6</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_SURFACELOST   :{i = <span class="cpp-number">7</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_UNSUPPORTED   :{i = <span class="cpp-number">8</span>;<span class="cpp-keyword">break</span>;}<span class="cpp-keyword">case</span> DDERR_WASSTILLDRAWING :{i = <span class="cpp-number">9</span>;<span class="cpp-keyword">break</span>;}}<span class="cpp-keyword">if</span>( ddrval != DD_OK )<span class="cpp-keyword">return</span> ;   Flip(hwnd, x, y, w, h);}</pre></div><!–ENDSCRIPT–>A typical function call would be…<!–STARTSCRIPT–><!–source lang="cpp"–><div class="source"><pre> drawImg(<span class="cpp-literal">"card09.bmp"</span>, hwnd, player1-&gt;left, player1-&gt;top, bm_width, bm_height);</pre></div><!–ENDSCRIPT–>
  1. Your text drawing function is attempting to output directly to the primary surface. It should be drawing to the back buffer.2. The rectangle you specify with BltFast() is the source rectangle, not the destination rectangle. So it should never be larger than the source surface. If you want to do scaling, you must use Blt() instead of BltFast().