|
|
//
// 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(WC_LISTVIEW, 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, 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, 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) { // NT5 has fontlink functionality
_s_uiFontAssocStatus = FAS_ENABLED; } *puiAssoced = _s_uiFontAssocStatus;
return hr; }
extern "C" { BOOL InitNativeFontCtl(HINSTANCE hinst) { WNDCLASS 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;
if (!RegisterClass(&wc) && !GetClassInfo(hinst, WC_NATIVEFONTCTL, &wc)) return FALSE;
return TRUE; }
};
|