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)
// 使程序最大化 .
主窗口的 指 针 保存在 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 下的画笔, 应该 用 访问 注册表的方法 获 得其路径,要作成一个比 较 考究的程序,考 虑应该 全面点 .
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"
请 注意前两个函数的第一个参数 为 目 录变 量名,后一个 为缓 冲区后两个相反 .
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"
}
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)
向窗口 发 送 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)
}
重 载 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( )
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 的 风 格。
先 说 窗口。
在 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 中写代 码 :
也就是 FixedDialog 形式。 Windows 发 送 WM_GETMAXMININFO 消息来跟踪 , 响 应 它 , 在 OnGetMAXMININFO 中写代 码 :
(
11
)
如何使窗口不可
见
?
很 简单 , 用 SW_HIDE 隐 藏窗口,可以 结 合 FindWindow,ShowWindow 控制 .
很 简单 , 用 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
}
重 载 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
}
这么办 : 在恢 复 程序窗体大小 时 , 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)
调 用 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 可以 处 理多 种编辑 控件。
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 )
调 用 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
) )
}
当窗口需要确定鼠 标 位置 时 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
}
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 )
}
}
调 用 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 来 设 置 标题 。 记 住自己 设 置 标题时 要遵循接口 风 格指南。
创 建主框窗口和 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" ,
调 用 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)
缺省 时 , 工作框 创 建状 态 条和工具条 时 将它 们 作 为 主框窗口的子窗口,状 态 条有一个 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 )
}
如果 设 置了 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
}
可以使用新的 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()
应 用程序的 实 例句柄保存在 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 开发 人 员 指南 " 一 书 有比 较详细 的介 绍 , 这 里就不再多 说乐 。
这 是个很 简单 又是 编 程中 经 常要遇到的 问题 .
向窗口 发 送 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 )
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 来 设 置 标题 。 记 住自己 设 置 标题时 要遵循接口 风 格指南。
创 建主框窗口和 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)
缺省 时 , 工作框 创 建状 态 条和工具条 时 将它 们 作 为 主框窗口的子窗口,状 态 条有一个 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)
三个 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)
缺省 时 , 工作框 创 建状 态 条和工具条 时 将它 们 作 为 主框窗口的子窗口,状 态 条有一个 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)
如果 设 置了 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")
工具条是一个窗口,所以可以在 调 用 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)
}
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 的 资 源 编辑 器,在 对话 框中 显 示位 图 是很容易的, 只需将 图 形控件拖到 对话 中并 选择 适当属性即可,用 户 也可以 显 示 图标 、位 图 以及增 强 型元文件。
这 要 归 功于 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
)
}
调 用 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 对话 。
有两 种 方法。其一, 调 用 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 )
控件也是窗口,所以可以 调 用 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 )
…
}
由于控件是也是窗口,用 户 可以 调 用 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
…
}
诸 如 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
}
调 用 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 按 钮时 拷 贝 的数目增加。
需要 调 用 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 )可以 设 置 对话 的 标签顺 序。
如果使用旋 转 按 钮 的 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
}
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 即可。不用任何附加程序就可以成 为 三 态 下 压 按 钮 。
可以使用新的 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 )
分配一个控件 对 象的 实 例并 调 用其 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 ))
}
如果用 户 在 编辑 控件中只允 许 接收数字,可以使用一个 标 准的 编辑 控件并指定新的 创 建 标 志 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 ()
}
现 在,控件可以自己决定如何 绘 画,与父窗口无 关 。
有两 种 方法。其一,可以在父 类 中指定控件的 颜 色,或者利用 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 ()
调 用 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)
}
由于没有 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)
}
可以通 过调 用 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)
}
可以 调 用 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)
}
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)
}
调 用 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"))
可以指定字体 逻辑单 位的大小,但有 时 指定字体的点的大小可能会更方便一些。可以如下将字体的点 转换为 字体的高度:
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
}
函数 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()
}
}
只要用 户 使用 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)
}
调 用 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)
调 用 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)
}
调 用 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)
需要将 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 的串表的入口来 实现 。
给 系 统 菜 单 添加一个菜 单项 需要 进 行下述三个 步骤 :
首先,使用 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)
}
这 可以通 过简单 的减法和除法来 实现 。首先,用 户 需要 计 算主框窗口的高度和客 户 区;其次,从主框窗口的高度中减去客 户 区、框 边 界以及 标题 的高度;最后,除以菜 单栏 的高度。下例成 员 函数是一个 计 算主框菜 单 所占据的行数的代 码实现 。
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))
…
调 用 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)
在 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))
调 用 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)
}
调 用 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)
}
}
原先的 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)
有两个 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
}
调 用 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();
调 用 BeginWaitCursor 函 数 来 启 动 等 待 光 标 , 调 用 EndWaitCursor 函 数 来 结 束 等 待 光 标 。要 注 意,二 者 都 要 调 用 app 的 成 员 函 数,如 下 所 示 :
AfxGetApp()->BeginWaitCursor();
// 要做的事
AfxGetApp()->EndWaitCursor();
(
72
)
我在
MDI
框架中有个
form
视
窗。它有个取消按
钮
,我需要当用
户
按取消按
钮时
可
关闭
form
视
窗。我
应该
如何
关闭该
文档
?
调 用 OnCloseDocument 函 数。
调 用 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)
}
…
静 态 函数 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 中 的 颜 色 对 话 框,它 需 要 文 件。
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 个 元 素 空 间 , 这 也 会 大 大 提 高 程 序 的 运 行 速 度。
CDWordArray 是 很 好 用 的,只 是 因 为 你 没 有 指 定 数 组 的最大尺寸。因 此,当 你 添 加 新 元 素 时 , 该 类 会 从 堆 中 重 新 分 配 空 间 。不 幸 的 是, 该 类 会 在 每 次 插 入 新 元 素 时 都 为 数 组 重 新 分 配 空 间 。如 果 你 向 它 添 加 了 很 多 新 元 素,所 有 这 些 分 配 和 复 制 数 组 的 操 作 会 就 会 使 它 变 慢。解 决 该 问 题 的 方 法 是,你 可 以 使 用 SetSize 函 数 的 第 二 个 参 数 来 改 变 这 种 重 新 分 配 的 频 率。例 如,如 果 你 把 该 参 数 设 置 为 500 , 则 每 次 数 组 空 间 超 出 时 它 才 重 新 分 配 并 添 加 500 个 新 空 间 ,而 不 是 1 个。 这 样 一 来,你 就 可 以 不 用 重 新 分 配 而 添 加 了 另 外 499 个 元 素 空 间 , 这 也 会 大 大 提 高 程 序 的 运 行 速 度。
(
77
)
我
该
如何改
变
MDI
框架窗口的子窗口的大小以使在窗口以一定的大小打
开
?
在 视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。 GetParentFrame 会 返 回 一 指 向 一 保 存 有 该 视 的 框 架 窗 口 的 指 针 。然 后 调 用 在 框 架 窗 口 上 调 用 MoveWindow 。
在 视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。 GetParentFrame 会 返 回 一 指 向 一 保 存 有 该 视 的 框 架 窗 口 的 指 针 。然 后 调 用 在 框 架 窗 口 上 调 用 MoveWindow 。
(
78
)
在我的程序的某些部分,我可以
调
用
MessageBox
函数来建立一个信息
对话
框,例如在
视类
中。但是,在其它部分我却不能,如文档
类
中。
为
什
么
?我怎
样
才能在我的
应
用程序
类
中建立一个信息
对话
框?
MessageBox 函 数 来 自 CWnd 类 ,所 以 你 只 能 在 从 CWnd 继 承 的 类 ( 如 CView ) 中 调 用 它。但 是, MFC 也 提 供 了 AfxMessageBox 函 数,你 可 以 在 任 何 地 方 调 用 它。
MessageBox 函 数 来 自 CWnd 类 ,所 以 你 只 能 在 从 CWnd 继 承 的 类 ( 如 CView ) 中 调 用 它。但 是, MFC 也 提 供 了 AfxMessageBox 函 数,你 可 以 在 任 何 地 方 调 用 它。
(
79
)
我需要在我的程序中
设
置全局
变
量,以使文档中的所有
类
都能
访问
。我
应该
吧
它放到哪儿
?
把 该 变 量 放 到 该 应 用 程 序 类 的 头 文 件 中 的 attribute 处 。然 后,在 程 序 的 任 何 地 方,你 都 可 以 用 下 面 的 方 法 来 访 问 该 变 量:
CMyApp *app = (CMyApp *)AfxGetApp();
app->MyGlobalVariable = ...
把 该 变 量 放 到 该 应 用 程 序 类 的 头 文 件 中 的 attribute 处 。然 后,在 程 序 的 任 何 地 方,你 都 可 以 用 下 面 的 方 法 来 访 问 该 变 量:
CMyApp *app = (CMyApp *)AfxGetApp();
app->MyGlobalVariable = ...
(
80
)
我听
说
MFC
可以
发现
内存漏洞,我怎
样
使用
该
特性
?
如 果 你 在 Debug 菜 单 中 的 Go 选 项 ( 不 是 Project 菜 单 中 的 Execute 选 项 ) 来 运 行 你 的 应 用 程 序, MFC 应 该 在 程 序 终 止 时 报 告 内 存 漏 洞。如 果 没 有,那 么 试 试 运 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 组 中 ) ,并 启 动 跟 踪。然 后 返 回 应 用 程 序。
如 果 你 在 Debug 菜 单 中 的 Go 选 项 ( 不 是 Project 菜 单 中 的 Execute 选 项 ) 来 运 行 你 的 应 用 程 序, MFC 应 该 在 程 序 终 止 时 报 告 内 存 漏 洞。如 果 没 有,那 么 试 试 运 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 组 中 ) ,并 启 动 跟 踪。然 后 返 回 应 用 程 序。
(
81
)
我怎
样
才能在我的
应
用程序中循
环浏览
已
经
打
开
的文档
?
使用 CDocTemplate 中未公 开 的 GetFirstDocPosition() 和 GetNextDoc() 函数。
使用 CDocTemplate 中未公 开 的 GetFirstDocPosition() 和 GetNextDoc() 函数。
(
82
)才能在我的
应
用程序中循
环浏览
已
经
打
开
的
视
?
使 用 CDocument 中 未 公 开 的 GetFirstViewPosition() 和 GetNextView() 函 数。
使 用 CDocument 中 未 公 开 的 GetFirstViewPosition() 和 GetNextView() 函 数。
(
83
)数
PreCreateWindow
是干什
么
用的
?
PreCreateWindow 允 许 你 在 调 用 CreateWindow 之 前 来 改 变 窗 口 属 性。
PreCreateWindow 允 许 你 在 调 用 CreateWindow 之 前 来 改 变 窗 口 属 性。
(
84
)
该
怎
样
防止
MFC
在窗口
标题栏
上把文档名
预
置成
应
用程序名
?
在 PreCreateWindow 函 数 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 样 式:
cs.style &= ~FWS_PREFIXTITLE;
在 PreCreateWindow 函 数 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 样 式:
cs.style &= ~FWS_PREFIXTITLE;
(
85
)
我
应该
怎
样
防止
MFC
在窗口
标题栏
上添加文档名
?
在 PreCreateWindow 函 数 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 样 式:
cs.style &= ~FWS_ADDTOTITLE ;
在 PreCreateWindow 函 数 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 样 式:
cs.style &= ~FWS_ADDTOTITLE ;
(
86
)
我
应该
如何改
变视
窗口的大小
?
因 为 视 窗 口 实 际 上 是 框 架 窗 口 的 子 窗 口,所 以 你 必 须 改 变 框 架 窗 口 的 大 小,而 不 是 改 变 视 窗 口。使 用 CView 类 中 的 GetParentFrame() 函 数 获 得 指 向 框 架 窗 口 的 指 针 ,然 后 调 用 MoveWindow() 函 数 来 改 变 框 架 的 大 小。 这 会 使 变 尺 寸 的 视 充 满 框 架 窗 口。
因 为 视 窗 口 实 际 上 是 框 架 窗 口 的 子 窗 口,所 以 你 必 须 改 变 框 架 窗 口 的 大 小,而 不 是 改 变 视 窗 口。使 用 CView 类 中 的 GetParentFrame() 函 数 获 得 指 向 框 架 窗 口 的 指 针 ,然 后 调 用 MoveWindow() 函 数 来 改 变 框 架 的 大 小。 这 会 使 变 尺 寸 的 视 充 满 框 架 窗 口。
(
87
)
我有一无模式
对话
框。我怎
样
才能在窗口退出
时删
除
CDialog
对
象
?
把 “delete this” 加 到 PostNcDestroy 中。 这 主 要 用 在 需 要 自 动 删 除 对 象 的 场 合。
把 “delete this” 加 到 PostNcDestroy 中。 这 主 要 用 在 需 要 自 动 删 除 对 象 的 场 合。
(
88
)
为
什
么
把
“delete this”
放在
PostNcDestroy
中而不是
OnNcDestroy?
OnNcDestroy 只 被 已 建 立 的 窗 口 调 用。如 果 建 立 窗 口 失 败 ( 如 PreCreateWindow ) , 则 没 有 窗 口 处 来 发 送 WM_NCDESTROY 消 息。 PostNcDestroy 是 在 对 象 窗 口 被 完 全 删 除,在 OnNcDestroy 后,甚 至 在 窗 口 建 立 失 败 之 后 调 用 的。
OnNcDestroy 只 被 已 建 立 的 窗 口 调 用。如 果 建 立 窗 口 失 败 ( 如 PreCreateWindow ) , 则 没 有 窗 口 处 来 发 送 WM_NCDESTROY 消 息。 PostNcDestroy 是 在 对 象 窗 口 被 完 全 删 除,在 OnNcDestroy 后,甚 至 在 窗 口 建 立 失 败 之 后 调 用 的。
(
89
)
File
菜
单
中的
MRU
列表是从哪儿来的?列表中的名字放在哪儿了?我怎
样
才能改
变
列表中
项
目的最大
值
?
在 应 用 程 序 类 的 InitInstance 函 数 中 对 LoadStdProfileSettings 的 调 用 中。 该 调 用 接 受 一 个 参 数 ( 在 缺 省 情 况 下 如 果 没 有 传 递 值 则 为 4 ) 。 MRU 文 件 名 是 从 INI 文 件 中 调 用 的。如 果 你 有 带 有 ID_FILE_MRU_FILE1 的 ID 的 菜 单 选 项 ,它 会 为 调 入 的 MRU 列 表 所 替 换 。如 果 你 改 变 传 递 给 LoadStdProfileSettings 的 数 值 ( 最 大 为 16 ) , 则 你 就 改 变 了 所 装 如 文 件 名 的 最 大 值 。
在 应 用 程 序 类 的 InitInstance 函 数 中 对 LoadStdProfileSettings 的 调 用 中。 该 调 用 接 受 一 个 参 数 ( 在 缺 省 情 况 下 如 果 没 有 传 递 值 则 为 4 ) 。 MRU 文 件 名 是 从 INI 文 件 中 调 用 的。如 果 你 有 带 有 ID_FILE_MRU_FILE1 的 ID 的 菜 单 选 项 ,它 会 为 调 入 的 MRU 列 表 所 替 换 。如 果 你 改 变 传 递 给 LoadStdProfileSettings 的 数 值 ( 最 大 为 16 ) , 则 你 就 改 变 了 所 装 如 文 件 名 的 最 大 值 。
(
90
)
我在菜
单
中添加了新的
项
。但是,当我
选该项时
,在状
态栏
上没有出
现
任何提示信息。
为
什
么
?
打 开 资 源 文 件 中 的 菜 单 模 板。打 开 新 菜 单 选 项 的 属 性 对 话 框。在 对 话 框 的 底 部 的 Prompt 编 辑 框 中 ,你 可 以 如 下 指 定 状 态 栏 上 的 提 示 信 息 和 工 具 栏 上 的 提 示 信 息 ( 如 果 你 已 经 建 立 的 工 具 栏 按 钮 ):
Status bar string/nFlying tag
打 开 资 源 文 件 中 的 菜 单 模 板。打 开 新 菜 单 选 项 的 属 性 对 话 框。在 对 话 框 的 底 部 的 Prompt 编 辑 框 中 ,你 可 以 如 下 指 定 状 态 栏 上 的 提 示 信 息 和 工 具 栏 上 的 提 示 信 息 ( 如 果 你 已 经 建 立 的 工 具 栏 按 钮 ):
Status bar string/nFlying tag
(
91
)
我怎
样
才能在
应
用程序的缺省系
统
菜
单
中加上一些
东
西
?
系 统 菜 单 与 其 它 菜 单 类 似,你 可 以 添 加 或 删 除 项 目, 这 需 要 使 用 CMenu 类 的 成 员 函 数。下 面 的 代 码 在 你 的 系 统 菜 单 后 面 添 加 一 个 新 菜 单 项 :
CMenu *sysmenu;
sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
参 见 MFC 帮 助 文 件 中 的 CMenu 类 。
系 统 菜 单 与 其 它 菜 单 类 似,你 可 以 添 加 或 删 除 项 目, 这 需 要 使 用 CMenu 类 的 成 员 函 数。下 面 的 代 码 在 你 的 系 统 菜 单 后 面 添 加 一 个 新 菜 单 项 :
CMenu *sysmenu;
sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
参 见 MFC 帮 助 文 件 中 的 CMenu 类 。
(
92
)
我建立了一个
对话
框。但是当我
显
示
该对话
框
时
,第一个
编辑
框
总
是不能
获
得焦点,我必
须单击
它来使它
获
得焦点。我怎
样
才能使第一个
编辑
框在
对话
框打
开时
就
获
得焦点
?
打 开 资 源 编 辑 器 中 的 对 话 框 模 板。在 Layout 菜 单 中 选 择 Tab Order 选 项 。按 你 的 需 求 单 击 对 话 框 中 的 控 制 来 重 新 排 列 这 些 控 制 的 tab 顺 序。
打 开 资 源 编 辑 器 中 的 对 话 框 模 板。在 Layout 菜 单 中 选 择 Tab Order 选 项 。按 你 的 需 求 单 击 对 话 框 中 的 控 制 来 重 新 排 列 这 些 控 制 的 tab 顺 序。
(
93
)
我怎
样
才能使一个窗口具有
“always on top”
特性
?
在 调 用 OnFileNew 后,在 你 的 InitInstance 函 数 中 加 上 下 面 的 代 码 :
m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
在 调 用 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 被 显 示成小黑 块 而没有展 开 。哪儿出 错 了 ?
(95) 我在一 对话 框中有一列表框,我需要 tabbed 列表框中的 项 目。 但是,当我 处 理含有 tab 字符 ( 用 AddString 添加的 ) 的列表 项时 , tab 被 显 示成小黑 块 而没有展 开 。哪儿出 错 了 ?
在
对
话
框
模
版
中,打
开
列
表
框
的
属
性。确
保
选
择
了
“Use Tabstops”
样
式。然
后,确
保
在
对
话
框
类
中
OnInitDialog
函
数
中
调
用
SetTabStops
。
(96) 我建立了一个 应 用程序,并使用了 CRecordset 类 。但是,当我运行 该 程序 时 ,它 试图 要 访问 数据 库 ,并 给 出 “Internal Application Error” 对话 框。我 应该 怎 样 做 ?
(96) 我建立了一个 应 用程序,并使用了 CRecordset 类 。但是,当我运行 该 程序 时 ,它 试图 要 访问 数据 库 ,并 给 出 “Internal Application Error” 对话 框。我 应该 怎 样 做 ?
通
常
情
况
下,当
你
的
程
序
中
向
数
据
库
发
送
信
息
的
SQL
语
句
出
现
问
题
时
才
出
现
该
对
话
框。例
如,参
见
下
面
的
例
子:
set.m_strFilter = "(ZipCode = '27111')";
如 果 ZipCode 列 被 定 义 为 字 符 串 时 不 会 出 现 问 题 ,如 果 定 义 为 long , 则 会 出 现 “Internal Application Error” 对 话 框, 这 是 由 于 类 型 不 匹 配 的 缘 故。如 果 你 删 除 27111 的 单 引 号, 则 不 会 出 现 问 题 。当 你 看 到 “Internal Application Error” 时 ,最 好 检 查 一 下 试 图 要 发 送 给 数 据 库 的 SQL 语 句。
(97) 我用 ClassWizard 建立了一个 类 。但是,我把名字取 错 了,我想把它从 项 目中 删 除, 应该 如何做 ?
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), 我想控制 这 个菜 单 的大小 ( 长 + 高 ).
我用 MFC 的 CMenu 生成了一个 动态 菜 单 ( 例如 File,Edit,View...Help), 我想控制 这 个菜 单 的大小 ( 长 + 高 ).
方法一
:
查
找
WM_MEASUREITEM
和
MEASUREITEMSTRUCT.
方法二 : 查询 系 统 ::GetSystemMetric(SM_CXMENUSIZE).
方法二 : 查询 系 统 ::GetSystemMetric(SM_CXMENUSIZE).
/*
你可以通
过
如下代
码
来
获
得文本的大小
:
(A) 获 得被使用的字体 */
(A) 获 得被使用的字体 */
NONCLIENTMETRICS ncm;
HFONT hFontMenu;
SIZE size;
size.cy = size.cy = 0;
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];
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;
/*
然后 , 获 得菜 单项 文本的高度 : */
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
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 状 态时 的 颜 色 变 灰 .
我想将 CListCtrl 项 和 CTreeCtrl 项 在 LVIS_SELECTED 状 态时 的 颜 色 变 灰 .
方法一
:
查
找函数
CustomDraw,
它是
IE4
提供的公共控制
,
允
许
有你自己的代
码
.
方法二 : 生成一个 draw 控件 , 然后在 DrawItem 中 处 理文本 颜 色 .
方法二 : 生成一个 draw 控件 , 然后在 DrawItem 中 处 理文本 颜 色 .
(102)
如何只存
储
文档的某一部分
?
我只想存 储 文档的某一部分 , 能否象使用文件一 样 使用文档 ?( 也就是有定位函数 ). 将 每 个 CArchive 类设 置 为 CFile 类 的派生 类 , 这样 你就能使用 Seek 等成 员 函数 .
我只想存 储 文档的某一部分 , 能否象使用文件一 样 使用文档 ?( 也就是有定位函数 ). 将 每 个 CArchive 类设 置 为 CFile 类 的派生 类 , 这样 你就能使用 Seek 等成 员 函数 .
(103)
保存工具条菜
单
有
bug
吗
?
使用浮
动
菜
单
条
时
,SaveBarState
和
LoadBarState
出
现
了
问题
.
如果菜
单
是浮
动
的
,
重起
应
用程序
时
它会出
现
在左上角
,
而它固定在屏幕其它位置
时
,
下一次启
动
就会出
现
在
该
位置
,
这
是什
么
原因
?
你
试试这
个
PToolBar->Create(this,...,ID_MYTOOLBAR);
你的工具条需要包括 id, 而不是象默 认 的工具条那 样 .
你的工具条需要包括 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) 如何控制窗口框架的最大最小尺寸 ?
当从 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) 如何改 变 窗口框架的 颜 色 ?
// 最大最小尺寸的象素点 - 示例
#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) 如何将 应 用程序窗口置于屏幕正中 ?
#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() );
CenterWindow( GetDesktopWindow() );