DlgTemplate.cpp
上传用户:kj0090
上传日期:2007-03-02
资源大小:39k
文件大小:16k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /***********************************************************************
  2. *
  3. * This module is part of the XMLGUI system 
  4. *
  5. * File name:       DlgTemplate.cpp
  6. *
  7. * Creation date:   [12 AUGUST 2002] 
  8. *
  9. * Author(s):       [Kolosenko Ruslan]
  10. *
  11. * Description:     Implements the class CDlgTemplate
  12. *
  13. **********************************************************************/
  14. #include "stdafx.h"
  15. #include "DlgTemplate.h"
  16. #include "XMLIterator.h"
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[]=__FILE__;
  20. #define new DEBUG_NEW
  21. #endif
  22. //////////////////////////////////////////////////////////////////////
  23. // Construction/Destruction
  24. //////////////////////////////////////////////////////////////////////
  25. /**************************************************************************
  26. * Function     : CDlgTemplate::CDlgTemplate
  27. * Description  : Constructor
  28. ***************************************************************************/
  29. CDlgTemplate::CDlgTemplate()
  30. {
  31.     m_hGlobalTemplate = NULL;
  32.     m_pInitData       = NULL;
  33. }
  34. /**************************************************************************
  35. * Function     : CDlgTemplate::~CDlgTemplate
  36. * Description  : Destructor
  37. ***************************************************************************/
  38. CDlgTemplate::~CDlgTemplate()
  39. {
  40.     Invalidate();   // free any previously allocated memory
  41. }
  42. /**************************************************************************
  43. * Function     : CDlgTemplate::operator LPDLGTEMPLATE
  44. * Description  : Converts CDlgTemplate object to Win32 DLGTEMPLATE structure
  45. *              : allocates memory and initializes it with values of dialog
  46. *              : template fields
  47. * Return value : pointer to the allocated memory holding DLGTEMPLATE structure
  48. * CAUTION      : zero may be returned, which indicates structure building failure
  49. ***************************************************************************/
  50. CDlgTemplate::operator LPDLGTEMPLATE()
  51. {
  52.     if ( m_hGlobalTemplate )
  53.     {
  54.            // if the memory was already allocated and it is not invalidated yet
  55.            // we do not reallocate memory but return pointer to the old memory
  56.         LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)::GlobalLock(m_hGlobalTemplate);
  57.         ::GlobalUnlock(m_hGlobalTemplate);   // to restore memory lock counter
  58.         return lpTemplate;
  59.     }
  60.     m_hGlobalTemplate = ::GlobalAlloc(GMEM_ZEROINIT,Length());  // allocate memory
  61.     LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)::GlobalLock(m_hGlobalTemplate);
  62.     if ( !lpTemplate )
  63.     {
  64.         TRACE(_T("nCannot allocate memory for DLGTEMPLATE"));
  65.         return NULL;
  66.     }
  67.     // now, fill the allocated buffer with the dialog template
  68.     // first we fill all static length fields except cdit, it will be filled later
  69.     lpTemplate->style = style;
  70.     lpTemplate->dwExtendedStyle = dwExtendedStyle;
  71.     lpTemplate->x = x;
  72.     lpTemplate->y = y;
  73.     lpTemplate->cx = cx;
  74.     lpTemplate->cy = cy;
  75.        // and now copy all variable length fields to the buffer
  76.     LPBYTE pToWrite = (LPBYTE)lpTemplate + sizeof(DLGTEMPLATE);   // pointer to
  77.                               // the current byte in the structure being filled,
  78.         // start copying from the next byte after the structure's static fields
  79.        // store menu name for the dialog
  80.     if ( m_nMenuID )
  81.     {
  82.            // if menu ID is specified by an ordinal - in the template it looks like
  83.            // ... FF FF <WORD value> ...
  84.         *((LPWORD)pToWrite) = 0xFFFF;
  85.         *((LPWORD)pToWrite+1) = m_nMenuID;
  86.         pToWrite += 4;    // two words were written to the template
  87.     }
  88.     else
  89.     {
  90.         int nSizeOfMenuString = 2*m_strMenuName.length(); // length of the UNICODE
  91.                 // string without trailing 0 that will be built from m_strMenuName
  92.         if ( !!m_strMenuName )   // copy UNICODE string if not empty
  93.         {
  94.             memcpy(pToWrite,(const wchar_t*)m_strMenuName,nSizeOfMenuString);
  95.         }
  96.         *((LPWORD)(pToWrite+nSizeOfMenuString)) = 0;   // add trailing zero
  97.         pToWrite += nSizeOfMenuString+2;   // nSizeOfMenuString+2 bytes were written
  98.     }
  99.        // store dialog's window class name
  100.     if ( m_nWndClassOrdinal )
  101.     {
  102.         // if window class is specified by an ordinal - in the template it looks like
  103.         // ... FF FF <WORD value> ...
  104.         *((LPWORD)pToWrite) = 0xFFFF;
  105.         *((LPWORD)pToWrite+1) = m_nWndClassOrdinal;
  106.         pToWrite += 4;    // two words were written to the template
  107.     }
  108.     else
  109.     {
  110.         int nSizeOfClassString = 2*m_strWndClass.length(); // length of the UNICODE
  111.                                                         // built from m_strWndClass
  112.         if ( !!m_strWndClass )
  113.         {
  114.             memcpy(pToWrite,(const wchar_t*)m_strWndClass,nSizeOfClassString);
  115.         }
  116.         *((LPWORD)(pToWrite+nSizeOfClassString)) = 0;
  117.         pToWrite += nSizeOfClassString+2;
  118.     }
  119.     
  120.        // store title of the dialog's window
  121.     int nSizeOfTitleString = 2*m_strTitle.length();
  122.     if ( !!m_strTitle )
  123.     {
  124.         memcpy(pToWrite,(const wchar_t*)m_strTitle,nSizeOfTitleString);
  125.     }
  126.     *((LPWORD)(pToWrite+nSizeOfTitleString)) = 0;
  127.     pToWrite += nSizeOfTitleString+2;
  128.     if ( style & DS_SETFONT )   // fill font size and typeface name only if the dialog
  129.                                 // has style DS_SETFONT
  130.     {
  131.            // store font size
  132.         *((LPWORD)pToWrite) = m_nFontSize;
  133.         pToWrite += 2;  // two bytes were written
  134.            // store font's typeface name
  135.         int nSizeOfFontString = 2*m_strFontTypeface.length();
  136.         if ( !!m_strFontTypeface )
  137.         {
  138.             memcpy(pToWrite,(const wchar_t*)m_strFontTypeface,nSizeOfFontString);
  139.         }
  140.         *((LPWORD)(pToWrite+nSizeOfFontString)) = 0;
  141.         pToWrite += nSizeOfFontString+2;
  142.     }
  143.        // skip bytes allocated for DWORD alignment
  144.     pToWrite += (UINT)pToWrite%4 ? 4-(UINT)pToWrite%4 : 0;
  145.        // append DLGITEMTEMPLATE structure for each control to the dialog template
  146.     UINT nItemTemplateSize = 0;
  147.     for ( int i = 0; i < cdit(); i++ )
  148.     {
  149.         nItemTemplateSize = controls[i].FillBuffer(pToWrite);
  150.         pToWrite += nItemTemplateSize;   // shift write pointer to the next position
  151.         if ( nItemTemplateSize )
  152.         {
  153.             lpTemplate->cdit++;    // increase cdit field for valid controls only
  154.         }
  155.     }
  156.        // DLGTEMPLATE structure has been filled successfully
  157.     return lpTemplate;
  158. }
  159. /**************************************************************************
  160. * Function     : CDlgTemplate::Length
  161. * Description  : Calculates number of bytes necessary to store Win32 DLGTEMPLATE
  162. *              : structure holding all dialog template's data
  163. * Return value : number of bytes calculated
  164. ***************************************************************************/
  165. UINT CDlgTemplate::Length()
  166. {
  167. UINT nLen = sizeof(DLGTEMPLATE);   // all static length fields
  168.     nLen += m_nMenuID ? 4 : 2*(1+m_strMenuName.length()); // 4 bytes for menu
  169.                                 // ordinal if any, or length of the menu name
  170.                                     // ( 1+ for trailing 0 , 2* for UNICODE )
  171.     nLen += m_nWndClassOrdinal ? 4 : 2*(1+m_strWndClass.length());    // 4 bytes
  172.               // for class ordinal value if any, or length of the UNICODE string 
  173.                                //with trailing zero containing window class name
  174.     nLen += 2*(1+m_strTitle.length());   // length of the UNICODE string
  175.             // with trailing 0 containing the title of the dialog window
  176.     if ( style & DS_SETFONT )    // font size and typeface name are included 
  177.                 // into the DLGTEMPLATE structure only if dialog has DS_SETFONT style
  178.     {
  179.         nLen += 2 + 2*(1+m_strFontTypeface.length());   // 2 bytes for the font size
  180.                // value plus the length of the UNICODE string with the typeface name
  181.     }
  182.     nLen += nLen%4 ? 4-nLen%4 : 0;    // align on a DWORD boundary,
  183.                                       // nLen must be aliqout of 4
  184.     for ( int i = 0; i < cdit(); i++ )
  185.     {
  186.         nLen += controls[i].Length();   // add to this all DLGITEMTEMPLATE's lengths
  187.     }
  188.     return nLen;
  189. }
  190. /**************************************************************************
  191. * Function     : CDlgTemplate::GetInitData
  192. * Description  : Allocates memory and initializes it with dialog init data
  193. *              : section used for creating dialog controls
  194. * Return value : pointer to the allocated memory holding init data section
  195. *              : or zero if no init data required for the dialog's controls
  196. ***************************************************************************/
  197. LPVOID CDlgTemplate::GetInitData()
  198. {
  199. if ( m_pInitData )
  200.     {
  201.            // if the memory was already allocated and it is not invalidated yet
  202.            // we just return pointer to the old memory
  203.         return m_pInitData;
  204.     }
  205.     UINT nInitDataLen = InitDataLength();   // get the required number of bytes
  206.     if ( !nInitDataLen )
  207.     {
  208.         return NULL;   // if no init data required for any control - return NULL
  209.     }
  210.     m_pInitData = malloc(nInitDataLen + 2);   // allocate new memory,
  211.                                   // + 2 is here for terminating zero
  212.        // write init data section for each control to the allocated memory
  213.     LPBYTE pToWrite    = (LPBYTE)m_pInitData;
  214.     UINT nInitDataSize = 0;
  215.     for ( int i = 0; i < cdit(); i++ )
  216.     {
  217.         nInitDataSize = controls[i].FillInitDataBuffer(pToWrite);
  218.         pToWrite += nInitDataSize;   // shift write pointer to the next position
  219.     }
  220.     *((LPWORD)pToWrite) = 0;   // append terminating zero
  221.     return m_pInitData;
  222. }
  223. /**************************************************************************
  224. * Function     : CDlgTemplate::InitDataLength
  225. * Description  : Calculates number of bytes necessary to store init data
  226. *              : section holding dialog control's initialization data
  227. *              : excluding terminating zero
  228. * Return value : number of bytes calculated,
  229. *              : excluding 2 bytes for terminating zero
  230. ***************************************************************************/
  231. UINT CDlgTemplate::InitDataLength()
  232. {
  233.     UINT nLen = 0;   // dialog itself doesn't have its own init data
  234.        // we just calculate sum of the init data section for each control
  235. for ( int i = 0; i < cdit(); i++ )
  236.     {
  237.         nLen += controls[i].InitDataLength();
  238.     }
  239.     return nLen;
  240. }
  241. /**************************************************************************
  242. * Function     : CDlgTemplate::SerializeFrom(LPCTSTR)
  243. * Description  : Initializes CDlgTemplate object from XML file with XML-style
  244. *              : dialog template
  245. * Return value : nonzero if XML parsing is successful, otherwise zero
  246. * Arguments    : szXMLFile - pointer to a string with the name of XML file
  247. *              :    containing XML-style template for dialog
  248. ***************************************************************************/
  249. BOOL CDlgTemplate::SerializeFrom(LPCTSTR szXMLFile)
  250. {
  251.     try   // watch possible CXMLParsingException
  252.     {
  253.            // construct CXMLTag object for root <DIALOG> tag in the XML file
  254.         CXMLDialogTag xmlDialog(szXMLFile);
  255.            // serialize dialog template fields from the XML tag
  256.         return SerializeFrom(xmlDialog);
  257.     }
  258.     catch ( const CXMLParsingException& excp )
  259.     {
  260.         TRACE(excp.GetDescription());
  261.         return FALSE;
  262.     }
  263. }
  264. /**************************************************************************
  265. * Function     : CDlgTemplate::SerializeFrom(IXMLElement*)
  266. * Description  : Initializes CDlgTemplate object from XML tag pointer
  267. *              : describing dialog template
  268. * Return value : nonzero if XML parsing is successful, otherwise zero
  269. * Arguments    : pXMLTag - pointer to the COM interface of the XML element
  270. *              :    which contains XML-style template for dialog
  271. ***************************************************************************/
  272. BOOL CDlgTemplate::SerializeFrom(IXMLElement* pXMLTag)
  273. {
  274.     try   // watch possible CXMLParsingException
  275.     {
  276.            // construct CXMLDialogTag object from the COM interface pointer
  277.         CXMLDialogTag xmlDialog(pXMLTag);
  278.         
  279.            // check validity of the tag, naturally compare the tag name with "DIALOG"
  280.         if ( !CXMLDialogTag::IsTypeValid(xmlDialog) )
  281.         {
  282.             TRACE(_T("nXML file with dialog template is not valid. Serialization failed."));
  283.             return FALSE;
  284.         }
  285.         
  286.            // fill all properties of the dialog template from the XML
  287.         style = xmlDialog.GetStyles();
  288.         dwExtendedStyle = xmlDialog.GetExStyles();
  289.         x = (short)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_LEFT);
  290.         y = (short)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_TOP);
  291.         cx = (short)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_WIDTH);
  292.         cy = (short)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_HEIGHT);
  293.         m_strTitle = xmlDialog.GetAttributeString(ATTRIBUTE_DIALOG_CAPTION);
  294.         m_nMenuID = (WORD)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_MENU);
  295.         if ( !m_nMenuID )  // if menu not specified by ordinal number -
  296.         {                  // try to interpret the XML attribute as menu name
  297.             m_strMenuName = xmlDialog.GetAttributeString(ATTRIBUTE_DIALOG_MENU);
  298.         }
  299.         m_nWndClassOrdinal = (WORD)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_CLASS);
  300.         if ( !m_nWndClassOrdinal )  // if class ordinal value not specified -
  301.         {                           // try to extract from XML attribute the class name
  302.             m_strWndClass = xmlDialog.GetAttributeString(ATTRIBUTE_DIALOG_CLASS);
  303.         }
  304.         m_nFontSize = (WORD)xmlDialog.GetAttributeInt(ATTRIBUTE_DIALOG_FONTSIZE);
  305.         m_strFontTypeface = xmlDialog.GetAttributeString(ATTRIBUTE_DIALOG_FONTNAME);
  306.         
  307.            // now we fill controls array
  308.         controls.RemoveAll();   // remove all previously written entries if any
  309.         
  310.            // iterate through all <CONTROL> tags within the root <DIALOG> tag
  311.         CXMLControlIterator iControl(xmlDialog);
  312.         for ( iControl.Begin(); !iControl.AtEnd(); ++iControl )
  313.         {
  314.                // temporary CDlgItemTemplate object to be filled and added to controls array
  315.             CDlgItemTemplate control;
  316.                // temporary CXMLTag object for retrieving XML attribute values
  317.             CXMLControlTag xmlControl(*iControl);
  318.             
  319.                // fill all control's properties from the XML
  320.             control.SerializeFrom(xmlControl);
  321.             
  322.                // add the built dialog item template to the controls array
  323.             *this += control;
  324.         }
  325.         
  326.            // dialog template object was successfully initialized from XML
  327.         return TRUE;
  328.     }
  329.     catch ( const CXMLParsingException& excp )
  330.     {
  331.         TRACE(excp.GetDescription());
  332.         return FALSE;
  333.     }
  334. }
  335. /**************************************************************************
  336. * Function     : CDlgTemplate::Invalidate
  337. * Description  : Discards any memory that was allocated in previous calls to
  338. *              : the operator LPDLGTEMPLATE, the next call to this operator
  339. *              : will allocate a new memory and build a new DLGTEMPLATE structure
  340. * CAUTION      : all LPDLGTEMPLATE pointers that were previously obtained
  341. *              : through calls to operator LPDLGTEMPLATE become invalid
  342. *              : and should not be used
  343. ***************************************************************************/
  344. void CDlgTemplate::Invalidate()
  345. {
  346.     if ( m_hGlobalTemplate )
  347.     {
  348.         ::GlobalUnlock(m_hGlobalTemplate);   // free any previously allocated
  349.         ::GlobalFree(m_hGlobalTemplate);     // memory and set m_hGlobalTemplate
  350.         m_hGlobalTemplate = NULL;     // to NULL allowing next memory allocation       
  351.     }
  352.     if ( m_pInitData )
  353.     {
  354.         free(m_pInitData);    // free memory holding init data section as well
  355.         m_pInitData = NULL;   // and set pointer to NULL allowing next allocation
  356.     }
  357. }