www.pudn.com > 3DÓÎÏ·Source.rar > demo10_4.cpp


// DEMO10_4.CPP DirectMusic Example 
 
// INCLUDES /////////////////////////////////////////////// 
 
#define INITGUID 
#define WIN32_LEAN_AND_MEAN  // just say no to MFC 
 
#include    // include important windows stuff 
#include   
#include  
#include  // include important C/C++ stuff 
#include  
#include  
#include  
#include  
#include  
#include  
#include   
#include  
#include  
#include  
#include  
#include  
 
#include  
#include  // include dsound, dmusic 
#include  
#include  
#include  
#include  
 
// directx 7.0 compatibility 
 
#ifndef DSBCAPS_CTRLDEFAULT 
#define DSBCAPS_CTRLDEFAULT (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME ) 
#endif 
 
 
// DEFINES //////////////////////////////////////////////// 
 
// defines for windows  
#define WINDOW_CLASS_NAME "WINCLASS1" 
 
// default screen size 
#define SCREEN_WIDTH    640  // size of screen 
#define SCREEN_HEIGHT   480 
#define SCREEN_BPP      8    // bits per pixel 
#define MAX_COLORS      256  // maximum colors 
 
// TYPES ////////////////////////////////////////////////////// 
 
// basic unsigned types 
typedef unsigned short USHORT; 
typedef unsigned short WORD; 
typedef unsigned char  UCHAR; 
typedef unsigned char  BYTE; 
 
// MACROS ///////////////////////////////////////////////// 
 
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) 
 
// Convert from multibyte format to Unicode using the following macro: 
#define MULTI_TO_WIDE( x,y )  MultiByteToWideChar( CP_ACP,MB_PRECOMPOSED, y,-1,x,_MAX_PATH); 
 
 
// initializes a direct draw struct 
#define DD_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); } 
 
// GLOBALS //////////////////////////////////////////////// 
HWND      main_window_handle = NULL; // globally track main window 
HINSTANCE main_instance      = NULL; // globally track hinstance 
 
// direct music globals 
IDirectMusicPerformance    *dm_perf = NULL; 
IDirectMusicLoader         *dm_loader = NULL; 
IDirectMusicSegment        *dm_segment = NULL; 
IDirectMusicSegmentState   *dm_segstate = NULL; 
 
// these are overwritten globally by DD_Init() 
int screen_width  = SCREEN_WIDTH,            // width of screen 
    screen_height = SCREEN_HEIGHT,           // height of screen 
    screen_bpp    = SCREEN_BPP;              // bits per pixel 
 
char buffer[80];                     // general printing buffer 
 
// FUNCTIONS ////////////////////////////////////////////// 
 
LRESULT CALLBACK WindowProc(HWND hwnd,  
						    UINT msg,  
                            WPARAM wparam,  
                            LPARAM lparam) 
{ 
// this is the main message handler of the system 
PAINTSTRUCT		ps;		// used in WM_PAINT 
HDC				hdc;	// handle to a device context 
char buffer[80];        // used to print strings 
 
// what is the message  
switch(msg) 
	{	 
	case WM_CREATE:  
        { 
		// do initialization stuff here 
        // return success 
		return(0); 
		} break; 
    
	case WM_PAINT:  
		{ 
		// simply validate the window  
   	    hdc = BeginPaint(hwnd,&ps);	  
         
        // end painting 
        EndPaint(hwnd,&ps); 
 
        // return success 
		return(0); 
   		} break; 
 
	case WM_DESTROY:  
		{ 
 
		// kill the application, this sends a WM_QUIT message  
		PostQuitMessage(0); 
 
        // return success 
		return(0); 
		} break; 
 
	default:break; 
 
    } // end switch 
 
// process any messages that we didn't take care of  
return (DefWindowProc(hwnd, msg, wparam, lparam)); 
 
} // end WinProc 
 
/////////////////////////////////////////////////////////// 
 
int Game_Main(void *parms = NULL, int num_parms = 0) 
{ 
// this is the main loop of the game, do all your processing 
// here 
 
// for now test if user is hitting ESC and send WM_CLOSE 
if (KEYDOWN(VK_ESCAPE)) 
   SendMessage(main_window_handle,WM_CLOSE,0,0); 
 
// return success or failure or your own return code here 
return(1); 
 
} // end Game_Main 
 
//////////////////////////////////////////////////////////// 
 
IDirectMusicPerformance* CreatePerformance(void) 
{ 
// this function creates the performance 
 
IDirectMusicPerformance* pPerf;      
 
if (FAILED(CoCreateInstance(CLSID_DirectMusicPerformance, 
                            NULL, 
                            CLSCTX_INPROC, 
                            IID_IDirectMusicPerformance, 
                            (void**)&pPerf)))     
   { 
   // return null         
   pPerf = NULL;     
   } // end if 
 
   return pPerf; 
 
} // end CreatePerformance 
 
//////////////////////////////////////////////////////////// 
 
IDirectMusicLoader* CreateLoader(void) 
{ 
// this function creates the loader 
 
    IDirectMusicLoader* pLoader; 
  
    if (FAILED(CoCreateInstance( 
            CLSID_DirectMusicLoader, 
            NULL, 
            CLSCTX_INPROC,  
            IID_IDirectMusicLoader, 
            (void**)&pLoader))) 
    { 
    pLoader = NULL; 
    } // end if 
 
    return pLoader; 
 
} // end CreateLoader 
 
/////////////////////////////////////////////////////////// 
 
IDirectMusicSegment* LoadMIDISegment(IDirectMusicLoader* pLoader,  
                                     WCHAR *wszMidiFileName ) 
{ 
// this function loads a midi segment off disk 
 
DMUS_OBJECTDESC ObjDesc;  
HRESULT hr; 
IDirectMusicSegment* pSegment = NULL; 
  
// get current working directory 
char szDir[_MAX_PATH]; 
WCHAR wszDir[_MAX_PATH]; 
  
if(_getcwd( szDir, _MAX_PATH ) == NULL) 
  { 
  return NULL; 
  } // end if 
 
// convert to wide characters 
MULTI_TO_WIDE(wszDir, szDir); 
 
// set the search directory 
hr = pLoader->SetSearchDirectory(GUID_DirectMusicAllTypes,wszDir, FALSE); 
 
if (FAILED(hr))  
   { 
   return NULL; 
   } // end if 
  
// setup object description 
ZeroMemory(&ObjDesc, sizeof(DMUS_OBJECTDESC)); 
ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC); 
ObjDesc.guidClass = CLSID_DirectMusicSegment; 
wcscpy(ObjDesc.wszFileName, wszMidiFileName ); 
 
ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME; 
  
// load the object and query it for the IDirectMusicSegment interface 
// This is done in a single call to IDirectMusicLoader::GetObject 
// note that loading the object also initializes the tracks and does  
// everything else necessary to get the MIDI data ready for playback. 
 
hr = pLoader->GetObject(&ObjDesc,IID_IDirectMusicSegment, (void**) &pSegment); 
 
if (FAILED(hr)) 
   return(0); 
  
// ensure that the segment plays as a standard MIDI file 
// you now need to set a parameter on the band track 
// Use the IDirectMusicSegment::SetParam method and let  
// DirectMusic find the trackby passing -1 (or 0xFFFFFFFF) in the dwGroupBits method parameter. 
 
hr = pSegment->SetParam(GUID_StandardMIDIFile,-1, 0, 0, (void*)dm_perf); 
 
if (FAILED(hr)) 
   return(0); 
   
// This step is necessary because DirectMusic handles program changes and  
// bank selects differently for standard MIDI files than it does for MIDI  
// content authored specifically for DirectMusic.  
// The GUID_StandardMIDIFile parameter must be set before the instruments are downloaded.  
 
// The next step is to download the instruments.  
// This is necessary even for playing a simple MIDI file  
// because the default software synthesizer needs the DLS data  
// for the General MIDI instrument set 
// If you skip this step, the MIDI file will play silently. 
// Again, you call SetParam on the segment, this time specifying the GUID_Download parameter: 
 
hr = pSegment->SetParam(GUID_Download, -1, 0, 0, (void*)dm_perf); 
 
if (FAILED(hr)) 
   return(0); 
 
// return the pointer 
return pSegment; 
  
} // end LoadSegment 
 
//////////////////////////////////////////////////////////// 
 
int Game_Init(void *parms = NULL, int num_parms = 0) 
{ 
// this is called once after the initial window is created and 
// before the main event loop is entered, do all your initialization 
// here 
 
// set up directmusic 
if (FAILED(CoInitialize(NULL))) 
   {     
   // Terminate the application. 
   return(0); 
   }   // end if 
 
 
// create the performance 
dm_perf = CreatePerformance(); 
 
if (dm_perf == NULL) 
   { 
   return(0);// Failure -- performance not created 
   } // end if 
 
 
// initialize the performance 
if (FAILED(dm_perf->Init(NULL, NULL, main_window_handle))) 
   { 
   return(0);// Failure -- performance not initialized 
   } // end if  
 
// add the port to the performance 
if (FAILED(dm_perf->AddPort(NULL))) 
   {     
   return(0);// Failure -- port not initialized 
   } // end if 
 
// create the loader to load object(s) such as midi file 
dm_loader = CreateLoader(); 
 
if (dm_loader == NULL) 
   { 
    return(0);// Failure -- loader not created 
   } // end if 
 
// release the old segment 
if (dm_segment) 
   {     
   dm_segment->Release();     
   dm_segment = NULL; 
   } // end if 
 
// load the segment 
if (dm_loader) 
   { 
   dm_segment = LoadMIDISegment(dm_loader,L"BATTLE.MID"); 
   } // end if 
 
// start the song 
if (dm_segment) 
   { 
   dm_perf->PlaySegment(dm_segment, 0, 0, &dm_segstate); 
   }  // end if 
 
// return success or failure or your own return code here 
return(1); 
 
} // end Game_Init 
 
///////////////////////////////////////////////////////////// 
 
HRESULT FreeDirectMusic(void) 
{ 
// If there is any music playing, stop it. This is  
// not really necessary, because the music will stop when 
// the instruments are unloaded or the performance is    // closed down. 
dm_perf->Stop( NULL, NULL, 0, 0 );  
 
// Unload instruments this will cause silence. 
// CloseDown unloads all instruments, so this call is also not  
// strictly necessary. 
dm_segment->SetParam(GUID_Unload, -1, 0, 0, (void*)dm_perf);  
 
// Release the segment.     
dm_segment->Release();  
// CloseDown and Release the performance object.     
dm_perf->CloseDown(); 
dm_perf->Release();      
 
// Release the loader object. 
dm_loader->Release();      
 
// Release COM.     
CoUninitialize();  
return S_OK; 
 
} // end FreeDirectMusic 
 
/////////////////////////////////////////////////////////////// 
 
int Game_Shutdown(void *parms = NULL, int num_parms = 0) 
{ 
// this is called after the game is exited and the main event 
// loop while is exited, do all you cleanup and shutdown here 
 
FreeDirectMusic(); 
 
// return success or failure or your own return code here 
return(1); 
 
} // end Game_Shutdown 
 
// WINMAIN //////////////////////////////////////////////// 
 
int WINAPI WinMain(	HINSTANCE hinstance, 
					HINSTANCE hprevinstance, 
					LPSTR lpcmdline, 
					int ncmdshow) 
{ 
 
WNDCLASSEX winclass; // this will hold the class we create 
HWND	   hwnd;	 // generic window handle 
MSG		   msg;		 // generic message 
HDC        hdc;      // graphics device context 
 
// first fill in the window class stucture 
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(BLACK_BRUSH); 
winclass.lpszMenuName	= NULL; 
winclass.lpszClassName	= WINDOW_CLASS_NAME; 
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION); 
 
// save hinstance in global 
main_instance = hinstance; 
 
// register the window class 
if (!RegisterClassEx(&winclass)) 
	return(0); 
 
// create the window 
if (!(hwnd = CreateWindowEx(NULL,                  // extended style 
                            WINDOW_CLASS_NAME,     // class 
						    "DirectMusic Demo", // title 
						    WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
					 	    0,0,	  // initial x,y 
						    400,300,  // initial width, height 
						    NULL,	  // handle to parent  
						    NULL,	  // handle to menu 
						    hinstance,// instance of this application 
						    NULL)))	// extra creation parms 
return(0); 
 
// save main window handle 
main_window_handle = hwnd; 
 
// initialize game here 
Game_Init(); 
 
// enter main event loop 
while(TRUE) 
	{ 
    // test if there is a message in queue, if so get it 
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) 
	   {  
	   // test if this is a quit 
       if (msg.message == WM_QUIT) 
           break; 
	 
	   // translate any accelerator keys 
	   TranslateMessage(&msg); 
 
	   // send the message to the window proc 
	   DispatchMessage(&msg); 
	   } // end if 
     
       // main game processing goes here 
       Game_Main(); 
        
	} // end while 
 
// closedown game here 
Game_Shutdown(); 
 
// return to Windows like this 
return(msg.wParam); 
 
} // end WinMain 
 
///////////////////////////////////////////////////////////