/**
* \file DSAddIn.cpp
*
* \brief Implementation file for class CDSAddIn
*
* $Id: DSAddIn.cpp, v1.1.1.1 2006/09/24 23:12:30 mgh Exp $
*
*
* Copyright (C) 2006 Michael G. Herstine <sp1ff@pobox.com>
*
* Permission to use, copy, or modify this source code is hereby granted
* free of charge, provided that this copyright notice appear on all
* copies and on all source code derived from this code. No
* representation is made regarding the suitability of this software for
* any purpose. It is provided "as is" without express or implied
* warranty.
*
*
*/
////////////////////////////////////////////////////////////////////////////
// Modified by Jordan Walters, 01.03.2008 for multi-IDE version increment //
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h" // Pre-compiled header
#include "AddIn.h" // For CreateInstanceWithParamItf
#include "DSAddIn.h" // For class CDSAddIn
#include <time.h>
#include <sstream>
////////////////////////////////////////////////////////////////////////
// Class CDSCommands
void CDSCommands::SetParam(CAddIn *pParent)
{
ATLASSERT(NULL != pParent);
m_pParent = pParent;
}
void CDSCommands::IncVersion()
{
USES_CONVERSION;
ATLASSERT(NULL != m_pParent);
// User has pressed the IncVersion button.
IGenericProject* pProject = NULL;
if(SUCCEEDED(m_pParent->GetApplicationObject()->get_ActiveProject((LPDISPATCH*)&pProject)))
{
USES_CONVERSION;
CComBSTR bstrProjectName;
if(SUCCEEDED(pProject->get_FullName(&bstrProjectName.m_str)))
{
std::string strProjectName = OLE2T(bstrProjectName.m_str);
if(m_pParent->isCPlusPlusProject(strProjectName))
{
std::list<std::string> strListResourceName;
std::list<std::string> strListResourceContent;
std::list<std::string> strListOrigResourceContent;
std::list<std::string> listIncWarningMessages;
m_pParent->IncVersion(strProjectName,
es_User_ButtonPress,
strListResourceName,
strListResourceContent,
strListOrigResourceContent,
listIncWarningMessages);
if(listIncWarningMessages.size())
{
std::stringstream ssWarningText;
std::list<std::string>::iterator it = listIncWarningMessages.begin();
std::list<std::string>::iterator itEnd = listIncWarningMessages.end();
for(; it != itEnd; ++it)
{
ssWarningText << *it << "\n";
}
MessageBox(NULL, ssWarningText.str().c_str(), INCVERSION, MB_OK | MB_ICONWARNING);
}
g_mapListResourceName[strProjectName] = strListResourceName;
g_mapListResourceContent[strProjectName] = strListResourceContent;
g_mapListOrigResourceContent[strProjectName] = strListOrigResourceContent;
}
}
pProject->Release();
}
}
void CDSCommands::Configure()
{
ATLASSERT(NULL != m_pParent);
m_pParent->Configure();
}
////////////////////////////////////////////////////////////////////////
// Class CDSAppEvents
void CDSAppEvents::SetParam(CAddIn *pParent)
{
ATLASSERT(NULL != pParent);
m_pParent = pParent;
}
void CDSAppEvents::Connect(IUnknown* pUnk)
{
HRESULT hr = AtlAdvise(pUnk, this, IID_IApplicationEvents,
&m_dwAdvise);
if (FAILED(hr)) throw _com_error(hr);
}
void CDSAppEvents::Disconnect(IUnknown* pUnk)
{
AtlUnadvise(pUnk, IID_IApplicationEvents, m_dwAdvise);
}
////////////////////////////////////////////////////////////////////////
// Interface IApplicationEvents
STDMETHODIMP CDSAppEvents::BeforeBuildStart()
{
USES_CONVERSION;
ATLTRACE2(atlTraceIncVersion, 2, "BeforeBuildStart\n");
// We must call the version increment stuff BEFORE the build actually happens
// so that the rc/rc2 files get saved with the new versions.
// An (unfortunate) side effect is that the version gets updated every time you
// do a build, even if there have been no code changes.
IApplication *pApplication = m_pParent->GetApplicationObject();
IGenericProject* pProject = NULL;
if(SUCCEEDED(pApplication->get_ActiveProject((LPDISPATCH*)&pProject)))
{
CComBSTR bstrProjectName;
if(SUCCEEDED(pProject->get_FullName(&bstrProjectName.m_str)))
{
std::string strProjectName = OLE2T(bstrProjectName.m_str);
if(m_pParent->isCPlusPlusProject(strProjectName))
{
std::list<std::string> strListResourceName;
std::list<std::string> strListResourceContent;
std::list<std::string> strListOrigResourceContent;
std::list<std::string> listIncWarningMessages;
m_pParent->IncVersion(strProjectName,
es_IDE_BuildStart,
strListResourceName,
strListResourceContent,
strListOrigResourceContent,
listIncWarningMessages);
if(listIncWarningMessages.size())
{
time_t ltime;
time(<ime);
struct tm today;
_localtime64_s(&today, <ime);
char timeBuf[128];
strftime(timeBuf, 128, "%#c", &today);
pApplication->PrintToOutputWindow(CComBSTR(""));
pApplication->PrintToOutputWindow(CComBSTR("IncVersion - ") + (timeBuf));
pApplication->PrintToOutputWindow(CComBSTR("----------------------------------------------------------------"));
std::list<std::string>::iterator it = listIncWarningMessages.begin();
std::list<std::string>::iterator itEnd = listIncWarningMessages.end();
for(; it != itEnd; ++it)
{
CComBSTR strOutStr(it->c_str());
pApplication->PrintToOutputWindow(strOutStr);
}
}
g_mapListResourceName[strProjectName] = strListResourceName;
g_mapListResourceContent[strProjectName] = strListResourceContent;
g_mapListOrigResourceContent[strProjectName] = strListOrigResourceContent;
}
}
pProject->Release();
}
return S_OK;
}
STDMETHODIMP CDSAppEvents::BuildFinish(long nErrors, long /*nWarnings*/)
{
USES_CONVERSION;
ATLTRACE2(atlTraceIncVersion, 2, "BuildFinish\n");
if(nErrors != 0)
{
// If the build failed, reset the resource version numbers to the original content
IGenericProject* pProject = NULL;
if(SUCCEEDED(m_pParent->GetApplicationObject()->get_ActiveProject((LPDISPATCH*)&pProject)))
{
CComBSTR bstrProjectName;
if(SUCCEEDED(pProject->get_FullName(&bstrProjectName.m_str)))
{
std::string strProjectName = OLE2T(bstrProjectName.m_str);
m_pParent->updateResource(g_mapListResourceName[strProjectName],
g_mapListOrigResourceContent[strProjectName]);
}
pProject->Release();
}
}
else if(g_mapListResourceContent.size() > 0)
{
// We incremented a digit. If it was not the build number, but the
// major/minor version/revision, and if the user has configured to revert
// to incrementing the build number, do this here.
DWORD dwDigit = DEF_DIGIT;
bool bResetLowerVersions = DEF_RESET;
bool bRevertToBuildNumber = DEF_REVERT;
bool bDisplayWarnings = DEF_DISPLAY_WARNINGS;
getOptionsFromReg(dwDigit, bResetLowerVersions, bRevertToBuildNumber, bDisplayWarnings);
if(bRevertToBuildNumber)
{
dwDigit = BUILD_NUMBER_DIGIT;
setOptionsToReg(dwDigit, bResetLowerVersions, bRevertToBuildNumber, bDisplayWarnings);
}
}
return S_OK;
}
STDMETHODIMP CDSAppEvents::BeforeApplicationShutDown()
{
ATLTRACE2(atlTraceIncVersion, 2, "BeforeApplicationShutDown\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::DocumentOpen(IDispatch * /*pDocument*/)
{
ATLTRACE2(atlTraceIncVersion, 2, "DocumentOpen\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::BeforeDocumentClose(IDispatch * /*pDocument*/)
{
ATLTRACE2(atlTraceIncVersion, 2, "BeforeDocumentClose\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::DocumentSave(IDispatch * /*pDocument*/)
{
ATLTRACE2(atlTraceIncVersion, 2, "DocumentSave\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::NewDocument(IDispatch * /*pDocument*/)
{
ATLTRACE2(atlTraceIncVersion, 2, "NewDocument\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::WindowActivate(IDispatch * /*pWindow*/)
{
ATLTRACE2(atlTraceIncVersion, 2, "WindowActivate\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::WindowDeactivate(IDispatch * /*pWindow*/)
{
ATLTRACE2(atlTraceIncVersion, 2, "WindowDeactivate\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::WorkspaceOpen()
{
ATLTRACE2(atlTraceIncVersion, 2, "WorkspaceOpen\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::WorkspaceClose()
{
ATLTRACE2(atlTraceIncVersion, 2, "WorkspaceClose\n");
return S_OK;
}
STDMETHODIMP CDSAppEvents::NewWorkspace()
{
ATLTRACE2(atlTraceIncVersion, 2, "NewWorkspace\n");
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// Class CDSAddIn
const TCHAR * const CDSAddIn::VAL_CREATED_DSTB =
_T("CreatedDSTb");
const TCHAR * const CDSAddIn::WND_BASE_NAME =
_T("###INCVERSION-MessageWnd-f61141fa-8c74-11da-bf67-0007e946f29c-");
const TCHAR * const CDSAddIn::WND_CLASS_NAME =
_T("###INCVERSION-WNDCLASS-f61141f9-8c74-11da-bf67-0007e946f29c###");
CDSAddIn::CDSAddIn() : m_pParent(NULL)
{ }
/**
* \brief ATL-defined initialization routine
*
* \sa OnConnection
*
*
* \return S_OK on success, a failed HRESULT to abort object creation
*
*
* I don't care for the trivial constructor/initialization routine
* approach. ATL does, however, and when in Rome...
*
* This method will create a hidden window for posting message to
* ourselves. See the documentation for OnConnection as to why this
* would be useful. The message window is destroyed in FinalRelease.
*
*
* \pre m_pParent has been initialized
*
*
*/
HRESULT CDSAddIn::FinalConstruct()
{
ATLTRACE2(atlTraceCOM, 2, "CDSAddIn::FinalConstruct\n");
ATLASSERT(NULL != m_pParent);
// Create our message window:
WNDCLASS wndclass;
::memset(&wndclass, 0, sizeof(WNDCLASS));
wndclass.lpfnWndProc = MsgWindowProc;
wndclass.hInstance = _AtlBaseModule.m_hInst;
wndclass.lpszClassName = WND_CLASS_NAME;
if (!::RegisterClass(&wndclass))
{
DWORD dwStatus = ::GetLastError();
if (ERROR_CLASS_ALREADY_EXISTS != dwStatus)
{
return HRESULT_FROM_WIN32(::GetLastError());
}
}
// We should concoct a unique Window name, in case multiple DevStudio
// instances are running simultaneously. We use this DLL's HINSTANCE.
ATLASSERT(_tcslen(WND_BASE_NAME) + 8 + 3 + 1 <= WND_NAME_STR_LEN);
TCHAR lpszWndName[WND_NAME_STR_LEN];
_sntprintf_s(lpszWndName, WND_NAME_STR_LEN, _T("%s%08x###"),
WND_BASE_NAME, HandleToUlong(_AtlBaseModule.m_hInst));
// Create our hidden, message-only Window:
m_hWnd = ::CreateWindow(WND_CLASS_NAME, // Window class
lpszWndName, // Window name
0U, // Window style
0, // x position
0, // y position
0, // width
0, // height
HWND_MESSAGE, // Parent Window
NULL, // Menu
_AtlBaseModule.m_hInst, // Owning instance
this); // Create params
if (NULL == m_hWnd)
{
return HRESULT_FROM_WIN32(::GetLastError());
}
ATLTRACE2(atlTraceWindowing, 3, "Created a message window with HWND"
" 0x%08x.\n", m_hWnd);
return S_OK;
}
void CDSAddIn::FinalRelease()
{
ATLTRACE2(atlTraceCOM, 2, "CDSAddIn::FinalRelease\n");
// Destroy *our* message window...
::DestroyWindow(m_hWnd);
// & if that was the last one...
if (!::FindWindow(WND_CLASS_NAME, NULL))
{
// de-register the WNDCLASS.
::UnregisterClass(WND_CLASS_NAME, _AtlBaseModule.m_hInst);
}
} // End CDSAddIn::FinalRelease.
void CDSAddIn::SetParam(CAddIn *pParent)
{
ATLASSERT(NULL != pParent);
m_pParent = pParent;
}
////////////////////////////////////////////////////////////////////////
// Interface ISupportsErrorInfo
STDMETHODIMP CDSAddIn::InterfaceSupportsErrorInfo(REFIID riid)
{
return InlineIsEqualGUID(IID_IDSAddIn, riid) ? S_OK : S_FALSE;
}
////////////////////////////////////////////////////////////////////////
// Interface IDSAddIn
/**
* \brief Connect to this AddIn
*
*
* \param pApp An IApplication reference on the DevStudio 6.0
* Application object
*
* \param vfFirstTime If this is the first time the AddIn has been
* loaded, DevStudio will set this to VARIANT_TRUE
*
* \param lCookie A cookie this AddIn will use to identify itself to
* DevStudio in assorted method calls
*
* \param pvfOnConnection On successful return, this parameter should be
* set to VARIANT_TRUE.
*
* \return S_OK on success, a stock HRESULT otherwise
*
*
* I've implemented this method in a different way from the code the
* AppWizard generates. First, we don't depend on the vfFirstTime
* parameter, leaving us the possibility of registering the AddIn at
* installation, so the user doesn't have to browse from Tools |
* Customize | Addins & Macro Files.
*
* This complicates toolbar creation, since a) we need to keep track
* ourselves whether or not it's been created, and b) calling
* AddCommandBarButton when vfFirstTime is \em not true will fail.
*
* I've solved problem a) by just writing down a boolean in the Registry.
* I've solved problem b) by posting a message to our hidden message
* window (it turns out that AddCommandBarButton will succeed if we call
* it outside the context of OnConnection).
*
* I learned how to do this from Nick Hodapp's article "Undocumented
* Visual C++" (http://www.codeproject.com/macro/openvc.asp).
*
*
*/
STDMETHODIMP CDSAddIn::OnConnection(IApplication *pApp,
VARIANT_BOOL vfFirstTime,
long lCookie,
VARIANT_BOOL *pvfOnConnection)
{
HRESULT hr = S_OK; // Eventual return value...
try
{
// Validate our parameters...
if (NULL == pApp) throw _com_error(E_INVALIDARG);
if (NULL == pvfOnConnection) throw _com_error(E_POINTER);
// & get to work -- assume failure until we know we're done:
*pvfOnConnection = VARIANT_FALSE;
ATLTRACE2(atlTraceHosting, 3, "DevStudio is connecting to VisEmacs "
"%s(pApp is 0x%08x & our cookie is 0x%08x).\n",
VARIANT_TRUE == vfFirstTime ? "for the first time " :
" ", pApp, lCookie);
// Store this for future reference. N.B. The assignment to a smart
// ptr implicitly calls AddRef.
m_pApp = pApp;
m_lCookie = lCookie;
// DevStudio wants a dispatch interface describing all the commands
// we implement. For now, I've implemented that interface on a
// separate COM component. However, given how peculiar that object
// is, I've chosen *not* to make it externally creatable:
HRESULT hr;
IUnknown *pOuterUnk = GetControllingUnknown();
// N.B. We don't keep a reference to the Commands object around once
// we've handed it off to DevStudio.
IDispatch *pCommands = NULL;
hr = CreateInstanceWithParamItf(pOuterUnk, m_pParent, &pCommands,
(CComObject<CDSCommands>**)NULL);
// 'pCommands' now has one outstanding reference...
if (FAILED(hr)) throw _com_error(hr);
m_pParent->SetApplicationObject(m_pApp);
// Ok -- we've initialized our data structures & we've got a command
// object. It's time to tell DevStudio about *us*. N.B. DevStudio
// will take out another reference:
LONG lInstance = HandleToLong(_AtlBaseModule.m_hInst);
hr = m_pApp->SetAddInInfo(lInstance, // DLL Instance
pCommands, // Dispinterface
IDB_DSTBMED, // Medium bmps
IDB_DSTBLRG, // Large bmps
m_lCookie); // Our cookie
pCommands->Release(); // No longer need it, since either
// DevStudio took out a reference, or we
// failed!
if (FAILED(hr)) throw _com_error(hr);
// Next, we sink the Application's Events:
hr = CreateInstanceWithParam(pOuterUnk, m_pParent, &m_pAppEvents);
if (FAILED(hr)) throw _com_error(hr);
m_pAppEvents->Connect(m_pApp);
// The only remaining step is to apprise DevStudio of our commands
// and their toolbar buttons. We add commands every time we're
// loaded, but we only want to create the toolbar once. The intent
// was that `vfFirstTime' would be used to distinguish this.
// However, since we "self-register", we may never be called with
// this flag set to VARIANT_TRUE. Hence, we note creation in the
// Registry.
bool fCreateTb = false;
if (VARIANT_TRUE == vfFirstTime)
{
// Either we never self-registered, and this really is the first
// time we've been loaded into DevStudio.
fCreateTb = true;
}
else
{
// We should have scribbled down the fact that we created the
// toolbar, if in fact we've done so. Look that up:
CRegKey hKey;
LONG lStatus = hKey.Create(HKEY_CURRENT_USER, SOFTWARE);
if (ERROR_SUCCESS != lStatus) throw _com_error(HRESULT_FROM_WIN32(lStatus));
lStatus = hKey.Create(hKey, KITTYLION);
if (ERROR_SUCCESS != lStatus) throw _com_error(HRESULT_FROM_WIN32(lStatus));
lStatus = hKey.Create(hKey, INCVERSION);
if (ERROR_SUCCESS != lStatus) throw _com_error(HRESULT_FROM_WIN32(lStatus));
DWORD dwCreated;
lStatus = hKey.QueryDWORDValue(VAL_CREATED_DSTB, dwCreated);
if (ERROR_FILE_NOT_FOUND == lStatus)
{
dwCreated = VAL_CREATED_DSTB_NO;
}
else if (ERROR_SUCCESS != lStatus)
{
throw _com_error(HRESULT_FROM_WIN32(lStatus));
}
fCreateTb = (dwCreated != VAL_CREATED_DSTB_YES);
}
// With that knowledge, we can finally add our commands:
AddCommands(fCreateTb);
// Indicate success to DevStudio:
*pvfOnConnection = VARIANT_TRUE;
}
catch (const _com_error &ex)
{
LPCTSTR lpszMsg = NULL;
_bstr_t bstrDsc = ex.Description();
if (0 != bstrDsc.length()) lpszMsg = bstrDsc;
else lpszMsg = ex.ErrorMessage();
hr = AtlReportError(CLSID_CoDSAddIn, lpszMsg, IID_IDSAddIn, ex.Error());
}
catch (const std::exception &ex)
{
hr = AtlReportError(CLSID_CoDSAddIn, ex.what(), IID_IDSAddIn, E_FAIL);
}
return hr;
}
/**
* \brief Disconnect from this AddIn
*
*
* \param vfLastTime This will be set to VARIANT_TRUE if the user is
* uninstalling the AddIn; if DevStudio is merely shutting down, it will
* be set to VARIANT_FALSE
*
* \return S_OK on success, a stock HRESULT else
*
*
*/
STDMETHODIMP CDSAddIn::OnDisconnection(VARIANT_BOOL /*vfLastTime*/)
{
HRESULT hr = S_OK; // Eventual return value...
try
{
m_pAppEvents->Disconnect(m_pApp);
m_pApp = NULL;
}
catch (const _com_error &ex)
{
LPCTSTR lpszMsg = NULL;
_bstr_t bstrDsc = ex.Description();
if (0 != bstrDsc.length()) lpszMsg = bstrDsc;
else lpszMsg = ex.ErrorMessage();
hr = AtlReportError(CLSID_CoDSAddIn, lpszMsg, IID_IDSAddIn, ex.Error());
}
catch (const std::exception &ex)
{
hr = AtlReportError(CLSID_CoDSAddIn, ex.what(), IID_IDSAddIn, E_FAIL);
}
return hr;
}
////////////////////////////////////////////////////////////////////////
// Toolbar & Command Management
/**
* \brief Add our commands to DevStudio
*
*
* \param fCreateTb The caller should set this to true in order to
* create a toolbar in addition to adding our commands
*
*
* Refer to the documentation for OnConnection for why we're posting a
* message to create the toolbar.
*
*
*/
void CDSAddIn::AddCommands(bool fCreateTb)
{
HRESULT hr = S_OK;
VARIANT_BOOL vfStatus;
hr = m_pApp->AddCommand(
CComBSTR(_T("IncVersion.IncVersion\n") // Cmd name
_T("Increment\n") // Button text
_T("Increment the Version\n") // Status bar text
_T("Increment the Version")), // Tooltip
CComBSTR(_T("IncVersion")), // Disp method name
0L, // Bitmap offset
m_lCookie, // DS-provided cookie
&vfStatus); // [out] status
if (FAILED(hr)) throw _com_error(hr);
if (VARIANT_FALSE == vfStatus)
{
ATLTRACE2(atlTraceHosting, 1, "Warning: DevStudio returned VARIANT"
"_FALSE when adding the IncVersion command.\n");
}
hr = m_pApp->AddCommand(
CComBSTR(_T("IncVersion.Configure\n") // Cmd name
_T("Configure the IncVersion AddIn\n") // Button text
_T("Configure\n") // Status bar text
_T("Configure")), // Tooltip
CComBSTR(_T("Configure")), // Disp method name
1L, // Bitmap offset
m_lCookie, // DS-provided cookie
&vfStatus); // [out] status
if (FAILED(hr)) throw _com_error(hr);
if (VARIANT_FALSE == vfStatus)
{
ATLTRACE2(atlTraceHosting, 1, "Warning: DevStudio returned VARIANT"
"_FALSE when adding the Configure command.\n");
}
// If we try to create our toolbar when DevStudio set `vfFirstTime' to
// VARIANT_FALSE in OnConnect, our attempt will fail. However, if we
// return from OnConnect, and *then* make the attempt, the call will
// succeed.
// We arrange for this to happen by posting a message to our hidden
// window & calling ourselves back later.
if (fCreateTb)
{
ATLASSERT(::IsWindow(m_hWnd));
::PostMessage(m_hWnd, WM_CREATETOOLBAR, 0U, 0L);
}
}
/**
* \brief Create the VisEmacs toolbar in DevStudio
*
*
* One of the annoying things about writing DevStudio AddIns is that we
* have no chance to name it -- the new toolbar will be called "Toolbar
* n". From Nick Hodapp "Undocumented Visual C++", I learned a cool
* little trick -- hook the creation of the toolbar window & change the
* window name.
*
*
*/
void CDSAddIn::CreateToolbar()
{
HHOOK hHook = ::SetWindowsHookEx(WH_CBT,
DsToolbarHook,
_AtlBaseModule.m_hInst,
::GetCurrentThreadId());
m_pApp->AddCommandBarButton(dsGlyph,
CComBSTR(_T("IncVersion.IncVersion")),
m_lCookie);
m_pApp->AddCommandBarButton(dsGlyph,
CComBSTR(_T("IncVersion.Configure")),
m_lCookie);
if (NULL != hHook) ::UnhookWindowsHookEx(hHook);
CRegKey hKey;
LONG lStatus = hKey.Create(HKEY_CURRENT_USER, SOFTWARE);
if (ERROR_SUCCESS != lStatus) throw _com_error(HRESULT_FROM_WIN32(lStatus));
lStatus = hKey.Create(hKey, KITTYLION);
if (ERROR_SUCCESS != lStatus) throw _com_error(HRESULT_FROM_WIN32(lStatus));
lStatus = hKey.Create(hKey, INCVERSION);
if (ERROR_SUCCESS != lStatus) throw _com_error(HRESULT_FROM_WIN32(lStatus));
lStatus = hKey.SetDWORDValue(VAL_CREATED_DSTB, VAL_CREATED_DSTB_YES);
if (ERROR_SUCCESS != lStatus)
{
throw _com_error(HRESULT_FROM_WIN32(lStatus));
}
}
LRESULT CALLBACK CDSAddIn::DsToolbarHook(int nCode,
WPARAM wParam,
LPARAM lParam)
{
if (HCBT_CREATEWND == nCode)
{
CBT_CREATEWNDA *pcw = (CBT_CREATEWNDA*)lParam;
if (pcw->lpcs->lpszName)
{
if (0 == strncmp(pcw->lpcs->lpszName, "Toolbar", 7))
{
strcpy((char*)pcw->lpcs->lpszName, "IncVersion");
}
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
LRESULT CALLBACK CDSAddIn::MsgWindowProc(HWND hWnd,
UINT nMsg,
WPARAM wParam,
LPARAM lParam)
{
LRESULT lResult;
CDSAddIn *pAddIn = NULL;
LONG lUserData = ::GetWindowLong(hWnd, GWL_USERDATA);
if (0L != lUserData)
{
pAddIn = reinterpret_cast<CDSAddIn*>(LongToPtr(lUserData));
}
try
{
switch (nMsg)
{
case WM_CREATE:
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
::SetWindowLong(hWnd, GWL_USERDATA, PtrToLong(pcs->lpCreateParams));
lResult = ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}
break;
case WM_CREATETOOLBAR:
{
pAddIn->CreateToolbar();
lResult = 0L;
}
break;
default:
lResult = ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}
}
catch (const _com_error &ex)
{
ATLTRACE2(atlTraceWindowing, 0, "WARNING: Unhandled COM exception "
"in CoDSAddIn's message window procedure: 0x%08x!\n",
ex.Error());
ex; // Shutup the compiler in Release builds...
lResult = -1L;
}
catch (const std::exception &ex)
{
ATLTRACE2(atlTraceWindowing, 0, "WARNING: Unhandled exception in C"
"oDSAddIn's message window procedure: %s!\n", ex.what());
ex; // Shutup the compiler in Release builds...
lResult = -1L;
}
return lResult;
} // End MsgWindowProc.
// Local Variables:
// fill-column: 72
// indent-tabs-mode: nil
// show-trailing-whitespace: t
// End:
// DSAddIn.cpp ends here.