Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

COM programming and DirectX 2

Status
Not open for further replies.

chpicker

Programmer
Apr 10, 2001
1,316
I'm fairly new to programming in C/C++, but I think I've got a pretty good handle on the language itself. However, I am still very confused over how to access COM objects. Specifically, I downloaded the DirectX 8.0a SDK, but cannot figure out how to use it.

How difficult would it be to create a program that simply creates a DirectDraw window and displays a .BMP file in it? Could someone post an example of this? Perhaps I can learn from that and figure out the rest...at this point, I don't even know where to start.
 
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ddraw.h>

#define WIN_NAME &quot;DDBitmapDisplay&quot;
#define WIN_X 200
#define WIN_Y 200
#define WINPOS_X 0
#define WINPOS_Y 0
#define SIZE_X 800
#define SIZE_Y 600
#define BPP 24
#define NAME_OF_BITMAP &quot;castle.bmp&quot;


HWND hMainWin = NULL;
HINSTANCE hInstance = NULL;
LPDIRECTDRAW lpDDObject = NULL;
LPDIRECTDRAWSURFACE lpPrimary = NULL;
LPDIRECTDRAWSURFACE lpBackBuffer = NULL;

bool Init_DirectDraw( HWND hWin );
bool Load_Bitmap( LPDIRECTDRAWSURFACE lpSurface,
char *NameOfBitmap );
void Clean_Up();
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam );



int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow) {


HWND hwnd;
MSG msg;
WNDCLASSEX winclass;


winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL,
IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL,
IDC_ARROW);
winclass.hbrBackground = (HBRUSH)
GetStockObject(WHITE_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = &quot;WIN_SHELL&quot;;
winclass.hIconSm = NULL;


if(!RegisterClassEx( &winclass ))
return FALSE;

if(!(hwnd = CreateWindow(&quot;WIN_SHELL&quot;,
WIN_NAME, WS_VISIBLE |
WS_POPUP,
WINPOS_X,WINPOS_Y,
WIN_X,WIN_Y,
NULL,
NULL,
hinstance,
NULL)))
return FALSE;


hMainWin = hwnd;
ShowCursor( FALSE );

if(!Init_DirectDraw( hMainWin ))
Clean_Up();

if(!Load_Bitmap( lpBackBuffer,NAME_OF_BITMAP ))
Clean_Up();


while ( true )
{


if( PeekMessage(&msg,NULL,0,0,PM_REMOVE ) )
{


if( msg.message == WM_QUIT )
break;

TranslateMessage( &msg ); DispatchMessage ( &msg );

}




}



return(msg.wParam);

}






LRESULT CALLBACK WindowProc( HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam ) {

PAINTSTRUCT ps;
HDC hdc;



switch ( msg )
{


case WM_CREATE:

return 0;

case WM_PAINT:

hdc = BeginPaint( hwnd,&ps);

EndPaint( hwnd,&ps );

return 0;

case WM_DESTROY:

Clean_Up();

return 0;

case WM_KEYDOWN:

if ( ((int)wparam) == VK_RETURN )
Clean_Up();
else
lpPrimary->Flip( NULL,DDFLIP_WAIT );

return 0;


default:break;


}


return ( DefWindowProc( hwnd, msg, wparam, lparam ) );

}


bool Init_DirectDraw( HWND hWin ) {


DDSURFACEDESC ddsd;
ZeroMemory( &ddsd,sizeof(ddsd) );

if ( DirectDrawCreate( NULL,&lpDDObject,NULL ) != DD_OK )
{
MessageBox( hWin,&quot;DDObject ERROR&quot;,&quot;ERROR&quot;,MB_OK );
return false;
}

if ( lpDDObject->SetCooperativeLevel(
hWin,DDSCL_EXCLUSIVE |
DDSCL_FULLSCREEN |
DDSCL_ALLOWREBOOT ) != DD_OK)
{

MessageBox( hWin,&quot;Error Coop. level.&quot;,&quot;ERROR&quot;,MB_OK );
return false;
}

if ( lpDDObject->SetDisplayMode( SIZE_X,SIZE_Y,BPP ) !=
DD_OK )
{

MessageBox( hWin,&quot;Error display mode.&quot;,&quot;ERROR&quot;,MB_OK );
return false;

}

ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;

if( lpDDObject->CreateSurface( &ddsd,&lpPrimary,NULL )!=
DD_OK )
{

MessageBox( hWin,&quot;Error P. surface.&quot;,&quot;ERROR&quot;,MB_OK );
return false;

}

DDSCAPS ddscaps;
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

if ( lpPrimary->GetAttachedSurface(
&ddscaps,&lpBackBuffer ) != DD_OK )
{

MessageBox( hWin,&quot;Error backbuffer.&quot;,&quot;ERROR&quot;,MB_OK );
return false;

}

return true;

}


void Clean_Up() {


if ( lpDDObject )
{

if ( lpBackBuffer )
{

lpBackBuffer->Release();
lpBackBuffer = NULL;

}


if ( lpPrimary )
{

lpPrimary->Release();
lpPrimary = NULL;

}

lpDDObject->Release();
lpDDObject = NULL;

}


PostQuitMessage( 0 );

}


bool Load_Bitmap( LPDIRECTDRAWSURFACE surface,
char *nameOfBitmap ) {


HBITMAP hBitmap = NULL;
HDC hdcSurface = NULL;
HDC hdcMain = NULL;
HRESULT result = NULL;
DDSURFACEDESC ddsd;


hBitmap = (HBITMAP)LoadImage(
NULL,nameOfBitmap,IMAGE_BITMAP,0,0,LR_LOADFROMFILE );

if(hBitmap == NULL) {

MessageBox( hMainWin,&quot;Error bitmap.&quot;,&quot;ERROR&quot;,MB_OK );
return false;

}


ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
surface->GetSurfaceDesc(&ddsd);

result = surface->GetDC(&hdcSurface);
hdcMain = CreateCompatibleDC(NULL);
SelectObject(hdcMain,hBitmap);



if(!BitBlt(hdcSurface,0,0,
ddsd.dwWidth,ddsd.dwHeight,
hdcMain,0,0,SRCCOPY)) {

MessageBox( hMainWin,&quot;ERROR BLT bitmap.&quot;,&quot;ERROR&quot;,MB_OK );
return false;

}


surface->ReleaseDC(hdcSurface);
DeleteDC(hdcMain);
DeleteObject(hBitmap);

return true;

}











Mike L.G.
mlg400@blazemail.com
 
The code above lost most of it's formatting during the copy and paste, so I hope it's still easy to read. This is just a simple quick example I wrote. Of course there is always a more elegant way of doing things, but I tried to keep it short and dirty for simplicities sake. You may want to look into your DD documentation for a more in depth look at some of the function and method calls made in the code.
The above source makes a couple DirectDraw calls to init. a DirectDrawObject. From this COM object I request full access to the video hardware and I change the screen resolution to 800x600:24 BPP. From this DirectDrawObject I derive 2 surfaces in video memory. Each surface will be big enough to hold 1 800x600 bitmap. One surface will be the current display surface, and one will be the backbuffer. I then attach the backbuffer to the display surface. This will allow me to execute flippable animation like effects. I then load a bitmap onto the backbuffer via the win32 api call BitBlt(...);. You can then press any key (execept the Enter key) to flip the backbuffer image onto the primary surface. This will display the image on screen. To exit the program just hit Enter.

NOTE: To compile the above source you must create a win32 app. Then just copy and paste the source. You must also link in the ddraw.lib ->

Project->Settings->Link->Then type in ddraw.lib in the Object/library modules text box.

ALSO:The above program will require a bitmap (800x600:24 BPP) to be in the current directory. You can just whip up a fast one with MS paint.

Mike L.G.
mlg400@blazemail.com
 
PS: Modify #define NAME_OF_BITMAP to coincide with your bitmaps name. Mike L.G.
mlg400@blazemail.com
 
Ugh...

I did a direct copy/paste into Visual C++ 6.0, added ddraw.lib to the spot you indicated, and tried to build it. The compiler came up with 17 errors, 2 warnings. I was thoroughly confused until I realized that I had named the file .c instead of .cpp, and apparently VC++ disables the C++ extensions when the filename is just .c *sighs*

Anyway, the program works perfectly now...thanks, Mike! I'll dive into it and see if I can figure out how it works, now. :eek:)

Oh yeah...I tried to mark your post as helpful, got the Yes/No confirmation box, but then got an Error box when I clicked Yes. :eek:/
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top