VC如何在VC5中控制工具条的停靠位置

时间:2022-03-03 00:18:39

 

作者:宋立波



在VC5 中开发大型应用程序时,工具条通常是程序中必不可少的重要功能因素,
其中工具条在整个窗口中的停靠位置尤其关键,它直接影响到程序界面的外观形
象。下面针对笔者实际开发中各类工具条停靠位置的控制过程,详细阐述其实现
技巧。
  一、标准工具条停靠位置的控制
  VC5 应用程序向导生成的框架代码中,都具有普通工具条的控制方法。正
常情况下工具条类CToolBar是控制条类CControlBar 的派生类,其显示的初始
停靠位置是通过调用继承的函数CControlBar::EnableDocking(DWORD dwStyle)来
确定的,其参数dwStyle用来指定停靠具体位置,与本文有关的风格如下(其余请
参阅VC5的联机文档):
  CBRS_ALIGN_TOP 停靠在框架窗口客户区域顶部
  CBRS_ALIGN_BOTTOM 停靠在框架窗口客户区域底部
  CBRS_ALIGN_LEFT 停靠在框架窗口客户区域左边
  CBRS_ALIGN_RIGHT 停靠在框架窗口客户区域右边
  CBRS_ALIGN_ANY 停靠在框架窗口客户区域任何位置
  在利用应用程序向导AppWizard 生成的应用程序中,其控制代码默认的停靠
位置控制风格为CBRS_ALIGN_ANY,即允许停靠在框架窗口客户区域的任何边上。
工具条在正常显示时为停靠在窗口客户区域的顶部,控制指令为
EnableDocking(CBRS_ALIGN_ANY)或m_wndToolBar。EnableDocking(CBRS_ALIGN_ANY) ,
注意,在实际程序控制时前者必须处于所有其它控制代码的前面,否则浮动工具
条或特殊工具条等部分代码可能无法奏效。具体控制方法请参考利用应用程序向
导生成的任何一个程序实例的框架代码部分中的建立函数ONCREATE()。
  应用程序的单文档和多文档的窗口框架类均为CFrameWnd 的派生类,其指定
工具条的停靠位置均是通过调用继承的函数 CFrameWnd::EnableDocking(DWORD
dwDockStyle)来实现的,其可选的参数除上述五种之外,还增加了
CBRS_FLOAT_MULTI参数,这个参数主要是为设计浮动工具条而增加的,其用来确
定一个框架窗口中允许存在多个浮动工具条。同样,利用应用程序向导
AppWizard 生成的应用程序,其默认的停靠位置也是CBRS_ALIGN_ANY,即允许工
具条停靠在框架窗口的任何边上,其默认的初始位置为框架窗口的顶部,即为
EnableDocking(CBRS_ALIGN_ANY)或m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY)。

  二、浮动工具条停靠位置的控制
  如果在一个框架窗口中存在多个标准或浮动工具条时,需要利用函数
void DockControlBar(CControlBar *pBar,UINT nDockBarID=0,LPCRECT lpRect= NULL)来
确定要控制停靠位置的工具条,它也是CFrameWnd类的成员函数,其中参数pBar用
来指向被控制停靠位置的工具条对象指针,参数nDockBarID用来确定工具条停靠
在框架窗口的哪条边上,其控制风格的具体取值为:
  AFX_IDW_DOCKBAR_TOP 停靠在框架窗口的顶部
  AFX_IDW_DOCKBAR_BOTTOM 停靠在框架窗口的底部
  AFX_IDW_DOCKBAR_LEFT 停靠在框架窗口的左边
  AFX_IDW_DOCKBAR_RIGHT 停靠在框架窗口的右边
  当参数nDockBarID的取值为0时,则工具条可以停靠在框架窗口中的任何一
个可停靠的边上,其默认的初始位置为窗口顶部。
  三、并列工具条停靠位置的控制
  很多大型应用程序中都存在这样的工具条,将多个工具条同时并列停靠在某
窗口的某一条边上。对于这种停靠方法,利用上述工具条控制函数
DockControlBar的lpRect参数,通过控制工具条的停靠矩形区域的方法可以实现。
如笔者实现的函数如下:
  (一)在实现文件MainFrm.h中增加如下成员函数定义
  void DockControlBarLeftOf(CToolBar* Bar,CToolBar* LeftOf);
  (二)在实现文件MainFrm.cpp中增加如下成员函数
  void CMainFrame::DockControlBarLeftOf(CToolBar* Bar,CToolBar* LeftOf)
   { //设置工具条并列停靠在同一条边上
   Crect rect; //矩形区域定义
   DWORD dw;
   UINT n=0;
   RecalcLayout();//重新显示
   LeftOf->GetWindowRect(&rect);
   rect.OffsetRect(1,0);//设置偏移值以停靠在同一边上
   dw=LeftOf->GetBarStyle();
   n=(dw&CBRS_ALIGN_TOP)?AFX_IDW_DOCKBAR_TOP:n;
   n=(dw&CBRS_ALIGN_BOTTOM&&n==0)?AFX_IDW_DOCKBAR_BOTTOM:n;
   n=(dw&CBRS_ALIGN_LEFT&&n==0)?AFX_IDW_DOCKBAR_LEFT:n;
   n=(dw&CBRS_ALIGN_RIGHT&&n==0)?AFX_IDW_DOCKBAR_RIGHT:n;
   DockControlBar(Bar,n,&rect);
   }
  在这个函数中应注意对RecalcLayout()函数和OffsetRect()函数的调用,
前一个函数用来重新显示被调整的客户区和工具条,后一个函数用来重新确定
矩形区域,这相当于利用鼠标将第二个工具条窗口拖动到前一个工具条上然后释放。
  (三)修改应用程序建立函数OnCreate()中的相应DockControlBar()函数
为DoctControlBarOf()函数,并正确设置工具条对象的指针,如笔者实现程序
中的控制代码如下:
  EnableDocking(CBRS_
在自己的应用程序定制多媒体真彩封页,可以使应用程序在显示名称和版权
特性时丰富程序界面,避免由于应用程序启动前进行大量数据初始化时用户进
行较长时间的空等待过程,在给应用程序增加了生动特性和专业特性的同时,
也起到了宣传和广告的作用。虽然VC5中具有特定的类来实现这一功能,但通过
定制自己的应用程序多媒体启动封页,还可使自己的应用程序别具一格。VC5中
的实现步骤:

  1.制作封页位图:制作应用程序多媒体启动封页真彩位图,记录位图的高
度和宽度,建立所需要的其它多媒体声音等文件;

  2.建立应用程序:利用FILE-〉NEW菜单建立名为START的多文档应用程序框
架,并利用类向导AppWizard增加基类为generic CWnd 的新类CSplashWnd,将
新类的文件改名为splash.h和splash.cpp,并增加WM_CREATE和WM_PAINT的消息
映射函数;

  3.定义变量和函数:在splash.h中定义如下成员变量和函数:

  public:

   BOOL Create(CWnd* pParentWnd=NULL);

   HANDLE hBitsSrc;

   LPSTR pBitsSrc;

   UINT iW,iH;

  4.建立启动封页窗口:在splash.cpp中增加Create函数,建立显示位图的
弹出窗口:

  #include "windowsx.h"//增加扩展窗口建立

  ......

  struct{//位图文件头结构

   BITMAPINFOHEADER Header;

  }Info;

  BOOL CSplashWnd::Create(CWnd* pParentWnd)

  { //建立显示位图的弹出窗口

   return CreateEx(0,AfxRegisterWndClass(0,

   AfxGetApp()-〉LoadStandardCursor(IDC_ARROW)),

   NULL,WS_POPUP|WS_VISIBLE,0,0,672,480,

   pParentWnd-〉GetSafeHwnd(),NULL);

  }

  int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)

  { ......

   // TODO: Add your specialized creation code here

   CenterWindow();//使弹出窗口居中

   return 0;

  }

  5.完善析构函数:在splash.cpp中完善析构函数,为显示位图作准备:

  CSplashWnd::CSplashWnd()//完善析构函数

  { iW=672;iH=480;//位图的宽度和高度

   Info.Header.biSize=sizeof(BITMAPINFOHEADER);

   Info.Header.biWidth=iW;

   Info.Header.biHeight=iH;

   Info.Header.biPlanes=1L;

   Info.Header.biBitCount=24L;

   hBitsSrc=::GlobalAlloc(GHND,(long)(iW*iH*3));//分配内存

   pBitsSrc=(LPSTR)::GlobalLock(hBitsSrc);//加锁内存

  }

  CSplashWnd::~CSplashWnd()

  { ::GlobalUnlock(hBitsSrc);//解锁内存

   ::GlobalFree(hBitsSrc);//释放内存

  }

  6.显示真彩位图:在splash.cpp中完善Onpaint函数,实现真彩位图的显示:

  void CSplashWnd::OnPaint()

  {......// TODO: Add your message handler code here

   CFile fbmp;

   fbmp.Open("c://windows//EMC1.BMP",CFile::modeRead|

   CFile::typeBinary|CFile::shareExclusive);//打开文件

   fbmp.Seek(54,CFile::begin);//位图文件头为54字节

   fbmp.ReadHuge(pBitsSrc,(long)(iW*iH*3));//读文件

   fbmp.Close();//关闭文件

   HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

   (BITMAPINFOHEADER FAR*)&(Info.Header),CBM_INIT,

   pBitsSrc,(LPBITMAPINFO)&Info,DIB_RGB_COLORS);//建立位图

   HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);//建立内存

   HBITMAP hBitmapOld=SelectBitmap(hMemDC,hBitmap);//选择对象

   ::StretchBlt(dc.m_hDC,0,0,iW,iH,hMemDC,

   0,0,iW,iH,SRCCOPY);//显示真彩位图

   ::DeleteObject(SelectObject(hMemDC,hBitmapOld));//删除位图

  }

  7.弹出窗口类声明:在Mainfrm.h中增加代码,为显示和撤销弹出窗口作准备:

  class CsplashWnd;//闪烁窗口类

  ......

  class CMainFrame : public CMDIFrameWnd

  {......

  public:

   CSplashWnd SplashWnd;//声明类

  8.真彩封页的实现:在Mainfrm.cpp中增加显示弹出窗口、播放音乐、延时
功能和撤销弹出窗口的代码,以实现真彩封页的整个处理过程:

  #include "splash.h" //新类支持

  #include "mmsystem.h"//多媒体支持

  #pragma comment(lib,"WINMM.LIB")//多媒体支持

  ......

  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

  {

   SplashWnd.Create(this);//创建弹出窗口

   SplashWnd.ShowWindow(SW_SHOW);//显示弹出窗口

   SplashWnd.UpdateWindow();//更新弹出窗口

   int dd=sndPlaySound("c://windows//reminder.wav",

   SND_ASYNC|SND_LOOP);//异步播放WAV文件

   if (dd==FALSE){//参数SND_ASYNC
在CFormView 中产生CBitmapButtom:
例如要生成一个OPEN和一个SAVE的CBitmapButtom,可按如下方法:

class CMainWindow : public CFrameWnd
{
private:
CBitmapButtom m_OpenButtom;
CBitmapButtom m_SaveButtom;
CBitmapButtom m_SaveButtom;
public:
......
};

int CMainWindow : OnCreate(LPREATESTRUCT)
{
CRect rect;
rect.SetRect(4,4,36.36);
m_OpenButtom.Create(NULL, WS_CHILD | WS_VISIBLE |
BS_OWNERDRAW,
rect, this, IDB_OPEN);
m_OpenBittom.LoadBitmap("OPENU","OPEND");

// m_SaveButtom 如上

。。。。。。。
return 0;
}

......

BEGING_MESSAGE_MAP(CMainWindow, CFromView)
.

......

BEGING_MESSAGE_MAP(CMainWindow, CFromView)
.
ON_BN_CLICKED (IDB_OPEN, OnOpen)
.
.
END_MESSAGE_MAP()

//如果以上方法不行请检查你的BITMAP 资源,APPSTUDIO中,"OPENU"和
// "OPEND" 等的资源名称都是需要用引号引起来的, LoadBitmap不成功
// "OPEND" 等的资源名称都是需要用引号引起来的, LoadBitmap不成功
// 很可能就是由此产生的。
// AutoLoad的用法下次再POST出来
---- 当前,用AppWizard新建的支持文档/视的SDI项目,只含有从CWinApp,
CFrameWnd,CDocument,CView或CView的子类派生的4个类,在CWinApp的
InitInstance函数中只实现了一个管理文档/普通视的文档模板.

---- 若想实现管理文档/滚动视,及管理文档/两行一列可编辑分隔器这样
两个文档模板,只需做:

---- (1) 用AppWizard新建名为T2的支持文档/视的SDI项目,建立的最后
一步,选择CScrollView派生视类.

---- 建立完后,此项目的文件名及类名为:

T2App.h,T2App.cpp: 含CT2App类的声明及实现
MainFrame.h,MainFrame.cpp:
含CMainFrame类的声明及实现
T2Doc.h,T2Doc.cpp: 含CT2Doc类的声明及实现
T2View.h,T2View.cpp: 含CT2View类的声明及实现
(2) 用ClassWizard从CFrameWnd生成名为F2的框架类,从CEditView生成名
为V的视类.

---- (3) 新建一菜单,其ID值为M2,然后新建一串表条目,其ID,VALUE,
CAPTION域分别等于M2,M2的值(在resource.h可找到),"/n/nTEMPLATE2".

---- (4) 在CWinApp.cpp中,加入#include "F2.h"及#include "V.h".

---- 在InitInstance函数的AddDocTemplate(pDocTemplate)语句后,加入以
下语句,以生成 与M2菜单及串表相关的第2个文档模板:

pDocTemplate=new CSingleDocTemplate(
M2,
RUNTIME_CLASS(CT2Doc),
RUNTIME_CLASS(F2),
RUNTIME_CLASS(V));
AddDocTemplate(pDocTemplate);
---- (5) 在F2.h中,加入成员变量private:
CSplitterWnd m_splitter;在F2.cpp中,加入 #include "V.h".

---- 重载框架类F2的成员函数F2::OnCreateClient:

CRect rc;
GetClientRect(&rc);
m_splitter.CreateStatic(this,2,1);
//建立两行一列分隔器
m_splitter.CreateView(0,0,pContext- >
m_pNewViewClass,CSize
(rc.Width(),rc.Height()/2),pContext);

m_splitter.CreateView(1,0,RUNTIME_CLASS
(V),CSize(0,0),pContext);
SetActiveView((CView*)m_splitter.GetPane(0,0));
return TRUE;
---- 初启此SDI,或用户点击了"文件"- >"新建"菜单项时,将出现要求选定
模板类型的"新建"对话框,选定"T2"将运行滚动视模板,而点击"TEMPLATE2"
将运行两行一列可编辑分隔器模板.

---- 要使滚动视中的水平和垂直滚动条可见,可在CT2View::OnInitialUpdate()
中,将sizeTotal.cx,sizeTotal.cy置为大于600的值.

---- 对支持文档/视的MDI项目,可照搬以上的做法,但要从CMDIChildWnd派
生F2框架类.初启此MDI时,不会出现"新建"对话框,这点与SDI不同.仅当用户
点击了"文件"- >"新建"菜单 项时,才会出现"新建"对话框.
有两种方法。其一,调用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对话。
如何用VC++实现在对话框的控件上显示ToolTip 并在状态条上显示控件的信息
---- 利用 VC++ 的 AppWizard,可以很容易地实现工具条和菜单项的 ToolTip
或在状态条上显 示帮助信息,但要在对话框的控件上显示 ToolTip 并在状态条
上显示控件信息并不是那么容易, 其实,利用 VC++ 中的 WM_SETCURSOR 与
TTN_NEEDTEXT 消息就可达到目的。具体操作如下:

---- 一

---- 利用 VC++ 的 MFC AppWizard 生成一个 SDI 或 MDI 的应用程序

---- 二

---- 编辑对话框控件的字符串资源

---- 例如:

---- IDC_DBBUTTON1 = "this is 肖天鹏的第一自制按钮/n天 鹏", 其中字符
串"this is 肖天鹏的第一自制按钮"将在鼠标移到控件上时显示在状态条上,字
符串"天 鹏"将作为 ToolTip 显示。

---- 三

---- 建立消息映射。

---- 在对话框的头文件 (*.H) 中加入以下代码:

protected:
void SetStatusText(UINT nID=0);
//{{AFX_MSG(CFileOp1)
afx_msg void OnDestroy();
afx_msg BOOL OnSetCursor(CWnd* pWnd,
UINT nHitTest, UINT message);
//}}AFX_MSG
afx_msg BOOL OnTipNotify( UINT id, NMHDR *
pNMHDR, LRESULT * pResult );
DECLARE_MESSAGE_MAP()

---- 在对话框的实现文件 (*.CPP) 中加入以下代码:

BEGIN_MESSAGE_MAP(CFileOp1, CDialog)
//{{AFX_MSG_MAP(CFileOp1)
ON_WM_DESTROY()
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
ON_NOTIFY_EX(TTN_NEEDTEXT,0,OnTipNotify)
END_MESSAGE_MAP()

---- 四

---- 编辑消息处理函数。

BOOL CFileOp1::OnSetCursor
(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TODO: Add your message handler
code here and/or call default
if(pWnd==this)
SetStatusText();
else
{
TOOLTIPTEXT m_psttt;
m_psttt.hdr.hwndFrom=m_hWnd;
m_psttt.hdr.idFrom=pWnd- >GetDlgCtrlID();
m_psttt.hdr.code=TTN_NEEDTEXT;
m_psttt.uFlags= TTF_IDISHWND;
SetStatusText(pWnd- >GetDlgCtrlID());
this- >SendMessage(WM_NOTIFY,
m_psttt.hdr.idFrom,(LPARAM)&m_psttt);
}
return CDialog::OnSetCursor
(pWnd, nHitTest, message);
}

void CFileOp1::OnDestroy()
{
SetStatusText();
CDialog::OnDestroy();
}

void CFileOp1::SetStatusText(UINT nID)
{
if(nID==0)
nID=AFX_IDS_IDLEMESSAGE;
CWnd *pWnd=AfxGetMainWnd()- >GetDescendantWindow
(AFX_IDW_STATUS_BAR);
if(pWnd)
{
AfxGetMainWnd()- >SendMessage
(WM_SETMESSAGESTRING ,nID);
pWnd- >SendMessage(WM_IDLEUPDATECMDUI);
pWnd- >UpdateWindow();
}
}

BOOL CFileOp1::OnTipNotify( UINT id, NMHDR *
pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID =pNMHDR- >idFrom;
if (pTTT- >uFlags & TTF_IDISHWND)
{
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
TCHAR szFullText[256];
CString StrTipText;
AfxLoadString(nID,szFullText);
AfxExtractSubString(StrTipText,
szFullText,1,’/n’);
if(!StrTipText.IsEmpty())
strcpy(pTTT- >lpszText,StrTipText);
pTTT- >hinst = AfxGetResourceHandle();
return(TRUE);
}
}
return(FALSE);
}

---- 五

---- 在 Stdafx.h 文件中加入以下指令:

#include 〈 afxpriv.h>
#include 〈 afxres.h>

---- 六

---- 将该对话框作为一个 SDI 或 MDI 应用程序的主框架的子窗口,生成这样
一个对话框后,当你把鼠标移到某个控件 ( 必须有相应的字符串资源 )上时,
就会出现该控件的 ToolTip 和状态条信息。
任志民

  VC++ 5.0风格的工具栏具有平面外观,左边带有一个“把手”,你可以通过
鼠标拖动这个“把手”来移动工具栏。工具栏各组间带有分隔线(如图1所示)。
当鼠标在工具栏上面移动时,工具栏上的相应按钮会突出显示。本文所讨论的增
强型工具栏CEnhanceToolBar类由CToolBar类所派生,是CToolBar类的补充和扩展。

  

  如果你并不在乎工具栏有没有“把手”的话,要生成平面工具栏是十分简单
的。你只需要在CMainFrame的OnCreate()函数中添加一句话就可以(必须加在工
具栏生成函数之后,因为MFC在生成工具栏时,要清除其式样):

  //MainFrm.cpp

  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

  {

   ......

  if(!m_wndToolBar.Create(this)

  //!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

   {

   TRACE0("Failed to create toolbar/n");

   return -1; // fail to create

   }

  m_wndToolBar.ModifyStyle(0,TBSTYLE_FLAT);

  //设置工具栏为平面格式

   ......

  }

  如果你的计算机安装了4.71.1712.3版本的COMCTL32.DLL(该动态库随
IE 4.0一同发行),那就更好了,你的工具栏就会自动绘制分隔线。你可以通过
鼠标拖动工具栏的非按钮区域来移动这种工具栏。GetRight中的工具栏就是这
样的。


  如果你要得到更好看(更“专业”)的工具栏,那么就请跟我一步步地做下去。

  

  1.添加一个新类,本文中叫做CEnhanceToolBar类,由CToolBar类派生。

  2.为CEnhanceToolBar类添加成员变量和函数的声明,并且根据你的需要设
置其访问属性。

  //EnhanceToolBar.h

  // Overrides

  // ClassWizard generated virtual function overrides

  //{{AFX_VIRTUAL(CEnhanceToolBar)

  //按钮状态变化时调用此函数

  virtual void OnUpdateCmdUI(CFrameWnd*pTarget,BOOL bDisableIfNoHndler);

  //}}AFX_VIRTUAL

  // Implementation

  public:

   void DrawGrip(CWindowDC*pDC,CRect& rectWindow);//“把手”绘制函数

   void EraseNonClient();//擦除非客户区

   void DrawSpace();//分隔线绘制函数

   void RedrawBackground();//背景重绘函数

  

  private:

   int ButtonNumber;//工具栏的按钮数(包括分隔线)

   COLORREF HiLight, Shadow;//3D控件的加亮色和阴影色

  

  3.添加成员函数的定义:

  //EnhanceToolBar.cpp

  void CenhanceToolBar :: OnUpdateCmdUI(CframeWnd * pTarget, BOOL bDisableIfNoHndler)

  {//按钮状态变化时调用此函数

   static CUIntArray Styles;

   int Index;

   UINT dwStyle;

   for (Index = 0; Index < ButtonNumber; Index++)

   {

   dwStyle = GetButtonStyle(Index);

   Styles.SetAtGrow(Index,dwStyle);//保存按钮的式样

   }

  CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);

  //调用基类的处理函数

   for (Index = 0; Index < ButtonNumber; Index++)

   {//设置选中的按钮(checked button)为按下的状态

   dwStyle = GetButtonStyle(Index);

   if (dwStyle & TBBS_DISABLED)

   return;//如果按钮为禁用状态,则返回(避免闪烁)

   if (dwStyle & TBBS_CHECKBOX)

   {

   if (dwStyle & TBBS_CHECKED)

   dwStyle |= TBBS_PRESSED;

   else

   dwStyle &= ~TBBS_PRESSED;

   SetButtonStyle(Index,dwStyle);//设置按钮的式样

   }

   }

   //检查按钮的式样是否改变(按下或释放)

   for (Index = 0; Index < ButtonNumber; Index++)

   {

   dwStyle = GetButtonStyle(Index);

   if (Styles[Index] != dwStyle)

   {

   RedrawBackground();//重新绘制背景

   Invalidate();//重新绘制整个工具栏

   break;//已更新整个工具栏,因此没必要继续循环

   }

   }

  }

  

  void CEnhanceToolBar::DrawGrip(CWindowDC *pDC, CRect& rectWindow)

  {//绘制把手

   if (IsFloating())//如果工具栏是浮动状态,则不绘制“把手”

   return;

   CRect GripRect = rectWindow;//得到把手的矩形区域

   GripRect.DeflateRect(1,1);//矩形区域的各边向中心靠近一个像素

  if (m_dwStyle & CBRS_ORIENT_HORZ)

  //如果工具栏为水平状态,则“把手”在左边

   {

   GripRect.right = GripRect.left + 3;//绘制第一条隆起的棱

   pDC->Draw3dRect(GripRect, HiLight, Shadow);

   GripRect.OffsetRect(4,0);//绘制第二条隆起的棱

 
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的处理了.
调用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:: 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)
}
当窗口需要确定鼠标位置时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
) )
}
可以使用新的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

}
原著:Roger Onslow

本文所讨论的工具栏类是同标准的 MFC CToolBar 一同工作的。

注意:你必须有新的 COMCTL32.DLL (版本4.7或更高)。它是随 Internet Explorer 3
一同发行,并且将做为 Windows 98 的标准组件。如果你使用的是 VC++ 5,则你已经有该
动态库了。

所谓类似 Word 97 的增强工具栏具有平面外观,它的左边带有“gripper”并且各组
间带有分隔线。当鼠标移动到上面时,按钮就会突出来。

MFC 使用样式位来控制其平面外观。所以你不能在建立工具栏时来设置这
种样式,你必须建立之后使用SetFlatLookStyle()函数来修改其样式。

平面外观工具栏是透明绘制的。不幸的是,MFC 没有介绍该如何编写这种透明的工具栏,
所以需要你重绘背景。这要通过变尺寸和移动信息来实现,例如当你拖动可移动的工具栏。
你也可以通过其按钮样式改变时来实现。例如,当按钮从按状态变成释放状态时,背景需要
重新绘制。

工具栏控制本身并不在各组按钮间绘制分隔线,只是在其间增加一个空格。该类将
截取 WM_PAINT 消息,并在正确的位置添加分隔线。

工具栏控制也不支持在起左边或顶部的gripper。该类将调整其用户区并绘制相应
的gripper。

使用本类,只要简单的把你的 CToolBar 变成 CFlatToolBar,并在建立工具栏后
调用 SetFlatLookStyle() 函数 (既当工具栏位图装入之后 )。

// FlatToolBar.h
// (c) 1997, Roger Onslow

class CFlatToolBar : public CToolBar
{
DECLARE_DYNAMIC(CFlatToolBar);

public:
void SetFlatLookStyle();
void RepaintBackground();
void DrawSeparators();
void DrawSeparators(CClientDC* pDC);
void EraseNonClient();
void DrawGripper(CWindowDC *pDC, CRect& rectWindow);

protected:
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CFlatToolBar)
virtual void OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler);
//}}AFX_VIRTUAL

// 消息处理函数
protected:
//{{AFX_MSG(CFlatToolBar)
afx_msg void OnWindowPosChanging(LPWINDOWPOS lpWndPos);
afx_msg void OnPaint();
afx_msg void OnNcPaint();
afx_msg void OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp );
//}}AFX_MSG

DECLARE_MESSAGE_MAP();
};
//***************************************************************
// FlatToolBar.cpp

#include "stdafx.h"
#include "flattoolbar.h"

#ifdef _DEBUG
#undef THIS_FILE
#define new DEBUG_NEW
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

BEGIN_MESSAGE_MAP(CFlatToolBar, CToolBar)
//{{AFX_MSG_MAP(CFlatToolBar)
ON_WM_WINDOWPOSCHANGING()
ON_WM_PAINT()
ON_WM_NCPAINT()
ON_WM_NCCALCSIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(CFlatToolBar,CToolBar)
// 必须在建立之后,因为MFC要清除多余的样式位
void CFlatToolBar::SetFlatLookStyle()
{
// 设置平面样式(透明的)
ModifyStyle(0,TBSTYLE_FLAT);

// others are...
// #define TBSTYLE_TOOLTIPS 0x0100
// #define TBSTYLE_WRAPABLE 0x0200
// #define TBSTYLE_ALTDRAG 0x0400
// #define TBSTYLE_FLAT 0x0800
// #define TBSTYLE_LIST 0x1000
}
// 因为按钮是透明的,所以我们需要重新绘制背景

void CFlatToolBar::RepaintBackground()
{
CRect rc; GetWindowRect(&rc); // 获取工具栏的矩形区域
CWnd* pParent = GetParent(); // 获取父窗口
pParent->ScreenToClient(&rc); // 转换为父窗口的坐标
pParent->InvalidateRect(&rc); // 绘制其下面的矩形
}
// 在用户区中绘制分隔线

void CFlatToolBar::DrawSeparators()
{
CClientDC dc(this); // get a dc for the client area
DrawSeparators(&dc); // draw the separators on it
}
// 绘制分隔线
void CFlatToolBar::DrawSeparators(CClientDC* pDC)
{
// 水平与垂直
bool ishorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;

// 获取按钮数目
int nIndexMax = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
int nIndex;

// 试一下每个按钮
for (nIndex = 0; nIndex < nIndexMax; nIndex++)
{
UINT dwStyle = GetButtonStyle(nIndex);
UINT wStyle = LOWORD(dwStyle);

// 如果是分隔线
if (wStyle == TBBS_SEPARATOR)
{
// 获取它的矩形和宽度
CRect rect;
GetItemRect(nIndex,rect);

// 如
让你的工具栏多姿多彩

  ---- 应用程序的工具栏上除了可以放置图形按钮和一些控件,实现快捷操作外,
我们还可以在其上播放动画,以增加程序动感,并使用户知道程序正在工作。此功能
在VC++可以中通过向工具栏添加播放动画的标准控件-CanimateCtrl来方便的实现这
一效果。本程序允许用户通过"查看/动画"菜单播放与关闭动画。
---- 开始编制程序之前,应先选择合适的AVI文件,供程序调用。本文使用sample.avi.,
放置在c:/temp目录下。

---- AVI文件可以用一些AVI编辑器中自己进行制作,如Adobe Premiere 5.1,
Corel Photo-Paint 8等,也可以使用现有AVI资源,制作和选择时,应考虑到工具栏
大小适合播放视频图象较小的动画(本文选取的AVI文件中图象大小为 27 x 14 象素,
Pixel depth是4位。

程序具体实现步骤如下:

---- 1. 创建工程

---- 用MFC AppWizard(exe)创建一个新工程AnimateToolbar,在MFC AppWizard-Step 1
对话框选中"Single Document"选项后,单击Finish按钮,在接着弹出的对话框中单击OK按
钮,工程创建完毕。

---- 2. 创建菜单资源

---- 在菜单"查看中添加"动画(A )"菜单项,并设置其标识号为ID_VIEW_ANIMATE,
状态栏提示(Prompt)设为"播放/停止动画"。

---- 3. 添加工具栏上按纽位图资源。

---- 在位图资源上添加一个新的按纽,标识号设为ID_ANIMATE。

---- 4. 往工具栏中添加一个CanimateCtrl控件,并播放动画。

---- (1) 在CmainFrame类中声明下面的成员变量:

class CMainFrame : public CFrameWnd
{

public:
BOOL IsAnimationActive;//是否播放动画标识
CAnimateCtrl m_Animate;

}

---- (2)在CmainFrame类构造函数中初始化IsAnimationActive变量:
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
IsAnimationActive=TRUE;
}

---- (3)在CMainFrame::OnCreate函数中创建CAnimateCtrl控件
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{

CRect rect;
m_wndToolBar.SetButtonInfo (12,ID_VIEW_ANIMATE,
TBBS_SEPARATOR,40);
m_wndToolBar.GetItemRect (12,&rect);
DWORD dwStyle = WS_CHILD|WS_VISIBLE|ACS_AUTOPLAY|
ACS_TRANSPARENT|ACS_CENTER;
if (!m_Animate.Create( dwStyle, rect, &m_wndToolBar, 0 ))
return FALSE;

}

---- (4) 使用ClassWizard处理菜单项"查看/动画"标识号ID为(ID_VIEW_ANIMATE)
的COMMAND和UPDATE_COMMAND_UI消息,并增加下述代码。该段代码根据可以让用户在播
放动画与关闭动画之间进行切换。
void CMainFrame::OnViewAnimate()
{
// TODO: Add your command handler code here
if(IsAnimationActive){
m_Animate.Open("c://temp//sample.avi");
IsAnimationActive=FALSE;

}
else{
m_Animate.Stop();
m_Animate.Close();
IsAnimationActive=TRUE;
}
}

void CMainFrame::OnUpdateViewAnimate(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetCheck(!IsAnimationActive? 1 : 0);
}

---- 本程序在Visual C++ 6.0,Windows 98环境下调试通过。
一、给文档/视图应用程序做启动画面
(一) 建立一个单文档/视图应用程序Hs
从File菜单选择New对话,在Projects选项卡中选择AppWizard(ex e)图标。键入Hs
作为项目名并单击OK。在第一步中选中Single Docum ent单选按钮,其它接受所有默认选项。
(二) 添加启动画面
当AppWizard完成,而且Visual C++打开项目的时候,从Project菜单中选择
Add To P roject,并单击位于次级菜单上的Components and Controls...,选
择Splash screen组件,如图1所示,单击Insert。接受所有的默认设置。
图1
以上几步就建立起了一个有主框架结构的应用程序,并使它具有了启动画面。
二、给基于对话框的应用程序做启动画面
(一)建立基于对话框的应用程序Spla
从File菜单选择New对话,在Projects选项卡中选择AppWizard(ex e)图标。键入Spla
作为项目名并单击OK。在第一步中选中Dialog B ased单选按钮,其它接受所有默认选项。
(二)做启动画面
这里做启动画面如果仍采用前述用Gallery来插入是不行的,因为基于对话框的应用
程序没有主框架。不过我们可以把上面建立起的启动画面文件移植过来,然后,对程
序进行少许编程修改就行。请按照下面的步骤来做:
1. 将Splash.cpp和Splash.h两个文件从Hs工程中拷贝到你的工程中。添加如下代
码到CSplaApp的InitInstance()函数中。

#include "Splash.h"//头文件请放在开始位置
BOOL CSplaApp::InitInstance()
{
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
CSplashWnd::EnableSplashScreen(cmdInfo.m_bShowSplash);
...
}

2. 接下来,使用ClassWizard来添加OnCreate函数到你的对话框类中,并且添加如下代码:
#include "Splash.h"//头文件请放在开始位置
int CSplaDlg::OnCreate(LPCREATESTRUCT
lpCreateStruct)
{
...
CSplashWnd::ShowSplashScreen(this);
...
}

3. 将Splash16.bmp文件从Hs工程中拷贝到你的工程中。打开Wor kspace的Resouce项,
将Splash16.bmp插入。打开Properties将IDB_BI TMAP1改为IDB_SPLASH,这个ID值只要
和程序中一致起来就行,现在这样改最简便。
现在可以编译运行程序了,程序运行时出现如图2的启动画面。图 2
这是默认的画面,你可以打开图形编辑器自己加工。如果你要改变启动画面的停留时间,
就修改SetTime中的第二个参数,这里是750毫秒。

int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
// Set a timer to destroy the splash screen.
SetTimer(1, 750, NULL);
return 0;
}
本程序在VC6.0下通过。
Visual C++是Microsoft至今最全面和最完善的程序开放产品之一,它提供了一组各种各样的为适应几乎每一种编程风格而设计的工具,在编程能力和方便性方面达到了空前的水平。
应用程序的界面设计占用了整个程序设计的很大一部分工作量,一个应用程序是否成功,界面的好坏有很大的影响,因此,现代的软件设计特别强调界面设计,并且也做得很好,使用户使用起来很容易,对话框就是Windows提供的界面元素的一个,它用来进行信息输入,也可用来把程序的结果或中间结果告诉用户。实际上,它是应用程序中使用最多的一种交互方式。
在Visual C++中,对话框的背景通常是灰色的,文字是黑色的(这也是默认值),见下图。
但用户可以通过使用位图可以很容易地改变对话框的背景,这里,笔者编写了一个CBmpDialog类,将位图引入到对话框的背景之中,改善了对话框的视觉效果。添加了位图背景的对话框效果如以下两图所示。
CBmpDialog类的创建过程如下,首先在资源中设计一个对话框,然后创建一个管理该对话框的类,即CBmpDialog,基类为CDialog,通过类向导为其添加消息处理函数OnCtlColor(
)和OnEraseBkgnd ( ),并在其头文件BmpDialog.h中添加以下内容:

# define BITMAP_TILE 0
# define BITMAP_CENTER 1

class CBmpDialog : public CDialog
{
public:
void SetBitmap (UINT ResID,int Type=BITMAP_TILE); //该函
数装入位图并决定如何显示,缺省放置方式为平铺
private:
int mType; //定义位图放置方式变量
CBrush mHollowBrush; //定义一个画笔类
CBitmap mBitmap; //定义一个位图类
};

接下来在源程序BmpDialog.cpp加入下列代码:
1、构造函数CBmpDialog::CBmpDialog (
),该函数构造了一个CbmpDialog对象,并生成一个空画笔,以便被类引用。

CBmpDialog::CBmpDialog (CWnd* pParent /*=NULL*/)
: CDialog (CBmpDialog::IDD, pParent)
{
mHollowBrush.CreateStockObject (HOLLOW_BRUSH);

}

2、CBmpDialog::OnCtlColor (
)函数,当对话框准备显示一个控件时,调用此函数,它返回一个HBRUSH,用于绘制控件背景,对于静态控件返回一个空画笔,位图将出现在控件的后面;对于其它控件,则采用OnCtlColor
( )的默认值,并允许控件以普通方式绘制,此时,位图不会出现在控件的后面。

HBRUSH CBmpDialog::OnCtlColor (CDC* pDC, CWnd* pWnd,
UINT nCtlColor)
{
if (mBitmap.GetSafeHandle ( ) !=NULL) //返回的位图句柄非空时
{
switch (nCtlColor)
{
case CTLCOLOR_STATIC: //为静态控件时,返回空画笔
pDC->SetBkMode (TRANSPARENT);
return (HBRUSH) mHollowBrush.m_hObject;
break;
default: //对其它控件,采用缺省值
HBRUSH hbr = CDialog::OnCtlColor (pDC,
pWnd, nCtlColor);
return hbr ;
break;
}
}
else //无位图背景时
{
HBRUSH hbr = CDialog::OnCtlColor (pDC, pWnd,
nCtlColor);
return hbr;
}
}

3、CBmpDialog::OnEraseBkgnd (
)函数,当对话框需要重绘时,框架将调用此函数,OnEraseBkgnd (
)显示位图的方式有两种:如果位图居中放置,就先调用基类的OnEraseBkgnd (
),重新绘制整个背景,然后把位图显示在对话框的中心位置;如果想以铺瓦的方式排列位图,就以对话框的左上角
设计XP风格的按钮
作者:郑恒(lbird)
论坛上许多人都在讨论如何编写具有XP风格的界面,其实网上有设计好的类库,可以直接拿来使用。但这些终归是别人写的,能不能转化成自已的呢。于是笔者就对这些代码进行研究,算是偷一点吧:)
研究了几种控件,这里就把其中最简单的按钮控件拿来供大家一起讨论。
这是程序的运行效果:

步骤:
1、创建一个派生自CButton的新类CButtonXp
2、重载PreSubClassWindow()函数,在该函数内修改按钮的风格为自绘制(owner):
添加如下代码:ModifyStyle(0,BS_OWNERDRAW);
3、因为XP风格按钮具有鼠标感应的效果,当鼠标移动到按钮上方时,按钮的颜色会改变。所以就必须跟踪鼠标。当鼠标移到按钮上方时,窗口会收到
WM_MOUSEMOVE消息,但怎么才能得知鼠标离开按钮呢?
这里我们使用 TrackMouseEvent() Api函数:
BOOL TrackMouseEvent( LPTRACKMOUSEEVENT lpEventTrack );
参数:
typedef struct tagTRACKMOUSEEVENT {
DWORD cbSize; //结构大小
DWORD dwFlags; //设定为TME_LEAVE
HWND hwndTrack; //要跟踪鼠标的窗口句柄
DWORD dwHoverTime;} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
调用该函数可以在鼠标离开指定窗口时收到WM_MOUSELEAVE消息。

添加成员变量:m_bOver ,初始化为FALSE。m_bOver=true用来表示鼠标在按钮区域。
添加WM_MOUSEMOVE消息处理函数:
void CButtonXp::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_bOver ==FALSE)
{
//鼠标在按钮之上
m_bOver =TRUE;

//按钮重绘
InvalidateRect(NULL,FALSE);

//跟踪鼠标
//当鼠标离开按钮区域会收到WM_MOUSELEAVE,该消息直接调用OnMouseOut()
TRACKMOUSEEVENT tme;
tme.cbSize =sizeof(TRACKMOUSEEVENT);
tme.dwFlags =TME_LEAVE;
tme.dwHoverTime=0;
tme.hwndTrack =m_hWnd;
::TrackMouseEvent(&tme);
}
CButton::OnMouseMove(nFlags, point);
}
再添加一成员函数OnMouseOut(),
并在BEGIN_MESSAGE_MAP(CButtonXp, CButton)和END_MESSAGE_MAP()之间添加
宏 ON_MESSAGE(WM_MOUSELEAVE,OnMouseOut)
在OnMouseOut()中写入以下代码
void CButtonXp::OnMouseOut ()
{
//鼠标已离开按钮区域
m_bOver =FALSE;

//重绘按钮
InvalidateRect(NULL,FALSE);

}
4、添加成员函数 MouseOver()
//返回鼠标是否在按钮区域内
BOOL CButtonXp::MouseOver()
{
return m_bOver;
}
5、最后重载DrawItem(LPDRAWITEMSTRUCT lpDIS)
void CButtonXp::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CDC *pDC =CDC::FromHandle(lpDIS->hDC);

CRect rtControl(lpDIS->rcItem);

CPen pen,*old_pen;
CBrush brush,*old_brush;
CString strText;

HFONT hOldFont = (HFONT)pDC->SelectObject ((HFONT)::GetStockObject (DEFAULT_GUI_FONT));

UINT state =lpDIS->itemState;

if(state & ODS_FOCUS)
{
rtControl.DeflateRect(1,1); //拥有焦点矩形变小
}

if((state & ODS_DISABLED) ||
(!MouseOver() &&!(state & ODS_SELECTED)))
{
//普通状态、禁用、拥有焦点三种情况下
pen.CreatePen (PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
brush.CreateSolidBrush(HLS_TRANSFORM(::GetSysColor(COLOR_3DFACE),-10,0));
}
else
{
COLORREF crBorder =::GetSysColor(COLOR_HIGHLIGHT);

pen.CreatePen(PS_SOLID, 1, crBorder);

if( state & ODS_SELECTED)
{
//按钮按下时
brush.CreateSolidBrush(HLS_TRANSFORM(crBorder,+50,-50));

pDC->SetTextColor(RGB(240,240,240));
}
else
{
//鼠标在区域内
brush.CreateSolidBrush(HLS_TRANSFORM(crBorder,+80,-66));
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
}
}

if(state &ODS_DISABLED)
pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));//灰色字:禁用状态
else if(state & ODS_SELECTED)
pDC->SetTextColor(RGB(240,240,240)); //白色字:PUSH状态
else if(MouseOver())
pDC->SetTextColor(0); //黑色字:热感应状态
else
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT)); //黑色字:普通状态

old_brush=pDC->SelectObject(&brush);
old_pen =pDC->SelectObject(&pen);

pDC->Rectangle(rtControl);
pDC->SetBkMode(TRANSPARENT);
GetWindowText(strText);
pDC->DrawText(strText,rtControl,DT_SINGLELINE|DT_CENTER|DT_VCENTER);


if(state & ODS_FOCUS)
{
rtControl.DeflateRect(3,3);
pDC->DrawFocusRect(rtControl);
}

pDC->SelectObject(old_pen);
pDC->SelectObject(old_brush);
pDC->SelectObject(hOldFont);
}

计算机世界2001年第49期

用VC制作个性化浏览器

曹朝晖

  随着计算机网络技术的飞速发展,互联网上的网站越来越多,它们在内容和形式上追求特色化和个性化,其中一些精美的网页令人赏心悦目,流连忘返。但是,目前绝大多数人使用的浏览工具却是界面单调、功能整齐划一的商用产品,在追求个性化的时代,这不能不说是一种遗憾。下面本文介绍一种利用VC ++ 6.0制作个性化浏览器的方法。利用这种方法,不但可以制作出个性化的浏览器,同时还能根据需要加入比商业产品更多的安全措施。

功能特点

本文要制作的浏览器程序具有如下功能:

● 自动播号功能;

● 具有前进、后退、停止、刷新、搜索等功能,还可以选用自己喜欢的工具图标,定制个性化界面;

● 自动网站网址记录备份功能;

● 隔离不良网站功能。

在微软IE浏览器中,安全属性选项的受限站点的内容很容易被更改,使安全性大打折扣。本文介绍的方法通过把所有能找到的不良站点放在一个数组中,经编译、链接后生成.EXE文件,他人不能更改,所以具有更高的安全性。这种方法特别适合有小孩的家庭上网、校园学生上网和社会上的网吧管理。

实现步骤

1. 首先用VC ++ 6.0的MFC AppWizard生成一个单文档程序,在第1步到第5步时保持缺省设置,在第6步时将Cview类改为CHtmlView类。

2. 在集成编辑环境下,将Microsoft Web浏览器控件添加到程序中,这样就可以利用该控件的函数来完成浏览器的一些有用的功能,如页面浏览的前进、后退、搜索、停止等。由于这部分功能大多由控件直接完成,本文不再赘述。下面重点介绍如何添加安全措施。

3. 在MFC ClassWizard中添加OnBeforeNavigate2程序。下列代码用来阻止用户访问一些不良网站:

void CSina6View:: OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel)

{

 //不良网站的地址被列在CstringArray类的m_strBlockList 数组中

 for(int i=0; i<m_strBlockList.GetSize(); i++) {

CString strTemp;

strTemp=m_strBlockList.GetAt(i);

//检查用户访问的网站地址lpszURL是否在被禁止的数组中

if(! strnicmp(lpszURL,strTemp,strTemp. GetLength()))

{

//如果用户访问被禁止的网站,则出现提示,并禁止用户浏览该网页

*pbCancel=TRUE;

AfxMessageBox(“此网站被禁止访问!”);

break;

}

}

}

上述代码可以禁止访问不良网站的主页地址,如HTTP://WWW. XXXSEX.COM/等。但对于直接在链接对话框中输入不良网站深层内容地址时,该程序就无能为力,如直接输入内容地址HTTP://WWW. XXXSEX.COM/MANXX/。为严格这种限制,程序必须能阻止访问被限制网站的所有内容。为此,需要对上述代码进行如下修改:

void CSina6View:: OnBeforeNavigate2(LPCTSTR lpszURL, DWORD nFlags, LPCTSTR lpszTargetFrameName, CByteArray& baPostedData, LPCTSTR lpszHeaders, BOOL* pbCancel)

{

for(int i=0; i<m_strBlockList.GetSize(); i++) {

CString strTemp;

strTemp=m_strBlockList.GetAt(i);

//检查请求访问的网站地址是否被列入数组中,或请求访问的网址的前几位是否与被限制的网址一样?如:HTTP://WWW.XXXSEX.COM/XXMAN/作为是HTTP://WWW. XXXSEX.COM/网站的下一层内容,也在被禁止之列

if(! strnicmp(lpszURL, strTemp, strTemp. GetLength())||! strnicmp(lpszURL. Left(strTemp. GetLength())), strTemp, StrTemp.GetLength())

{

*pbCancel=TRUE;

AfxMessageBox(“此网站被禁止访问!”);

break;

}

}

}

这样就能从根本上禁止用户访问已知的不良网站。如果在使用中发现了数组中还没有收集到的不良网站的网址,可以打开源程序把该不良网址添加到数组中。

4. 因为不良网站是动态变化的,所以我们不能、也不可能把所有的不良网站都列入到禁止搜索数组中,并且经常把源程序改来改去也不方便。为此,我们可以采取事后备案的方法,即记录近期用户所浏览的网站地址,以备日后查找和核对,这样也可以对用户起到一定的阻止作用。

在MFC ClassWizard中添加OnNavigate-

Complete2程序:

Void CSina6View::OnNavigateComplete2(LPCTSTR strURL)

{

CFile storeURL;

//打开备份文件

if(!storeURL.Open(“URLHist.dat”,CFile::modeREAD|CFile:: modeWrite))

{

if(! storeURL. Open(“URLHist.dat”, CFile::modeCreate|CFile:: modeWrite))

  return;

}

//找到文件结尾处

storeURL. SeekToEnd();

//写文件

storeURL.Write(strURL, strlen(strURL));

}

作者邮箱: fawudai@263.net
湖北省襄樊市电信局计算机中心
张洪征
---- 很多windows软件的版权对话框中都设有超级链接,这些链接或提供公司网址,或提供电子邮件信箱,使操作者能够非常方便地与公司和作者联系,同时也为公司作了很好的宣传。如果能在自己写的软件中实现这个功能,定会使程序大增光彩。

---- 实现这个功能要用到一个WINDOWS API函数ShellExecute,其原形为:

HINSTANCE ShellExecute(
HWND hwnd, //窗口句柄
LPCTSTR lpOperation, //操作类型
LPCTSTR lpFile, //文件指针
LPCTSTR lpParameters, //文件可带的参数
LPCTSTR lpDirectory, //缺省目录
INT nShowCmd //显示方式
);

---- ShellExecute函数用于打开或执行一个文件,在调用此函数时只须指定要打开或执行的文件名,而不必管用什么程序去打开或执行文件,WINDOWS会自动根据要打开或执行的文件去判断该如何执行文件或用什么程序去打开文件。以下给出一个完整实例,具体实步骤:
创建一个基于对话框的应用程序,命名为hyperlink;

打开资源编辑器,在对话框上添加两个static text控件和两个button控件。
---- Static1和button1并列排放,Static1和button1并列排放。
---- 将static1的ID设为ID_STATIC1,caption设为:计算机世界日报:,button1的ID设为ID_BUTTON1,caption设为:http://www.computerworld.com.cn,并选中flat属性。将static2的ID设为:ID_STATIC2,caption设为为:给我写信:,button2的ID设为ID_BUTTON2,caption设为: west_virginia@netease.com,并选中flat属性。

创建一个新光标,将其图标编辑成一个手的图像,其ID命名为ID_CURSOR1;

给ChyperlinkDlg类增加一个WM_SETCURSOR消息处理函数,其代码如下:
BOOL ChyperlinkDlg::OnSetCursor(CWnd* pWnd,
UINT nHitTest, UINT message)
{
CRect rcButton1,rcButton2;
CPoint ptCursor;
CWnd *pStatic1=GetDlgItem(IDC_BUTTON1);
CWnd *pStatic2=GetDlgItem(IDC_BUTTON2);
pStatic1->GetWindowRect (rcButton1);
pStatic2->GetWindowRect (rcButton2);
GetCursorPos(&ptCursor);
if (rcButton1.PtInRect (ptCursor)||
rcButton2.PtInRect (ptCursor))
{
CWinApp *pApp=AfxGetApp();
HICON hIconBang=pApp->LoadCursor (IDC_CURSOR1);
SetCursor(hIconBang);
return TRUE;
}
else

return CDialog::OnSetCursor
(pWnd, nHitTest, message);
}
其作用是当鼠标位于button1和button2控件上时,
将其形状设为手形。

5、 给IDC_BUTTON1增加BN_CLICKD消息处理函数,代码如下:
void ChyperlinkDlg::OnButton1()
{
// TODO: Add your control notification handler
code here
ShellExecute(m_hWnd,NULL,
"http://www.computerworld.com.cn",
NULL,NULL,SW_SHOWMAXIMIZED);
}

6、 给IDC_BUTTON2增加BN_CLICKD消息处理函数,代码如下:
void ChyperlinkDlg::OnButton2()
{
// TODO: Add your control notification
handler code here
ShellExecute(m_hWnd,NULL,
"mailto:west_virginia@netease.com",
NULL,NULL,SW_SHOWMAXIMIZED);
}

---- 运行此程序,在对话框上显示计算机世界日报的首页链接和作者的电子邮件地址,在其上点鼠标左键后将自动进入计算机日报首页或启动邮件收发程序给作者写信,效果很理想。读者可在此基础上进一步完善,使其更专业化,也可将其写成类,用起来更方便。
---- ShellExecute是一功能很强大的函数,本文只使用了它的一种用法,更详细全面的用法可参考Visual studio 6.0中所带的MSDN library 。

2005-09-01

CComboBox(3) - [MFC]

CComboBox::MeasureItem
virtual void MeasureItem( LPMEASUREITEMSTRUCTlpMeasureItemStruct );
参数
lpMeasureItemStruct指向一个LPMEASUREITEMSTRUCT结构的长指针。
说明
当创建一个具有自定义风格的组合框时,由主程序调用。缺省时此函数什么都不做。可以覆盖它并填充MEASUREITEMSTRUCT结构通知Windows组合框中列表框的维数。如果组合框是CBS_OWNERDRAW-VARIABLE风格的,主程序需要为列表框中的每个项调用此函数。否则,此函数只需调用一次。用CWnd的成员函数SubclassDlgItem创建一个具有CBS_OWNERDRAWFIXED风格的自定义组合框要考虑其它的一些编程细节。参阅“技术指南14”。
关于结构MEASUREITEMSTRUCT,请参阅CWnd::OnMeasureItem。
请参阅 CComboBox::CompareItem,
CComboBox::DrawItem
WM_MEASUREITEM,
CComboBox::DeleteItem

CComboBox::Paste
void Paste( );
说明
本函数把剪贴板中的数据插入到组合框中编辑控件当前光标位置。剪贴板中的数据必须是CF_TEXT格式的。
请参阅 CComboBox::Clear,
CComboBox::Copy,
CComboBox::Cut,
WM_PASTE

CComboBox::ResetContent
void ResetContent( );
说明
本函数删除组合框中列表和编辑控件中的所有项。
请参阅 cb_resetcontent

CComboBox::SelectString
int SelectString( int nStartAfter, LPCTSTR lpszString );
返回值
找到相应的字符串时,返回它的下标。没有找到时,返回CB_ERR,并且当前的选择不变。
参数
nStartAfter指定了查找开始的下标。当查到列表的结尾处时,又继续找到它标志的位置。如果设为-1,则从列表的开始处开始查找匹配的串。
lpszString指向一个以null结尾的字符串,该字符串就是待查找的匹配前缀。查找过程是不区分大小写的。
说明
查找组合框的列表中匹配指定前缀的第一个字符串,如果找到则把它选为当前项,并把它拷贝到编辑控件中。
注意,成员函数SelectString和FindString都是查找字符串,但是SelectString同时也把找到的字符串作为当前选中的项。
请参阅 CComboBox::FindString, CB_SELECTSTRING

CComboBox::SetCurSel
int SetCurSel( int nSelect );
返回值
调用成功时返回选中的项的下标。如果nSelect大于列表中项的个数,则返回CB_ERR。如果nSelect为-1,则清除当前的选择并返回CB_ERR。
参数
nSelect指定要选中的字符串的下标。如果为-1,则清除当前的选择,编辑控件中的内容设置为空。
说明
本函数在组合框的列表框中选择一个字符串。必要时列表框会滚动,以使该字符串在列表的可视区内(列表是可见的时)。编辑控件中的文本将相应地变为选中的字符串。此前在列表框中的选择将不复存在。
请参阅 CComboBox::GetCurSel, CB_SETCURSEL

CComboBox::SetDroppedWidth
int SetDroppedWidth( UINT nWidrh );
返回值
调用成功时,返回列表框的新宽度。否则返回CB_ERR。
参数
nWidth组合框的列表框所允许的最小宽度(以像素为单位)。
说明
本函数用于设置组合框中列表框所允许的最小宽度。只对风格为CBS_DROPD-OWN或CBS_DROPDOWNLIST的组合框有效。缺省时,下拉列表框所允许的最小宽度为0。显示组合框的列表部分时,它的真正宽度是设置的最小宽度和组合框的宽度二者中较大的一个。
请参阅 CComboBox::GetDroppedWidth, CB_SETDROPPEDWIDTH

CComboBox::SetEditSel
BOOL SetEditSel( int nStartChar , int nEndChar );
返回值
调用成功时返回非零值,否则为0。如果CComboBox的风格为CBS_DROPD-OWNLIST或没有列表框,则返回CB_ERR。
参数
nStartChar指定起始位置。如果为-1,则清除当前的选择。
nEndChar指定结束位置。如果为-1,则选中编辑控件中从开始位置到最后的所有字符。
说明
本函数用来选中编辑控件中的部分字符串。位置是从0开始计算的。要选中编辑控件中的第一个字符,开始位置要设为0。结束位置指的是紧跟着要选择的字符串的最后一个字符的那个位置。例如,选中编辑控件中的前四个字符,需要把开始位置设为0,结束位置设为4(而不是3)。
请参阅 CComboBox::GetEditSel, CB_SETEDITSEL

CComboBox::SetExtendedUI
int SetExtendedUI(BOOL bExtended = TRUE );
返回值
调用成功时返回CB_OKAY,否则返回CB_ERR。
参数
bExtended指定组合框是采用扩展的用户接口,还是采用缺省的用户接口。为TRUE时采用扩展的用户接口,FALSE时采用标准的用户接口(缺省的)。
说明
本函数用于为风格为CBS_DROPDOWN或CBS_DROPDOWNLIST的组合框设置使用用户接口的方式。扩展的用户接口可以用以下步骤确认:l 单击组合框的静态控件(只适用于CBS_DROPDOWNLIST风格的组合框);l 按向下的箭头以显示列表框(功能键F4被禁止了)。当项的列表不可见时,是不能在静态控件中滚动的(箭头键被禁止了)。
请参阅 CComboBox::GetExtendedUI, CB_SETEXTENDEDUI

CComboBox::SetHorizontalExtent
void SetHorizontalExtent( UINT nExtent );
参数
nExtent指定组合框中列表框能够水平滚动的像素数。
说明
本函数设置组合框中的列表框所能水

2005-09-01

CComboBox(2) - [MFC]

CComboBox::DrawItem
virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
参数
lpDrawItemStruct指向一个LPDRAWITEMSTRUCT结构的指针,结构中包含了有关项的绘制的信息。
说明
本函数在自定义的组合框的某个可视属性发生改变时由框架调用。结构DRAWITEMSTRUCT中的成员itemAction指明了要进行的绘制动作。缺省时,此函数什么也不做。可以覆盖此函数以实现对自定义组合框的绘制。在此成员函数终止之前,应用必须重设置所有为lpDrawItemStruct中的显示上下文选中的GDI对象。
请参阅 CComboBox::CompareItem,
WM_DRAWITEM,
CComboBox::MeasureItem,
CComboBox::DeleteItem,

CComboBox::FindString
int FinsString( int nStartAfter, LPCTSTR lpszString )const;
返回值
大于等于0时,是找到的匹配字符串的下标。查找未命中时返回CB_ERR。
参数
nStartAfter指定了查找开始的下标。当查到列表的结尾处时,又继续找到它标志的位置。如果设为-1,则从列表的开始处开始查找匹配的串。
lpszString指向一个以null结尾的字符串,该字符串就是待查找的匹配前缀。查找过程是不区分大小写的。
说明
查找组合框的列表中匹配指定前缀的第一个字符串,但不把它选为当前项。
请参阅 CComboBox::SelectString,CComboBox::SetCursel,CB_FINDSTRING

CComboBox::FindStringExact
int FindStringExact( int nIndexStart, LPCTSTR lpszFind ) const;
返回值
返回匹配的项的下标。未查找到匹配串时返回CB_ERR。
参数
nIndexStart指定了查找开始的下标。当查到列表的结尾处时,又继续找到它标志的位置。如果设为-1,则从列表的开始处开始查找匹配的串。
lpszFind指向一个以null结尾的字符串,该字符串中可以包括完整的文件名(包括扩展名)。查找过程是不区分大小写的。
说明
本函数用于查找组合框的列表中匹配指定字符串的第一个项,但不把它选为当前项。如果组合框是自定义的,但未设置CBS_HASSTRING风格,FindStringExact会试图匹配双字值。
请参阅 CComboBox::FindString, CB_FINDSTRINGEXACT

CComboBox::GetCount
int GetCount( ) const;
返回值
返回项的个数。该值比最后一项的下标要大1(因为下标是从0开始计算的)。出错时返回CB_ERR。
说明
本函数用于取得组合框中列表框中项的个数。
请参阅 CB_GETCOUNT

CComboBox::GetCurSel
int GetCursor( ) const;
返回值
返回组合框中列表框中当前选中的项的下标。如果没有选中项,则返回CB_ERR。
说明
本函数用于取得组合框中当前选中的项的下标。
请参阅 CComboBox::SetCurSel, CB_GETCURSEL

CComboBox::GetDroppedControlRect
void GetDroppedControlRect( LPRECT lprect ) const;
参数
lprect指向RECT结构的一个指针,该结构用于接收取得的坐标。
说明
本函数用于取得下拉组合框中可见(已经下拉)的列表框的屏幕坐标。
请参阅 CB_GETDROPPEDCONTROLRECT

CComboBox::GetDroppedState
BOOL GetDroppedState( ) const;
返回值
列表框可见时返回非零值,否则为0。
说明
本函数用于判断下拉组合框的列表框是否可见(是否已经下拉)。
请参阅 CB_SHOWDROPDOWN, CB_GETDROPPEDSTATE

CComboBox::GetDroppedWidth
int GetDroppedWidth( ) const;
返回值
调用成功时,返回允许的最小宽度,否则返回CB_ERR。
说明
本函数用于取得组合框中的列表框所允许的最小宽度(以像素为单位)。它只对风格为CBS_DROPDOWN或CBS_DROPDOWNLIST的组合框有效。缺省时,下拉列表框允许的最小宽度为0。可以调用函数SetDroppedWidth来设置这个值。当组合框的列表框部分显示时,它的宽度是二者中大的那个或组合框的宽度。
请参阅 CComboBox::SetDroppedWidth, CB_GETDROPPEDWIDTH

CComboBox::GetEditSel
DWORD GetEditSel( ) const;
返回值
返回一个32位的值。低字记录了编辑控件中选中的字符串中起始位置,高字记录了紧接着选中的字符串的第一个字符的位置。如果组合框上没有编辑控件,则返回CB_ERR。
说明
本函数取得组合框的编辑控件中当前被选中的字符串的起止位置。
请参阅 CComboBox::SetEditSel, CB_GETEDITSEL

CComboBox::GetExtendedUI
BOOL GetExtendedUI( ) const;
返回值
如果组合框有扩展的用户接口,则返回非零值,否则为0。
说明
调用GetExtendedUI成员函数,确定组合框是具有缺省用户界面,还是扩展的用户界面。扩展的用户界面可用下列方法指定:
 单击组合框的静态控件(只适用于CBS_DROPDOWNLIST风格的组合框)。
 按向下的箭头以显示列表框(功能键F4被禁止了)。当项的列表不可见时,是不能在静态控件中滚动的(箭头键被禁止了)。
请参阅 CComboBox::SetExtendedUI, CB_GETEXTENDEDUI

CComboBox::GetHorizontalExtent
UINT GetHorizontalExtent( ) const;
返回值
返回组合框中列表框的可滚动部分的宽度(以像素为单位)。
说明
本函数取得组合框中列表框的可水平滚动部分的宽度。仅当组合框的列表框有水平滚动条时有效。
请参阅 C

2005-09-01

CComboBox(1) - [MFC]

类CComboBox封装了Windows组合框。组合框由一个列表框和一个静态控件(或编辑控件)组成。列表框部分可以是一直显示的,也可以是隐藏的,在用户单击编辑控件边上的按钮(下拉箭头)时下拉该列表框。列表框中当前选中的项(如果有的话)显示在静态控件或编辑控件中。如果组合框带有下拉风格,则当用户在编辑框中输入列表项的开始字符时,对应项(如果有的话)中的第一个将会加亮显示。下表列出了组合框的三种风格:
风格 列表框何时可见 静态控件还是编辑控件
Simple 总是可见 编辑控件
Drop-down 当用户单击控件边上的下拉箭头时 编辑控件
Drop-down list 当用户单击控件边上的下拉箭头时 静态控件
可以从对话框模板中建立一个CComboBox对象,也可以直接在代码中创建。无论采用哪种方法,都要先调用CComboBox的构造函数构造一个CComboBox对象,然后调用成员函数Create创建控件并在CComboBox对象上应用它。消息映射入口的格式如下:ON_Notification( id, memberFxn )其中id指定了发送通知的组合框控件的子窗口ID,而memberFxn是用于处理该通知的父成员函数的名字。父窗口的函数原型的格式如下:afx_msg void memberFxn( );通知发送的次序是不能预先确定的。例如,通知CBN_SELCHANGE既可能在CBN_CLOSEUP之前也可能在它之后出现。可能的消息映射入口如下:
 ON_CBN_CLOSEUP(Windows 3.1及更高版本) 组合框的列表已被关闭。对于风格为CBS_SIMPLE的组合框来说,不会发送该通知消息。
 ON_CBN_DBCLICK 用户双击了列表框中的一个字符串。只对风格为CBS_SIMPLE的组合框发送。对于风格为CBS_DROPDOWN或CBS_DROP-DOWNLIST的组合框来说,不会出现双击的消息,因为一次单击就会使下拉列表隐藏或显示了。
 ON_CBN_DROPDOWN 下拉出下拉列表(变为可见)。只对风格为CBS_DROPDOWN或CBS_DROPDOWNLIST的组合框起作用。
 ON_CBN_EDITCHANGE 用户发出了一个可能改变编辑控件中文本的动作。与消息CBN_EDITUPDATE不同,本消息是在Windows刷新屏幕之后发出的。风格为CBS_DROPDOWNLIST的组合框没有该通知。
 ON_CBN_EDITUPDATE 编辑控件部分将显示变化了的文本。本通知消息在控件已经格式化了文本但没有显示时发送。风格为CBS_DROPDOWNLIST的组合框没有该通知。
 ON_CBN_ERRSPACE 不能为组合框分配足够的内存进行响应某个请求。
 ON_CBN_SELENDCANCEL(Wndows 3.1及更高版本) 表明用户的选择将被忽略。用户在单击了一个项之后,又单击了另外一个窗口或控件隐藏了组合框的下拉列表。此通知消息在CBN_CLOSEUP消息之前发送,以表明用户的选择将被忽略。即使没有发送CBN_CLOSEUP通知消息,也会发送CBN_SELENDCANCEL或CBN_SELENDOK消息(例如风格为CBS_SIMPLE的组合框)。
 ON_CBN_SELENDOK 用户在选择了一项以后,要么按了ENTER键,要么按了向下箭头键,从而隐藏了组合框的列表。此通知消息在CBN_CLOSEUP之前发送,表明用户的选择将不被认为是有效的。即使没有发送CBN_CLOSEUP通知消息,也会发送CBN_SELENDCANCEL或CBN_SEL-ENDOK消息(例如风格为CBS_SIMPLE的组合框)。
 ON_CBN_KILLFOCUS 组合框将失去输入焦点。
 ON_CBN_SELCHANGE 用户在列表中单击或者利用箭头键选择了另一个项,从而引起了选中项的改变。在处理此消息时,编辑控件中的文本只能通过GetLBText或者类似的某个函数存取。不能使用GetWindowText函数。
 l ON_CBN_SETFOCUS 组合框获得输入焦点。
如果在对话框中创建了一个CComboBox对象,在关闭对话框时该CComboBox对象将自动撤消。如果在另外一个窗口对象中嵌入了一个CComboBox对象,不需要显式地撤消它。如果在堆栈中创建了一个CComboBox对象,它也会被自动地撤消。如果采用new在内存堆中创建了一个CComboBox对象,则必须调用delete来撤消它。
#include <afxwin.h>
请参阅 CWnd, CButton, CEdit, CListBox, CScrollBar, CStatic,CDialog

CComboBox类的成员
构造函数
CcomboBox构造一个CComboBox对象
初始化函数
Create创建一个组合框并应用到CComboBox对象上
InitStorage预先为组合框的列表框中的项和字符串分配内存
通用操作
GetCount取得组合框的列表框中项的个数
GetCurSel取得组合框的列表框中当前选中项(如果有的话)的下标
SetCurSel在组合框的列表框中选择一个字符串
GetEditSel取得组合框的编辑控件中当前选项的起止字符位置
SetEditSel选中组合框的编辑控件中的字符
SetItemData设置组合框中指定项的32位值
SetItemDataPtr把组合框中指定项的32位值设置成一个指定的void型指针
GetItemData检索应用为组合框的项提供的32位值
GetItemDataPtr检索应用为组合框的项提供的32位值,返回一个void型指针
GetTopIndex返回组合框中列表框的第一个可见项的下标
SetTopIndex让组合框的列表框显示指定下标所在的项
SetHorizontalExtent设置组合框中列表框的水平宽度(以像素为单位),如果列表超过该宽度,将需要用滚动条
GetHorizontalExtent返回组合框中列表框的水平宽度(以像

2005-09-01

CBitmap(2) - [MFC]

CBitmap::LoadBitmap
BOOL LoadBitmap( LPCTSTR lpszRecourceName );BOOL LoadBitmap( UINT nIDResource );
返回值
调用成功时返回非零值,否则为0。
参数
lpszResourceName指向一个包含了位图资源名字的字符串(该字符串以null结尾)。
NIDResource指定位图资源中资源的ID号。
说明
本函数从应用的可执行文件中加载由lpszResourceName指定名字或者由nIDResource指定的ID号标志的位图资源。加载的位图被附在CBitmap对象上。如果由lpszResourceName指定名字的对象不存在,或者没有足够的内存加载位图,函数将返回0。可以调用函数CgdiObject::DeleteObject删除由LoadBitmap加载的位图,否则CBitmap的析构函数将删除该位图对象。
警告 在删除位图对象之前,要保证它没有被选到设备上下文中。在Windows3.1以及以后的版本中,增加了如下的位图:
 OBM_UPARROWI
 ORM_DNARROWI
 OBM_RGARROWI
 OBM_LFARROWI
在Windows3.0或者更早版本的设备驱动程序中不支持这些位图。位图的完整列表和图形请参阅“Win32程序员参考”。
请参阅 CBitmap::LoadOEMBitmap,
::LoadBitmap,CgdiObject::DeleteObject

CBitmap::LoadMappedBitmap
BOOL LoadmappedBitmap( UINT nIDBitmap, UNIT nFlags =0,LPCOLORMAP lpColor-Map = NULL, int nMapSize = 0 );
返回值
调用成功时返回非零值,否则为0。
参数
nIDBitmap位图资源的ID号。
NFlags位图的标记。可以是0或者CMB_MASKED。
LpColorMap指向COLORMAP结构的一个指针。结构中记录了映射位图所需的颜色信息。如果本参数为NULL,函数将使用缺省的颜色映射。
NMapsize由lpColorMap指向的颜色映射的数目。
说明
本函数加载一个位图并把它的颜色映射为当前系统颜色。缺省时LoadMapped Bitmap将映射通常在按钮图形中采用的颜色。要建立一个映射的位图,请参阅“Win32 程序员参考斨械腤indows函数::CreateMappedBitmap以及COLORMAP结构。
请参阅 ::LoadBitmap, ::CreateMappedBitmap

CBitmap::LoadOEMBitmap
BOOL LoadOEMBitmap( UINT nIDBitmap );
返回值
调用成功返回非零值,否则为0。
参数
nIDBitmap预定义的Windows位图的ID号。具体定义在头文件WINDOWS.H中。可用的值如下:OBM_BTNCORNERS
 OBM_OLD_RESTORE
 OBM_BTSIZE
 OBM_OLD_RGARROW
 OBM_CHECK
 OBM_OLD_UPARROW
 OBM_CHECKBOXES
 OBM_OLD_ZOOM
 OBM_CLOSE
 OBM_REDUCE
 OBM_COMBO
 OBM_REDUCED
 OBM_DNARROW
 OBM_RESTORE
 OBM_DNARROWD
 OBM_RESTORED
 OBM_DNARROWI
 OBM_RGARROW
 OBM_LFARROW
 OBM_RGARROWD
 OBM_LFARROWD
 OBM_RGARROWI
 OBM_LFARROWI
 OBM_SIZE
 OBM_MNARROW
 OBM_UPARROW
 OBM_OLD_CLOSE
 OBM_UPARROWD
 OBM_OLD_DNARROW
 OBM_UPARROWI
 OBM_OLD_LFARROW
 OBM_ZOOM
 OBM_OLD_REDUCE
 OBM_ZOOMD
说明
本函数用于加载一个Windows预定义的位图。以OBM_OLD开头的位图名表示它们是在Windows3.0之前的版本采用的。使用不是以OBM_OLD开头的常量,需要在包括头文件WINDOW.H之前定义常量OEMRESOURCE。
请参阅 CBitmap::LoadBitmap,
::LoadBitmap

CBitmap::operator HBITMAP
operator HBITMAP( ) const;
返回值
调用成功时返回一个由CBitmap对象表示的Windows GDI对象的句柄,否则返回NULL。
说明
本操作符用于取得CBitmap对象上的Windows GDI对象句柄。这是一个校验性操作符,可直接参考HBITMAP对象。要了解有关使用图形对象的更详细的信息,请参阅“Win32 程序员参考斨械摹巴夹味韵髷。

CBitmap::SetBitmapBits
DWORD SetBitmapBits( DWORD dwCount, const void* lpBits );
返回值
调用成功时返回设置位图位值的字节数,否则为0。
参数
dwCount指定由lpBits指向的字节数。
lpBits指向一个BYTE类型的数组,数组中记录了要拷贝到CBitmap对象的位值。
说明
本函数用lpBits指定的位值设置位图的位值。
请参阅 ::SetBitmapBits

CBitmap::SetBitmapDimension
CSize SetBitmapDimension (int nWidth, int nHeight );
返回值
返回前一个位图的维数。高度存放在CSize对象的成员cy中,宽度存放在成员cx中。
参数
nWidth指定位图的宽度(以0.1毫米为单位)。
nHeight指定位图的高度(以0.1毫米为单位)。
说明
本函数用于设置位图的高度和宽度。GDI一般不用这些数字,除非应用调用成员函数GetBitmapDimension来获取它们。
请参阅 CBitmap::GetBitmapDimensio

2005-09-01

CBitmap(1) - [MFC]

类CBitmap封装了Windows图形设备接口(GDI)中的位图,并且提供了操纵位图的成员函数。使用CBitmap对象之前要先构造CBitmap对象,调用其中的一个初始化成员函数设置位图对象的句柄。此后就可以调用其它成员函数了。要了解有关使用像CBitmap这样的图形对象的详细信息,请参阅联机文档“Visual C++ 程序员指南”中的“图形对象”。#include <afxwin.h>

CBitmap类的成员

构造函数
CBitmap构造一个CBitmap对象

初始化函数
LoadBitmap从应用的可执行文件中加载一个命名的位图资源来初始化位图对象LoadOEMBitmap加载一个预定义的Windows位图来初始化位图对象
LoadMappedBitmap加载一个位图并把它的颜色映射为系统颜色
CreateBitmap用一个指定宽度、高度和位图模式的依赖于设备的内存位图初始化位图对象
CreateBitmapIndirect用BITMAP结构中给出的宽度、高度和模式(可以不指定)的位图初始化位图对象
CreateCompatibleBitmap用一个位图初始化对象使之与指定设备兼容CreateDiscardableBitmap用一个可丢弃的、与指定设备兼容的位图初始化对象
属性
GetBitmap用位图信息填充BITMAP结构
operator HBITMAP返回CBitmap对象上的Windows句柄
操作
FromHandle给出Windows HBITMAP结构的指针时,返回指向CBitmap对象的指针SetBitmapBits把位图的位设为指定的值
GetBitmapBits拷贝指定位图的位值到指定的缓冲
SetBitmapDimension设置位图的宽度和高度(以0.1毫米为单位)
GetBitmapDimension返回位图的宽度和高度。要求已经调用
SetBitmapDimension设置位图的宽度和高度

成员函数
CBitmap:: CBitmap
CBitmap();
说明
构造一个CBitmap对象。生成的对象必须用下面的一个成员函数进行初始化。
请参阅
CBitmap::LoadBitmap,
CBitmap::LoadOEMBitmap,
CBitmap::CreateBitmap,
CBitmap::BitmapIndirect,
CBitmap::CreateCompatibleBitmap,
CBitmap::CreateDiscardableBitmap

CBitmap::CreateBitmap
BOOL CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINTnBitcount, const void* lpBits );
返回值
调用成功时返回非零值,否则为0。
参数
nWidth指定位图的宽度(以像素数为单位)。
NHeight指定位图的高度(以像素数为单位)。
NPlanes指定位图中的彩色位面数。
NBitCount指定位图中每个像素颜色的位数。
LpBits指向一个短整型数组,数组中记录了位图的初始位值。如果为NULL,则新的位图没有被初始化。
说明
本函数用指定的宽度、高度和位模式初始化依赖于设备的内存位图。对彩色位图来说,参数nPlanes和nBitcount要有一个被设置为1。如果二者都被设置为1,则建立一个黑白位图。
虽然不能为显示设备直接选中一个位图,但可以调用CDC::SelectObject把位图置为内存设备上下文(memory device context)的当前位图,然后调用CDC::BitBlt函数把它拷贝到任何兼容的设备上下文中。终止用CreateBitmap建立的CBitmap对象,先要从设备上下文中移出该位图,然后删除该对象。要了解有关的更详细信息,请参阅BITMAP结构中对成员bmBits的描述。BITMAP结构在成员函数CBitmap::CreateBitmapIndirect中的说明。
请参阅 CDC::SelectObject,
CgdiObject::DeleteObject,
CDC::BitBlt, ::CreateBitmap

CBitmap::CreateBitmapIndirect
BOOL CreateBitmapIndirect( LPBITMAP lpBitmap );
返回值
调用成功时返回非零值,否则为0。
参数
lpBitmap指向包含有关位图信息的BITMAP结构。
说明
本函数用lpBitmap指向的结构中指定的宽度、高度和位模式(可以不指定)初始化位图对象。虽然显示设备不能直接选中一个位图,但可以调用CDC::Select Object把位图置为内存设备上下文(memory device context)的当前位图,然后调用CDC::BitBlt或CDC::StrechBlt把它拷贝到任何兼容的设备上下文中(CDC::PatBlt 函数能把当前画刷的位图直接拷贝到显示设备的上下文中)。如果已经调用函数GetObject填充了lpBitmap指向的结构,则位图的位值没有指定,并且位图未被初始化。要初始化该位图,应用可以调用CDC:BitBlt或::SetDIBits把CgdiObject::GetObject函数的第一个参数指定的位图的位值拷贝到CreateBitmapIndirect建立的位图中。终止用CreateBitmapIndirect建立的CBitmap对象,要先从设备上下文中移出该位图,然后删除该对象。
请参阅
CDC::SelectObject,
CDC::BitBlt,
CgdiObject::DeleteObject,
CgdiObject::GetObject,
::CreateBitmapIndirect

CBitmap::CreateCompatibleBitmap
BOOL CreateCompatibleBitmap( CDC* pDC, int nWidth,int nHeight );
返回值
调用成功时返回非零值,否则为0。
参数
pDC指定设备上下文。
NWidth指定位图的宽度(以像素数为单位)。
NHeight指定位图的高度(以像素数为单位)。
说明
初始化一个与pDC指定的设备上下文兼容的位图。位图与指定的设备上下文具有相同的颜色位面数或相同的每个像素的位数。任何与pDC指定的设备兼容的内存设备都可以选择它作为当前位图。如果pDC指向的是内存设备上下文,则返回的位图与设备上下文中当前

2005-09-01

CComboBoxEx - [MFC]

类CComboBoxEx扩展了类CComboBox,支持图像列表。使用CComboBoxEx创建组合框控件不需要书写绘制图像的代码,就可以直接存取图形列表中的图像。对图形列表的支持在标准的CComboBox中,绘制图像需要程序员把组合框控件设为自定义风格。在使用CComboBoxEx时,不再需要把组合框的风格设置为CBS_OWNE-RDRAWFIXED以及CBS_HASSTRINGS,因为类中已经实现了处理图像的功能。在CComboBoxEx控件中,每项最多可有3个图像:一个代表选中状态,一个代表未选中状态,另一个代表覆盖的图像。风格CComboBoxEx支持四种风格:CBS_SIMPLE、CBS_DROPDOWN、CBS_DR-OPDOWNLIST和WS_CHILD。创建窗口时提供了其它的风格时,控件都会忽略它。窗口创建完成之后,可以调用成员函数SetExtendedStyle把组合框设置成其它的风格。采用这些风格,可以:
 在列表中查找字符串可以设置成大小写敏感的;
 创建一个使用斜线(/)、反斜线(/)和句点(.)作为单词的分隔符的组合框控件;
 让组合框控件显示或隐藏图像。如果没有显示图像,组合框可以取消那些为适应图像的显示而进行的缩进;
 创建一个狭窄的组合框,可以调整它的大小使它所包括的大组合框被剪裁缩小。
这些风格的描述在联机文档“Visual C++程序员指南”中的“使用CComboBoxEx”部分。项的保留和和回调项属性项的信息,例如项的下标、图像、缩进值和文本字符串,保存在Win32结构COMBOBOXEXITEM中,该结构在联机文档“平台SDK”中说明。结构中也包括了记录回调标记的成员。要了解有关概念的更详细的说明,请参阅联机文档“Visual C++程序员指南”中的“使用ComboBoxEx”。
#include <afxcmn.h>
请参阅 CComboBox

CComboBoxEx类的成员
构造函数
CComboBoxEx构造一个CComboBoxEx对象
初始化函数
Create创建组合框并和CComboBoxEx对象相联系
操作符
DeleteItem从组合框控件中删除一个项
GetIttem检索组合框中某个项的相关信息
InsertItem在组合框控件中插入一项
SetItem设置组合框中某个项的属性
属性
HasEditChanged检测用户是否改变了组合框中编辑控件的内容
GetExtendedStyle检索在组合框上采用的扩展风格
GetExtendedStyle设置组合框的扩展风格
GetEditCtrl检索组合框中编辑控件的句柄
GetComboBoxCtrl取得指向子组合框控件的指针
GetImageList取得指向在组合框控件中图像列表的指针。
SetImageList为组合框控件设置一个图像列表。

成员函数
CComboBoxEx:: CComboBoxEx
CComboBoxEx( );
说明
本函数创建一个CComboBoxEx对象。
请参阅 CComboBoxEx::Create, CComboBox

CComboBoxEx::Create
BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd,UINT nID );
返回值
对象创建成功时返回非零值,否则为0。
参数
dwStyle指定在组合框上应用的风格的组合。参阅下面的说明部分。
rect对一个CRect对象的或RECT结构的参考,其中记录了组合框的位置和大小。
pParentWnd指向一个CWnd对象,该对象是组合框的父窗口(通常是一个CDialog对象)。不能为NULL。
nID指定组合框的控制ID。
说明
创建一个CComboBoxEx对象需要两步:
1. 调用构造函数CComboBoxEx构造一个CComboBoxEx对象;
2. 调用成员函数Create创建扩展的Windows组合框并且使它与CComboBoxEx对象相联系。
调用Create时,MFC对通用控件进行初始化。
创建组合框时,可指定的风格有:
 CBS_SIMPLE
 CBS_DROPDOWN
 CBS_DROPDOWNLIST
 WS_CHILD
创建窗口时传送的其它风格都被忽略。CComboBoxEx控件也支持扩展风格,它们提供一些附加特征。这些风格在联机文档“平台SDK”的“CComboBoxEx控件扩展风格”中说明。可以调用函数SetExtendedStyle设置扩展风格。
请参阅 CComboBoxEx::CComboBoxEx

CComboBoxEx::DeleteItem
int DeleteIten( int iIndex );
返回值
调用成功时返回组合框控件中剩下的项数。如果nIndex无效,则返回CB_ERR。
参数
nIndex指定待删除的项的下标。
说明
本函数是对通知消息CBEM_DELETEITEM的实现,有关的说明可参阅联机文档“平台SDK”。在调用DeleteItem时,将会向父窗口发送通知CBEM_DEL-ETEITEM和消息WM_NOTIFY。

CComboBoxEx::GetComboBoxCtrl
CComboBox* GetComboBoxCtrl( );
返回值
返回一个CComboBox对象指针。
说明
本函数用于取得CComboBoxEx对象中组合框控件的指针。此CComboBoxEx控件有一个父窗口,该窗口中实现了一个CComboBox。返回值指向的CComboBox对象是一个临时对象,系统将在下一个空闲的处理时间中删除它。
请参阅 CComboBoxEx::GetEditStyle

CComboBoxEx::GetEditCtrl
CEdit* GetEditCtrl( );
返回值
返回一个CEdit对象指针。
说明
本函数用于取得组合框中编辑控件的指针。组合框控件在以CBS_DROPDOWN风格创建时会有一个编辑控件。返回值指向的CEdit对象是一个临时对象,系统将在下一个空闲的处理时间中删除它。
请参阅 CComboBoxEx::Create

CComboBoxEx::GetExtendedStyle
DWORD GetExtendedStyle( ) const;

2005-09-01

CColorDialog - [MFC]

类CColorDialog支持在应用中使用颜色选择对话框。CColorDialog对象是一个拥有一个颜色列表的对话框。用户可以在列表中选择一种颜色,也可以定制颜色,在退出该对话框时,向应用告知选中的颜色。构造一个CColorDialog对象可以使用类中的构造函数,也可以从类CColorDialog派生一个子类,然后定义自己的构造函数。在构造了CColorDialog对象后,可以设置或者修改m_cc结构中的任一个值以初始化对话框控件的值。m_cc是一个CHOOSECOLOR类型的结构。初始化对话框控件之后,就可以调用成员函数DoModal来显示对话框并允许用户选择颜色了。DoModal返回用户对按钮OK或Cancel的选择(返回值依次为IDOK,IDCANCEL)。如果DoModal返回了IDOK,则可以调用CColorDialog的一个成员函数来检索用户选择的颜色信息。可以使用Windows函数CommDlgExtendedError来检测对话框初始化时是否发生了错误,并取得错误的相关信息。类CColorDialog需要使用Windows3.1或更高版本提供的COMMDLG.DLL文件。定制对话框,可以从CColorDialog派生一个子类,提供一个定制的对话框模板,并增加一个消息映射来处理扩展的控件发来的通知。所有悬挂的消息将被送到基类。不需要定制钩子函数。注意 在某些版本中,如果在框架中使其它的CDialog对象变灰色,CColorDialog对象将不会以灰色背景显示。要了解有关使用类CColorDialog的更详细的信息,请参阅联机文档“Visual C++程序员指南”中的“通用对话框类”部分。
#include <afxdlgs.h>

CColorDialog类的成员
数据成员
m_cc用于定制对话框设置的一个结构
构造函数
CColorDialog构造一个CColorDialog对象
操作
DoModal显示对话框,并接收用户的选择
GetColor返回一个包含了选中的颜色的值的COLORREF结构
GetSavedCustomColors检索用户定制的颜色
SetCurrentColor设置当前选中的颜色
可覆盖的函数
OnColorOK覆盖它来检验对话框中输入颜色的有效性

成员函数
CColorDialog::CColorDialog
CColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd*pParentWnd = NULL );
参数
clrInit缺省时选择的颜色。如果没有设置,缺省为RGB(0,0,0)(黑色)。
dwFlags定制函数和对话框外观的一组标志。要了解更详细的信息,请参阅联机文档“Win32 SDK”中的COLORREF结构。
pParentWnd指向对话框的父窗口或者所有者窗口的指针。
说明
本函数构造一个CColorDialog对象。
请参阅 CDialog::DoModal

CColorDialog::DoModal
virtual int DoModal( );
返回值
IDOK或者IDCANCEL。如果返回了IDCANCEL,则可以调用Windows函数CommDlgExtendedError来检测是否发生了错误。
说明
本函数用于显示Windows通用颜色对话框并接收用户的选择。如果想通过设置m_cc结构的各个成员来初始化不同的颜色对话框,应在对话框对象构造之后,调用DoModal之前进行。在调用DoModal之后,可以调用其它的成员函数检索设置信息和用户输入的信息。
请参阅 CDialog::DoModal, CColorDialog::CColorDialog

CColorDialog::GetColor
COLORREF GetColor( ) const;
返回值
返回一个COLORREF结构,其中包含了对话框中选中的颜色的RGB颜色值。
说明
本函数用于检索用户在对话框中选中的颜色。必须在DoModal之后调用。
请参阅 CColorDialog::SetCurrentColor

CColorDialog::GetSavedCustomColors
static COLORREF* GetSavedCustomColors( );
返回值
返回一个指向有16成员的RGB颜色数组的指针,数组中记录了用户定义的颜色。
说明
CColorDialog对象最多允许用户建立16种自定义颜色。成员函数GetSaved CustomColors提供了对这些颜色的存取。在DoModal调用返回IDOK后可以检索这些信息。返回的数组中的每个RGB值都被初始化为RGB(255,255,255)(白色)。用户选中的自定义颜色仅在同一应用中对话框的两次激活之间保存。如果想在应用运行后还保存这些颜色,就必须采用别的方法(例如放在一个.INI文件中)。
请参阅 CColorDialog::GetColor

CColorDialog::OnColorOK
virtual BOOL OnColorOK( );
返回值
如果不应撤消对话框,则返回非零值。否则为0以备以后接收选中的颜色。
说明
如果想提供对对话框中输入的颜色的有效性检查,可以覆盖此函数。可以用本函数拒绝用户在通用颜色对话框中输入的颜色。通常不需要使用此函数,因为框架已提供了对颜色的缺省的有效性检查。可以调用成员函数GetColor取得选中的颜色的RGB值。如果返回0,则仍然显示该对话框,等待用户输入文件名。

CColorDialog::SetCurrentColor
void SetCurrentColor( COLORREF clr);
参数
clr一个RGB颜色值。
说明
本函数在调用DoModal之后调用,把选中的颜色设置为clr指定的RGB值。一般在一个消息处理过程中或者OnColorOK中调用。对话框将自动地根据参数clr的值改变选中的颜色。
请参阅 CColorDialog::GetColor, CColorDialog::OnColorOK

数据成员
CColorDialog::m_cc
CHOOSECOLOR m_cc
说明
m_cc是一个CHOOSECOLOR类型的结构,它的成员记录了对话框的特性和值。在构造一个CColorDialog对象之后调用DoModal之前

2005-09-01

CCmdUI - [MFC]

CCmdUI没有基类。它仅在一个CCmdTarget派生类的ON_UPDATE_COMMAND_UI处理程序中使用。当用户在应用的下拉菜单时,要确定每个菜单项的显示状态——允许存取或禁止存取。菜单命令的目标通过实现一个ON_UPDATE_COMMAND_UI处理来提供这些信息。可以使用ClassWizard来浏览定位应用中的命令用户接口对象,然后为它建立一个消息映射入口,并为每个消息处理函数提供函数原型。当菜单被下拉时,框架搜索并调用每个ON_UPDATE_COMMAND_UI处理,每个处理调用Enable和Check之类的成员函数,相应地,框架就可以正确地显示每个菜单项了。菜单项可以用控件条按钮或者其它的命令用户接口对象替换,而在ON_UPDATE _COMMAND_UI处理中的代码不需要改动。下表列出了各种命令用户接口上的CCmdGUI的成员函数。
用户接口项 Enable SetCheck SetRadio SetText

菜单项 允许或禁止存取该项 选中(ⅹ)或未选中 选中(有黑点) 设置项的文本
工具条 按钮允许或禁止存取该项 选中未选中或不定 (不可用) 与SetChec相同

状态条状态提示 文本可见或不可见 设置凸出或正常边框 与SetCheck相同 设置状态条的提示文本
CdialogBar中的普通按钮 允许或禁止存取该项 复选框选中或未选中 与SetCheck相同 设置按钮的文本
CdialogBar中的普通按钮 允许或禁止存取该项 (不可用) (不可用) 设置窗口中的文本
有关使用类CCmdGUI的更详细信息,请参阅联机文档“Visual C++教程”中的“构造用户界面”部分和联机文档“Visual C++程序员指南”中的” 如何更新用户界面对象”部分。
include <afxwin.h>
请参阅 CcmdTarget

CCmdUI类的成员
数据成员
m_nID用户接口对象的
IDm_nIndex用户接口对象的下标
m_pMenu指向CCmdUI对象代表的菜单
m_pSubMenu指向CCmdUI对象代表的菜单的子菜单
m_pOther指向发送通知的窗口对象

操作
Enable允许或禁止本命令存取用户接口对象
SetCheck为本命令设置用户接口对象的选中状态
SetRadio与成员函数SetCheck类似,作用于单选钮组
SetText为本命令设置用户接口对象的文本
ContinueRouting通知命令路由机制继续沿处理链传送当前消息

成员函数
CCmdUI::ContinueRouting
void ContinueRouting( );
说明
本函数通知路由机制继续沿处理链传送当前消息。本函数应该和一个返回FALSE的ON_COMMAND_EX处理函数联合使用。有关更详细的信息,请参阅“技术指南21”。

CCmdUI::Enable
virtual void Enable( BOOL bOn = TRUE );
参数
bOn如果为TRUE,则把该项设置为允许存取;为FALSE,则设置为禁止存取。
说明
本函数用来设置一个命令是否可以存取用户接口项。
请参阅 CCmdUI::SetCheck

CCmdUI::SetCheck
virtula void SetCheck( int nCheck = 1 );
参数
nCheck指定要设置的选中状态。0表示设置为未选中状态,1表示选中,2表示不确定。
说明
本函数为命令设置用户接口项相应的选中状态。它对菜单项和工具条按钮起作用。不确定状态只适用于工具条按钮。
请参阅 CCmdUI::SetRadio

CCmdUI::SetRadio
virtual void SetRadio( BOOL bOn =TRUE );
参数
bOn如果为TRUE,则把项设置为允许存取;为FALSE,则设置为禁止存取。
说明
本函数用于为命令设置用户接口项的状态。作用类似于SetCheck,但对单选钮组中的成员起作用。不会自动清除组中其它项的选中状态,除非这些项自己维护了组的行为。
请参阅 CCmdUI::SetCheck

CCmdUI::SetText
virtual void SetText( LPCTSTR lpszText );
参数
lpszText指向字符串的指针。
说明
本函数为命令设置用户接口项中的文本。
请参阅 CCmdUI::Enable

数据成员
CCmdUI::m_nID
说明
m_nID是由CCmdUI对象代表的菜单项、工具条或者其它用户接口对象的ID。
CCmdUI::m_nIndex
说明
m_nIndex是由CCmdUI对象代表的菜单项、工具条或者其它用户接口对象的下标。
CCmdUI::m_pMenu
说明
m_pMenu指向由CCmdUI对象代表的菜单指针(类型为CMenu)。如果此项不是菜单,则设置为NULL。
请参阅 CMenu
CCmdUI::m_pSubMenu
说明
m_pSubMenu指向由CCmdUI对象代表的菜单的子菜单指针(类型为CMenu)。如果项不是菜单,则设置为NULL。如果子菜单是弹出式的,m_nID包含了弹出菜单中的第一项。要了解有关更详细的信息,请参阅“技术指南21”。.
请参阅 CMenu
CCmdUI::m_pOther
说明
m_pOther是一个指向工具条、状态条等发送通知的窗口对象的指针(CWnd类型)。如果项是菜单或不是CWnd对象,则为NULL。
请参阅 CWnd

2005-09-01

CCmdTarget - [MFC]

类CCmdTarget是MFC类库中消息映射体系的一个基类。消息映射把命令或消息引导给用户为之编写的响应函数(命令是由菜单项、命令按钮或者加速键产生的消息)。从CCmdTarget继承来的按键框架类包括:CView、CWinApp、CDocument、CWnd和CFrameWnd。如果想生成一个处理按键消息的类,可以选择其中的一个派生一个子类。很少需要直接从CCmdTarget派生类。相关的命令目标和OnCmdMsg例程的其它信息,请参阅联机文档“VisualC++程序员指南斨械摹懊

2005-09-01

CClientDC - [MFC]

类CClientDC派生于CDC,在构造时调用了Windows函数GetDC,在析构时调用了ReleaseDC。这意味着和CClientDC对象相关的设备上下文是窗口的客户区。要了解有关CClientDC的更详细的信息,请参阅联机文档“Visual C++程序员指南斨械摹吧璞干舷挛臄部分。#include <afxwin.h>
请参阅 CDC

CClientDC类的成员
构造函数
CClientDC构造一个连接到CWnd上的CClientDC对象

数据成员
m_hWnd CClientDC所在的有效窗口的HWND

成员函数
CClientDC::CClientDC
CClientDC(CWnd* pWnd );
throw( CResourceException );
参数
pWnd设备上下文将要存取的客户区所在的窗口。
说明
本函数构造一个CClientDC对象,它将存取pWnd指向的CWnd的客户区。此构造函数调用了Windows函数GetDC。如果Windows函数GetDC调用失败,则产生一个CResourceException类型的异常。如果Windows已经分配出了所有可用的设备上下文,则没有新的设备上下文可用。无论何时,应用总在竞争使用Windows提供的五个公共显示上下文。

数据成员
CClientDC::m_hWnd
说明
m_hWnd是一个保护的变量,是用来构造m_hWnd对象的CWnd指针的HWND。

2005-09-01

CCheckListBox - [MFC]

类CCheckListBox实现了Windows复选列表框。复选列表框显示项的一个列表,例如文件名列表。列表中的每项都有一个复选框。CCheckListBox只用于自定义的控件,列表中不仅仅包含字符串文本。当然简单的复选列表框可以只有字符串文本和相应的复选框。实际上也可以没有文本。例如可以是一个位图以及相应于复选框的列表。创建自己的复选列表框,要从类CCheckListBox派生一个子类。然后为它写一个构造函数,并调用成员函数Create。如果复选列表框是缺省形式的(由左边带有固定大小的复选框的字符串组成),就可以用缺省的CCheckListBox::DrawItem函数绘制复选列表框。否则就要覆盖函数CListBox::CompareItem、CCheckListBox::DrawItem以及CCheckListBox::Meas-ureItem。可以在对话框模板或程序代码中直接创建一个复选列表框。#include <afxwin.h>请参阅

CListBoxCCheckListBox类的成员
构造函数
CcheckListBox构造一个CCheckListBox对象
Create创建Windows复选列表框并应用到CCheckListBox对象上
属性函数
SetCheckStyle设置控件的复选框的风格
GetCheckStyle获取控件的复选框的风格
SetCheck设置某个项的复选框的状态
GetCheck取得某个项的复选框的状态Enable允许或禁止存取某个项
IsEnabled检测某个项是否允许存取
OnGetCheckPosition由框架调用,取得某个项的复选框的状态
可覆盖的函数
DrawItem当自定义的列表框的某个可视属性改变时由框架调用
MeasureItem当自定义的列表框的风格改变时由框架调用

成员函数
CCheckListBox:: CCheckListBoxCCheckListBox( );
说明
构造一个CCheckListBox对象。构造一个CCheckListBox需要两步:首先,定义一个从类CCheckListBox派生出来的子类,然后调用函数Create初始化Windows复选列表框并在CCheckListBox对象上应用它。例如:
class CMyCheckListBox : public CCheckListBox
{DECLARE_DYNAMIC(CMyCheckListBox)
//Constructors
public:CMyCheckListBox( );
BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
……..
请参阅 CCheckListBox::Create

CCheckListBox::Create
BOOL Create( DWORD dwStyle, CONST RECT& rect, CWnd*pParentWnd, UINT nID );
返回值
调用成功时返回非零值,否则为0。
参数
dwStyle指定复选列表框的风格。取值为LBS_OWNERDRAWFIXED(列表中的所有项的高度都相同)或LBS_OWNERDRAWVARIABLE(列表中项的高度各不相同)。这个风格参数可以和别的列表框风格组合使用。
rect指定复选列表框的大小和位置。可以是一个CRect对象或者一个RECT结构。
pParentWnd指定复选列表框所在的父窗口(通常是一个CDialog对象)。此值不能为NULL。
nID指定复选列表框的控制ID号。
说明
构造一个CCheckListBox对象需要两步:首先,定义一个从类CCheckListBox派生出来的子类,然后调用函数Create初始化Windows复选列表框并在CCheckListBox对象上应用它。参阅CCheckListBox::CCheckListBox的例子。在执行Create时,Windows向复选列表框控件发送如下消息:WM_NCCREATE、WM_CREATE、WM_NCCALCSIZE和WM_GETMINMAXINFO。缺省时,这些消息分别由基类CWnd的成员函数OnNcCreate、OnCreate、OnNcCalcSize和OnGetMinMaxInfo处理。要扩展缺省的消息处理功能,可以在派生出的类中加入一个消息映射并覆盖这些消息处理函数。例如,可以覆盖函数OnCreate进行一些初始化工作。复选列表框上可用的窗口风格有:
 WS_CHILD 总是设置
 WS_VISIBLE 通常要设置
 WS_DISABLED 很少使用
 WS_VSCROLL 增加一个垂直滚动条
 WS_HSCROLL 增加一个水平滚动条
 WS_GROUP 用来成组控件
 WS_TABSTOP 允许控件接收制表键焦点
请参阅 CCheckListBox::CCheckListBox

CCheckListBox::DrawItem
virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
参数
lpDrawItemStruct指向结构DRAWITEMSTRUCT的长指针,该结构中包含了绘制控件所需的信息。
说明
本函数在自定义的复选列表框的某个可视属性发生改变时,由框架调用。结构DRAWITEMSTRUCT中的成员itemAction和itemState指明了要进行的绘制动作。缺省时,此函数绘制一个缺省的复选列表框,它由字符串组成,每个字符串的左边都有一个缺省大小的复选框。复选列表框的大小在Create 时指定。覆盖此函数可以实现对非缺省状态的自定义复选列表框的绘制。例如列表中不是字符串、项的高度各不相同或是复选框不在左边等等。在此成员函数终止之前,应用必须重置所有为lpDrawItemStruct中的显示上下文所选中的GDI对象。
如果复选列表框中项的高度不完全一样,则它的风格(在调用Create时指定)必须为LBS_OWNERVARIABLE,函数MeasureItem也必须覆盖。
请参阅 CCheckListBox::Create, CCheckListBox::MeasureItem

CCheckListBox::Enable
void Enable( int nIndex, BOOL bEnabled = TRUE );
参数
nIndex允许的复选列表框项的下标。
bEnabled指定是否允许存取。
说明
本函数用于设置复选列表框