惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
Jina AI
Jina AI
GbyAI
GbyAI
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
P
Proofpoint News Feed
The Cloudflare Blog
H
Help Net Security
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
量子位
博客园 - 聂微东
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
月光博客
月光博客

博客园 - dtor

TD-SCDMA小区初搜方法研究 (转) 面试题 the beginning of gidplus 关闭进程. - dtor - 博客园 vc任务栏隐藏 sql 连接字符串 xml 留言本 - dtor - 博客园 浮动 div javascript 读写xml --2 - dtor VC编译优化设置 javascript读写 xml - dtor - 博客园 vector 转 array 线程基础知识 VC++ 环 境 下 利 用 管 道 和 线 程 实 现 进 程 间 通 信 Windows管道技术 Windows下多线程编程技术及其实现 error LNK2001: unresolved external symbol _WinMain@16 ATL布幔下的秘密之窗口类的秘密(果冻) VC制作工具条
atl中的mfc线程
dtor · 2006-08-04 · via 博客园 - dtor

MFC提供了许多十分有用的类和对象,在很多时候在Office插件、BHO、常规DLL这样的工程中加入MFC支持是一个不错的选择。但是,MFC中的很多功能,例如资源查找,消息预处理等等都依赖于在进程或者线程创建时被初始化的MFC内部数据;而对于需要添加MFC支持的工程,这些数据并不会被自动地初始化。这时候使用一些MFC的功能,例如使用CString从字符串表加载一个字符串,或者使用CDialog::DoModal()创建一个模态对话框,都会有断言错误,用ATL向导创建的支持MFC的程序也没有多少改善,在CWinApp的DLL版本中没有初始化线程数据,所以调用AfxGetThread会返回空指针。解决这个问题的一个办法是使用AfxBeginThread来启动一个MFC线程,这样MFC会初始化线程相关的数据。在下面的示例中,我在线程初始化时建立了一个模态对话框,以避免直接创建模态对话框会触发的断言失败信息。为了模拟模态对话框的效果,在CDialogThread::WaitForDoModal()这个函数中创建了一个消息循环来等待线程结束,同时用MsgWaitForMultipleObjects来避免死锁。因为MFC中和进程相关的数据并不总是被正确初始化,在调用模态对话框之前也需要手动设置一下。

//如果这段代码可以工作,那么它的作者是Jiangsheng
//否则我不知道它的作者
void __stdcall CFrontPageAddin::OnClickButtonExportCHM(IDispatch* /*Office::_CommandBarButton* 
*/ Ctrl,VARIANT_BOOL * CancelDefault)
{
    AtlTrace(_T(
" CFPAnt::OnClickButtonExportCHM\n"));
    
//create a thread to avoid assert failure
    CDialogThread* pDialogThread=
        (CDialogThread
*)AfxBeginThread(RUNTIME_CLASS(CDialogThread),
        THREAD_PRIORITY_NORMAL,
        
0,
        CREATE_SUSPENDED,NULL);
    
if(pDialogThread)
    {
        pDialogThread
->m_prc=RUNTIME_CLASS(CExportCHMSheet);
        pDialogThread
->ResumeThread();
        pDialogThread
->WaitForDoModal();
        delete pDialogThread;
    }
}
class CDialogThread : public CWinThread
{
    
    
int m_nModalResult;
    CRuntimeClass
* m_prc;
    
void WaitForDoModal();
    
};
CDialogThread::CDialogThread()
{
    m_bAutoDelete
=FALSE;
    m_prc
=NULL;
    m_nModalResult
=0;
}
BOOL CDialogThread::InitInstance()
{
    
// TODO: perform and per-thread initialization here
    AFX_MANAGE_STATE(AfxGetAppModuleState());
    AFX_MODULE_STATE
* pModuleState=AfxGetModuleState();
    pModuleState
->m_hCurrentInstanceHandle=_Module.GetModuleInstance();
    AfxSetResourceHandle(_Module.GetModuleInstance());
    
if(m_prc)
    {
        
if(m_prc->IsDerivedFrom(RUNTIME_CLASS(CDialog)))
        {
            CDialog
* pDialog=(CDialog*)m_prc->CreateObject();
            
if(pDialog)
            {
                m_pMainWnd
=pDialog;
                m_nModalResult
=pDialog->DoModal();
            }
        }
        
else if(m_prc->IsDerivedFrom(RUNTIME_CLASS(CPropertySheet)))
        {
            CPropertySheet
* pDialog=(CPropertySheet*)m_prc->CreateObject();
            
if(pDialog)
            {
                m_pMainWnd
=pDialog;
                m_nModalResult
=pDialog->DoModal();
            }
        }
    }
    
return FALSE;
}
void CDialogThread::WaitForDoModal()
{
    
//from http://blogs.msdn.com/oldnewthing/archive/2005/02/17/375307.aspx
    MSG msg;
    UINT cRecords 
= 0;
    
while (true) {
        
switch (MsgWaitForMultipleObjects(1&m_hThread,
            FALSE, INFINITE, QS_ALLINPUT)) {
            
case WAIT_OBJECT_0:
            
return ; // event has been signalled
            break;
            
case WAIT_OBJECT_0+1:
            
// we have a message - peek and dispatch it
            if (PeekMessage(&msg, NULL, 00, PM_REMOVE)) {
                TranslateMessage(
&msg);
                DispatchMessage(
&msg);
            }
            
break;
            
default:
            
return ; // unexpected failure
        }
    }
}

使用VC6.0编译通过。

上面的方法只对于DLL之类的组件比较有用。对于使用MFC的应用程序来说,上面的方法比较繁琐。比较简单的方法还是使用MFC向导来创建应用程序,然后再添加ATL或者.Net之类的额外支持。参考微软知识库文章Q181505和Q824480。
参考

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=459594