/* 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) { StringCchPrintf(szTemp, ARRAYSIZE(szTemp), szPctD, i); TextOut(hdc, rc.left+1, rc.bottom-g.wHeight, szTemp, lstrlen(szTemp)); } } 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; StringCchPrintf(szBuf, ARRAYSIZE(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); StringCchPrintf(szBuf, ARRAYSIZE(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); StringCchPrintf(szBuf, ARRAYSIZE(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++) { StringCchPrintf(szBuf, ARRAYSIZE(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) { StringCchPrintf(szBuf, ARRAYSIZE(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); GetTextExtentPoint32(hdc, TEXT("0"), 1, &szSize); g.wWidth = szSize.cx; g.wHeight = szSize.cy; LoadString(HINST_THISDLL, IDS_RULERDIRECTION, g_szRulerDirections, ARRAYSIZE(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_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); }