DeadLine快到 了,请大神耐心帮我看下这个蹊跷的问题!

npu_wy 2014-06-04 11:26:03
为方便理解,我用PPT描述了问题:

在CWinApp有2个模态对话框成员A和B,
在CWinApp::InitInstance()中创建模态对话框C,并调用C.DoModal(),
在C的OnBnClickedOk()中调用theApp.A.DoModal();
此时在另一个线程P中收到关闭A的消息,执行
::PostMessage(theApp.A.GetSafeHwnd(), WM_CLOSE, 0, 0);
然后,A就结束了,主线程在C中继续执行,调用theApp.B.DoModal();
这时又在另一个线程P中收到关闭B的消息,我希望执行:
::PostMessage(theApp.B.GetSafeHwnd(), WM_CLOSE, 0, 0);
关闭B,然后在C中调用CDialog::OnOK();关闭C,就回到了CWinApp::InitInstance()中,然后继续下去就会顺利执行CWinView类,可是……,事实是这样的:
在执行::PostMessage(theApp.B.GetSafeHwnd(), WM_CLOSE, 0, 0);后,B确实关闭了,但是,程序没有继续执行下去,CWinView没有显示,我查看任务管理器,没有看到我的程序……
介个是为什么呢…… 大神快帮帮吧,同学没人学MFC,只能到这里求助了……
...全文
248 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
npu_wy 2014-06-05
  • 打赏
  • 举报
回复
引用 8 楼 zhousitiaoda 的回复:
CLoginDlg是怎么关闭的? //CDialog::OnOK();// 关闭登陆对话框 这个注释了对话框就不会关闭了啊
在29行关了,也就是在显示roomDlg前关了,我改到函数末尾关效果一样
npu_wy 2014-06-05
  • 打赏
  • 举报
回复
引用 7 楼 zhousitiaoda 的回复:
程序是单文档还是对话框?对话框的话该不会C是主对话框吧? 程序没有继续执行下去,CWinView没有显示 这句没说清,没有继续执行下去是什么意思?打个断点没有下去还是?CWinView没有显示?单文档的视图?
DWORD WINAPI CClientApp::recvCenter(LPVOID lpParameter)
{
	char recvBuffer[500];
	memset(recvBuffer, 0, sizeof(recvBuffer));
	while (true)
	{
		if (0 == theApp.msgCenter.m_socket || INVALID_SOCKET == theApp.msgCenter.m_socket || !theApp.msgCenter.bindSuccess)
		{
			continue;
		}
		// 接收消息
		if (-1 != theApp.msgCenter.RecvFrom(recvBuffer, 500))
		{
			// 根据首字符分发消息
			theApp.dispatchMsg(recvBuffer);
		}
	}
}

// 根据首字符分发消息
bool CClientApp::dispatchMsg(char* recvBuffer) const
{
	CString recvMsg(recvBuffer);
	CString allWords;
	switch (recvBuffer[0])
	{
	case '1':
		switch (recvBuffer[2])
		{
		case '2':// 登陆请求之后返回房间信息
			theApp.m_bIsConnect = TRUE;
			//theApp.roomDlg.updateRoomInfo(recvMsg);// 更新房间信息
			theApp.roomDlg.storeRoomInfo = recvMsg;
			::PostMessage(theApp.waitDlg.GetSafeHwnd(), WM_CLOSE, 0, 0);
			break;

		case '4':// 更换房间之后返回房间信息
			theApp.roomDlg.updateRoomInfo(recvMsg);// 更新房间信息
			break;

		case '7':// 游戏开始,得到对方角色ID,并关闭roomDlg
			theApp.roomDlg.m_nFigureIDhe = recvMsg[4] - '0';
			//theApp.roomDlg.SendMessage(WM_CLOSE, 0, 0);
			::PostMessage(theApp.roomDlg.GetSafeHwnd(), WM_CLOSE, 0, 0);
			//theApp.roomDlg.OK();
			//theApp.roomDlg.ShowWindow(SW_HIDE);
			break;

		default:
			break;
		}
		break;
                ……
           ……
}
npu_wy 2014-06-05
  • 打赏
  • 举报
回复
引用 7 楼 zhousitiaoda 的回复:
程序是单文档还是对话框?对话框的话该不会C是主对话框吧? 程序没有继续执行下去,CWinView没有显示 这句没说清,没有继续执行下去是什么意思?打个断点没有下去还是?CWinView没有显示?单文档的视图?
程序是MFC单文档; 在运行情况下:服务器发送开始游戏后,游戏大厅对话框直接消失,并没有出现CWinView,没有任何响应,查看任务管理器,找不到我的程序运行; 在调试情况下:(在接收消息那个线程中设有断点)当接收到服务器发送的开始游戏消息后,调用PostMessage()关闭对话框后,程序在接收消息的线程函数recvCenter中顺序执行,并且
if (0 == theApp.msgCenter.m_socket || INVALID_SOCKET == theApp.msgCenter.m_socket || !theApp.msgCenter.bindSuccess)
始终未FALSE,按下F5,程序显示: Source Not Available
zhousitiaoda 2014-06-05
  • 打赏
  • 举报
回复
CLoginDlg是怎么关闭的? //CDialog::OnOK();// 关闭登陆对话框 这个注释了对话框就不会关闭了啊
zhousitiaoda 2014-06-05
  • 打赏
  • 举报
回复
程序是单文档还是对话框?对话框的话该不会C是主对话框吧? 程序没有继续执行下去,CWinView没有显示 这句没说清,没有继续执行下去是什么意思?打个断点没有下去还是?CWinView没有显示?单文档的视图?
npu_wy 2014-06-05
  • 打赏
  • 举报
回复
引用 3 楼 ouyh12345 的回复:
为什么要在InitInstance里做这些,而且这么复杂? 正常的流程就行了,加上log
引用 1 楼 91program 的回复:
如果思路没有问题,可能是你的代码实现的逻辑有问题
void CLoginDlg::OnBnClickedOk()
{
	// TODO: Add your control notification handler code here
	UpdateData();
	m_strUserName.Trim();// 去除空格
	if ("" == m_strUserName)
	{
		MessageBox(_T("昵称不能为空"));
		return;
	}

	/////////////////////////////// 发现主机 ////////////////////////////////////
	// 发送昵称和IP地址到服务器
	// 接收房间信息等待……
	USES_CONVERSION;
	string tmp1(W2A(m_strUserName));
	string tmp = string("1 1 ") + tmp1;
	if (-1 == theApp.msgCenter.FindHost((u_short)6000, tmp.c_str(), tmp.length()))
	{
		MessageBox(_T("发现主机失败!"));
		return;
	}

	ShowWindow(SW_HIDE);// 先隐藏登陆对话框
	theApp.waitDlg.DoModal();// 显示连接服务器对话框

	if (theApp.m_bIsConnect)
	{
		CDialog::OnOK();// 关闭登陆对话框
		theApp.roomDlg.DoModal(); // 登录对话框成功登录后再显示游戏大厅
	}
	else
	{
		MessageBox(_T("链接服务器失败!请检查服务器是否开启"));
		ShowWindow(SW_SHOW);// 显示登陆对话框
	}
	//CDialog::OnOK();// 关闭登陆对话框
}
npu_wy 2014-06-05
  • 打赏
  • 举报
回复
引用 1 楼 91program 的回复:
如果思路没有问题,可能是你的代码实现的逻辑有问题
引用 3 楼 ouyh12345 的回复:
为什么要在InitInstance里做这些,而且这么复杂? 正常的流程就行了,加上log
我写的是一个局域网格斗游戏,在CClientView出现前,先出现Login对话框(C对话框),给服务器发送登陆消息,然后显示连接服务器的等待对话框waitDlg(A对话框),然后在另一个msgCenter中接收消息,那里接收到后,关闭waitDlg对话框(A对话框)后,CLoginDlg::OnBnClickedOk()继续顺序执行,去显示theApp.roomDlg.DoModal(); (B对话框),同时可以考虑调用CDialog::OnOK();关闭Login对话框(C对话框),然后客户端在接收到服务器发送的开始游戏的消息后,客户端调用
::PostMessage(theApp.roomDlg.GetSafeHwnd(), WM_CLOSE, 0, 0);
关闭游戏大厅,让阻塞的主程序顺序执行,去CClientView那里,显示格斗场面……
npu_wy 2014-06-05
  • 打赏
  • 举报
回复
引用 3 楼 ouyh12345 的回复:
为什么要在InitInstance里做这些,而且这么复杂? 正常的流程就行了,加上log
BOOL CClientApp::InitInstance()
{
	CWinApp::InitInstance();


	// 初始化 OLE 库
	if (!AfxOleInit())
	{
		AfxMessageBox(IDP_OLE_INIT_FAILED);
		return FALSE;
	}

	AfxEnableControlContainer();

	// 初始化socket
	if (!msgCenter.SocketInit())
	{
		AfxMessageBox(_T("初始化套接字失败!"));
		PostQuitMessage(WM_QUIT);
		return false;
	}
	else
	{
		HANDLE hThreadMsg = ::CreateThread(NULL, 0, recvCenter, NULL, 0, NULL);
		CloseHandle(hThreadMsg);
	}
	

//////////////////////// 显示欢迎界面 ////////////////////////////
	{// 使用块是希望欢迎界面播放结束后,自动析构,不然进入下面的loginDlg里面,
	 // 是无法使用mci播放视频的,估计是mci设备被占用,没有得到释放
		//CWaitDlg  welcomeDlg(CString(_T("welcome.avi")), WELCOME);
		//welcomeDlg.DoModal();
	}

/////////////////////// 显示登录对话框 ///////////////////////////
	CLoginDlg loginDlg;
	if (!loginDlg.DoModal())
	{
		return FALSE;
	}
////////////////////////////////////////////////////////////////
	EnableTaskbarInteraction(FALSE);

	// 使用 RichEdit 控件需要  AfxInitRichEdit2()	
	// AfxInitRichEdit2();

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
	LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)


	// 注册应用程序的文档模板。文档模板
	// 将用作文档、框架窗口和视图之间的连接
	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CClientDoc),
		RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
		RUNTIME_CLASS(CClientView));
	if (!pDocTemplate)
		return FALSE;
	AddDocTemplate(pDocTemplate);


	// 分析标准 shell 命令、DDE、打开文件操作的命令行
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// 调度在命令行中指定的命令。如果
	// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

	// 唯一的一个窗口已初始化,因此显示它并对其进行更新
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();
	return TRUE;
}
ouyh12345 2014-06-05
  • 打赏
  • 举报
回复
为什么要在InitInstance里做这些,而且这么复杂? 正常的流程就行了,加上log
lis2012 2014-06-05
  • 打赏
  • 举报
回复
引用 楼主 npu_wy 的回复:
为方便理解,我用PPT描述了问题: 在CWinApp有2个模态对话框成员A和B, 在CWinApp::InitInstance()中创建模态对话框C,并调用C.DoModal(), 在C的OnBnClickedOk()中调用theApp.A.DoModal(); 此时在另一个线程P中收到关闭A的消息,执行 ::PostMessage(theApp.A.GetSafeHwnd(), WM_CLOSE, 0, 0); 然后,A就结束了,主线程在C中继续执行,调用theApp.B.DoModal(); 这时又在另一个线程P中收到关闭B的消息,我希望执行: ::PostMessage(theApp.B.GetSafeHwnd(), WM_CLOSE, 0, 0); 关闭B,然后在C中调用CDialog::OnOK();关闭C,就回到了CWinApp::InitInstance()中,然后继续下去就会顺利执行CWinView类,可是……,事实是这样的: 在执行::PostMessage(theApp.B.GetSafeHwnd(), WM_CLOSE, 0, 0);后,B确实关闭了,但是,程序没有继续执行下去,CWinView没有显示,我查看任务管理器,没有看到我的程序…… 介个是为什么呢…… 大神快帮帮吧,同学没人学MFC,只能到这里求助了……
把 CWinApp::InitInstance()代码贴上来,你这是多文档或者单文档程序?
91program 2014-06-05
  • 打赏
  • 举报
回复
如果思路没有问题,可能是你的代码实现的逻辑有问题
神-气 2014-06-05
  • 打赏
  • 举报
回复
楼主是蜗牛

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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