380 lines
11 KiB
C++
380 lines
11 KiB
C++
|
|
// File: dlgcset.cpp
|
|
|
|
// This file contains the code that implements CNativeFont class.
|
|
|
|
// history:
|
|
// 7-21-97 created;
|
|
|
|
#include "ctlspriv.h"
|
|
#include "ccontrol.h"
|
|
|
|
#define THISCLASS CNativeFont
|
|
#define SUPERCLASS CControl
|
|
|
|
typedef enum
|
|
{
|
|
FAS_NOTINITIALIZED = 0,
|
|
FAS_DISABLED,
|
|
FAS_ENABLED,
|
|
} FASTATUS;
|
|
|
|
class CNativeFont : public CControl
|
|
{
|
|
public:
|
|
//Function Memebers
|
|
virtual LRESULT v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
static LRESULT NativeFontWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
protected:
|
|
|
|
CNativeFont();
|
|
|
|
//Function Members
|
|
|
|
virtual void v_OnPaint(HDC hdc) ;
|
|
virtual LRESULT v_OnCreate();
|
|
virtual void v_OnSize(int x, int y) {};
|
|
|
|
virtual LRESULT v_OnCommand(WPARAM wParam, LPARAM lParam);
|
|
virtual LRESULT v_OnNotify(WPARAM wParam, LPARAM lParam);
|
|
virtual DWORD v_OnStyleChanged(WPARAM wParam, LPARAM lParam) { return 0; };
|
|
|
|
HRESULT _GetNativeDialogFont(HWND hDlg);
|
|
static HRESULT _GetFontAssocStatus(FASTATUS *uiAssoced);
|
|
static BOOL _SetFontEnumProc(HWND hwnd, LPARAM lparam);
|
|
static LRESULT _SubclassDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam, WPARAM uIdSubclass, ULONG_PTR dwRefData);
|
|
|
|
HFONT m_hfontOrg;
|
|
HFONT m_hfontNative;
|
|
HFONT m_hfontDelete;
|
|
typedef struct {
|
|
HFONT hfontSet;
|
|
DWORD dwStyle;
|
|
} NFENUMCHILDDATA;
|
|
static FASTATUS _s_uiFontAssocStatus;
|
|
};
|
|
|
|
// static variable initialization
|
|
FASTATUS CNativeFont::_s_uiFontAssocStatus = FAS_NOTINITIALIZED;
|
|
|
|
// reg keys
|
|
static const TCHAR s_szRegFASettings[] = TEXT("System\\CurrentControlSet\\Control\\FontAssoc\\Associated Charset");
|
|
|
|
CNativeFont::CNativeFont(void)
|
|
{
|
|
m_hfontOrg = NULL;
|
|
m_hfontNative = NULL;
|
|
m_hfontDelete = NULL;
|
|
}
|
|
|
|
LRESULT THISCLASS::NativeFontWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CNativeFont *pn = (CNativeFont *)GetWindowLongPtr(hwnd, 0);
|
|
if (uMsg == WM_CREATE) {
|
|
ASSERT(!pn);
|
|
pn = new CNativeFont();
|
|
if (!pn)
|
|
return 0L;
|
|
}
|
|
|
|
if (pn) {
|
|
return pn->v_WndProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
void THISCLASS::v_OnPaint(HDC hdc)
|
|
{
|
|
return;
|
|
}
|
|
|
|
LRESULT THISCLASS::v_OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// forward to parent (do we really need this?)
|
|
return SendMessage(ci.hwndParent, WM_COMMAND, wParam, lParam);
|
|
}
|
|
|
|
LRESULT THISCLASS::v_OnNotify(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// forward to parent
|
|
LPNMHDR lpNmhdr = (LPNMHDR)lParam;
|
|
|
|
return SendNotifyEx(ci.hwndParent, (HWND) -1,
|
|
lpNmhdr->code, lpNmhdr, ci.bUnicode);
|
|
}
|
|
|
|
LRESULT THISCLASS::v_OnCreate()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL THISCLASS::_SetFontEnumProc(HWND hwnd, LPARAM lparam)
|
|
{
|
|
NFENUMCHILDDATA * pdt = (NFENUMCHILDDATA *)lparam;
|
|
BOOL bMatch = FALSE;
|
|
|
|
if (pdt && pdt->hfontSet)
|
|
{
|
|
if (pdt->dwStyle & NFS_ALL)
|
|
{
|
|
bMatch = TRUE;
|
|
}
|
|
else
|
|
{
|
|
TCHAR szClass[32];
|
|
|
|
GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
|
|
|
|
if (pdt->dwStyle & NFS_EDIT)
|
|
{
|
|
bMatch |= (lstrcmpi(TEXT("Edit"), szClass) == 0);
|
|
bMatch |= (lstrcmpi(TEXT("RichEdit20A"), szClass) == 0);
|
|
bMatch |= (lstrcmpi(TEXT("RichEdit20W"), szClass) == 0);
|
|
}
|
|
|
|
if (pdt->dwStyle & NFS_STATIC)
|
|
bMatch |= (lstrcmpi(TEXT("Static"), szClass) == 0);
|
|
|
|
if (pdt->dwStyle & NFS_BUTTON)
|
|
bMatch |= (lstrcmpi(TEXT("Button"), szClass) == 0);
|
|
|
|
if (pdt->dwStyle & NFS_LISTCOMBO)
|
|
{
|
|
bMatch |= (lstrcmpi(TEXT("ListBox"), szClass) == 0);
|
|
bMatch |= (lstrcmpi(TEXT("ComboBox"), szClass) == 0);
|
|
bMatch |= (lstrcmpi(TEXT("ComboBoxEx32"), szClass) == 0);
|
|
bMatch |= (lstrcmpi(TEXT("SysListView32"), szClass) == 0);
|
|
}
|
|
}
|
|
|
|
if (bMatch)
|
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)pdt->hfontSet, MAKELPARAM(FALSE, 0));
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
LRESULT THISCLASS::_SubclassDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam, WPARAM uIdSubclass, ULONG_PTR dwRefData)
|
|
{
|
|
LRESULT lret = 0;
|
|
CNativeFont * pnf = (CNativeFont *)dwRefData;
|
|
|
|
if (pnf)
|
|
{
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// we enumerate its children so they get font
|
|
// in native charset selected if necessary
|
|
|
|
if (S_OK == pnf->_GetNativeDialogFont(hdlg))
|
|
{
|
|
// S_OK means we have different charset from
|
|
// the default of the platform on which we're
|
|
// running.
|
|
NFENUMCHILDDATA dt;
|
|
dt.hfontSet = pnf->m_hfontNative;
|
|
dt.dwStyle = pnf->ci.style;
|
|
EnumChildWindows(hdlg, (WNDENUMPROC)pnf->_SetFontEnumProc, (LPARAM)&dt);
|
|
}
|
|
// we no longer need subclass procedure.
|
|
// assumes no one has subclassed this dialog by now
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
// if we've created a font, we have to clean it up.
|
|
if (pnf->m_hfontDelete)
|
|
{
|
|
NFENUMCHILDDATA dt;
|
|
|
|
dt.hfontSet = pnf->m_hfontOrg;
|
|
dt.dwStyle = pnf->ci.style;
|
|
// just in case anyone is still alive
|
|
EnumChildWindows(hdlg, (WNDENUMPROC)pnf->_SetFontEnumProc, (LPARAM)&dt);
|
|
DeleteObject(pnf->m_hfontDelete);
|
|
pnf->m_hfontDelete = NULL;
|
|
}
|
|
RemoveWindowSubclass(hdlg, pnf->_SubclassDlgProc, 0);
|
|
|
|
break;
|
|
}
|
|
|
|
lret = DefSubclassProc(hdlg, uMsg, wParam, lParam);
|
|
}
|
|
|
|
return lret;
|
|
}
|
|
|
|
LRESULT THISCLASS::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hdlg;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
// subclass the parent dialog just to get notified for WM_INITDIALOG
|
|
hdlg = GetParent(hwnd);
|
|
if (hdlg)
|
|
{
|
|
// if we had an error just do nothing, we have to succeed in creating
|
|
// window anyway otherwise dialog fails.
|
|
SetWindowSubclass(hdlg, _SubclassDlgProc, 0, (ULONG_PTR)this);
|
|
}
|
|
break;
|
|
}
|
|
return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
// _GetNativeDialogFont
|
|
|
|
// Retreive font handle in platform native character set
|
|
|
|
// returns S_OK if the given dialogbox requires setting font
|
|
// in native charset
|
|
// S_FALSE if the given dialogbox already has native
|
|
// charset.
|
|
// E_FAIL if anyother error occurs
|
|
|
|
HRESULT THISCLASS::_GetNativeDialogFont(HWND hDlg)
|
|
{
|
|
HRESULT hres = E_FAIL;
|
|
|
|
if(!m_hfontNative)
|
|
{
|
|
HFONT hfontNative, hfont = GetWindowFont(hDlg);
|
|
LOGFONT lf, lfNative;
|
|
FASTATUS uiFAStat = FAS_NOTINITIALIZED;
|
|
GetObject(hfont, sizeof(LOGFONT), &lf);
|
|
|
|
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lfNative, 0);
|
|
|
|
// there are two cases we don't want to create/set font
|
|
// for the platform native character set.
|
|
// 1) we already have matching character set
|
|
// 2) the platform has 'font assoc' enabled or 'font link'
|
|
// and our client wants to use it instead of
|
|
// setting the right character set. (NFS_USEFONTASSOC)
|
|
// this solution sometimes provides better
|
|
// appearance (thought it is broken in its
|
|
// font metrics) because it would use
|
|
// 'western font' as is.
|
|
if (ci.style & NFS_USEFONTASSOC)
|
|
{
|
|
_GetFontAssocStatus(&uiFAStat);
|
|
}
|
|
|
|
if ( uiFAStat == FAS_ENABLED
|
|
|| lfNative.lfCharSet == lf.lfCharSet)
|
|
{
|
|
|
|
m_hfontOrg = m_hfontNative = hfont;
|
|
}
|
|
else
|
|
{
|
|
// we have non-native charset for the platform
|
|
// Save away the original font first.
|
|
m_hfontOrg = hfont;
|
|
|
|
// Use the height of original dialog font
|
|
lfNative.lfHeight = lf.lfHeight;
|
|
if (!(hfontNative=CreateFontIndirect(&lfNative)))
|
|
{
|
|
hfontNative = hfont;
|
|
}
|
|
|
|
// save it away so we can delete it later
|
|
if (hfontNative != hfont)
|
|
m_hfontDelete = hfont;
|
|
|
|
// set this variable to avoid calling createfont twice
|
|
// if we get called again.
|
|
m_hfontNative = hfontNative;
|
|
}
|
|
}
|
|
|
|
return hres = (m_hfontNative == m_hfontOrg ? S_FALSE : S_OK);
|
|
}
|
|
|
|
|
|
// _GetFontAssocStatus
|
|
|
|
// synopsis: check to see if the platform has "Font Association"
|
|
// enabled or 'Font Link' capability
|
|
|
|
HRESULT THISCLASS::_GetFontAssocStatus(FASTATUS *puiAssoced)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ASSERT(puiAssoced);
|
|
|
|
// I assume the setting won't change without rebooting
|
|
// the system
|
|
|
|
if (FAS_NOTINITIALIZED == _s_uiFontAssocStatus)
|
|
{
|
|
if (g_bRunOnNT5)
|
|
{
|
|
// NT5 has fontlink functionality
|
|
_s_uiFontAssocStatus = FAS_ENABLED;
|
|
}
|
|
else
|
|
{
|
|
HKEY hkey;
|
|
TCHAR szYesOrNo[16] = {0};
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, s_szRegFASettings, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwSize = sizeof(szYesOrNo);
|
|
RegQueryValueEx(hkey, TEXT("ANSI(00)"), 0, NULL, (LPBYTE)szYesOrNo, &dwSize);
|
|
RegCloseKey(hkey);
|
|
}
|
|
else
|
|
{
|
|
// this only indicates the reg func failed
|
|
// we can't always assume the key is there (Western)
|
|
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && !lstrcmpi(szYesOrNo, TEXT("yes")))
|
|
{
|
|
// font assoc is enabled
|
|
_s_uiFontAssocStatus = FAS_ENABLED;
|
|
}
|
|
else
|
|
_s_uiFontAssocStatus = FAS_DISABLED;
|
|
}
|
|
}
|
|
*puiAssoced = _s_uiFontAssocStatus;
|
|
|
|
return hr;
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
BOOL InitNativeFontCtl(HINSTANCE hinst)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
if (!GetClassInfo(hinst, WC_NATIVEFONTCTL, &wc)) {
|
|
wc.lpfnWndProc = THISCLASS::NativeFontWndProc;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hIcon = NULL;
|
|
wc.lpszMenuName = NULL;
|
|
wc.hInstance = hinst;
|
|
wc.lpszClassName = WC_NATIVEFONTCTL;
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); // NULL;
|
|
wc.style = CS_GLOBALCLASS;
|
|
wc.cbWndExtra = sizeof(LPVOID);
|
|
wc.cbClsExtra = 0;
|
|
|
|
return RegisterClass(&wc);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
};
|