home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / ATL / INCLUDE / ATLWIN.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  17.3 KB  |  681 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATLWIN_H__
  12.     #error atlwin.cpp requires atlwin.h to be included first
  13. #endif
  14.  
  15. #ifndef ATL_NO_NAMESPACE
  16. namespace ATL
  17. {
  18. #endif
  19.  
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CWndProcThunk
  22.  
  23. void CWndProcThunk::Init(WNDPROC proc, void* pThis)
  24. {
  25. #if defined(_M_PPC)
  26. #error PPC not yet implemented
  27. #elif defined (_M_ALPHA)
  28.     thunk.ldah_at = 0x279f0000 | HIWORD(proc);
  29.     thunk.ldah_a0 = 0x261f0000 | HIWORD(pThis);
  30.     thunk.lda_at = 0x239c0000 | LOWORD(proc);
  31.     thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
  32.     thunk.jmp = 0x6bfc0000;
  33. #elif defined (_M_IX86)
  34.     thunk.m_mov = 0xb9;
  35.     thunk.m_this = (DWORD)pThis;
  36.     thunk.m_jmp = 0xe9;
  37.     thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
  38. #endif
  39. }
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CWindow
  43.  
  44. HWND CWindow::GetDescendantWindow(int nID) const
  45. {
  46.     _ASSERTE(::IsWindow(m_hWnd));
  47.  
  48.     // GetDlgItem recursive (return first found)
  49.     // breadth-first for 1 level, then depth-first for next level
  50.  
  51.     // use GetDlgItem since it is a fast USER function
  52.     HWND hWndChild, hWndTmp;
  53.     CWindow wnd;
  54.     if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL)
  55.     {
  56.         if(::GetTopWindow(hWndChild) != NULL)
  57.         {
  58.             // children with the same ID as their parent have priority
  59.             wnd.Attach(hWndChild);
  60.             hWndTmp = wnd.GetDescendantWindow(nID);
  61.             if(hWndTmp != NULL)
  62.                 return hWndTmp;
  63.         }
  64.         return hWndChild;
  65.     }
  66.  
  67.     // walk each child
  68.     for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  69.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  70.     {
  71.         wnd.Attach(hWndChild);
  72.         hWndTmp = wnd.GetDescendantWindow(nID);
  73.         if(hWndTmp != NULL)
  74.             return hWndTmp;
  75.     }
  76.  
  77.     return NULL;    // not found
  78. }
  79.  
  80. void CWindow::SendMessageToDescendants(UINT message, WPARAM wParam/*= 0*/, LPARAM lParam/*= 0*/, BOOL bDeep/* = TRUE*/)
  81. {
  82.     CWindow wnd;
  83.     for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  84.         hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  85.     {
  86.         ::SendMessage(hWndChild, message, wParam, lParam);
  87.  
  88.         if(bDeep && ::GetTopWindow(hWndChild) != NULL)
  89.         {
  90.             // send to child windows after parent
  91.             wnd.Attach(hWndChild);
  92.             wnd.SendMessageToDescendants(message, wParam, lParam, bDeep);
  93.         }
  94.     }
  95. }
  96.  
  97. BOOL CWindow::CenterWindow(HWND hWndCenter/* = NULL*/)
  98. {
  99.     _ASSERTE(::IsWindow(m_hWnd));
  100.  
  101.     // determine owner window to center against
  102.     DWORD dwStyle = GetStyle();
  103.     if(hWndCenter == NULL)
  104.     {
  105.         if(dwStyle & WS_CHILD)
  106.             hWndCenter = ::GetParent(m_hWnd);
  107.         else
  108.             hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  109.     }
  110.  
  111.     // get coordinates of the window relative to its parent
  112.     RECT rcDlg;
  113.     ::GetWindowRect(m_hWnd, &rcDlg);
  114.     RECT rcArea;
  115.     RECT rcCenter;
  116.     HWND hWndParent;
  117.     if(!(dwStyle & WS_CHILD))
  118.     {
  119.         // don't center against invisible or minimized windows
  120.         if(hWndCenter != NULL)
  121.         {
  122.             DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
  123.             if(!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
  124.                 hWndCenter = NULL;
  125.         }
  126.  
  127.         // center within screen coordinates
  128.         ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
  129.  
  130.         if(hWndCenter == NULL)
  131.             rcCenter = rcArea;
  132.         else
  133.             ::GetWindowRect(hWndCenter, &rcCenter);
  134.     }
  135.     else
  136.     {
  137.         // center within parent client coordinates
  138.         hWndParent = ::GetParent(m_hWnd);
  139.         _ASSERTE(::IsWindow(hWndParent));
  140.  
  141.         ::GetClientRect(hWndParent, &rcArea);
  142.         _ASSERTE(::IsWindow(hWndCenter));
  143.         ::GetClientRect(hWndCenter, &rcCenter);
  144.         ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  145.     }
  146.  
  147.     int DlgWidth = rcDlg.right - rcDlg.left;
  148.     int DlgHeight = rcDlg.bottom - rcDlg.top;
  149.  
  150.     // find dialog's upper left based on rcCenter
  151.     int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
  152.     int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
  153.  
  154.     // if the dialog is outside the screen, move it inside
  155.     if(xLeft < rcArea.left)
  156.         xLeft = rcArea.left;
  157.     else if(xLeft + DlgWidth > rcArea.right)
  158.         xLeft = rcArea.right - DlgWidth;
  159.  
  160.     if(yTop < rcArea.top)
  161.         yTop = rcArea.top;
  162.     else if(yTop + DlgHeight > rcArea.bottom)
  163.         yTop = rcArea.bottom - DlgHeight;
  164.  
  165.     // map screen coordinates to child coordinates
  166.     return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1,
  167.         SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  168. }
  169.  
  170. BOOL CWindow::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  171. {
  172.     _ASSERTE(::IsWindow(m_hWnd));
  173.  
  174.     DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
  175.     DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  176.     if(dwStyle == dwNewStyle)
  177.         return FALSE;
  178.  
  179.     ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle);
  180.     if(nFlags != 0)
  181.     {
  182.         ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  183.             SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  184.     }
  185.  
  186.     return TRUE;
  187. }
  188.  
  189. BOOL CWindow::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  190. {
  191.     _ASSERTE(::IsWindow(m_hWnd));
  192.  
  193.     DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  194.     DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  195.     if(dwStyle == dwNewStyle)
  196.         return FALSE;
  197.  
  198.     ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle);
  199.     if(nFlags != 0)
  200.     {
  201.         ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  202.             SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  203.     }
  204.  
  205.     return TRUE;
  206. }
  207.  
  208. BOOL CWindow::GetWindowText(BSTR& bstrText)
  209. {
  210.     USES_CONVERSION;
  211.     _ASSERTE(::IsWindow(m_hWnd));
  212.  
  213.     int nLen = ::GetWindowTextLength(m_hWnd);
  214.     if(nLen == 0)
  215.         return FALSE;
  216.  
  217.     LPTSTR lpszText = (LPTSTR)_alloca((nLen+1)*sizeof(TCHAR));
  218.  
  219.     if(!::GetWindowText(m_hWnd, lpszText, nLen+1))
  220.         return FALSE;
  221.  
  222.     bstrText = ::SysAllocString(T2OLE(lpszText));
  223.  
  224.     return (bstrText != NULL) ? TRUE : FALSE;
  225. }
  226.  
  227. HWND CWindow::GetTopLevelParent() const
  228. {
  229.     _ASSERTE(::IsWindow(m_hWnd));
  230.  
  231.     HWND hWndParent = m_hWnd;
  232.     HWND hWndTmp;
  233.     while((hWndTmp = ::GetParent(hWndParent)) != NULL)
  234.         hWndParent = hWndTmp;
  235.  
  236.     return hWndParent;
  237. }
  238.  
  239. HWND CWindow::GetTopLevelWindow() const
  240. {
  241.     _ASSERTE(::IsWindow(m_hWnd));
  242.  
  243.     HWND hWndParent = m_hWnd;
  244.     HWND hWndTmp = hWndParent;
  245.  
  246.     while(hWndTmp != NULL)
  247.     {
  248.         hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER);
  249.         hWndParent = hWndTmp;
  250.     }
  251.  
  252.     return hWndParent;
  253. }
  254.  
  255. /////////////////////////////////////////////////////////////////////////////
  256. // CDynamicChain
  257.  
  258. CDynamicChain::~CDynamicChain()
  259. {
  260.     if(m_pChainEntry != NULL)
  261.     {
  262.         for(int i = 0; i < m_nEntries; i++)
  263.         {
  264.             if(m_pChainEntry[i] != NULL)
  265.                 delete m_pChainEntry[i];
  266.         }
  267.  
  268.         delete [] m_pChainEntry;
  269.     }
  270. }
  271.  
  272. BOOL CDynamicChain::SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID /* = 0 */)
  273. {
  274. // first search for an existing entry
  275.  
  276.     for(int i = 0; i < m_nEntries; i++)
  277.     {
  278.         if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  279.         {
  280.             m_pChainEntry[i]->m_pObject = pObject;
  281.             m_pChainEntry[i]->m_dwMsgMapID = dwMsgMapID;
  282.             return TRUE;
  283.         }
  284.     }
  285.  
  286. // create a new one
  287.  
  288.     ATL_CHAIN_ENTRY* pEntry = NULL;
  289.     ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
  290.  
  291.     if(pEntry == NULL)
  292.         return FALSE;
  293.  
  294. // search for an empty one
  295.  
  296.     for(i = 0; i < m_nEntries; i++)
  297.     {
  298.         if(m_pChainEntry[i] == NULL)
  299.         {
  300.             m_pChainEntry[i] = pEntry;
  301.             return TRUE;
  302.         }
  303.     }
  304.  
  305. // add a new one
  306.  
  307.     ATL_CHAIN_ENTRY** ppNew = NULL;
  308.     ATLTRY(ppNew = new ATL_CHAIN_ENTRY*[m_nEntries + 1]);
  309.  
  310.     if(ppNew == NULL)
  311.     {
  312.         delete pEntry;
  313.         return FALSE;
  314.     }
  315.  
  316.     pEntry->m_dwChainID = dwChainID;
  317.     pEntry->m_pObject = pObject;
  318.     pEntry->m_dwMsgMapID = dwMsgMapID;
  319.  
  320.     if(m_pChainEntry != NULL)
  321.     {
  322.         memcpy(ppNew, m_pChainEntry, m_nEntries * sizeof(ATL_CHAIN_ENTRY*));
  323.         delete [] m_pChainEntry;
  324.     }
  325.  
  326.     m_pChainEntry = ppNew;
  327.  
  328.     m_pChainEntry[m_nEntries] = pEntry;
  329.  
  330.     m_nEntries++;
  331.  
  332.     return TRUE;
  333. }
  334.  
  335. BOOL CDynamicChain::RemoveChainEntry(DWORD dwChainID)
  336. {
  337.     for(int i = 0; i < m_nEntries; i++)
  338.     {
  339.         if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  340.         {
  341.             delete m_pChainEntry[i];
  342.             m_pChainEntry[i] = NULL;
  343.             return TRUE;
  344.         }
  345.     }
  346.  
  347.     return FALSE;
  348. }
  349.  
  350. BOOL CDynamicChain::CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  351. {
  352.     for(int i = 0; i < m_nEntries; i++)
  353.     {
  354.         if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  355.             return (m_pChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_pChainEntry[i]->m_dwMsgMapID);
  356.     }
  357.  
  358.     return FALSE;
  359. }
  360.  
  361. /////////////////////////////////////////////////////////////////////////////
  362. // CWndClassInfo
  363.  
  364. ATOM CWndClassInfo::Register(WNDPROC* pProc)
  365. {
  366.     if (m_atom == 0)
  367.     {
  368.         ::EnterCriticalSection(&_Module.m_csWindowCreate);
  369.         if(m_atom == 0)
  370.         {
  371.             HINSTANCE hInst = _Module.GetModuleInstance();
  372.             if (m_lpszOrigName != NULL)
  373.             {
  374.                 _ASSERTE(pProc != NULL);
  375.                 LPCTSTR lpsz = m_wc.lpszClassName;
  376.                 WNDPROC proc = m_wc.lpfnWndProc;
  377.  
  378.                 WNDCLASSEX wc;
  379.                 wc.cbSize = sizeof(WNDCLASSEX);
  380.                 if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  381.                 {
  382.                     ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  383.                     return 0;
  384.                 }
  385.                 memcpy(&m_wc, &wc, sizeof(WNDCLASSEX));
  386.                 pWndProc = m_wc.lpfnWndProc;
  387.                 m_wc.lpszClassName = lpsz;
  388.                 m_wc.lpfnWndProc = proc;
  389.             }
  390.             else
  391.             {
  392.                 m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst,
  393.                     m_lpszCursorID);
  394.             }
  395.  
  396.             m_wc.hInstance = hInst;
  397.             if (m_wc.lpszClassName == NULL)
  398.             {
  399.                 if (m_lpszOrigName != NULL)
  400.                     wsprintf(m_szAutoName, _T("ATL:%s:%8.8X"), m_lpszOrigName, (DWORD)&m_wc);
  401.                 else
  402.                     wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD)&m_wc);
  403.                 m_wc.lpszClassName = m_szAutoName;
  404.             }
  405.             WNDCLASSEX wcTemp;
  406.             memcpy(&wcTemp, &m_wc, sizeof(WNDCLASSEX));
  407.             m_atom = ::GetClassInfoEx(m_wc.hInstance, m_szAutoName, &wcTemp);
  408.             if (m_atom == 0)
  409.                 m_atom = ::RegisterClassEx(&m_wc);
  410.         }
  411.         ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  412.     }
  413.  
  414.     if (m_lpszOrigName != NULL)
  415.     {
  416.         _ASSERTE(pProc != NULL);
  417.         _ASSERTE(pWndProc != NULL);
  418.         *pProc = pWndProc;
  419.     }
  420.     return m_atom;
  421. }
  422.  
  423. /////////////////////////////////////////////////////////////////////////////
  424. // CWindowImpl
  425.  
  426. LRESULT CALLBACK CWindowImplBase::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  427. {
  428.     CWindowImplBase* pT = (CWindowImplBase*)_Module.ExtractCreateWndData();
  429.     _ASSERTE(pT != NULL);
  430.     pT->m_hWnd = hWnd;
  431.     pT->m_thunk.Init(WindowProc, pT);
  432.     WNDPROC pProc = (WNDPROC)&(pT->m_thunk.thunk);
  433.     ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  434.     // if somebody has subclassed us already we can't do anything,
  435.     // so discard return value from SetWindowLong
  436.     return pProc(hWnd, uMsg, wParam, lParam);
  437. }
  438.  
  439. LRESULT CALLBACK CWindowImplBase::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  440. {
  441. #ifdef _M_IX86
  442.     __asm mov dword ptr[hWnd], ecx
  443. #endif
  444.     CWindowImplBase* pT = (CWindowImplBase*)hWnd;
  445.     LRESULT lRes;
  446.     BOOL bRet = pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  447.     if(uMsg == WM_NCDESTROY)
  448.         pT->m_hWnd = NULL;
  449.     if(bRet)
  450.         return lRes;
  451.     return pT->DefWindowProc(uMsg, wParam, lParam);
  452. }
  453.  
  454. HWND CWindowImplBase::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  455.         DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom)
  456. {
  457.     _ASSERTE(m_hWnd == NULL);
  458.  
  459.     if(atom == 0)
  460.         return NULL;
  461.  
  462.     _Module.AddCreateWndData(&m_thunk.cd, this);
  463.  
  464.     if(nID == 0 && (dwStyle & WS_CHILD))
  465.         nID = (UINT)this;
  466.  
  467.     HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  468.         dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  469.         rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  470.         _Module.GetModuleInstance(), NULL);
  471.  
  472.     _ASSERTE(m_hWnd == hWnd);
  473.  
  474.     return hWnd;
  475. }
  476.  
  477. BOOL CWindowImplBase::SubclassWindow(HWND hWnd)
  478. {
  479.     _ASSERTE(m_hWnd == NULL);
  480.     _ASSERTE(::IsWindow(hWnd));
  481.     m_thunk.Init(WindowProc, this);
  482.     WNDPROC pProc = (WNDPROC)&(m_thunk.thunk);
  483.     WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  484.     if(pfnWndProc == NULL)
  485.         return FALSE;
  486.     m_pfnSuperWindowProc = pfnWndProc;
  487.     m_hWnd = hWnd;
  488.     return TRUE;
  489. }
  490.  
  491. HWND CWindowImplBase::UnsubclassWindow()
  492. {
  493.     _ASSERTE(m_hWnd != NULL);
  494.  
  495.     if(!::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfnSuperWindowProc))
  496.         return NULL;
  497.  
  498.     m_pfnSuperWindowProc = ::DefWindowProc;
  499.  
  500.     HWND hWnd = m_hWnd;
  501.     m_hWnd = NULL;
  502.  
  503.     return hWnd;
  504. }
  505.  
  506. /////////////////////////////////////////////////////////////////////////////
  507. // CDialogImplBase
  508.  
  509. LRESULT CALLBACK CDialogImplBase::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  510. {
  511.     CDialogImplBase* pT = (CDialogImplBase*)_Module.ExtractCreateWndData();
  512.     _ASSERTE(pT != NULL);
  513.     pT->m_hWnd = hWnd;
  514.     pT->m_thunk.Init(DialogProc, pT);
  515.     WNDPROC pProc = (WNDPROC)&(pT->m_thunk.thunk);
  516.     WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, DWL_DLGPROC, (LONG)pProc);
  517.     // check if somebody has subclassed us already since we don't hold onto it
  518.     ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  519.     return pProc(hWnd, uMsg, wParam, lParam);
  520. }
  521.  
  522. LRESULT CALLBACK CDialogImplBase::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  523. {
  524. #ifdef _M_IX86
  525.     __asm mov dword ptr[hWnd], ecx
  526. #endif
  527.     CDialogImplBase* pT = (CDialogImplBase*)hWnd;
  528.     LRESULT lRes;
  529.     if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0))
  530.     {
  531.         switch (uMsg)
  532.         {
  533.         case WM_COMPAREITEM:
  534.         case WM_VKEYTOITEM:
  535.         case WM_CHARTOITEM:
  536.         case WM_INITDIALOG:
  537.         case WM_QUERYDRAGICON:
  538.             return lRes;
  539.             break;
  540.         }
  541.         if (lRes != 0)
  542.             ::SetWindowLong(pT->m_hWnd, DWL_MSGRESULT, lRes);
  543.         return TRUE;
  544.     }
  545.     return FALSE;
  546. }
  547.  
  548. BOOL CDialogImplBase::EndDialog(int nRetCode)
  549. {
  550.     _ASSERTE(m_hWnd);
  551.     return ::EndDialog(m_hWnd, nRetCode);
  552. }
  553.  
  554. /////////////////////////////////////////////////////////////////////////////
  555. // CContainedWindow
  556.  
  557. LRESULT CALLBACK CContainedWindow::StartWindowProc(HWND hWnd, UINT uMsg,
  558.     WPARAM wParam, LPARAM lParam)
  559. {
  560.     CContainedWindow* pThis = (CContainedWindow*)_Module.ExtractCreateWndData();
  561.     _ASSERTE(pThis != NULL);
  562.     pThis->m_hWnd = hWnd;
  563.     pThis->m_thunk.Init(pThis->WindowProc, pThis);
  564.     WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
  565.     WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  566.     // check if somebody has subclassed us already since we don't hold onto it
  567.     ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  568.     return pProc(hWnd, uMsg, wParam, lParam);
  569. }
  570.  
  571. LRESULT CALLBACK CContainedWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
  572.     LPARAM lParam)
  573. {
  574. #ifdef _M_IX86
  575.     __asm mov dword ptr[hWnd], ecx
  576. #endif
  577.     CContainedWindow* pT = (CContainedWindow*)hWnd;
  578.     _ASSERTE(pT->m_hWnd != NULL);
  579.     _ASSERTE(pT->m_pObject != NULL);
  580.  
  581.     LRESULT lRes;
  582.     if(pT->m_pObject->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, pT->m_dwMsgMapID))
  583.         return lRes;
  584.  
  585.     return pT->DefWindowProc(uMsg, wParam, lParam);
  586. }
  587.  
  588. ATOM CContainedWindow::RegisterWndSuperclass()
  589. {
  590.     ATOM atom = 0;
  591.     LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
  592.  
  593.     WNDCLASSEX wc;
  594.     wc.cbSize = sizeof(WNDCLASSEX);
  595.  
  596.     if(::GetClassInfoEx(NULL, m_lpszClassName, &wc))
  597.     {
  598.         m_pfnSuperWindowProc = wc.lpfnWndProc;
  599.  
  600.         wsprintf(szBuff, _T("ATL:%s"), m_lpszClassName);
  601.  
  602.         WNDCLASSEX wc1;
  603.         wc1.cbSize = sizeof(WNDCLASSEX);
  604.         atom = (ATOM)::GetClassInfoEx(_Module.GetModuleInstance(), szBuff, &wc1);
  605.  
  606.         if(atom == 0)   // register class
  607.         {
  608.             wc.lpszClassName = szBuff;
  609.             wc.lpfnWndProc = StartWindowProc;
  610.             wc.hInstance = _Module.GetModuleInstance();
  611.  
  612.             atom = ::RegisterClassEx(&wc);
  613.         }
  614.     }
  615.  
  616.     return atom;
  617. }
  618.  
  619. HWND CContainedWindow::Create(HWND hWndParent, RECT& rcPos,
  620.     LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, UINT nID)
  621. {
  622.     _ASSERTE(m_hWnd == NULL);
  623.  
  624.     ATOM atom = RegisterWndSuperclass();
  625.     if(atom == 0)
  626.         return NULL;
  627.  
  628.     _Module.AddCreateWndData(&m_thunk.cd, this);
  629.  
  630.     if(nID == 0 && (dwStyle & WS_CHILD))
  631.         nID = (UINT)this;
  632.  
  633.     HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  634.                             dwStyle,
  635.                             rcPos.left, rcPos.top,
  636.                             rcPos.right - rcPos.left,
  637.                             rcPos.bottom - rcPos.top,
  638.                             hWndParent, (HMENU)nID,
  639.                             _Module.GetModuleInstance(), this);
  640.  
  641.     _ASSERTE(m_hWnd == hWnd);
  642.     return hWnd;
  643. }
  644.  
  645. BOOL CContainedWindow::SubclassWindow(HWND hWnd)
  646. {
  647.     _ASSERTE(m_hWnd == NULL);
  648.     _ASSERTE(::IsWindow(hWnd));
  649.  
  650.     m_thunk.Init(WindowProc, this);
  651.     WNDPROC pProc = (WNDPROC)&m_thunk.thunk;
  652.     WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  653.     if(pfnWndProc == NULL)
  654.         return FALSE;
  655.     m_pfnSuperWindowProc = pfnWndProc;
  656.     m_hWnd = hWnd;
  657.     return TRUE;
  658. }
  659.  
  660. HWND CContainedWindow::UnsubclassWindow()
  661. {
  662.     _ASSERTE(m_hWnd != NULL);
  663.  
  664.     if(!::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfnSuperWindowProc))
  665.         return NULL;
  666.     m_pfnSuperWindowProc = ::DefWindowProc;
  667.  
  668.     HWND hWnd = m_hWnd;
  669.     m_hWnd = NULL;
  670.  
  671.     return hWnd;
  672. }
  673.  
  674. #ifndef ATL_NO_NAMESPACE
  675. }; //namespace ATL
  676. #endif
  677.  
  678. ///////////////////////////////////////////////////////////////////////////////
  679. //All Global stuff goes below this line
  680. ///////////////////////////////////////////////////////////////////////////////
  681.