C++
的常用知
识
,
常见问题解答。
一
C++
的常用知识
1:
得到系
统时间
日期
(
使用
GetLocalTime)
CString sTime,sYear,sMonth,sDay;
SYSTEMTIME CurTime;
GetLocalTime(&CurTime);
sYear.Format(%d
年
,CurTime.wYear);
sMonth.Format(%d
月
,CurTime.wMonth);
sDay.Format(%d
日
,CurTime.wDay);
sTime = sYear+ sMonth + sDay;
// CurTime.wHour
// CurTime.wMinute
// CurTime.wSecond IBM
的
AfxMessageBox(sTime);
2:
分离字串
CString str = 4d3f0a2278;
unsigned char a12;
long x;
for(int i = 0;i< (str.GetLength()/2);i++)
{
sscanf(str.Mid(2*i,2),%x,&x);
a[i] = x;
}
3:
得到当前目
录
(GetCurrentDirectory)
char CurPath[MAX_PATH];
DWORD size=MAX_PATH;
GetCurrentDirectory(size,CurPath);
AfxMessageBox(CurPath);
//
CString number;
int len = LineLength(LineIndex(0));
LPTSTR p=number.GetBuffer(len);
this->GetLine(0,p,len);
AfxMessageBox(number);
得到系
统
目
录
(GetSystemDirectory)
4:
从字符串中提取数字
CString strNum;
CString str(
测试
125
各国
87kk);
strNum = GetStr(str);
AfxMessageBox(strNum);
5:
创
建无模
对话
框
CDlg_Test *aa = new CDlg_Test;
aa->Create(IDD_DIALOG1,NULL);
aa->ShowWindow(SW_SHOW);1
6:
得到窗口
绝对
坐
标
CString strNum,strNum1;
CRect rect;
GetClientRect(&rect);
ClientToScreen(&rect);
strNum.Format(X: %d,rect.top);
strNum1.Format( Y: %d,rect.center);
strNum = strNum + strNum1;
AfxMessageBox(strNum);
7:
复
制文件
夹
SHFILEOPSTRUCT Op;
char FromBuf[]=E:temp;
char ToBuf[]=SINTEKSERVER
个人文档
陈
伟
;;
Op.hwnd = NULL;
Op.wFunc = FO_COPY;
Op.pFrom = FromBuf;
Op.pTo = ToBuf;
Op.fFlags = FOF_NOCONFIRMATION | FOF_RENAMEONCOLLISION ;
Op.fAnyOperationsAborted = FALSE;
Op.hNameMappings = NULL;
Op.lpszProgressTitle = NULL;
MessageBox(
复
制完
毕
,
提示
,MB_OK|MB_ICONINFORMATION);
8:
捕
获
Ctrl
+鼠
标
左
键
组
合
case WM_LBUTTONDOWN://
鼠
标
消息
wParam ==
if (wParam & MK_CONTROL)
MessageBox(hwnd,aaa,bbb,MB_OK);
break;
或
case WM_LBUTTONDOWN:
MessageBox(hwnd,aaa,bbb,MB_OK);
break;
二
常见问题解答。
(
1
)
如何通
过
代
码获
得
应
用程序主窗口的
指
针
?
主窗口的
指
针
保存在
CWinThread::m_pMainWnd
中
,
调
用
AfxGetMainWnd
实现
。
AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED)
//
使程序最大化
.
(
2
)
确定
应
用程序的路径
Use GetModuleFileName
获
得
应
用程序的路径,然后去掉可
执
行文件名。
Example:
TCHAR
exeFullPath[MAX_PATH] // MAX_PATH
在
API
中定
义
了吧,好象是
128
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)
{
temp
目
录
: Use "GetTempPath"
//
加入你的
处
理函数
irectory"
}
(
6
)
如何改
变
窗口的
图标
?
向窗口
发
送
WM_SECTION
消息。
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::
Center Windows
Example(1):
Center Window( ) //Relative to it's parent
// Relative
to Screen
Example(2):
Center Window(CWnd:: GetDesktopWindow( ))
//Relative to
Application's MainWindow
AfxGetMainWnd( ) ->
Center Window( )
(
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_QUERY-OPEN
消息,用
ClassWizard
设
置成
员
函数
OnQueryOpen() ,add following code:
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, goint )
//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.
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )
如果需要
经
常修改窗口的
标题
(注:控件也是窗口),
应该
考
虑
使用半文档化的函数
AfxSetWindowText
。
该
函数在
AFXPRIV.H
中
说
明,在
WINUTIL.CPP
中
实现
,在
联
机帮助中找不到它,它在
AFXPRIV.H
中半文档化,
在以后
发
行的
MFC
中将文档化。
AfxSetWindowText
的
实现
如下:
voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )
{
itn nNewLen= Istrlen (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
||
Istrcmp (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 de (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 (&brhsh)
//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 —> Creste (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
)
如何在
对话
框中
显
示一个位
图
这
要
归
功于
Win 32
先
进
的静
态
控件和
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
…
}
(
41
)
在不使用通用文件打
开对话
的情况下如何
显
示一个文件列表
调
用
CWnd: : DlgDirList
或者
CWnd: : DlgDirListComboBox
,
Windows
将自
动
地向列表框或
组
合框填充可用的
驱动
器名或者指定目
录
中的文件,下例将
Windows
目
录
中的文件填充在
组
合框中:
BOOL CSampleDig : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )
TCHAR szPath [MAX_PATH] = {"c://windows"}
int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE
|
DDL_READONLY
|
DDL_HIDDEN
|
DDL_SYSTEM
|
DDL_ARCHIVE)
return TRUE
}
(
42
)
为
什
么
旋
转
按
钮
控件看起来倒
转
需要
调
用
CSpinCtrl : : SetRange
设
置旋
转
按
钮
控件的范
围
,旋
转
按
钮
控件的缺省上限
为
0
,缺省下限
为
100
,
这
意味着增加
时
旋
转
按控件的
值
由
100
变为
0
。下例将旋
转
按
钮
控件的范
围设
置
为
0
到
100
:
BOOL CAboutDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )
//set the lower and upper limit of the spin button
m_wndSpin . SetRange ( 0 ,100 )
return TRUE
}
Visual C++ 4.0 Print
对话
中的
Copise
旋
转
按
钮
控件也有同
样
的
问题
:按下
Up
按
钮时
拷
贝
的数目减少,而按下
Down
按
钮时
拷
贝
的数目增加。
(
43
)
为
什
么
旋
转
按
钮
控件不能自
动
地更新它下面的
编辑
控件
如果使用旋
转
按
钮
的
autu buddy
特性,
则
必
须
保
证
在
对话
的
标记顺
序中
buddy
窗口
优
先于旋
转
按
钮
控件。从
Layout
菜
单
中
选择
Tab Order
菜
单项
(或者按下
Crtl+D
)可以
设
置
对话
的
标签顺
序。
(
44
)
如何用位
图显
示下
压
按
钮
Windows 95
按
钮
有几
处
新的
创
建
风
格,尤其是
BS_BITMAP
和
BS_ICON
,要想具有位
图
按
钮
,
创
建按
钮
和
调
用
CButton : : SetBitmap
或
CButton : : SetIcon
时
要指定
BS_BITMAP
或
BS_ICON
风
格。
首先,
设
置按
钮
的
图标
属性。然后,当
对话
初始化
时调
用
CButton: : SetIcon
。注意:下例用
图标
代替位
图
,使用位
图时
要小心,因
为
不知道背景所有的
颜
色
——
并非
每
个人都使用浅灰色。
BOOL CSampleDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )
//set the images for the push buttons .
BOOL CSampleDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )
//set the images for the push buttons .
m_wndButton1.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION1))
m_wndButton2.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION2))
m_wndButton3.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION3))
return TRUE
}
(
45
)
如何一个
创
建三
态
下
压
按
钮
可以使用新的
BS_PUSHBUTTON
风
格位和
检测
框以及按
钮
来
创
建一个三
态
下
压
按
钮
。
这
很容易,只需将
检测
框和按
钮
拖拉到
对话
中并指定属性
Push—like
即可。不用任何附加程序就可以成
为
三
态
下
压
按
钮
。
(
46
)
如何
动态创
建控件
分配一个控件
对
象的
实
例并
调
用其
Create
成
员
函数。
开发
者最容易忽略两件事:忘
记
指定
WS_VISBLE
标签
和在
栈
中分配控件
对
象。下例
动态
地
创
建一个下
压
按
钮
控件:
//In class declaration (.H file ).
private : CButton* m _pButton
//In class implementation (.cpp file ) .
m_pButton =new CButton
ASSERT_VALID (m_pButton)
m_pButton —>Create (_T ("Button Title ") , WS_CHILD
|
WS_VISIBLE
|
BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )
(
47
)
如何限制
编辑
框中的准
许
字符
如果用
户
在
编辑
控件中只允
许
接收数字,可以使用一个
标
准的
编辑
控件并指定新的
创
建
标
志
ES_NUMBERS,
它是
Windows 95
新增加的
标
志,
该标
志限制
编辑
控件只按收数字字符。如果用
户
需要
复杂
的
编辑
控件,可以使用
Microsoft
的屏蔽
编辑
控件,它是一个很有用的
OLE
定制控件。
如果希望不使用
OLE
定制控件自己
处
理字符,可以派生一个
CEdit
类
并
处
理
WM_CHAR
消息,然后从
编辑
控件中
过滤
出特定的字符。首先,使用
ClassWizard
建立一个
CEdit
的派生
类
,其次,在
对话类
中指定一个成
员变
量将
编辑
控件分
类
在
OnInitdialog
中
调
用
CWnd: : SubclassDlgItem .
//In your dialog class declaration (.H file )
private : CMyEdit m_wndEdit // Instance of your new edit control .
//In you dialog class implementation (.CPP file )
BOOL CSampleDialog : : OnInitDialog ( )
{
…
//Subclass the edit lontrod .
m_wndEdit .SubclassDlgItem (IDC_EDIT,this)
…
}
使用
ClassWizard
处
理
WM_CHAR
消息,
计
算
nChar
参量并决定所
执
行的操作,用
户
可以确定是否修改、
传
送字符。下例
说
明了如何
显
示字母字符,如果字符是字母字符,
则调
用
CWnd OnChar
,否
则
不
调
用
OnChar.
//Only display alphabetic dharacters .
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
{
//Determine if nChar is an alphabetic character.
if (: : IsCharAlpha ( ( TCHAR) nChar ) )
CEdit : : OnChar (nChar, nRepCnt , nFlags )
}
如果要修改字符,
则
不能
仅仅简单
地用修改
过
的
nChar
调
用
CEdit: : OnChar
,然后
CEdit: : OnChar
调
用
CWnd: : Default
获
取原来的
wParam
和
lParam
的
值
,
这样
是不行的。要修改一个字符,需要首先修改
nChar
,然后用修改
过
的
nChar
调
用
CWnd: : DefWindowProc
。下例
说
明了如何将字符
转变为
大写:
//Make all characters uppercase
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
{
//Make sure character is uppercase .
if (: : IsCharAlpha ( .( TCHAR) nChar)
nChar=: : CharUpper(nChar )
//Bypass default OnChar processing and directly call
//default window proc.
DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))
}
(
48
)
如何改
变
控件的
颜
色
有两
种
方法。其一,可以在父
类
中指定控件的
颜
色,或者利用
MFC4.0
新的消息反射在控件
类
中指定
颜
色。
当控件需要重新着色
时
,工作框
调
用父窗口(通常是
对话
框)的
CWnd: : OnCrtlColor,
可以在父窗口
类
中重置
该
函数并指定控件的新的
绘
画属性。例如,下述代
码
将
对话
中的所有
编辑
控件文本
颜
色改
为红
色:
HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)
{
HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor )
//Draw red text for all edit controls .
if (nCtlColor= = CTLCOLOR_EDIT )
pDC —> SetTextColor (RGB (255, 0 , 0 , ) )
return hbr
}
然而,由于
每
个父窗口必
须处
理通知消息并指定
每
个控件的
绘
画属性,所以,
这种
方法不是完全的面向
对
象的方法。控件
处
理
该
消息并指定
绘
画属性更合情合理。消息反射允
许
用
户这样
做。通知消息首先
发
送
给
父窗口,如果父窗口没有
处
理
则发
送
给
控件。
创
建一个定制彩色列表框控件必
须
遵循下述
步骤
。
首先,使用
ClassWizard
创
建一个
CListBox
的派生
类
并
为该类
添加下述数据成
员
。
class CMyListBox publilc CListBox
{
…
private
COLORREF m_clrFor // foreground color
COLORREF m_clrBack //background color
Cbrush m_brush //background brush
…
}
其次,在
类
的构造函数中,初始化数据中。
CMyListBox : : CMyListBox ()
{
//Initialize data members .
m_clrFore =RGB (255 , 255 , 0) //yellow text
m_clrBack=RGB (0 , 0 , 255) // blue background
m_brush . CreateSolidBrush (m _clrBack )
}
最后,使用
ClassWizard
处
理反射的
WM_CTLCOLOR(=WM_CTLCOLOR)
消息并指定新的
绘
画属性。
HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )
{
pDC—>SetTextColor (m_clrFore)
pDC—>SetBkColor (m_clrBack)
return (HBRUSH) m_brush.GetSafeHandle ()
}
现
在,控件可以自己决定如何
绘
画,与父窗口无
关
。
(
49
)
当向列表框中添加多个
项时
如何防止
闪烁
调
用
CWnd::SetRedraw
清除重画
标
志可以禁止
CListBox
(或者窗口)重画。当向列表框添加几个
项时
,用
户
可以清除重画
标
志,然后添加
项
,最后恢
复
重画
标
志。
为
确保重画列表框的新
项
,
调
用
SetRedraw (TRUE)
之后
调
用
CWnd::Invalidate
。
//Disable redrawing.
pListBox->SetRedraw (FALSE)
//Fill in the list box gere
//Enable drwing and make sure list box is redrawn.
pListBox->SetRedraw (TRUE)
pListBox->Invalidate ()
(
50
)
如何向
编辑
控件中添加文本
由于没有
CEdit:: AppendText
函数,用
户
只好自己做此
项
工作。
调
用
CEdit:: SetSel
移
动
到
编辑
控件末尾,然后
调
用
CEdit:: ReplaceSel
添加文本。下例是
AppendText
的一
种实现
方法:
void CMyEdit:: AppendText (LPCSTR pText)
{
int nLen=GetWindowTextLength ()
SetFocus ()
SetSel (nLen, nLen)
ReplaceSel (pText)
}
(
51
)
如何
访问预
定
义
的
GDI
对
象
可以通
过调
用
CDC:: SlectStockObject
使用
Windows
的几个
预
定
义
的
对
象,
诸
如刷子、笔以及字体。下例使用了
Windows
预
定
义
的笔和刷子
GDI
对
象在
视
窗中画一个
椭圆
。
//Draw ellipse using stock black pen and gray brush.
void CSampleView:: OnDraw (CDC* pDC)
{
//Determine size of view.
CRect rcView
GetClientRect (rcView)
//Use stock black pen and stock gray brush to draw ellipse.
pDC->SelectStockObject (BLACK_PEN)
pDC->SelectStockObject (GRAY_BRUSH)
//Draw the ellipse.
pDC->Ellipse (reView)
}
也可以
调
用新的
SDK
函数
GetSysColorBrush
获
取一个系
统颜
色刷子,下例用背景色在
视
窗中画一个
椭圆
:
void CsampleView:: OnDraw (CDC* pDC)
{
//Determine size of view.
CRect rcView
GetClientRect (rcView)
//Use background color for tooltips brush.
CBrush * pOrgBrush=pDC->SelectObject ( CBrush ::FromHandle( ::GetSysColorBrush (COLOR_INFOBK)))
//Draw the ellipse.
pDC->Ellipse (rcView)
//Restore original brush.
pDC->SelectObject (pOrgBrush)
}
(
52
)
如何
获
取
GDI
对
象的属性信息
可以
调
用
GDIObject:: GetObject
。
这
个函数将指定
图
表
设备
的消息写入到
缓
冲区。下例
创
建了几个有用的
辅
助函数。
//Determine if font is bold.
BOOL IsFontBold (const CFont&font)
{
LOGFONT stFont
font.GetObject (sizeof (LOGFONT), &stFont)
return (stFont.lfBold)? TRUE: FALSE
}
//Return the size of a bitmap.
CSize GetBitmapSize (const CBitmap&bitmap)
{
BITMAP stBitmap
bitmap.GetObject (sizeof (BITMAP), &stBitmap)
return CSize (stBitmap.bmWidth, stBitmap.bmHeight)
}
//Create a pen with the same color as a brush.
BOOL CreatePenFromBrush (Cpen&pen, cost Cbrush&brush)
{
LOGBRUSH stBrush
brush.Getobject (sizeof (LOGBRUSH), &stBrush)
return pen. Createpen (PS_SOLID, 0, stBrush.ibColor)
}
(
53
)
如何
实现
一个橡皮区矩形
CRectTracker
是一个很有用的
类
,可以通
过调
用
CRectTracker::TrackRubberBand
响
应
WM_LBUTTONDOWN
消息来
创
建一个橡皮区矩形。
下例表明使用
CRectTracker
移
动
和重置
视
窗中的
蓝
色
椭圆
的大小是很容易的事情。
首先,在文件档中声明一个
CRectTracker
数据成
员
:
class CSampleView : Public CView
{
…
public :
CrectTracker m_tracker
…
}
其次,在文档
类
的构造函数中初始化
CRectTracker
对
象:
CSampleDoc:: CSampleDOC ()
{
//Initialize tracker position, size and style.
m_tracker.m_rect.SetRect (0, 0, 10, 10)
m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine
}
然后,在
OnDraw
函数中画
椭圆
和踪迹矩形:
void CSampleView:: OnDraw (CDC* pDC)
{
CSampleDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)
//Select blue brush into device context.
CBrush brush (RGB (0, 0, 255))
CBrush* pOldBrush=pDC->SelectObject (&brush)
//draw ellipse in tracking rectangle.
Crect rcEllipse
pDoc->m_tracker.GetTrueRect (rcEllipse)
pDC->Ellipse (rcEllipse)
//Draw tracking rectangle.
pDoc->m_tracker.Draw (pDC)
//Select blue brush out of device context.
pDC->Selectobject (pOldBrush)
}
最后,使用
ClassWizard
处
理
WM_LBUTTONDOWN
消息,并增加下述代
码
。
该
段代
码
根据鼠
标击键
情况可以拖放、移
动
或者重置
椭圆
的大小。
void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
{
//Get pointer to document.
CSampleDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)
//If clicked on ellipse, drag or resize it.Otherwise create a
//rubber-band rectangle nd create a new ellipse.
BOOL bResult=pDoc->m_tracker.HitTest (point)!= CRectTracker::hitNothing
//Tracker rectangle changed so update views.
if (bResult)
{
pDoc->m_tracker.Track (this,point,TRue)
pDoc->SetModifiedFlag ()
pDoc->UpdateAllViews (NULL)
}
else
pDoc->m-tracker.TrackRubberBand(this,point,TRUE)
CView:: onLButtonDown (nFlags,point)
}
(
54
)
如何更新翻
转
背景
颜
色的文本
调
用
CDC:: SetBkmode
并
传
送
OPAQUE
用当前的背景
颜
色填充背景,或者
调
用
CDC::SetBkMode
并
传
送
TRANSPAARENT
使背景保持不
变
,
这
两
种
方法都可以
设
置背景模式。下例
设
置背景模式
为
TRANSPARENT
,可以两次更新串,用花色
带
黑
阴
影更新文本。黑色串在
红
色串之后,但由于
设
置了背景模式仍然可
见
。
void CSampleView:: OnDraw (CDC* pDC)
{
//Determint size of view.
CRect rcView
GetClientRect (rcVieew)
//Create sample string to display.
CString str (_T ("Awesome Shadow Text
...
"))
//Set the background mode to transparent.
pDC->SetBKMode (TRANSPARENT)
w black shadow text.
rcView.OffsetRect (1, 1)
pDc->SetTextColor (RGB (0, 0, 0))
pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)
//Draw red text.
rcView.OffsetRect (-1,-1)
pDc->SetTextColor (RGB (255, 0, 0))
pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)
}
(
55
)
如何
创
建一个具有特定点大小的字体
可以指定字体
逻辑单
位的大小,但有
时
指定字体的点的大小可能会更方便一些。可以如下将字体的点
转换为
字体的高度:
int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72)
下例
创
建了一个
8
点的
Apial
字体:
…
CClientDC dc (AqfxGetMainWnd ())
m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF-SWISS,_T("Arial"))
(
56
)
如何
计
算一个串的大小
函数
CDC:: Det text Extent
根据当前
选择
的字体
计
算一个串的高度和
宽
度。如果使用的不是系
统
字体而是其他字体,
则
在
调
用
GetTextExtent
之前将字体
选进设备
上下文中是很重要的,否
则计
算高度和
宽
度
时
将依据系
统
字体,由此得出的
结
果当然是不正确的。下述
样
板程序当改
变
下
压
按
钮
的
标题时动态调
整按
钮
的大小,按
钮
的大小由按
钮
的字体和
标题
的大小而定。响
应
消息
WM_SETTEXT
时调
用
OnSetText
,
该
消息使用
ON_MESSAE
宏指令定
义
的用
户
自定
义
消息。
LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)
{
//Pass message to window procedure.
LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr(), m_hWnd, GetCurrentMessage() ->message,wParam,lParam)
//Get title of push button.
CString strTitle
GetWindowText (strTitle)
//Select current font into device context.
CDC* pDC=GetDc ()
CFont*pFont=GetFont ()
CFont*pOldFont=pDC->SelectObject (pFont)
//Calculate size of title.
CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength())
//Adjust the button's size based on its title.
//Add a 5-pixel border around the button.
SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE)
//Clean up.
pDC->SelectFont (pOldFont)
ReleaseDC (pDC)
return bResult
}
(
57
)
如何
显
示旋
转
文本
只要用
户
使用
TrueType
或者
GDI
笔或字体就可以
显
示旋
转
文本
(
有些硬件
设备
也支持旋
转
光
栅
字体)。
LOGFONT
结
构中的
ifEscapement
成
员
指定了文本行和
x
轴
的角度,角度的
单
位是十分之一度而不是度,例如,
ifEscapement
为
450
表示字体旋
转
45
度。
为
确保所有的字体沿坐
标
系
统
的同一方向旋
转
,一定要
设
置
ifEscapement
成
员
的
CLIP_LH_ANGLES
位,否
则
,有些字体可能反向旋
转
。下例使用了
14
点
Arial
字体
每间
隔
15
度画一个串。
void CSampleView:: OnDraw (CDC* pDC)
{
//Determine the size of the window.
CRect rcClient
GetClientRect (rcClient)
//Create sample string.
CString str (_T ("Wheeee
...
I am rotating!"))
//Draw transparent, red text.
pDC->SetBkMode (TRANSPARENT)
pDC->SetTextColor (RGB (255,0,0))
CFont font
//font object
LOGFONT stFont //font definition
//Set font attributes that will not change.
memset (&stFont, 0, sizeof (LOGFONT))
stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps(LOGPIXELSY), 72)
stFont.ifWeight=FW_NORMAL
stFont.ifClipPrecision=LCIP_LH_ANGLES
strcpy (stFont.lfFaceName, "Arial")
//Draw text at 15degree intervals.
for (int nAngle=0 nAngle<3600 nAngle+=150)
{
//Specify new angle.
stFont.lfEscapement=nAngle
//Create and select font into dc.
font.CreateFontIndirect(&stfont)
CFont* pOldFont=pDC ->SelectObject(&font)
//Draw the text.
pDC->SelectObject(pOldFont)
font.DelectObjext()
}
}
(
58
)
如何正确
显
示包含
标签
字符的串
调
用
GDI
文本
绘
画函数
时
需要展
开标签
字符,
这
可以通
过调
用
CDC:: TabbedTextOut
或者
CDC:: DrawText
并指定
DT_EXPANDTABS
标
志来完成。
TabbedTextOut
函数允
许
指定
标签
位的数
组
,下例指定
每
20
设备单
位展
开
一个
标签
:
void CSampleView:: OnDraw (CDC* pDC)
{
CTestDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoC)
CString str
str.Format (_T ("Cathy/tNorman/tOliver"))
int nTabStop=20 //tabs are every 20 pixels
pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10)
}
(
59
)
如何快速地格式化一个
CString
对
象
调
用
CString:: Format
,
该
函数和
printf
函数具有相同的参数,下例
说
明了如何使用
Format
函数:
//Get size of window.
CRect rcWindow
GetWindowRect (rcWindow)
//Format message string.
CString strMessage
strMessage.Format (_T ("Window Size (%d, %d)"),
rcWindow.Width (), rcWindow.Height ())
//Display the message.
MessageBox (strmessage)
(
60
)
串太
长时
如何在其末尾
显
示一个省略号
调
用
CDC:: DrawText
并指定
DT_END_ELLIPSIS
标
志,
这样
就可以用小略号取代串末尾的字符使其适合于指定的
边
界矩形。如果要
显
示路径信息,指定
DT_END_ELLIPSIS
标
志并省略号取代串中
间
的字符。
void CSampleView:: OnDraw (CDC* pDC)
{
CTestDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)
//Add ellpsis to end of string if it does not fit
pDC->Drawtext (CString ("This is a long string"), CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS)
//Add ellpsis to middle of string if it does not fit
pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath, CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS)
}
(
61
)
为
什
么
即使
调
用
EnableMenuItem
菜
单项
后,菜
单项还处
于禁止状
态
需要将
CFrameWnd:: m_bAutomenuEnable
设
置
为
FALSE
,如果
该
数据成
员为
TRUE
(缺省
值
),工作框将自
动
地禁止没有
ON_UPDATE_COMMAND_UI
或者
ON_COMMAND
的菜
单项
。
//Disable MFC from automatically disabling menu items.
m_bAuoMenuEnable=FALSE
//Now enable the menu item.
CMenu* pMenu=GetMenu ()
ASSERT_VALID (pMenu)
pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)
(
62
)
如何
给
系
统
菜
单
添加一个菜
单项
给
系
统
菜
单
添加一个菜
单项
需要
进
行下述三个
步骤
:
首先,使用
Resource Symbols
对话
(在
View
菜
单
中
选择
Resource Symbols
...可以
显
示
该对话
)定
义
菜
单项
ID
,
该
ID
应
大于
0x0F
而小于
0xF000
;
其次,
调
用
CWnd::GetSystemMenu
获
取系
统
菜
单
的指
针
并
调
用
CWnd:: Appendmenu
将菜
单项
添加到菜
单
中。下例
给
系
统
菜
单
添加两个新的
int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{
…
//Make sure system menu item is in the right range.
ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM)
ASSERT (IDM-MYSYSITEM<0xF000)
//Get pointer to system menu.
CMenu* pSysmenu=GetSystemmenu (FALSE)
ASSERT_VALID (pSysMenu)
//Add a separator and our menu item to system menu.
CString StrMenuItem (_T ("New menu item"))
pSysMenu->Appendmenu (MF_SEPARATOR)
pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem)
…
}
现
在,
选择
系
统
菜
单项时
用
户应进
行
检测
。使用
ClassWizard
处
理
WM_SYSCOMMAND
消息并
检测
用
户
菜
单
的
nID
参数:
void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
{
//Determine if our system menu item was selected.
if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
{
//TODO-process system menu item
}
else
CMDIFrameWnd ::OnSysCommand (nID, lParam)
}
最后,一个
设计
良好的
UI
应
用程序
应
当在系
统
菜
单项
加亮
时
在状
态
条
显
示一个帮助信息,
这
可以通
过
增加一个包含系
统
菜
单
基
ID
的串表的入口来
实现
。
(
63
)
如何确定
顶层
菜
单
所占据的菜
单
行数
这
可以通
过简单
的减法和除法来
实现
。首先,用
户
需要
计
算主框窗口的高度和客
户
区;其次,从主框窗口的高度中减去客
户
区、框
边
界以及
标题
的高度;最后,除以菜
单栏
的高度。下例成
员
函数是一个
计
算主框菜
单
所占据的行数的代
码实现
。
int CMainFrame:: GetMenuRows ()
{
CRect rcFrame,rcClient
GetWindowRect (rcFrame)
GetClientRect (rcClient)
return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU)
}
(
64
)
在用
户环
境中如何确定系
统显
示元素的
颜
色
调
用
SDK
函数
GetSysColor
可以
获
取一个特定
显
示元素的
颜
色。下例
说
明了如何在
MFC
函数
CMainFrameWnd:: OnNcPaint
中
调
用
该
函数
设
置窗口
标题颜
色。
void CMiniFrameWnd:: OnNcPaint ()
{
…
dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT))
…
(
65
)
如何
查询
和
设
置系
统
参数
在
Windows 3.1 SDK
中介
绍过
SDK
函数
SystemParametersInfo
,
调
用
该
函数可以
查询
和
设
置系
统
参数,
诸
如按
键
的重
复
速率
设
置、鼠
标
双
击
延
迟时间
、
图标
字体以及桌面覆盖位
图
等等。
//Create a font that is used for icon titles.
LOGFONT stFont
∶
: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &s
tFont, SPIF_SENDWININICHANGE)
m_font.CreateFontIndirect (&stFont)
//Change the wallpaper to leaves.bmp.
∶
: SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (" forest.bmp"), SPIF_UPDATEINIFILE)
(
66
)
如何确定当前屏幕分辨率
调
用
SDK
函数
GetSystemMetrics
,
该
函数可以
检
索有
关
windows
显
示信息,
诸
如
标题
大小、
边
界大小以及
滚动
条大小等等。
//Initialize CSize object with screen size.
CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN))
(
67
)
如何使用一个
预
定
义
的
Windows
光
标
调
用
CWinApp:: LoadStandardCursor
并
传
送光
标标识
符。
BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd,
UINT nHitTest, UINT
message)
{
//Display wait cursor if busy.
if (m_bBusy)
{
SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT))
return TRUE
}
return CDialog:: OnSetCursor (pWnd. nHitTest,message)
}
(
68
)
如何
检
索原先的
Task Manager
应
用程序使用的任
务
列表
原先的
Task Manager
应
用程序
显
示
顶层
窗口的列表。
为
了
显
示
该
列表,窗口必
须
可
见
、包含一个
标题
以及不能被其他窗口
拥
有。
调
用
CWnd:: GetWindow
可以
检
索
顶层
窗口的列表,
调
用
IsWindowVisible
、
GetWindowTextLength
以及
GetOwner
可以确定窗口是否
应该
在列表中。下例将把
TaskManager
窗口的
标题
填充到列表中。
void GetTadkList (CListBox&list)
{
CString strCaption
//Caption of window.
list.ResetContent ()
//Clear list box.
//Get first Window in window list.
ASSERT_VALID (AfxGetMainWnd ())
CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST)
//Walk window list.
while (pWnd)
{
// I window visible, has a caption, and does not have an owner?
if (pWnd ->IsWindowVisible()
&& pWnd ->GetWindowTextLength ()
&&! pWnd ->GetOwner ())
{
//Add caption o window to list box.
pWnd ->GetWindowText (strCaption)
list.AddString (strCaption)
}
//Get next window in window list.
pWnd=pWnd ->GetWindow(GW_HWNDNEXT)
}
}
(
69
)
如何确定
Windows
和
Windows
系
统
目
录
有两个
SDK
函数可以完成
该
功能。
GetWindowsDirectory
和
GetSystemDirectory
,下例
说
明了如何使用
这
两个函数:
TCHAR szDir [MAX_PATH]
//Get the full path of the windows directory.
∶
: GetWindowsDirectory (szDir, MAX_PATH)
TRACE ("Windows directory %s/n", szD
ir)
//Get the full path of the windows system directory.
∶
: GetSystemDirectory (szDir, MAX_PATH)
TRACE ("Windows system directory %s/n", szDir)
(
70
)
在哪儿
创
建
临
文件
调
用
SDK
函数
GetTemPath
可以确定
临时
文件的目
录
,
该
函数首先
为临时
路径
检测
TMP
环
境
变
量:如果没有指定
TMP
,
检测
TMP
环
境
变
量,然后返回到当前目
录
。下例
说
明了如何
创
建一个
临时
文件。
…
//get unique temporary file.
CString strFile
GetUniqueTempName (strFile)
TRY
{
//Create file and write data.Note that file is closed
//in the destructor of the CFile object.
CFile file (strFile,CFile ::modeCreate | Cfile:: modeWrite)
//write data
}
CATCH (CFileException, e)
{
//error opening file
}
END_CATCH
…
Void GetuniqueTempName (CString& strTempName)
{
//Get the temporary files directory.
TCHAR szTempPath [MAX_PATH]
DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)
ASSERT (dwResult)
//Create a unique temporary file.
TCHAR szTempFile [MAX_PATH]
UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile)
ASSERT (nResult)
strTempName=szTempFile
}
(
71
)
我怎
样
才能建立一个等待光
标
?
调
用
BeginWaitCursor
函
数
来
启
动
等
待
光
标
,
调
用
EndWaitCursor
函
数
来
结
束
等
待
光
标
。要
注
意,二
者
都
要
调
用
app
的
成
员
函
数,如
下
所
示
:
AfxGetApp()->BeginWaitCursor();
//
要做的事
AfxGetApp()->EndWaitCursor();
(
72
)
我在
MDI
框架中有个
form
视
窗。它有个取消按
钮
,我需要当用
户
按取消按
钮时
可
关闭
form
视
窗。我
应该
如何
关闭该
文档
?
调
用
OnCloseDocument
函
数。
(
73
)
如何
访问
桌面窗口
静
态
函数
CWnd:: GetDesktopWindow
返回桌面窗口的指
针
。下例
说
明了
MFC
函数
CFrameWnd::BeginModalStae
是如何使用
该
函数
进
入内部窗口列表的。
void CFrameWnd::BeginModalState ()
{
…
//first count all windows that need to be disabled
UINT nCount=0
HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)
while (hWnd!=NULL)
{
if (:: IsWindowEnabled (hwnd)
&& CWnd::FromHandlePermanent (hWnd)!=NULL
&& AfxIsDescendant (pParent->m_hWnd, hWnd)
&& :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
{
++nCount
}
hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)
}
…
(
74
)
什
么
是
COLORREF?
我
该
怎
样
用它
?
COLORREF
是
一
个
32-bit
整
型
数
值
,它
代
表
了
一
种
颜
色。你
可
以
使
用
RGB
函
数
来
初
始
化
COLORREF
。例
如:
COLORREF color = RGB(0, 255, 0);
RGB
函
数
接
收
三
个
0-255
数
值
,一
个
代
表
红
色,
一
个
代
表
绿
色,
一
个
代
表
蓝
色。在
上
面的
例
子
中,
红
色
和
蓝
色
值
都
为
0
,所
以
在
该
颜
色
中
没
有
红
色
和
蓝
色。
绿
色
为
最
大
值
255
。所
以
该
颜
色
为
绿
色。
0,0,0
为
黑
色,
255,255,255
为
白
色。
另
一
种
初
始
化
COLORREF
的
方
法
如
下
所
示:
CColorDialog colorDialog;
COLORREF color;
if( colorDialog.DoModal() == IDOK )
{
color = colorDialog.GetColor();
}
这
段
代
码
使
用
了
MFC
中
的
颜
色
对
话
框,它
需
要
文
件。
(
75
)
AppWizard
所
产
生的
STDAFX
文件是干什
么
用的
?
它
主
要
是
协
助
产
生
预
编
译
头
文
件
的。通
常
你
是
不
需
要
修
改
它
的。
(
76
)
我在我的程序中是了
CDWordArray
。我向它添加了
约
10,000
个整数,
这
使得
它
变
得非常非常慢。
为
什
么
会
这么
糟
?
CDWordArray
是
很
好
用
的,只
是
因
为
你
没
有
指
定
数
组
的最大尺寸。因
此,当
你
添
加
新
元
素
时
,
该
类
会
从
堆
中
重
新
分
配
空
间
。不
幸
的
是,
该
类
会
在
每
次
插
入
新
元
素
时
都
为
数
组
重
新
分
配
空
间
。如
果
你
向
它
添
加
了
很
多
新
元
素,所
有
这
些
分
配
和
复
制
数
组
的
操
作
会
就
会
使
它
变
慢。解
决
该
问
题
的
方
法
是,你
可
以
使
用
SetSize
函
数
的
第
二
个
参
数
来
改
变
这
种
重
新
分
配
的
频
率。例
如,如
果
你
把
该
参
数
设
置
为
500
,
则
每
次
数
组
空
间
超
出
时
它
才
重
新
分
配
并
添
加
500
个
新
空
间
,而
不
是
1
个。
这
样
一
来,你
就
可
以
不
用
重
新
分
配
而
添
加
了
另
外
499
个
元
素
空
间
,
这
也
会
大
大
提
高
程
序
的
运
行
速
度。
(
77
)
我
该
如何改
变
MDI
框架窗口的子窗口的大小以使在窗口以一定的大小打
开
?
在
视
中
的
OnInitialUpdate
函
数
中
调
用
GetParentFrame
函
数。
GetParentFrame
会
返
回
一
指
向
一
保
存
有
该
视
的
框
架
窗
口
的
指
针
。然
后
调
用
在
框
架
窗
口
上
调
用
MoveWindow
。
(
78
)
在我的程序的某些部分,我可以
调
用
MessageBox
函数来建立一个信息
对话
框,例如在
视类
中。但是,在其它部分我却不能,如文档
类
中。
为
什
么
?我怎
样
才能在我的
应
用程序
类
中建立一个信息
对话
框?
MessageBox
函
数
来
自
CWnd
类
,所
以
你
只
能
在
从
CWnd
继
承
的
类
(
如
CView )
中
调
用
它。但
是,
MFC
也
提
供
了
AfxMessageBox
函
数,你
可
以
在
任
何
地
方
调
用
它。
(
79
)
我需要在我的程序中
设
置全局
变
量,以使文档中的所有
类
都能
访问
。我
应该
吧
它放到哪儿
?
把
该
变
量
放
到
该
应
用
程
序
类
的
头
文
件
中
的
attribute
处
。然
后,在
程
序
的
任
何
地
方,你
都
可
以
用
下
面
的
方
法
来
访
问
该
变
量:
CMyApp *app = (CMyApp *)AfxGetApp();
app->MyGlobalVariable = ...
(
80
)
我听
说
MFC
可以
发现
内存漏洞,我怎
样
使用
该
特性
?
如
果
你
在
Debug
菜
单
中
的
Go
选
项
(
不
是
Project
菜
单
中
的
Execute
选
项
)
来
运
行
你
的
应
用
程
序,
MFC
应
该
在
程
序
终
止
时
报
告
内
存
漏
洞。如
果
没
有,那
么
试
试
运
行
MFC Tracer
工
具
程
序
(
在
VC++
程
序
组
中
)
,并
启
动
跟
踪。然
后
返
回
应
用
程
序。
(
81
)
我怎
样
才能在我的
应
用程序中循
环浏览
已
经
打
开
的文档
?
使用
CDocTemplate
中未公
开
的
GetFirstDocPosition()
和
GetNextDoc()
函数。
(
82
)才能在我的
应
用程序中循
环浏览
已
经
打
开
的
视
?
使
用
CDocument
中
未
公
开
的
GetFirstViewPosition()
和
GetNextView()
函
数。
(
83
)数
PreCreateWindow
是干什
么
用的
?
PreCreateWindow
允
许
你
在
调
用
CreateWindow
之
前
来
改
变
窗
口
属
性。
(
84
)
该
怎
样
防止
MFC
在窗口
标题栏
上把文档名
预
置成
应
用程序名
?
在
PreCreateWindow
函
数
中
删
除
FWS_PREFIXTITLE
标
志
的
窗
口
样
式:
cs.style &= ~FWS_PREFIXTITLE;
(
85
)
我
应该
怎
样
防止
MFC
在窗口
标题栏
上添加文档名
?
在
PreCreateWindow
函
数
中
删
除
FWS_ADDTOTITLE
标
志
的
窗
口
样
式:
cs.style &= ~FWS_ADDTOTITLE ;
(
86
)
我
应该
如何改
变视
窗口的大小
?
因
为
视
窗
口
实
际
上
是
框
架
窗
口
的
子
窗
口,所
以
你
必
须
改
变
框
架
窗
口
的
大
小,而
不
是
改
变
视
窗
口。使
用
CView
类
中
的
GetParentFrame()
函
数
获
得
指
向
框
架
窗
口
的
指
针
,然
后
调
用
MoveWindow()
函
数
来
改
变
框
架
的
大
小。
这
会
使
变
尺
寸
的
视
充
满
框
架
窗
口。
(
87
)
我有一无模式
对话
框。我怎
样
才能在窗口退出
时删
除
CDialog
对
象
?
把
“delete this”
加
到
PostNcDestroy
中。
这
主
要
用
在
需
要
自
动
删
除
对
象
的
场
合。
(
88
)
为
什
么
把
“delete this”
放在
PostNcDestroy
中而不是
OnNcDestroy?
OnNcDestroy
只
被
已
建
立
的
窗
口
调
用。如
果
建
立
窗
口
失
败
(
如
PreCreateWindow )
,
则
没
有
窗
口
处
来
发
送
WM_NCDESTROY
消
息。
PostNcDestroy
是
在
对
象
窗
口
被
完
全
删
除,在
OnNcDestroy
后,甚
至
在
窗
口
建
立
失
败
之
后
调
用
的。
(
89
)
File
菜
单
中的
MRU
列表是从哪儿来的?列表中的名字放在哪儿了?我怎
样
才能改
变
列表中
项
目的最大
值
?
在
应
用
程
序
类
的
InitInstance
函
数
中
对
LoadStdProfileSettings
的
调
用
中。
该
调
用
接
受
一
个
参
数
(
在
缺
省
情
况
下
如
果
没
有
传
递
值
则
为
4 )
。
MRU
文
件
名
是
从
INI
文
件
中
调
用
的。如
果
你
有
带
有
ID_FILE_MRU_FILE1
的
ID
的
菜
单
选
项
,它
会
为
调
入
的
MRU
列
表
所
替
换
。如
果
你
改
变
传
递
给
LoadStdProfileSettings
的
数
值
(
最
大
为
16 )
,
则
你
就
改
变
了
所
装
如
文
件
名
的
最
大
值
。
(
90
)
我在菜
单
中添加了新的
项
。但是,当我
选该项时
,在状
态栏
上没有出
现
任何提示信息。
为
什
么
?
打
开
资
源
文
件
中
的
菜
单
模
板。打
开
新
菜
单
选
项
的
属
性
对
话
框。在
对
话
框
的
底
部
的
Prompt
编
辑
框
中
,你
可
以
如
下
指
定
状
态
栏
上
的
提
示
信
息
和
工
具
栏
上
的
提
示
信
息
(
如
果
你
已
经
建
立
的
工
具
栏
按
钮
):
Status bar string/nFlying tag
(
91
)
我怎
样
才能在
应
用程序的缺省系
统
菜
单
中加上一些
东
西
?
系
统
菜
单
与
其
它
菜
单
类
似,你
可
以
添
加
或
删
除
项
目,
这
需
要
使
用
CMenu
类
的
成
员
函
数。下
面
的
代
码
在
你
的
系
统
菜
单
后
面
添
加
一
个
新
菜
单
项
:
CMenu *sysmenu;
sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
参
见
MFC
帮
助
文
件
中
的
CMenu
类
。
(
92
)
我建立了一个
对话
框。但是当我
显
示
该对话
框
时
,第一个
编辑
框
总
是不能
获
得焦点,我必
须单击
它来使它
获
得焦点。我怎
样
才能使第一个
编辑
框在
对话
框打
开时
就
获
得焦点
?
打
开
资
源
编
辑
器
中
的
对
话
框
模
板。在
Layout
菜
单
中
选
择
Tab Order
选
项
。按
你
的
需
求
单
击
对
话
框
中
的
控
制
来
重
新
排
列
这
些
控
制
的
tab
顺
序。
(
93
)
我怎
样
才能使一个窗口具有
“always on top”
特性
?
在
调
用
OnFileNew
后,在
你
的
InitInstance
函
数
中
加
上
下
面
的
代
码
:
m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
(94)
我要
为
我的
form view
添加文档模板。我先建立了
对话
框模板,然后使用
ClassWizard
建立了基于
CFormView
的新
类
,它也是从
CDocument
继
承来的。我
还
建立了相
应
的
资
源并在
InitInstance
中添加了新的文档模板。但是,当我
试图
运行
该
程序
时
,出
现
了
Assertion
信息。
为
什
么
?
form
的
对
话
框
模
板
需
要
些
特
殊
设
置
以
便
可
用
于
CFromView
。确
保
这
些
设
置
的
最
简
单
方
法
是
使
用
AppWizard
来
建
立
CFormView
应
用
程
序,并
查
看
AppWizard
所
建
立
的
对
话
框
模
板
所
选
择
的
Styles Properties
。你
会
发
现
该
对
话
框
模
板
具
有
下
列
样
式:没
有
标
题
栏
、不
可
见
和
“Child”
。把
你
的
form view
的
对
话
框
属
性
变
成
这
样
就
可
以
了。
(95)
我在一
对话
框中有一列表框,我需要
tabbed
列表框中的
项
目。
但是,当我
处
理含有
tab
字符
(
用
AddString
添加的
)
的列表
项时
,
tab
被
显
示成小黑
块
而没有展
开
。哪儿出
错
了
?
在
对
话
框
模
版
中,打
开
列
表
框
的
属
性。确
保
选
择
了
“Use Tabstops”
样
式。然
后,确
保
在
对
话
框
类
中
OnInitDialog
函
数
中
调
用
SetTabStops
。
(96)
我建立了一个
应
用程序,并使用了
CRecordset
类
。但是,当我运行
该
程序
时
,它
试图
要
访问
数据
库
,并
给
出
“Internal Application Error”
对话
框。我
应该
怎
样
做
?
通
常
情
况
下,当
你
的
程
序
中
向
数
据
库
发
送
信
息
的
SQL
语
句
出
现
问
题
时
才
出
现
该
对
话
框。例
如,参
见
下
面
的
例
子:
set.m_strFilter = "(ZipCode = '27111')";
如
果
ZipCode
列
被
定
义
为
字
符
串
时
不
会
出
现
问
题
,如
果
定
义
为
long
,
则
会
出
现
“Internal Application Error”
对
话
框,
这
是
由
于
类
型
不
匹
配
的
缘
故。如
果
你
删
除
27111
的
单
引
号,
则
不
会
出
现
问
题
。当
你
看
到
“Internal Application Error”
时
,最
好
检
查
一
下
试
图
要
发
送
给
数
据
库
的
SQL
语
句。
(97)
我用
ClassWizard
建立了一个
类
。但是,我把名字取
错
了,我想把它从
项
目中
删
除,
应该
如何做
?
在
ClassWizard
对
话
框
关
闭
后,用
文
件
管
理
器
删
除
新
类
的
H
和
CPP
文
件。然
后
打
开
ClassWizard
,它
会
提
示
丢
失
了
两
个
文
件,并
询
问
你
该
如
何
做。你
可
以
选
择
从
项
目
中
删
除
这
两
个
问
的
按
钮
。
(98)
当我打
开应
用程序中的窗口
时
,我要
传递该
窗口的矩形尺寸。
该
矩形指定了窗口的外
围
大小,但是当我
调
用
GetClientRect
时
,所得到的尺寸要比所希望的
值
要小
(
因
为
工具
栏
和窗口
边
框的
缘
故
)
。有其它方法来
计
算窗口的尺寸
吗
?
参见 CWnd::CalcWindowRect。
(99)
我在文档
类
中
设
置了一个整型
变
量。
但是,当我
试图
把
该变
量写入
Serialize
函数中的
archive
文件中
时
,出
现
了
类
型
错误
。而文档中的其它
变
量没有
问题
。
为
什
么
?
archive
类
只
重
载
某
些
类
型
的
>>
和
<<
操
作
符。
“int”
类
型
没
有
在
其
中,也
许
是
因
为
int
变
量
在
Windows 3.1
与
Windows NT/95
有
所
不
同
的
缘
故
吧。
“long”
类
型
得
到
了
支
持,所
以
你
可
以
把
int
类
型
改
成
long
型。参
见
MFC
帮
助
文
件
中
CArchive
类
。
(100)
如何控制菜
单
的大小
?
我用
MFC
的
CMenu
生成了一个
动态
菜
单
(
例如
File,Edit,View...Help),
我想控制
这
个菜
单
的大小
(
长
+
高
).
方法一
:
查
找
WM_MEASUREITEM
和
MEASUREITEMSTRUCT.
方法二
:
查询
系
统
::GetSystemMetric(SM_CXMENUSIZE).
/*
你可以通
过
如下代
码
来
获
得文本的大小
:
(A)
获
得被使用的字体
*/
NONCLIENTMETRICS ncm;
HFONT hFontMenu;
SIZE size;
size.cy = size.cy = 0;
memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
{
hFontMenu = CreateFontIndirect(&ncm.lfMenuFont);
/*
(B)
获
得菜
单项
的文本
: */
char szText[_MAX_PATH];
pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);
/*
然后
,
获
得菜
单项
文本的高度
: */
HFONT hFontOld;
HDC hDC;
hDC = ::GetDC(NULL);
hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);
GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size);
SelectObject(hDC, hFontOld);
::ReleaseDC(NULL, hDC);
}
/*
此
时
,size.cy
即
为
高度
,size.cx
为宽
度
,
你可以
给
菜
单
加上自定
义
的高度和
宽
度
,
通
过
比
较
,
我
发现宽
度
为
4
比
较
合适。
*/
(101)
改
变
LVIS_SELECTED
的状
态颜
色
?
我想将
CListCtrl
项
和
CTreeCtrl
项
在
LVIS_SELECTED
状
态时
的
颜
色
变
灰
.
方法一
:
查
找函数
CustomDraw,
它是
IE4
提供的公共控制
,
允
许
有你自己的代
码
.
方法二
:
生成一个
draw
控件
,
然后在
DrawItem
中
处
理文本
颜
色
.
(102)
如何只存
储
文档的某一部分
?
我只想存
储
文档的某一部分
,
能否象使用文件一
样
使用文档
?(
也就是有定位函数
).
将
每
个
CArchive
类设
置
为
CFile
类
的派生
类
,
这样
你就能使用
Seek
等成
员
函数
.
(103)
保存工具条菜
单
有
bug
吗
?
使用浮
动
菜
单
条
时
,SaveBarState
和
LoadBarState
出
现
了
问题
.
如果菜
单
是浮
动
的
,
重起
应
用程序
时
它会出
现
在左上角
,
而它固定在屏幕其它位置
时
,
下一次启
动
就会出
现
在
该
位置
,
这
是什
么
原因
?
你
试试这
个
PToolBar->Create(this,...,ID_MYTOOLBAR);
你的工具条需要包括
id,
而不是象默
认
的工具条那
样
.
(104) Tip of the day
的
bug
我
创
建了一个
简单
的
mdi
应
用程序
,
使用
.BSF(
自定
义
的文档
扩
展名
)
作
为
它的文档我保存一个
foo.bsf
文档后
,
可以在
资
源管理器中双
击该
文件打
开
mdi
应
用程序同
时
打
开
foo.bsf
文档
.
但当我
给
mdi
应
用程序加上
a tip of the day
组
件之后
,
从
资
源管理器中双
击
foo.bsf
后
,
就会
给
我一个警告
:ASSERT(::IsWindow(m_hWnd)),
然后
mdi
应
用程序就死那了
.
当从
dde
启
动应
用程序
(
例如
:
双
击
相
关
文档
)
时
,"Tip of the Day"
是有
bug
的
.
你可以看看函数
"ShowTipAtStartup",
它在
"InitInstance"
中
调
用
,
可以看到
tip of the day
作
为
一个模式
对话
框
显
示
,
在
处
理其它消息
时
它一直
进
行消息循
环
你可心修改
ShowTipAtStartup
使其从
dde
启
动时
不出
现
tip of the day.
void CTipOfApp::ShowTipAtStartup(void)
{
// CG: This function added by 'Tip of the Day' component.
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (
cmdInfo.m_bShowSplash &&
cmdInfo.m_nShellCommand != CCommandLineInf:FileDDE
)
{
CTipDlg dlg;
if (dlg.m_bStartup)
dlg.DoModal();
}
}
如果
还
有其它
bug,
你可以
设
定
cmdInfo.m_nShellCommand
的
过滤
.
(105)
如何可以
让
我的程序可以
显
示在其它的窗口上面
?
让
用
户选择
"
总
是在最上面
"
最好是在系
统
菜
单
里加入一个
选项
.
可以通
过
修改
WM_SYSCOMMAND
消息来
发
送用
户
的
选择
.
菜
单
的命令
标识
(id)
会作
为
一个参数
传给
OnSysCommand().
要定
义标识
(id),
将如下代
码
加入到
CMainFrame.CPP
中
:
#define WM_ALWAYSONTOP WM_USER + 1
将
"
总
在最上面
"
的菜
单项
加入到系
统
菜
单
中
,
将如下代
码
加入到函数
CMainFrame::OnCreate()
中
:
CMenu* pSysMenu = GetSystemMenu(FALSE);
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, WM_ALWAYSONTOP,
"&Always On Top");
使用
ClassWizard,
加入
对
WM_SYSCOMMAND
消息的
处
理
,
你
应该
改
变
消息
过滤
器
,
使用系
统
可以
处
理
这
个消息
.
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
switch ( nID )
{
case WM_ALWAYSONTOP:
if ( GetExStyle() & WS_EX_TOPMOST )
{
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,
MF_UNCHECKED);
}
else
{
SetWindowPos(&wndTopMost, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED);
}
break;
default:
CFrameWnd::OnSysCommand(nID, lParam);
}
}
(106)
如何控制窗口框架的最大最小尺寸
?
要控制一个框架的的最大最小尺寸
,
你需要做两件事情
.
在
CFrameWnd
的
继
承
类
中
处
理消息
WM_GETMINMAXINFO,
结
构
MINMAXINFO
设
置了整个窗口
类
的限制
,
因此
记
住要考
虑
工具条
,
卷
动
条等等的大小
.
//
最大最小尺寸的象素点
-
示例
#define MINX 200
#define MINY 300
#define MAXX 300
#define MAXY 400
void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
CRect rectWindow;
GetWindowRect(&rectWindow);
CRect rectClient;
GetClientRect(&rectClient);
// get offset of toolbars, scrollbars, etc.
int nWidthOffset = rectWindow.Width() - rectClient.Width();
int nHeightOffset = rectWindow.Height() - rectClient.Height();
lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;
lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;
lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;
lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset;
}
第二
步
,
在
CFrameWnd
的
继
承
类
的
PreCreateWindow
函数中去掉
WS_MAXIMIZEBOX
消息
,
否
则
在最大化
时
你将得不到
预
料的
结
果
.
BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style &= ~WS_MAXIMIZEBOX;
return CFrameWnd::PreCreateWindow(cs);
}
(107)
如何改
变
窗口框架的
颜
色
?
MDI
框架的客
户
区被另一个窗口的框架所覆盖
.
为
了改
变
客
户
区的背景色
,
你需要重画
这
个客
户
窗口
.
为
了做到
这
点
,
你要
处
理消息
WM_ERASEBKND
产
生一个新
类
,
从
CWnd
继
承
,
姑且称之
为
CMDIClient.
给
它加上一个成
员变
量
,
#include "MDIClient.h"
class CMainFrame : public CMDIFrameWnd
{
...
protected:
CMDIClient m_wndMDIClient;
}
在
CMainFrame
中重
载
CMDIFrameWnd::OnCreateClient
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) )
{
m_wndMDIClient.SubclassWindow(m_hWndMDIClient);
return TRUE;
}
else
return FALSE;
}
然后就可以加入
对
消息
WM_ERASEBKGND
的
处
理了
.
(108)
如何将
应
用程序窗口置于屏幕正中
?
要将你的
应
用程序窗口放置在屏幕正中央
,
只
须
在
MainFrame
的
OnCreate
函数中加入
:
CenterWindow( GetDesktopWindow() );