( 1 ) 如何通过代码获得应用程序主窗口的指针 ?
主窗口的指针保存在 CWinThread::m_pMainWnd 中 , 调用 AfxGetMainWnd 实现。
AfxGetMainWnd()->ShowWindow(SW_SHOWMAXMIZED)
// 使程序最大化 .
( 2 ) 确定应用程序的路径
Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。
Example:
TCHAR exeFullPath[MAX_PATH] // MAX_PATH 在 MFC 中定义为 260
GetModuleFileName(NULL,exeFullPath,MAX_PATH)
( 3 ) 如何在程序中获得其他程序的图标 ?
两种方法 :
(1) SDK 函数 SHGetFileInfo 或使用 ExtractIcon 获得图标资源的 handle,
(2) SDK 函数 SHGetFileInfo 获得有关文件的很多信息 , 如大小图标 , 属性 , 类型等 .
Example(1):
在程序窗口左上角显示 NotePad 图标 .
void CSampleView::OnDraw(CDC * pDC)
{
if( ::SHGetFileInfo(_T("c://pwin95//notepad.exe"),0,
&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
{
pDC ->DrawIcon(10,10,stFileInfo.hIcon);
}
}
Example(2): 同样功能 ,Use ExtractIcon Function
void CSampleView::OnDraw(CDC *pDC)
{
HICON hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0) ;
if (hIcon && hIcon!=(HICON)-1))
pDC->DrawIcon(10,10,hIcon);
}
说明 : 获得 notepad.exe 的路径正规上来说用 GetWindowsDirectory 函数得到 , 如果是调用 win95 下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点 .
( 4 ) 获得各种目录信息
Windows 目录 : Use "GetWindowsDirectory"
Windows 下的 system 目录 : Use "GetSystemDirectory"
temp 目录 : Use "GetTempPath"
当前目录 : Use "GetCurrentDirectory"
请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区后两个相反 .
( 5 ) 如何自定义消息
1) 手工定义消息,可以这么写
#define WM_MY_MESSAGE(WM_USER+100),MS 推荐的至少是 WM_USER+100
(2) 写消息处理函数 , 用 WPARAM,LPARAM 返回 LRESULT.
LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)
{
// 加入你的处理函数
}
( 6 ) 如何改变窗口的图标 ?
向窗口发送 WM_SETICON 消息。
Example:
HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON);
ASSERT(hIcon)
AfxGetMainWnd()->SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon);
( 7 ) 如何改变窗口的缺省风格 ?
重载 CWnd::PreCreateWindow 并修改 CREATESTRUCT 结构来指定窗口风格和其他创建信息 .
Example: Delete "Max" Button and Set Original Window's Position and Size
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &cs)
{
cs.style &=~WS_MAXINIZEMOX
cs.x=cs.y=0
cs.cx=GetSystemMetrics(SM_CXSCREEN/2)
cs.cy=GetSystemMetrics(SM_CYSCREEN/2)
return CMDIFramewnd ::PreCreateWindow(cs)
}
( 8 ) 如何将窗口居中显示 ?
Call Function CWnd::CenterWindow
Example(1):
CenterWindow() //Relative to it's parent
Example(2):
CenterWindow(CWnd:: GetDesktopWindow( )) // Relative to Screen
AfxGetMainWnd()->CenterWindow() //Relative to Application's MainWindow
( 9 ) 如何让窗口和 MDI 窗口一启动就最大化和最小化 ?
先说窗口。
在 InitStance 函数中设定 m_nCmdShow 的取值 .
m_nCmdShow=SW_SHOWMAXMIZED // 最大化
m_nCmdShow=SW_SHOWMINMIZED // 最小化
m_nCmdShow=SW_SHOWNORMAL // 正常方式
MDI 窗口 :
如果是创建新的应用程序 , 可以用 MFC AppWizard 的 Advanced 按钮并在 MDI 子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的 PreCreateWindow 函数,设置 WS_MAXMIZE or WS_MINMIZE
如果从 CMDIChildWnd 派生 , 调用 OnInitialUpdate 函数中的 CWnd::Show Window 来指定 MDI Child Window 的风格。
( 10 ) 如何限制窗口的大小 ?
也就是 FixedDialog 形式。 Windows 发送 WM_GETMAXMININFO 消息来跟踪 , 响应它 , 在 OnGetMAXMININFO 中写代码 .
( 11 ) 如何使窗口不可见?
很简单 , 用 SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow 控制 .
( 12 ) 如何创建一个字回绕的 CEditView
重载 CWnd::PreCreateWindow 和修改 CREATESTRUCT 结构,关闭 CEditView 对象的 ES_AUTOHSCROLL 和 WS_HSCROLL 风格位,由于 CEditView::PreCreateWindow 显示设置 cs.style ,调用基类函数后要修改 cs.style 。
BOOL CSampleEDitView::PreCreateWindow (CREATESTRUCT&cs)
{
//First call basse class function .
BOOL bResutl = CEditView::PreCreateWindow(cs);
// Now specify the new window style.
cs.style &= ~(ES_AUTOHSCROLL | WS_HSCROLL);
return bResult;
}
( 13 ) 如何使程序保持极小状态 ?
这么办 : 在恢复程序窗体大小时, Windows 会发送 WM_QUERYOPEN 消息,用 ClassWizard 设置成员函数 OnQueryOpen(), 添加如下代码 :
Bool CMainFrame:: OnQueryOpen( )
{
Return false;
}
( 14 ) 移动窗口
调用 CWnd::SetWindowPos 并指定 SWP_NOSIZE 标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用 CWnd::MoveWindow 时必须要指定窗口的大小。
//Move window to positoin 100 , 100 of its parent window .
SetWindowPos(NULL, 100, 100, 0, 0, SWP_NOSIZE | SWP_NOAORDER) ;
( 15 ) 通用控件的显示窗口
MFC 提供了几个 CView 派生的视窗类,封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构: CEditView 封装了编辑控件, CTreeView 保持了树列表控件, CListView 封装了列表显示窗口控件, CRichEditView 可以处理多种编辑控件。
( 16 ) 重置窗口的大小
调用 CWnd::SetWindowPos 并指定 SWP_NOMOVE 标志, 也可调用 CWnd::MoveWindow 但必须指定窗口的位置。
// Get the size of the window .
CRect reWindow;
GetWindowRect(&reWindow);
//Make the window twice as wide and twice as tall .
SetWindowPos(NULL, 0, 0, reWindow.Width() * 2,
reWindow.Height() * 2, SWP_NOMOVE | SWP_NOZORDER);
( 17 ) 如何单击除了窗口标题栏以外的区域使窗口移动
当窗口需要确定鼠标位置时 Windows 向窗口发送 WM_NCHITTEST 信息,可以处理该信息使 Windows 认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用 ClassWizard 处理该信息并调用基类函数, 如果函数返回 HTCLIENT 则表明鼠标在客户区域,返回 HTCAPTION 表明鼠标在 Windows 的标题栏中。
UINT CSampleDialog::OnNcHitTest(CPoint point)
{
UINT nHitTest =Cdialog::OnNcHitTest(point);
return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
}
上述技术有两点不利之处,
其一是在窗口的客户区域双击时,窗口将极大;
其二,它不适合包含几个视窗的主框窗口。
还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用 ClassWizard 在视窗中处理 WM_LBUTTODOWN 信息并向主框窗口发送一个 WM_NCLBUTTONDOWN 信息和一个单击测试 HTCAPTION 。
void CSampleView::OnLButtonDown(UINT nFlags , CPoint point)
{
CView::OnLButtonDow(nFlags, pont);
//Fool frame window into thinking somene clicked on its caption bar .
GetParentFrame()->PostMessage(WM_NCLBUTTONDOWN , HTCAPTION, MAKELPARAM(poitn.x, point.y));
}
该技术也适用于对话框和基于对的应用程序,只是不必调用 CWnd::GetParentFrame 。
void CSampleDialog::OnLbuttonDown(UINT nFlags, Cpoint point)
{
Cdialog::OnLButtonDow(nFlags, point);
//Fool dialog into thinking simeone clicked on its caption bar.
PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARM (point.x, point.y));
}
( 18 ) 如何改变视窗的背景颜色
Windows 向窗口发送一个 WM_ERASEBKGND 消息通知该窗口擦除背景,可以使用 ClassWizard 重载该消息的缺省处理程序来擦除背景(实际是画),并返回 TRUE 以防止 Windows 擦除窗口。
//Paint area that needs to be erased.
BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
{
// Create a pruple brush.
CBrush Brush(RGB(128, 0, 128));
// Select the brush into the device context .
CBrush* pOldBrush = pDC->SelcetObject (&brush);
// Get the area that needs to be erased .
CRect reClip;
pDC->GetCilpBox(&rcClip);
//Paint the area.
pDC->PatBlt(rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), PATCOPY);
//Unselect brush out of device context.
pDC->SelectObject(pOldBrush);
// Return nonzero to half fruther processing.
return TRUE;
}
( 19 ) 如何改变窗口标题
调用 CWnd::SetWindowText 可以改变任何窗口(包括控件)的标题。
//Set title for application's main frame window .
AfxGetMainWnd()->SetWindowText(_T("Application title"));
//Set title for View's MDI child frame window .
GetParentFrame()->SetWindowText("_T("MDI Child Frame new title"))
//Set title for dialog's push button control.
GetDlgItem(IDC_BUTTON)->SetWindowText(_T("Button new title "))
如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数 AfxSetWindowText 。该函数在 AFXPRIV.H 中说明,在 WINUTIL.CPP 中实现,在联机帮助中找不到它,它在 AFXPRIV.H 中半文档化, 在以后发行的 MFC 中将文档化。
AfxSetWindowText 的实现如下:
voik AFXAPI AfxSetWindowText(HWND hWndCtrl, LPCTSTR IpszNew)
{
int nNewLen = strlen(Ipaznew);
TCHAR szOld[256];
//fast check to see if text really changes (reduces flash in the controls)
if (nNewLen > _contof(szOld)
||::GetWindowText(hWndCrtl, szOld , _countof(szOld)) != nNewLen
|| strcmp(szOld, IpszNew)! = 0)
{
//change it
::SetWindowText(hWndCtrl, IpszNew);
}
}
( 20 ) 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和 MDI 子窗口进通常具有 FWS_ADDTOTITLE 风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用 ClassWizard 重置 CWnd::PreCreateWindow 并关闭 FWS_ADDTOTITLE 风格。
BOOL CMainFrame::PreCreateWindow (CREATESTRUCT&cs)
{
//Turn off FWS_ADDTOTITLE in main frame .
cs.styel & = ~FWS_ADDTOTITLE
return CMDIFrameWnd::PreCreateWindow (cs)
}
关闭 MDI 子窗口的 FWS _ADDTOTITLE 风格将创建一个具有空标题的窗口,可以调用 CWnd::SetWindowText 来设置标题。记住自己设置标题时要遵循接口风格指南。
( 21 ) 如何获取有关窗口正在处理的当前消息的信息
调用 CWnd::GetCurrentMessage 可以获取一个 MSG 指针。例如,可以使用 ClassWizard 将几个菜单项处理程序映射到一个函数中,然后调用 GetCurrentMessage 来确定所选中的菜单项。
viod CMainFrame::OnCommmonMenuHandler()
{
//Display selected menu item in debug window .
TRACE ("Menu item %u was selected./n",
( 22 ) 如何在代码中获取工具条和状态条的指针
缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个 AFX_IDW_STATUS_BAR 标识符,工具条有一个 AFX_IDW_TOOLBAR 标识符,下例说明了如何通过一起调用 CWnd::GetDescendantWindow 和 AfxGetMainWnd 来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STUTUS_BAR);
//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
( 23 ) 如何使能和禁止工具条的工具提示
如果设置了 CBRS_TOOLTIPS 风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用 CControlBar::GetBarStyle 和 CControlBar::SetBarStyle 建立一个完成此功能的成员函数:
void CMainFrame::EnableToolTips ( BOOL bDisplayTips )
{
ASSERT_VALID (m_wndToolBar);
DWORD dwStyle = m _wndToolBar.GetBarStyle();
if (bDisplayTips)
dwStyle |= CBRS_TOOLTIPS;
else
dwStyle & = ~CBRS_TOOLTIPS;
m_wndToolBar.SetBarStyle(dwStyle);
}
( 24 ) 如何创建一个不规则形状的窗口
可以使用新的 SDK 函数 SetWindowRgn 。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。 使用 AppWizard 创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。
给对话类增加一个 CRgn 数据成员,以后要使用该数据成员建立窗口区域。
Class CRoundDlg : public CDialog
{
…
private :
Crgn m_rgn : // window region
…
}
修改 OnInitDialog 函数建立一个椭圆区域并调用 SetWindowRgn 将该区域分配给窗口:
BOOL CRoundDlg::OnInitDialog ( )
{
CDialog::OnInitDialog();
//Get size of dialog .
CRect rcDialog;
GetClientRect(rcDialog);
// Create region and assign to window .
m_rgn.CreateEllipticRgn(0 , 0 , rcDialog.Width(), rcDialog.Height());
SetWindowRgn(GetSafeHwnd() , (HRGN) m_ rgn ,TRUE);
return TRUE;
}
通过建立区域和调用 SetWindowRgn ,已经建立一个不规则形状的窗口,下面的例子程序是修改 OnPaint 函数使窗口形状看起来象一个球形体。
voik CRoundDlg::OnPaint ( )
{
CPaintDC dc(this); // device context for painting.
//draw ellipse with out any border
dc.SelecStockObject(NULL_PEN);
//get the RGB colour components of the sphere color
COLORREF color= RGB( 0 , 0 , 255);
BYTE byRed =GetRValue (color);
BYTE byGreen = GetGValue(color);
BYTE byBlue = GetBValue (color);
// get the size of the view window
CRect rect;
GetClientRect(rect);
// get minimun number of units
int nUnits = min(rect.right, rect.bottom );
//calculate he horiaontal and vertical step size
float fltStepHorz = (float) rect.right /nUnits;
float fltStepVert = (float) rect.bottom /nUnits;
int nEllipse = nUnits/3 // calculate how many to draw
int nIndex; // current ellipse that is being draw
CBrush brush; // bursh used for ellipse fill color
CBrush *pBrushOld; // previous brush that was selected into dc
//draw ellipse , gradually moving towards upper-right corner
for (nIndex = 0 nIndes < + nEllipse nIndes++)
{
//creat solid brush
brush.CreatSolidBrush(RGB(((nIndex*byRed)/nEllipse).((nIndex * byGreen)/nEllipse ),
((nIndex * byBlue)/nEllipse)));
//select brush into dc
pBrushOld = dc.SelectObject(&brush);
//draw ellipse
dc.Ellipse((int)fltStepHorz * 2, (int) fltStepVert * nIndex,
rect.right - ((int) fltStepHorz * nIndex )+ 1,
rect.bottom -((int) fltStepVert * (nIndex *2) ) +1);
//delete the brush
brush.DelecteObject();
}
}
最后,处理 WM_NCHITTEST 消息,使当击打窗口的任何位置时能移动窗口。
UINT CRoundDlg::OnNchitTest (CPoint point )
{
//Let user move window by clickign anywhere on thewindow .
UINT nHitTest = CDialog::OnNcHitTest(point);
rerurn (nHitTest == HTCLIENT)? HTCAPTION : nHitTest;
}
( 25 ) 如何获取应用程序的实例句柄 ?
应用程序的实例句柄保存在 CWinApp m_hInstance 中 , 可以这么调用 AfxGetInstancdHandle 获得句柄 .
Example: HANDLE hInstance=AfxGetInstanceHandle();
( 26 ) 如何编程结束应用程序 ?
这是个很简单又是编程中经常要遇到的问题 .
向窗口发送 WM_CLOSE 消息 , 调用 CWnd::OnClose 成员函数 . 允许对用户提示是否保存修改过的数据 .
Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)
还可以创建一个自定义的函数 Terminate Window
void Terminate Window(LPCSTR pCaption)
{
CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption);
if (pWnd)
pWnd ->SendMessage(WM_CLOSE);
}
说明 : FindWindow 函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad 是不是已运行而事先不知道 Notepad 的标题栏 , 这时 FindWindow 就无能为力了,可以通过枚举 windows 任务列表的办法来实现。在机械出版社 "Windows 95 API 开发人员指南 " 一书有比较详细的介绍 , 这里就不再多说了。
( 27 ) 如何创建和使用无模式对话框
MFC 将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用 ClassWizard 创建一个 CDialog 的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用 CDialog::EndDialog 来中止,无模式对话则是调用 CWnd::DestroyWindow 来中止的,函数 CDialog::OnOK 和 CDialog::OnCancel 调用 EndDialog , 所以需要调用 DestroyWindow 并重置无模式对话的函数。
void CSampleDialog::OnOK ( )
{
// Retrieve and validate dialog data .
if (!UpdateData (TRUE))
{
// the UpdateData rountine will set focus to correct item
TRACEO (" UpdateData failed during dialog termination ./n") ;
return ;
}
//Call DestroyWindow instead of EndDialog .
DestroyWindow ( ) ;
}
void CSampleDialog::OnCancel ( )
{
//Call DestroyWindow instead of EndDialog .
DestroyWindow ( ) ;
}
其次,需要正确删除表示对话的 C++ 对象。对于模式对来说,这很容易,需要创建函数返回后即可删除 C++ 对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除 C++ 对象。撤销窗口时工作框调用 CWnd::PostNcDestroy ,可以重置该函数并执行清除操作,诸如删除 this 指针。
void CSampleDialog::PostNcDestroy ( )
{
// Declete the C++ object that represents this dialog.
delete this;
}
最后,要创建无模式对话。可以调用 CDialog::DoModal 创建一个模式对放,要创建一个无模式对话则要调用 CDialog::Create 。下面的例子说明 了应用程序是如何创建无模式对话的对象;无模式对话不是同步的,创建函数调用后立即返回,
void CMainFrame::OnSampleDialog ( )
{
//Allocate a modeless dialog object .
CSampleDilog * pDialog =new CSampleDialog;
ASSERT_VALID (pDialog) Destroy ( );
//Create the modeless dialog . represents this dialog.
BOOL bResult = pDialog->Create(IDD_IDALOG);
ASSERT (bResult );
}
( 28 ) 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和 MDI 子窗口进通常具有 FWS_ADDTOTITLE 风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用 ClassWizard 重置
CWnd: : PreCreateWindow 并关闭 FWS_ADDTOTITLE 风格。
BOOL CMainFrame::PreCreateWindow (CREATESTRUCT&cs)
{
//Turn off FWS_ADDTOTITLE in main frame .
cs.styel & = ~FWS_ADDTOTITLE;
return CMDIFrameWnd::PreCreateWindow (cs);
}
关闭 MDI 子窗口的 FWS _ADDTOTITLE 风格将创建一个具有空标题的窗口,可以调用 CWnd: : SetWindowText 来设置标题。记住自己设置标题时要遵循接口风格指南。
( 29 ) 如何在代码中获取工具条和状态条的指针
缺省时, 工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个 AFX_IDW_STATUS_BAR 标识符,工具条有一个 AFX_IDW_TOOLBAR 标识符,下例说明了如何通过一起调用 CWnd: : GetDescendantWindow 和 AfxGetMainWnd 来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STUTUS_BAR);
//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
( 30 ) 怎样加载其他的应用程序 ?
三个 SDK 函数 winexec, shellexecute,createprocess 可以使用。
WinExec 最简单,两个参数,前一个指定路径,后一个指定显示方式 . 后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED 方式去加载一个无最大化按钮的程序,就是 Neterm,calc 等等,就不会出现正常的窗体,但是已经被加到任务列表里了。
ShellExecute 较 WinExex 灵活一点,可以指定工作目录 , 下面的 Example 就是直接打开 c:/temp/1.txt, 而不用加载与 txt 文件关联的应用程序 , 很多安装程序完成后都会打开一个窗口,来显示 Readme or Faq, 我猜就是这么作的啦 .
ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED);
CreateProcess 最复杂,一共有十个参数,不过大部分都可以用 NULL 代替,它可以指定进程的安全属性,继承信息,类的优先级等等 . 来看个很简单的 Example:
STARTUPINFO stinfo; // 启动窗口的信息
PROCESSINFO procinfo; // 进程的信息
CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,
NORMAL_PRIORITY_CLASS,NULL,NULL, &stinfo,&procinfo);
( 31 ) 如何在代码中获取工具条和状态条的指针
缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个 AFX_IDW_STATUS_BAR 标识符,工具条有一个 AFX_IDW_TOOLBAR 标识符,下例说明了如何通过一起调用 CWnd: : GetDescendantWindow 和 AfxGetMainWnd 来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STUTUS_BAR);
( 32 ) 如何使能和禁止工具条的工具提示
如果设置了 CBRS_TOOLTIPS 风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用 CControlBar::GetBarStyle 和 CControlBar::SetBarStyle 建立一个完成此功能的成员函数:
void CMainFrame::EnableToolTips ( BOOL bDisplayTips )
{
ASSERT_VALID (m_wndToolBar);
DWORD dwStyle = m _wndToolBar.GetBarStyle();
if (bDisplayTips)
dwStyle | =CBRS_TOOLTIPS;
else
dwStyle & = ~CBRS_TOOLTIPS;
m_wndToolBar.SetBarStyle(dwStyle);
}
//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
( 33 ) 如何设置工具条标题
工具条是一个窗口,所以可以在调用 CWnd::SetWindowText 来设置标题,例子如下:
int CMainFrame::OnCreate (LPCREATESTRUCT lpCreateStruct )
{
…
// Set the caption of the toolbar .
m_wndToolBar.SetWindowText (_T "Standdard");
}
( 34 ) 如何使窗口始终在最前方 ?
BringWindowToTop(Handle)
SetWindowPos 函数,指定窗口的 最顶风格 , 用 WS_EX_TOPMOST 扩展窗口的风格
Example:
void ToggleTopMost(CWnd *pWnd)
{
ASSERT_VALID(pWnd);
pWnd->SetWindowPos(pWnd->GetStyle() &WS_EX_TOPMOST)?
&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE);
}
( 35 ) 如何在对话框中显示一个位图
这要归功于 Win32 先进的静态控件和 Microsoft 的资源编辑器,在对话框中显示位图是很容易的,只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。
( 36 ) 如何改变对话或窗体视窗的背景颜色
调用 CWinApp::SetDialogBkColor 可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。
BOOL CSampleApp::InitInstance ( )
{
…
//use blue dialog with yellow text .
SetDialogBkColor(RGB (0, 0, 255), RGB(255, 255, 0));
…
}
需要重画对话(或对话的子控件)时, Windows 向对话发送消息 WM_CTLCOLOR ,通常用户可以让 Windows 选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。
首先,给对话基类增加一人成员变量
CBursh :class CMyFormView : public CFormView
{
…
private :
CBrush m_ brush; // background brush
…
}
其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
CMyFormView::CMyFormView ( )
{
// Initialize background brush .
m_brush.CreateSolidBrush(RGB(0, 0, 255));
}
最后,使用 ClassWizard 处理 WM_CTLCOLOR 消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测 nCtlColor 参量。
HBRUSH CMyFormView::OnCtlColor(CDC* pDC , CWnd*pWnd , UINT nCtlColor)
{
// Determine if drawing a dialog box . If we are, return +handle to
//our own background brush . Otherwise let windows handle it .
if (nCtlColor = = CTLCOLOR _ DLG )
return (HBRUSH) m_brush.GetSafeHandle();
return CFormView::OnCtlColor(pDC, pWnd, nCtlColor);
}
( 37 ) 如何获取一个对话控件的指针
有两种方法。其一,调用 CWnd::GetDlgItem ,获取一个 CWnd* 指针调用成员函数。下例调用 GetDlgItem ,将返回值传给一个 CSpinButtonCtrl* 以便调用 CSpinButtonCtrl::SetPos 函数:
BOOL CSampleDialog::OnInitDialog ( )
{
CDialog::OnInitDialog();
//Get pointer to spin button .
CSpinButtonCtrl * pSpin = (CSpinButtonCtrl *) GetDlgItem(IDC_SPIN);
ASSERT_VALID(pSpin);
//Set spin button's default position .
pSpin->SetPos(10);
return TRUE;
}
其二, 可以使用 ClassWizard 将控件和成员变量联系起来。在 ClassWizard 中简单地选择 Member Variables 标签,然后选择 Add Variable … 按钮。如果在对话资源编辑器中,按下 Ctrl 键并双击控件即可转到 Add Member Variable 对话。
( 38 ) 如何禁止和使能控件
控件也是窗口,所以可以调用 CWnd::EnableWindow 使能和禁止控件。
//Disable button controls .
m_wndOK.EnableWindow (FALSE);
m_wndApply.EnableWindow (FALSE);
( 39 ) 如何改变控件的字体
由于控件是也是窗口,用户可以调用 CWnd: : SetFont 指定新字体。该函数用一个 Cfont 指针,要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字体改为 8 点 Arial 字体:
//Declare font object in class declaration (.H file ).
private : CFont m_font;
// Set font in class implementation (.Cpp file ). Note m_wndButton is a
// member variable added by ClassWizard.DDX routines hook the member
//variable to a dialog button contrlo.
BOOL CSampleDialog::OnInitDialog ( )
{
…
//Create an 8-point Arial font
m_font.CreateFont(MulDiv(8, pDC->GetDeviceCaps(LOGPIXELSY), 72, 0 , 0 , 0 , FW_NORMAL , 0 , 0, 0, ANSI_CHARSER, OUT_STROKE_PRECIS, CLIP_STROKE _PRECIS , DRAFT _QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial") );
//Set font for push button .
m_wndButton.SetFont(&m_font);
…
}
( 40 ) 如何在 OLE 控件中使用 OLE_COLOR 数据类型
诸如 COleControl::GetFortColor 和 COleControl::GetBackColor 等函数返回 OLE _COLOR 数据类型的颜色,而 GDI 对象诸如笔和刷子使用的是 COLORREF 数据类型,调用 COleControl::TranslateColor 可以很容易地将 OLE_COLOR 类型改为 COLORREF 类型。下例创建了一个当前背景颜色的刷子:
void CSampleControl::OnDraw (CDC* pdc, const Crect& rcBounds , const Crect& rcInvalid)
{
//Create a brush of the cuttent background color.
CBrush brushBack(TranslateColor (GetBackColor () ) );
//Paint the background using the current backgroundcolor .
pdc->FilllRect(rcBounds , &brushBack);
//other drawign commands
…
}