怎样把CListView中的CListCtrl换成自己的类 写了一个自己的CMyListCtrl,现在使用CListView,但是CListView::GetListCtrl返回的是CListCtrl的对象,请问怎样能够替换CListView中的CListCtrl对象为自己的CMyListCtrl?有这个可能吗? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 安全的方法是复制代码到你的CListView派生类,或者使用模板来共享代码。CListView中并不包含一个CListCtrl。4 为什么一个类的指针可以强制转化为另外一个类的指针,即使它们之间没有派生关系?答:只要你访问的数据的内存表示是完全相同的,那么这种转化就是安全的。考虑MFC从CWnd到CEdit的派生过程,是一个纯粹的封装——既没有增加数据成员也没有增加虚函数(虚函数表的指针实际上是类的第一个成员,你可以在VC的监视窗口看到)——所有的代码只是在操作基类的成员。所以你可以在对话框的成员函数中安全地进行如下调用CEdit* pEdit=GetDlgItem (IDC_EDIT);也就是说,你可以安全地把CWnd指针转化为CEdit指针。在CWnd的窗口类为EDIT的情况下,你可以安全地用这个CEdit指针来访问CEdit具有的而CWnd不具有的特性。由于CEditView的窗口类也是EDIT,同时是从CWnd派生下来的,所以你也可以把CEditView指针转化成CEdit指针。MFC的CCtrlView的派生类都可以做这样的转化。在这样做之前,你需要查看类的定义头文件以确保类型安全。CEdit, CListCtrl, CTreeCtrl,CToolBarCtrl都是这样的封装,但是CToolTipCtrl是一个例外。除了对TTM_ADDTOOL消息的处理可能不一致之外。LRESULT CToolTipCtrl::OnAddTool(WPARAM wParam, LPARAM lParam){ TOOLINFO ti = *(LPTOOLINFO)lParam; if ((ti.hinst == NULL) && (ti.lpszText != LPSTR_TEXTCALLBACK) && (ti.lpszText != NULL)) { void* pv; if (!m_mapString.Lookup(ti.lpszText, pv)) m_mapString.SetAt(ti.lpszText, NULL); // set lpszText to point to the permanent memory associated // with the CString VERIFY(m_mapString.LookupKey(ti.lpszText, ti.lpszText)); } return DefWindowProc(TTM_ADDTOOL, wParam, (LPARAM)&ti);}这里访问了CToolTipCtrl的数据成员,这样的话下面的代码就似乎未必安全_AFXCMN_INLINE CToolTipCtrl* CTreeCtrl::GetToolTips() const { ASSERT(::IsWindow(m_hWnd)); return (CToolTipCtrl*)CWnd::FromHandle((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L)); }不过CTreeCtrl::GetToolTips()返回的只是有效的CWnd,TVM_ADDTOOL消息也是被默认窗口过程而不是CToolTipCtrl的代码来处理, 所以上面的用法还是安全的。顺便说一下,尽管大部分这样的封装是用SendMessage实现的,但是Redmond的家伙似乎很热衷于用DefWindowProc替代SendMessage来节省CPU的时钟周期。这样的一个副作用是MFC不会有处理这样的消息的机会,例如PretranslateMessage和Subclass都会失效了。这样的一个副作用是protected修饰符不再是类成员的保护伞。考虑如下情况Class A{ protected: int m_iProtected;};如果我想获得m_iProtected的public访问权,我可以写一个封装类Class B:public A{public:int & GetProtected(){return m_iProtected;}friend class C;};然后把A类型的指针强制转化成B类型的就可以以public方式访问声明为m_iProtected的成员了。在C类中访问B的成员也不受限制。尽管多继承是C++的一个特性,从理想情况来说,CEditView应该从CCtrlView和CEdit派生出来,但是所有的人都知道多继承是多么的麻烦。对于MFC的CObject派生类,默认的情况是不允许的——尽管你可以通过的MFC技术文档TN016: Using C++ Multiple Inheritance with MFC中提供的方法手动添加多继承支持。实际上,这些特性应该以接口的形式提供——把GetEditCtrl转换成QueryInterface,但是性能上又会损失很多,而且Windows通用控件和MFC对它的封装总是在不断地升级,所以MFC使用了如上的Hack方法来提供和多继承类似的功能。 这里有一篇文章:http://www.codeguru.com/Cpp/controls/listview/introduction/article.php/c901/不过我认为更好一点的方式是在view上画一个控件。1,视图从CView继承。2,在视图内动态创建CMyListCtrl.3, 将CMyListCtrl全视图显示。3,处理基本的界面缩放消息,CMyListCtrl中保存CView指针,通过它处理doc/view的串行动作。4,视图撤销时destroy listctrl. 同意jiangsheng。CListView派生自CCtrlView,CListView的构造函数显式调用CCtrlView的构造函数,CCtrlView的构造函数有两个参数,分别表示窗口类的类名和窗口风格。CListView传递给它的是预定义的窗口类WC_LISTVIEW,所以整个CListView其实就是一个win32 common ctrl ListView而已。 简单一点的:加一个Dialog,边框什么的不要,放一个ListCtrl进去,再将Dialog生成一个FormView的类。响应WM_SIZE消息,将ListCtrl的大小和FormView的大小一样。再把ListCtrl生成一个变量,关连到你的那个listctrl类就可以了。 呵呵,简单点,按照baberson说得就够了。 请问一下enoloo:你说的1,视图从CView继承。2,在视图内动态创建CMyListCtrl.3, 将CMyListCtrl全视图显示。3,处理基本的界面缩放消息,CMyListCtrl中保存CView指针,通过它处理doc/view的串行动作。怎么实现阿 CMyListCtrl m_listctrl; //类中//实现: CRect rect; GetClientRect(&rect); CRect rectctl(rect); rect.right = rect.right/2; rect.bottom = rect.bottom/2; m_listctrl.Create(WS_VISIBLE |WS_CHILD |LVS_REPORT |LVS_OWNERDRAWFIXED, rectctrl,this,IDC_LIST1); int i; m_listctrl.GetClientRect(&rect); m_listctrl.InsertColumn(0,"abc"); m_listctrl.SetColumnWidth(0,rect.Width()/2); m_listctrl.InsertColumn(1,"ABC"); m_listctrl.SetColumnWidth(1,rect.Width()/2); listview是能接受所有发送到他本身的消息。但是,如果listview重绘,那么消息是发送到父窗口的,他自己怎么处理? 我猜楼主的意思可能是以对象的概念来处理消息。比如mfc的消息反射。重载DrawItem函数等等。 如何分割这个字符串 MFC登录界面 在mfc的单文档 里如何 添加 响应右键 点击 消息? 求《Visual C++项目开发实践》一书光盘源码 ListCtrl 和 ListCtrl 及 ListBox 列表间如何实现拖拽操作?????? Help Me,50 score 想问关于MIDI文件的结构(资料)及其生成原码 如何取得Param中的值 怎样使用树型的控件?初学者急用!高分! 大家来讨论一下吧。 CStatic类的控件 调用SetBitmap后需要自己释放返回的句柄吗 请问:
CListView中并不包含一个CListCtrl。4 为什么一个类的指针可以强制转化为另外一个类的指针,即使它们之间没有派生关系?
答:只要你访问的数据的内存表示是完全相同的,那么这种转化就是安全的。考虑MFC从CWnd到CEdit的派生过程,是一个纯粹的封装——既没有增加数据成员也没有增加虚函数(虚函数表的指针实际上是类的第一个成员,你可以在VC的监视窗口看到)——所有的代码只是在操作基类的成员。所以你可以在对话框的成员函数中安全地进行如下调用
CEdit* pEdit=GetDlgItem (IDC_EDIT);
也就是说,你可以安全地把CWnd指针转化为CEdit指针。在CWnd的窗口类为EDIT的情况下,你可以安全地用这个CEdit指针来访问CEdit具有的而CWnd不具有的特性。由于CEditView的窗口类也是EDIT,同时是从CWnd派生下来的,所以你也可以把CEditView指针转化成CEdit指针。MFC的CCtrlView的派生类都可以做这样的转化。在这样做之前,你需要查看类的定义头文件以确保类型安全。CEdit, CListCtrl, CTreeCtrl,CToolBarCtrl都是这样的封装,但是CToolTipCtrl是一个例外。除了对TTM_ADDTOOL消息的处理可能不一致之外。
LRESULT CToolTipCtrl::OnAddTool(WPARAM wParam, LPARAM lParam)
{
TOOLINFO ti = *(LPTOOLINFO)lParam;
if ((ti.hinst == NULL) && (ti.lpszText != LPSTR_TEXTCALLBACK)
&& (ti.lpszText != NULL))
{
void* pv;
if (!m_mapString.Lookup(ti.lpszText, pv))
m_mapString.SetAt(ti.lpszText, NULL);
// set lpszText to point to the permanent memory associated
// with the CString
VERIFY(m_mapString.LookupKey(ti.lpszText, ti.lpszText));
}
return DefWindowProc(TTM_ADDTOOL, wParam, (LPARAM)&ti);
}
这里访问了CToolTipCtrl的数据成员,这样的话下面的代码就似乎未必安全
_AFXCMN_INLINE CToolTipCtrl* CTreeCtrl::GetToolTips() const
{ ASSERT(::IsWindow(m_hWnd)); return (CToolTipCtrl*)CWnd::FromHandle((HWND)::SendMessage(m_hWnd, TVM_GETTOOLTIPS, 0, 0L)); }不过CTreeCtrl::GetToolTips()返回的只是有效的CWnd,TVM_ADDTOOL消息也是被默认窗口过程而不是CToolTipCtrl的代码来处理, 所以上面的用法还是安全的。
顺便说一下,尽管大部分这样的封装是用SendMessage实现的,但是Redmond的家伙似乎很热衷于用DefWindowProc替代SendMessage来节省CPU的时钟周期。这样的一个副作用是MFC不会有处理这样的消息的机会,例如PretranslateMessage和Subclass都会失效了。这样的一个副作用是protected修饰符不再是类成员的保护伞。考虑如下情况
Class A
{
protected: int m_iProtected;
};
如果我想获得m_iProtected的public访问权,我可以写一个封装类
Class B:public A
{
public:int & GetProtected(){return m_iProtected;}
friend class C;
};
然后把A类型的指针强制转化成B类型的就可以以public方式访问声明为m_iProtected的成员了。在C类中访问B的成员也不受限制。尽管多继承是C++的一个特性,从理想情况来说,CEditView应该从CCtrlView和CEdit派生出来,但是所有的人都知道多继承是多么的麻烦。对于MFC的CObject派生类,默认的情况是不允许的——尽管你可以通过的MFC技术文档TN016: Using C++ Multiple Inheritance with MFC中提供的方法手动添加多继承支持。实际上,这些特性应该以接口的形式提供——把GetEditCtrl转换成QueryInterface,但是性能上又会损失很多,而且Windows通用控件和MFC对它的封装总是在不断地升级,所以MFC使用了如上的Hack方法来提供和多继承类似的功能。
http://www.codeguru.com/Cpp/controls/listview/introduction/article.php/c901/
不过我认为更好一点的方式是在view上画一个控件。
1,视图从CView继承。
2,在视图内动态创建CMyListCtrl.
3, 将CMyListCtrl全视图显示。
3,处理基本的界面缩放消息,CMyListCtrl中保存CView指针,通过它处理doc/view的串行动作。
4,视图撤销时destroy listctrl.
CListView派生自CCtrlView,CListView的构造函数显式调用CCtrlView的构造函数,CCtrlView的构造函数有两个参数,分别表示窗口类的类名和窗口风格。CListView传递给它的是预定义的窗口类WC_LISTVIEW,所以整个CListView其实就是一个win32 common ctrl ListView而已。
加一个Dialog,边框什么的不要,放一个ListCtrl进去,再将Dialog生成一个FormView的类。
响应WM_SIZE消息,将ListCtrl的大小和FormView的大小一样。再把ListCtrl生成一个变量,关连到你的那个listctrl类就可以了。
你说的1,视图从CView继承。
2,在视图内动态创建CMyListCtrl.
3, 将CMyListCtrl全视图显示。
3,处理基本的界面缩放消息,CMyListCtrl中保存CView指针,通过它处理doc/view的串行动作。怎么实现阿
CRect rect;
GetClientRect(&rect);
CRect rectctl(rect);
rect.right = rect.right/2;
rect.bottom = rect.bottom/2; m_listctrl.Create(WS_VISIBLE |WS_CHILD |LVS_REPORT |LVS_OWNERDRAWFIXED, rectctrl,this,IDC_LIST1);
int i;
m_listctrl.GetClientRect(&rect);
m_listctrl.InsertColumn(0,"abc");
m_listctrl.SetColumnWidth(0,rect.Width()/2);
m_listctrl.InsertColumn(1,"ABC");
m_listctrl.SetColumnWidth(1,rect.Width()/2);
listview是能接受所有发送到他本身的消息。但是,如果listview重绘,那么消息是发送到父窗口的,他自己怎么处理? 我猜楼主的意思可能是以对象的概念来处理消息。比如mfc的消息反射。重载DrawItem函数等等。