425 lines
13 KiB
C++
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)
|