浪迹天涯

唯有努力...
努力....再努力...

如何更改属性页向导页的字体

前段时间,一个底层开发的同事写一个MFC工具,在想实现设置属性页字体时遇到了困难,问我该如何实现?根据多年的经验,想当然的以为很简单,只需在资源里,更改对话框的字体即可,试了试不行;那就CreateFont,然后SetFont,可是无论怎么弄,程序运行后,属性页的字体依然如故!在网上搜索也没有找到好的解决办法,最后折腾许久,终于找到一篇文章,最终把这个问题解决了。
  
文章:http://support.microsoft.com/default.aspx?scid=kb;en-us;142170
示例下载:http://download.microsoft.com/download/vc60pro/samp40/1/win98/en-us/prpfont.exe

概要

PRPFONT 说明如何为您 CPropertyPages 在资源编辑器, 并在运行时设置所需字体, 设置要和一切正常大小相同表的字体。 所有这是一个类称为 CMySheet 中完成。 调用 ChangeDialogFont() 函数进行调整窗口以及设置字体工作。 CPropertySheet::BuildPropPageArray() 被覆盖以便不重置网页中字体。

更多信息

在 VisualC++ 的版本低于 4.0, MFC 必须自己实现 CPropertySheet。 对于您 CPropertySheet 通过资源编辑器中设置首 CPropertyPage 您对话框资源的字体可能设置字体。 在运行时, 表将使用字体设置并一切根据字体大小。 开头 VisualC++4.0, MFC 使用 Windows 95 PropertySheet 控件。 此控件将始终使用系统字体来表。 这是设计使然。 MFC 还将强制页以用作表相同字体。 这样调用 BuildPropPageArray() 函数中。 因为这是无出处函数, 它可能更改或将来的 MFC 版本中被删除。

CMySheet 将使用的首活动 CPropertyPage 字体来设置字体和 CPropertySheet 和其子窗口大小。 CPropertyPages 与资源编辑器中指定字体显示。

具体步骤:
1、新建类CMySheet,继承自CPropertySheet
2、在.cpp文件中大概实现如下。
3、修改.h文件。
4、使用这个CMySheet,更改资源中的属性页,则程序运行后,设置的字体有效。

#define WM_RESIZEPAGE WM_APP+1

enum { CDF_CENTER, CDF_TOPLEFT, CDF_NONE };

// helper function which sets the font for a window and all its children
// and also resizes everything according to the new font
void ChangeDialogFont(CWnd* pWnd, CFont* pFont, int nFlag)
{
 CRect windowRect;

 // grab old and new text metrics
 TEXTMETRIC tmOld, tmNew;
 CDC * pDC = pWnd->GetDC();
 CFont * pSavedFont = pDC->SelectObject(pWnd->GetFont());
 pDC->GetTextMetrics(&tmOld);
 pDC->SelectObject(pFont);
 pDC->GetTextMetrics(&tmNew);
 pDC->SelectObject(pSavedFont);
 pWnd->ReleaseDC(pDC);

 long oldHeight = tmOld.tmHeight+tmOld.tmExternalLeading;
 long newHeight = tmNew.tmHeight+tmNew.tmExternalLeading;

 if (nFlag != CDF_NONE)
 {
  // calculate new dialog window rectangle
  CRect clientRect, newClientRect, newWindowRect;

  pWnd->GetWindowRect(windowRect);
  pWnd->GetClientRect(clientRect);
  long xDiff = windowRect.Width() - clientRect.Width();
  long yDiff = windowRect.Height() - clientRect.Height();
 
  newClientRect.left = newClientRect.top = 0;
  newClientRect.right = clientRect.right * tmNew.tmAveCharWidth / tmOld.tmAveCharWidth;
  newClientRect.bottom = clientRect.bottom * newHeight / oldHeight;

  if (nFlag == CDF_TOPLEFT) // resize with origin at top/left of window
  {
   newWindowRect.left = windowRect.left;
   newWindowRect.top = windowRect.top;
   newWindowRect.right = windowRect.left + newClientRect.right + xDiff;
   newWindowRect.bottom = windowRect.top + newClientRect.bottom + yDiff;
  }
  else if (nFlag == CDF_CENTER) // resize with origin at center of window
  {
   newWindowRect.left = windowRect.left -
       (newClientRect.right - clientRect.right)/2;
   newWindowRect.top = windowRect.top -
       (newClientRect.bottom - clientRect.bottom)/2;
   newWindowRect.right = newWindowRect.left + newClientRect.right + xDiff;
   newWindowRect.bottom = newWindowRect.top + newClientRect.bottom + yDiff;
  }
  pWnd->MoveWindow(newWindowRect);
 }

 pWnd->SetFont(pFont);

 // iterate through and move all child windows and change their font.
 CWnd* pChildWnd = pWnd->GetWindow(GW_CHILD);

 while (pChildWnd)
 {
  pChildWnd->SetFont(pFont);
  pChildWnd->GetWindowRect(windowRect);

  CString strClass;
  ::GetClassName(pChildWnd->m_hWnd, strClass.GetBufferSetLength(32), 31);
  strClass.MakeUpper();
  if(strClass==_T("COMBOBOX"))
  {
   CRect rect;
   pChildWnd->SendMessage(CB_GETDROPPEDCONTROLRECT,0,(LPARAM) &rect);
   windowRect.right = rect.right;
   windowRect.bottom = rect.bottom;
  }

  pWnd->ScreenToClient(windowRect);
  windowRect.left = windowRect.left * tmNew.tmAveCharWidth / tmOld.tmAveCharWidth;
  windowRect.right = windowRect.right * tmNew.tmAveCharWidth / tmOld.tmAveCharWidth;
  windowRect.top = windowRect.top * newHeight / oldHeight;
  windowRect.bottom = windowRect.bottom * newHeight / oldHeight;
  pChildWnd->MoveWindow(windowRect);
  
  pChildWnd = pChildWnd->GetWindow(GW_HWNDNEXT);
 }
}
/////////////////////////////////////////////////////////////////////////////
// CMySheet

IMPLEMENT_DYNAMIC(CMySheet, CPropertySheet)

CMySheet::CMySheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
 :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
}

CMySheet::CMySheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
 :CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
}

CMySheet::~CMySheet()
{
 if (m_fntPage.m_hObject)
  VERIFY (m_fntPage.DeleteObject ());
}

BEGIN_MESSAGE_MAP(CMySheet, CPropertySheet)
 //{{AFX_MSG_MAP(CMySheet)
 //}}AFX_MSG_MAP
 ON_MESSAGE (WM_RESIZEPAGE, OnResizePage) 
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMySheet message handlers

void CMySheet::BuildPropPageArray()
{
 CPropertySheet::BuildPropPageArray();

 // get first page
 CPropertyPage* pPage = GetPage (0);
 ASSERT (pPage);
 
 // dialog template class in afxpriv.h
 CDialogTemplate dlgtemp;
 // load the dialog template
 VERIFY (dlgtemp.Load (pPage->m_psp.pszTemplate));
 // get the font information
 CString strFace;
 WORD wSize;
 VERIFY (dlgtemp.GetFont (strFace, wSize));
 if (m_fntPage.m_hObject)
  VERIFY (m_fntPage.DeleteObject ());
 // create a font using the info from first page
 VERIFY (m_fntPage.CreatePointFont (wSize*10, strFace));
}

BOOL CMySheet::OnInitDialog()
{
 CPropertySheet::OnInitDialog();

 // get the font for the first active page
 CPropertyPage* pPage = GetActivePage ();
 ASSERT (pPage);

 // change the font for the sheet
 ChangeDialogFont (this, &m_fntPage, CDF_CENTER);
 // change the font for each page
 for (int iCntr = 0; iCntr < GetPageCount (); iCntr++)
 {
  VERIFY (SetActivePage (iCntr));
  CPropertyPage* pPage = GetActivePage ();
  ASSERT (pPage);
  ChangeDialogFont (pPage, &m_fntPage, CDF_CENTER);
 }

 VERIFY (SetActivePage (pPage));

 // set and save the size of the page
 CTabCtrl* pTab = GetTabControl ();
 ASSERT (pTab);

 if (m_psh.dwFlags & PSH_WIZARD)
 {
  pTab->ShowWindow (SW_HIDE);
  GetClientRect (&m_rctPage);

  CWnd* pButton = GetDlgItem (ID_WIZBACK);
  ASSERT (pButton);
  CRect rc;
  pButton->GetWindowRect (&rc);
  ScreenToClient (&rc);
  m_rctPage.bottom = rc.top-2;
 }
 else
 {
  pTab->GetWindowRect (&m_rctPage);
  ScreenToClient (&m_rctPage);
  pTab->AdjustRect (FALSE, &m_rctPage);
 }

 // resize the page 
 pPage->MoveWindow (&m_rctPage);

 return TRUE;
}

BOOL CMySheet::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
 NMHDR* pnmh = (LPNMHDR) lParam;

 // the sheet resizes the page whenever it is activated so we need to size it correctly
 if (TCN_SELCHANGE == pnmh->code)
  PostMessage (WM_RESIZEPAGE);
 
 return CPropertySheet::OnNotify(wParam, lParam, pResult);
}

LONG CMySheet::OnResizePage (UINT, LONG)
{
 // resize the page
 CPropertyPage* pPage = GetActivePage ();
 ASSERT (pPage);
 pPage->MoveWindow (&m_rctPage);

 return 0;
}

BOOL CMySheet::OnCommand(WPARAM wParam, LPARAM lParam)
{
 // the sheet resizes the page whenever the Apply button is clicked so we need to size it correctly
 if (ID_APPLY_NOW == wParam ||
  ID_WIZNEXT == wParam ||
  ID_WIZBACK == wParam)
  PostMessage (WM_RESIZEPAGE);
 
 return CPropertySheet::OnCommand(wParam, lParam);
}

posted on 2008-01-25 17:42 浪迹天涯 阅读(5031) 评论(10)  编辑 收藏 引用 所属分类: C++

评论

# re: 如何更改属性页向导页的字体 2008-01-30 09:21 追梦时代

学习了,谢谢楼主  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-07-25 00:02 cuckoo321

写的很不错。请问大侠,如何更改属性页的标题字体和字号?  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-07-28 08:56 浪击天涯

你可以试试这样行吗?

怎样改变标题栏的宽度:

方法一:

NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof( NONCLIENTMETRICS );

::SystemParametersInfo( SPI_GETNONCLIENTMETRICS,
sizeof( NONCLIENTMETRICS ),
&ncm,
0
);

ncm.lfCaptionFont.lfHeight = -300;
::SystemParametersInfo( SPI_SETNONCLIENTMETRICS,
sizeof( NONCLIENTMETRICS ),
&ncm,
SPIF_SENDCHANGE
);
 

方法二:

case WM_NCCALCSIZE:
{
BOOL bSpecial=FALSE;
int nEdgeWidth =3;
int nBarHeight =CAPTIONHEIGHT+3;
int nBottomEdge =3;

if(!(BOOL)wParam)
{
RECT rtSave;
CopyRect(&rtSave,(LPRECT)lParam);
// ::CallWindowProcA(lpwndinfo->pWndProc,hWnd,uMsg,wParam,lParam);


if(lpwndinfo->bIM ==TRUE)
{
int imbarheight =17;
rtSave.left+=nEdgeWidth;
rtSave.top+=imbarheight+3;
rtSave.right-=nEdgeWidth;
rtSave.bottom-=nBottomEdge;
}
else
{
rtSave.left+=nEdgeWidth;
rtSave.top+=nBarHeight;
rtSave.right-=nEdgeWidth;
rtSave.bottom-=nBottomEdge;
}
CopyRect((LPRECT)lParam,&rtSave);

*lResult=0;
::ReleaseDC(hWnd,hDC);
return TRUE;
}
else
{
RECT rtSave;
LPRECT prtClt;
LPNCCALCSIZE_PARAMS pNC;
pNC=(LPNCCALCSIZE_PARAMS)lParam;

prtClt=&(pNC->rgrc[0]);
CopyRect(&rtSave,prtClt);
CopyRect( &(pNC->rgrc[2]), &(pNC->rgrc[1]));

if(bSysDlg)
{
(pNC->rgrc[2]).left +=nEdgeWidth;
(pNC->rgrc[2]).right -=nEdgeWidth;
}
else
{
if(lpwndinfo->bIM ==TRUE)
{
int imbarheight =17;
(pNC->rgrc[2]).left +=nEdgeWidth;
(pNC->rgrc[2]).top +=imbarheight+3;
(pNC->rgrc[2]).right -=nEdgeWidth;
(pNC->rgrc[2]).bottom -=nBottomEdge;

rtSave.left+=nEdgeWidth;
rtSave.top+=imbarheight+3;
rtSave.right-=nEdgeWidth;
rtSave.bottom-=nBottomEdge;
}
else
{
(pNC->rgrc[2]).left+=nEdgeWidth;
(pNC->rgrc[2]).top+=nBarHeight;
(pNC->rgrc[2]).right-=nEdgeWidth;
(pNC->rgrc[2]).bottom-=nBottomEdge;
// Result=::CallWindowProcA(lpwndinfo->pWndProc,hWnd,uMsg,wParam,lParam);
//prtClt=&(pNC->rgrc[0]);
rtSave.left+=nEdgeWidth;
rtSave.top+=nBarHeight;
rtSave.right-=nEdgeWidth;
rtSave.bottom-=nBottomEdge;
}
}
CopyRect(prtClt,&rtSave);
*lResult=0;
::ReleaseDC(hWnd,hDC);
return TRUE;
}
break;
}   回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-08-19 16:41 勤奋的人

你好 用了你的方法可以实现更改字体了;
但是出现了新的问题
就是编辑框没办法输入中文了;都是乱码
请问这个能解决吗?  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-08-19 16:50 浪迹天涯

我试了,我这是可以输入中文,而且显示也不是乱码的。  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-08-19 18:19 勤奋的人

终于找到什么原因了 我做的是PROE二次开发 不知道为什么 创建的非模式对话框里 用编辑框或者组合框键盘输入 中文 总是显示乱码 创建的模式对话框就不会!还在摸索中! 不过仍然很感谢你! 我才知道不是程序问题!  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-08-19 18:26 浪迹天涯

呵,客气!
输入中文乱码的问题,有可能是和字符集设置有关,具体原因我也没碰见过。  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-09-13 11:24 RSW

按照上面的方法,无法修改某些窗口的大小(比如,文本框),有时还感觉它变小了,而且对于静态文本框文字输入很多的话,有部分不能显示。
不知道有没有解决办法  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-09-13 12:01 RSW

我把窗口调小一点,窗口就可以完整显示了。^_^
调大了好像部分被什么东西遮挡了。
  回复  更多评论   

# re: 如何更改属性页向导页的字体 2008-09-16 09:18 浪迹天涯

这可能是你属性页显示范围太小,调大显示范围即可!  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2008年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿(20)

随笔分类(30)

随笔档案(29)

文章分类

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜