WTL
开发时,我们开发自定义的窗口类,继承自CWindowImpl
,而这个类自带有SetFont
和GetFont
方法. 问题是调用了这个SetFont
方法,之后在调用GetFont
方法返回的HFONT
是NULL
, 怎么回事?在CWindowImpl
类里,SetFont
方法实际上就是发送了WM_SETFONT消息. 而WM_SETFONT的API
并没有说明提示设置字体不生效的情况。事实上,查阅网上的资料,对于自定义的控件(即内部是自定义WNDCLASS),不是系统自带的默认控件,系统不会处理WM_SETFONT
和WM_GETFONT
消息,需要自己处理这两个消息,也就是说并没有一个句柄HFONT
变量存储设置的值。
在自定义的控件里,我们可以在消息映射里处理这两个消息, 还需要添加一个HFONT
的实例变量来存储WM_SETFONT
消息设置的值.
MSG_WM_SETFONT(OnSetFont)
MSG_WM_GETFONT(OnGetFont);
CFont font_normal_;
HFONT CView::OnGetFont()
{
return font_normal_;
}
void CView::OnSetFont(CFontHandle font, BOOL bRedraw)
{
font_normal_ = font;
}
my_container.h 只是用来测试自定义窗口默认的SetFont
无效的窗口类.
CView.h 是增加了处理WM_SETFONT
和WM_GETFONT
消息的自定义窗口类.
// MyContainer.h : interface of the MyContainer class
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
#include
#include
#include
#include
#include
#include
class MyContainer : public CWindowImpl<MyContainer>
{
public:
DECLARE_WND_CLASS(NULL)
BOOL PreTranslateMessage(MSG* pMsg);
BEGIN_MSG_MAP_EX(MyContainer)
MSG_WM_CREATE(OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
int OnCreate(LPCREATESTRUCT lpCreateStruct);
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
private:
std::wstring GetControlText(HWND hwnd,wchar_t* buf = NULL);
CFont font_normal_;
CBrushHandle brush_white_;
CBrushHandle brush_hollow_;
CBrush brush_red_;
public:
};
// my_container.cpp : implementation of the MyContainer class
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "resource.h"
#include
#include
#include "my_container.h"
#include
#include
#include
BOOL MyContainer::PreTranslateMessage(MSG* pMsg)
{
return FALSE;
}
LRESULT MyContainer::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC dc(m_hWnd);
CMemoryDC mdc(dc,dc.m_ps.rcPaint);
CRect rect_client;
GetClientRect(&rect_client);
mdc.FillSolidRect(rect_client,RGB(255,0,0));
mdc.SetBkColor(RGB(255,0,0));
auto font = GetFont();
static const wchar_t* text = L"GetFont result is NULL";
if(font == NULL)
mdc.DrawText(text,wcslen(text),rect_client,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
return 0;
}
int MyContainer::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
brush_hollow_ = AtlGetStockBrush(HOLLOW_BRUSH);
brush_white_ = AtlGetStockBrush(WHITE_BRUSH);
brush_red_.CreateSolidBrush(RGB(255,0,0));
return 0;
}
// View.h : interface of the CView class
//
/////////////////////////////////////////////////////////////////////////////
#pragma once
#include
#include
#include
#include
#include
#include
#include "my_container.h"
class CView : public CWindowImpl<CView>
{
public:
DECLARE_WND_CLASS(NULL)
BOOL PreTranslateMessage(MSG* pMsg);
BEGIN_MSG_MAP_EX(CView)
MSG_WM_CREATE(OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MSG_WM_SETFONT(OnSetFont)
MSG_WM_GETFONT(OnGetFont);
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
int OnCreate(LPCREATESTRUCT lpCreateStruct);
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
private:
std::wstring GetControlText(HWND hwnd,wchar_t* buf = NULL);
void OnSetFont(CFontHandle font, BOOL bRedraw);
HFONT OnGetFont();
MyContainer container_;
CFont font_normal_;
CBrushHandle brush_white_;
CBrushHandle brush_hollow_;
CBrush brush_red_;
public:
};
// View.cpp : implementation of the CView class
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "resource.h"
#include
#include
#include "View.h"
#include
#include
#include
BOOL CView::PreTranslateMessage(MSG* pMsg)
{
return FALSE;
}
LRESULT CView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC dc(m_hWnd);
CMemoryDC mdc(dc,dc.m_ps.rcPaint);
CRect rect_client;
GetClientRect(&rect_client);
mdc.FillSolidRect(rect_client,RGB(255,255,255));
auto font = GetFont();
static const wchar_t* text = L"SetFont is not NULL";
if(font){
mdc.SelectFont(font);
mdc.DrawText(text,wcslen(text),rect_client,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
return 0;
}
static HFONT GetFont(int pixel,bool bold,const wchar_t* font_name)
{
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT)); // zero out structure
lf.lfHeight = pixel; // request a 8-pixel-height font
if(bold)
{
lf.lfWeight = FW_BOLD;
}
lstrcpy(lf.lfFaceName, font_name); // request a face name "Arial"
HFONT font = ::CreateFontIndirect(&lf);
return font;
}
static std::wstring GetProductBinDir()
{
static wchar_t szbuf[MAX_PATH];
GetModuleFileName(NULL,szbuf,MAX_PATH);
PathRemoveFileSpec(szbuf);
int length = lstrlen(szbuf);
szbuf[length] = L'\\';
szbuf[length+1] = 0;
return std::wstring(szbuf);
}
HFONT CView::OnGetFont()
{
return font_normal_;
}
void CView::OnSetFont(CFontHandle font, BOOL bRedraw)
{
font_normal_ = font;
}
int CView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
auto font = ::GetFont(20,false,L"Arial");
SetFont(font);
container_.Create(m_hWnd,CRect(CPoint(100,100),CSize(200,100)),L"MyContainer");
container_.SetFont(font);
brush_hollow_ = AtlGetStockBrush(HOLLOW_BRUSH);
brush_white_ = AtlGetStockBrush(WHITE_BRUSH);
brush_red_.CreateSolidBrush(RGB(255,0,0));
return 0;
}