Written by: Patty Buchanan
Participates: Tom Curry and Harris Phram
IX. Registering COM Objects in Visual C++
In order to have the DirectX7 program work under the launcher, it must be registered in the registry. The following program is an example of how to register and unregister these programs using the functions in the DirectX 7 for C++ Libraries.
Step1
Use Visual C++ to create an AppWizard Dialog project. Make sure that AppWizared.exe is selected for projects and that Dialog Based is selected. Then click on Finish for a default project. Compile the program.
Step 2
Two additional libraries from DirectX 7 must added to the project libraries. The instructions to do this are in the How to Compile A DirectX Application with Visual C++ section. The two libraries to be added are dxguid.lib and dplayx.lib. See the figure below.
Step 3
In the view finder window on the left hand side of your screen, there are three tabs, one for class view, one for resource view and one for file view. Select the resource view tab and locate the main Dialog form to be displayed. Add two command buttons to the dialog plus any desired static text. The first button is to register the objects and the second button is to unregister them.
Step 4
The button name properties were set to IDC_REGISTER and to IDC_UNREGISTER. By double clicking on the buttons, the class wizard was automatically invoked mapping the buttons to functions onregister and onunregister in the ChatRegister_CPPDlg class. Compile the program again.
Step 5
Add additional variables and code to the following source files and their respective headers. The code additions are displayed in BOLD text.
The first file is the ChatRegister_CPP.h file listed below.
// ChatRegister_CPP.h : main header file for the CHATREGISTER_CPP application
//
#if !defined(AFX_CHATREGISTER_CPP_H__B008DFA6_9791_11D3_8DA2_EA0B1BB2F108__INCLUDED_)
#define AFX_CHATREGISTER_CPP_H__B008DFA6_9791_11D3_8DA2_EA0B1BB2F108__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPApp:
// See ChatRegister_CPP.cpp for the implementation of this class
//
class CChatRegister_CPPApp : public CWinApp
{
public:
CChatRegister_CPPApp();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChatRegister_CPPApp)
public:
virtual BOOL InitInstance();
virtual int ExitInstance(); //this function was added to the class
//}}AFX_VIRTUAL
// Implementation
//{{AFX_MSG(CChatRegister_CPPApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHATREGISTER_CPP_H__B008DFA6_9791_11D3_8DA2_EA0B1BB2F108__INCLUDED_)
Step 6
The next file is ChatRegister_CPPDlg.h listed below.
// ChatRegister_CPPDlg.h : header file
//
#if !defined(AFX_CHATREGISTER_CPPDLG_H__B008DFA8_9791_11D3_8DA2_EA0B1BB2F108__INCLUDED_)
#define AFX_CHATREGISTER_CPPDLG_H__B008DFA8_9791_11D3_8DA2_EA0B1BB2F108__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "dplay.h" //These two include statements were added
#include "dplobby.h" //These two include statements were added
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPDlg dialog
class CChatRegister_CPPDlg : public CDialog
{
// Construction
public:
BOOL InitDPlayLobby(); //This function was added to the class.
CChatRegister_CPPDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CChatRegister_CPPDlg)
enum { IDD = IDD_CHATREGISTER_CPP_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CChatRegister_CPPDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
LPDIRECTPLAYLOBBY3A m_pDPLobby; //This variable was added to the class
// Generated message map functions
//{{AFX_MSG(CChatRegister_CPPDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnRegister(); //This function was added by the class wizard
afx_msg void OnUnregister();//This function was added by the class wizard
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_CHATREGISTER_CPPDLG_H__B008DFA8_9791_11D3_8DA2_EA0B1BB2F108__INCLUDED_)
Step 7
The next file with additional code is ChatRegister_CPP.cpp
// ChatRegister_CPP.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "ChatRegister_CPP.h" //These two includes were added to the file
#include "ChatRegister_CPPDlg.h" //These two includes were added to the file
#include "objbase.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPApp
BEGIN_MESSAGE_MAP(CChatRegister_CPPApp, CWinApp)
//{{AFX_MSG_MAP(CChatRegister_CPPApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPApp construction
CChatRegister_CPPApp::CChatRegister_CPPApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CChatRegister_CPPApp object
CChatRegister_CPPApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPApp initialization
BOOL CChatRegister_CPPApp::InitInstance()
{
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
if(CoInitialize(NULL) != S_OK) //These lines of coded were added
{ //These lines of coded were added
AfxMessageBox("Unable to Initialze COM--Exiting");
return FALSE; //These lines of coded were added
} /These lines of coded were added
CChatRegister_CPPDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
int CChatRegister_CPPApp::ExitInstance() //These lines of coded were added
{ //These lines of coded were added
CoUninitialize(); //These lines of coded were added
return CWinApp::ExitInstance(); //These lines of coded were added
} //These lines of coded were added
Step 8
The last file to require modification is ChatRegister_CPPDlg.cpp
// ChatRegister_CPPDlg.cpp : implementation file
//
#include "stdafx.h"
#include "ChatRegister_CPP.h" //These include statements were added
#include "ChatRegister_CPPDlg.h" //These include statements were added
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//This guid code below was added
static const GUID DIRECTXCHATCONNECT_GUID =
{ 0x55100520, 0x907, 0x11d2, { 0xa0, 0x81, 0x0, 0x60, 0x8, 0xa3, 0x78, 0x9d } };
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPDlg dialog
CChatRegister_CPPDlg::CChatRegister_CPPDlg(CWnd* pParent /*=NULL*/)
: CDialog(CChatRegister_CPPDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CChatRegister_CPPDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pDPLobby = NULL; //This variable was set to null
}
void CChatRegister_CPPDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChatRegister_CPPDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CChatRegister_CPPDlg, CDialog)
//{{AFX_MSG_MAP(CChatRegister_CPPDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_REGISTER, OnRegister) //Added by Class Wizard
ON_BN_CLICKED(IDC_UNREGISTER, OnUnregister) //Added by Class Wizard
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChatRegister_CPPDlg message handlers
BOOL CChatRegister_CPPDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
InitDPlayLobby(); //This function call was added
return TRUE; // return TRUE unless you set the focus to a control
}
void CChatRegister_CPPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CChatRegister_CPPDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CChatRegister_CPPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//The three functions below are all added to this program.
//Modify the path statements to match your file paths.
void CChatRegister_CPPDlg::OnRegister()
{
// TODO: Add your control notification handler code here
if(!m_pDPLobby)
return;
DPAPPLICATIONDESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.lpszApplicationNameA = "DirectX Chat Connect";
desc.guidApplication = DIRECTXCHATCONNECT_GUID;
desc.lpszFilenameA = "chatconnect.exe";
desc.lpszPathA = "D:\\dx7sdk-700.1\\samples\\multimedia\\dplay\\src\\chatconnect\\Releasedesc.lpszCurrentDirectoryA = "D:\\dx7sdk-700.1\\samples\\multimedia\\dplay\\src\\chatconnect\\Release";
desc.lpszCommandLineA = "";
HRESULT hr = m_pDPLobby->RegisterApplication(0,&desc);
if(hr != DP_OK)
{
AfxMessageBox("Unable to register ChatConnection application\n");
return;
}
else
{
AfxMessageBox("Successful ChatConnection Registration\n");
return;
}
}
void CChatRegister_CPPDlg::OnUnregister()
{
// TODO: Add your control notification handler code here
if(!m_pDPLobby)
return;
HRESULT hr = m_pDPLobby->UnregisterApplication(0,DIRECTXCHATCONNECT_GUID);
if(hr != DP_OK)
{
AfxMessageBox("Unable to unregister ChatConnection application\n");
return;
}
else
{
AfxMessageBox("Successful ChatConnection unregistration\n");
return;
}
}
BOOL CChatRegister_CPPDlg::InitDPlayLobby()
{
HRESULT hr = CoCreateInstance(CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER,IID_IDirectPlayLobby3A, (LPVOID *)&m_pDPLobby);
if(hr != S_OK)
{
AfxMessageBox("Unable to initialize Lobby interface\n");
return FALSE;
}
return TRUE;
}