\t\tCDialogBar的创建和使用 (转载自百度文库)

一个朋友让我看一个关于DialogBar的程序,问题是在一个DialogBar中添加一个Tree Control控件,在初始化函数OnInitDialog中使用InsertItem添加一项,结果运行后,始终在DialogBar中显示不出来,后来我又加入了一个Button测试,结果Button是灰色的,根本不能点击。在OnInitDialog中加入断点,程序根本执行不到这个函数。按理说,界面已经显示出来了,早应该调用OnInitDialog函数了。当时百思不得其解。

后来在网上查了一下,才知道CDialogBar根本没有重载OnInitDialog这个函数(你查一下MSDN,就知道CDialog是重载了这个函数的),所以导致我虽然有这个函数,但是始终不调用。这就需要我手动添加这个消息映射。我通过ON_MESSAGE宏,映射了这个消息响应函数,运行结果没问题,Tree Control中有我添加的项了。

剩下的就是Button不能用的问题了。通过网上和自己试验,知道在DialogBar中,Button发出的消息根本就不通过DialogBar,而是直接发到MainFrame中,所以只要在MainFrame中进行响应或者把消息再转发到DialogBar中就可以了。我在CMainFrame类中重载了OnCmdMsg这个函数,在这个函数中,先用DialogBar去拦截消息,这样,只需要在DialogBar中取相应Button的消息就可以了。

下面是我做试验的大致过程:

1 创建一个单文档的MFC工程,名为MyDialogBar

2 要使用DialogBar,当然首先要在ResourceView中添加一个DialogBar了。添加好了DialogBarID采用默认的IDD_DIALOGBAR,至于它的properties,就采用默认的好了。

3 添加一个Tree ControlIDIDC_TREE,在它的properties对话框Styles选项卡中选择Has buttonsHas linesLines at root三个选项,看起来就比较正常了。

4 然后为这个DialogBar添加一个类,类名为CDlgBar,继承自CDialog,因为在向导中没有CDialogBar这个基类。然后把它的WM_INITDIALOG消息响应函数加上,记住这时我们的DialogBar还是一个CDialog的子类呢。然后给Tree Control映射变量m_tree

5 下面就轮到对我们自己的DialogBar动手脚了。

1)首先中把CDlgBar的基类改成CDialogBar,然后在.cpp文件中,把CDialogBar的构造函数的对CDialog的构造函数去掉,即:

CDlgBar::CDlgBar(CWnd* pParent/*=NULL*/):CDialog(CDlgBar::IDD, pParent)修改为

CDlgBar::CDlgBar(CWnd* pParent /*=NULL*/)

2)然后把DoDataExchange函数中的CDialog::DoDataExchange(pDX);一句改成CDialogBar::DoDataExchange(pDX);

3)把BEGIN_MESSAGE_MAP(CDlgBar,CDialog)中的CDialog改成CDialogBar

4)把OnInitDialog函数中的CDialog::OnInitDialog();一句去掉。

6 OnInitDialog中添加向TreeControl中插入数据的语句:

BOOLCDlgBar::OnInitDialog() 

{

    HTREEITEM hParent =m_tree.InsertItem("parent");

    m_tree.InsertItem("boy",hParent);

    m_tree.InsertItem("girl",hParent);

    return TRUE; // return TRUE unless you setthe focus to a control

                           // EXCEPTION: OCX Property Pages should returnFALSE

}

7 CMainFrame中添加一个变量:CDlgBar m_wndDlgBar;,当然不能忘了include进头文件DlgBar.h。然后在它的OnCreate函数中创建DialogBar。添加如下语句:

if(!m_wnd             DlgBar.Create(this, IDD_DIALOGBAR, WS_CHILD |WS_VISIBLE |

                              CBRS_LEFT | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | 

                              CBRS_SIZE_DYNAMIC, IDD_DIALOGBAR))

{

       TRACE0("Failed to create dialogbar\n");

      return -1;      // fail to create

}

m_wndDlgBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndDlgBar);

这是你可以运行一下,就会看到DialogBar虽然已经加入了,但是里面的tree control中什么都没有。在CDlgBarOnInitDialog函数中设置断点,调试,也进入不到这个函数中。

8 这时,你可以在CDlgBar中为WM_INITDIALOG消息映射我们的OnInitDialog函数。这样,当WM_INITDIALOG消息发送到CDlgBar中就可以响应了。

BEGIN_MESSAGE_MAP(CDlgBar,CDialogBar)

            //{{AFX_MSG_MAP(CDlgBar)

           ON_MESSAGE(WM_INITDIALOG, OnInitDialog)

           //}}AFX_MSG_MAP

END_MESSAGE_MAP()

      这时,你运行一下,就会看到一个断言错误。

OnInitDialog函数中一开始添加UpdateData(FALSE);,这时你再运行,就会看到我们的tree control中有东西了。

那么这个UpdateData(FALSE);到底干了什么呢?MSDN上说当参数为FALSE时,会调用DoDataExchange函数,对控件进行初始化,当参数为TRUE时,从控件中获取值。

9 ResourceViewDialogBar中添加一个按钮,IDIDC_BTN_TEST,并添加单击响应函数OnBtnTest。里面使用MessageBox(“OK”)来表示响应单击消息。

运行一下,可以看到,按钮是灰色的。

10 原因是Button的消息发送到了MainFrame,到底有些什么消息,我还不是很清楚。这个问题的解决方法就是在CMainFrame中重载一个函数OnCmdMsg,并在这里面拦截消息发送到我们的CDlgBar中。

BOOLCMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, 

          AFX_CMDHANDLERINFO* pHandlerInfo) 

{

    if(m_wndDlgBar.OnCmdMsg(nID, nCode, pExtra,pHandlerInfo))

    {

           return TRUE;

    }

    return CFrameWnd::OnCmdMsg(nID, nCode,pExtra, pHandlerInfo);

}

运行一下我们的程序,就可以看到没有问题了。

11顺便添加一个tree control的选择消息TVN_SELCHANGED响应函数。在向导里面,选择IDC_TREE,添加它的TVN_SELCHANGED响应函数OnSelchangedTree。如下代码:

voidCDlgBar::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult) 

{

           NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

           HTREEITEM hSelItem = pNMTreeView->itemNew.hItem;// 选择的项

            CStringstrSelText = m_tree.GetItemText(hSelItem);

           MessageBox(strSelText);

            *pResult = 0;

}

 

 

 

 

 

 

图标创建 

CImagelist*m_imagelist;
m_imagelist=newCImageList();
m_imagelist->Create(16,16,TRUE,2,2);

// BOOLCreate(intcx,intcy,UINTnFlags,intnInitial,intnGrow);

nInitial 创建的图标个数

nGrow 一般等于nIntial

     HICON hIcon;

     HTREEITEM htem;

     TV_INSERTSTRUCT Instru;

     hIcon=AfxGetApp()->LoadIcon(IDI_ICON2);

     m_imagelist->Add(hIcon);

     hIcon=AfxGetApp()->LoadIcon(IDI_ICON1);

     m_imagelist->Add(hIcon);

     m_treeList.ShowWindow(SW_HIDE);

     m_treeList.SetImageList(m_imagelist,TVSIL_NORMAL);

      htem=m_treeList.InsertItem("北京太格服务器",0,0);

     m_treeList.InsertItem("北京太格通道一",1,1,htem);//参数2.图标索引.参数3.TreeList项目被选中是显示的图标索引,参数4.父节点

     m_treeList.InsertItem("北京太格通道二",1,1,htem);

// HTREEITEMInsertItem(LPTVINSERTSTRUCTlpInsertStruct);

//HTREEITEM InsertItem(LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST );

//HTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage,HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter= TVI_LAST);

// HTREEITEMInsertItem(LPTVINSERTSTRUCTlpInsertStruct);

     Instru.hParent=NULL;

     Instru.item.iImage=0;

     Instru.item.iSelectedImage=0;

     Instru.item.mask=TVIF_CHILDREN|TVIF_IMAGE|TVIF_TEXT;

     Instru.item.pszText="测试服务器";

     m_treeList.InsertItem(&Instru);

     m_treeList.SetBkColor(RGB(193,255,255));

     m_treeList.SetTextColor(RGB(255,0,0));

 

 

主要用到的类有:CListCtrl,CTreeCtrl,CImageList,CFileFind 和函数SHGetFileInfo()
简述步骤如下:
1、增加 TreeCtrl 的TVS_HASBUTTONS,TVS_HASLINES、TVS_LINESATROOT Style,代码如下:
   DWORD dwStyle =GetWindowLong(m_tree.m_hWnd,GWL_STYLE);
   dwStyle |= TVS_HASBUTTONS | TVS_HASLINES |TVS_LINESATROOT;
   SetWindowLong(m_tree.m_hWnd,GWL_STYLE,dwStyle);
2、为TreeCtrl添加Root项:
   m_hRoot = m_tree.InsertItem("我的电脑");
   InsertItem()的函数原形为
   HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEMhParent = TVI_ROOT,
   HTREEITEM hInsertAfter = TVI_LAST );

3、获取本地逻辑驱动器,并添加:

void CTreeViewDlg::GetLogicalDrives(HTREEITEM hParent)
   {
   size_t szAllDriveStrings =GetLogicalDriveStrings(0,NULL);
  char *pDriveStrings = new char[szAllDriveStrings +sizeof(_T(""))];
  GetLogicalDriveStrings(szAllDriveStrings,pDriveStrings);
  size_t szDriveString = strlen(pDriveStrings);
  while(szDriveString 0)
  {
  m_tree.InsertItem(pDriveStrings,hParent);
  pDriveStrings += szDriveString + 1;
  szDriveString = strlen(pDriveStrings);
  }
   }

4、添加TVN_EXPANDED消息处理函数,当一项展开时,为其子项添加下一级目录:

 voidCTreeViewDlg::OnItemexpandedTree(NMHDR* pNMHDR, LRESULT* pResult)
   {
  NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  // TODO: Add your control notification handler codehere
  TVITEM item = pNMTreeView-itemNew;
  if(item.hItem == m_hRoot)
  return;
   HTREEITEM hChild = m_tree.GetChildItem(item.hItem);
  while(hChild)
  {
  AddSubDir(hChild);
  hChild = m_tree.GetNextItem(hChild,TVGN_NEXT);
  }
  *pResult = 0;
   }
AddSubDir函数功能添加子项,具体代码见示例。

5、添加TVN_SELCHANGED消息处理函数,在这个函数里,用GetFullPath()取得选中项的绝对路径(GetFullPath()具体代码看示例),在ListCtrl中添加文件而非文件夹的图标:

 voidCTreeViewDlg::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
   {
  m_list.DeleteAllItems();
  NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  TVITEM item = pNMTreeView-itemNew;
  if(item.hItem == m_hRoot)
  return;
  CString str = GetFullPath(item.hItem);
   if(str.Right(1) != "\\")
   str += "\\";
  str += "*.*";
  CFileFind file;
  BOOL bContinue = file.FindFile(str);
  while(bContinue)
  {
  bContinue = file.FindNextFile();
  if(!file.IsDirectory() && !file.IsDots())
  {
   SHFILEINFO info;
  CString temp = str;
  int index = temp.Find("*.*");
  temp.Delete(index,3);
   SHGetFileInfo(temp + file.GetFileName(),
   0,
   &info,sizeof(&info),
   SHGFI_DISPLAYNAME | SHGFI_ICON);
   int i = m_ImageList.Add(info.hIcon);
   m_list.InsertItem(i,info.szDisplayName,i);
  }
  }
  *pResult = 0;
   }
   这只是一个简单的例子,你可以在 ListCtrl 中添加鼠标双击消息的处理函数,用 Process 打开该选中的文件;  该示例在VC6,xp下编译通过。


原文地址:http://wenku.baidu.com/view/8848d40a79563c1ec5da71f6.html

 

  CDialogBar的创建和使用 (转载自百度文库) - 大灰狼 - 大灰狼 的博客?

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值