65.9K
CodeProject 正在变化。 阅读更多。
Home

基于 WTL 的字体预览组合框

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.25/5 (4投票s)

2000年8月24日

viewsIcon

87051

downloadIcon

2338

一个字体组合框, 在下拉视图中预览字体。

  • 下载源代码文件 - 19 Kb
  • 下载演示项目 - 10 Kb
  • 概述

    本文介绍了如何实现这个字体预览组合框的拥有者绘制部分。我不会讨论窗口子类化,但我会使用一个我继承的子类。我将详细指导您如何在自己的程序中使用这个子类控件。

    我如何得到这个带字体预览的组合框

    很久以前,我第一次启动Word2000。我注意到一些类似扁平化控件、酷炫的rebar实现,以及最重要的,那个看起来很棒的字体选择器,它在你滚动时预览字体。2000年8月初,我下载了Konstantin Bukreev的kPad,它几乎拥有Office2000的外观和感觉(主要是rebar),但缺少那个炫酷的字体选择器。于是我决定实现它,因为kPad的源代码已经自带了一个子类字体组合框。

    要求

    在你继续下载源代码使用之前,请确保你已经下载了包含WTL头文件的Platform SDK(请参阅本站的另一篇文章)。我包含了kFlatCombo、kFontCombo和atl/aux(后者由Andrew Nosenko提供)的原始包含文件。我修改了kFontCombo的实现,因为一些数据成员是私有的,无法通过继承访问。如果你想理解源代码,你还应该了解WTL中的拥有者绘制控件和子类化。

    我的操作方法

    正如我在《概述》中提到的,我主要依赖于其他开发者的类/代码。我继承了kFontCombo,在我将其数据成员从private更改为protected之后,我就可以在新的子类中访问它们了。然后我使用WTL链接方法来接收来自基类的消息。拥有者绘制 你可以看到,正如上面截图中的组合框,它不只包含文本项。它在适当的时候绘制TrueType符号,并使用字体本身的名称预览字体,就像Word2000的字体选择器一样。除此之外,它还继承了行为,使其像一个扁平化控件。通过重写MeasureItemDrawItem方法,你可以将任何东西放入组合框。Windows将遍历组合框中的所有项,并通过调用(MeasureItem)询问每项的尺寸。之后,它会要求你绘制每个项,并提供可用尺寸的信息(DrawItem)。当Windows请求每项的最小尺寸时,我返回0作为宽度,20像素作为高度。然后Windows要求我绘制每项的内容,我只需从基类检索字体名称,创建一个带有该名称的字体对象,绘制文本,恢复之前的字体,就大功告成了。

    LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, 
                LPARAM lParam, BOOL& /*bHandled*/)
    {
    	MEASUREITEMSTRUCT* pmis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
    	ATLASSERT(pmis->CtlType == ODT_COMBOBOX);
    
    	if (m_cyItem == -1)
    	{
    		// calculate height
    
    		CClientDC dc(m_hWnd);
    		HFONT hFont = ((HFONT)GetStockObject( DEFAULT_GUI_FONT ));
    		dc.SelectFont( hFont );
    		TEXTMETRIC tm;
    		dc.GetTextMetrics(&tm); 
    
    		pmis->itemHeight = tm.tmHeight + tm.tmInternalLeading;
    	}else
    		m_cyItem = 20;
    	pmis->itemHeight = m_cyItem;
    	return TRUE;			
    }
    
    RESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, 
                LPARAM lParam, BOOL& /*bHandled*/)
    {
    	// ...
    
    	// After: rc.left += GLYPH_WIDTH + 2;
    
    
    	CFont cf;
    
    	cf.CreateFont(20,0,0,0,FW_NORMAL,FALSE, FALSE, FALSE,
                DEFAULT_CHARSET ,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
                ANTIALIASED_QUALITY,DEFAULT_PITCH,psFont);
    	HFONT hf = dc.SelectFont(cf);
    	dc.TextOut(rc.left+10, rc.top, psFont);
    	dc.SelectFont(hf);
    
    	// Before:dc.RestoreDC(nIndexDC);
    
    	// ...
    
    }
    

    如何在你的应用程序中使用它

    我将通过我的演示应用程序来解释如何在自己的应用程序中使用这个类。只需下载源代码看看即可。

    • 打开项目文件后,您可以看到我只是在对话框上添加了一个普通的组合框
    • 要使用新类,您需要包含其头文件以及它所依赖的头文件。这些是“AtlAux2.h”、“kFlatCombo.h”、“kFontCombo.h”和“rsPreviewFontCombo.h”,位于“include”目录中。
    • 在实现对话框的类(在此演示应用中是CMainDlg)中添加一个类型为rsFontPreviewCombo的数据成员。
    • 通过将以下代码添加到对话框类的OnInitDialog方法中来初始化组合框
      RECT rc;
      ::GetWindowRect(GetDlgItem(IDC_COMBO_FONT), &rc);
      ::DestroyWindow(GetDlgItem(IDC_COMBO_FONT));
      ScreenToClient(&rc);
      rc.bottom += 150;
      m_comboFontName.CreateEx(m_hWnd, rc, -1, IDC_COMBO_FONT);
    • 最后要做的是添加消息反射,以便子类控件能够接收消息。如果您不将REFLECT_NOTIFICATIONS()添加到消息映射中,组合框将不会包含任何内容。

    参与规则

    我希望这篇文章能让你有所启发,可以随意使用(和滥用)它。如果你愿意,可以对其进行扩展、修复bug和改进。如果你认为这些例程和文章的编写花费了大量时间,并打算使用,那么在你的程序或文档中给我(和其他人)署名,那将是很好的。


    关于我,我自己

    我叫Ramon Smits,住在荷兰鹿特丹附近。我的职业是软件开发,我在InfoSupport公司工作。我使用C++、VB、(D)HTML、JavaScript、ASP、T-SQL等编程语言进行开发。我过去使用的语言有Borland Pascal,甚至x86汇编(如果真的需要,我仍然会用)。我也熟悉COM/MTS、COM+、ATL/WTL、STL、OLEDB、ADO、DirectX。所以你可以说,我可以在n层环境中的任何地方发挥作用:-) 我对SDM-II、Yourdon、Staged Delivery、OMT/UML和通用的OO设计有深入的了解。

    在工作中,我按照Microsoft DNA结构(最终会是.NET)进行开发,主要使用ASP、VB、SQL。但当我在家,没有什么可做,除了看Jerry Springer节目时,我会打开我漂亮的旧电脑,做一些酷炫的编码。我对3D引擎、粒子系统和通用图形编程有常识性的了解。如果你想了解更多关于我的信息,请访问我的网站:http://www.exyll.com


    欢迎给我发送bug、批评、评论、建议、改进意见,或者只是为了好玩而给我发邮件。

    我还写了另一篇关于如何在菜单中使用WTL实现渐变侧边栏的文章,也在本站发表。

    © . All rights reserved.