We have a CPropertySheet that have 5 CPropertyPage inside.
Let say we have something like this
1 2 3 4 5
Then, based on some business logic, when the user click refresh, we would like to have
1 5 2 3 4
We don't want to delete all the CPropertyPage and recreate them in the correct order (with AddPage()
), we just want to update the position of the page in the sheet.
Is this possible?
Thanks!
Microsoft's MFC CPropertySheet doesn't have a function to do this, however, if you check the Property Sheet Windows Controls API, you can achieve something similar by removing the page you want to move and then insert it at the desired position.
To do this, you first need to subclass CPropertySheet and add a function to insert a page to a given order:
//In the .h of your subclass
//Inserts the page at a given Index
void InsertPageAt(CPropertyPage* pPageToInsert, int nPos);
//In the .cpp file
void CPropertySheetControleur::InsertPageAt(CPropertyPage* pPage, int nPos)
{
ASSERT_VALID(this);
ENSURE_VALID(pPage);
ASSERT_KINDOF(CPropertyPage, pPage);
// add page to internal list
m_pages.InsertAt(nPos, pPage);
// add page externally
if (m_hWnd != NULL)
{
// determine size of PROPSHEETPAGE array
PROPSHEETPAGE* ppsp = const_cast<PROPSHEETPAGE*>(m_psh.ppsp);
int nBytes = 0;
int nNextBytes;
for (UINT i = 0; i < m_psh.nPages; i++)
{
nNextBytes = nBytes + ppsp->dwSize;
if ((nNextBytes < nBytes) || (nNextBytes < (int)ppsp->dwSize))
AfxThrowMemoryException();
nBytes = nNextBytes;
(BYTE*&)ppsp += ppsp->dwSize;
}
nNextBytes = nBytes + pPage->m_psp.dwSize;
if ((nNextBytes < nBytes) || (nNextBytes < (int)pPage->m_psp.dwSize))
AfxThrowMemoryException();
// build new prop page array
ppsp = (PROPSHEETPAGE*)realloc((void*)m_psh.ppsp, nNextBytes);
if (ppsp == NULL)
AfxThrowMemoryException();
m_psh.ppsp = ppsp;
// copy processed PROPSHEETPAGE struct to end
(BYTE*&)ppsp += nBytes;
Checked::memcpy_s(ppsp, nNextBytes - nBytes , &pPage->m_psp, pPage->m_psp.dwSize);
pPage->PreProcessPageTemplate(*ppsp, IsWizard());
if (!pPage->m_strHeaderTitle.IsEmpty())
{
ppsp->pszHeaderTitle = pPage->m_strHeaderTitle;
ppsp->dwFlags |= PSP_USEHEADERTITLE;
}
if (!pPage->m_strHeaderSubTitle.IsEmpty())
{
ppsp->pszHeaderSubTitle = pPage->m_strHeaderSubTitle;
ppsp->dwFlags |= PSP_USEHEADERSUBTITLE;
}
HPROPSHEETPAGE hPSP = AfxCreatePropertySheetPage(ppsp);
if (hPSP == NULL)
AfxThrowMemoryException();
if (!SendMessage(PSM_INSERTPAGE, nPos, (LPARAM)hPSP))
{
AfxDestroyPropertySheetPage(hPSP);
AfxThrowMemoryException();
}
++m_psh.nPages;
}
}
I based this fonction on the CPropertySheet::AddPage code, but at the end of the function, I substituted the message PSM_ADDPAGE to PSM_INSERTPAGE
Then, to move a page to a specific position, just remove it, then add it at the desired position.
pPropertySheet->RemovePage(pPageToAdd);
pPropertySheet->InsertPageAt(pPageToAdd, nIndex);