home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OCCMGR.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-03  |  19.3 KB  |  734 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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. inline static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
  48. {
  49.     return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  50. }
  51.  
  52. inline static 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. inline static 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. static DLGITEMTEMPLATE* FindFirstDlgItem(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. static DLGITEMTEMPLATE* FindNextDlgItem(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 = FindFirstDlgItem(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 = FindNextDlgItem(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 = FindNextDlgItem(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. #ifndef _MAC
  389.             WORD nIDC = *lpnRes++;
  390.             WORD nMsg = *lpnRes++;
  391.             DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++;
  392. #else
  393.             // Unfortunately we can't count on these values being
  394.             // word-aligned (and dwLen is word-swapped besides), so
  395.             // we have to pull them out a byte at a time to avoid
  396.             // address errors on 68000s.
  397.             WORD nIDC;
  398.             WORD nMsg;
  399.             DWORD dwLen;
  400.  
  401.             memcpy(&nIDC, lpnRes++, sizeof(WORD));
  402.             memcpy(&nMsg, lpnRes++, sizeof(WORD));
  403.             memcpy((WORD*)&dwLen + 1, lpnRes++, sizeof(WORD));
  404.             memcpy(&dwLen, lpnRes++, sizeof(WORD));
  405. #endif
  406.             #define WIN16_LB_ADDSTRING  0x0401
  407.             #define WIN16_CB_ADDSTRING  0x0403
  408.  
  409.             ASSERT(nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING ||
  410.                 nMsg == WIN16_LB_ADDSTRING || nMsg == WIN16_CB_ADDSTRING ||
  411.                 nMsg == WM_OCC_LOADFROMSTREAM ||
  412.                 nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  413.                 nMsg == WM_OCC_LOADFROMSTORAGE ||
  414.                 nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
  415.                 nMsg == WM_OCC_INITNEW);
  416.  
  417.             if (nMsg == WM_OCC_LOADFROMSTREAM ||
  418.                 nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  419.                 nMsg == WM_OCC_LOADFROMSTORAGE ||
  420.                 nMsg == WM_OCC_LOADFROMSTORAGE_EX ||
  421.                 nMsg == WM_OCC_INITNEW)
  422.             {
  423.                 // Locate the DLGITEMTEMPLATE for the new control, and the control
  424.                 // that should precede it in z-order.
  425.                 DLGITEMTEMPLATE* pDlgItem;
  426.                 while (((pDlgItem = ppOleDlgItems[iItem++]) == NULL) &&
  427.                     (pDlgItem != (DLGITEMTEMPLATE*)(-1)))
  428.                 {
  429.                     if (hwAfter == HWND_TOP)
  430.                         hwAfter = GetWindow(hwParent, GW_CHILD);
  431.                     else
  432.                         hwAfter = GetWindow(hwAfter, GW_HWNDNEXT);
  433.  
  434.                     ASSERT(hwAfter != NULL);  // enough non-OLE controls?
  435.                 }
  436.  
  437.                 ASSERT(pDlgItem != NULL);   // enough dialog item templates?
  438.  
  439.                 HWND hwNew = NULL;
  440.                 if (pDlgItem != (DLGITEMTEMPLATE*)(-1))
  441.                 {
  442. #ifdef _DEBUG
  443.                     WORD id = bDialogEx ?
  444.                         (WORD)((DLGITEMTEMPLATEEX*)pDlgItem)->id :
  445.                         pDlgItem->id;
  446.                     ASSERT(id == nIDC); // make sure control IDs match!
  447. #endif
  448.  
  449.                     // Create the OLE control now.
  450.                     hwNew = CreateDlgControl(pWndParent, hwAfter, bDialogEx,
  451.                         pDlgItem, nMsg, (BYTE*)lpnRes, dwLen);
  452.                 }
  453.  
  454.                 if (hwNew != NULL)
  455.                 {
  456.                     if (GetParent(hwNew) == hwParent)
  457.                         hwAfter = hwNew;
  458.                 }
  459.                 else
  460.  
  461.                     bSuccess = FALSE;
  462.  
  463.             }
  464.  
  465.             // skip past data
  466.             lpnRes = (WORD*)((LPBYTE)lpnRes + (UINT)dwLen);
  467.         }
  468.     }
  469.  
  470.     if (bSuccess)
  471.     {
  472.         // unfreeze events now that all controls are loaded
  473.         if (pWndParent->m_pCtrlCont != NULL)
  474.             pWndParent->m_pCtrlCont->FreezeAllEvents(FALSE);
  475.  
  476.         BindControls(pWndParent);
  477.     }
  478.  
  479.     return bSuccess;
  480. }
  481.  
  482.  
  483. void COccManager::BindControls(CWnd* pWndParent)
  484. {
  485.     HWND hWnd;
  486.     COleControlSite* pSite;
  487.  
  488.     if (pWndParent->m_pCtrlCont != NULL)
  489.     {
  490.         // Now initialize bound controls
  491.         POSITION pos = pWndParent->m_pCtrlCont->m_siteMap.GetStartPosition();
  492.         while (pos != NULL)
  493.         {
  494.             pWndParent->m_pCtrlCont->m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  495.  
  496.             // For each cursor bound property initialize pClientSite ptr and bind to DSC
  497.             CDataBoundProperty* pBinding = pSite->m_pBindings;
  498.             while(pBinding)
  499.             {
  500.                 pBinding->SetClientSite(pSite);
  501.                 if (pBinding->m_ctlid != 0)
  502.                 {
  503.                     CWnd* pWnd = pWndParent->GetDlgItem(pBinding->m_ctlid);
  504.                     ASSERT(pWnd);
  505.                     ASSERT(pWnd->m_pCtrlSite);
  506.                     pBinding->SetDSCSite(pWnd->m_pCtrlSite);
  507.                 }
  508.                 pBinding = pSite->m_pBindings->GetNext();
  509.             }
  510.  
  511.             // Bind default bound property
  512.             if (pSite->m_ctlidRowSource != NULL)
  513.             {
  514.                 CWnd* pWnd = pWndParent->GetDlgItem(pSite->m_ctlidRowSource);
  515.                 ASSERT(pWnd);  // gotta be a legitimate control id
  516.                 ASSERT(pWnd->m_pCtrlSite);  // and it has to be an OLE Control
  517.  
  518.                 pWnd->m_pCtrlSite->EnableDSC();
  519.  
  520.                 ASSERT(pWnd->m_pCtrlSite->m_pDataSourceControl);  // and a Data Source Control
  521.                 pSite->m_pDSCSite = pWnd->m_pCtrlSite;
  522.                 pWnd->m_pCtrlSite->m_pDataSourceControl->BindProp(pSite);
  523.             }
  524.  
  525.         }
  526.  
  527.         // Finally, set up bindings on all DataSource controls
  528.         pos = pWndParent->m_pCtrlCont->m_siteMap.GetStartPosition();
  529.         while (pos != NULL)
  530.         {
  531.             pWndParent->m_pCtrlCont->m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  532.             if (pSite->m_pDataSourceControl)
  533.                 pSite->m_pDataSourceControl->BindColumns();
  534.         }
  535.     }
  536. }
  537.  
  538.  
  539. HWND COccManager::CreateDlgControl(CWnd* pWndParent, HWND hwAfter,
  540.     BOOL bDialogEx, LPDLGITEMTEMPLATE pItem, WORD nMsg, BYTE* lpData, DWORD cb)
  541. {
  542. #ifndef OLE2ANSI
  543.     LPWSTR pszClass = (LPWSTR)(pItem + 1);
  544. #else
  545.     LPSTR pszClass = (LPSTR)(pItem + 1);
  546. #endif
  547.     DLGITEMTEMPLATE dlgItemTmp;
  548.  
  549.     if (bDialogEx)
  550.     {
  551.         // We have an extended dialog template: copy relevant parts into an
  552.         // ordinary dialog template, because their layouts are different
  553.         DLGITEMTEMPLATEEX* pItemEx = (DLGITEMTEMPLATEEX*)pItem;
  554.         dlgItemTmp.style = pItemEx->style;
  555.         dlgItemTmp.dwExtendedStyle = pItemEx->exStyle;
  556.         dlgItemTmp.x = pItemEx->x;
  557.         dlgItemTmp.y = pItemEx->y;
  558.         dlgItemTmp.cx = pItemEx->cx;
  559.         dlgItemTmp.cy = pItemEx->cy;
  560.         dlgItemTmp.id = (WORD)pItemEx->id;
  561.         pItem = &dlgItemTmp;
  562. #ifndef OLE2ANSI
  563.         pszClass = (LPWSTR)(pItemEx + 1);
  564. #else
  565.         pszClass = (LPSTR)(pItemEx + 1);
  566. #endif
  567.     }
  568.  
  569.     CRect rect(pItem->x, pItem->y, pItem->x + pItem->cx, pItem->y + pItem->cy);
  570.     ::MapDialogRect(pWndParent->m_hWnd, &rect);
  571.  
  572.     BSTR bstrLicKey = NULL;
  573.  
  574.     // extract license key data, if any
  575.     if (cb >= sizeof(ULONG))
  576.     {
  577.         ULONG cchLicKey = *(UNALIGNED ULONG*)lpData;
  578.         lpData += sizeof(ULONG);
  579.         cb -= sizeof(ULONG);
  580.         if (cchLicKey > 0)
  581.         {
  582.             bstrLicKey = SysAllocStringLen((LPCOLESTR)lpData, cchLicKey);
  583.             lpData += cchLicKey * sizeof(WCHAR);
  584.             cb -= cchLicKey * sizeof(WCHAR);
  585.         }
  586.     }
  587.  
  588.     // If WM_OCC_INITNEW, we should have exhausted all of the data by now.
  589.     ASSERT((nMsg != WM_OCC_INITNEW) || (cb == 0));
  590.  
  591.     CDataBoundProperty* pBindings = NULL;
  592.     CString strDataField;
  593.     WORD ctlidRowSource = 0;
  594.     DISPID defdispid = 0;
  595.     UINT dwType = 0;
  596.  
  597.     if (nMsg == WM_OCC_LOADFROMSTREAM_EX ||
  598.         nMsg == WM_OCC_LOADFROMSTORAGE_EX)
  599.     {
  600.         // Read the size of the section
  601.         ULONG cbOffset = *(UNALIGNED ULONG*)lpData;
  602.         ULONG cbBindInfo = cbOffset - sizeof(DWORD);
  603.         lpData += sizeof(DWORD);
  604.  
  605.         ULONG dwFlags = *(UNALIGNED ULONG*)lpData;
  606.         cbBindInfo -= sizeof(DWORD);
  607.         lpData += sizeof(DWORD);
  608.         ASSERT(dwFlags == 1);
  609.  
  610.         ULONG cbBinding = *(UNALIGNED ULONG*)lpData;
  611.         cbBindInfo -= sizeof(DWORD);
  612.         lpData += sizeof(DWORD);
  613.  
  614.         while(cbBindInfo > 0)
  615.         {
  616.             DISPID dispid;
  617.             UWORD ctlid;
  618.  
  619.             dispid = *(UNALIGNED DISPID *)lpData;
  620.             lpData += sizeof(DISPID);
  621.             cbBindInfo -= sizeof(DISPID);
  622.             ctlid =  *(UNALIGNED WORD *)lpData;
  623.             lpData += sizeof(WORD);
  624.             cbBindInfo -= sizeof(WORD);
  625.  
  626.             if(dispid == DISPID_DATASOURCE)
  627.             {
  628.                 defdispid = *(UNALIGNED ULONG*)lpData;
  629.                 cbBindInfo -= sizeof(DISPID);
  630.                 lpData += sizeof(DISPID);
  631.                 dwType = *(UNALIGNED ULONG*)lpData;
  632.                 cbBindInfo -= sizeof(DWORD);
  633.                 lpData += sizeof(DWORD);
  634.  
  635.                 ASSERT(*(UNALIGNED DISPID *)lpData == DISPID_DATAFIELD);
  636.                 lpData += sizeof(DISPID);
  637.                 cbBindInfo -= sizeof(DISPID);
  638.                 // Skip the string length
  639.                 lpData += sizeof(DWORD);
  640.                 cbBindInfo -= sizeof(DWORD);
  641.                 strDataField = (char *)lpData;
  642.                 lpData += strDataField.GetLength()+1;
  643.                 cbBindInfo -= strDataField.GetLength()+1;
  644.                 ctlidRowSource = ctlid;
  645.             } else
  646.                 pBindings = new CDataBoundProperty(pBindings, dispid, ctlid);
  647.         }
  648.         cb -= cbOffset;
  649.  
  650.         // From now on act as a regular type
  651.         nMsg -= (WM_OCC_LOADFROMSTREAM_EX - WM_OCC_LOADFROMSTREAM);
  652.     }
  653.  
  654.     GUID clsid;
  655.     HRESULT hr;
  656. #ifndef OLE2ANSI
  657.     if (pszClass[0] == L'{')
  658. #else
  659.     if (pszClass[0] == '{')
  660. #endif
  661.         hr = CLSIDFromString(pszClass, &clsid);
  662.     else
  663.         hr = CLSIDFromProgID(pszClass, &clsid);
  664.  
  665. #ifdef _DEBUG
  666.     if (FAILED(hr))
  667.     {
  668. #ifndef OLE2ANSI
  669.         TRACE1("Unable to convert \"%ls\" to a class ID.\n", pszClass);
  670. #else
  671.         TRACE1("Unable to convert \"%s\" to a class ID.\n", pszClass);
  672. #endif
  673.         TRACE1(">>> Result code: 0x%08lx\n", hr);
  674.         if (pszClass[0] != L'{')
  675.             TRACE0(">>> Is the control properly registered?\n");
  676.     }
  677. #endif
  678.  
  679.     CMemFile memFile(lpData, cb);
  680.     CMemFile* pMemFile = (nMsg == WM_OCC_INITNEW) ? NULL : &memFile;
  681.  
  682.     CWnd* pWndNew = NULL;
  683.     COleControlSite* pSite = NULL;
  684.  
  685.     if (SUCCEEDED(hr) &&
  686.         pWndParent->InitControlContainer() &&
  687.         pWndParent->m_pCtrlCont->CreateControl(NULL, clsid, NULL, pItem->style,
  688.             rect, pItem->id, pMemFile, (nMsg == WM_OCC_LOADFROMSTORAGE),
  689.             bstrLicKey, &pSite))
  690.     {
  691.         ASSERT(pSite != NULL);
  692.  
  693.         // freeze events until all controls are loaded
  694.         pSite->FreezeEvents(TRUE);
  695.  
  696.         // set ZOrder only!
  697.         SetWindowPos(pSite->m_hWnd, hwAfter, 0, 0, 0, 0,
  698.             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  699.  
  700.         pSite->m_pBindings = pBindings;
  701.         pSite->m_strDataField = strDataField;
  702.         pSite->m_ctlidRowSource = ctlidRowSource;
  703.         pSite->m_defdispid = defdispid;
  704.         pSite->m_dwType = dwType;
  705.     }
  706.  
  707.     if (bstrLicKey != NULL)
  708.         SysFreeString(bstrLicKey);
  709.  
  710.     return (pSite != NULL) ? pSite->m_hWnd : NULL;
  711. }
  712.  
  713. /////////////////////////////////////////////////////////////////////////////
  714. // CDataExchange::PrepareOleCtrl
  715.  
  716. CWnd* CDataExchange::PrepareOleCtrl(int nIDC)
  717. {
  718.     ASSERT(nIDC != 0);
  719.     ASSERT(nIDC != -1); // not allowed
  720.     CWnd* pWndCtrl = m_pDlgWnd->GetDlgItem(nIDC);
  721.     if ((pWndCtrl == NULL) || (pWndCtrl->m_hWnd == NULL))
  722.     {
  723.         TRACE1("Error: no data exchange control with ID 0x%04X\n", nIDC);
  724.         ASSERT(FALSE);
  725.         AfxThrowNotSupportedException();
  726.     }
  727.     m_hWndLastControl = pWndCtrl->m_hWnd;
  728.     m_bEditLastControl = FALSE; // not an edit item by default
  729.     return pWndCtrl;
  730. }
  731.  
  732.  
  733. #endif //!_AFX_NO_OCC_SUPPORT
  734.