⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atlapp.h文件剖析.txt

📁 WTL源码剖析 --- ATLAPP.H
💻 TXT
📖 第 1 页 / 共 2 页
字号:
              if(::IsWindow(hNtfWnd))
              {
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
                   ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
#else
                   ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
#endif
                   //加入该窗口句柄
                   bRet = m_pSettingChangeNotify->Add(hNtfWnd);
              }
              else
              {
                   bRet = FALSE;
              }
         }
 
          lock.Unlock();
 
         return bRet;
     }
该函数用来初始化一个存放窗口句柄的对象
 
     BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
     {
          CStaticDataInitCriticalSectionLock lock;
          if(FAILED(lock.Lock()))
         {
              ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
              ATLASSERT(FALSE);
              return FALSE;
         }
 
          if(m_pSettingChangeNotify == NULL)
         {
              typedef ATL::CSimpleArray<HWND>   _notifyClass;
              ATLTRY(m_pSettingChangeNotify = new _notifyClass);
              ATLASSERT(m_pSettingChangeNotify != NULL);
         }
 
         BOOL bRet = (m_pSettingChangeNotify != NULL);
          if(bRet && m_pSettingChangeNotify->GetSize() == 0)
         {
              // init everything
              //??空的ATL Dialog Template吗?
              _ATL_EMPTY_DLGTEMPLATE templ;
              //增加一个无模式对话框
              HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
              ATLASSERT(::IsWindow(hNtfWnd));
              if(::IsWindow(hNtfWnd))
              {
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
                   ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
#else
                   ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, PtrToLong(this));
#endif
                   bRet = m_pSettingChangeNotify->Add(hNtfWnd);
              }
              else
              {
                   bRet = FALSE;
              }
         }
 
          lock.Unlock();
 
         return bRet;
     }
 
     //清理消息
     void TermSettingChangeNotify()
     {
          CStaticDataInitCriticalSectionLock lock;
          if(FAILED(lock.Lock()))
         {
              ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
              ATLASSERT(FALSE);
              return;
         }
 
          if(m_pSettingChangeNotify != NULL && m_pSettingChangeNotify->GetSize() > 0)
              //销毁窗口
              ::DestroyWindow((*m_pSettingChangeNotify)[0]);
         delete m_pSettingChangeNotify;
          m_pSettingChangeNotify = NULL;
 
          lock.Unlock();
     }
 
BOOL AddSettingChangeNotify(HWND hWnd)
     {
          CStaticDataInitCriticalSectionLock lock;
          if(FAILED(lock.Lock()))
         {
              ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
              ATLASSERT(FALSE);
              return FALSE;
         }
 
          ATLASSERT(::IsWindow(hWnd));
         BOOL bRet = FALSE;
          if(InitSettingChangeNotify() != FALSE)
              bRet = m_pSettingChangeNotify->Add(hWnd);
 
          lock.Unlock();
 
         return bRet;
     }
 
BOOL RemoveSettingChangeNotify(HWND hWnd)
     {
          CStaticDataInitCriticalSectionLock lock;
          if(FAILED(lock.Lock()))
         {
              ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
              ATLASSERT(FALSE);
              return FALSE;
         }
 
         BOOL bRet = FALSE;
          if(m_pSettingChangeNotify != NULL)
              bRet = m_pSettingChangeNotify->Remove(hWnd);
 
          lock.Unlock();
 
         return bRet;
     }
 
     现在回到刚才提到的Run()函数,里面最开始就定义了一个CmessageLoop循环对象,然后通过_Module对象的AddMessageLoop成员函数加入到循环队列里面,直到_Module调用了RemoveMessageLoop移除循环队列,程序才结束循环,返回到WinMain函数。
     在这里还有一个比较重要的类,那就是CMessageLoop,是他维持了系统的消息,维持了程序的生命周期。那么下面我们来看看这个类的定义和具体的实现方法。
CmessageLoop包含了如下一些成员函数和成员变量
成员变量
//处理消息
     ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
     //处理空闲句柄
     ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
     //Win32API消息结构
     MSG m_msg;
 
     成员函数(用红色标记的函数是虚函数)
AddMessageFilter         加入一条消息过滤
RemoveMessageFilter      移除一条消息过滤
AddIdleHandler       加入一个空闲句柄
RemoveIdleHandler         移出一个空闲句柄
AddUpdateUI              为了兼容老的ATL而设计的
RemoveUpdateUI           为了兼容老的ATL而设计的
IsIdleMessage            过滤一些比如WM_MOUSEMOVE之类的消息
Run                      消息循环。关键部分!!!
PreTranslateMessage      消息过滤
OnIdle                   空闲处理
 
再这里我不准备对每个函数都进行详细的分析,主要分析核心的函数Run,CmessageLoop由它来维持着系统的消息循环。
函数如下:
int Run()
     {
         //空闲?
         BOOL bDoIdle = TRUE;
         //空闲计数器
         int nIdleCount = 0;
         //返回标志
         BOOL bRet;
 
         //开始消息循环了哦!!!
          for(;;)
         {
 
              //当bDoIdle为TRUE,并且不能从消息队列里面取出消息了,那么开始空闲操作了!
              //PM_NOREMOVE:再PeekMessage函数处理后不将消息从队列里移除
              while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
              {
                   if(!OnIdle(nIdleCount++))
                        bDoIdle = FALSE;
              }
              
              //从当前线程获取一个消息
              //返回-1表示出现一个错误
              //返回 0表示提交了一个WM_QUIT,程序将要退出
              //成功获得一个消息,返回不等于0的值
              bRet = ::GetMessage(&m_msg, NULL, 0, 0);
 
              if(bRet == -1)
              {
                   ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
                   continue;   // error, don't process
              }
              else if(!bRet)
              {
                   ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
                   break;   // WM_QUIT, exit message loop
              }
 
              //如果熟悉使用c语言来写Win32的程序员会发现,原来WinMain中的哪个处理消息循环的语句放到这里来了!!!
              if(!PreTranslateMessage(&m_msg))
              {
                   //translates virtual-key messages into character messages.
                   ::TranslateMessage(&m_msg);
                   //dispatches a message to a window procedure
                   ::DispatchMessage(&m_msg);
              }
              
              //判断是否为空闲消息?
              //排除WM_MOUSEMOVE WM_NCMOUSEMOVE WM_SYSTIMER消息
              if(IsIdleMessage(&m_msg))
              {
                   bDoIdle = TRUE;
                   nIdleCount = 0;
              }
         }
 
         return (int)m_msg.wParam;
     }
以上就是对ATLAPP.H中的几个比较重要的类的分析,还有其他几个类的分析我将放在以后的文章中
(待续。。。)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -