前台线程与后台线程,AfxGetApp->GetMainWnd()与AfxGetMainWnd的不同

本文详细解析了AfxGetMainWnd()函数在不同线程环境下的工作原理,特别强调了后台线程与主窗口句柄之间的区别,并通过跟踪代码揭示了函数内部实现细节。此外,文章还提供了获取程序主窗口的方法和注意事项,旨在帮助开发者正确理解和使用该函数。
CWnd* pWnd = AfxGetApp()->GetMainWnd();


 

  

  顾名思义,前台指看得见,既然看得见自然要有窗口,而后台是看不见,看不见可以理解为没有窗口,既然没有窗口,那么用AfxGetMainWnd()取得其窗口句柄,未免有些搞笑,为什么呢?聪明的你想必早已明白,如果你曾经跟踪过AfxGetMainWnd()的调用,会发现它取得的是AFX_MODULE_THREAD_STATE线程模块中保存的活动线程的窗口句柄,而后台线程既然没有窗口,那你又从何而言取得窗口句柄呢,(也许有人对后台的理解是不显示窗口,就算有窗口,只要不显示就是后台线程,严格的说不是这样,窗口主要用来与用户交互,有窗口就难免阻塞,而后台线程往往用来进行一些后面的运算或处理,是通过前台传递的信息或数据进行相应运做的,如果窗口隐藏谈何信息传递呢?况又不能像其它线程那样进行后台运做.不过你如此理解也无防 ,关键是明白有什么区别,及怎么用.)
AfxGetApp()->GetMainWnd()取得的是主窗口句柄,无论在那个线程里调用都是没有问题的,因为它先取得主线程句柄,再取得主线程的活动窗口(如视图切换可能导致的替代,这种情况我也不大清楚),如果没有活动窗口则取主窗口,任何程序总要有一个主窗口,所以它的调用不会出现问题,如果想取得程序的主窗口建议用AfxGetApp()->GetMainWnd().

  要注意的是控制台程序没有窗口,其窗口句柄始终为0.其次后台线程其实就是一个控制台式的程序,只不过不是主线程罢了.还有就是用API Createthread之类的函数创建的线程无法生成CWinThread对象.所以如果想使用CWinThread对象里的函数,以及一些全局函数进行操作,如上面的AfxGetMainWnd(),就必须用CWinThread对象的CreateThread函数,或用AfxBeginThread()函数创建线程,否则很可能出现错误,因为MFC对线程的管理是通过CWinThread对象来完成的,通过下面的跟踪代码你不难看出.  记得当初有一位前辈曾提到过这个问题,只是不知它是否理解这其中的原因

以下是跟踪代码:

_AFXWIN_INLINE CWnd* AFXAPI AfxGetMainWnd()
{ CWinThread* pThread = AfxGetThread();
        return pThread != NULL ? pThread->GetMainWnd() : NULL; }


CWinThread* AFXAPI AfxGetThread()
{
// check for current thread in module thread state
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;

// if no CWinThread for the module, then use the global app
if (pThread == NULL)
        pThread = AfxGetApp();

return pThread;
}

可以看出当取得的线程句柄为空时,则返回主线程句柄,所以在主线程里调用AfxGetMainWnd()是一定没问题的,(控制台程序除外)

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()
{ return afxCurrentWinApp; }


CWnd* CWinThread::GetMainWnd()
{
if (m_pActiveWnd != NULL)
        return m_pActiveWnd;          // probably in-place active

// when not inplace active, just return main window
if (m_pMainWnd != NULL)
        return m_pMainWnd;

return CWnd::GetActiveWindow();
}

那个afxCurrentWinApp就不用说了吧.

嘿嘿,一切完毕,如果你的程序存在类似上面的问题可一定要改回来噢.

 

在 MFC 应用程序中,`AfxGetApp()->GetMainWnd()` 返回的是指向应用程序主窗口的指针,其类型为 `CWnd*`。将 `CWnd*` 强制转换为 `CysxfdaclibraryApp*` 类型存在根本性错误,因为 `GetMainWnd()` 返回的是窗口对象指针,而非应用程序对象指针。这种类型不匹配的转换会导致运行时错误或未定义行为。 ### 转换失败的原因分析 - `GetMainWnd()` 返回的是主窗口对象的指针(`CWnd*`),而不是应用程序对象(`CWinApp*`)的指针。`CysxfdaclibraryApp` 是从 `CWinApp` 派生的类, `CWnd` 是完全不同的类层次结构,因此直接进行类型转换是无效的 [^1]。 - 使用强制类型转换 `(CysxfdaclibraryApp*)AfxGetApp()->GetMainWnd()` 会绕过类型检查机制,导致指针指向错误的内存结构,进而引发访问冲突或逻辑错误 [^2]。 ### 正确获取应用程序对象的方式 若需获取应用程序对象的实例,应使用 `AfxGetApp()` 获取 `CWinApp*` 类型的指针,并将其转换为派生类 `CysxfdaclibraryApp*`,而非对 `GetMainWnd()` 的返回值进行转换: ```cpp CysxfdaclibraryApp* pInstance = dynamic_cast<CysxfdaclibraryApp*>(AfxGetApp()); if (pInstance != nullptr) { // 成功获取应用程序对象 } else { // 转换失败,可能原因包括类未正确继承 CWinApp 或 RTTI 未启用 } ``` ### 调试建议 - 确保 `CysxfdaclibraryApp` 类继承自 `CWinApp`,并在全局作用域中定义了该类的唯一实例。 - 检查项目是否启用了运行时类型信息(RTTI),即编译器选项 `/GR` 是否启用。 - 避免在 `InitInstance` 方法执行前调用 `AfxGetApp()`,否则可能导致指针尚未初始化。 - 若应用程序为 DLL 项目,确保 MFC 被设置为“在共享 DLL 中使用”,以避免 EXE 和 DLL 使用不同的 MFC 实例。 --- ### 示例代码:正确获取应用程序对象 ```cpp CysxfdaclibraryApp* GetAppInstance() { CWinApp* pApp = AfxGetApp(); if (pApp == nullptr) { // 应用程序对象尚未初始化 return nullptr; } CysxfdaclibraryApp* pInstance = dynamic_cast<CysxfdaclibraryApp*>(pApp); if (pInstance == nullptr) { // 类型转换失败,可能原因包括类未正确继承 CWinApp 或 RTTI 未启用 AfxMessageBox(_T("Failed to cast application instance.")); } return pInstance; } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值