WindowsXP-SP1/shell/themes/themeui/custfont.cpp
2020-09-30 16:53:49 +02:00

462 lines
14 KiB
C++

/* CUSTFONT.C
**
** Copyright (C) Microsoft, 1993, All Rights Reserved.
**
** History:
**
*/
#include "priv.h"
#pragma hdrstop
static struct
{
UINT wWidth;
UINT wHeight;
UINT wSizeFontId;
UINT wStartPos;
UINT wStartPix;
} g;
static UINT g_iCurPercent;
static RECT g_rcRuler;
static TCHAR g_szRulerDirections[200];
static TCHAR g_szSample[100];
static TCHAR g_szSampleFace[32];
static int g_cxRulerDirections;
static BOOL g_bTypeTimer = FALSE;
static TCHAR szPctD[] = TEXT("%d");
static TCHAR szPercentNum[] = TEXT("%d%%");
#define NUM_DEFPERCENTS 5
static UINT g_DefaultPercents[NUM_DEFPERCENTS] = {75, 100, 125, 150, 200};
#define MAX_PERCENT 500
#define MIN_PERCENT 20
#define GETPERCENT(dpi) ((dpi * 100 + 50) / 96)
#define GETDPI(percent) ((percent * 96 + 48) /100)
#define UPDATE_CURPER 0x0001
#define UPDATE_COMBO 0x0002
#define UPDATE_SAMPLE 0x0004
#define UPDATE_RULER 0x0008
#define UPDATE_ALL 0x000F
void NEAR PASCAL DrawRuler(HWND hDlg, LPDRAWITEMSTRUCT lpdis)
{
int nFact;
RECT rc;
HDC hdc;
int nPixInch;
int i, j;
TCHAR szTemp[10];
int nOldMode;
hdc = lpdis->hDC;
nOldMode = SetBkMode(hdc, TRANSPARENT);
// use g_rcRuler to draw the ruler. it's already been spaced
rc = g_rcRuler;
// first, draw the directions
i = rc.left + ((rc.right - rc.left) - g_cxRulerDirections)/2;
nPixInch = GETDPI(g_iCurPercent);
// draw the top and left edge of the ruler
DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOPLEFT);
// rest of drawing happens just below the top
rc.top += ClassicGetSystemMetrics(SM_CYEDGE);
nFact = 1;
// draw one of the etch heights (1", 1/2", 1/4") per iteration
for (j=0; j<3; ++j)
{
for (i=0; ; ++i)
{
rc.left = g_rcRuler.left + (j==0 ? i*nPixInch : (2*i+1)*nPixInch/nFact);
if (rc.left >= g_rcRuler.right)
{
break;
}
DrawEdge(hdc, &rc, EDGE_ETCHED, BF_LEFT | BF_ADJUST);
// dominant etch deserves a number
if (j == 0)
{
TextOut(hdc, rc.left+1, rc.bottom-g.wHeight,
szTemp, wsprintf(szTemp, szPctD, i));
}
}
rc.bottom -= (rc.bottom - rc.top)/2;
nFact *= 2;
}
SetBkMode(hdc, nOldMode);
}
void NEAR PASCAL CF_UpdateRuler(HWND hDlg)
{
RECT rc;
HWND hwnd;
/* Don't do this stuff if the dialog is not
** visible yet, or other windows will flash.
*/
if (IsWindowVisible(hDlg))
{
// don't invalidate top and left because they never change.
rc = g_rcRuler;
rc.left += ClassicGetSystemMetrics(SM_CXEDGE);
rc.top += ClassicGetSystemMetrics(SM_CYEDGE);
hwnd = GetDlgItem(hDlg, IDC_CUSTOMRULER);
InvalidateRect(hwnd, &rc, TRUE);
UpdateWindow(hwnd);
}
}
void NEAR PASCAL CF_ShowNewPercent(HWND hDlg, UINT uPer)
{
TCHAR szBuf[10];
g_iCurPercent = uPer;
wsprintf(szBuf, szPercentNum, uPer);
SetWindowText(GetDlgItem(hDlg, IDC_CUSTOMCOMBO), szBuf);
UpdateWindow(GetDlgItem(hDlg, IDC_CUSTOMCOMBO));
}
// Build lf with given face and height
//
int CALLBACK EnumProc(CONST LOGFONT *lplf, CONST TEXTMETRIC *lptm, DWORD nType, LPARAM lpData )
{
*(LPLOGFONT)lpData = *lplf;
return FALSE;
}
HFONT CreateFontWithFace(HWND hwnd, int nHeight, LPCTSTR lpszFace)
{
LOGFONT lf;
HDC hdc;
hdc = GetDC(hwnd);
if(hdc)
{
EnumFontFamilies(hdc, lpszFace, EnumProc, (LPARAM)&lf);
ReleaseDC(hwnd,hdc);
}
lf.lfHeight = nHeight;
lf.lfWidth = lf. lfEscapement = lf.lfOrientation = 0;
return CreateFontIndirect(&lf);
}
void NEAR PASCAL CF_UpdateData(HWND hDlg, UINT uPer, UINT flags)
{
TCHAR szBuf[100];
HFONT hfont;
int i;
HWND hwnd;
int iDPI;
if (flags & UPDATE_CURPER)
{
if (uPer == g_iCurPercent)
return;
if (uPer < MIN_PERCENT)
uPer = MIN_PERCENT;
else if (uPer > MAX_PERCENT)
uPer = MAX_PERCENT;
g_iCurPercent = uPer;
}
if (flags & UPDATE_COMBO)
{
hwnd = GetDlgItem(hDlg, IDC_CUSTOMCOMBO);
wsprintf(szBuf, szPercentNum, g_iCurPercent);
i = (int)SendMessage(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)szBuf);
SendMessage(hwnd, CB_SETCURSEL, (WPARAM)i, 0L);
if (i == -1)
{
SetWindowText(hwnd, szBuf);
UpdateWindow(hwnd);
}
}
if (flags & UPDATE_RULER)
CF_UpdateRuler(hDlg);
if (flags & UPDATE_SAMPLE)
{
iDPI = GETDPI(g_iCurPercent);
// build and set string with DPI info
hwnd = GetDlgItem(hDlg, IDC_CUSTOMSAMPLE);
wsprintf(szBuf, g_szSample, (LPTSTR)g_szSampleFace, iDPI);
SetWindowText(hwnd, szBuf);
hfont = CreateFontWithFace(hwnd, -10 * iDPI / 72, g_szSampleFace);
if (hfont)
{
hfont = (HFONT)SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, 1L);
if (hfont)
DeleteObject(hfont);
}
}
}
void NEAR PASCAL CF_ReadNewPercent(HWND hDlg)
{
TCHAR szBuf[10];
LPTSTR pstr;
UINT uPer = 0;
GetWindowText(GetDlgItem(hDlg, IDC_CUSTOMCOMBO), szBuf, ARRAYSIZE(szBuf));
pstr = szBuf;
while (*pstr && (*pstr != TEXT('%')))
{
if (*pstr >= TEXT('0') && *pstr <= TEXT('9'))
uPer = uPer * 10 + (*pstr - TEXT('0'));
pstr++;
}
CF_UpdateData(hDlg, uPer, UPDATE_ALL);
}
void NEAR PASCAL CF_InitDialog(HWND hDlg, UINT uDPI)
{
HWND hwnd;
HDC hdc;
HFONT hfont;
SIZE szSize;
int i;
TCHAR szBuf[10];
int iCurSel;
g_iCurPercent = GETPERCENT(uDPI);
hwnd = GetDlgItem(hDlg, IDC_CUSTOMCOMBO);
iCurSel = -1; // assume not in list
for (i = 0; i < NUM_DEFPERCENTS; i++)
{
wsprintf(szBuf, szPercentNum, g_DefaultPercents[i]);
SendMessage(hwnd, CB_INSERTSTRING, (WPARAM)i, (LPARAM)szBuf);
SendMessage(hwnd, CB_SETITEMDATA, (WPARAM)i, g_DefaultPercents[i]);
if (g_iCurPercent == g_DefaultPercents[i])
iCurSel = i;
}
SendMessage(hwnd, CB_SETCURSEL, (WPARAM)iCurSel, 0L);
if (iCurSel == -1)
{
wsprintf(szBuf, szPercentNum, g_iCurPercent);
SetWindowText(hwnd, szBuf);
}
hdc = GetDC(hDlg);
hfont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
if (hfont)
hfont = (HFONT) SelectObject(hdc, hfont);
//dwSize = GetTextExtentPoint32(hdc, TEXT("0"), 1);
GetTextExtentPoint32(hdc, TEXT("0"), 1, &szSize);
g.wWidth = szSize.cx;
g.wHeight = szSize.cy;
LoadString(HINST_THISDLL, IDS_RULERDIRECTION, g_szRulerDirections, ARRAYSIZE(g_szRulerDirections));
//g_cxRulerDirections = LOWORD(GetTextExtent(hdc, g_szRulerDirections, lstrlen(g_szRulerDirections)));
GetTextExtentPoint32(hdc, g_szRulerDirections, lstrlen(g_szRulerDirections), &szSize);
g_cxRulerDirections = szSize.cx;
if (hfont)
SelectObject(hdc, hfont);
ReleaseDC(hDlg, hdc);
// calculate the rectangle for the actual ruler drawing in relation
// to its window
GetClientRect(GetDlgItem(hDlg, IDC_CUSTOMRULER), &g_rcRuler);
g_rcRuler.left += g.wWidth;
g_rcRuler.right -= g.wWidth;
// bottom offset like the sides
g_rcRuler.bottom -= g.wWidth;
LoadString(HINST_THISDLL, IDS_10PTSAMPLE, g_szSample, ARRAYSIZE(g_szSample));
LoadString(HINST_THISDLL, IDS_10PTSAMPLEFACENAME, g_szSampleFace, ARRAYSIZE(g_szSampleFace));
CF_UpdateData(hDlg, 0, UPDATE_SAMPLE);
}
/////////////////////////////////////////////////////////////////////////////
const static DWORD FAR aCustFontHelpIds[] = {
// IDC_NO_HELP_1, IDH_COMM_GROUPBOX,
IDC_CUSTOMCOMBO, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_CUSTOMFONT_LISTBOX,
IDC_CUSTOMRULER, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_CUSTOMFONT_RULER,
IDC_CUSTOMSAMPLE,IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_CUSTOMFONT_SAMPLE,
0, 0
};
INT_PTR CALLBACK CustomFontDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
HFONT hfont;
int i;
switch (uMessage)
{
case WM_CREATE:
break;
case WM_INITDIALOG:
CF_InitDialog(hDlg, (UINT)lParam);
break;
case WM_DESTROY:
hfont = (HFONT)SendDlgItemMessage(hDlg, IDC_CUSTOMSAMPLE, WM_GETFONT, 0, 0L);
if (hfont)
DeleteObject(hfont);
break;
case WM_DRAWITEM:
if (wParam == IDC_CUSTOMRULER)
DrawRuler(hDlg, (LPDRAWITEMSTRUCT)lParam);
break;
case WM_TIMER:
if (g_bTypeTimer)
{
KillTimer(hDlg, 13);
g_bTypeTimer = FALSE;
CF_ReadNewPercent(hDlg);
}
break;
case WM_HELP:
WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP,
(DWORD_PTR)(LPTSTR)aCustFontHelpIds);
break;
case WM_CONTEXTMENU:
WinHelp((HWND)wParam, TEXT("display.hlp"), HELP_CONTEXTMENU,
(DWORD_PTR)(LPTSTR)aCustFontHelpIds);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, GETDPI(g_iCurPercent));
break;
case IDCANCEL:
EndDialog(hDlg, 0);
break;
case IDC_CUSTOMRULER:
switch (HIWORD(wParam))
{
case DSN_NCCREATE:
SetWindowLong((HWND)lParam, GWL_EXSTYLE,
GetWindowLong((HWND)lParam, GWL_EXSTYLE) | WS_EX_WINDOWEDGE);
break;
case DSN_BEGINDRAG:
// Set the focus to the corresponding edit ctl
SendMessage(hDlg, WM_NEXTDLGCTL,
(WPARAM)GetDlgItem(hDlg, IDC_CUSTOMCOMBO), 1L);
SendMessage((HWND)lParam, DSM_DRAGPOS, 0, (LPARAM)&(g.wStartPos));
if ((int)g.wStartPos < g_rcRuler.left)
{
g.wStartPos = g_rcRuler.left;
}
g.wStartPix = g_iCurPercent;
break;
case DSN_DRAGGING:
{
UINT wNow, wPix;
POINT pt;
//wNow = LOWORD(SendMessage((HWND)lParam, DSM_DRAGPOS, 0, 0L));
SendMessage((HWND)lParam, DSM_DRAGPOS, 0, (LPARAM)&pt);
wNow = pt.x;
if ((int)wNow < g_rcRuler.left)
{
wNow = g_rcRuler.left;
}
wPix = LOWORD((DWORD)wNow*g.wStartPix/g.wStartPos);
if (wPix < MIN_PERCENT)
{
wPix = MIN_PERCENT;
}
if (wPix > MAX_PERCENT)
{
wPix = MAX_PERCENT;
}
if (wPix != g_iCurPercent)
{
CF_ShowNewPercent(hDlg, wPix);
CF_UpdateRuler(hDlg);
}
break;
}
case DSN_ENDDRAG:
CF_UpdateData(hDlg, 0, UPDATE_COMBO | UPDATE_SAMPLE);
break;
default:
break;
}
break;
case IDC_CUSTOMCOMBO:
switch(HIWORD(wParam))
{
case CBN_SELCHANGE:
i = (int)SendDlgItemMessage(hDlg, IDC_CUSTOMCOMBO, CB_GETCURSEL, 0, 0L);
if (i != CB_ERR)
{
i = LOWORD(SendDlgItemMessage(hDlg, IDC_CUSTOMCOMBO, CB_GETITEMDATA, (WPARAM)i, 0L));
CF_UpdateData(hDlg, (UINT)i, UPDATE_CURPER | UPDATE_SAMPLE | UPDATE_RULER);
}
break;
case CBN_EDITCHANGE:
if (g_bTypeTimer)
{
KillTimer(hDlg, 13);
}
g_bTypeTimer = TRUE;
SetTimer(hDlg, 13, 500, NULL);
break;
}
break;
default:
return(FALSE);
}
break;
default:
return(FALSE);
}
return(TRUE);
}