476 lines
13 KiB
C++
476 lines
13 KiB
C++
|
/*****************************************************************************\
|
||
|
FILE: appStyle.cpp
|
||
|
|
||
|
DESCRIPTION:
|
||
|
This is the Autmation Object to theme scheme object.
|
||
|
|
||
|
BryanSt 4/3/2000 (Bryan Starbuck)
|
||
|
Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include <cowsite.h>
|
||
|
#include <atlbase.h>
|
||
|
#include "util.h"
|
||
|
#include "theme.h"
|
||
|
#include "appsize.h"
|
||
|
#include "appstyle.h"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//===========================
|
||
|
// *** Class Internals & Helpers ***
|
||
|
//===========================
|
||
|
HRESULT CAppearanceStyle::_getSizeByIndex(IN long nIndex, OUT IThemeSize ** ppThemeSize)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (ppThemeSize)
|
||
|
{
|
||
|
HKEY hKeyStyle;
|
||
|
|
||
|
*ppThemeSize = NULL;
|
||
|
hr = HrRegOpenKeyEx(m_hKeyStyle, NULL, 0, (KEY_WRITE | KEY_READ), &hKeyStyle); // Clone the key.
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
HKEY kKeySizes;
|
||
|
|
||
|
hr = HrRegCreateKeyEx(m_hKeyStyle, SZ_REGKEY_SIZES, 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &kKeySizes, NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
HKEY kKeyTheSize;
|
||
|
TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
|
||
|
|
||
|
wnsprintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%d"), nIndex);
|
||
|
hr = HrRegOpenKeyEx(kKeySizes, szKeyName, 0, (KEY_WRITE | KEY_READ), &kKeyTheSize);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CAppearanceSize_CreateInstance(hKeyStyle, kKeyTheSize, ppThemeSize); // This function takes ownership of hKeyStyle and kKeyTheSize
|
||
|
}
|
||
|
|
||
|
RegCloseKey(kKeySizes);
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
RegCloseKey(hKeyStyle);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#define SZ_APPEARANCE_SCHEME_NAME L"NoVisualStyle"
|
||
|
|
||
|
//===========================
|
||
|
// *** ITheme Interface ***
|
||
|
//===========================
|
||
|
HRESULT CAppearanceStyle::get_DisplayName(OUT BSTR * pbstrDisplayName)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (pbstrDisplayName)
|
||
|
{
|
||
|
CComBSTR bstrDisplayName;
|
||
|
|
||
|
*pbstrDisplayName = NULL;
|
||
|
hr = HrBStrRegQueryValue(m_hKeyStyle, SZ_REGVALUE_DISPLAYNAME, &bstrDisplayName);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
WCHAR szDisplayName[MAX_PATH];
|
||
|
if (SUCCEEDED(SHLoadIndirectString(bstrDisplayName, szDisplayName, ARRAYSIZE(szDisplayName), NULL)))
|
||
|
{
|
||
|
hr = HrSysAllocStringW(szDisplayName, pbstrDisplayName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HrSysAllocStringW(bstrDisplayName, pbstrDisplayName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::put_DisplayName(IN BSTR bstrDisplayName)
|
||
|
{
|
||
|
return HrRegSetValueString(m_hKeyStyle, NULL, SZ_REGVALUE_DISPLAYNAME, bstrDisplayName);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::get_Name(OUT BSTR * pbstrName)
|
||
|
{
|
||
|
// This will be connonical. And it will be language independent if it is one that
|
||
|
// we could upgrade to MUI compat strings.
|
||
|
return HrBStrRegQueryValue(m_hKeyStyle, SZ_REGVALUE_DISPLAYNAME, pbstrName);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::put_Name(IN BSTR bstrName)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::get_length(OUT long * pnLength)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (pnLength)
|
||
|
{
|
||
|
HKEY hKeyStyle;
|
||
|
|
||
|
*pnLength = 0;
|
||
|
|
||
|
hr = HrRegOpenKeyEx(m_hKeyStyle, SZ_REGKEY_SIZES, 0, KEY_READ, &hKeyStyle);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
DWORD dwValues = 0;
|
||
|
|
||
|
hr = HrRegQueryInfoKey(hKeyStyle, NULL, NULL, NULL, &dwValues, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||
|
*pnLength = (long) dwValues;
|
||
|
|
||
|
RegCloseKey(hKeyStyle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::get_item(IN VARIANT varIndex, OUT IThemeSize ** ppThemeSize)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (ppThemeSize)
|
||
|
{
|
||
|
long nCount = 0;
|
||
|
|
||
|
get_length(&nCount);
|
||
|
*ppThemeSize = NULL;
|
||
|
|
||
|
// This is sortof gross, but if we are passed a pointer to another variant, simply
|
||
|
// update our copy here...
|
||
|
if (varIndex.vt == (VT_BYREF | VT_VARIANT) && varIndex.pvarVal)
|
||
|
varIndex = *(varIndex.pvarVal);
|
||
|
|
||
|
switch (varIndex.vt)
|
||
|
{
|
||
|
case VT_I2:
|
||
|
varIndex.lVal = (long)varIndex.iVal;
|
||
|
// And fall through...
|
||
|
|
||
|
case VT_I4:
|
||
|
if ((varIndex.lVal >= 0) && (varIndex.lVal < nCount))
|
||
|
{
|
||
|
hr = _getSizeByIndex(varIndex.lVal, ppThemeSize);
|
||
|
}
|
||
|
break;
|
||
|
case VT_BSTR:
|
||
|
if (varIndex.bstrVal)
|
||
|
{
|
||
|
for (int nIndex = 0; FAILED(hr) && (nIndex < nCount); nIndex++)
|
||
|
{
|
||
|
IThemeSize * pThemeSize;
|
||
|
|
||
|
if (SUCCEEDED(_getSizeByIndex(nIndex, &pThemeSize)))
|
||
|
{
|
||
|
CComBSTR bstrDisplayName;
|
||
|
|
||
|
if (SUCCEEDED(pThemeSize->get_DisplayName(&bstrDisplayName)))
|
||
|
{
|
||
|
if (!StrCmpIW(bstrDisplayName, varIndex.bstrVal))
|
||
|
{
|
||
|
// They match, so this is the one.
|
||
|
*ppThemeSize = pThemeSize;
|
||
|
pThemeSize = NULL;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
if (bstrDisplayName)
|
||
|
{
|
||
|
bstrDisplayName.Empty();
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(pThemeSize->get_Name(&bstrDisplayName)))
|
||
|
{
|
||
|
if (!StrCmpIW(bstrDisplayName, varIndex.bstrVal))
|
||
|
{
|
||
|
// They match, so this is the one.
|
||
|
*ppThemeSize = pThemeSize;
|
||
|
pThemeSize = NULL;
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ATOMICRELEASE(pThemeSize);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = E_NOTIMPL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::get_SelectedSize(OUT IThemeSize ** ppThemeSize)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (ppThemeSize)
|
||
|
{
|
||
|
HKEY hKeyStyle;
|
||
|
|
||
|
*ppThemeSize = NULL;
|
||
|
AssertMsg((NULL != m_hKeyStyle), TEXT("If this isn't set, then someone didn't construct us correctly"));
|
||
|
hr = HrRegOpenKeyEx(m_hKeyStyle, NULL, 0, (KEY_WRITE | KEY_READ), &hKeyStyle); // Clone the key.
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TCHAR szSelectedSize[MAXIMUM_SUB_KEY_LENGTH];
|
||
|
DWORD cbSize = sizeof(szSelectedSize);
|
||
|
|
||
|
hr = HrSHGetValue(m_hKeyStyle, NULL, SZ_REGVALUE_SELECTEDSIZE, NULL, szSelectedSize, &cbSize);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
StrCpyN(szSelectedSize, TEXT("0"), ARRAYSIZE(szSelectedSize)); // Select the first one in the list when in doubt.
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
|
||
|
HKEY hKeyTheSize;
|
||
|
|
||
|
wnsprintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%s\\%s"), SZ_REGKEY_SIZES, szSelectedSize);
|
||
|
|
||
|
// Let's find the next empty slot
|
||
|
hr = HrRegOpenKeyEx(m_hKeyStyle, szKeyName, 0, (KEY_WRITE | KEY_READ), &hKeyTheSize);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CAppearanceSize_CreateInstance(hKeyStyle, hKeyTheSize, ppThemeSize); // This function takes ownership of hKeyStyle and kKeySizes
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
RegCloseKey(hKeyTheSize);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
RegCloseKey(hKeyStyle);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::put_SelectedSize(IN IThemeSize * pThemeSize)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (pThemeSize)
|
||
|
{
|
||
|
TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
|
||
|
CComBSTR bstrDisplayNameSource;
|
||
|
|
||
|
szKeyName[0] = 0;
|
||
|
hr = pThemeSize->get_DisplayName(&bstrDisplayNameSource);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
for (int nIndex = 0; SUCCEEDED(hr); nIndex++)
|
||
|
{
|
||
|
IThemeSize * pThemeSizeInList;
|
||
|
|
||
|
hr = _getSizeByIndex(nIndex, &pThemeSizeInList);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
CComBSTR bstrDisplayName;
|
||
|
|
||
|
hr = pThemeSizeInList->get_DisplayName(&bstrDisplayName);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
ATOMICRELEASE(pThemeSizeInList);
|
||
|
if (!StrCmpIW(bstrDisplayName, bstrDisplayNameSource))
|
||
|
{
|
||
|
// They match, so this is the one.
|
||
|
wnsprintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%d"), nIndex);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr) && szKeyName[0])
|
||
|
{
|
||
|
DWORD cbSize = ((lstrlen(szKeyName) + 1) * sizeof(szKeyName[0]));
|
||
|
|
||
|
hr = HrSHSetValue(m_hKeyStyle, NULL, SZ_REGVALUE_SELECTEDSIZE, REG_SZ, szKeyName, cbSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle::AddSize(OUT IThemeSize ** ppThemeSize)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (ppThemeSize)
|
||
|
{
|
||
|
HKEY kKeySizes;
|
||
|
*ppThemeSize = NULL;
|
||
|
|
||
|
hr = HrRegCreateKeyEx(m_hKeyStyle, SZ_REGKEY_SIZES, 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &kKeySizes, NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
for (int nIndex = 0; nIndex < 10000; nIndex++)
|
||
|
{
|
||
|
HKEY hKeyTheSize;
|
||
|
TCHAR szKeyName[MAXIMUM_SUB_KEY_LENGTH];
|
||
|
|
||
|
wnsprintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%d"), nIndex);
|
||
|
|
||
|
// Let's find the next empty slot
|
||
|
hr = HrRegOpenKeyEx(kKeySizes, szKeyName, 0, (KEY_WRITE | KEY_READ), &hKeyTheSize);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
RegCloseKey(hKeyTheSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = HrRegCreateKeyEx(kKeySizes, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, (KEY_WRITE | KEY_READ), NULL, &hKeyTheSize, NULL);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
HKEY hKeyStyle;
|
||
|
|
||
|
hr = HrRegOpenKeyEx(m_hKeyStyle, NULL, 0, (KEY_WRITE | KEY_READ), &hKeyStyle); // Clone the key.
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = CAppearanceSize_CreateInstance(hKeyStyle, hKeyTheSize, ppThemeSize); // This function takes ownership of hKeyStyle and kKeySizes
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
RegCloseKey(hKeyStyle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
RegCloseKey(hKeyTheSize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegCloseKey(kKeySizes);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//===========================
|
||
|
// *** IUnknown Interface ***
|
||
|
//===========================
|
||
|
ULONG CAppearanceStyle::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&m_cRef);
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG CAppearanceStyle::Release()
|
||
|
{
|
||
|
if (InterlockedDecrement(&m_cRef))
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
//===========================
|
||
|
// *** Class Methods ***
|
||
|
//===========================
|
||
|
HRESULT CAppearanceStyle::QueryInterface(REFIID riid, void **ppvObj)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
QITABENT(CAppearanceStyle, IThemeStyle),
|
||
|
QITABENT(CAppearanceStyle, IDispatch),
|
||
|
{ 0 },
|
||
|
};
|
||
|
|
||
|
return QISearch(this, qit, riid, ppvObj);
|
||
|
}
|
||
|
|
||
|
|
||
|
CAppearanceStyle::CAppearanceStyle(IN HKEY hkeyStyle) : CImpIDispatch(LIBID_Theme, 1, 0, IID_IThemeStyle), m_cRef(1)
|
||
|
{
|
||
|
DllAddRef();
|
||
|
|
||
|
// This needs to be allocated in Zero Inited Memory.
|
||
|
// Assert that all Member Variables are inited to Zero.
|
||
|
m_hKeyStyle = hkeyStyle;
|
||
|
}
|
||
|
|
||
|
|
||
|
CAppearanceStyle::~CAppearanceStyle()
|
||
|
{
|
||
|
if (m_hKeyStyle)
|
||
|
{
|
||
|
RegCloseKey(m_hKeyStyle);
|
||
|
}
|
||
|
|
||
|
DllRelease();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT CAppearanceStyle_CreateInstance(IN HKEY hkeyStyle, OUT IThemeStyle ** ppThemeStyle)
|
||
|
{
|
||
|
HRESULT hr = E_INVALIDARG;
|
||
|
|
||
|
if (ppThemeStyle)
|
||
|
{
|
||
|
CAppearanceStyle * pObject = new CAppearanceStyle(hkeyStyle);
|
||
|
|
||
|
*ppThemeStyle = NULL;
|
||
|
if (pObject)
|
||
|
{
|
||
|
hr = pObject->QueryInterface(IID_PPV_ARG(IThemeStyle, ppThemeStyle));
|
||
|
pObject->Release();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|