Source code of Windows XP (NT5)
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.

325 lines
8.4 KiB

  1. #include "windows.h"
  2. #include "shlwapi.h"
  3. #include "shpriv.h"
  4. #include "commctrl.h"
  5. #include "resource.h"
  6. #include "ccstock.h"
  7. #include "shlguid.h"
  8. // globals and classes
  9. HINSTANCE g_hAppInst; // instance information for the wizard
  10. HWND g_hwndFrame; // wizard frame (cached on startup)
  11. IWebWizardExtension *g_pwe; // IWizardExtension (we want to show)
  12. // IWizardSite
  13. // -----------
  14. //
  15. // This object is used by the wizard extension to navigate in and out of the
  16. // main wizard. When the wizard extension has finished displaying its set
  17. // of pages (and recieves its final PSN_WIZNEXT or PSN_WIZBACK) it is
  18. // responsible for calling the site to navigate in and out of the
  19. // stack of pages.
  20. class CWizSite : public IWizardSite, IServiceProvider
  21. {
  22. public:
  23. CWizSite(IPropertyBag *ppb);
  24. ~CWizSite();
  25. // IUnknown
  26. STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
  27. STDMETHOD_(ULONG,AddRef)(void);
  28. STDMETHOD_(ULONG,Release)(void);
  29. // IWizardSite
  30. STDMETHODIMP GetPreviousPage(HPROPSHEETPAGE *phPage);
  31. STDMETHODIMP GetNextPage(HPROPSHEETPAGE *phPage);
  32. STDMETHODIMP GetCancelledPage(HPROPSHEETPAGE *phPage)
  33. { return E_NOTIMPL; }
  34. // IServiceProvider
  35. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
  36. private:
  37. LONG _cRef;
  38. IPropertyBag *_ppb;
  39. };
  40. // reference counting of the object
  41. ULONG CWizSite::AddRef()
  42. {
  43. return InterlockedIncrement(&_cRef);
  44. }
  45. ULONG CWizSite::Release()
  46. {
  47. if (InterlockedDecrement(&_cRef))
  48. return _cRef;
  49. delete this;
  50. return 0;
  51. }
  52. HRESULT CWizSite::QueryInterface(REFIID riid, void **ppv)
  53. {
  54. static const QITAB qit[] =
  55. {
  56. QITABENT(CWizSite, IWizardSite), // IID_IWizardSite
  57. QITABENT(CWizSite, IServiceProvider), // IID_IServiceProvider
  58. {0},
  59. };
  60. return QISearch(this, qit, riid, ppv);
  61. }
  62. // instance creation
  63. CWizSite::CWizSite(IPropertyBag *ppb) :
  64. _cRef(1),
  65. _ppb(ppb)
  66. {
  67. ppb->AddRef();
  68. }
  69. CWizSite::~CWizSite()
  70. {
  71. ATOMICRELEASE(_ppb);
  72. }
  73. HRESULT CWizSite_CreateInstance(IPropertyBag *ppb, REFIID riid, void **ppv)
  74. {
  75. CWizSite *pws = new CWizSite(ppb);
  76. if (!pws)
  77. return E_OUTOFMEMORY;
  78. HRESULT hr = pws->QueryInterface(riid, ppv);
  79. pws->Release();
  80. return hr;
  81. }
  82. // methods for returning our page range
  83. HRESULT CWizSite::GetPreviousPage(HPROPSHEETPAGE *phPage)
  84. {
  85. int i = PropSheet_IdToIndex(g_hwndFrame, IDD_WELCOME);
  86. *phPage = PropSheet_IndexToPage(g_hwndFrame, i);
  87. return S_OK;
  88. }
  89. HRESULT CWizSite::GetNextPage(HPROPSHEETPAGE *phPage)
  90. {
  91. int i = PropSheet_IdToIndex(g_hwndFrame, IDD_DONE);
  92. *phPage = PropSheet_IndexToPage(g_hwndFrame, i);
  93. return S_OK;
  94. }
  95. // Service provider object
  96. HRESULT CWizSite::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  97. {
  98. *ppv = NULL; // no result yet
  99. if (guidService == SID_PublishingWizard)
  100. {
  101. if (riid == IID_IPropertyBag)
  102. return _ppb->QueryInterface(riid, ppv);
  103. }
  104. return E_FAIL;
  105. }
  106. // Sample dialog proc's for the welcome and done pages (these then call into
  107. // the wizard extension to show their pages).
  108. BOOL _HandleWizNextBack(HWND hwnd, HPROPSHEETPAGE hpage)
  109. {
  110. PropSheet_SetCurSel(GetParent(hwnd), hpage, -1);
  111. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, -1);
  112. return TRUE;
  113. }
  114. INT_PTR _WelcomeDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  115. {
  116. switch ( uMsg )
  117. {
  118. case WM_INITDIALOG:
  119. g_hwndFrame = GetParent(hwnd);
  120. return TRUE;
  121. case WM_NOTIFY:
  122. {
  123. LPNMHDR pnmh = (LPNMHDR)lParam;
  124. switch (pnmh->code)
  125. {
  126. case PSN_SETACTIVE:
  127. PropSheet_SetWizButtons(g_hwndFrame, PSWIZB_NEXT);
  128. return TRUE;
  129. case PSN_WIZNEXT:
  130. {
  131. HPROPSHEETPAGE hpage;
  132. g_pwe->GetFirstPage(&hpage);
  133. return _HandleWizNextBack(hwnd, hpage);
  134. }
  135. }
  136. break;
  137. }
  138. }
  139. return FALSE;
  140. }
  141. INT_PTR _DoneDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  142. {
  143. switch ( uMsg )
  144. {
  145. case WM_NOTIFY:
  146. {
  147. LPNMHDR pnmh = (LPNMHDR)lParam;
  148. switch (pnmh->code)
  149. {
  150. case PSN_SETACTIVE:
  151. PropSheet_SetWizButtons(g_hwndFrame, PSWIZB_FINISH | PSWIZB_BACK);
  152. return TRUE;
  153. case PSN_WIZBACK:
  154. {
  155. HPROPSHEETPAGE hpage;
  156. g_pwe->GetLastPage(&hpage);
  157. return _HandleWizNextBack(hwnd, hpage);
  158. }
  159. }
  160. break;
  161. }
  162. }
  163. return FALSE;
  164. }
  165. // Our Wizard, its very simple.
  166. #define WIZDLG(name, dlgproc, dwFlags) \
  167. { MAKEINTRESOURCE(IDD_##name##), dlgproc, MAKEINTRESOURCE(IDS_##name##), MAKEINTRESOURCE(IDS_##name##_SUB), dwFlags }
  168. const struct
  169. {
  170. LPCWSTR idPage;
  171. DLGPROC pDlgProc;
  172. LPCWSTR pHeading;
  173. LPCWSTR pSubHeading;
  174. DWORD dwFlags;
  175. }
  176. c_pages[] =
  177. {
  178. WIZDLG(WELCOME, _WelcomeDlgProc, 0x0),
  179. WIZDLG(DONE, _DoneDlgProc, 0x0),
  180. };
  181. HRESULT _InitExtensionSite(IWizardExtension *pwe)
  182. {
  183. IPropertyBag *ppb;
  184. HRESULT hr = SHCreatePropertyBagOnMemory(STGM_READWRITE, IID_PPV_ARG(IPropertyBag, &ppb));
  185. if (SUCCEEDED(hr))
  186. {
  187. IWizardSite *pws;
  188. hr = CWizSite_CreateInstance(ppb, IID_PPV_ARG(IWizardSite, &pws));
  189. if (SUCCEEDED(hr))
  190. {
  191. IUnknown_SetSite(pwe, pws);
  192. pws->Release();
  193. }
  194. ppb->Release();
  195. }
  196. return hr;
  197. }
  198. int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  199. {
  200. g_hAppInst = hInstance;
  201. CoInitialize(NULL);
  202. InitCommonControls();
  203. // For our example we will create the Publishing Wizard, it supports IWizardExtension and
  204. // we will host its pages within ours.
  205. HRESULT hr = CoCreateInstance(CLSID_WebWizardHost, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IWebWizardExtension, &g_pwe));
  206. if (SUCCEEDED(hr))
  207. {
  208. hr = _InitExtensionSite(g_pwe);
  209. if (SUCCEEDED(hr))
  210. {
  211. // Create our pages, these are placed at the top of the array,
  212. // the extensions are placed after.
  213. HPROPSHEETPAGE hpages[10] = { 0 };
  214. for (int i = 0; i < ARRAYSIZE(c_pages) ; i++ )
  215. {
  216. PROPSHEETPAGE psp = { 0 };
  217. psp.dwSize = sizeof(psp);
  218. psp.hInstance = g_hAppInst;
  219. psp.dwFlags = PSP_USETITLE | PSP_DEFAULT |
  220. PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE |
  221. c_pages[i].dwFlags;
  222. psp.pszTemplate = c_pages[i].idPage;
  223. psp.pfnDlgProc = c_pages[i].pDlgProc;
  224. psp.pszTitle = TEXT("Wizard Hosting Example");
  225. psp.pszHeaderTitle = c_pages[i].pHeading;
  226. psp.pszHeaderSubTitle = c_pages[i].pSubHeading;
  227. hpages[i] = CreatePropertySheetPage(&psp);
  228. }
  229. // Fill out the structure for the property sheet, we indicate
  230. // that we want this to behave like a wizard.
  231. PROPSHEETHEADER psh = { 0 };
  232. psh.dwSize = sizeof(psh);
  233. psh.hInstance = g_hAppInst;
  234. psh.dwFlags = PSH_WIZARD | PSH_WIZARD97 | PSH_HEADER;
  235. psh.pszbmHeader = MAKEINTRESOURCE(IDB_BANNER);
  236. psh.phpage = hpages;
  237. psh.nPages = i;
  238. // Let the extension add its pages it will append an array of
  239. // HPROPSHEETPAGE to the structure, it also return the count.
  240. UINT nPages;
  241. hr = g_pwe->AddPages(&hpages[i], ARRAYSIZE(hpages)-i, &nPages);
  242. if (SUCCEEDED(hr))
  243. {
  244. psh.nPages = i+nPages;
  245. TCHAR szPath[MAX_PATH];
  246. GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath));
  247. PathRenameExtension(szPath, TEXT(".htm"));
  248. WCHAR szURL[128];
  249. DWORD cch = ARRAYSIZE(szURL);
  250. UrlCreateFromPath(szPath, szURL, &cch, 0);
  251. g_pwe->SetInitialURL(szURL);
  252. PropertySheet(&psh);
  253. }
  254. }
  255. g_pwe->Release();
  256. g_pwe = NULL;
  257. }
  258. CoUninitialize();
  259. return 0;
  260. }