ActiveX控件事件多层次Fire后的问题

FinalInches 2005-10-26 01:55:49
我现在写了2个OCX,假如COcx1和COcx12和一个应用app,COcx2调用COcx1,app调用COcx2。在COcx2中提供一个方法,COcx2::Start(),这其中其实就是调用COcx1中的COcx1::Start()。COcx1中COcx1::Start()的实现是开启一个线程,让线程执行操作,最后实际结果通过COcx1::FireStartResult事件发送给COcx2,而在COcx2中的COcx2::OnStartResult()中继续COcx2::FireStartResult给app。
现在因为Start()执行的线程是个耗时操作,所以在app中调用了COcx1::Start()后会弹出一个对话框dlg1::DoModel()并记下这dlg1的地址 m_pDlg = &dlg1,然后在事件响应函数app::OnStartResult()先ASSERT_VALID(m_pDlg)。
这样操作的时候,每次在启动完成后,在app::OnStartResult()中的断言都无法通过,会出现错误
用的是VC6.0开发平台,系统是Win2000,请问这是什么道理??
...全文
178 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
FinalInches 2005-10-27
  • 打赏
  • 举报
回复
可以确定的告诉你,对话框启动了,而且我需要的就是模态的,非模态的对我没有意义,因为Start()中开启的线程是个费时操作,所以才出现一个模特对话框,以防用户发出别的会产生冲突的操作,m_pDlg->DoModel()之后没有输入是不会返回,也就是OnButtonStart函数不会返回,所以这个地址一直是有效的,而在OnStartResult()里面是响应控件启动完成后的事件,这个时候才能让这个对话框消失,之所以要ASSERT_VALID,就是为了防止对话框还没有出现的情况。
最后,问题也找出来了,就是因为在COcx1里面在线程函数里面直接调用了FireStartResult函数P->FireStartReslut()。所以才会出错,而改为给自己发送一个消息再在消息处理函数里面COcx1::FireStartResult()就没有问题,我推断可能是在线程里面直接FireStartResult的时候可能会造成访问冲突,以至于在ASSERT_VALID的时候,线程的状态不对,所以会出现ASSERT_VALID无法通过的情况。
zxyjyzxyjy 2005-10-27
  • 打赏
  • 举报
回复
当你改为发送消息时,注意程序执行的顺序是
App::OnButtonStart()
{
// ...
COcx2::Start();//在启动的另一个线程中发消息给这个App处理,这时程序运行到这里,不会立即处理消息,而是要把这后面的语句执行完后再处理你发的那个消息,你可以在这个后面设一个段点和在App::OnStartReslut()里设一个断点来看看先运行哪个函数。

CDlg dlg;
m_pDlg = &dlg;
m_pDlg->DoModel();
}
zxyjyzxyjy 2005-10-27
  • 打赏
  • 举报
回复
把:
App::OnButtonStart()
{
// ...
COcx2::Start();

CDlg dlg;
m_pDlg = &dlg;
m_pDlg->DoModel();
}
改为:
App::OnButtonStart()
{

CDlg dlg;
m_pDlg = &dlg;
m_pDlg.Create(....);
m_pDlg.Show......;//非模态的来显示

COcx2::Start();

}
来试试。
根据你的代码,可能是对话框根本没有建起来,就进入了App::OnStartReslut()函数调用。
sgzwiz 2005-10-27
  • 打赏
  • 举报
回复
m_pDlg.DoModel();
sgzwiz 2005-10-27
  • 打赏
  • 举报
回复
你在app.h中把CDlg *m_dlg;改成CDlg m_dlg;

App::OnButtonStart()
{
// ...
COcx2::Start();

CDlg dlg;
m_pDlg = &dlg;
m_pDlg->DoModel();
}
改成
App::OnButtonStart()
{
// ...
COcx2::Start();

// CDlg dlg;
// m_pDlg = &dlg;
m_pDlg->DoModel();
}
看看。
sgzwiz 2005-10-27
  • 打赏
  • 举报
回复
App::OnButtonStart()
{
// ...
COcx2::Start();

CDlg dlg;
m_pDlg = &dlg;
m_pDlg->DoModel();
}
在App::OnButtonStart()运行结束后,该函数的局部变量dlg就会被解析掉。在其他函数中得到的这个地址肯定是无效的。你在app.h中把CDlg *m_dlg;改成CDlg m_dlg;看看。
FinalInches 2005-10-26
  • 打赏
  • 举报
回复
大概函数情况是:
COcx1::Start()
{
//....
m_pThread = AfxBeginThread(ThreadProc, this)
// ...
}

COcx1::ThreadProc(LPVOID pParam)
{
COcx1 *p = (COcx1 *)pParam;

// 启动操作
// ...
p->FireStartResult();
// ...
}

COcx2::Start()
{
// ...
COcx1::Start();
// ..
}

COcx2::OnStartResult()
{
// ..
FireStartResult();
// ...
}

App::OnButtonStart()
{
// ...
COcx2::Start();

CDlg dlg;
m_pDlg = &dlg;
m_pDlg->DoModel();
}

App::OnStartReslut()
{
// ...
ASSERT_VALID(m_pDlg);
m_pDlg->SendMessage(WM_COMMAND, IDOK, 0); // 让之前出现的dlg消失
// ...
}

这里的关键问题就是出在COcx1中的ThreadProc中的p->FireStartResult,直接这样调用会造成App里面ASSERT_VALID(m_pDlg)出错,如果不是直接调用p->FireStartResult,而是改成p->SendMessage(my_msg, .., ..),在提供一个消息响应函数
COcx1::OmMymsgProc()
{
// ...
FireStartResult();
// ..
}

这样就不会出现ASSERT_VALID(m_pDlg)失败的情况。
zxyjyzxyjy 2005-10-26
  • 打赏
  • 举报
回复
检查你必须重载AssertValid函数。
FinalInches 2005-10-26
  • 打赏
  • 举报
回复
我是在app里的app::OnButton()里面先产生一个dlg,不是new出来的,是直接栈区申请的局部变量,不过把这个dlg的地址赋给了app的成员变量app::m_pDlg,主要是为了在响应完成消息里面app::OnStartResult()里面给这个对话框发送消息,让他消息
zxyjyzxyjy 2005-10-26
  • 打赏
  • 举报
回复
另外,这个宏的要求是这样的。
ASSERT_VALID
ASSERT_VALID( pObject )

Parameters

pObject

Specifies an object of a class derived from CObject that has an overriding version of the AssertValid member function.

zxyjyzxyjy 2005-10-26
  • 打赏
  • 举报
回复
补充一点,指针不指针都一样,关键是如果对话框退出了就不行。
zxyjyzxyjy 2005-10-26
  • 打赏
  • 举报
回复
所以在app中调用了COcx1::Start()后会弹出一个对话.
该对话框是在app中生成的吗?它应该属于app的一个成员,所以应该用指针并且是new出来的,在调用dlg1::DoModel()时不应反回,只能在app::OnStartResult函数内部对话框才OK什么的。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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