Leaked source code of windows server 2003
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.
 
 
 
 
 
 

759 lines
23 KiB

/**************************************************************************\
* Module Name: general.cpp
*
* Contains all the code to manage multiple devices
*
* Copyright (c) Microsoft Corp. 1995-1996 All Rights Reserved
*
* NOTES:
*
* History: Create by dli on 7/21/97
*
\**************************************************************************/
#include "priv.h"
#include "SettingsPg.h"
extern INT_PTR CALLBACK CustomFontDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
//-----------------------------------------------------------------------------
static const DWORD sc_GeneralHelpIds[] =
{
// font size
IDC_FONTSIZEGRP, NO_HELP, // IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE,
IDC_FONT_SIZE_STR, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE,
IDC_FONT_SIZE, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE,
IDC_CUSTFONTPER, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE,
// group box
IDC_DYNA, NO_HELP, // IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_DYNA,
// radio buttons
IDC_DYNA_TEXT, NO_HELP,
IDC_NODYNA, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_RESTART,
IDC_YESDYNA, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_DONT_RESTART,
IDC_SHUTUP, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_ASK_ME,
IDC_SETTINGS_GEN_COMPATWARNING, (DWORD)-1,
0, 0
};
/*--------------------------------------------------------------------------*
*--------------------------------------------------------------------------*/
class CGeneralDlg {
private:
int _idCustomFonts;
int _iDynaOrg;
IUnknown * _punkSite;
HWND _hwndFontList;
HWND _hDlg;
//
// current log pixels of the screen.
// does not change !
int _cLogPix;
BOOL _fForceSmallFont;
BOOL _InitFontList();
void _InitDynaCDSPreference();
LRESULT _OnNotify(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
public:
CGeneralDlg(GENERAL_ADVDLG_INITPARAMS * pInitParams);
void InitGeneralDlg(HWND hDlg);
void SetFontSizeText( int cdpi );
BOOL ChangeFontSize();
void HandleGeneralApply(HWND hDlg);
void HandleFontSelChange();
void ForceSmallFont();
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
CGeneralDlg::CGeneralDlg(GENERAL_ADVDLG_INITPARAMS * pInitParams) : _fForceSmallFont(pInitParams->fFoceSmallFont), _idCustomFonts(-1)
{
HKEY hkFont;
DWORD cb;
_punkSite = pInitParams->punkSite;
// For font size just always use the one of the current screen.
// Whether or not we are testing the current screen.
_cLogPix = 96;
// If the size does not match what is in the registry, then install
// the new one
if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE,
SZ_FONTDPI_PROF,
0,
KEY_READ,
&hkFont) == ERROR_SUCCESS) ||
(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
SZ_FONTDPI,
0,
KEY_READ,
&hkFont) == ERROR_SUCCESS))
{
cb = sizeof(DWORD);
if (RegQueryValueEx(hkFont,
SZ_LOGPIXELS,
NULL,
NULL,
(LPBYTE) &_cLogPix,
&cb) != ERROR_SUCCESS)
{
_cLogPix = 96;
}
RegCloseKey(hkFont);
}
};
//
// The purpose of this function is to check if the OriginalDPI value was already saved in the
// per-machine part of the registry. If this is NOT present, then get the system DPI and save it
// there. We want to do it just once for a machine. When an end-user logsin, we need to detect if
// we need to change the sizes of UI fonts based on DPI change. We use the "AppliedDPI", which is
// stored on the per-user branch of the registry to determine the dpi change. If this "AppliedDPI"
// is missing, then this OriginalDPI value will be used. If this value is also missing, that
// implies that nobody has changed the system DPI value.
//
void SaveOriginalDPI()
{
//See if the "OriginalDPI value is present under HKEY_LOCAL_MACHINE.
HKEY hk;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
SZ_CONTROLPANEL,
0,
KEY_READ | KEY_WRITE,
&hk) == ERROR_SUCCESS)
{
DWORD dwOriginalDPI;
DWORD dwDataSize = sizeof(dwOriginalDPI);
if (RegQueryValueEx(hk, SZ_ORIGINALDPI, NULL, NULL,
(LPBYTE)&dwOriginalDPI, &dwDataSize) != ERROR_SUCCESS)
{
//"OriginalDPI" value is not present in the registry. Now, get the DPI
// and save it as the "OriginalDPI"
HDC hdc = GetDC(NULL);
dwOriginalDPI = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc);
}
DWORD dwSize = sizeof(dwOriginalDPI);
//Save the current DPI as the "OriginalDPI" value.
RegSetValueEx(hk, SZ_ORIGINALDPI, NULL, REG_DWORD, (LPBYTE) &dwOriginalDPI, dwSize);
RegCloseKey(hk);
}
}
BOOL CGeneralDlg::ChangeFontSize()
{
int cFontSize = 0;
int cForcedFontSize;
int cUIfontSize;
// Change font size if necessary
int i = ComboBox_GetCurSel(_hwndFontList);
if (i != CB_ERR )
{
TCHAR awcDesc[10];
cFontSize = (int)ComboBox_GetItemData(_hwndFontList, i);
if ( (cFontSize != CB_ERR) &&
(cFontSize != 0) &&
(cFontSize != _cLogPix))
{
//Save the original DPI before the DPI ever changed.
SaveOriginalDPI();
cUIfontSize = cForcedFontSize = cFontSize;
if (_idCustomFonts == i)
{
BOOL predefined = FALSE;
int count = ComboBox_GetCount(_hwndFontList);
int max = -1, min = 0xffff, dpi;
for (i = 0; i < count; i++)
{
if (i == _idCustomFonts)
continue;
dpi = (int)ComboBox_GetItemData(_hwndFontList, i);
if (dpi == cFontSize)
{
predefined = TRUE;
break;
}
if (dpi < min) min = dpi;
if (dpi > max) max = dpi;
}
if (!predefined) {
if ((cFontSize > max) || (cFontSize + (max-min)/2 > max))
cForcedFontSize = max;
else
cForcedFontSize = min;
// Currently our Custom font picker allows end-users to pick upto 500% of
// normal font size; But, when we enlarge the UI fonts to this size, the
// system becomes un-usable after reboot. So, what we do here is to allow
// ui font sizes to grow up to 200% and then all further increases are
// proportionally reduced such that the maximum possible ui font size is only
// 250%. (i.e the range 200% to 500% is mapped on to a range of 200% to 250%)
// In other words, we allow upto 192 dpi (200%) with no modification. For any
// DPI greater than 192, we proportionately reduce it such that the highest DPI
// is only 240!
if(cUIfontSize > 192)
cUIfontSize = 192 + ((cUIfontSize - 192)/6);
}
}
// Call setup to change the font size.
StringCchPrintf(awcDesc, ARRAYSIZE(awcDesc), TEXT("%d"), cForcedFontSize);
if (SetupChangeFontSize(_hDlg, awcDesc) == NO_ERROR)
{
IPropertyBag * pPropertyBag;
// Font change has succeeded; Now there is a new DPI to be applied to UI fonts!
if (_punkSite && SUCCEEDED(GetPageByCLSID(_punkSite, &PPID_BaseAppearance, &pPropertyBag)))
{
// Use _punkSite to push the DPI back up to the Appearance tab where it's state lives.
LogStatus("CGeneralDlg::ChangeFontSize() user changed DPI to %d\r\n", cUIfontSize);
SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_DPI_MODIFIED_VALUE, cUIfontSize);
pPropertyBag->Release();
}
// A font size change will require a system reboot.
PropSheet_RestartWindows(GetParent(_hDlg));
HrRegSetDWORD(HKEY_LOCAL_MACHINE, SZ_FONTDPI_PROF, SZ_LOGPIXELS, cFontSize);
HrRegSetDWORD(HKEY_LOCAL_MACHINE, SZ_FONTDPI, SZ_LOGPIXELS, cFontSize);
}
else
{
// Setup failed.
FmtMessageBox(_hDlg,
MB_ICONSTOP | MB_OK,
ID_DSP_TXT_CHANGE_FONT,
ID_DSP_TXT_ADMIN_INSTALL);
return FALSE;
}
}
}
if (cFontSize == 0)
{
// If we could not read the inf, then ignore the font selection
// and don't force the reboot on account of that.
cFontSize = _cLogPix;
}
return TRUE;
}
void CGeneralDlg::InitGeneralDlg(HWND hDlg)
{
_hDlg = hDlg;
_hwndFontList = GetDlgItem(_hDlg, IDC_FONT_SIZE);
_InitFontList();
_iDynaOrg = -1;
}
void CGeneralDlg::_InitDynaCDSPreference()
{
int iDyna = GetDynaCDSPreference();
if(iDyna != _iDynaOrg)
{
_iDynaOrg = iDyna;
CheckDlgButton(_hDlg, IDC_SHUTUP, FALSE);
CheckDlgButton(_hDlg, IDC_YESDYNA, FALSE);
CheckDlgButton(_hDlg, IDC_NODYNA, FALSE);
if (_iDynaOrg & DCDSF_ASK)
CheckDlgButton(_hDlg, IDC_SHUTUP, TRUE);
else if (_iDynaOrg & DCDSF_DYNA)
CheckDlgButton(_hDlg, IDC_YESDYNA, TRUE);
else
CheckDlgButton(_hDlg, IDC_NODYNA, TRUE);
}
}
static UINT s_DPIDisplayNames[] =
{
96 /*DPI*/, IDS_SETTING_GEN_96DPI,
120 /*DPI*/, IDS_SETTING_GEN_120DPI,
};
HRESULT _LoadDPIDisplayName(int nDPI, LPTSTR pszDisplayName, DWORD cchSize)
{
HRESULT hr = E_FAIL;
int nIndex;
for (nIndex = 0; nIndex < ARRAYSIZE(s_DPIDisplayNames); nIndex += 2)
{
if (nDPI == (int)s_DPIDisplayNames[nIndex])
{
LoadString(HINST_THISDLL, s_DPIDisplayNames[nIndex + 1], pszDisplayName, cchSize);
hr = S_OK;
break;
}
}
return hr;
}
// Init Font sizes
//
// For NT:
// Read the supported fonts out of the inf file(s)
// Select was the user currently has.
//
BOOL CGeneralDlg::_InitFontList() {
int i;
ASSERT(_hwndFontList);
ULONG uCurSel = (ULONG) -1;
int cPix = 0;
TCHAR szBuf2[100];
HINF InfFileHandle;
INFCONTEXT infoContext;
//
// Get all font entries from both inf files
//
InfFileHandle = SetupOpenInfFile(TEXT("font.inf"),
NULL,
INF_STYLE_WIN4,
NULL);
if (InfFileHandle != INVALID_HANDLE_VALUE)
{
if (SetupFindFirstLine(InfFileHandle,
TEXT("Font Sizes"),
NULL,
&infoContext))
{
for (;;)
{
TCHAR awcDesc[LINE_LEN];
if (SetupGetStringField(&infoContext,
0,
awcDesc,
ARRAYSIZE(awcDesc),
NULL) &&
SetupGetIntField(&infoContext,
1,
&cPix))
{
// Add it to the list box
_LoadDPIDisplayName(cPix, awcDesc, ARRAYSIZE(awcDesc));
i = ComboBox_AddString(_hwndFontList, awcDesc);
if (i != CB_ERR)
{
ComboBox_SetItemData(_hwndFontList, i, cPix);
if (_cLogPix == cPix)
uCurSel = i;
}
}
//
// Try to get the next line.
//
if (!SetupFindNextLine(&infoContext,
&infoContext))
{
break;
}
}
}
SetupCloseInfFile(InfFileHandle);
}
//
// Put in the custom fonts string
//
LoadString(HINST_THISDLL, ID_DSP_CUSTOM_FONTS, szBuf2, ARRAYSIZE(szBuf2));
_idCustomFonts = ComboBox_AddString(_hwndFontList, szBuf2);
if (_idCustomFonts != CB_ERR)
ComboBox_SetItemData(_hwndFontList, _idCustomFonts, _cLogPix);
if (uCurSel == (ULONG) -1) {
uCurSel = _idCustomFonts;
}
// NOTE: We currently change the font size by calling SetupChangeFontSize
// This function will fail if the user is not an administrator. We would like to
// disable this functionality but system admins want to be able to allow
// non-admins to install by turning on a registry flag. NT4 supports this,
// so we need to also. In order for this to work, we need to leave the
// install button enabled. This backs out NT #318617. Contact
// the following people about this issue: Marius Marin, Tom Politis,
// Naresh Jivanji. -BryanSt 3/24/2000
// EnableWindow(_hwndFontList, IsUserAdmin());
if (_fForceSmallFont && (_cLogPix == 96))
this->ForceSmallFont();
else
{
//
// Select the right entry.
//
ComboBox_SetCurSel(_hwndFontList, uCurSel);
this->SetFontSizeText( _cLogPix );
}
return TRUE;
}
void CGeneralDlg::SetFontSizeText( int cdpi )
{
HWND hwndCustFontPer;
TCHAR achStr[80];
TCHAR achFnt[120];
if (cdpi == CDPI_NORMAL)
{
LoadString(HINST_THISDLL, ID_DSP_NORMAL_FONTSIZE_TEXT, achStr, ARRAYSIZE(achStr));
StringCchPrintf(achFnt, ARRAYSIZE(achFnt), achStr, cdpi);
}
else
{
LoadString(HINST_THISDLL, ID_DSP_CUSTOM_FONTSIZE_TEXT, achStr, ARRAYSIZE(achStr));
StringCchPrintf(achFnt, ARRAYSIZE(achFnt), achStr, (100 * cdpi + 50) / CDPI_NORMAL, cdpi );
}
hwndCustFontPer = GetDlgItem(_hDlg, IDC_CUSTFONTPER);
SendMessage(hwndCustFontPer, WM_SETTEXT, 0, (LPARAM)achFnt);
}
//
// ForceSmallFont method
//
//
void CGeneralDlg::ForceSmallFont() {
int i, iSmall, dpiSmall, dpi;
//
// Set small font size in the listbox.
//
iSmall = CB_ERR;
dpiSmall = 9999;
for (i=0; i <=1; i++)
{
dpi = (int)ComboBox_GetItemData(_hwndFontList, i);
if (dpi == CB_ERR)
continue;
if (dpi < dpiSmall || iSmall < CB_ERR)
{
iSmall = i;
dpiSmall = dpi;
}
}
if (iSmall != -1)
ComboBox_SetCurSel(_hwndFontList, iSmall);
this->SetFontSizeText(dpiSmall);
EnableWindow(_hwndFontList, FALSE);
}
void CGeneralDlg::HandleGeneralApply(HWND hDlg)
{
int iDynaNew;
if (IsDlgButtonChecked(hDlg, IDC_YESDYNA))
iDynaNew= DCDSF_YES;
else if (IsDlgButtonChecked(hDlg, IDC_NODYNA))
iDynaNew= DCDSF_NO;
else
iDynaNew = DCDSF_PROBABLY;
if (iDynaNew != _iDynaOrg)
{
SetDisplayCPLPreference(REGSTR_VAL_DYNASETTINGSCHANGE, iDynaNew);
_iDynaOrg = iDynaNew;
}
BOOL bSuccess = ChangeFontSize();
long lRet = (bSuccess ? PSNRET_NOERROR: PSNRET_INVALID_NOCHANGEPAGE);
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, lRet);
}
void CGeneralDlg::HandleFontSelChange()
{
//
// Warn the USER font changes will not be seen until after
// reboot
//
int iCurSel;
int cdpi;
iCurSel = ComboBox_GetCurSel(_hwndFontList);
cdpi = (int)ComboBox_GetItemData(_hwndFontList, iCurSel);
if (iCurSel == _idCustomFonts) {
InitDragSizeClass();
cdpi = (int)DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_CUSTOMFONT),
_hDlg, CustomFontDlgProc, cdpi );
if (cdpi != 0)
ComboBox_SetItemData(_hwndFontList, _idCustomFonts, cdpi);
else
cdpi = (int)ComboBox_GetItemData(_hwndFontList, _idCustomFonts);
}
if (cdpi != _cLogPix)
{
// Remove in blackcomb. We need to streamline this process. That includes verifying that
// the fonts will always be on disk and there is no need to allow users to get them from
// the CD.
FmtMessageBox(_hDlg,
MB_ICONINFORMATION,
ID_DSP_TXT_CHANGE_FONT,
ID_DSP_TXT_FONT_LATER);
PropSheet_Changed(GetParent(_hDlg), _hDlg);
}
this->SetFontSizeText(cdpi);
}
LRESULT CGeneralDlg::_OnNotify(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lReturn = TRUE;
NMHDR *lpnm = (NMHDR *)lParam;
if (lParam)
{
switch (lpnm->code)
{
case PSN_SETACTIVE:
_InitDynaCDSPreference();
break;
case PSN_APPLY:
HandleGeneralApply(hDlg);
break;
case NM_RETURN:
case NM_CLICK:
{
PNMLINK pNMLink = (PNMLINK) lpnm;
if (!StrCmpW(pNMLink->item.szID, L"idGameCompat"))
{
TCHAR szHelpURL[MAX_PATH * 2];
LoadString(HINST_THISDLL, IDS_SETTING_GEN_COMPAT_HELPLINK, szHelpURL, ARRAYSIZE(szHelpURL));
HrShellExecute(hDlg, NULL, szHelpURL, NULL, NULL, SW_NORMAL);
}
break;
}
default:
lReturn = FALSE;
break;
}
}
return lReturn;
}
LRESULT CALLBACK CGeneralDlg::WndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lReturn = TRUE;
switch (message)
{
case WM_INITDIALOG:
InitGeneralDlg(hDlg);
break;
case WM_NOTIFY:
lReturn = _OnNotify(hDlg, message, wParam, lParam);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_NODYNA:
case IDC_YESDYNA:
case IDC_SHUTUP:
if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
PropSheet_Changed(GetParent(hDlg), hDlg);
break;
case IDC_FONT_SIZE:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case CBN_SELCHANGE:
HandleFontSelChange();
break;
default:
break;
}
break;
default:
break;
}
break;
case WM_HELP:
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP,
(DWORD_PTR)(LPTSTR)sc_GeneralHelpIds);
break;
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, TEXT("display.hlp"), HELP_CONTEXTMENU,
(DWORD_PTR)(LPTSTR)sc_GeneralHelpIds);
break;
default:
return FALSE;
}
return lReturn;
}
//-----------------------------------------------------------------------------
//
// Callback functions PropertySheet can use
//
INT_PTR CALLBACK
GeneralPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
CGeneralDlg * pcgd = (CGeneralDlg * )GetWindowLongPtr(hDlg, DWLP_USER);
switch (message)
{
case WM_INITDIALOG:
ASSERT(!pcgd);
ASSERT(lParam);
if (((LPPROPSHEETPAGE)lParam)->lParam)
{
GENERAL_ADVDLG_INITPARAMS * pInitParams = (GENERAL_ADVDLG_INITPARAMS *) ((LPPROPSHEETPAGE)lParam)->lParam;
pcgd = new CGeneralDlg(pInitParams);
if(pcgd)
{
// now we need to init
pcgd->InitGeneralDlg(hDlg);
SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pcgd);
return TRUE;
}
}
break;
case WM_DESTROY:
if (pcgd)
{
SetWindowLongPtr(hDlg, DWLP_USER, NULL);
delete pcgd;
}
break;
default:
if (pcgd)
return pcgd->WndProc(hDlg, message, wParam, lParam);
break;
}
return FALSE;
}
/*--------------------------------------------------------------------------*
*--------------------------------------------------------------------------*/
INT_PTR CALLBACK AskDynaCDSProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
int *pTemp;
switch (msg)
{
case WM_INITDIALOG:
if ((pTemp = (int *)lp) != NULL)
{
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pTemp);
CheckDlgButton(hDlg, (*pTemp & DCDSF_DYNA)?
IDC_YESDYNA : IDC_NODYNA, BST_CHECKED);
}
else
EndDialog(hDlg, -1);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wp, lp))
{
case IDOK:
if ((pTemp = (int *)GetWindowLongPtr(hDlg, DWLP_USER)) != NULL)
{
*pTemp = IsDlgButtonChecked(hDlg, IDC_YESDYNA)? DCDSF_DYNA : 0;
if (!IsDlgButtonChecked(hDlg, IDC_SHUTUP))
*pTemp |= DCDSF_ASK;
SetDisplayCPLPreference(REGSTR_VAL_DYNASETTINGSCHANGE, *pTemp);
}
EndDialog(hDlg, TRUE);
break;
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
int AskDynaCDS(HWND hOwner)
{
int val = GetDynaCDSPreference();
if (val & DCDSF_ASK)
{
switch (DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_ASKDYNACDS),
hOwner, AskDynaCDSProc, (LPARAM)(int *)&val))
{
case 0: // user cancelled
return -1;
case -1: // dialog could not be displayed
val = DCDSF_NO;
break;
}
}
return ((val & DCDSF_DYNA) == DCDSF_DYNA);
}