Access to COM servers using C++ can be as easy as with scripts as you
can see if you compare the program in this topic with the version in the
previous topic - both performing
the same task (for details, see the previous topic). The easy approach
presented here is possible by exploiting the informations in the type library which is stored in BrainVoyager.exe.
The informations in the type library are accessed with the "#import"
statement in one of the first lines of the program. The #import-technique
also provides "smart pointers" to interfaces. With these smart
pointers, you do not have to care about calling "Release" to
release a reference of a particular interface when you no longer need
the reference. This and other "bookkeeping" operations are done
automatically with smart pointers. To use a smart pointer, append "Ptr"
after the interface name, i.e. IApplicationPtr is used below to access
the IApplication interface.
Note, however, that the type library technique presented here works only
with the Microsoft Visual C++ compiler. If you use another compiler, you
must use the general approach as described in the previous
topic.
// BrainVoyagerEasyClient.cpp // Adjust the following path if your BV is not in "C:\Program Files\BrainVoyager" #import "C:\Program Files\BrainVoyager\BrainVoyager.exe" no_namespace #include <fstream.h> BOOL MyLoadVMR(const char *filename); BOOL MySaveVMR(const char *filename); BYTE *Vol; // Pointer to VMR data set int DimX, DimY, DimZ; void main() { CoInitialize(NULL); // direct access to IApplication interface IApplicationPtr BVApplication(__uuidof(BrainVoyager)); char path[_MAX_PATH], filename[_MAX_PATH]; // Adjust the following path if necessary strcpy(path, "D:\\Program Files\\Samples\\ObjectsRawData\\"); strcpy(filename, path); strcat(filename, "cg2_tal.vmr"); // Easy and direct access to IDocument interface // OpenDocument works like in scripts: it returns the Document object IDocumentPtr BVDoc = BVApplication->OpenDocument(filename); // Call document methods //BVDoc->SetZoomLevel(2); BVDoc->Hide3DVolumeTools(); // Now let's work on a BrainVoyager file format: a VMR file int new_val; if(MyLoadVMR(filename)) { int x, y, z; for(x=0; x<DimX; x++) { for(y=0; y<DimY; y++) { for(z=0; z<DimZ; z++) { new_val = Vol[z*DimY*DimX + y*DimX + x]; if((new_val > 30) && (new_val < 226)) // > 10 new_val = 225 - new_val + 10; Vol[z*DimY*DimX + y*DimX + x] = (BYTE)max(0, new_val); } } } strcpy(filename, path); strcat(filename, "cg2_tal_inv.vmr"); MySaveVMR(filename); free(Vol); IDocumentPtr BVDoc = BVApplication->OpenDocument(filename); //BVDoc->SetZoomLevel(2); BVDoc->Hide3DVolumeTools(); } BVDoc = NULL; BVApplication = NULL; CoUninitialize(); } BOOL MyLoadVMR(const char *filename) { ifstream VMRFile( filename, ios::binary | ios::nocreate ); if( !VMRFile ) { cout << "ERROR: Cannot open VMR file." << endl; return FALSE; } unsigned short Nx, Ny, Nz; VMRFile.read((char *)(&Nx), sizeof(unsigned short)); VMRFile.read((char *)(&Ny), sizeof(unsigned short)); VMRFile.read((char *)(&Nz), sizeof(unsigned short)); DimX = (int)Nx; DimY = (int)Ny; DimZ = (int)Nz; cout << Nx << " " << Ny << " " << Nz << endl; if((Vol = (BYTE *)malloc(Nz*Ny*Nx*sizeof(BYTE))) == NULL) { cout << "ERROR: Cannot allocate memory for VMR file." << endl; return FALSE; } VMRFile.read(Vol, Nx*Ny*Nz*sizeof(BYTE)); return TRUE; } BOOL MySaveVMR(const char *filename) { ofstream VMRFile( filename, ios::binary | ios::trunc ); if( !VMRFile ) { cout << "ERROR: Cannot open VMR file." << endl; return FALSE; } unsigned short Nx, Ny, Nz; Nx = (unsigned short)DimX; Ny = (unsigned short)DimY; Nz = (unsigned short)DimZ; cout << Nx << " " << Ny << " " << Nz << endl; VMRFile.write((char *)(&Nx), sizeof(unsigned short)); VMRFile.write((char *)(&Ny), sizeof(unsigned short)); VMRFile.write((char *)(&Nz), sizeof(unsigned short)); VMRFile.write(Vol, Nx*Ny*Nz*sizeof(BYTE)); return TRUE; }