You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1466 lines
42 KiB
1466 lines
42 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
//
|
|
// File: proppag_.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// private helper functions
|
|
|
|
BOOL CALLBACK EnumThreadWndProc(HWND hwnd, /* enumerated HWND */
|
|
LPARAM lParam /* pass a HWND* for return value*/ )
|
|
{
|
|
ASSERT(hwnd);
|
|
HWND hParentWnd = GetParent(hwnd);
|
|
// the main window of the MMC console should staitsfy this condition
|
|
if ( ((hParentWnd == GetDesktopWindow()) || (hParentWnd == NULL)) && IsWindowVisible(hwnd) )
|
|
{
|
|
HWND* pH = (HWND*)lParam;
|
|
*pH = hwnd;
|
|
return FALSE; // stop enumerating
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
HWND FindMMCMainWindow()
|
|
{
|
|
DWORD dwThreadID = ::GetCurrentThreadId();
|
|
ASSERT(dwThreadID != 0);
|
|
HWND hWnd = NULL;
|
|
EnumThreadWindows(dwThreadID, EnumThreadWndProc,(LPARAM)&hWnd);
|
|
|
|
ASSERT(hWnd != NULL);
|
|
return hWnd;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// CHiddenWndBase : Utility Hidden Window
|
|
|
|
|
|
BOOL CHiddenWndBase::Create(HWND hWndParent)
|
|
{
|
|
ASSERT(hWndParent == NULL || ::IsWindow(hWndParent));
|
|
RECT rcPos;
|
|
ZeroMemory(&rcPos, sizeof(RECT));
|
|
HWND hWnd = CWindowImpl<CHiddenWndBase>::Create(hWndParent,
|
|
rcPos, //RECT& rcPos,
|
|
NULL, //LPCTSTR szWindowName = NULL,
|
|
(hWndParent) ? WS_CHILD : WS_POPUP, //DWORD dwStyle = WS_CHILD | WS_VISIBLE,
|
|
0x0, //DWORD dwExStyle = 0,
|
|
0 //UINT nID = 0
|
|
);
|
|
return hWnd != NULL;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSheetWnd
|
|
|
|
const UINT CSheetWnd::s_SheetMessage = WM_USER + 100;
|
|
const UINT CSheetWnd::s_SelectPageMessage = WM_USER + 101;
|
|
|
|
LRESULT CSheetWnd::OnSheetMessage(UINT, WPARAM wParam, LPARAM lParam, BOOL&)
|
|
{
|
|
ASSERT(m_pHolder != NULL);
|
|
m_pHolder->OnSheetMessage(wParam,lParam);
|
|
return 1;
|
|
}
|
|
|
|
LRESULT CSheetWnd::OnSelectPageMessage(UINT, WPARAM wParam, LPARAM, BOOL&)
|
|
{
|
|
TRACE(_T("CSheetWnd::OnSelectPageMessage()\n"));
|
|
ASSERT(m_pHolder != NULL);
|
|
int nPage = m_pHolder->OnSelectPageMessage((long)wParam);
|
|
if (nPage >= 0)
|
|
{
|
|
// can use SendMessage() because the sheet has been created already
|
|
VERIFY(PropSheet_SetCurSel(m_pHolder->m_hSheetWindow, NULL, nPage));
|
|
}
|
|
::SetForegroundWindow(::GetParent(m_hWnd));
|
|
return 1;
|
|
}
|
|
|
|
LRESULT CSheetWnd::OnClose(UINT, WPARAM, LPARAM, BOOL&)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCloseDialogInfo
|
|
|
|
|
|
struct FIND_MSG_BOX_INFO
|
|
{
|
|
LPCTSTR lpszTitle;
|
|
HWND hWnd;
|
|
HWND hWndParent;
|
|
};
|
|
|
|
BOOL CALLBACK EnumMessageBoxProc(HWND hwnd, LPARAM lParam)
|
|
{
|
|
static const size_t BuffSizeInCharacters = 256;
|
|
|
|
FIND_MSG_BOX_INFO* pInfo = (FIND_MSG_BOX_INFO*)lParam;
|
|
if (::GetParent(hwnd) != pInfo->hWndParent)
|
|
return TRUE;
|
|
|
|
TCHAR szTitle[BuffSizeInCharacters] = {0};
|
|
::GetWindowText(hwnd, szTitle, BuffSizeInCharacters);
|
|
TRACE(_T("Title <%s>\n"), szTitle);
|
|
|
|
if (_wcsnicmp(szTitle, pInfo->lpszTitle, BuffSizeInCharacters) == 0)
|
|
{
|
|
pInfo->hWnd = hwnd;
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HWND FindMessageBox(LPCTSTR lpszTitle, HWND hWndParent)
|
|
{
|
|
FIND_MSG_BOX_INFO info;
|
|
info.hWndParent = hWndParent;
|
|
info.lpszTitle = lpszTitle;
|
|
info.hWnd = NULL;
|
|
EnumWindows(EnumMessageBoxProc, (LPARAM)&info);
|
|
if (info.hWnd != NULL)
|
|
return info.hWnd;
|
|
return NULL;
|
|
}
|
|
|
|
BOOL CCloseDialogInfo::CloseMessageBox(HWND hWndParent)
|
|
{
|
|
BOOL bClosed = FALSE;
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
LPCTSTR lpszMsgBoxTitle = AfxGetApp()->m_pszAppName;
|
|
HWND hWndMessageBox = FindMessageBox(lpszMsgBoxTitle, hWndParent);
|
|
if (hWndMessageBox != NULL)
|
|
{
|
|
// figure out if there is a cancel button or not
|
|
HWND hWndCtrl = ::GetDlgItem(hWndMessageBox, IDCANCEL);
|
|
if (hWndCtrl != NULL)
|
|
{
|
|
VERIFY(::SendMessage(hWndMessageBox, WM_CLOSE, 0, 0) == 0);
|
|
bClosed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// does it have just the OK button?
|
|
hWndCtrl = ::GetDlgItem(hWndMessageBox, IDOK);
|
|
if (hWndCtrl != NULL)
|
|
{
|
|
VERIFY(::SendMessage(hWndMessageBox, WM_COMMAND, IDOK, 0) == 0);
|
|
bClosed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// does it have a NO button?
|
|
hWndCtrl = ::GetDlgItem(hWndMessageBox, IDNO);
|
|
if (hWndCtrl != NULL)
|
|
{
|
|
VERIFY(::SendMessage(hWndMessageBox, WM_COMMAND, IDNO, 0) == 0);
|
|
bClosed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bClosed;
|
|
}
|
|
|
|
BOOL CCloseDialogInfo::CloseDialog(BOOL bCheckForMsgBox)
|
|
{
|
|
if (bCheckForMsgBox)
|
|
CloseMessageBox(m_hWnd);
|
|
return (::SendMessage(m_hWnd, WM_CLOSE, 0, 0) == 0);
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPropertyPageHolderBase
|
|
|
|
CPropertyPageHolderBase::CPropertyPageHolderBase(CContainerNode* pContNode, CTreeNode* pNode,
|
|
CComponentDataObject* pComponentData)
|
|
{
|
|
m_szSheetTitle = (LPCWSTR)NULL;
|
|
m_pDummySheet = NULL;
|
|
|
|
// default setting for a self deleting modeless property sheet,
|
|
// automatically deleting all the pages
|
|
m_bWizardMode = FALSE;
|
|
m_bAutoDelete = TRUE;
|
|
m_bAutoDeletePages = TRUE;
|
|
|
|
m_forceContextHelpButton = useDefault;
|
|
|
|
m_pContHolder = NULL;
|
|
m_nCreatedCount = 0;
|
|
m_hSheetWindow = NULL;
|
|
m_pSheetWnd = NULL;
|
|
m_nStartPageCode = -1; // not set
|
|
m_hConsoleHandle = 0;
|
|
m_hEventHandle = NULL;
|
|
m_pSheetCallback = NULL;
|
|
|
|
// setup from arguments
|
|
// For tasks in can be null ASSERT(pContNode != NULL); // must always have a valid container node to refer to
|
|
m_pContNode = pContNode;
|
|
ASSERT((pNode == NULL) || (pNode->GetContainer() == m_pContNode) );
|
|
m_pNode = pNode;
|
|
ASSERT(pComponentData != NULL);
|
|
m_pComponentData = pComponentData;
|
|
|
|
m_hMainWnd = NULL;
|
|
LPCONSOLE pConsole = m_pComponentData->GetConsole();
|
|
if (pConsole != NULL)
|
|
{
|
|
pConsole->GetMainWindow(&m_hMainWnd);
|
|
}
|
|
|
|
m_dwLastErr = 0x0;
|
|
m_pPropChangePage = NULL;
|
|
m_pWatermarkInfo = NULL;
|
|
}
|
|
|
|
CPropertyPageHolderBase::~CPropertyPageHolderBase()
|
|
{
|
|
FinalDestruct();
|
|
ASSERT(m_pSheetWnd == NULL);
|
|
SAFE_RELEASE(m_pSheetCallback);
|
|
if (m_hEventHandle != NULL)
|
|
{
|
|
VERIFY(::CloseHandle(m_hEventHandle));
|
|
m_hEventHandle = NULL;
|
|
}
|
|
if (m_pDummySheet != NULL)
|
|
delete m_pDummySheet;
|
|
}
|
|
|
|
void CPropertyPageHolderBase::Attach(CPropertyPageHolderBase* pContHolder)
|
|
{
|
|
ASSERT( (m_pContHolder == NULL) && (pContHolder != NULL) );
|
|
m_pContHolder = pContHolder;
|
|
m_bWizardMode = pContHolder->IsWizardMode();
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::EnableSheetControl(UINT nCtrlID, BOOL bEnable)
|
|
{
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
return m_pContHolder->EnableSheetControl(nCtrlID, bEnable);
|
|
}
|
|
ASSERT(::IsWindow(m_hSheetWindow));
|
|
HWND hWndCtrl = ::GetDlgItem(m_hSheetWindow, nCtrlID);
|
|
if (hWndCtrl == NULL)
|
|
return FALSE;
|
|
return ::EnableWindow(hWndCtrl, bEnable);
|
|
}
|
|
|
|
HRESULT CPropertyPageHolderBase::CreateModelessSheet(CTreeNode* pNode, CComponentDataObject* pComponentData)
|
|
{
|
|
ASSERT(pNode != NULL);
|
|
ASSERT(pComponentData != NULL);
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// get an interface to a sheet provider
|
|
IPropertySheetProvider* pSheetProvider;
|
|
HRESULT hr = pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetProvider,(void**)&pSheetProvider);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pSheetProvider != NULL);
|
|
|
|
// get an interface to a sheet callback
|
|
IPropertySheetCallback* pSheetCallback;
|
|
hr = pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetCallback,(void**)&pSheetCallback);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pSheetCallback != NULL);
|
|
|
|
// create a data object for this node
|
|
IDataObject* pDataObject;
|
|
hr = pComponentData->QueryDataObject((MMC_COOKIE)pNode, CCT_SCOPE, &pDataObject);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pDataObject != NULL);
|
|
|
|
// get a sheet
|
|
hr = pSheetProvider->CreatePropertySheet(_T("SHEET TITLE"), TRUE, (MMC_COOKIE)pNode, pDataObject, 0x0 /*dwOptions*/);
|
|
ASSERT(SUCCEEDED(hr));
|
|
pDataObject->Release();
|
|
|
|
HWND hWnd = NULL;
|
|
hr = pComponentData->GetConsole()->GetMainWindow(&hWnd);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(hWnd == ::FindMMCMainWindow());
|
|
|
|
IUnknown* pUnkComponentData = pComponentData->GetUnknown(); // no addref
|
|
hr = pSheetProvider->AddPrimaryPages(pUnkComponentData,
|
|
TRUE /*bCreateHandle*/,
|
|
hWnd,
|
|
TRUE /* bScopePane*/);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
hr = pSheetProvider->Show(reinterpret_cast<LONG_PTR>(hWnd), 0);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// final interface release
|
|
pSheetProvider->Release();
|
|
pSheetCallback->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT CPropertyPageHolderBase::CreateModelessSheet(CTreeNode* pCookieNode)
|
|
{
|
|
ASSERT(!IsWizardMode());
|
|
ASSERT(m_pContHolder == NULL);
|
|
ASSERT(m_pComponentData != NULL);
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// get an interface to a sheet provider
|
|
IPropertySheetProvider* pSheetProvider;
|
|
HRESULT hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetProvider,(void**)&pSheetProvider);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pSheetProvider != NULL);
|
|
|
|
// get an interface to a sheet callback
|
|
IPropertySheetCallback* pSheetCallback;
|
|
hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetCallback,(void**)&pSheetCallback);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pSheetCallback != NULL);
|
|
|
|
// create a data object for this node
|
|
IDataObject* pDataObject;
|
|
hr = m_pComponentData->QueryDataObject((MMC_COOKIE)pCookieNode, CCT_SCOPE, &pDataObject);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pDataObject != NULL);
|
|
|
|
// get a sheet
|
|
hr = pSheetProvider->CreatePropertySheet(m_szSheetTitle, TRUE, (MMC_COOKIE)pCookieNode, pDataObject, 0x0 /*dwOptions*/);
|
|
ASSERT(SUCCEEDED(hr));
|
|
pDataObject->Release();
|
|
|
|
HWND hWnd = GetMainWindow();
|
|
ASSERT(hWnd == ::FindMMCMainWindow());
|
|
|
|
IUnknown* pUnkComponentData = m_pComponentData->GetUnknown(); // no addref
|
|
hr = pSheetProvider->AddPrimaryPages(pUnkComponentData,
|
|
TRUE /*bCreateHandle*/,
|
|
NULL /*hWnd*/,
|
|
FALSE /* bScopePane*/);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
hr = pSheetProvider->Show(reinterpret_cast<LONG_PTR>(hWnd), 0);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// final interface release
|
|
pSheetProvider->Release();
|
|
pSheetCallback->Release();
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CPropertyPageHolderBase::CreateModelessSheet(LPPROPERTYSHEETCALLBACK pSheetCallback, LONG_PTR hConsoleHandle)
|
|
{
|
|
ASSERT(m_pContHolder == NULL);
|
|
ASSERT(pSheetCallback != NULL);
|
|
ASSERT(m_pSheetCallback == NULL);
|
|
|
|
//
|
|
// REVIEW_JEFFJON : seems to be NULL when called from CComponentDataObject::CreatePropertySheet()
|
|
//
|
|
m_hConsoleHandle = hConsoleHandle;
|
|
|
|
m_bWizardMode = FALSE; // we go modeless
|
|
ASSERT(m_pNode != NULL);
|
|
CPropertyPageHolderTable* pPPHTable = m_pComponentData->GetPropertyPageHolderTable();
|
|
ASSERT(pPPHTable != NULL);
|
|
|
|
// add the property sheet holder to the holder table
|
|
pPPHTable->Add(this);
|
|
// notify the node it has a sheet up
|
|
m_pNode->OnCreateSheet();
|
|
|
|
// temporarily attach the sheet callback to this object to add pages
|
|
// do not addref, we will not hold on to it;
|
|
m_pSheetCallback = pSheetCallback;
|
|
|
|
HRESULT hr = AddAllPagesToSheet();
|
|
m_pSheetCallback = NULL; // detach
|
|
return hr;
|
|
}
|
|
|
|
void CPropertyPageHolderBase::SetWatermarkInfo(CWatermarkInfo* pWatermarkInfo)
|
|
{
|
|
ASSERT(m_pWatermarkInfo == NULL);
|
|
ASSERT(pWatermarkInfo != NULL);
|
|
}
|
|
|
|
HRESULT CPropertyPageHolderBase::DoModalWizard()
|
|
{
|
|
ASSERT(m_pContHolder == NULL);
|
|
ASSERT(m_pComponentData != NULL);
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
m_bWizardMode = TRUE;
|
|
|
|
// get an interface to a sheet provider
|
|
IPropertySheetProvider* pSheetProvider;
|
|
HRESULT hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetProvider,(void**)&pSheetProvider);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pSheetProvider != NULL);
|
|
|
|
// get an interface to a sheet callback
|
|
IPropertySheetCallback* pSheetCallback;
|
|
hr = m_pComponentData->GetConsole()->QueryInterface(IID_IPropertySheetCallback,(void**)&pSheetCallback);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pSheetCallback != NULL);
|
|
m_pSheetCallback = pSheetCallback; // save to add/remove pages
|
|
|
|
// Create a dummy data object. AddPrimaryPages will call
|
|
// IextendPropertySheet2::QueryPagesFor() and
|
|
// IextendPropertySheet2::CreatePropertyPages()
|
|
// that will ignore the un-initialized data object
|
|
MMC_COOKIE cookie = -1;
|
|
DATA_OBJECT_TYPES type = CCT_UNINITIALIZED;
|
|
IDataObject* pDataObject;
|
|
hr = m_pComponentData->QueryDataObject(cookie, type, &pDataObject);
|
|
ASSERT(SUCCEEDED(hr));
|
|
ASSERT(pDataObject != NULL);
|
|
|
|
|
|
// Switch Watermark information, AddPrimaryPages will call
|
|
// IextendPropertySheet2::GetWatermarks()
|
|
CWatermarkInfo* pOldWatermarkInfo = NULL;
|
|
if (m_pWatermarkInfo != NULL)
|
|
pOldWatermarkInfo = m_pComponentData->SetWatermarkInfo(m_pWatermarkInfo);
|
|
|
|
// create sheet
|
|
hr = pSheetProvider->CreatePropertySheet( m_szSheetTitle, FALSE /* wizard*/,
|
|
(MMC_COOKIE)cookie, pDataObject, MMC_PSO_NEWWIZARDTYPE /*dwOptions*/);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// add pages to sheet
|
|
hr = AddAllPagesToSheet();
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// add pages
|
|
hr = pSheetProvider->AddPrimaryPages((IExtendPropertySheet2*)m_pComponentData, FALSE, NULL,FALSE);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
// restore the old watermark info
|
|
if (pOldWatermarkInfo != NULL)
|
|
m_pComponentData->SetWatermarkInfo(pOldWatermarkInfo);
|
|
|
|
// for further dynamic page manipulation, don't use the Console's sheet callback interface
|
|
// but resurt to the Win32 API's
|
|
m_pSheetCallback->Release();
|
|
m_pSheetCallback = NULL;
|
|
|
|
// show the modal wizard
|
|
HWND hWnd = GetMainWindow();
|
|
ASSERT(hWnd != NULL);
|
|
hr = pSheetProvider->Show((LONG_PTR)hWnd, 0);
|
|
ASSERT(SUCCEEDED(hr));
|
|
|
|
pSheetProvider->Release();
|
|
pDataObject->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
INT_PTR CPropertyPageHolderBase::DoModalDialog(LPCTSTR pszCaption)
|
|
{
|
|
ASSERT(m_pDummySheet == NULL);
|
|
m_bWizardMode = TRUE;
|
|
m_bAutoDelete = FALSE; // use on the stack
|
|
m_pDummySheet = new CPropertySheet();
|
|
m_pDummySheet->m_psh.dwFlags |= PSH_NOAPPLYNOW;
|
|
m_pDummySheet->m_psh.pszCaption = pszCaption;
|
|
VERIFY(SUCCEEDED(AddAllPagesToSheet()));
|
|
return m_pDummySheet->DoModal();
|
|
}
|
|
|
|
void CPropertyPageHolderBase::SetSheetWindow(HWND hSheetWindow)
|
|
{
|
|
ASSERT(hSheetWindow != NULL);
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
// we will use the HWND of the parent holder
|
|
m_pContHolder->SetSheetWindow(hSheetWindow);
|
|
return;
|
|
}
|
|
ASSERT( (m_hSheetWindow == NULL) || ((m_hSheetWindow == hSheetWindow)) );
|
|
m_hSheetWindow = hSheetWindow;
|
|
|
|
if (IsWizardMode())
|
|
{
|
|
if (m_forceContextHelpButton != useDefault)
|
|
{
|
|
DWORD dwStyle = ::GetWindowLong(m_hSheetWindow, GWL_EXSTYLE);
|
|
if (m_forceContextHelpButton == forceOn)
|
|
{
|
|
dwStyle |= WS_EX_CONTEXTHELP; // force the [?] button
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_forceContextHelpButton == forceOff);
|
|
dwStyle &= ~WS_EX_CONTEXTHELP; // get rid of the [?] button
|
|
}
|
|
::SetWindowLong(m_hSheetWindow, GWL_EXSTYLE, dwStyle);
|
|
}
|
|
|
|
if (m_pDummySheet != NULL)
|
|
{
|
|
VERIFY(PushDialogHWnd(m_hSheetWindow));
|
|
}
|
|
return;
|
|
}
|
|
// hook up hidden window only when in sheet mode
|
|
if(m_pSheetWnd == NULL)
|
|
{
|
|
CWinApp* pApp = AfxGetApp();
|
|
ASSERT(pApp);
|
|
ASSERT(!IsWizardMode());
|
|
m_pSheetWnd = new CSheetWnd(this);
|
|
VERIFY(m_pSheetWnd->Create(hSheetWindow));
|
|
|
|
ASSERT(::GetParent(m_pSheetWnd->m_hWnd) == hSheetWindow);
|
|
GetComponentData()->OnCreateSheet(this, m_pSheetWnd->m_hWnd);
|
|
if (m_nStartPageCode > -1)
|
|
{
|
|
// we do a PostMessage() because we are in to middle of a page creation
|
|
// and MFC does not digest this
|
|
::PostMessage(m_hSheetWindow, PSM_SETCURSEL, OnSelectPageMessage(m_nStartPageCode), NULL);
|
|
}
|
|
|
|
// if needed, set the wizard title
|
|
if (!m_szSheetTitle.IsEmpty())
|
|
{
|
|
::SetWindowText(m_hSheetWindow, (LPCWSTR)m_szSheetTitle);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPropertyPageHolderBase::SetSheetTitle(LPCWSTR lpszSheetTitle)
|
|
{
|
|
ASSERT(!IsWizardMode());
|
|
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
// defer to parent holder
|
|
m_pContHolder->SetSheetTitle(lpszSheetTitle);
|
|
return;
|
|
}
|
|
m_szSheetTitle = lpszSheetTitle;
|
|
|
|
// if the sheet has been created already, set right away
|
|
if (m_hSheetWindow != NULL && !m_szSheetTitle.IsEmpty())
|
|
{
|
|
::SetWindowText(m_hSheetWindow, (LPCWSTR)m_szSheetTitle);
|
|
}
|
|
}
|
|
|
|
void CPropertyPageHolderBase::SetSheetTitle(UINT nStringFmtID, CTreeNode* pNode)
|
|
{
|
|
ASSERT(!IsWizardMode());
|
|
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
// defer to parent holder
|
|
m_pContHolder->SetSheetTitle(nStringFmtID, pNode);
|
|
return;
|
|
}
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CString szFmt;
|
|
VERIFY(szFmt.LoadString(nStringFmtID));
|
|
m_szSheetTitle.Format((LPCWSTR)szFmt, pNode->GetDisplayName());
|
|
|
|
// if the sheet has been created already, set right away
|
|
if (m_hSheetWindow != NULL && !m_szSheetTitle.IsEmpty())
|
|
{
|
|
::SetWindowText(m_hSheetWindow, (LPCWSTR)m_szSheetTitle);
|
|
}
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderBase::AddRef()
|
|
{
|
|
if(m_pContHolder != NULL)
|
|
{
|
|
m_pContHolder->AddRef();
|
|
return;
|
|
}
|
|
m_nCreatedCount++;
|
|
}
|
|
void CPropertyPageHolderBase::Release()
|
|
{
|
|
if(m_pContHolder != NULL)
|
|
{
|
|
m_pContHolder->Release();
|
|
return;
|
|
}
|
|
m_nCreatedCount--;
|
|
if (m_nCreatedCount > 0)
|
|
return;
|
|
|
|
if(IsWizardMode())
|
|
{
|
|
if (m_pDummySheet != NULL)
|
|
VERIFY(PopDialogHWnd());
|
|
}
|
|
else
|
|
{
|
|
// hidden window created only in sheet mode
|
|
if (m_pSheetWnd != NULL)
|
|
{
|
|
if (m_pSheetWnd->m_hWnd != NULL)
|
|
m_pSheetWnd->DestroyWindow();
|
|
}
|
|
}
|
|
if (m_bAutoDelete)
|
|
delete this;
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::IsWizardMode()
|
|
{
|
|
if(m_pContHolder != NULL)
|
|
{
|
|
return m_pContHolder->IsWizardMode();
|
|
}
|
|
return m_bWizardMode;
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::IsModalSheet()
|
|
{
|
|
if(m_pContHolder != NULL)
|
|
{
|
|
return m_pContHolder->IsModalSheet();
|
|
}
|
|
return m_pDummySheet != NULL;
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderBase::ForceDestroy()
|
|
{
|
|
ASSERT(!IsWizardMode()); // should never occur on modal wizard
|
|
|
|
// contained by other holder
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
ASSERT(!m_bAutoDelete); // container responsible for deleting this holder
|
|
m_pContHolder->ForceDestroy();
|
|
return;
|
|
}
|
|
|
|
// this is the primary holder
|
|
ASSERT(m_bAutoDelete); // should be self deleting sheet
|
|
HWND hSheetWindow = m_hSheetWindow;
|
|
if (hSheetWindow != NULL)
|
|
{
|
|
ASSERT(::IsWindow(hSheetWindow));
|
|
// this message will cause the sheet to close all the pages,
|
|
// and eventually the destruction of "this"
|
|
VERIFY(::PostMessage(hSheetWindow, WM_COMMAND, IDCANCEL, 0L) != 0);
|
|
}
|
|
else
|
|
{
|
|
// explicitely delete "this", there is no sheet created
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
DWORD CPropertyPageHolderBase::NotifyConsole(CPropertyPageBase* pPage)
|
|
{
|
|
|
|
if(m_pContHolder != NULL)
|
|
{
|
|
return m_pContHolder->NotifyConsole(pPage);
|
|
}
|
|
|
|
ASSERT(m_pNode != NULL);
|
|
if (IsWizardMode())
|
|
{
|
|
ASSERT(m_hConsoleHandle == NULL);
|
|
return 0x0;
|
|
}
|
|
|
|
m_pPropChangePage = pPage; // to pass to the main thread
|
|
m_dwLastErr = 0x0;
|
|
|
|
if (m_hEventHandle == NULL)
|
|
{
|
|
// REVIEWED-2002/03/08-JeffJon-Squatting isn't an issue here because this is not a
|
|
// named event
|
|
|
|
m_hEventHandle = ::CreateEvent(NULL,TRUE /*bManualReset*/,FALSE /*signalled*/, NULL);
|
|
ASSERT(m_hEventHandle != NULL);
|
|
}
|
|
|
|
if (m_hConsoleHandle != NULL)
|
|
{
|
|
MMCPropertyChangeNotify(m_hConsoleHandle, reinterpret_cast<LPARAM>(this));
|
|
|
|
DWORD dwRet;
|
|
do
|
|
{
|
|
ASSERT(::IsWindow(m_hSheetWindow));
|
|
dwRet = MsgWaitForMultipleObjects(1,&m_hEventHandle,FALSE,INFINITE, QS_SENDMESSAGE);
|
|
if(dwRet == (WAIT_OBJECT_0+1))
|
|
{
|
|
MSG tempMSG;
|
|
PeekMessage(&tempMSG,m_hSheetWindow,0,0,PM_NOREMOVE);
|
|
}
|
|
}
|
|
while(dwRet == (WAIT_OBJECT_0+1));
|
|
}
|
|
|
|
VERIFY(0 != ::ResetEvent(m_hEventHandle));
|
|
|
|
m_pPropChangePage = NULL; // reset
|
|
return m_dwLastErr;
|
|
}
|
|
|
|
void CPropertyPageHolderBase::AcknowledgeNotify()
|
|
{
|
|
if(m_pContHolder != NULL)
|
|
{
|
|
m_pContHolder->AcknowledgeNotify();
|
|
return;
|
|
}
|
|
ASSERT(!IsWizardMode());
|
|
ASSERT(m_hEventHandle != NULL);
|
|
//TRACE(_T("before SetEvent\n"));
|
|
VERIFY(0 != ::SetEvent(m_hEventHandle));
|
|
//TRACE(_T("after SetEvent\n"));
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::OnPropertyChange(BOOL bScopePane, long* pChangeMask)
|
|
{
|
|
ASSERT(!IsWizardMode());
|
|
CPropertyPageBase* pPage = GetPropChangePage();
|
|
if (pPage == NULL)
|
|
return FALSE;
|
|
return pPage->OnPropertyChange(bScopePane, pChangeMask);
|
|
}
|
|
|
|
|
|
BOOL CPropertyPageHolderBase::SetWizardButtons(DWORD dwFlags)
|
|
{
|
|
ASSERT(IsWizardMode());
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
ASSERT(m_hSheetWindow == NULL);
|
|
return m_pContHolder->SetWizardButtons(dwFlags);
|
|
}
|
|
ASSERT(::IsWindow(m_hSheetWindow));
|
|
return (BOOL)SendMessage(m_hSheetWindow, PSM_SETWIZBUTTONS, 0, dwFlags);
|
|
}
|
|
|
|
HRESULT CPropertyPageHolderBase::AddPageToSheet(CPropertyPageBase* pPage)
|
|
{
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
ASSERT(m_hSheetWindow == NULL);
|
|
return m_pContHolder->AddPageToSheet(pPage);
|
|
}
|
|
|
|
CWinApp* pApp = AfxGetApp();
|
|
ASSERT(pApp);
|
|
if (m_pSheetCallback != NULL)
|
|
{
|
|
VERIFY(SUCCEEDED(MMCPropPageCallback((void*)(&pPage->m_psp97))));
|
|
}
|
|
|
|
HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&pPage->m_psp97);
|
|
if (hPage == NULL)
|
|
return E_UNEXPECTED;
|
|
pPage->m_hPage = hPage;
|
|
if (m_pSheetCallback != NULL)
|
|
return m_pSheetCallback->AddPage(hPage);
|
|
else if (m_pDummySheet != NULL)
|
|
{
|
|
m_pDummySheet->AddPage(pPage);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(::IsWindow(m_hSheetWindow));
|
|
return PropSheet_AddPage(m_hSheetWindow, hPage) ? S_OK : E_FAIL;
|
|
}
|
|
}
|
|
|
|
HRESULT CPropertyPageHolderBase::AddPageToSheetRaw(HPROPSHEETPAGE hPage)
|
|
{
|
|
ASSERT(m_pSheetCallback != NULL);
|
|
if ((hPage == NULL) || (m_pSheetCallback == NULL))
|
|
return E_INVALIDARG;
|
|
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
ASSERT(m_hSheetWindow == NULL);
|
|
return m_pContHolder->AddPageToSheetRaw(hPage);
|
|
}
|
|
|
|
// assume this is not a n MFC property page
|
|
return m_pSheetCallback->AddPage(hPage);
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT CPropertyPageHolderBase::RemovePageFromSheet(CPropertyPageBase* pPage)
|
|
{
|
|
if (m_pContHolder != NULL)
|
|
{
|
|
ASSERT(m_hSheetWindow == NULL);
|
|
return m_pContHolder->RemovePageFromSheet(pPage);
|
|
}
|
|
|
|
ASSERT(pPage->m_hPage != NULL);
|
|
if (m_pSheetCallback != NULL)
|
|
return m_pSheetCallback->RemovePage(pPage->m_hPage);
|
|
else
|
|
{
|
|
ASSERT(::IsWindow(m_hSheetWindow));
|
|
PropSheet_RemovePage(m_hSheetWindow, 0, pPage->m_hPage); // returns void
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
HRESULT CPropertyPageHolderBase::AddAllPagesToSheet()
|
|
{
|
|
POSITION pos;
|
|
int nPage = 0;
|
|
HRESULT hr = OnAddPage(nPage, NULL); // zero means add before the first
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
for( pos = m_pageList.GetHeadPosition(); pos != NULL; )
|
|
{
|
|
CPropertyPageBase* pPropPage = m_pageList.GetNext(pos);
|
|
hr = AddPageToSheet(pPropPage);
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
nPage++;
|
|
hr = OnAddPage(nPage, pPropPage); // get called on nPage == 1,2, n-1
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
// add after the last
|
|
return OnAddPage(-1, NULL); // -1 means
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderBase::AddPageToList(CPropertyPageBase* pPage)
|
|
{
|
|
ASSERT(pPage != NULL);
|
|
pPage->SetHolder(this);
|
|
m_pageList.AddTail(pPage);
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::RemovePageFromList(CPropertyPageBase* pPage, BOOL bDeleteObject)
|
|
{
|
|
ASSERT(pPage != NULL);
|
|
POSITION pos = m_pageList.Find(pPage);
|
|
if (pos == NULL)
|
|
return FALSE;
|
|
m_pageList.RemoveAt(pos);
|
|
if (bDeleteObject)
|
|
delete pPage;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderBase::DeleteAllPages()
|
|
{
|
|
if (!m_bAutoDeletePages)
|
|
return;
|
|
// assume all pages out of the heap
|
|
while (!m_pageList.IsEmpty())
|
|
{
|
|
delete m_pageList.RemoveTail();
|
|
}
|
|
}
|
|
|
|
void CPropertyPageHolderBase::FinalDestruct()
|
|
{
|
|
DeleteAllPages();
|
|
if (IsWizardMode() || (m_pContHolder != NULL))
|
|
return;
|
|
|
|
if (m_hConsoleHandle != NULL)
|
|
{
|
|
MMCFreeNotifyHandle(m_hConsoleHandle);
|
|
}
|
|
|
|
// tell the component data object that the sheet is going away
|
|
GetComponentData()->OnDeleteSheet(this,m_pNode);
|
|
|
|
if (m_pSheetWnd != NULL)
|
|
{
|
|
delete m_pSheetWnd;
|
|
m_pSheetWnd = NULL;
|
|
}
|
|
ASSERT(m_dlgInfoStack.IsEmpty());
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::PushDialogHWnd(HWND hWndModalDlg)
|
|
{
|
|
return m_dlgInfoStack.Push(hWndModalDlg, 0x0);
|
|
}
|
|
|
|
BOOL CPropertyPageHolderBase::PopDialogHWnd()
|
|
{
|
|
return m_dlgInfoStack.Pop();
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderBase::CloseModalDialogs(HWND hWndPage)
|
|
{
|
|
m_dlgInfoStack.ForceClose(hWndPage);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPropertyPageBase
|
|
|
|
BEGIN_MESSAGE_MAP(CPropertyPageBase, CPropertyPage)
|
|
ON_WM_CREATE()
|
|
ON_WM_DESTROY()
|
|
ON_WM_CONTEXTMENU()
|
|
ON_MESSAGE(WM_HELP, OnHelp)
|
|
ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
CPropertyPageBase::CPropertyPageBase(UINT nIDTemplate,
|
|
UINT nIDCaption) :
|
|
CPropertyPage(nIDTemplate, nIDCaption)
|
|
{
|
|
m_hPage = NULL;
|
|
m_pPageHolder = NULL;
|
|
m_bIsDirty = FALSE;
|
|
m_nPrevPageID = 0;
|
|
|
|
// hack to have new struct size with old MFC and new NT 5.0 headers
|
|
ZeroMemory(&m_psp97, sizeof(PROPSHEETPAGE));
|
|
|
|
// REVIEWED-2002/03/08-JeffJon-This is acceptable usage
|
|
|
|
memcpy(&m_psp97, &m_psp, m_psp.dwSize);
|
|
m_psp97.dwSize = sizeof(PROPSHEETPAGE);
|
|
}
|
|
|
|
|
|
CPropertyPageBase::~CPropertyPageBase()
|
|
{
|
|
}
|
|
|
|
int CPropertyPageBase::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
m_pPageHolder->AddRef();
|
|
int res = CPropertyPage::OnCreate(lpCreateStruct);
|
|
ASSERT(res == 0);
|
|
ASSERT(m_hWnd != NULL);
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
HWND hParent = ::GetParent(m_hWnd);
|
|
ASSERT(hParent);
|
|
m_pPageHolder->SetSheetWindow(hParent);
|
|
return res;
|
|
}
|
|
|
|
void CPropertyPageBase::OnDestroy()
|
|
{
|
|
ASSERT(m_hWnd != NULL);
|
|
CPropertyPage::OnDestroy();
|
|
m_pPageHolder->Release();
|
|
}
|
|
|
|
void CPropertyPageBase::OnWhatsThis()
|
|
{
|
|
//
|
|
// Display context help for a control
|
|
//
|
|
if ( m_hWndWhatsThis )
|
|
{
|
|
//
|
|
// Build our own HELPINFO struct to pass to the underlying
|
|
// CS help functions built into the framework
|
|
//
|
|
int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
|
|
HELPINFO helpInfo;
|
|
ZeroMemory(&helpInfo, sizeof(HELPINFO));
|
|
helpInfo.cbSize = sizeof(HELPINFO);
|
|
helpInfo.hItemHandle = m_hWndWhatsThis;
|
|
helpInfo.iCtrlId = iCtrlID;
|
|
|
|
m_pPageHolder->GetComponentData()->OnDialogContextHelp(m_nIDHelp, &helpInfo);
|
|
}
|
|
}
|
|
|
|
BOOL CPropertyPageBase::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
|
|
{
|
|
const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
|
|
|
|
if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
|
|
{
|
|
//
|
|
// Display context help for a control
|
|
//
|
|
m_pPageHolder->GetComponentData()->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CPropertyPageBase::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
|
|
{
|
|
//
|
|
// point is in screen coordinates
|
|
//
|
|
|
|
CMenu bar;
|
|
if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
|
|
{
|
|
CMenu& popup = *bar.GetSubMenu (0);
|
|
ASSERT(popup.m_hMenu);
|
|
|
|
if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
|
|
point.x, // in screen coordinates
|
|
point.y, // in screen coordinates
|
|
this) ) // route commands through main window
|
|
{
|
|
m_hWndWhatsThis = 0;
|
|
ScreenToClient (&point);
|
|
CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
|
|
CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
|
|
if ( pChild )
|
|
{
|
|
m_hWndWhatsThis = pChild->m_hWnd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CPropertyPageBase::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
NMHDR* hdr = reinterpret_cast<NMHDR*>(lParam);
|
|
|
|
if (hdr &&
|
|
hdr->code == PSN_HELP)
|
|
{
|
|
OnWizardHelp();
|
|
}
|
|
return CPropertyPage::OnNotify(wParam, lParam, pResult);
|
|
}
|
|
|
|
void CPropertyPageBase::OnCancel()
|
|
{
|
|
CString szTitle;
|
|
GetWindowText(szTitle);
|
|
TRACE(_T("CPropertyPageBase::OnCancel()called on <%s>\n"),(LPCTSTR)szTitle);
|
|
CWinApp* pApp = AfxGetApp();
|
|
ASSERT(pApp);
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
m_pPageHolder->CloseModalDialogs(m_hWnd);
|
|
}
|
|
|
|
BOOL CPropertyPageBase::OnApply()
|
|
{
|
|
if (IsDirty())
|
|
{
|
|
if (m_pPageHolder->NotifyConsole(this) == 0x0)
|
|
{
|
|
SetDirty(FALSE);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef _DEBUG
|
|
// test only
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
AfxMessageBox(_T("Apply Failed"));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CPropertyPageBase::SetDirty(BOOL bDirty)
|
|
{
|
|
if (!m_pPageHolder->IsWizardMode())
|
|
{
|
|
SetModified(bDirty);
|
|
}
|
|
m_bIsDirty = bDirty;
|
|
}
|
|
|
|
|
|
void CPropertyPageBase::InitWiz97(BOOL bHideHeader,
|
|
UINT nIDHeaderTitle,
|
|
UINT nIDHeaderSubTitle,
|
|
bool hasHelp)
|
|
{
|
|
if (bHideHeader)
|
|
{
|
|
// for first and last page of the wizard
|
|
m_psp97.dwFlags |= PSP_HIDEHEADER;
|
|
}
|
|
else
|
|
{
|
|
// for intermediate pages
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
m_szHeaderTitle.LoadString(nIDHeaderTitle);
|
|
m_szHeaderSubTitle.LoadString(nIDHeaderSubTitle);
|
|
|
|
m_psp97.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
|
|
m_psp97.pszHeaderTitle = (LPCTSTR)m_szHeaderTitle;
|
|
m_psp97.pszHeaderSubTitle = (LPCTSTR)m_szHeaderSubTitle;
|
|
}
|
|
|
|
if (hasHelp)
|
|
{
|
|
m_psp97.dwFlags |= PSP_HASHELP;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPropertyPageHolderTable
|
|
|
|
#define PPAGE_HOLDER_ARRAY_DEF_SIZE (10)
|
|
|
|
|
|
CPropertyPageHolderTable::CPropertyPageHolderTable(CComponentDataObject* pComponentData)
|
|
{
|
|
m_pComponentData = pComponentData;
|
|
|
|
size_t arraySizeInBytes = sizeof(PPAGE_HOLDER_TABLE_ENTRY) * PPAGE_HOLDER_ARRAY_DEF_SIZE;
|
|
m_pEntries = (PPAGE_HOLDER_TABLE_ENTRY*)malloc(arraySizeInBytes);
|
|
if (m_pEntries != NULL)
|
|
{
|
|
memset(m_pEntries,0, arraySizeInBytes);
|
|
}
|
|
m_nSize = PPAGE_HOLDER_ARRAY_DEF_SIZE;
|
|
|
|
}
|
|
CPropertyPageHolderTable::~CPropertyPageHolderTable()
|
|
{
|
|
#ifdef _DEBUG
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
ASSERT(m_pEntries[k].pPPHolder == NULL);
|
|
ASSERT(m_pEntries[k].pNode == NULL);
|
|
}
|
|
#endif
|
|
free(m_pEntries);
|
|
}
|
|
|
|
void CPropertyPageHolderTable::Add(CPropertyPageHolderBase* pPPHolder)
|
|
{
|
|
ASSERT(pPPHolder != NULL);
|
|
ASSERT(pPPHolder->GetTreeNode() != NULL);
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if (m_pEntries[k].pPPHolder == NULL) // get the first empty spot
|
|
{
|
|
m_pEntries[k].pPPHolder = pPPHolder;
|
|
m_pEntries[k].pNode = pPPHolder->GetTreeNode();
|
|
m_pEntries[k].hWnd = NULL;
|
|
return;
|
|
}
|
|
}
|
|
// all full, need to grow the array
|
|
int nAlloc = m_nSize*2;
|
|
PPAGE_HOLDER_TABLE_ENTRY* temp = (PPAGE_HOLDER_TABLE_ENTRY*)realloc(m_pEntries, sizeof(PPAGE_HOLDER_TABLE_ENTRY)*nAlloc);
|
|
if (temp)
|
|
{
|
|
m_pEntries = temp;
|
|
memset(&m_pEntries[m_nSize], 0, sizeof(PPAGE_HOLDER_TABLE_ENTRY)*m_nSize);
|
|
m_pEntries[m_nSize].pPPHolder = pPPHolder;
|
|
m_pEntries[m_nSize].pNode = pPPHolder->GetTreeNode();
|
|
m_pEntries[m_nSize].hWnd = NULL;
|
|
m_nSize = nAlloc;
|
|
}
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderTable::AddWindow(CPropertyPageHolderBase* pPPHolder, HWND hWnd)
|
|
{
|
|
// By now, the PPHolder might have gone away, so use it as a cookie
|
|
// but do not call any methods on it.
|
|
// The node is still valid, because we do not delete nodes from secondary
|
|
// threads
|
|
ASSERT(pPPHolder != NULL);
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if (m_pEntries[k].pPPHolder == pPPHolder)
|
|
{
|
|
ASSERT(m_pEntries[k].pNode != NULL);
|
|
ASSERT(m_pEntries[k].pNode->GetSheetCount() > 0);
|
|
m_pEntries[k].hWnd = hWnd;
|
|
return; // assume no more that one holder entry
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CPropertyPageHolderTable::Remove(CPropertyPageHolderBase* pPPHolder)
|
|
{
|
|
// By now, the PPHolder might have gone away, so use it as a cookie
|
|
// but do not call any methods on it.
|
|
// The node is still valid, because we do not delete nodes from secondary
|
|
// threads
|
|
ASSERT(pPPHolder != NULL);
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if (m_pEntries[k].pPPHolder == pPPHolder)
|
|
{
|
|
ASSERT(m_pEntries[k].pNode != NULL);
|
|
ASSERT(m_pEntries[k].pNode->GetSheetCount() > 0);
|
|
m_pEntries[k].pPPHolder = NULL;
|
|
m_pEntries[k].pNode = NULL;
|
|
m_pEntries[k].hWnd = NULL;
|
|
return; // assume no more that one holder entry
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderTable::DeleteSheetsOfNode(CTreeNode* pNode)
|
|
{
|
|
ASSERT(pNode != NULL);
|
|
int nCount = BroadcastCloseMessageToSheets(pNode);
|
|
WaitForSheetShutdown(nCount);
|
|
}
|
|
|
|
|
|
void CPropertyPageHolderTable::WaitForAllToShutDown()
|
|
{
|
|
int nCount = 0;
|
|
// allocate and array of HWND's for broadcast
|
|
HWND* hWndArr = new HWND[m_nSize];
|
|
|
|
if (hWndArr)
|
|
{
|
|
memset(hWndArr, 0x0, m_nSize*sizeof(HWND));
|
|
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if (m_pEntries[k].pPPHolder != NULL)
|
|
{
|
|
m_pEntries[k].pPPHolder = NULL;
|
|
m_pEntries[k].pNode = NULL;
|
|
hWndArr[k] = ::GetParent(m_pEntries[k].hWnd);
|
|
m_pEntries[k].hWnd = NULL;
|
|
nCount++;
|
|
}
|
|
}
|
|
|
|
// wait for shutdown (wait for posted messages to come through
|
|
WaitForSheetShutdown(nCount, hWndArr);
|
|
|
|
delete [] hWndArr;
|
|
}
|
|
}
|
|
|
|
void CPropertyPageHolderTable::BroadcastSelectPage(CTreeNode* pNode, long nPageCode)
|
|
{
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if ((m_pEntries[k].hWnd != NULL) && (m_pEntries[k].pNode == pNode))
|
|
{
|
|
::PostMessage(m_pEntries[k].hWnd, CSheetWnd::s_SelectPageMessage, (WPARAM)nPageCode, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPropertyPageHolderTable::BroadcastMessageToSheets(CTreeNode* pNode, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if ((m_pEntries[k].hWnd != NULL) && (m_pEntries[k].pNode == pNode))
|
|
{
|
|
::PostMessage(m_pEntries[k].hWnd, CSheetWnd::s_SheetMessage, wParam, lParam);
|
|
}
|
|
}
|
|
}
|
|
|
|
int CPropertyPageHolderTable::BroadcastCloseMessageToSheets(CTreeNode* pNode)
|
|
{
|
|
ASSERT(m_nSize > 0);
|
|
int nCount = 0;
|
|
// allocate and array of HWND's for broadcast
|
|
HWND* hWndArr = new HWND[m_nSize];
|
|
|
|
if (hWndArr)
|
|
{
|
|
memset(hWndArr, 0x0, m_nSize*sizeof(HWND));
|
|
|
|
// find the HWND's that map to this node and its children
|
|
for (int k=0; k < m_nSize; k++)
|
|
{
|
|
if (m_pEntries[k].hWnd != NULL)
|
|
{
|
|
if (m_pEntries[k].pNode == pNode)
|
|
{
|
|
hWndArr[nCount++] = ::GetParent(m_pEntries[k].hWnd);
|
|
}
|
|
else if (pNode->IsContainer())
|
|
{
|
|
if (m_pEntries[k].pNode->HasContainer((CContainerNode*)pNode))
|
|
{
|
|
hWndArr[nCount++] = ::GetParent(m_pEntries[k].hWnd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// shut down the sheets
|
|
for (int j=0; j < nCount; j++)
|
|
::PostMessage(hWndArr[j], WM_COMMAND, IDCANCEL, 0);
|
|
|
|
delete [] hWndArr;
|
|
}
|
|
|
|
return nCount;
|
|
}
|
|
|
|
|
|
|
|
void CPropertyPageHolderTable::WaitForSheetShutdown(int nCount, HWND* hWndArr)
|
|
{
|
|
ASSERT(m_pComponentData != NULL);
|
|
HWND hWnd = m_pComponentData->GetHiddenWindow();
|
|
ASSERT(::IsWindow(hWnd));
|
|
MSG tempMSG;
|
|
DWORD dwTimeStart = ::GetTickCount();
|
|
while(nCount > 0)
|
|
{
|
|
if ( hWndArr != NULL && (::GetTickCount() > dwTimeStart + 2000) )
|
|
{
|
|
// force sheets shut down
|
|
for (int j=0; j < nCount; j++)
|
|
::PostMessage(hWndArr[j], WM_COMMAND, IDCANCEL, 0);
|
|
hWndArr = NULL;
|
|
}
|
|
|
|
if (::PeekMessage(&tempMSG,hWnd, CHiddenWnd::s_NodePropertySheetDeleteMessage,
|
|
CHiddenWnd::s_NodePropertySheetDeleteMessage,
|
|
PM_REMOVE))
|
|
{
|
|
TRACE(_T("-------------------->>>>enter while peek loop, nCount = %d\n"),nCount);
|
|
DispatchMessage(&tempMSG);
|
|
nCount--;
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CHelpDialog
|
|
|
|
BEGIN_MESSAGE_MAP(CHelpDialog, CDialog)
|
|
ON_WM_CONTEXTMENU()
|
|
ON_MESSAGE(WM_HELP, OnHelp)
|
|
ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
CHelpDialog::CHelpDialog(UINT nIDTemplate, CComponentDataObject* pComponentData) :
|
|
m_hWndWhatsThis(0),
|
|
m_pComponentData(pComponentData),
|
|
CDialog(nIDTemplate)
|
|
{
|
|
}
|
|
|
|
CHelpDialog::CHelpDialog(UINT nIDTemplate, CWnd* pParentWnd, CComponentDataObject* pComponentData) :
|
|
m_hWndWhatsThis(0),
|
|
m_pComponentData(pComponentData),
|
|
CDialog(nIDTemplate, pParentWnd)
|
|
{
|
|
}
|
|
|
|
void CHelpDialog::OnWhatsThis()
|
|
{
|
|
//
|
|
// Display context help for a control
|
|
//
|
|
if ( m_hWndWhatsThis )
|
|
{
|
|
//
|
|
// Build our own HELPINFO struct to pass to the underlying
|
|
// CS help functions built into the framework
|
|
//
|
|
int iCtrlID = ::GetDlgCtrlID(m_hWndWhatsThis);
|
|
HELPINFO helpInfo;
|
|
ZeroMemory(&helpInfo, sizeof(HELPINFO));
|
|
helpInfo.cbSize = sizeof(HELPINFO);
|
|
helpInfo.hItemHandle = m_hWndWhatsThis;
|
|
helpInfo.iCtrlId = iCtrlID;
|
|
|
|
m_pComponentData->OnDialogContextHelp(m_nIDHelp, &helpInfo);
|
|
}
|
|
}
|
|
|
|
BOOL CHelpDialog::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
|
|
{
|
|
const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
|
|
|
|
if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
|
|
{
|
|
//
|
|
// Display context help for a control
|
|
//
|
|
m_pComponentData->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CHelpDialog::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
|
|
{
|
|
//
|
|
// point is in screen coordinates
|
|
//
|
|
|
|
CMenu bar;
|
|
if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
|
|
{
|
|
CMenu& popup = *bar.GetSubMenu (0);
|
|
ASSERT(popup.m_hMenu);
|
|
|
|
if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
|
|
point.x, // in screen coordinates
|
|
point.y, // in screen coordinates
|
|
this) ) // route commands through main window
|
|
{
|
|
m_hWndWhatsThis = 0;
|
|
ScreenToClient (&point);
|
|
CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
|
|
CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
|
|
if ( pChild )
|
|
{
|
|
m_hWndWhatsThis = pChild->m_hWnd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|