#include "stdafx.h"
#include "CCOMCategoriesComboBox.h"
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::CCOMCategoriesComboBox
//
// Synopsis : Constructor
//
// Argument :
//
// [const CATID & catid] -- UUID of the COM Category
// [CString strRegKeyHive] -- Cache key hive based in HKEY_LOCAL_MACHINE
// [CString strRegKeyValueName] -- Registry value name to store cached value
//
//-----------------------------------------------------------------------------
CCOMCategoriesComboBox::CCOMCategoriesComboBox( const CATID & catid,
CString strRegKeyHive,
CString strRegKeyValueName ) :
m_catid( catid ),
m_strRegKeyHive( strRegKeyHive ),
m_strRegKeyValueName( strRegKeyValueName ),
m_strRegKeyValueIID( strRegKeyValueName + "IID" ),
m_bReadAll( false )
{
Init();
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::CCOMCategoriesComboBox
//
// Synopsis : Constructor
//
// Argument :
//
// [LPCTSTR psCatid] -- pointer on a string representing UUID of the COM Cat.
// [CString strRegKeyHive] -- Cache key hive based in HKEY_LOCAL_MACHINE
// [CString strRegKeyValueName] -- Registry value name to store cached value
//
//-----------------------------------------------------------------------------
CCOMCategoriesComboBox::CCOMCategoriesComboBox( LPCTSTR psCatid,
CString strRegKeyHive,
CString strRegKeyValueName ) :
m_strRegKeyHive( strRegKeyHive ),
m_strRegKeyValueName( strRegKeyValueName ),
m_strRegKeyValueIID( strRegKeyValueName + "IID" ),
m_bReadAll( false )
{
//Determine CATID from string
size_t length = strlen(psCatid) + 1;
wchar_t *pwCatid = (wchar_t*)malloc((sizeof(wchar_t) * length));
if (pwCatid)
{
mbstowcs(pwCatid, psCatid, length);
}
IIDFromString((LPOLESTR)pwCatid, &m_catid);
free( pwCatid );
Init();
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::~CCOMCategoriesComboBox
//
// Synopsis : Destructor
//
//-----------------------------------------------------------------------------
CCOMCategoriesComboBox::~CCOMCategoriesComboBox()
{
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::Init
//
// Synopsis : Create the cache key if it do not exists already
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::Init()
{
CRegKey regkey;
// Open/Create the settings registry key
if ( ERROR_SUCCESS == regkey.Create( HKEY_LOCAL_MACHINE,
m_strRegKeyHive
) )
{
regkey.Close();
}
}
///////////////////////////////////////////////////////////////////////////////
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::SubclassWindow
//
// Synopsis : Subclasses the window identified by hWnd
//
// Return type: [BOOL] -- TRUE if the window is successfully subclassed;
// otherwise, it is FALSE
//
// Argument :
//
// [HWND hWnd] -- [in] The handle to the window being subclassed.
//
//-----------------------------------------------------------------------------
BOOL CCOMCategoriesComboBox::SubclassWindow(HWND hWnd)
{
BOOL bRet = thisClass::SubclassWindow(hWnd);
if ( bRet )
{
ReadFromRegistry();
}
return bRet;
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::BuildList
//
// Synopsis : Build the list box of the combo box using ICatInformation and
// "(Default)" string of the COM object
// Sets the 32-bit value associated with the specified item in
// the combo box to be a CString's pointer containing the CLSID
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::BuildList()
{
HRESULT hr = ::CoInitialize( NULL );
if ( SUCCEEDED(hr) )
{
ICatInformation * pICatInformation;
HRESULT hr = CoCreateInstance( CLSID_StdComponentCategoriesMgr,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICatInformation,
(void**) &pICatInformation );
if ( SUCCEEDED(hr) )
{
IEnumGUID * pIEnumGUID = 0;
HRESULT hr = pICatInformation->EnumClassesOfCategories(
1,
&m_catid,
0,
0,
&pIEnumGUID );
if ( SUCCEEDED(hr) )
{
pIEnumGUID->Reset();
ULONG lFetched;
CLSID ClsID;
CRegKey regKey;
LPOLESTR lpClsIDString;
while ( S_OK == pIEnumGUID->Next( 1, &ClsID, &lFetched ) )
{
CString sKey( _T("CLSID\\") );
CString * pstrItemData = NULL;
if ( S_OK == StringFromIID( ClsID, &lpClsIDString ) )
{
sKey += lpClsIDString;
pstrItemData = new CString( lpClsIDString );
CoTaskMemFree( lpClsIDString );
}
// Open the registry key
if ( ERROR_SUCCESS == regKey.Open( HKEY_CLASSES_ROOT,
sKey,
KEY_QUERY_VALUE) )
{
DWORD dwCount = 256;
char sValue[256];
// Read "(Default)" string value
if ( ERROR_SUCCESS == regKey.QueryValue( sValue,
NULL,
&dwCount ) )
{
// Adds "(Default)" string to the list box of the
// combo box
int nIndex = AddString( sValue );
if ( nIndex >= 0 )
{
// Sets the 32-bit value associated with the
// specified item in the combo box to be a
// CString's pointer containing the CLSID
if ( CB_ERR == SetItemDataPtr(
nIndex,
(void*)pstrItemData ) )
{
DeleteString( nIndex );
}
}
}
regKey.Close();
}
}
pIEnumGUID->Release();
}
pICatInformation->Release();
}
::CoUninitialize();
}
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::WriteToRegistry
//
// Synopsis : Cache chosen value to the registry
//
// Notes: Needed to quicken the combo box creation
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::WriteToRegistry()
{
if ( !m_strRegKeyHive.IsEmpty() &&
!m_strRegKeyValueName.IsEmpty() &&
!m_strRegKeyValueIID.IsEmpty()
)
{
// Save the settings in the registry
int nIndex = GetCurSel();
if ( CB_ERR != nIndex )
{
CString * pstr = (CString*)GetItemDataPtr( nIndex );
CRegKey regkey;
//Open the settings registry key
if ( ERROR_SUCCESS == regkey.Open( HKEY_LOCAL_MACHINE,
m_strRegKeyHive,
KEY_ALL_ACCESS) )
{
//Write registry settings
CString str( *pstr );
regkey.SetValue( (LPCTSTR)str, m_strRegKeyValueIID );
char sName[256];
GetLBText( GetCurSel(), sName );
regkey.SetValue( sName, m_strRegKeyValueName );
regkey.Close();
}
}
}
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::ReadFromRegistry
//
// Synopsis : Read cached value from the registry
//
// Notes: Needed to quicken the combo box creation
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::ReadFromRegistry()
{
if ( !m_strRegKeyHive.IsEmpty() &&
!m_strRegKeyValueName.IsEmpty() &&
!m_strRegKeyValueIID.IsEmpty()
)
{
//Read settings in the registry and setup the combo accordingly
CRegKey regkey;
//Open the settings registry key
if ( ERROR_SUCCESS == regkey.Open( HKEY_LOCAL_MACHINE,
m_strRegKeyHive,
KEY_QUERY_VALUE) )
{
char sIID[256];
char sName[256];
unsigned long stringsize = 256;
//Read registry settings
if ( ERROR_SUCCESS == regkey.QueryValue( sName,
m_strRegKeyValueName,
&stringsize ) )
{
stringsize = 256;
if ( ERROR_SUCCESS == regkey.QueryValue( sIID,
m_strRegKeyValueIID,
&stringsize ) )
{
int nIndex = AddString( sName );
if ( nIndex >= 0 )
{
CString * pstrItemData = new CString(sIID);
if ( CB_ERR != SetItemDataPtr( nIndex,
(void*)pstrItemData ) )
{
SetCurSel( nIndex );
}
}
}
}
regkey.Close();
}
}
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::OnDropDown
//
// Synopsis : The list box of a combo box is about to drop down (be made
// visible). Build the list by reading values from registry if not
// done already.
//
// Argument :
//
// [UINT msg] -- WM_COMMAND
// [int id] -- control identifier of the combo box
// [HWND hwnd] -- handle to window
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::OnDropDown( UINT msg, int id, HWND hwnd )
{
if ( hwnd == m_hWnd )
{
if ( !m_bReadAll )
{
CWaitCursor waitcursor;
Destroy();
BuildList();
m_bReadAll = true;
}
}
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::OnSelChange
//
// Synopsis : The selection in the list box of a combo box is about to be
// changed as a result of the user either clicking in the list box
// or changing the selection by using the arrow keys.
// Write new selected value to the cache.
//
// Argument :
//
// [UINT msg] -- WM_COMMAND
// [int id] -- control identifier of the combo box
// [HWND hwnd] -- handle to window
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::OnSelChange( UINT msg, int id, HWND hwnd )
{
if ( hwnd == m_hWnd )
{
WriteToRegistry();
}
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::OnDestroy
//
// Synopsis : Combo box is being destroyed.
// Free all allocated memory
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::OnDestroy()
{
Destroy();
}
//+----------------------------------------------------------------------------
//
// Function : CCOMCategoriesComboBox::Destroy
//
// Synopsis : Free allocated memory to handle CLSID
//
//-----------------------------------------------------------------------------
void CCOMCategoriesComboBox::Destroy()
{
int n = GetCount();
if ( n != CB_ERR )
{
while ( --n >= 0 )
{
void * pData = GetItemDataPtr( n );
if ( pData != (void*)-1 )
{
delete pData;
}
}
}
ResetContent();
}