Board index » cppbuilder » Drawing using direct draw

Drawing using direct draw

I am developing a display class using direct draw but my problem is that I can't draw image in my main window. In fact it draws on the screen but not in my window.
I tested it using the TextOut function telling it to print a simple message at position 0,0 of my window but it seems to print it out of my window.
What is the problem and is there anybody there who can help me.

Thank you.

 

Re:Drawing using direct draw


If you will use DirectDraw in windowed mode, you must use the clipper object of DirectX.

Re:Drawing using direct draw


Quote
"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:
> I tested it using the TextOut function telling it to print a simple
> message at position 0,0 of my window but it seems to print
> it out of my window.

Remember that the Primary Surface always covers the entire screen.
Retrieving its DC with GetDC and then drawing to 0,0 will always draw to the
upper left corner of the screen, not of your window. Usually, you create a
Back Buffer that is only as large as the window's client area and draw
there. Then, you will have to calculate the absolute screen coordinates of
your window's client area (ClientToScreen) and blit to that area of the
Primary.
Using a clipper will restrict output to your window but 0,0 will still be
outside of it and will therefore be clipped!

M.F.

Re:Drawing using direct draw


Quote
"Michael F?tsch" <foet...@crosswinds.net> wrote:
>>"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:
>> I tested it using the TextOut function telling it to print a simple
>> message at position 0,0 of my window but it seems to print
>> it out of my window.

>Remember that the Primary Surface always covers the entire screen.
>Retrieving its DC with GetDC and then drawing to 0,0 will always draw to the
>upper left corner of the screen, not of your window. Usually, you create a
>Back Buffer that is only as large as the window's client area and draw
>there. Then, you will have to calculate the absolute screen coordinates of
>your window's client area (ClientToScreen) and blit to that area of the
>Primary.
>Using a clipper will restrict output to your window but 0,0 will still be
>outside of it and will therefore be clipped!

>M.F.

this what my test text-writing routine looks like :

        HDC hdc;
        BackBuf->GetDC(&hdc);
        SetBkColor(hdc,RGB(0,0,0));
        SetTextColor(hdc,RGB(0,0,255));
        char buf[]="A sample string";

        TextOut(hdc,0,0,buf,strlen(buf));

      BackBuf->Blt(&rcDest,
                        lpDDS,
                        0,
                        DDBLT_WAIT ,
                        NULL)

        BackBuf->ReleaseDC(hdc)  ;

As you can see I 'm already using a backbuffer but now nothing is printed. What is wrong with it ?
I got one clipper, a primary surface and a backbuffer. So what is the problem ? Perhaps a made a bad "Blt" (inversed) ?

Thank you for answering.

Re:Drawing using direct draw


The backbuffer is really a backbuffer surface or it is a offscreen surfarce ( in DirectX terminology ). Because in windowed
you can't use a backbuffer surface.

PS: sorry for my bad english.

Quote
Xavier MAILLARD wrote:
> "Michael F?tsch" <foet...@crosswinds.net> wrote:
> >>"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:
> >> I tested it using the TextOut function telling it to print a simple
> >> message at position 0,0 of my window but it seems to print
> >> it out of my window.

> >Remember that the Primary Surface always covers the entire screen.
> >Retrieving its DC with GetDC and then drawing to 0,0 will always draw to the
> >upper left corner of the screen, not of your window. Usually, you create a
> >Back Buffer that is only as large as the window's client area and draw
> >there. Then, you will have to calculate the absolute screen coordinates of
> >your window's client area (ClientToScreen) and blit to that area of the
> >Primary.
> >Using a clipper will restrict output to your window but 0,0 will still be
> >outside of it and will therefore be clipped!

> >M.F.

> this what my test text-writing routine looks like :

>         HDC hdc;
>         BackBuf->GetDC(&hdc);
>         SetBkColor(hdc,RGB(0,0,0));
>         SetTextColor(hdc,RGB(0,0,255));
>         char buf[]="A sample string";

>         TextOut(hdc,0,0,buf,strlen(buf));

>       BackBuf->Blt(&rcDest,
>                         lpDDS,
>                         0,
>                         DDBLT_WAIT ,
>                         NULL)

>         BackBuf->ReleaseDC(hdc)  ;

> As you can see I 'm already using a backbuffer but now nothing is printed. What is wrong with it ?
> I got one clipper, a primary surface and a backbuffer. So what is the problem ? Perhaps a made a bad "Blt" (inversed) ?

> Thank you for answering.

Re:Drawing using direct draw


Quote
{*word*269}ie Mock <v...@nettech-eur.com> wrote:
>The backbuffer is really a backbuffer surface or it is a offscreen surfarce ( in DirectX terminology ). Because in windowed>you can't use a backbuffer surface.

>PS: sorry for my bad english.

>Xavier MAILLARD wrote:

>> "Michael F?tsch" <foet...@crosswinds.net> wrote:
>> >>"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:
>> >> I tested it using the TextOut function telling it to print a simple
>> >> message at position 0,0 of my window but it seems to print
>> >> it out of my window.

>> >Remember that the Primary Surface always covers the entire screen.
>> >Retrieving its DC with GetDC and then drawing to 0,0 will always draw to the
>> >upper left corner of the screen, not of your window. Usually, you create a
>> >Back Buffer that is only as large as the window's client area and draw
>> >there. Then, you will have to calculate the absolute screen coordinates of
>> >your window's client area (ClientToScreen) and blit to that area of the
>> >Primary.
>> >Using a clipper will restrict output to your window but 0,0 will still be
>> >outside of it and will therefore be clipped!

>> >M.F.

>> this what my test text-writing routine looks like :

>>         HDC hdc;
>>         BackBuf->GetDC(&hdc);
>>         SetBkColor(hdc,RGB(0,0,0));
>>         SetTextColor(hdc,RGB(0,0,255));
>>         char buf[]="A sample string";

>>         TextOut(hdc,0,0,buf,strlen(buf));

>>       BackBuf->Blt(&rcDest,
>>                         lpDDS,
>>                         0,
>>                         DDBLT_WAIT ,
>>                         NULL)

>>         BackBuf->ReleaseDC(hdc)  ;

>> As you can see I 'm already using a backbuffer but now nothing is printed. What is wrong with it ?
>> I got one clipper, a primary surface and a backbuffer. So what is the problem ? Perhaps a made a bad "Blt" (inversed) ?

>> Thank you for answering.

It is an offscreen surface declared with the flags (see below):
SurfaceDesc.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
    SurfaceDesc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
    SurfaceDesc.dwHeight=H;
    SurfaceDesc.dwWidth=W;

Is that can help you to help solve my problem ?
PS:Sorry for my english too !!!!! :-)

Re:Drawing using direct draw


Quote
Xavier MAILLARD wrote:
> >> this what my test text-writing routine looks like :

> >>         HDC hdc;
> >>         BackBuf->GetDC(&hdc);
> >>         SetBkColor(hdc,RGB(0,0,0));
> >>         SetTextColor(hdc,RGB(0,0,255));
> >>         char buf[]="A sample string";

> >>         TextOut(hdc,0,0,buf,strlen(buf));

> >>       BackBuf->Blt(&rcDest,
> >>                         lpDDS,
> >>                         0,
> >>                         DDBLT_WAIT ,
> >>                         NULL)

> >>         BackBuf->ReleaseDC(hdc)  ;

> >> As you can see I 'm already using a backbuffer but now nothing is printed. What is wrong with it ?
> >> I got one clipper, a primary surface and a backbuffer. So what is the problem ? Perhaps a made a bad "Blt" (inversed) ?

> >> Thank you for answering.

> It is an offscreen surface declared with the flags (see below):
> SurfaceDesc.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
>     SurfaceDesc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
>     SurfaceDesc.dwHeight=H;
>     SurfaceDesc.dwWidth=W;

> Is that can help you to help solve my problem ?
> PS:Sorry for my english too !!!!! :-)

You believe i found the problem! Try to Release the DC before blt the surface.

PS: on pourrai peut etre passer en mail perso et en Francais ( ca serai plus facile non ? ). Pour directX je peut un plus t'aider que pour ma precedente reponse,
car j'ai un peu programmer DirectX.

Re:Drawing using direct draw


Quote
"Michael F?tsch" <foet...@crosswinds.net> wrote:
>>"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:
>> I tested it using the TextOut function telling it to print a simple
>> message at position 0,0 of my window but it seems to print
>> it out of my window.

>Remember that the Primary Surface always covers the entire screen.
>Retrieving its DC with GetDC and then drawing to 0,0 will always draw to the
>upper left corner of the screen, not of your window. Usually, you create a
>Back Buffer that is only as large as the window's client area and draw
>there. Then, you will have to calculate the absolute screen coordinates of
>your window's client area (ClientToScreen) and blit to that area of the
>Primary.
>Using a clipper will restrict output to your window but 0,0 will still be
>outside of it and will therefore be clipped!

>M.F.

I understood what you have told but the problem is that it doesn't work. Any source code to show me ?

Re:Drawing using direct draw


Quote
"{*word*269}ie Mock" <v...@nettech-eur.com> wrote:
> Try to Release the DC before blt the surface.

Exactly!

"Xavier MAILLRD" <maill...@leri.univ-reims.fr> schrieb im Newsbeitrag
news:3909830b@dnews...

Quote
> I understood what you have told but the problem is
> that it doesn't work. Any source code to show me ?

Xavier!

I don't know what W and H are in your offscreen surface creation. However,
they should be:
RECT clientrect;
GetClientRect(YourHWnd, &clientrect);
W = clientrect.right;
H = clientrect.bottom;

When drawing text to 0,0 it'll appear in the upper left corner of your
window. As expected.

But remember to not blit to 0,0 on the Primary Surface!
RECT screenrect;
CopyMemory(&screenrect, &clientrect, sizeof(RECT));
// Convert left and top:
ClientToScreen(YourHWnd, (LPPOINT)&screenrect.left);
// Convert right and bottom:
ClientToScreen(YourHWnd, (LPPOINT)&screenrect.right);
// screenrect now contains the dest rect to blit to on the Primary

Now you'd blit like this:
PrimarySurface->Blt(&screenrect, BackBuf, NULL,
    0, NULL);

(Call PrimarySurface->Blt, not BackBuf->Blt!)

Regards,
M.F.

Re:Drawing using direct draw


Quote
"Michael F?tsch" <foet...@crosswinds.net> wrote:
>>"{*word*269}ie Mock" <v...@nettech-eur.com> wrote:
>> Try to Release the DC before blt the surface.

>Exactly!

>"Xavier MAILLRD" <maill...@leri.univ-reims.fr> schrieb im Newsbeitrag
>news:3909830b@dnews...
>> I understood what you have told but the problem is
>> that it doesn't work. Any source code to show me ?

>Xavier!

>I don't know what W and H are in your offscreen surface creation. However,
>they should be:
>RECT clientrect;
>GetClientRect(YourHWnd, &clientrect);
>W = clientrect.right;
>H = clientrect.bottom;

>When drawing text to 0,0 it'll appear in the upper left corner of your
>window. As expected.

>But remember to not blit to 0,0 on the Primary Surface!
>RECT screenrect;
>CopyMemory(&screenrect, &clientrect, sizeof(RECT));
>// Convert left and top:
>ClientToScreen(YourHWnd, (LPPOINT)&screenrect.left);
>// Convert right and bottom:
>ClientToScreen(YourHWnd, (LPPOINT)&screenrect.right);
>// screenrect now contains the dest rect to blit to on the Primary

>Now you'd blit like this:
>PrimarySurface->Blt(&screenrect, BackBuf, NULL,
>    0, NULL);

>(Call PrimarySurface->Blt, not BackBuf->Blt!)

>Regards,
>M.F.

Here is my text drawing routine, is there any errors in my code ?
RECT rcRectSrc;
        RECT rcRectDest;
        POINT p;

        HDC hdc;

        //what's wrong with this ????? ////////////
        BackBuf->GetDC(&hdc);

        // first we need to figure out where on the primary surface our window lives
        GetClientRect(HandleParent, &rcRectDest);
        p.x = rcRectDest.left; p.y = rcRectDest.top;
        ClientToScreen(HandleParent, &p);

        OffsetRect(&rcRectDest, p.x, p.y);
        SetRect(&rcRectSrc, 0, 0, H, W);

        SetBkColor(hdc,RGB(0,0,0));
        SetTextColor(hdc,RGB(0,0,255));
        ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.left);
        ClientToScreen(HandleParent,(LPPOINT) & rcRectDest.bottom);

         lpDDS->Blt( &rcRectDest, BackBuf, &rcRectSrc, 0, NULL);

        BackBuf->ReleaseDC(hdc)  ;

Re:Drawing using direct draw


Quote
Xavier MAILLARD wrote:
> Here is my text drawing routine, is there any errors in my code ?
> RECT rcRectSrc;
>         RECT rcRectDest;
>         POINT p;

>         HDC hdc;

>         //what's wrong with this ????? ////////////
>         BackBuf->GetDC(&hdc);

>         // first we need to figure out where on the primary surface our window lives
>         GetClientRect(HandleParent, &rcRectDest);
>         p.x = rcRectDest.left; p.y = rcRectDest.top;
>         ClientToScreen(HandleParent, &p);

>         OffsetRect(&rcRectDest, p.x, p.y);
>         SetRect(&rcRectSrc, 0, 0, H, W);

>         SetBkColor(hdc,RGB(0,0,0));
>         SetTextColor(hdc,RGB(0,0,255));
>         ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.left);
>         ClientToScreen(HandleParent,(LPPOINT) & rcRectDest.bottom);

>          lpDDS->Blt( &rcRectDest, BackBuf, &rcRectSrc, 0, NULL);

>         BackBuf->ReleaseDC(hdc)  ;

No Textout, a Paste-and-Copy error? :))

Re:Drawing using direct draw


It missed a few lines in my previous message, so this exactly what i do :
////////// pb il y a un endroit ou ca plante la dedans !!!!!!!!!
HRESULT display::initDisplay(DWORD & H, DWORD & W)
{
    HRESULT             hr;
    DDSURFACEDESC2      SurfaceDesc;
    DDPIXELFORMAT       Depth;

    // On initialise la description de surface
    ZeroMemory(&SurfaceDesc, sizeof(DDSURFACEDESC2));
    SurfaceDesc.dwSize = sizeof(DDSURFACEDESC2);
    SurfaceDesc.dwFlags =  DDSD_CAPS;
    SurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // |

    hr=DirectDrawCreateEx(NULL,(void **)& lpDD7,IID_IDirectDraw7,NULL);
    if(hr!=DD_OK)
        return hr;

        hr=lpDD7->SetCooperativeLevel(HandleParent,DDSCL_NORMAL);
    if(hr!=DD_OK)
        return hr;

    // Cration de la surface
    if(FAILED(hr = lpDD7->CreateSurface(&SurfaceDesc, &lpDDS, NULL)))
        return hr;

    // Cration de notre clipper
    if(FAILED(hr = lpDD7->CreateClipper(0,&lpDDClip,NULL)))
        return hr;

    lpDDClip->SetHWnd(0, HandleParent);
    lpDDS->SetClipper(lpDDClip);

    lpDDClip->Release();

    /** In doubt we reset the Surface Description */
    //ZeroMemory(&SurfaceDesc, sizeof(DDSURFACEDESC2));
    SurfaceDesc.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
    SurfaceDesc.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
    SurfaceDesc.dwHeight=H;
    SurfaceDesc.dwWidth=W;

    if(FAILED(hr=lpDD7->CreateSurface(&SurfaceDesc,&BackBuf,NULL)))
        return hr;

    return hr=DD_OK;

Quote
}

// fonction qui dessine dans une partie de l'cran
void display::drawDIB(DWORD  H, DWORD  W)
{
        RECT rcRectSrc;
        RECT rcRectDest;
        POINT p;

        HDC hdc;

        //what's wrong with this ????? ////////////
        BackBuf->GetDC(&hdc);

        // first we need to figure out where on the primary surface our window lives
        GetClientRect(HandleParent, &rcRectDest);
        p.x = rcRectDest.left; p.y = rcRectDest.top;
        ClientToScreen(HandleParent, &p);

        OffsetRect(&rcRectDest, p.x, p.y);
        SetRect(&rcRectSrc, 0, 0, H, W);

        SetBkColor(hdc,RGB(0,0,0));
        SetTextColor(hdc,RGB(0,0,255));
        char str[]="A sample sentence";
        TextOut(HandleParent,0,0,str,strlen(str));
        ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.left);
        ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.bottom);

         lpDDS->Blt( &rcRectDest, BackBuf, &rcRectSrc, 0, NULL);

        BackBuf->ReleaseDC(hdc)  ;

        /////////////////////////////////////

Quote
}

Re:Drawing using direct draw


Quote
"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:
>         TextOut(HandleParent,0,0,str,strlen(str));

TextOut expects an HDC as its first parameter!
    TextOut(hdc, 0, 0, str, strlen(str));

Quote
>         ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.left);
>         ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.bottom);

You have already done that:

Quote
>         OffsetRect(&rcRectDest, p.x, p.y);

Don't do it twice!

lpDDS->Blt might have returned an error. (Well, in this case the clipper
catches the far-off dest rect...) Try introducing some basic error checking.
Like "if (FAILED(lpDDS->Blt))" and use OutputDebugString (or MessageBox) to
display the HRESULTs.
See http://www.crosswinds.net/~foetsch (yes, that's my own!) if you are in
need of a GetDXErrStr function and a return value viewer utility.

Regards,
M.F.

Re:Drawing using direct draw


Quote
"Michael F?tsch" <foet...@crosswinds.net> wrote:
>"Xavier MAILLARD" <maill...@leri.univ-reims.fr> wrote:>>         TextOut(HandleParent,0,0,str,strlen(str));

>TextOut expects an HDC as its first parameter!
>    TextOut(hdc, 0, 0, str, strlen(str));

>>         ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.left);
>>         ClientToScreen(HandleParent,(LPPOINT)&rcRectDest.bottom);

>You have already done that:

>>         OffsetRect(&rcRectDest, p.x, p.y);

>Don't do it twice!

>lpDDS->Blt might have returned an error. (Well, in this case the clipper
>catches the far-off dest rect...) Try introducing some basic error checking.
>Like "if (FAILED(lpDDS->Blt))" and use OutputDebugString (or MessageBox) to
>display the HRESULTs.
>See http://www.crosswinds.net/~foetsch (yes, that's my own!) if you are in
>need of a GetDXErrStr function and a return value viewer utility.

>Regards,
>M.F.

As you told i made a few corrections to my routine but it still doesn't want to work. So this the new style of my code.
I made a error processing routine to show me the state of a HRESULT variable after a process and when i test it,
it always returns DD_OK which is if i'm right the good state.
So i don't know what to do now.

// i called it drawDIB but for the moment i just want to display a sample sentence in my window
void display::drawDIB(DWORD  H, DWORD  W)
{
        RECT rcRectSrc;
        RECT rcRectDest;
        POINT p;
        HDC hdc;
        BackBuf->GetDC(&hdc);

        // first we need to figure out where on the primary surface our window lives
        GetClientRect(HandleParent, &rcRectDest);
        p.x = 0; p.y = 0;
        ClientToScreen(HandleParent, &p);

        OffsetRect(&rcRectDest, p.x, p.y);
        SetRect(&rcRectSrc, 0, 0, H, W);

        SetBkColor(hdc,RGB(0,0,0));
        SetTextColor(hdc,RGB(0,0,255));
        char str[]="A sample sentence";
        TextOut(hdc,100,100,str,strlen(str));

        //verrou severe de DDraw ==>on release avant le blitting
        BackBuf->ReleaseDC(hdc);
         HRESULT hr=lpDDS->Blt( &rcRectDest, BackBuf, &rcRectSrc, 0, NULL);

        //my error processing routine
        displayErreurMsg(hr);
       // return value is DD_OK everywhere i test it.So what is the problem

Quote
}

I have another question : do i need to do some specific things in the IDE such as process on some events, or anything else like ??
Anybody know ???

Thank you for answering to me.

A++

Re:Drawing using direct draw


I Find Locking the Surface and writing the Data like you used to do in the
DOS day,s works a lot faster than the DC method!
Go to page: [1] [2]

Other Threads