932 lines
24 KiB
C++
932 lines
24 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: N C U I . C P P
|
|
//
|
|
// Contents: Common user interface routines.
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: shaunco 24 Mar 1997
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.h>
|
|
#pragma hdrstop
|
|
|
|
#include "ncerror.h"
|
|
#include "ncstring.h"
|
|
#include "ncui.h"
|
|
#include "ncperms.h"
|
|
#include "netconp.h"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: EnableOrDisableDialogControls
|
|
//
|
|
// Purpose: Enable or disable a group of controls all at once.
|
|
//
|
|
// Arguments:
|
|
// hDlg [in] Window handle of parent dialog.
|
|
// ccid [in] Count of elements in array pointed to by acid.
|
|
// acid [in] Array of control ids.
|
|
// fEnable [in] TRUE to enable controls, FALSE to disable.
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// Author: shaunco 24 Mar 1997
|
|
//
|
|
// Notes: Don't forget to declare your array as 'static const'.
|
|
//
|
|
NOTHROW
|
|
VOID
|
|
EnableOrDisableDialogControls (
|
|
IN HWND hDlg,
|
|
IN INT ccid,
|
|
IN const INT* acid,
|
|
IN BOOL fEnable)
|
|
{
|
|
Assert (IsWindow (hDlg));
|
|
Assert (FImplies (ccid, acid));
|
|
|
|
while (ccid--)
|
|
{
|
|
EnableWindow (GetDlgItem (hDlg, *acid++), fEnable);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FMapRadioButtonToValue
|
|
//
|
|
// Purpose: Maps the current state of a set of radio buttons to a DWORD
|
|
// value based on a mapping table.
|
|
//
|
|
// Arguments:
|
|
// hDlg [in] Window handle of parent dialog.
|
|
// crbm [in] Count of elements in array pointed to by arbm.
|
|
// arbm [in] Array of elements that map a radio button control id to
|
|
// its associated value.
|
|
// pdwValue [out] The returned value.
|
|
//
|
|
// Returns: TRUE if a radio button was set and the value returned.
|
|
// FALSE otherwise.
|
|
//
|
|
// Author: shaunco 24 Mar 1997
|
|
//
|
|
// Notes: Don't forget to declare your array as 'static const'.
|
|
//
|
|
NOTHROW
|
|
BOOL
|
|
FMapRadioButtonToValue (
|
|
IN HWND hDlg,
|
|
IN INT crbm,
|
|
IN const RADIO_BUTTON_MAP* arbm,
|
|
OUT DWORD* pdwValue)
|
|
{
|
|
Assert (IsWindow (hDlg));
|
|
Assert (FImplies (crbm, arbm));
|
|
Assert (pdwValue);
|
|
|
|
while (crbm--)
|
|
{
|
|
// If it is set, return the corresponding value.
|
|
if (BST_CHECKED & IsDlgButtonChecked (hDlg, arbm->cid))
|
|
{
|
|
*pdwValue = arbm->dwValue;
|
|
return TRUE;
|
|
}
|
|
|
|
arbm++;
|
|
}
|
|
*pdwValue = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FMapValueToRadioButton
|
|
//
|
|
// Purpose: Set the state of a set of radio buttons based on the value of
|
|
// of a DWORD and a mapping table.
|
|
//
|
|
// Arguments:
|
|
// hDlg [in] Window handle of parent dialog.
|
|
// crbm [in] Count of elements in array pointed to by arbm.
|
|
// arbm [in] Array of elements that map a radio button control id to
|
|
// its associated value.
|
|
// dwValue [in] value which gets mapped to set the appropriate radio
|
|
// button.
|
|
//
|
|
// Returns: TRUE if dwValue was found in the map. FALSE otherwise.
|
|
//
|
|
// Author: shaunco 24 Mar 1997
|
|
//
|
|
// Notes: Don't forget to declare your array as 'static const'.
|
|
//
|
|
NOTHROW
|
|
BOOL
|
|
FMapValueToRadioButton (
|
|
IN HWND hDlg,
|
|
IN INT crbm,
|
|
IN const RADIO_BUTTON_MAP* arbm,
|
|
IN DWORD dwValue,
|
|
IN INT* pncid)
|
|
{
|
|
Assert (IsWindow (hDlg));
|
|
Assert (FImplies (crbm, arbm));
|
|
|
|
while (crbm--)
|
|
{
|
|
if (dwValue == arbm->dwValue)
|
|
{
|
|
// Set the radio button.
|
|
CheckDlgButton (hDlg, arbm->cid, BST_CHECKED);
|
|
|
|
// Return the control id if requested.
|
|
if (pncid)
|
|
{
|
|
*pncid = arbm->cid;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
arbm++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetIntegerFormat
|
|
//
|
|
// Purpose: Uses GetNumberFormat to format an integer number.
|
|
//
|
|
// Arguments:
|
|
// Locale [in] See Win32 API description of GetNumberFormat.
|
|
// pszValue [in]
|
|
// pszFormattedValue [out]
|
|
// cchFormattedValue [in]
|
|
//
|
|
// Returns: return value from GetNumberFormat
|
|
//
|
|
// Author: shaunco 4 May 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
INT
|
|
GetIntegerFormat (
|
|
IN LCID Locale,
|
|
IN PCWSTR pszValue,
|
|
OUT PWSTR pszFormattedValue,
|
|
IN INT cchFormattedValue)
|
|
{
|
|
// Format the number for the user's locale and preferences.
|
|
//
|
|
WCHAR szGrouping [16];
|
|
GetLocaleInfo (Locale, LOCALE_SGROUPING,
|
|
szGrouping, celems(szGrouping));
|
|
|
|
WCHAR szDecimalSep [16];
|
|
GetLocaleInfo (Locale, LOCALE_SDECIMAL,
|
|
szDecimalSep, celems(szDecimalSep));
|
|
|
|
WCHAR szThousandSep [16];
|
|
GetLocaleInfo (Locale, LOCALE_STHOUSAND,
|
|
szThousandSep, celems(szThousandSep));
|
|
|
|
NUMBERFMT nf;
|
|
ZeroMemory (&nf, sizeof(nf));
|
|
nf.Grouping = wcstoul (szGrouping, NULL, 10);
|
|
nf.lpDecimalSep = szDecimalSep;
|
|
nf.lpThousandSep = szThousandSep;
|
|
|
|
return GetNumberFormat (
|
|
Locale,
|
|
0,
|
|
pszValue,
|
|
&nf,
|
|
pszFormattedValue,
|
|
cchFormattedValue);
|
|
}
|
|
|
|
INT
|
|
Format32bitInteger (
|
|
IN UINT32 unValue,
|
|
IN BOOL fSigned,
|
|
OUT PWSTR pszFormattedValue,
|
|
IN INT cchFormattedValue)
|
|
{
|
|
// Convert the number to a string.
|
|
//
|
|
WCHAR szValue [33];
|
|
|
|
*szValue = 0;
|
|
|
|
if (fSigned)
|
|
{
|
|
_itow ((INT)unValue, szValue, 10);
|
|
}
|
|
else
|
|
{
|
|
_ultow (unValue, szValue, 10);
|
|
}
|
|
|
|
// Format the number according to user locale settings.
|
|
//
|
|
INT cch = GetIntegerFormat (
|
|
LOCALE_USER_DEFAULT,
|
|
szValue,
|
|
pszFormattedValue,
|
|
cchFormattedValue);
|
|
if (!cch)
|
|
{
|
|
TraceHr(ttidError, FAL, HrFromLastWin32Error(), FALSE,
|
|
"GetIntegerFormat failed in Format32bitInteger");
|
|
|
|
lstrcpynW (pszFormattedValue, szValue, cchFormattedValue);
|
|
cch = lstrlenW (pszFormattedValue);
|
|
}
|
|
return cch;
|
|
}
|
|
|
|
INT
|
|
Format64bitInteger (
|
|
IN UINT64 ulValue,
|
|
IN BOOL fSigned,
|
|
OUT PWSTR pszFormattedValue,
|
|
IN INT cchFormattedValue)
|
|
{
|
|
// Convert the number to a string.
|
|
//
|
|
WCHAR szValue [32];
|
|
|
|
*szValue = 0;
|
|
|
|
if (fSigned)
|
|
{
|
|
_i64tow ((INT64)ulValue, szValue, 10);
|
|
}
|
|
else
|
|
{
|
|
_ui64tow (ulValue, szValue, 10);
|
|
}
|
|
|
|
// Format the number according to user locale settings.
|
|
//
|
|
INT cch = GetIntegerFormat (
|
|
LOCALE_USER_DEFAULT,
|
|
szValue,
|
|
pszFormattedValue,
|
|
cchFormattedValue);
|
|
if (!cch)
|
|
{
|
|
TraceHr(ttidError, FAL, HrFromLastWin32Error(), FALSE,
|
|
"GetIntegerFormat failed in Format64bitInteger");
|
|
|
|
lstrcpynW (pszFormattedValue, szValue, cchFormattedValue);
|
|
cch = lstrlenW (pszFormattedValue);
|
|
}
|
|
return cch;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SetDlgItemFormatted32bitInteger (
|
|
IN HWND hDlg,
|
|
IN INT nIdDlgItem,
|
|
IN UINT32 unValue,
|
|
IN BOOL fSigned)
|
|
{
|
|
// Format the number according to user locale settings.
|
|
//
|
|
WCHAR szFormattedValue[64];
|
|
|
|
Format32bitInteger(
|
|
unValue,
|
|
fSigned,
|
|
szFormattedValue,
|
|
celems(szFormattedValue));
|
|
|
|
// Display the number.
|
|
//
|
|
return SetDlgItemText (hDlg, nIdDlgItem, szFormattedValue);
|
|
}
|
|
|
|
BOOL
|
|
SetDlgItemFormatted64bitInteger (
|
|
IN HWND hDlg,
|
|
IN INT nIdDlgItem,
|
|
IN UINT64 ulValue,
|
|
IN BOOL fSigned)
|
|
{
|
|
// Format the number according to user locale settings.
|
|
//
|
|
WCHAR szFormattedValue[64];
|
|
|
|
Format64bitInteger(
|
|
ulValue,
|
|
fSigned,
|
|
szFormattedValue,
|
|
celems(szFormattedValue));
|
|
|
|
// Display the number.
|
|
//
|
|
return SetDlgItemText (hDlg, nIdDlgItem, szFormattedValue);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrNcQueryUserForRebootEx
|
|
//
|
|
// Purpose: Query the user to reboot. If he/she chooses yes, a reboot
|
|
// is initiated.
|
|
//
|
|
// Arguments:
|
|
// hwndParent [in] Parent window handle.
|
|
// pszCaption [in] Caption text.
|
|
// pszText [in] Message text.
|
|
// dwFlags [in] Control flags (QUFR_PROMPT | QUFR_REBOOT)
|
|
//
|
|
// Returns: S_OK if a reboot was requested, S_FALSE if the user
|
|
// didn't want to, or an error code otherwise.
|
|
//
|
|
// Author: danielwe 29 Oct 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
HrNcQueryUserForRebootEx (
|
|
IN HWND hwndParent,
|
|
IN PCWSTR pszCaption,
|
|
IN PCWSTR pszText,
|
|
IN DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
INT nRet = IDYES;
|
|
|
|
if (dwFlags & QUFR_PROMPT)
|
|
{
|
|
nRet = MessageBox (hwndParent, pszText, pszCaption,
|
|
MB_YESNO | MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
if (nRet == IDYES)
|
|
{
|
|
if (dwFlags & QUFR_REBOOT)
|
|
{
|
|
TOKEN_PRIVILEGES* ptpOld;
|
|
hr = HrEnableAllPrivileges (&ptpOld);
|
|
if (S_OK == hr)
|
|
{
|
|
if (!ExitWindowsEx (EWX_REBOOT, 10))
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
|
|
MemFree (ptpOld);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
TraceError("HrNcQueryUserForRebootEx", (hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrNcQueryUserForReboot
|
|
//
|
|
// Purpose: Query the user to reboot. If he/she chooses yes, a reboot
|
|
// is initiated.
|
|
//
|
|
// Arguments:
|
|
// hinst [in] Module instance with string ids.
|
|
// hwndParent [in] Parent window handle.
|
|
// unIdCaption [in] String id of caption text.
|
|
// unIdText [in] String id of message text.
|
|
// dwFlags [in] Control flags (QUFR_PROMPT | QUFR_REBOOT)
|
|
//
|
|
// Returns: S_OK if a reboot is initiated, S_FALSE if the user
|
|
// didn't want to, or an error code otherwise.
|
|
//
|
|
// Author: shaunco 2 Jan 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
HrNcQueryUserForReboot (
|
|
IN HINSTANCE hinst,
|
|
IN HWND hwndParent,
|
|
IN UINT unIdCaption,
|
|
IN UINT unIdText,
|
|
IN DWORD dwFlags)
|
|
{
|
|
PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
|
|
PCWSTR pszText = SzLoadString (hinst, unIdText);
|
|
|
|
HRESULT hr = HrNcQueryUserForRebootEx (hwndParent, pszCaption,
|
|
pszText, dwFlags);
|
|
|
|
TraceError("HrNcQueryUserForReboot", (hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrShell_NotifyIcon
|
|
//
|
|
// Purpose: HRESULT returning wrapper for Shell_NotifyIcon.
|
|
//
|
|
// Arguments:
|
|
// dwMessage [in]
|
|
// pData [in]
|
|
//
|
|
// Returns: S_OK or an error code.
|
|
//
|
|
// Author: shaunco 11 Nov 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT
|
|
HrShell_NotifyIcon (
|
|
IN DWORD dwMessage,
|
|
IN PNOTIFYICONDATA pData)
|
|
{
|
|
HRESULT hr = E_FAIL; // First time through, this will succeed
|
|
BOOL fr = FALSE;
|
|
BOOL fRetriedAlready = FALSE;
|
|
BOOL fAttemptRetry = FALSE;
|
|
INT iRetries = 0;
|
|
|
|
// Attempt the first time, and attempt again after an attempted correction
|
|
//
|
|
while ((hr == E_FAIL) || fAttemptRetry)
|
|
{
|
|
if (fAttemptRetry)
|
|
fRetriedAlready = TRUE;
|
|
|
|
fr = Shell_NotifyIcon(dwMessage, pData);
|
|
if (!fr)
|
|
{
|
|
if (dwMessage == NIM_ADD && !fRetriedAlready)
|
|
{
|
|
NOTIFYICONDATA nidDelete;
|
|
|
|
ZeroMemory (&nidDelete, sizeof(nidDelete));
|
|
nidDelete.cbSize = sizeof(NOTIFYICONDATA);
|
|
nidDelete.hWnd = pData->hWnd;
|
|
nidDelete.uID = pData->uID;
|
|
|
|
Shell_NotifyIcon(NIM_DELETE, &nidDelete);
|
|
|
|
fAttemptRetry = TRUE;
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
// We should not attempt [a|another] retry
|
|
//
|
|
fAttemptRetry = FALSE;
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fAttemptRetry = FALSE;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
// At this point, if hr == S_FALSE, it means that we tried to retry, and even that failed
|
|
// We need to convert this to E_FAIL so we still return what we did before
|
|
//
|
|
if (S_FALSE == hr)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
// If we successfully swapped an icon, we should assert and figure out why that
|
|
// went wrong.
|
|
//
|
|
if ((S_OK == hr) && fRetriedAlready)
|
|
{
|
|
TraceTag(ttidShellFolder, "We should debug this. We worked around a duplicate icon by removing "
|
|
"the old one and putting the new one in place");
|
|
}
|
|
|
|
TraceError("HrShell_NotifyIcon", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LresFromHr
|
|
//
|
|
// Purpose: Translates an HRESULT into a valid LRESULT to be returned by
|
|
// a dialog handler function.
|
|
//
|
|
// Arguments:
|
|
// hr [in] HRESULT to be translated.
|
|
//
|
|
// Returns: LRESULT
|
|
//
|
|
// Author: danielwe 24 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
LRESULT
|
|
LresFromHr (
|
|
IN HRESULT hr)
|
|
{
|
|
AssertSz (((LRESULT)hr) != PSNRET_INVALID, "Don't pass PSNRET_INVALID to "
|
|
"LresFromHr! Use equivalent NETCFG_E_* value instead!");
|
|
AssertSz (((LRESULT)hr) != PSNRET_INVALID_NOCHANGEPAGE, "Don't pass "
|
|
"PSNRET_INVALID_NOCHANGEPAGE to "
|
|
"LresFromHr! Use equivalent NETCFG_E_* value instead!");
|
|
|
|
if (NETCFG_E_PSNRET_INVALID == hr)
|
|
{
|
|
return PSNRET_INVALID;
|
|
}
|
|
|
|
if (NETCFG_E_PSNRET_INVALID_NCPAGE == hr)
|
|
{
|
|
return PSNRET_INVALID_NOCHANGEPAGE;
|
|
}
|
|
|
|
return (SUCCEEDED(hr)) ? PSNRET_NOERROR : (LRESULT)hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NcMsgBox
|
|
//
|
|
// Purpose: Displays a message box using resource strings and replaceable
|
|
// parameters.
|
|
//
|
|
// Arguments:
|
|
// hinst [in] hinstance for resource strings
|
|
// hwnd [in] parent window handle
|
|
// unIdCaption [in] resource id of caption string
|
|
// unIdFormat [in] resource id of text string (with %1, %2, etc.)
|
|
// unStyle [in] standard message box styles
|
|
// ... [in] replaceable parameters (optional)
|
|
// (these must be PCWSTRs as that is all
|
|
// FormatMessage handles.)
|
|
//
|
|
// Returns: the return value of MessageBox()
|
|
//
|
|
// Author: shaunco 24 Mar 1997
|
|
//
|
|
// Notes: FormatMessage is used to do the parameter substitution.
|
|
//
|
|
INT
|
|
WINAPIV
|
|
NcMsgBox (
|
|
IN HINSTANCE hinst,
|
|
IN HWND hwnd,
|
|
IN UINT unIdCaption,
|
|
IN UINT unIdFormat,
|
|
IN UINT unStyle,
|
|
IN ...)
|
|
{
|
|
PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
|
|
PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
|
|
|
|
PWSTR pszText = NULL;
|
|
va_list val;
|
|
va_start (val, unStyle);
|
|
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
|
|
va_end (val);
|
|
|
|
INT nRet = MessageBox (hwnd, pszText, pszCaption, unStyle);
|
|
LocalFree (pszText);
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NcMsgBoxWithVarCaption
|
|
//
|
|
// Purpose: Same as NcMsgBox, but allows a string parameter to be used
|
|
// for the caption.
|
|
//
|
|
// Arguments:
|
|
// hinst [in] hinstance for resource strings
|
|
// hwnd [in] parent window handle
|
|
// unIdCaption [in] resource id of caption string
|
|
// pszCaptionParam [in] string parameter to use for caption
|
|
// unIdFormat [in] resource id of text string (with %1, %2, etc.)
|
|
// unStyle [in] standard message box styles
|
|
// ... [in] replaceable parameters (optional)
|
|
// (these must be PCWSTRs as that is all
|
|
// FormatMessage handles.)
|
|
//
|
|
// Returns: the return value of MessageBox()
|
|
//
|
|
// Author: danielwe 29 Oct 1997
|
|
//
|
|
// Notes: FormatMessage is used to do the parameter substitution.
|
|
//
|
|
INT
|
|
WINAPIV
|
|
NcMsgBoxWithVarCaption (
|
|
HINSTANCE hinst,
|
|
HWND hwnd,
|
|
UINT unIdCaption,
|
|
PCWSTR pszCaptionParam,
|
|
UINT unIdFormat,
|
|
UINT unStyle,
|
|
...)
|
|
{
|
|
PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
|
|
PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
|
|
|
|
PWSTR pszNewCaption = NULL;
|
|
DwFormatStringWithLocalAlloc (pszCaption, &pszNewCaption, pszCaptionParam);
|
|
|
|
PWSTR pszText = NULL;
|
|
va_list val;
|
|
va_start (val, unStyle);
|
|
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
|
|
va_end (val);
|
|
|
|
INT nRet = MessageBox (hwnd, pszText, pszNewCaption, unStyle);
|
|
LocalFree (pszText);
|
|
LocalFree (pszNewCaption);
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NcMsgBoxWithWin32ErrorText
|
|
//
|
|
// Purpose: Displays a message box using a Win32 error code, resource
|
|
// strings and replaceable parameters.
|
|
// The output text is a combination of the user's format
|
|
// string (with parameter's replaced) and the Win32 error
|
|
// text as returned from FormatMessage. These two strings
|
|
// are combined using the IDS_TEXT_WITH_WIN32_ERROR resource.
|
|
//
|
|
// Arguments:
|
|
// dwError [in] Win32 error code
|
|
// hinst [in] Module instance where string resources live.
|
|
// hwnd [in] parent window handle
|
|
// unIdCaption [in] resource id of caption string
|
|
// unIdCombineFormat [in] resource id of format string to combine
|
|
// error text with unIdFormat text.
|
|
// unIdFormat [in] resource id of text string (with %1, %2, etc.)
|
|
// unStyle [in] standard message box styles
|
|
// ... [in] replaceable parameters (optional)
|
|
// (these must be PCWSTRs as that is all
|
|
// FormatMessage handles.)
|
|
//
|
|
// Returns: the return value of MessageBox()
|
|
//
|
|
// Author: shaunco 3 May 1997
|
|
//
|
|
// Notes: FormatMessage is used to do the parameter substitution.
|
|
//
|
|
NOTHROW
|
|
INT
|
|
WINAPIV
|
|
NcMsgBoxWithWin32ErrorText (
|
|
IN DWORD dwError,
|
|
IN HINSTANCE hinst,
|
|
IN HWND hwnd,
|
|
IN UINT unIdCaption,
|
|
IN UINT unIdCombineFormat,
|
|
IN UINT unIdFormat,
|
|
IN UINT unStyle,
|
|
IN ...)
|
|
{
|
|
// Get the user's text with parameter's replaced.
|
|
//
|
|
PCWSTR pszFormat = SzLoadString (hinst, unIdFormat);
|
|
PWSTR pszText;
|
|
va_list val;
|
|
va_start (val, unStyle);
|
|
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
pszFormat, 0, 0, (PWSTR)&pszText, 0, &val);
|
|
va_end(val);
|
|
|
|
// Get the error text for the Win32 error.
|
|
//
|
|
PWSTR pszError;
|
|
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
|
|
(PWSTR)&pszError, 0, NULL);
|
|
|
|
// Combine the user's text with the error text using IDS_TEXT_WITH_WIN32_ERROR.
|
|
//
|
|
PCWSTR pszTextWithErrorFmt = SzLoadString (hinst, unIdCombineFormat);
|
|
PWSTR pszTextWithError;
|
|
DwFormatStringWithLocalAlloc (pszTextWithErrorFmt, &pszTextWithError,
|
|
pszText, pszError);
|
|
|
|
PCWSTR pszCaption = SzLoadString (hinst, unIdCaption);
|
|
INT nRet = MessageBox (hwnd, pszTextWithError, pszCaption, unStyle);
|
|
|
|
LocalFree (pszTextWithError);
|
|
LocalFree (pszError);
|
|
LocalFree (pszText);
|
|
|
|
return nRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SendDlgItemsMessage
|
|
//
|
|
// Purpose: Send a group of dialog items the same message.
|
|
//
|
|
// Arguments:
|
|
// hDlg [in] Window handle of parent dialog.
|
|
// ccid [in] Count of elements in array pointed to by acid.
|
|
// acid [in] Array of control ids.
|
|
// unMsg [in] Message to send
|
|
// wParam [in] First message parameter
|
|
// lParam [in] Second message parameter
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// Author: shaunco 11 Jun 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID
|
|
SendDlgItemsMessage (
|
|
IN HWND hDlg,
|
|
IN INT ccid,
|
|
IN const INT* acid,
|
|
IN UINT unMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
Assert (IsWindow (hDlg));
|
|
Assert (FImplies (ccid, acid));
|
|
|
|
while (ccid--)
|
|
{
|
|
Assert (IsWindow (GetDlgItem (hDlg, *acid)));
|
|
|
|
SendDlgItemMessage (hDlg, *acid++, unMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function: SetDefaultButton
|
|
//
|
|
// Purpose: Set the new default pushbutton on a dialog
|
|
//
|
|
// Params: hdlg [in] - Dialog HWND
|
|
// iddef [in] - Id of new default pushbutton
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
VOID
|
|
SetDefaultButton(
|
|
IN HWND hdlg,
|
|
IN INT iddef)
|
|
{
|
|
HWND hwnd;
|
|
DWORD dwData;
|
|
|
|
Assert(hdlg);
|
|
|
|
dwData = SendMessage (hdlg, DM_GETDEFID, 0, 0L);
|
|
if ((HIWORD(dwData) == DC_HASDEFID) && LOWORD(dwData))
|
|
{
|
|
hwnd = GetDlgItem (hdlg, (INT)LOWORD(dwData));
|
|
if ((LOWORD(dwData) != iddef) && (hwnd))
|
|
{
|
|
SendMessage (hwnd, BM_SETSTYLE, (WPARAM)BS_PUSHBUTTON, TRUE);
|
|
}
|
|
}
|
|
|
|
SendMessage (hdlg, DM_SETDEFID,(WPARAM)iddef, 0L);
|
|
if (iddef)
|
|
{
|
|
hwnd = GetDlgItem (hdlg, iddef);
|
|
Assert(hwnd);
|
|
SendMessage (hwnd, BM_SETSTYLE, (WPARAM)BS_DEFPUSHBUTTON, TRUE);
|
|
}
|
|
}
|
|
|
|
static const CONTEXTIDMAP c_adwContextIdMap[] =
|
|
{
|
|
{ IDOK, IDH_OK, IDH_OK },
|
|
{ IDCANCEL, IDH_CANCEL, IDH_CANCEL },
|
|
{ 0, 0, 0 }, // end marker
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DwContextIdFromIdc
|
|
//
|
|
// Purpose: Converts the given control ID to a context help ID
|
|
//
|
|
// Arguments:
|
|
// idControl [in] Control ID to convert
|
|
//
|
|
// Returns: Context help ID for that control (mapping comes from help
|
|
// authors)
|
|
//
|
|
// Author: danielwe 27 May 1998
|
|
//
|
|
// Notes:
|
|
//
|
|
DWORD DwContextIdFromIdc(
|
|
PCCONTEXTIDMAP lpContextIdMap,
|
|
BOOL bJpn,
|
|
INT idControl)
|
|
{
|
|
DWORD idw;
|
|
|
|
Assert(lpContextIdMap);
|
|
|
|
for (idw = 0; lpContextIdMap[idw].idControl; idw++)
|
|
{
|
|
if (idControl == lpContextIdMap[idw].idControl)
|
|
{
|
|
if (!bJpn)
|
|
{
|
|
return lpContextIdMap[idw].dwContextId;
|
|
}
|
|
else
|
|
{
|
|
return lpContextIdMap[idw].dwContextIdJapan;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Not found, just return 0
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: OnHelpGeneric
|
|
//
|
|
// Purpose: Handles help generically
|
|
//
|
|
// Arguments:
|
|
// hwnd [in] HWND of parent window
|
|
// lParam [in] lParam of the WM_HELP message
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Author: danielwe 27 May 1998
|
|
// anbrad 18 May 1999 moved to common. common control id's added.
|
|
//
|
|
// Notes:
|
|
//
|
|
VOID OnHelpGeneric(
|
|
HWND hwnd,
|
|
LPHELPINFO lphi,
|
|
PCCONTEXTIDMAP pContextMap,
|
|
BOOL bJpn,
|
|
PCWSTR pszHelpFile)
|
|
{
|
|
static const TCHAR c_szWindowsHelpFile[] = TEXT("windows.hlp");
|
|
|
|
Assert(lphi);
|
|
|
|
if (lphi->iContextType == HELPINFO_WINDOW)
|
|
{
|
|
switch(lphi->iCtrlId)
|
|
{
|
|
case -1: // IDC_STATIC
|
|
break;
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
case IDABORT:
|
|
case IDRETRY:
|
|
case IDIGNORE:
|
|
case IDYES:
|
|
case IDNO:
|
|
case IDCLOSE:
|
|
case IDHELP:
|
|
WinHelp(hwnd, c_szWindowsHelpFile, HELP_CONTEXTPOPUP,
|
|
DwContextIdFromIdc(c_adwContextIdMap, bJpn, lphi->iCtrlId));
|
|
break;
|
|
default:
|
|
WinHelp(hwnd, pszHelpFile, HELP_CONTEXTPOPUP,
|
|
DwContextIdFromIdc(pContextMap, bJpn, lphi->iCtrlId));
|
|
}
|
|
}
|
|
}
|
|
|