没有对应Document的CFormView为何创建后没有调用OnInitialUpdate,而且无法使用CListCtrl?

zhangtianhong 2005-05-09 09:54:36
我自己从CMDIChildWnd继承了一个新窗口类CfrmExamType,同时从CFormView继承了一个CfvExamType.
在CfrmExamType中定义了一个CfvExamType的指针,并且在它的OnCreate中创建了这个CfvExamType的FormView. 接下来我在FormView的资源中,加入了一个CListCtrl,然后在CfvExamType(FormView)的OnInitialUpdate中写入如下代码:
m_lcExamType.InsertColumn(0,"编号",LVCFMT_RIGHT,40);
m_lcExamType.InsertColumn(1,"考试类型",LVCFMT_CENTER,100);
m_lcExamType.InsertColumn(2,"培训费用",LVCFMT_RIGHT,60);
m_lcExamType.InsertColumn(3,"考试费用",LVCFMT_RIGHT,60);
m_lcExamType.InsertColumn(4,"培训时长",LVCFMT_RIGHT,60);
m_lcExamType.InsertColumn(5,"需要证书",LVCFMT_CENTER,60);

然后在MDI主窗口的菜单“考试类型"的OnCommand事件中以此CfrmExamType创建了一个窗口,但是发现OnInitialUpdate没有被调用,请问这是怎么回事?
另,我试着在FormView上加一个按钮,并且在按钮的OnClicked事件中写入以上同样的代码:则代码一执行就出现错误。若我在按钮中的代码改为:
DWORD dwListStyle;
CRect rListRect(10,10,400,500);
m_lcExamType.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT, rListRect, this, IDC_LC_EXAMTYPE); //没有这个语句就一定会出运行时错误
dwListStyle=m_lcExamType.GetStyle();
dwListStyle|= LVS_EX_GRIDLINES |LVS_EX_FULLROWSELECT|LVS_SHOWSELALWAYS|LVS_EX_HEADERDRAGDROP;
m_lcExamType.SetExtendedStyle(dwListStyle);
m_lcExamType.InsertColumn(0,"编号",LVCFMT_RIGHT,40);
m_lcExamType.InsertColumn(1,"考试类型",LVCFMT_CENTER,100);
m_lcExamType.InsertColumn(2,"培训费用",LVCFMT_RIGHT,60);
m_lcExamType.InsertColumn(3,"考试费用",LVCFMT_RIGHT,60);
m_lcExamType.InsertColumn(4,"培训时长",LVCFMT_RIGHT,60);
m_lcExamType.InsertColumn(5,"需要证书",LVCFMT_CENTER,60);
m_lcExamType.UpdateWindow();
则代码执行后可以看到ListCtrl的确是添加了几个栏,但是除了滚动条能响应鼠标之外,其它部位都不响应鼠标,也就是加了Item之后,Item都无法选择。

注意:我没有采用Document/View结构。
1.是否不采用这种结构,FormView创建时就不会调用OnInitialUpdate?
2.如果我采用Document/View结构,CListCtrl的使用就完全正常,这到底是什么回事?

还请高手提示!
...全文
385 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangtianhong 2005-05-10
  • 打赏
  • 举报
回复
不需要用Create来处理了。
zhangtianhong 2005-05-10
  • 打赏
  • 举报
回复
非常感谢“边城浪子”!!!此问题已经解决,我立刻给分!
“控件关联是通过 函数 DDX_Control 来进行的. 这个函数在 DoDataExchange 里

DoDataExchange 在 CFormView 里是在 CFormView::OnInitialUpdate() 里首次调用的:”
在手动调用了OnInitialUpdate()之后,控件就可以正常使用了!谢谢!!!
oyljerry 2005-05-10
  • 打赏
  • 举报
回复
Create后,ShowWindow显示一下
jerry 2005-05-10
  • 打赏
  • 举报
回复
我查了一下 WM_INITIALUPDATE 定义在 头文件 <afxpriv.h>
控件问题:
你用的是CFormView, 那么那个m_lcExamType 应该是关联到对话框模板上的相应控件了吧? 如果是这样.那么请继续看:


控件关联是通过 函数 DDX_Control 来进行的. 这个函数在 DoDataExchange 里

DoDataExchange 在 CFormView 里是在 CFormView::OnInitialUpdate() 里首次调用的:

void CFormView::OnInitialUpdate()
{
ASSERT_VALID(this);

if (!UpdateData(FALSE))
TRACE0("UpdateData failed during formview initial update.\n");

CScrollView::OnInitialUpdate();
}

DDX_Control 函数就是在这里关联到控件的:

void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)
{
if (rControl.m_hWnd == NULL) // not subclassed yet
{
ASSERT(!pDX->m_bSaveAndValidate);

HWND hWndCtrl = pDX->PrepareCtrl(nIDC);

if (!rControl.SubclassWindow(hWndCtrl))
{
ASSERT(FALSE); // possibly trying to subclass twice?
AfxThrowNotSupportedException();
}
#ifndef _AFX_NO_OCC_SUPPORT
else
{
// If the control has reparented itself (e.g., invisible control),
// make sure that the CWnd gets properly wired to its control site.
if (pDX->m_pDlgWnd->m_hWnd != ::GetParent(rControl.m_hWnd))
rControl.AttachControlSite(pDX->m_pDlgWnd);
}
#endif //!_AFX_NO_OCC_SUPPORT

}
}

可以看到, 它会检测对象句柄是否为空, 为空表示还没有关联. 这时才进行子类化. 因为DoDataExchange() 函数会被多次调用,这是必需要检测的,关联只能一次.

根据以上看到的, 你的控件不必手工创建的, 而是应该在 OnInitialUpdate() 调用用缺省实现,或者手工调用 UpdateData(FALSE) 来实现:

void CMyFormView::OnInitialUpdate()
{
CFormView::OnInitalUpdate();

// 初始化控件:
dwListStyle=m_lcExamType.GetStyle();
dwListStyle|= LVS_EX_GRIDLINES |LVS_EX_FULLROWSELECT|LVS_SHOWSELALWAYS|LVS_EX_HEADERDRAGDROP;
m_lcExamType.SetExtendedStyle(dwListStyle);
m_lcExamType.InsertColumn(0,"编号",LVCFMT_RIGHT,40);
m_lcExamType.InsertColumn(1,"考试类型",LVCFMT_CENTER,100);
....

}


}
zhangtianhong 2005-05-10
  • 打赏
  • 举报
回复
To:边城浪子,我发现WM_INITALUPDATE这个消息不存在啊?是不是我的环境不支持?我的是VS2003。
我在框架创建视图之后,手动加了一句:m_pWndView->OnInitialUpdate(); 这样解决了初始化过程的调用问题,难道这个过程是必须自己的代码显式调用的么?如果是用对话框,为何不需显式调用OnInitalDialog,这个过程就会被调用?
在FormView里面,到底应该用什么方法对CListCtrl和CTreeCtrl进行初始化呢?用它们的Create为何没有效果?
zhangtianhong 2005-05-10
  • 打赏
  • 举报
回复
谢谢边城浪子,现在的问题变成是:如何对FormView里的控件进行初始化?调用控件的Create函数之后,为什么只有滚动条能响应鼠标操作?
我今早又加了个CTreeCtrl试了一下,发现存在同样的问题,然而为什么在CDialog里面,这些控件就不需初始化而能正常使用呢?
jerry 2005-05-09
  • 打赏
  • 举报
回复
框架创建视图应该使用 CreateView, 当然,因为你的没文档,这个还有点麻烦: 请看 CSplitterWnd 是怎么创建视图的 (去掉对你无用的):

BOOL CSplitterWnd::CreateView(/*int row, int col, */
CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext)
{

// set the initial size for that pane

CCreateContext contextT;
if (pContext == NULL)
{
pContext = &contextT;
}

CWnd* pWnd;
TRY
{
pWnd = (CWnd*)pViewClass->CreateObject();
if (pWnd == NULL)
AfxThrowMemoryException();
}
CATCH_ALL(e)
{
TRACE0("Out of memory creating a splitter pane.\n");
// Note: DELETE_EXCEPTION(e) not required
return FALSE;
}
END_CATCH_ALL

ASSERT_KINDOF(CWnd, pWnd);
ASSERT(pWnd->m_hWnd == NULL); // not yet created

DWORD dwStyle = AFX_WS_DEFAULT_VIEW;
if (afxData.bWin4)
dwStyle &= ~WS_BORDER;

// Create with the right size (wrong position)
CRect rect(CPoint(0,0), sizeInit);
if (!pWnd->Create(NULL, NULL, dwStyle,
rect, this, 1, pContext)) // 视图的ID号,给一个唯一的
{
TRACE0("Warning: couldn't create client pane for splitter.\n");
// pWnd will be cleaned up by PostNcDestroy
return FALSE;
}

// send initial notification message
pWnd->SendMessage(WM_INITIALUPDATE); // 应该主动发消息来初始化视图

return TRUE;
}

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧