如题,我在自绘控件添加消息映射时,不知道怎么得到视图包含控件的资源id,一般的消息映射如下:ON_NOTIFY(NM_CUSTOMDRAW, IDC_LIST1, OnCustomdrawList),但是我怎么轻松得到视图包含控件的资源id呢(第二个参数IDC_LIST1)?真麻烦啊,菜鸟请教。

解决方案 »

  1.   

    应用程序是单文档工程,向导第六步基类选择下拉框选择:CListView,这样通过在视图继承类中使用CListCtrl& pListCtrl = GetListCtrl();使用视图包含的控件,不用另外添加头文件和变量了
      

  2.   

    这个如果你的控件是使用CWnd::Create动态创建的,手动添加的话,需要在Resource.h中定义控件ID的值,然后再用。你的控件已经创建了,难道这个ID你还找不到吗?
      

  3.   

    你可能还没看明白吧,我使用继承CListView的视图类,在其中封装了CListCtrl控件,我只需要用GetListCtrl()就可使用ListCtrl控件了,其它的什么都不用做
      

  4.   

    一般的对话框应用程序,将列表控件拖到主界面上,就在Resource.h中生成#define IDC_LIST1             1000这一项,现在我没有这么做,Resource.h也没有这一项。
      

  5.   

    CListView和它内部的CListCtrl不是父子关系,你只要处理反射消息就可以了:ON_NOTIFY_REFLECT
      

  6.   

    谢谢,我在弄界面过程中问题多多,就是在没有焦点的情况下如何使CListView中一行高亮选中,具体如下:SDI切分窗口多视图,我在CTreeView视图中响应TVN_SELCHANGED,在响应事件中使CListView中一行选中并高亮显示(),但是我怎么没弄成功,你可以帮我解决一下吗?我很菜,能帮帮我么。
    下面我贴出相关代码:在CTreeView中:
    void CITreeView::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
    // TODO: Add your control notification handler code here
    HTREEITEM hItem = pNMTreeView->itemNew.hItem;
    CString hSelect = GetTreeCtrl().GetItemText(hItem);
    HTREEITEM hItem1 = pNMTreeView->itemOld.hItem;
    CString hParent = GetTreeCtrl().GetItemText(hItem1); if (GetDocument()->pListView->GetSafeHwnd())
    {
    ::SendMessage(GetDocument()->pListView->GetSafeHwnd(),WM_UPDATESELECT,(WPARAM)&hParent,(LPARAM)&hSelect);
    }
    // GetDocument()->pListView->SetFocus();
    *pResult = 0;
    }在CListView中:
    映射关系:ON_MESSAGE(WM_UPDATESELECT,OnUpdateSelect)
    LRESULT CIListView::OnUpdateSelect(WPARAM wParam, LPARAM lParam)
    {
    CString m_strParent = *(CString *)wParam;
    CString m_strSelect = *(CString *)lParam;
    for (int iitem = 0;iitem < GetListCtrl().GetItemCount();iitem ++)
    {
    if(GetListCtrl().GetItemText(iitem,0) == m_strParent&&GetListCtrl().GetItemText(iitem,1) == m_strSelect)
    { GetListCtrl().SetItemState(iitem,LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
    GetListCtrl().EnsureVisible(iitem, true);
    GetListCtrl().SetFocus();
    break;
      }
    }
    //  GetDocument()->UpdateAllViews(this);
      GetListCtrl().Invalidate(); 
        return 0; 
    }
      

  7.   

    切分视图之类,只要有文档框架的,都可以通过文档实现各视图之间的通讯和同步,关键的函数是CDocument::UpdateAllViews()和CView::OnUpdate(),而不用发消息。
      

  8.   

    你看看代码可以吗?我的界面需求很特别:需要点击CTreeView中叶节点的时候,CListView中与叶节点字符相同的一行选中并高亮,我弄这个拖了很长时间,谢谢啦!
      

  9.   

    照你的做法,不清楚消息是否正确发送了。先调试确认。设置选中标记之后不要调用Invalidate,控件自动会刷新的。
      

  10.   

    第一次点击的叶节点始终会选中,在同一父节点下的其他叶节点在这之后点击却不会选中,用AfxMessageBox测试消息(节点字符信息)发送成功, 离我想要的界面效果还差很多啊。HELP!
      

  11.   

    下面我的代码,是用向导建立的资源管理器类型SDI界面,也就是左面一个CTreeView继承类CSplitterTestLeftView视图,右面一个CListCtrl继承类CSplitterTestView视图,填充的内容左面和右面一样,都是当前目录下的文件夹和文件列表的名称,并且把完成路径放在ItemData中(以BSTR的形式)。
    给出修改过的代码,相应消息响应都是用向导建立的。其中树控件的OnTvnGetdispinfo/OnTvnItemexpanding/OnTvnItemexpanded三个消息的处理是配合tvi.cChildren = I_CHILDRENCALLBACK实现的一种优化效率和内存使用的方法,即插入时不需要插入所有的子节点,等到父节点展开的时候才插入;一旦节点收缩,就删除所有的子节点,实际运用中还要考虑一些层次关系,和判断子节点的数量以确定OnTvnGetdispinfo中的pTVDispInfo->item.cChildren值为1还是0。
    这个例子的目的:
    1 树控件节点的优化插入
    2 ItemData的使用
    3 分割窗口中通过CDocument::UpdateAllViews()进行视图间的通讯点击左面的树控件的项目,右面列表控件相应的项目选中,经试验无误。// SplitterTestLeftView.cpp : CSplitterTestLeftView 类的实现
    //void CSplitterTestLeftView::OnInitialUpdate()
    {
    CTreeView::OnInitialUpdate(); // TODO: 调用 GetTreeCtrl() 直接访问 TreeView 的树控件,
    // 从而可以用项填充 TreeView。
    CTreeCtrl &cTree = GetTreeCtrl();
    cTree.ModifyStyle(0, TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT ); HTREEITEM hParent = TVI_ROOT;

    CFileFind fd;
    BOOL bFind = fd.FindFile(_T("*.*"));
    do
    {
    bFind = fd.FindNextFile();
    if (!fd.IsDots())
    {
    HTREEITEM hItem = cTree.InsertItem(fd.GetFileName(), hParent);
    TVITEM tvi = {0};
    tvi.mask = TVIF_CHILDREN | TVIF_PARAM;
    tvi.hItem = hItem;
    if (fd.IsDirectory())
    {
    tvi.cChildren = I_CHILDRENCALLBACK;
    }
    tvi.lParam = (LPARAM)fd.GetFilePath().AllocSysString();
    cTree.SetItem(&tvi);
    }
    }while (bFind);
    }void CSplitterTestLeftView::OnTvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    if (pTVDispInfo->item.mask & TVIF_CHILDREN)
    {
    pTVDispInfo->item.cChildren = 1;
    }
    *pResult = 0;
    }void CSplitterTestLeftView::OnTvnItemexpanding(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    if (pNMTreeView->action == TVE_EXPAND)
    {
    CTreeCtrl &cTree = GetTreeCtrl();
    CString strPath((BSTR)pNMTreeView->itemNew.lParam);
    strPath += _T("\\*.*");
    CFileFind fd;
    BOOL bFind = fd.FindFile(strPath);
    int nCount = 0;
    do
    {
    bFind = fd.FindNextFile();
    if (!fd.IsDots())
    {
    HTREEITEM hItem = cTree.InsertItem(fd.GetFileName(), pNMTreeView->itemNew.hItem);
    TVITEM tvi = {0};
    tvi.mask = TVIF_CHILDREN | TVIF_PARAM;
    tvi.hItem = hItem;
    if (fd.IsDirectory())
    {
    tvi.cChildren = I_CHILDRENCALLBACK;
    }
    tvi.lParam = (LPARAM)fd.GetFilePath().AllocSysString();
    cTree.SetItem(&tvi);
    nCount++;
    }
    }while (bFind);
    } *pResult = 0;
    }void CSplitterTestLeftView::OnTvnItemexpanded(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    if (pNMTreeView->action == TVE_COLLAPSE)
    GetTreeCtrl().Expand(pNMTreeView->itemNew.hItem, TVE_COLLAPSE | TVE_COLLAPSERESET); *pResult = 0;
    }void CSplitterTestLeftView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    GetDocument()->UpdateAllViews(this, pNMTreeView->itemNew.lParam, NULL); *pResult = 0;
    }// SplitterTestView.cpp : CSplitterTestView 类的实现
    //void CSplitterTestView::OnInitialUpdate()
    {
    CListView::OnInitialUpdate(); // TODO: 调用 GetListCtrl() 直接访问 ListView 的列表控件,
    // 从而可以用项填充 ListView。
    CListCtrl& cList = GetListCtrl();
    cList.ModifyStyle(LVS_TYPEMASK, LVS_REPORT | LVS_SHOWSELALWAYS);
    cList.SetExtendedStyle(LVS_EX_FULLROWSELECT); cList.InsertColumn(0, _T("文件名称"), 0, 300);
    cList.InsertColumn(1, _T("大小"), LVCFMT_RIGHT, 100);
    cList.InsertColumn(2, _T("创建时间"), 0, 200); CFileFind fd;
    BOOL bFind = fd.FindFile(_T("*.*"));

    int nIndex = 0;
    do
    {
    bFind = fd.FindNextFile();
    if (!fd.IsDots())
    {
    nIndex = cList.InsertItem(cList.GetItemCount(), fd.GetFileName());
    cList.SetItemData(nIndex, (LPARAM)fd.GetFilePath().AllocSysString());
    WIN32_FILE_ATTRIBUTE_DATA fa = {0};
    if (GetFileAttributesEx(fd.GetFilePath(), GetFileExInfoStandard, &fa))
    {
    CString strItemText;
    strItemText.Format(_T("%d Bytes"), fa.nFileSizeLow);
    cList.SetItemText(nIndex, 1, strItemText);
    SYSTEMTIME st;
    FileTimeToSystemTime(&fa.ftCreationTime, &st);
    strItemText.Format(_T("%d/%02d/%02d %02d:%02d:%02d.%03d"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    cList.SetItemText(nIndex, 2, strItemText);
    }
    }
    }while (bFind);
    }void CSplitterTestView::OnUpdate(CView* pSender, LPARAM lHint, CObject* /*pHint*/)
    {
    // TODO: 在此添加专用代码和/或调用基类
    if (pSender == this || lHint == 0)
    return; CListCtrl& cList = GetListCtrl();
    cList.SetItemState(-1, 0, LVIS_SELECTED | LVIS_FOCUSED); CString strFind((BSTR)lHint); for (int i = 0; i < cList.GetItemCount(); i++)
    {
    CString str((BSTR)cList.GetItemData(i));
    if (str == strFind)
    {
    cList.SetItemState(i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
    break;
    }
    }
    }