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

679 lines
17 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: firstpin.cpp
//
//--------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "firstpin.h"
#include "folder.h"
#include "idlhelp.h"
#include "msgbox.h"
#include "cscst.h"
#include "syncmgr.h"
#include "strings.h"
//
// Base class for all "first pin" wizard pages.
// Contains the single dialog proc used for all pages. Specialization
// for individual pages is achieved through deriviation and implementing
// virtual functions.
//
class CWizardPage
{
public:
enum { WM_WIZARDFINISHED = (WM_USER + 1) };
CWizardPage(HINSTANCE hInstance,
UINT idDlgTemplate,
UINT idsHdrTitle,
UINT idsHdrSubtitle,
DWORD dwPgFlags,
DWORD dwBtnFlags);
virtual ~CWizardPage(void);
UINT GetDlgTemplate(void) const
{ return m_idDlgTemplate; }
UINT GetHeaderTitle(void) const
{ return m_idsHdrTitle; }
UINT GetHeaderSubtitle(void) const
{ return m_idsHdrSubtitle; }
DWORD GetPageFlags(void) const
{ return m_dwPgFlags; }
DWORD GetBtnFlags(void) const
{ return m_dwBtnFlags; }
DLGPROC GetDlgProc(void) const
{ return DlgProc; }
virtual BOOL OnInitDialog(WPARAM wParam, LPARAM lParam)
{ return TRUE; }
virtual BOOL OnPSNSetActive(void);
virtual BOOL OnPSNWizFinish(void)
{ SetWindowLong(m_hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); return FALSE; }
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
{ return FALSE; }
virtual BOOL OnWizardFinished(void) { return FALSE; }
protected:
HINSTANCE m_hInstance;
HWND m_hwndDlg;
HFONT m_hTitleFont; // Used only by cover and finish pages.
UINT m_cyTitleFontHt; // Title font height in pts.
int FontPtsToHt(HWND hwnd, int pts);
BOOL FormatTitleFont(UINT idcTitle);
private:
UINT m_idDlgTemplate; // Dialog resource template.
UINT m_idsHdrTitle; // String ID for pg header title.
UINT m_idsHdrSubtitle; // String ID for pg header subtitle.
DWORD m_dwBtnFlags; // PSB_WIZXXXXX flags.
DWORD m_dwPgFlags; // PSP_XXXX flags.
static INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
//
// Welcome page.
//
class CWizardPgWelcome : public CWizardPage
{
public:
CWizardPgWelcome(HINSTANCE hInstance,
UINT idDlgTemplate,
UINT idsHdrTitle,
UINT idsHdrSubtitle,
DWORD dwPgFlags,
DWORD dwBtnFlags
) : CWizardPage(hInstance,
idDlgTemplate,
idsHdrTitle,
idsHdrSubtitle,
dwPgFlags,
dwBtnFlags)
{ }
BOOL OnInitDialog(WPARAM wParam, LPARAM lParam);
};
//
// Pinning page.
//
class CWizardPgPin : public CWizardPage
{
public:
CWizardPgPin(HINSTANCE hInstance,
UINT idDlgTemplate,
UINT idsHdrTitle,
UINT idsHdrSubtitle,
DWORD dwPgFlags,
DWORD dwBtnFlags
) : CWizardPage(hInstance,
idDlgTemplate,
idsHdrTitle,
idsHdrSubtitle,
dwPgFlags,
dwBtnFlags) { }
BOOL OnInitDialog(WPARAM wParam, LPARAM lParam);
BOOL OnWizardFinished(void);
};
//
// Offline page.
//
class CWizardPgOffline : public CWizardPage
{
public:
CWizardPgOffline(HINSTANCE hInstance,
UINT idDlgTemplate,
UINT idsHdrTitle,
UINT idsHdrSubtitle,
DWORD dwPgFlags,
DWORD dwBtnFlags
) : CWizardPage(hInstance,
idDlgTemplate,
idsHdrTitle,
idsHdrSubtitle,
dwPgFlags,
dwBtnFlags) { }
BOOL OnInitDialog(WPARAM wParam, LPARAM lParam);
BOOL OnPSNWizFinish(void);
BOOL OnWizardFinished(void);
};
//
// Class encapsulating the functionality of the entire wizard.
// It contains member instances of each of the page types.
//
class CFirstPinWizard
{
public:
CFirstPinWizard(HINSTANCE hInstance, HWND hwndParent);
HRESULT Run(void);
private:
enum { PG_WELCOME,
PG_PIN,
PG_OFFLINE,
PG_NUMPAGES };
HINSTANCE m_hInstance;
HWND m_hwndParent;
CWizardPgWelcome m_PgWelcome;
CWizardPgPin m_PgPin;
CWizardPgOffline m_PgOffline;
CWizardPage *m_rgpWizPages[PG_NUMPAGES];
};
//
// CWizardPage members --------------------------------------------------------
//
CWizardPage::CWizardPage(
HINSTANCE hInstance,
UINT idDlgTemplate,
UINT idsHdrTitle,
UINT idsHdrSubtitle,
DWORD dwPgFlags,
DWORD dwBtnFlags
) : m_hInstance(hInstance),
m_idDlgTemplate(idDlgTemplate),
m_idsHdrTitle(idsHdrTitle),
m_idsHdrSubtitle(idsHdrSubtitle),
m_dwPgFlags(dwPgFlags),
m_dwBtnFlags(dwBtnFlags),
m_cyTitleFontHt(12),
m_hwndDlg(NULL),
m_hTitleFont(NULL)
{
//
// Get the title font height from a resource string. That way localizers can
// play with the font dimensions if necessary.
//
TCHAR szFontHt[20];
if (0 < LoadString(m_hInstance, IDS_FIRSTPIN_FONTHT_PTS, szFontHt, ARRAYSIZE(szFontHt)))
{
m_cyTitleFontHt = StrToInt(szFontHt);
}
}
CWizardPage::~CWizardPage(
void
)
{
if (NULL != m_hTitleFont)
{
DeleteObject(m_hTitleFont);
}
}
//
// PSN_SETACTIVE handler.
//
BOOL
CWizardPage::OnPSNSetActive(
void
)
{
PropSheet_SetWizButtons(GetParent(m_hwndDlg), m_dwBtnFlags);
return FALSE;
}
//
// Dialog proc used by all pages in this wizard.
//
INT_PTR CALLBACK
CWizardPage::DlgProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
CWizardPage *pPage = (CWizardPage *)GetWindowLongPtr(hwnd, DWLP_USER);
BOOL bResult = FALSE;
switch(uMsg)
{
case WM_INITDIALOG:
{
PROPSHEETPAGE *ppsp = (PROPSHEETPAGE *)lParam;
pPage = (CWizardPage *)ppsp->lParam;
TraceAssert(NULL != pPage);
SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pPage);
pPage->m_hwndDlg = hwnd;
bResult = pPage->OnInitDialog(wParam, lParam);
break;
}
case WM_COMMAND:
if (NULL != pPage)
bResult = pPage->OnCommand(wParam, lParam);
break;
case WM_NOTIFY:
switch(((LPNMHDR)lParam)->code)
{
case PSN_SETACTIVE:
bResult = pPage->OnPSNSetActive();
break;
case PSN_WIZFINISH:
bResult = pPage->OnPSNWizFinish();
break;
}
break;
case PSM_QUERYSIBLINGS:
if (CWizardPage::WM_WIZARDFINISHED == wParam)
bResult = pPage->OnWizardFinished();
break;
default:
break;
}
return bResult;
}
//
// Helper function to convert a font point size to a height value
// used in a LOGFONT structure.
//
int
CWizardPage::FontPtsToHt(
HWND hwnd,
int pts
)
{
int ht = 10;
HDC hdc = GetDC(hwnd);
if (NULL != hdc)
{
ht = -MulDiv(pts, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(hwnd, hdc);
}
return ht;
}
//
// The title text on the cover and finish pages is enlarged and bold.
// This code modifies the text in the dialog accordingly.
// On return, m_hTitleFont contains the handle to the title font.
//
BOOL
CWizardPage::FormatTitleFont(
UINT idcTitle
)
{
BOOL bResult = FALSE;
HWND hwndTitle = GetDlgItem(m_hwndDlg, idcTitle);
HFONT hFont = (HFONT)SendMessage(hwndTitle, WM_GETFONT, 0, 0);
if (NULL != hFont)
{
if (NULL == m_hTitleFont)
{
LOGFONT lf;
if (GetObject(hFont, sizeof(lf), &lf))
{
lf.lfHeight = FontPtsToHt(hwndTitle, m_cyTitleFontHt);
m_hTitleFont = CreateFontIndirect(&lf);
}
}
if (NULL != m_hTitleFont)
{
SendMessage(hwndTitle, WM_SETFONT, (WPARAM)m_hTitleFont, 0);
bResult = TRUE;
}
}
return bResult;
}
//
// CWizardPgWelcome members -----------------------------------------------------
//
//
// WM_INITDIALOG handler.
//
BOOL
CWizardPgWelcome::OnInitDialog(
WPARAM wParam,
LPARAM lParam
)
{
FormatTitleFont(IDC_TXT_FIRSTPIN_WELCOME_TITLE);
return CWizardPage::OnInitDialog(wParam, lParam);
}
//
// CWizardPgPin members -------------------------------------------------------
//
//
// WM_INITDIALOG handler.
//
BOOL
CWizardPgPin::OnInitDialog(
WPARAM wParam,
LPARAM lParam
)
{
HRESULT hr = IsRegisteredForSyncAtLogonAndLogoff();
CheckDlgButton(m_hwndDlg,
IDC_CBX_FIRSTPIN_AUTOSYNC,
S_OK == hr ? BST_CHECKED : BST_UNCHECKED);
return CWizardPage::OnInitDialog(wParam, lParam);
}
//
// PSN_WIZFINISH handler.
//
BOOL
CWizardPgPin::OnWizardFinished(
void
)
{
HRESULT hr;
RegisterSyncMgrHandler(TRUE);
if (BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_FIRSTPIN_AUTOSYNC))
{
const DWORD dwFlags = SYNCMGRREGISTERFLAG_CONNECT | SYNCMGRREGISTERFLAG_PENDINGDISCONNECT;
hr = RegisterForSyncAtLogonAndLogoff(dwFlags, dwFlags);
if (SUCCEEDED(hr))
{
SetSyncMgrInitialized();
}
else
{
CscMessageBox(m_hwndDlg,
MB_OK | MB_ICONERROR,
Win32Error(HRESULT_CODE(hr)),
m_hInstance,
IDS_ERR_REGSYNCATLOGONLOGOFF);
}
}
return CWizardPage::OnWizardFinished();
}
//
// CWizardPgOffline members ---------------------------------------------------
//
//
// WM_INITDIALOG handler.
//
BOOL
CWizardPgOffline::OnInitDialog(
WPARAM wParam,
LPARAM lParam
)
{
//
// If policy allows configuration of the reminders, check the "enable reminders"
// checkbox.
//
CConfig& config = CConfig::GetSingleton();
bool bNoConfigReminders;
bool bNoCacheViewer = config.NoCacheViewer();
config.NoReminders(&bNoConfigReminders);
CheckDlgButton(m_hwndDlg, IDC_CBX_REMINDERS, !bNoConfigReminders);
EnableWindow(GetDlgItem(m_hwndDlg, IDC_CBX_REMINDERS), !bNoConfigReminders);
CheckDlgButton(m_hwndDlg, IDC_CBX_FIRSTPIN_FLDRLNK, BST_UNCHECKED);
EnableWindow(GetDlgItem(m_hwndDlg, IDC_CBX_FIRSTPIN_FLDRLNK), !bNoCacheViewer);
return CWizardPage::OnInitDialog(wParam, lParam);
}
//
// PSN_WIZFINISH handler.
//
BOOL
CWizardPgOffline::OnPSNWizFinish(
void
)
{
//
// Send PSM_QUERYSIBLINGS to all of the pages with
// wParam set to WM_WIZARDFINISHED. This will trigger
// a call to the virtual function OnWizardFinished()
// allowing each page to respond to the successful completion
// of the wizard.
//
PropSheet_QuerySiblings(GetParent(m_hwndDlg),
CWizardPage::WM_WIZARDFINISHED,
0);
//
// Now handle for this page.
//
OnWizardFinished();
return CWizardPage::OnPSNWizFinish();
}
//
// PSN_WIZFINISH handler.
//
BOOL
CWizardPgOffline::OnWizardFinished(
void
)
{
bool bEnableReminders = (BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_REMINDERS));
DWORD dwValue;
DWORD dwErr;
dwValue = bEnableReminders ? 0 : 1;
dwErr = SHSetValue(HKEY_CURRENT_USER,
REGSTR_KEY_OFFLINEFILES,
REGSTR_VAL_NOREMINDERS,
REG_DWORD,
&dwValue,
sizeof(dwValue));
if (bEnableReminders)
{
PostToSystray(PWM_RESET_REMINDERTIMER, 0, 0);
}
if (BST_CHECKED == IsDlgButtonChecked(m_hwndDlg, IDC_CBX_FIRSTPIN_FLDRLNK))
{
COfflineFilesFolder::CreateLinkOnDesktop(m_hwndDlg);
}
return CWizardPage::OnWizardFinished();
}
//
// CFirstPinWizard members ----------------------------------------------------
//
CFirstPinWizard::CFirstPinWizard(
HINSTANCE hInstance,
HWND hwndParent
) : m_hInstance(hInstance),
m_hwndParent(hwndParent),
m_PgWelcome(hInstance,
IDD_FIRSTPIN_WELCOME,
0,
0,
PSP_DEFAULT,
PSWIZB_NEXT),
m_PgPin(hInstance,
IDD_FIRSTPIN_PIN,
0,
0,
PSP_DEFAULT,
PSWIZB_NEXT | PSWIZB_BACK),
m_PgOffline(hInstance,
IDD_FIRSTPIN_OFFLINE,
0,
0,
PSP_DEFAULT,
PSWIZB_FINISH | PSWIZB_BACK)
{
//
// Store pointers to each page in an array. Makes creating the
// prop sheet easier in Run().
//
m_rgpWizPages[0] = &m_PgWelcome;
m_rgpWizPages[1] = &m_PgPin;
m_rgpWizPages[2] = &m_PgOffline;
}
//
// Creates the wizard and runs it.
// The wizard runs modally.
//
// Returns:
//
// S_OK = User completed wizard and pressed "Finish".
// S_FALSE = User pressed "Cancel" in wizard.
// Other = Error creating wizard.
//
HRESULT
CFirstPinWizard::Run(
void
)
{
HRESULT hr = NOERROR;
PROPSHEETHEADER psh;
PROPSHEETPAGE psp;
HPROPSHEETPAGE rghpage[ARRAYSIZE(m_rgpWizPages)];
ZeroMemory(&psh, sizeof(psh));
ZeroMemory(rghpage, sizeof(rghpage));
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_WIZARD_LITE;
psh.hwndParent = m_hwndParent;
psh.hInstance = m_hInstance;
psh.nPages = ARRAYSIZE(rghpage);
psh.phpage = rghpage;
TCHAR szTitle[MAX_PATH];
TCHAR szSubTitle[MAX_PATH];
for (int i = 0; i < ARRAYSIZE(rghpage) && SUCCEEDED(hr); i++)
{
CWizardPage *pwp = m_rgpWizPages[i];
ZeroMemory(&psp, sizeof(psp));
psp.dwSize = sizeof(psp);
psp.dwFlags |= pwp->GetPageFlags();
psp.hInstance = m_hInstance;
psp.pszTemplate = MAKEINTRESOURCE(pwp->GetDlgTemplate());
psp.pfnDlgProc = pwp->GetDlgProc();
psp.lParam = (LPARAM)pwp;
rghpage[i] = CreatePropertySheetPage(&psp);
if (NULL == rghpage[i])
{
while(0 <= --i)
{
DestroyPropertySheetPage(rghpage[i]);
}
hr = E_FAIL;
}
}
if (SUCCEEDED(hr))
{
switch(PropertySheet(&psh))
{
case -1:
hr = HRESULT_FROM_WIN32(GetLastError());
break;
case 0:
hr = S_FALSE; // User pressed "Cancel".
break;
case 1:
hr = S_OK; // User pressed "Finish".
break;
}
}
return hr;
}
//
// This is the function you call when you want to run the wizard.
// It merely creates a wizard object and tells it to run.
// If the user finishes the wizard, it records this fact in the
// registry. Calling FirstPinWizardCompleted() will tell
// you later if the user has finished the wizard.
//
// Returns:
//
// S_OK = User completed wizard and pressed "Finish".
// S_FALSE = User cancelled out of wizard.
// Other = Error creating wizard.
//
HRESULT
ShowFirstPinWizard(
HWND hwndParent
)
{
HRESULT hr = NOERROR;
CFirstPinWizard Wizard(g_hInstance, hwndParent);
hr = Wizard.Run();
if (S_OK == hr)
{
//
// Only record "finished" in registry if user
// pressed "finish".
//
RegKey key(HKEY_CURRENT_USER, REGSTR_KEY_OFFLINEFILES);
if (SUCCEEDED(key.Open(KEY_SET_VALUE, true)))
{
key.SetValue(REGSTR_VAL_FIRSTPINWIZARDSHOWN, 1);
}
}
return hr;
}
//
// Has user seen the wizard and pressed "finish"?
//
bool
FirstPinWizardCompleted(
void
)
{
return CConfig::GetSingleton().FirstPinWizardShown();
}