home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / occmgr.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  19KB  |  722 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #ifdef MACOCX
  13. #define DBINITCONSTANTS
  14. #endif
  15. #include "occimpl.h"
  16. #include "ocdb.h"
  17.  
  18. #ifdef AFX_OCC_SEG
  19. #pragma code_seg(AFX_OCC_SEG)
  20. #endif
  21.  
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. #define new DEBUG_NEW
  28.  
  29. #ifndef _AFX_NO_OCC_SUPPORT
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32. // AfxEnableControlContainer - wire up control container functions
  33.  
  34. PROCESS_LOCAL(COccManager, _afxOccManager)
  35.  
  36. void AFX_CDECL AfxEnableControlContainer(COccManager* pOccManager)
  37. {
  38.     if (pOccManager == NULL)
  39.         afxOccManager = _afxOccManager.GetData();
  40.     else
  41.         afxOccManager = pOccManager;
  42. }
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // Helper functions for cracking dialog templates
  46.  
  47. static inline BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
  48. {
  49.     return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  50. }
  51.  
  52. static inline WORD& DlgTemplateItemCount(DLGTEMPLATE* pTemplate)
  53. {
  54.     if (IsDialogEx(pTemplate))
  55.         return reinterpret_cast<DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
  56.     else
  57.         return pTemplate->cdit;
  58. }
  59.  
  60. static inline const WORD& DlgTemplateItemCount(const DLGTEMPLATE* pTemplate)
  61. {
  62.     if (IsDialogEx(pTemplate))
  63.         return reinterpret_cast<const DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
  64.     else
  65.         return pTemplate->cdit;
  66. }
  67.  
  68. AFX_STATIC DLGITEMTEMPLATE* AFXAPI _AfxFindFirstDlgItem(const DLGTEMPLATE* pTemplate)
  69. {
  70.     DWORD dwStyle = pTemplate->style;
  71.     BOOL bDialogEx = IsDialogEx(pTemplate);
  72.  
  73.     WORD* pw;
  74.     if (bDialogEx)
  75.     {
  76.         pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1);
  77.         dwStyle = ((DLGTEMPLATEEX*)pTemplate)->style;
  78.     }
  79.     else
  80.     {
  81.         pw = (WORD*)(pTemplate + 1);
  82.     }
  83.  
  84.     if (*pw == (WORD)-1)        // Skip menu name ordinal or string
  85.         pw += 2; // WORDs
  86.     else
  87.         while (*pw++);
  88.  
  89.     if (*pw == (WORD)-1)        // Skip class name ordinal or string
  90.         pw += 2; // WORDs
  91.     else
  92.         while (*pw++);
  93.  
  94.     while (*pw++);              // Skip caption string
  95.  
  96.     if (dwStyle & DS_SETFONT)
  97.     {
  98.         pw += bDialogEx ? 3 : 1;    // Skip font size, weight, (italic, charset)
  99.         while (*pw++);              // Skip font name
  100.     }
  101.  
  102.     // Dword-align and return
  103.     return (DLGITEMTEMPLATE*)(((DWORD)pw + 3) & ~3);
  104. }
  105.  
  106. AFX_STATIC DLGITEMTEMPLATE* AFXAPI _AfxFindNextDlgItem(DLGITEMTEMPLATE* pItem, BOOL bDialogEx)
  107. {
  108.     WORD* pw;
  109.  
  110.     if (bDialogEx)
  111.         pw = (WORD*)((DLGITEMTEMPLATEEX*)pItem + 1);
  112.     else
  113.         pw = (WORD*)(pItem + 1);
  114.  
  115.     if (*pw == (WORD)-1)            // Skip class name ordinal or string
  116.         pw += 2; // WORDs
  117.     else
  118.         while (*pw++);
  119.  
  120.     if (*pw == (WORD)-1)            // Skip text ordinal or string
  121.         pw += 2; // WORDs
  122.     else
  123.         while (*pw++);
  124.  
  125.     WORD cbExtra = *pw++;           // Skip extra data
  126.  
  127.     // Dword-align and return
  128.     return (DLGITEMTEMPLATE*)(((DWORD)pw + cbExtra + 3) & ~3);
  129. }
  130.  
  131. /////////////////////////////////////////////////////////////////////////////
  132. // COccManager
  133.  
  134. BOOL COccManager::OnEvent(CCmdTarget* pCmdTarget, UINT idCtrl,
  135.     AFX_EVENT* pEvent, AFX_CMDHANDLERINFO* pHandlerInfo)
  136. {
  137.     return pCmdTarget->OnEvent(idCtrl, pEvent, pHandlerInfo);
  138. }
  139.  
  140. COleControlContainer* COccManager::CreateContainer(CWnd* pWnd)
  141. {
  142.     // advanced control container apps may want to override
  143.     return new COleControlContainer(pWnd);
  144. }
  145.  
  146. COleControlSite* COccManager::CreateSite(COleControlContainer* pCtrlCont)
  147. {
  148.     // advanced control container apps may want to override
  149.     return new COleControlSite(pCtrlCont);
  150. }
  151.  
  152. const DLGTEMPLATE* COccManager::PreCreateDialog(_AFX_OCC_DIALOG_INFO* pDlgInfo,
  153.     const DLGTEMPLATE* pOrigTemplate)
  154. {
  155.     ASSERT(pDlgInfo != NULL);
  156.  
  157.     pDlgInfo->m_ppOleDlgItems =
  158.         (DLGITEMTEMPLATE**)malloc(sizeof(DLGITEMTEMPLATE*) *
  159.             (DlgTemplateItemCount(pOrigTemplate) + 1));
  160.  
  161.     if (pDlgInfo->m_ppOleDlgItems == NULL)
  162.         return NULL;
  163.  
  164.     DLGTEMPLATE* pNewTemplate = SplitDialogTemplate(pOrigTemplate,
  165.         pDlgInfo->m_ppOleDlgItems);
  166.     pDlgInfo->m_pNewTemplate = pNewTemplate;
  167.  
  168.     return (pNewTemplate != NULL) ? pNewTemplate : pOrigTemplate;
  169. }
  170.  
  171. void COccManager::PostCreateDialog(_AFX_OCC_DIALOG_INFO* pDlgInfo)
  172. {
  173.     if (pDlgInfo->m_pNewTemplate != NULL)
  174.         GlobalFree(pDlgInfo->m_pNewTemplate);
  175.  
  176.     if (pDlgInfo->m_ppOleDlgItems != NULL)
  177.         free(pDlgInfo->m_ppOleDlgItems);
  178. }
  179.  
  180. DLGTEMPLATE* COccManager::SplitDialogTemplate(const DLGTEMPLATE* pTemplate,
  181.     DLGITEMTEMPLATE** ppOleDlgItems)
  182. {
  183.     DLGITEMTEMPLATE* pFirstItem = _AfxFindFirstDlgItem(pTemplate);
  184.     ULONG cbHeader = (BYTE*)pFirstItem - (BYTE*)pTemplate;
  185.     ULONG cbNewTemplate = cbHeader;
  186.  
  187.     BOOL bDialogEx = IsDialogEx(pTemplate);
  188.  
  189.     int iItem;
  190.     int nItems = (int)DlgTemplateItemCount(pTemplate);
  191.     DLGITEMTEMPLATE* pItem = pFirstItem;
  192.     DLGITEMTEMPLATE* pNextItem = pItem;
  193. #ifndef OLE2ANSI
  194.     LPWSTR pszClassName;
  195. #else
  196.     LPSTR pszClassName;
  197. #endif
  198.     BOOL bHasOleControls = FALSE;
  199.  
  200.     // Make first pass through the dialog template.  On this pass, we're
  201.     // interested in determining:
  202.     //    1. Does this template contain any OLE controls?
  203.     //    2. If so, how large a buffer is needed for a template containing
  204.     //       only the non-OLE controls?
  205.  
  206.     for (iItem = 0; iItem < nItems; iItem++)
  207.     {
  208.         pNextItem = _AfxFindNextDlgItem(pItem, bDialogEx);
  209.  
  210.         pszClassName = bDialogEx ?
  211. #ifndef OLE2ANSI
  212.             (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  213.             (LPWSTR)(pItem + 1);
  214. #else
  215.             (LPSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  216.             (LPSTR)(pItem + 1);
  217. #endif
  218.  
  219. #ifndef OLE2ANSI
  220.         if (pszClassName[0] == L'{')
  221. #else
  222.         if (pszClassName[0] == '{')
  223. #endif
  224.         {
  225.             // Item is an OLE control.
  226.             bHasOleControls = TRUE;
  227.         }
  228.         else
  229.         {
  230.             // Item is not an OLE control: make room for it in new template.
  231.             cbNewTemplate += (BYTE*)pNextItem - (BYTE*)pItem;
  232.         }
  233.  
  234.         pItem = pNextItem;
  235.     }
  236.  
  237.     // No OLE controls were found, so there's no reason to go any further.
  238.     if (!bHasOleControls)
  239.     {
  240.         ppOleDlgItems[0] = (DLGITEMTEMPLATE*)(-1);
  241.         return NULL;
  242.     }
  243.  
  244.     // Copy entire header into new template.
  245.     BYTE* pNew = (BYTE*)GlobalAlloc(GMEM_FIXED, cbNewTemplate);
  246.     DLGTEMPLATE* pNewTemplate = (DLGTEMPLATE*)pNew;
  247.     memcpy(pNew, pTemplate, cbHeader);
  248.     pNew += cbHeader;
  249.  
  250.     // Initialize item count in new header to zero.
  251.     DlgTemplateItemCount(pNewTemplate) = 0;
  252.  
  253.     pItem = pFirstItem;
  254.     pNextItem = pItem;
  255.  
  256.     // Second pass through the dialog template.  On this pass, we want to:
  257.     //    1. Copy all the non-OLE controls into the new template.
  258.     //    2. Build an array of item templates for the OLE controls.
  259.  
  260.     for (iItem = 0; iItem < nItems; iItem++)
  261.     {
  262.         pNextItem = _AfxFindNextDlgItem(pItem, bDialogEx);
  263.  
  264.         pszClassName = bDialogEx ?
  265. #ifndef OLE2ANSI
  266.             (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  267.             (LPWSTR)(pItem + 1);
  268.  
  269.         if (pszClassName[0] == L'{')
  270. #else
  271.             (LPSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  272.             (LPSTR)(pItem + 1);
  273.  
  274.         if (pszClassName[0] == '{')
  275. #endif
  276.         {
  277.             // Item is OLE control: add it to the array.
  278.             ppOleDlgItems[iItem] = pItem;
  279.         }
  280.         else
  281.         {
  282.             // Item is not an OLE control: copy it to the new template.
  283.             ULONG cbItem = (BYTE*)pNextItem - (BYTE*)pItem;
  284.             ASSERT(cbItem >= (size_t)(bDialogEx ?
  285.                 sizeof(DLGITEMTEMPLATEEX) :
  286.                 sizeof(DLGITEMTEMPLATE)));
  287.             memcpy(pNew, pItem, cbItem);
  288.             pNew += cbItem;
  289.  
  290.             // Incrememt item count in new header.
  291.             ++DlgTemplateItemCount(pNewTemplate);
  292.  
  293.             // Put placeholder in OLE item array.
  294.             ppOleDlgItems[iItem] = NULL;
  295.         }
  296.  
  297.         pItem = pNextItem;
  298.     }
  299.     ppOleDlgItems[nItems] = (DLGITEMTEMPLATE*)(-1);
  300.  
  301.     return pNewTemplate;
  302. }
  303.  
  304. BOOL COccManager::CreateDlgControls(CWnd* pWndParent, LPCTSTR lpszResourceName,
  305.     _AFX_OCC_DIALOG_INFO* pOccDlgInfo)
  306. {
  307.     // find resource handle
  308.     void* lpResource = NULL;
  309.     HGLOBAL hResource = NULL;
  310.     if (lpszResourceName != NULL)
  311.     {
  312.         HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DLGINIT);
  313.         HRSRC hDlgInit = ::FindResource(hInst, lpszResourceName, RT_DLGINIT);
  314.         if (hDlgInit != NULL)
  315.         {
  316.             // load it
  317.             hResource = LoadResource(hInst, hDlgInit);
  318.             if (hResource == NULL)
  319.             {
  320.                 TRACE0("DLGINIT resource was found, but could not be loaded.\n");
  321.                 return FALSE;
  322.             }
  323.  
  324.             // lock it
  325.             lpResource = LockResource(hResource);
  326.             ASSERT(lpResource != NULL);
  327.         }
  328. #ifdef _DEBUG
  329.         else
  330.         {
  331.             // If we didn't find a DLGINIT resource, check whether we were
  332.             // expecting to find one
  333.             DLGITEMTEMPLATE** ppOleDlgItems = pOccDlgInfo->m_ppOleDlgItems;
  334.             ASSERT(ppOleDlgItems != NULL);
  335.  
  336.             while (*ppOleDlgItems != (DLGITEMTEMPLATE*)-1)
  337.             {
  338.                 if (*ppOleDlgItems != NULL)
  339.                 {
  340.                     TRACE0("Dialog has OLE controls, but no matching DLGINIT resource.\n");
  341.                     break;
  342.                 }
  343.                 ++ppOleDlgItems;
  344.             }
  345.         }
  346. #endif
  347.     }
  348.  
  349.     // execute it
  350.     BOOL bResult = TRUE;
  351.     if (lpResource != NULL)
  352.         bResult = CreateDlgControls(pWndParent, lpResource, pOccDlgInfo);
  353.  
  354.     // cleanup
  355.     if (lpResource != NULL && hResource != NULL)
  356.     {
  357.         UnlockResource(hResource);
  358.         FreeResource(hResource);
  359.     }
  360.  
  361.     return bResult;
  362. }
  363.  
  364. BOOL COccManager::CreateDlgControls(CWnd* pWndParent, void* lpResource,
  365.     _AFX_OCC_DIALOG_INFO* pOccDlgInfo)
  366. {
  367.     // if there are no OLE controls in this dialog, then there's nothing to do
  368.     if (pOccDlgInfo->m_pNewTemplate == NULL)
  369.         return TRUE;
  370.  
  371.     ASSERT(pWndParent != NULL);
  372.     HWND hwParent = pWndParent->GetSafeHwnd();
  373.  
  374.     BOOL bDialogEx = IsDialogEx(pOccDlgInfo->m_pNewTemplate);
  375.     BOOL bSuccess = TRUE;
  376.     if (lpResource != NULL)
  377.     {
  378.         ASSERT(pOccDlgInfo != NULL);
  379.         ASSERT(pOccDlgInfo->m_ppOleDlgItems != NULL);
  380.  
  381.         DLGITEMTEMPLATE** ppOleDlgItems = pOccDlgInfo->m_ppOleDlgItems;
  382.  
  383.         UNALIGNED WORD* lpnRes = (WORD*)lpResource;
  384.         int iItem = 0;
  385.         HWND hwAfter = HWND_TOP;
  386.         while (bSuccess && *lpnRes != 0)
  387.         {
  388.             WORD nIDC = *lpnRes++;
  389.             WORD nMsg = *lpnRes++;
  390.             DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
  391.  
  392.             #define WIN16_LB_ADDSTRING  0x0401
  393.             #define WIN16_CB_ADDSTRING  0x0403
  394.  
  395.             ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
  396.                 nMsg == WIN16_LB_ADDSTRING || nMsg == WIN16_CB_ADDSTRING ||
  397.                 nMsg == WM_OCC_LOADFROMSTREAM ||
  398.                 nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  399.                 nMsg == WM_OCC_LOADFROMSTORAGE ||
  400.                 nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
  401.                 nMsg == WM_OCC_INITNEW);
  402.  
  403.             if (nMsg == WM_OCC_LOADFROMSTREAM ||
  404.                 nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  405.                 nMsg == WM_OCC_LOADFROMSTORAGE ||
  406.                 nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
  407.                 nMsg == WM_OCC_INITNEW)
  408.             {
  409.                 // Locate the DLGITEMTEMPLATE for the new control, and the control
  410.                 // that should precede it in z-order.
  411.                 DLGITEMTEMPLATE* pDlgItem;
  412.                 while (((pDlgItem = ppOleDlgItems[iItem++]) == NULL) &&
  413.                     (pDlgItem != (DLGITEMTEMPLATE*)(-1)))
  414.                 {
  415.                     if (hwAfter == HWND_TOP)
  416.                         hwAfter = GetWindow(hwParent, GW_CHILD);
  417.                     else
  418.                         hwAfter = GetWindow(hwAfter, GW_HWNDNEXT);
  419.  
  420.                     ASSERT(hwAfter != NULL);  // enough non-OLE controls?
  421.                 }
  422.  
  423.                 ASSERT(pDlgItem != NULL);   // enough dialog item templates?
  424.  
  425.                 HWND hwNew = NULL;
  426.                 if (pDlgItem != (DLGITEMTEMPLATE*)(-1))
  427.                 {
  428. #ifdef _DEBUG
  429.                     WORD id = bDialogEx ?
  430.                         (WORD)((DLGITEMTEMPLATEEX*)pDlgItem)->id :
  431.                         pDlgItem->id;
  432.                     ASSERT(id == nIDC); // make sure control IDs match!
  433. #endif
  434.  
  435.                     // Create the OLE control now.
  436.                     hwNew = CreateDlgControl(pWndParent, hwAfter, bDialogEx,
  437.                         pDlgItem, nMsg, (BYTE*)lpnRes, dwLen);
  438.                 }
  439.  
  440.                 if (hwNew != NULL)
  441.                 {
  442.                     if (bDialogEx)
  443.                         SetWindowContextHelpId(hwNew,
  444.                             ((DLGITEMTEMPLATEEX*)pDlgItem)->helpID);
  445.                     if (GetParent(hwNew) == hwParent)
  446.                         hwAfter = hwNew;
  447.                 }
  448.                 else
  449.                     bSuccess = FALSE;
  450.             }
  451.  
  452.             // skip past data
  453.             lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
  454.         }
  455.     }
  456.  
  457.     if (bSuccess)
  458.     {
  459.         // unfreeze events now that all controls are loaded
  460.         if (pWndParent->m_pCtrlCont != NULL)
  461.             pWndParent->m_pCtrlCont->FreezeAllEvents(FALSE);
  462.  
  463.         BindControls(pWndParent);
  464.     }
  465.  
  466.     return bSuccess;
  467. }
  468.  
  469.  
  470. void COccManager::BindControls(CWnd* pWndParent)
  471. {
  472.     HWND hWnd;
  473.     COleControlSite* pSite;
  474.  
  475.     if (pWndParent->m_pCtrlCont != NULL)
  476.     {
  477.         // Now initialize bound controls
  478.         POSITION pos = pWndParent->m_pCtrlCont->m_siteMap.GetStartPosition();
  479.         while (pos != NULL)
  480.         {
  481.             pWndParent->m_pCtrlCont->m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  482.  
  483.             // For each cursor bound property initialize pClientSite ptr and bind to DSC
  484.             CDataBoundProperty* pBinding = pSite->m_pBindings;
  485.             if(pBinding)
  486.             {
  487.                 while(pBinding)
  488.                 {
  489.                     pBinding->SetClientSite(pSite);
  490.                     if (pBinding->m_ctlid != 0)
  491.                     {
  492.                         CWnd* pWnd = pWndParent->GetDlgItem(pBinding->m_ctlid);
  493.                         ASSERT(pWnd);
  494.                         ASSERT(pWnd->m_pCtrlSite);
  495.                         pBinding->SetDSCSite(pWnd->m_pCtrlSite);
  496.                     }
  497.                     pBinding = pSite->m_pBindings->GetNext();
  498.                 }
  499.             }
  500.  
  501.             // Bind default bound property
  502.             if (pSite->m_ctlidRowSource != NULL)
  503.             {
  504.                 CWnd* pWnd = pWndParent->GetDlgItem(pSite->m_ctlidRowSource);
  505.                 ASSERT(pWnd);  // gotta be a legitimate control id
  506.                 ASSERT(pWnd->m_pCtrlSite);  // and it has to be an OLE Control
  507.  
  508.                 pWnd->m_pCtrlSite->EnableDSC();
  509.  
  510.                 ASSERT(pWnd->m_pCtrlSite->m_pDataSourceControl);  // and a Data Source Control
  511.                 pSite->m_pDSCSite = pWnd->m_pCtrlSite;
  512.                 pWnd->m_pCtrlSite->m_pDataSourceControl->BindProp(pSite);
  513.             }
  514.         }
  515.  
  516.         // Finally, set up bindings on all DataSource controls
  517.         pos = pWndParent->m_pCtrlCont->m_siteMap.GetStartPosition();
  518.         while (pos != NULL)
  519.         {
  520.             pWndParent->m_pCtrlCont->m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  521.             if (pSite->m_pDataSourceControl)
  522.                 pSite->m_pDataSourceControl->BindColumns();
  523.         }
  524.     }
  525. }
  526.  
  527.  
  528. HWND COccManager::CreateDlgControl(CWnd* pWndParent, HWND hwAfter,
  529.     BOOL bDialogEx, LPDLGITEMTEMPLATE pItem, WORD nMsg, BYTE* lpData, DWORD cb)
  530. {
  531. #ifndef OLE2ANSI
  532.     LPWSTR pszClass = (LPWSTR)(pItem + 1);
  533. #else
  534.     LPSTR pszClass = (LPSTR)(pItem + 1);
  535. #endif
  536.     DLGITEMTEMPLATE dlgItemTmp;
  537.  
  538.     if (bDialogEx)
  539.     {
  540.         // We have an extended dialog template: copy relevant parts into an
  541.         // ordinary dialog template, because their layouts are different
  542.         DLGITEMTEMPLATEEX* pItemEx = (DLGITEMTEMPLATEEX*)pItem;
  543.         dlgItemTmp.style = pItemEx->style;
  544.         dlgItemTmp.dwExtendedStyle = pItemEx->exStyle;
  545.         dlgItemTmp.x = pItemEx->x;
  546.         dlgItemTmp.y = pItemEx->y;
  547.         dlgItemTmp.cx = pItemEx->cx;
  548.         dlgItemTmp.cy = pItemEx->cy;
  549.         dlgItemTmp.id = (WORD)pItemEx->id;
  550.         pItem = &dlgItemTmp;
  551. #ifndef OLE2ANSI
  552.         pszClass = (LPWSTR)(pItemEx + 1);
  553. #else
  554.         pszClass = (LPSTR)(pItemEx + 1);
  555. #endif
  556.     }
  557.  
  558.     CRect rect(pItem->x, pItem->y, pItem->x + pItem->cx, pItem->y + pItem->cy);
  559.     ::MapDialogRect(pWndParent->m_hWnd, &rect);
  560.  
  561.     BSTR bstrLicKey = NULL;
  562.  
  563.     // extract license key data, if any
  564.     if (cb >= sizeof(ULONG))
  565.     {
  566.         ULONG cchLicKey = *(UNALIGNED ULONG*)lpData;
  567.         lpData += sizeof(ULONG);
  568.         cb -= sizeof(ULONG);
  569.         if (cchLicKey > 0)
  570.         {
  571.             bstrLicKey = SysAllocStringLen((LPCOLESTR)lpData, cchLicKey);
  572.             lpData += cchLicKey * sizeof(WCHAR);
  573.             cb -= cchLicKey * sizeof(WCHAR);
  574.         }
  575.     }
  576.  
  577.     // If WM_OCC_INITNEW, we should have exhausted all of the data by now.
  578.     ASSERT((nMsg != WM_OCC_INITNEW) || (cb == 0));
  579.  
  580.     CDataBoundProperty* pBindings = NULL;
  581.     CString strDataField;
  582.     WORD ctlidRowSource = 0;
  583.     DISPID defdispid = 0;
  584.     UINT dwType = 0;
  585.  
  586.     if (nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  587.         nMsg == WM_OCC_LOADFROMSTORAGE_EX)
  588.     {
  589.         // Read the size of the section
  590.         ULONG cbOffset = *(UNALIGNED ULONG*)lpData;
  591.         ULONG cbBindInfo = cbOffset - sizeof(DWORD);
  592.         lpData += sizeof(DWORD);
  593.  
  594.         ULONG dwFlags = *(UNALIGNED ULONG*)lpData;
  595.         cbBindInfo -= sizeof(DWORD);
  596.         lpData += sizeof(DWORD);
  597.         ASSERT(dwFlags == 1);
  598.  
  599.         // ULONG cbBinding = *(UNALIGNED ULONG*)lpData;
  600.         cbBindInfo -= sizeof(DWORD);
  601.         lpData += sizeof(DWORD);
  602.  
  603.         while (cbBindInfo > 0)
  604.         {
  605.             DISPID dispid;
  606.             UWORD ctlid;
  607.  
  608.             dispid = *(UNALIGNED DISPID *)lpData;
  609.             lpData += sizeof(DISPID);
  610.             cbBindInfo -= sizeof(DISPID);
  611.             ctlid =  *(UNALIGNED WORD *)lpData;
  612.             lpData += sizeof(WORD);
  613.             cbBindInfo -= sizeof(WORD);
  614.  
  615.             if(dispid == DISPID_DATASOURCE)
  616.             {
  617.                 defdispid = *(UNALIGNED ULONG*)lpData;
  618.                 cbBindInfo -= sizeof(DISPID);
  619.                 lpData += sizeof(DISPID);
  620.                 dwType = *(UNALIGNED ULONG*)lpData;
  621.                 cbBindInfo -= sizeof(DWORD);
  622.                 lpData += sizeof(DWORD);
  623.  
  624.                 ASSERT(*(UNALIGNED DISPID *)lpData == DISPID_DATAFIELD);
  625.                 lpData += sizeof(DISPID);
  626.                 cbBindInfo -= sizeof(DISPID);
  627.                 // Skip the string length
  628.                 lpData += sizeof(DWORD);
  629.                 cbBindInfo -= sizeof(DWORD);
  630.                 strDataField = (char *)lpData;
  631.                 lpData += strDataField.GetLength()+1;
  632.                 cbBindInfo -= strDataField.GetLength()+1;
  633.                 ctlidRowSource = ctlid;
  634.             } else
  635.                 pBindings = new CDataBoundProperty(pBindings, dispid, ctlid);
  636.         }
  637.         cb -= cbOffset;
  638.  
  639.         // From now on act as a regular type
  640.         nMsg -= (WM_OCC_LOADFROMSTREAM_EX - WM_OCC_LOADFROMSTREAM);
  641.     }
  642.  
  643.     GUID clsid;
  644.     HRESULT hr;
  645. #ifndef OLE2ANSI
  646.     if (pszClass[0] == L'{')
  647. #else
  648.     if (pszClass[0] == '{')
  649. #endif
  650.         hr = CLSIDFromString(pszClass, &clsid);
  651.     else
  652.         hr = CLSIDFromProgID(pszClass, &clsid);
  653.  
  654. #ifdef _DEBUG
  655.     if (FAILED(hr))
  656.     {
  657. #ifndef OLE2ANSI
  658.         TRACE1("Unable to convert \"%ls\" to a class ID.\n", pszClass);
  659. #else
  660.         TRACE1("Unable to convert \"%s\" to a class ID.\n", pszClass);
  661. #endif
  662.         TRACE1(">>> Result code: 0x%08lx\n", hr);
  663.         if (pszClass[0] != L'{')
  664.             TRACE0(">>> Is the control properly registered?\n");
  665.     }
  666. #endif
  667.  
  668.     CMemFile memFile(lpData, cb);
  669.     CMemFile* pMemFile = (nMsg == WM_OCC_INITNEW) ? NULL : &memFile;
  670.  
  671.     COleControlSite* pSite = NULL;
  672.  
  673.     if (SUCCEEDED(hr) &&
  674.         pWndParent->InitControlContainer() &&
  675.         pWndParent->m_pCtrlCont->CreateControl(NULL, clsid, NULL, pItem->style,
  676.             rect, pItem->id, pMemFile, (nMsg == WM_OCC_LOADFROMSTORAGE),
  677.             bstrLicKey, &pSite))
  678.     {
  679.         ASSERT(pSite != NULL);
  680.  
  681.         // freeze events until all controls are loaded
  682.         pSite->FreezeEvents(TRUE);
  683.  
  684.         // set ZOrder only!
  685.         SetWindowPos(pSite->m_hWnd, hwAfter, 0, 0, 0, 0,
  686.             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  687.  
  688.         pSite->m_pBindings = pBindings;
  689.         pSite->m_strDataField = strDataField;
  690.         pSite->m_ctlidRowSource = ctlidRowSource;
  691.         pSite->m_defdispid = defdispid;
  692.         pSite->m_dwType = dwType;
  693.     }
  694.  
  695.     if (bstrLicKey != NULL)
  696.         SysFreeString(bstrLicKey);
  697.  
  698.     return (pSite != NULL) ? pSite->m_hWnd : NULL;
  699. }
  700.  
  701. /////////////////////////////////////////////////////////////////////////////
  702. // CDataExchange::PrepareOleCtrl
  703.  
  704. CWnd* CDataExchange::PrepareOleCtrl(int nIDC)
  705. {
  706.     ASSERT(nIDC != 0);
  707.     ASSERT(nIDC != -1); // not allowed
  708.     CWnd* pWndCtrl = m_pDlgWnd->GetDlgItem(nIDC);
  709.     if ((pWndCtrl == NULL) || (pWndCtrl->m_hWnd == NULL))
  710.     {
  711.         TRACE1("Error: no data exchange control with ID 0x%04X\n", nIDC);
  712.         ASSERT(FALSE);
  713.         AfxThrowNotSupportedException();
  714.     }
  715.     m_hWndLastControl = pWndCtrl->m_hWnd;
  716.     m_bEditLastControl = FALSE; // not an edit item by default
  717.     return pWndCtrl;
  718. }
  719.  
  720.  
  721. #endif //!_AFX_NO_OCC_SUPPORT
  722.