windows-nt/Source/XPSP1/NT/shell/ext/wizhost/wizhost.cpp
2020-09-26 16:20:57 +08:00

326 lines
8.4 KiB
C++

#include "windows.h"
#include "shlwapi.h"
#include "shpriv.h"
#include "commctrl.h"
#include "resource.h"
#include "ccstock.h"
#include "shlguid.h"
// globals and classes
HINSTANCE g_hAppInst; // instance information for the wizard
HWND g_hwndFrame; // wizard frame (cached on startup)
IWebWizardExtension *g_pwe; // IWizardExtension (we want to show)
// IWizardSite
// -----------
//
// This object is used by the wizard extension to navigate in and out of the
// main wizard. When the wizard extension has finished displaying its set
// of pages (and recieves its final PSN_WIZNEXT or PSN_WIZBACK) it is
// responsible for calling the site to navigate in and out of the
// stack of pages.
class CWizSite : public IWizardSite, IServiceProvider
{
public:
CWizSite(IPropertyBag *ppb);
~CWizSite();
// IUnknown
STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
STDMETHOD_(ULONG,AddRef)(void);
STDMETHOD_(ULONG,Release)(void);
// IWizardSite
STDMETHODIMP GetPreviousPage(HPROPSHEETPAGE *phPage);
STDMETHODIMP GetNextPage(HPROPSHEETPAGE *phPage);
STDMETHODIMP GetCancelledPage(HPROPSHEETPAGE *phPage)
{ return E_NOTIMPL; }
// IServiceProvider
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
private:
LONG _cRef;
IPropertyBag *_ppb;
};
// reference counting of the object
ULONG CWizSite::AddRef()
{
return InterlockedIncrement(&_cRef);
}
ULONG CWizSite::Release()
{
if (InterlockedDecrement(&_cRef))
return _cRef;
delete this;
return 0;
}
HRESULT CWizSite::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] =
{
QITABENT(CWizSite, IWizardSite), // IID_IWizardSite
QITABENT(CWizSite, IServiceProvider), // IID_IServiceProvider
{0},
};
return QISearch(this, qit, riid, ppv);
}
// instance creation
CWizSite::CWizSite(IPropertyBag *ppb) :
_cRef(1),
_ppb(ppb)
{
ppb->AddRef();
}
CWizSite::~CWizSite()
{
ATOMICRELEASE(_ppb);
}
HRESULT CWizSite_CreateInstance(IPropertyBag *ppb, REFIID riid, void **ppv)
{
CWizSite *pws = new CWizSite(ppb);
if (!pws)
return E_OUTOFMEMORY;
HRESULT hr = pws->QueryInterface(riid, ppv);
pws->Release();
return hr;
}
// methods for returning our page range
HRESULT CWizSite::GetPreviousPage(HPROPSHEETPAGE *phPage)
{
int i = PropSheet_IdToIndex(g_hwndFrame, IDD_WELCOME);
*phPage = PropSheet_IndexToPage(g_hwndFrame, i);
return S_OK;
}
HRESULT CWizSite::GetNextPage(HPROPSHEETPAGE *phPage)
{
int i = PropSheet_IdToIndex(g_hwndFrame, IDD_DONE);
*phPage = PropSheet_IndexToPage(g_hwndFrame, i);
return S_OK;
}
// Service provider object
HRESULT CWizSite::QueryService(REFGUID guidService, REFIID riid, void **ppv)
{
*ppv = NULL; // no result yet
if (guidService == SID_PublishingWizard)
{
if (riid == IID_IPropertyBag)
return _ppb->QueryInterface(riid, ppv);
}
return E_FAIL;
}
// Sample dialog proc's for the welcome and done pages (these then call into
// the wizard extension to show their pages).
BOOL _HandleWizNextBack(HWND hwnd, HPROPSHEETPAGE hpage)
{
PropSheet_SetCurSel(GetParent(hwnd), hpage, -1);
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, -1);
return TRUE;
}
INT_PTR _WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch ( uMsg )
{
case WM_INITDIALOG:
g_hwndFrame = GetParent(hwnd);
return TRUE;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR)lParam;
switch (pnmh->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(g_hwndFrame, PSWIZB_NEXT);
return TRUE;
case PSN_WIZNEXT:
{
HPROPSHEETPAGE hpage;
g_pwe->GetFirstPage(&hpage);
return _HandleWizNextBack(hwnd, hpage);
}
}
break;
}
}
return FALSE;
}
INT_PTR _DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch ( uMsg )
{
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR)lParam;
switch (pnmh->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(g_hwndFrame, PSWIZB_FINISH | PSWIZB_BACK);
return TRUE;
case PSN_WIZBACK:
{
HPROPSHEETPAGE hpage;
g_pwe->GetLastPage(&hpage);
return _HandleWizNextBack(hwnd, hpage);
}
}
break;
}
}
return FALSE;
}
// Our Wizard, its very simple.
#define WIZDLG(name, dlgproc, dwFlags) \
{ MAKEINTRESOURCE(IDD_##name##), dlgproc, MAKEINTRESOURCE(IDS_##name##), MAKEINTRESOURCE(IDS_##name##_SUB), dwFlags }
const struct
{
LPCWSTR idPage;
DLGPROC pDlgProc;
LPCWSTR pHeading;
LPCWSTR pSubHeading;
DWORD dwFlags;
}
c_pages[] =
{
WIZDLG(WELCOME, _WelcomeDlgProc, 0x0),
WIZDLG(DONE, _DoneDlgProc, 0x0),
};
HRESULT _InitExtensionSite(IWizardExtension *pwe)
{
IPropertyBag *ppb;
HRESULT hr = SHCreatePropertyBagOnMemory(STGM_READWRITE, IID_PPV_ARG(IPropertyBag, &ppb));
if (SUCCEEDED(hr))
{
IWizardSite *pws;
hr = CWizSite_CreateInstance(ppb, IID_PPV_ARG(IWizardSite, &pws));
if (SUCCEEDED(hr))
{
IUnknown_SetSite(pwe, pws);
pws->Release();
}
ppb->Release();
}
return hr;
}
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
g_hAppInst = hInstance;
CoInitialize(NULL);
InitCommonControls();
// For our example we will create the Publishing Wizard, it supports IWizardExtension and
// we will host its pages within ours.
HRESULT hr = CoCreateInstance(CLSID_WebWizardHost, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IWebWizardExtension, &g_pwe));
if (SUCCEEDED(hr))
{
hr = _InitExtensionSite(g_pwe);
if (SUCCEEDED(hr))
{
// Create our pages, these are placed at the top of the array,
// the extensions are placed after.
HPROPSHEETPAGE hpages[10] = { 0 };
for (int i = 0; i < ARRAYSIZE(c_pages) ; i++ )
{
PROPSHEETPAGE psp = { 0 };
psp.dwSize = sizeof(psp);
psp.hInstance = g_hAppInst;
psp.dwFlags = PSP_USETITLE | PSP_DEFAULT |
PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE |
c_pages[i].dwFlags;
psp.pszTemplate = c_pages[i].idPage;
psp.pfnDlgProc = c_pages[i].pDlgProc;
psp.pszTitle = TEXT("Wizard Hosting Example");
psp.pszHeaderTitle = c_pages[i].pHeading;
psp.pszHeaderSubTitle = c_pages[i].pSubHeading;
hpages[i] = CreatePropertySheetPage(&psp);
}
// Fill out the structure for the property sheet, we indicate
// that we want this to behave like a wizard.
PROPSHEETHEADER psh = { 0 };
psh.dwSize = sizeof(psh);
psh.hInstance = g_hAppInst;
psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_HEADER;
psh.pszbmHeader = MAKEINTRESOURCE(IDB_BANNER);
psh.phpage = hpages;
psh.nPages = i;
// Let the extension add its pages it will append an array of
// HPROPSHEETPAGE to the structure, it also return the count.
UINT nPages;
hr = g_pwe->AddPages(&hpages[i], ARRAYSIZE(hpages)-i, &nPages);
if (SUCCEEDED(hr))
{
psh.nPages = i+nPages;
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath));
PathRenameExtension(szPath, TEXT(".htm"));
WCHAR szURL[128];
DWORD cch = ARRAYSIZE(szURL);
UrlCreateFromPath(szPath, szURL, &cch, 0);
g_pwe->SetInitialURL(szURL);
PropertySheet(&psh);
}
}
g_pwe->Release();
g_pwe = NULL;
}
CoUninitialize();
return 0;
}