SourceCode/PROMS/FONTS/Size Project/src/XMonoFontDialog.cpp

425 lines
13 KiB
C++

// XMonoFontDialog.cpp Version 1.1
//
// Author: Hans Dietrich
// hdietrich@gmail.com
//
// Description:
// XMonoFontDialog.cpp implements CXMonoFontDialog, a class to display
// a customized CFontDialog.
//
// History
// Version 1.1 - 2008 October 29
// - Fixed problem with small point sizes
//
// Version 1.0 - 2008 October 22
// - Initial public release
//
// License:
// This software is released into the public domain. You are free to use
// it in any way you like, except that you may not sell this source code.
//
// This software is provided "as is" with no expressed or implied warranty.
// I accept no liability for any damage or loss of business that this
// software may cause.
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XMonoFontDialog.h"
#include "XMonoFontDialogRes.h"
#include "XFontSize.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef __noop
#if _MSC_VER < 1300
#define __noop ((void)0)
#endif
#endif
#undef TRACE
#define TRACE __noop
//=============================================================================
// if you want to see the TRACE output, uncomment this line:
//#include "XTrace.h"
//=============================================================================
#pragma warning(disable : 4996) // disable bogus deprecation warning
#define TIMER_FONTLIST_SELCHANGE 1
#define TIMER_FONTSIZES_SELCHANGE 2
#define TIMER_FONTSIZES_UPDATE 3
static int CALLBACK EnumFontFamExProcSizes(const ENUMLOGFONTEX *lpelfe,
const NEWTEXTMETRICEX *lpntme,
DWORD FontType,
LPARAM lParam);
IMPLEMENT_DYNAMIC(CXMonoFontDialog, CDialog)
//=============================================================================
BEGIN_MESSAGE_MAP(CXMonoFontDialog, CDialog)
//=============================================================================
//{{AFX_MSG_MAP(CXMonoFontDialog)
ON_WM_CTLCOLOR()
ON_WM_TIMER()
ON_CBN_SELCHANGE(IDC_FONT_LIST, OnSelchangeFontList)
ON_CBN_SELCHANGE(IDC_FONT_SIZE, OnSelchangeFontSize)
ON_CBN_EDITCHANGE(IDC_FONT_SIZE, OnEditchangeFontSize)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//=============================================================================
CXMonoFontDialog::CXMonoFontDialog(LPLOGFONT lplfInitial,
DWORD /*dwFlags*/, // compatibility with CFontDialog
CDC* /*pdcPrinter*/, // compatibility with CFontDialog
CWnd* pParentWnd /*= NULL*/) :
// use string resource name to avoid resource id conflicts
CDialog(_T("IDD_XMONOFONTDIALOG"), pParentWnd)
//CDialog(IDD_XMONOFONTDIALOG, pParentWnd)
//=============================================================================
{
m_strFaceName = _T("");
m_strCaption = _T("Font");
m_strSampleText = _T("AaBbYyZz 0123456789");
m_strMonospacedLabel = _T("MONOSPACED");
m_Height = 0;
m_dwFontFilter = 0;
m_bShowMonospacedLabel = TRUE;
m_bShowMonospacedAsBold = TRUE;
memset(&m_lfInitial, 0, sizeof(LOGFONT));
memset(&m_lfCurrent, 0, sizeof(LOGFONT));
if (lplfInitial)
{
memcpy(&m_lfInitial, lplfInitial, sizeof(LOGFONT));
}
else
{
m_lfInitial.lfCharSet = DEFAULT_CHARSET;
_tcscpy(m_lfInitial.lfFaceName, _T("Courier"));
m_lfInitial.lfHeight = FontSize.GetFontHeight(10);
}
memcpy(&m_lfCurrent, &m_lfInitial, sizeof(LOGFONT));
m_nPointSize = FontSize.GetFontPointSize(m_lfInitial.lfHeight);
m_strFaceName = m_lfInitial.lfFaceName;
}
//=============================================================================
CXMonoFontDialog::~CXMonoFontDialog()
//=============================================================================
{
if (m_SampleFont.GetSafeHandle())
m_SampleFont.DeleteObject();
}
//=============================================================================
void CXMonoFontDialog::DoDataExchange(CDataExchange* pDX)
//=============================================================================
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CXMonoFontDialog)
DDX_Control(pDX, IDC_FONT_SIZE, m_FontSizes);
DDX_Control(pDX, IDC_FONT_SAMPLE, m_Sample);
DDX_Control(pDX, IDC_FONT_MONOSPACED, m_MonospacedLabel);
DDX_Control(pDX, IDC_FONT_LIST, m_FontList);
//}}AFX_DATA_MAP
}
//=============================================================================
BOOL CXMonoFontDialog::OnInitDialog()
//=============================================================================
{
m_FontList.SetFontFilter(m_dwFontFilter)
.SetFont(m_lfInitial)
.ShowMonospacedAsBold(m_bShowMonospacedAsBold);
CDialog::OnInitDialog();
// at this point the font list combo has been filled with font names
m_MonospacedLabel.SetWindowText(m_strMonospacedLabel);
int h = m_FontList.GetItemHeight(0);
m_FontSizes.SetItemHeight(-1, h);
SetWindowText(m_strCaption);
m_Sample.SetWindowText(m_strSampleText);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//=============================================================================
HBRUSH CXMonoFontDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
//=============================================================================
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// set MONOSPACED label to blue
CWnd *pMonoSpaced = GetDlgItem(IDC_FONT_MONOSPACED);
if (pMonoSpaced && pWnd)
{
if (pWnd->m_hWnd == pMonoSpaced->m_hWnd)
pDC->SetTextColor(RGB(0,0,255));
}
return hbr;
}
//=============================================================================
void CXMonoFontDialog::GetCurrentFont(LPLOGFONT lplf)
//=============================================================================
{
ASSERT(lplf);
if (lplf)
memcpy(lplf, &m_lfCurrent, sizeof(LOGFONT));
}
//=============================================================================
// called when user selects size in combo list
void CXMonoFontDialog::OnSelchangeFontSize()
//=============================================================================
{
TRACE(_T("in CXMonoFontDialog::OnSelchangeFontSize\n"));
SetTimer(TIMER_FONTSIZES_SELCHANGE, 50, 0);
}
//=============================================================================
// called when user types in size combo edit box
void CXMonoFontDialog::OnEditchangeFontSize()
//=============================================================================
{
TRACE(_T("in CXMonoFontDialog::OnEditchangeFontSize\n"));
SetTimer(TIMER_FONTSIZES_UPDATE, 50, 0);
}
//=============================================================================
// called when user selects font in combo list
void CXMonoFontDialog::OnSelchangeFontList()
//=============================================================================
{
TRACE(_T("in CXMonoFontDialog::OnSelchangeFontList\n"));
CString s = _T("");
CString strFont = _T("");
int index = m_FontList.GetCurSel();
if (index != CB_ERR)
{
m_FontList.GetLBText(index, strFont);
m_FontList.SetWindowText(strFont);
m_FontSizes.ResetContent();
DWORD dwFlags = m_FontList.GetItemData(index);
if (dwFlags & (XFONT_TRUETYPE | XFONT_OPENTYPE | XFONT_VECTOR))
{
// use standard set of sizes
TRACE(_T("open or true type or vector\n"));
static int nSizes[] = { 8, 9, 10, 11, 12, 14, 16, 18,
20, 22, 24, 26, 28, 36, 48, 72, -1 };
for (int i = 0; nSizes[i] != -1; i++)
{
s.Format(_T("%d"), nSizes[i]);
m_FontSizes.AddString(s);
}
}
else
{
// some other font type - enumerate sizes
m_FontList.GetLBText(index, s);
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet = DEFAULT_CHARSET;
_tcsncpy(lf.lfFaceName, s, sizeof(lf.lfFaceName)/sizeof(TCHAR)-1);
CClientDC dcClient(this);
TRACE(_T("===== STARTING SIZE ENUMERATION ===========\n"));
EnumFontFamiliesEx(dcClient, &lf,
(FONTENUMPROC) EnumFontFamExProcSizes, (LPARAM)&m_FontSizes, 0);
TRACE(_T("===== ENDING SIZE ENUMERATION ===========\n"));
}
}
// clear size selection
m_FontSizes.SetCurSel(-1);
// set size in combo edit box
s.Format(_T("%d"), m_nPointSize);
m_FontSizes.SetWindowText(s);
// try to select size in combo
index = m_FontSizes.FindStringExact(-1, s);
if (index != CB_ERR)
m_FontSizes.SetCurSel(index);
SetCurFont();
}
//=============================================================================
void CXMonoFontDialog::SetCurFont()
//=============================================================================
{
TRACE(_T("in CXMonoFontDialog::SetCurFont\n"));
int index = m_FontList.GetCurSel();
if (index != CB_ERR)
{
m_dwXFontFlags = m_FontList.GetItemData(index);
m_FontList.GetLBText(index, m_strFaceName);
}
CString s = _T("");
m_FontSizes.GetWindowText(s);
if (s.IsEmpty())
s = _T("10");
int n = _ttoi(s);
if (n > 0)
m_nPointSize = n;
TRACE(_T("SetCurFont: setting font to %s(%d)\n"), m_strFaceName, m_nPointSize);
// set sample font
memset(&m_lfCurrent, 0, sizeof(LOGFONT));
m_lfCurrent.lfHeight = FontSize.GetFontHeight(m_nPointSize);
m_Height = m_lfCurrent.lfHeight;
m_lfCurrent.lfCharSet = DEFAULT_CHARSET;
_tcsncpy(m_lfCurrent.lfFaceName, m_strFaceName,
sizeof(m_lfCurrent.lfFaceName)/sizeof(TCHAR)-1);
DWORD weight = (m_dwXFontFlags & XFONT_WEIGHT_MASK) >> 16;
m_lfCurrent.lfWeight = weight;
m_lfCurrent.lfItalic = (BYTE) (m_dwXFontFlags & XFONT_ITALIC);
if (m_SampleFont.GetSafeHandle())
m_SampleFont.DeleteObject();
m_SampleFont.CreateFontIndirect(&m_lfCurrent);
m_Sample.SetFont(&m_SampleFont);
// show / hide MONOSPACED label
BOOL bIsMonospaced = m_dwXFontFlags & XFONT_MONOSPACED;
m_MonospacedLabel.ShowWindow((bIsMonospaced && m_bShowMonospacedLabel) ?
SW_SHOW : SW_HIDE);
// enable bold typeface in combo list
m_FontList.SetBold(bIsMonospaced && m_bShowMonospacedAsBold);
}
//=============================================================================
void CXMonoFontDialog::OnOK()
//=============================================================================
{
CString s = _T("");
m_FontSizes.GetWindowText(s);
if (s.IsEmpty())
s = _T("10");
m_nPointSize = _ttoi(s);
if (m_nPointSize <= 0)
m_nPointSize = 10;
memset(&m_lfCurrent, 0, sizeof(LOGFONT));
m_lfCurrent.lfHeight = FontSize.GetFontHeight(m_nPointSize);
m_Height = m_lfCurrent.lfHeight;
m_lfCurrent.lfCharSet = DEFAULT_CHARSET;
_tcsncpy(m_lfCurrent.lfFaceName, m_strFaceName,
sizeof(m_lfCurrent.lfFaceName)/sizeof(TCHAR)-1);
DWORD weight = (m_dwXFontFlags & XFONT_WEIGHT_MASK) >> 16;
m_lfCurrent.lfWeight = weight;
m_lfCurrent.lfItalic = (BYTE) (m_dwXFontFlags & XFONT_ITALIC);
CDialog::OnOK();
}
//=============================================================================
void CXMonoFontDialog::OnTimer(UINT nIDEvent)
//=============================================================================
{
KillTimer(nIDEvent);
if (nIDEvent == TIMER_FONTSIZES_SELCHANGE)
{
SetCurFont();
}
else if (nIDEvent == TIMER_FONTSIZES_UPDATE)
{
// user is typing into combo edit box - check if what he has typed
// so far is a valid size, and select it if it is
CString strSize = _T("");
m_FontSizes.GetWindowText(strSize);
int index = m_FontSizes.FindStringExact(-1, strSize);
if (index != CB_ERR)
{
TRACE(_T("found size at %d\n"), index);
m_FontSizes.SetCurSel(index);
}
OnSelchangeFontSize();
}
CDialog::OnTimer(nIDEvent);
}
#pragma warning(push)
#pragma warning(disable: 4100)
//=============================================================================
// This function is the enumeration callback for font sizes.
// Its purpose is to fill the size combo with non-duplicate
// sizes, making sure that they are entered in numerical order.
int CALLBACK EnumFontFamExProcSizes(const ENUMLOGFONTEX *lpelfe,
const NEWTEXTMETRICEX *lpntme,
DWORD FontType,
LPARAM lParam)
//=============================================================================
{
// the lParam is a pointer to the size combobox
CComboBox *pCombo = (CComboBox *) lParam;
ASSERT(pCombo);
ASSERT(IsWindow(pCombo->m_hWnd));
int nFontHeight = lpntme->ntmTm.tmHeight - lpntme->ntmTm.tmInternalLeading;
int nPointSize = FontSize.GetFontPointSize(nFontHeight);
TRACE(_T("_____ %s nPointSize=%d FontType=0x%X\n"),
lpelfe->elfLogFont.lfFaceName,
nPointSize,
FontType);
TCHAR szSize[100];
_stprintf(szSize, _T("%d"), nPointSize);
if (pCombo->FindStringExact(-1, szSize) == CB_ERR)
{
// size is not in list
// the sizes are not always enumerated in numerical order,
// so we have to check where to insert this size
// (example: Terminal font)
BOOL bAdded = FALSE;
int n = 0;
int count = pCombo->GetCount();
TCHAR szEntry[100];
for (int i = 0; i < count; i++)
{
szEntry[0] = 0;
pCombo->GetLBText(i, szEntry);
n = _ttoi(szEntry);
if (nPointSize < n)
{
VERIFY(pCombo->InsertString(i, szSize) >= 0);
bAdded = TRUE;
break;
}
}
if (!bAdded)
VERIFY(pCombo->AddString(szSize) >= 0);
}
return TRUE; // continue enumeration
}
#pragma warning(pop)