mailset.cpp

来自「WIndows mobile 5.0 pocket pc sdk sample 」· C++ 代码 · 共 992 行 · 第 1/2 页

CPP
992
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// MAILSET.CPP
//
// Allows you to set properties on stores
//


#include <windows.h>
#include "cemapi.h"
#include "mapiutil.h"
#include "resource.h"
#include "macros.h"
#include "aygshell.h"
#include "msxml.h"


// Different types that we recognize from the XML:
//   0 = String
//   1 = Integer
//   2 = Boolean
typedef enum
{
    vtNone,
    vtInteger,
    vtBoolean,
    vtString
} VALUETYPE;


// Structure to hold information about a store property
//   pwszPropertyName - The name of the property (e.g. PR_CE_SIGNATURE)
//   ulPropTag - The numeric value of this property
//   pwszDisplayName - A friendly description of this property
//   pwszDefault - The default value to use if this property isn't in the store
//   vt - The type of property
//   pStore - A pointer to the store being modified or queried
typedef struct tagSTOREINFO
{
    TCHAR *pwszPropertyName;
    ULONG ulPropTag;
    TCHAR *pwszDisplayName;
    TCHAR *pwszDefault;
    VALUETYPE vt;
    IMsgStore *pStore;
} STOREINFO;

// XML Filename
const TCHAR *kszXMLFileName = TEXT("mailset.xml");

// Node names used in the XML
const TCHAR *kszMailSetNode = TEXT("mailset");
const TCHAR *kszStoreNode = TEXT("store");

// Attribute names used in the XML
const TCHAR *kszDisplay = TEXT("display");
const TCHAR *kszDefault = TEXT("default");
const TCHAR *kszType = TEXT("type");
const TCHAR *kszPropTag = TEXT("proptag");
const TCHAR *kszPropName = TEXT("propname");

// Globals
HINSTANCE g_hInst;



///////////////////////////////////////////////////////////////////////////////
//
// PathFindFileName
//
// Searches a path for a file name
//
// pszPath: IN parameter pointing to a null-terminated string that contains the path to search.
//
// Returns a pointer to the address of the string if successful, or a pointer to the beginning of the path otherwise.
//

LPTSTR PathFindFileName(LPCTSTR pszPath)
{
    UINT ichCurrent;
    const TCHAR *pch;

    ichCurrent = 0;
    pch = &pszPath[0];

    // Iterate through the entire string
    while (pszPath[ichCurrent])
    {
        // filename only if char after '\' is not end of path or another '\'
        if (pszPath[ichCurrent] == TEXT('\\') &&
            pszPath[ichCurrent + 1] &&
            pszPath[ichCurrent + 1] != TEXT('\\'))
        {
            pch = &pszPath[ichCurrent + 1];
        }
        ichCurrent++;
    }

    return (TCHAR*)pch;
}


///////////////////////////////////////////////////////////////////////////////
//
// GetXMLPathName
//
// Generate the XML PathName based on the current app directoy and a predefined XML filename
// 
// pszPath: IN parameter pointing to a buffer to hold the pathname of the xml file
// cMaxPath: IN parameter to the length of the buffer
//
// Returns BOOL
//

BOOL GetXMLPathName(LPTSTR pszPath, UINT cMaxPath)
{
    TCHAR *pszFileName;
    BOOL fSuccess;
    HRESULT hr;
    DWORD cch;

    ZeroMemory(pszPath, cMaxPath);

    // Assume failure until all steps are done
    fSuccess = FALSE;
    
    // Get the pathname of the exe
    cch = GetModuleFileName(NULL, pszPath, cMaxPath);
    CBR(cch != 0);

    // Get the directory that the exe is running from
    // pszFileName should not point to pszPath, if so it means the filename of the exe cannot be found; pszPath is invalid
    pszFileName = PathFindFileName(pszPath);
    CBR(pszFileName != pszPath);
        
    // Generate the pathname of the XML file
    *pszFileName = NULL;
    hr = StringCchCat(pszPath, cMaxPath, kszXMLFileName);
    CHR(hr);

    // All steps successful
    fSuccess = TRUE;

Error:
    return fSuccess;
}


///////////////////////////////////////////////////////////////////////////////
//
// FreeStores
//
// Frees the store pointers associated with the combobox
// 
// hwndCombo: IN parameter containing the window handle to the combobox that has the store names
//
// Returns HRESULT
//

HRESULT FreeStores(HWND hwndCombo)
{
    HRESULT hr = S_OK;
    IMsgStore *pStore;
    UINT cCombo;
    UINT i;

    // Loop through each element in the combobox
    cCombo = SendMessage(hwndCombo, CB_GETCOUNT, 0, 0);
    for (i = 0; i < cCombo; i++)
    {
        // The ITEMDATA is a pointer to the store (see AddStoreOptions)
        pStore = (IMsgStore *) SendMessage(hwndCombo, CB_GETITEMDATA, i, 0);
        RELEASE_OBJ(pStore)
    }
    
    return hr;
}


///////////////////////////////////////////////////////////////////////////////
//
// FreeStoreOptions
//
// Frees the STOREINFO associated with the combobox
// 
// hwndCombo: IN parameter containing the window handle to the combobox that has the STOREINFO
//
// Returns HRESULT
//

HRESULT FreeStoreOptions(HWND hwndCombo)
{
    HRESULT hr = S_OK;
    UINT cCombo;
    UINT i;
    STOREINFO *psi;

    // Loop through each element in the combobox
    cCombo = SendMessage(hwndCombo, CB_GETCOUNT, 0, 0);
    for (i = 0; i < cCombo; i++)
    {
        // Get the STOREINFO and free memory in this structure (see AddStoreOptions)
        psi = (STOREINFO *) SendMessage(hwndCombo, CB_GETITEMDATA, i, 0);
        delete [] psi->pwszPropertyName;
        delete [] psi->pwszDisplayName;
        delete [] psi->pwszDefault;
        delete psi;
    }

    return hr;
}


///////////////////////////////////////////////////////////////////////////////
//
// ReadNodeType
//
// This function will read in a type node and return the VALUETYPE corresponding to the node value
// 
// pNodeMap: IN parameter pointing to the node
// pszNodeName : IN parameter indicating the property to retrieve from the XML
//
// Returns VALUETYPE
//

VALUETYPE ReadNodeType(IXMLDOMNamedNodeMap *pNodeMap, TCHAR *pszNodeName)
{
    HRESULT hr;
    IXMLDOMNode *pAttribute = NULL;
    VARIANT vt;
    VALUETYPE vtRet = vtNone;

    // Get the appropriate attribute
    hr = pNodeMap->getNamedItem(pszNodeName, &pAttribute);
    CHR(hr);
    CBR(pAttribute != NULL);

    // Read the value from this attribute
    VariantInit(&vt);
    hr = pAttribute->get_nodeValue(&vt);
    CHR(hr);

    // The string should be 0 (string), 1 (integer), or 2 (boolean)
    // If it's not one of these, the return value will be vtNone
    if (!lstrcmp(vt.bstrVal, TEXT("0")))
    {
        vtRet = vtString;
    }
    else if (!lstrcmp(vt.bstrVal, TEXT("1")))
    {
        vtRet = vtInteger;
    }
    else if (!lstrcmp(vt.bstrVal, TEXT("2")))
    {
        vtRet = vtBoolean;
    }
    
Error:
    RELEASE_OBJ(pAttribute)

    VariantClear(&vt);

    return vtRet;
}


///////////////////////////////////////////////////////////////////////////////
//
// ReadNodeNumber
//
// This function will read in a type node and return the ULONG corresponding to the node value
// 
// pNodeMap: IN parameter pointing to the node
// pszNodeName : IN parameter indicating the property to retrieve from the XML
//
// Returns ULONG
//

ULONG ReadNodeNumber(IXMLDOMNamedNodeMap *pNodeMap, TCHAR *pszNodeName)
{
    HRESULT hr;
    IXMLDOMNode *pAttribute = NULL;
    VARIANT vt;
    ULONG ulRet = 0;

    // Get the appropriate attribute
    hr = pNodeMap->getNamedItem(pszNodeName, &pAttribute);
    CHR(hr);
    CBR(pAttribute != NULL);

    // Read the value of this attribute
    VariantInit(&vt);
    hr = pAttribute->get_nodeValue(&vt);
    CHR(hr);

    // Convert the string to a number
    ulRet = _ttoi(vt.bstrVal);

Error:
    RELEASE_OBJ(pAttribute)

    VariantClear(&vt);

    return ulRet;
}


///////////////////////////////////////////////////////////////////////////////
//
// ReadNodeString
//
// This function will read in a type node and return the string corresponding to the node value
// 
// pNodeMap: IN parameter pointing to the node
// pszNodeName : IN parameter indicating the property to retrieve from the XML
//
// Returns LPTSTR -- the caller must free this string
//

LPTSTR ReadNodeString(IXMLDOMNamedNodeMap *pNodeMap, TCHAR *pszNodeName)
{
    HRESULT hr;
    IXMLDOMNode *pAttribute = NULL;
    VARIANT vt;
    TCHAR *pszRet = NULL;
    size_t cch;
    

    // Get the appropriate attribute
    hr = pNodeMap->getNamedItem(pszNodeName, &pAttribute);
    CHR(hr);
    CBR(pAttribute != NULL);

    // Read the value of this attribute
    VariantInit(&vt);
    hr = pAttribute->get_nodeValue(&vt);
    CHR(hr);

    // Allocate memory and copy it
    hr = StringCchLength(vt.bstrVal, STRSAFE_MAX_CCH, &cch);
    CHR(hr);
    pszRet = new TCHAR[++cch];
    CPR(pszRet);
    StringCchCopy(pszRet, cch, vt.bstrVal);

Error:
    RELEASE_OBJ(pAttribute)

    VariantClear(&vt);

    return pszRet;
}


///////////////////////////////////////////////////////////////////////////////
//
// AddStoreOptions
//
// Reads in an XML document and populates a combobox with the value in that document
// The XML document has the following format:
// 
//     <store proptag="0x811A000B"
//            propname="PR_CE_USE_SIGNATURE"
//            display="Use the account signature"
//            default="0"
//            type="2"/>
//
// See the definition of the STOREINFO structure to see how these attributes map to our
// internal data structure.
// 
// hwndCombo: IN parameter containing the window handle of the combobox to populate
//
// Returns HRESULT
//

HRESULT AddStoreOptions(HWND hwndCombo)
{
    HRESULT hr = S_OK;
    STOREINFO *psi = NULL;
    LRESULT lr;
    IXMLDOMDocument *pDOM = NULL;
    IXMLDOMNode *pMailNode = NULL;
    IXMLDOMNode *pNode = NULL;
    IXMLDOMNode *pSibling = NULL;
    IXMLDOMNamedNodeMap *pNodeMap = NULL;
    VARIANT_BOOL fSuccess;
    VARIANT vt;
    TCHAR szPath[MAX_PATH];
    BSTR bstrName = NULL;
    CLSID clsid;
    
    // Load the XML DOM
    hr = CLSIDFromProgID(TEXT("Msxml2.DOMDocument"), &clsid);
    CHR(hr);
    hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (LPVOID *) &pDOM);
    CHR(hr);

    // Get the xml pathname
    fSuccess = GetXMLPathName(szPath, MAX_PATH);
    CBR(fSuccess);

    // Load the mailset xml file
    vt.vt = VT_BSTR;
    vt.bstrVal = SysAllocString(szPath);
    hr = pDOM->load(vt, &fSuccess);
    CHR(hr);
    CBR(fSuccess);

    // Find the mailset node
    hr = pDOM->selectSingleNode((TCHAR *) kszMailSetNode, &pMailNode);
    CHR(hr);

    // Walk the children of this node -- each top-level child will be a single store property
    hr = pMailNode->get_firstChild(&pNode);
    CHR(hr);

    while (pNode)
    {
        hr = pNode->get_nodeName(&bstrName);
        CHR(hr);

        // We only care about Store nodes -- skip this node if it's not a store node
        if (!lstrcmpi(bstrName, kszStoreNode))
        {
            // Create a STOREINFO structure.  This will be used to store information
            // about this node in memory.  It will be the ITEMDATA stored with this entry in the combobox
            // and will need to be freed when the combobox is destroyed
            psi = new STOREINFO;
            CPR(psi);
            ZeroMemory(psi, sizeof(STOREINFO));

            // Load in any attributes on this node
            RELEASE_OBJ(pNodeMap)

            hr = pNode->get_attributes(&pNodeMap);
            CHR(hr);

            // Make sure the proptag and property description values are present
            psi->pwszPropertyName = ReadNodeString(pNodeMap, (TCHAR *) kszPropName);
            psi->ulPropTag = ReadNodeNumber(pNodeMap, (TCHAR *) kszPropTag);
            CBR((psi->pwszPropertyName != NULL) && (psi->ulPropTag != 0));

            // Display name and default value are mandatory
            psi->pwszDisplayName = ReadNodeString(pNodeMap, (TCHAR *) kszDisplay);
            CBR(psi->pwszDisplayName != NULL);
            psi->pwszDefault = ReadNodeString(pNodeMap, (TCHAR *) kszDefault);
            CBR(psi->pwszDefault != NULL);

            // Type is mandatory too
            psi->vt = ReadNodeType(pNodeMap, (TCHAR *) kszType);
            CBR(psi->vt != vtNone);
            
            // Now, add this to our combobox
            lr = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) psi->pwszPropertyName);
            CBR(lr >= 0);
            SendMessage(hwndCombo, CB_SETITEMDATA, lr, (LPARAM) psi);

            // Reset psi to NULL so it isn't freed (owned by combobox now)
            psi = NULL;
        }

        SysFreeString(bstrName);

        // Go to the next top-level node
        hr = pNode->get_nextSibling(&pSibling);
        CHR(hr);
        
        pNode->Release();
        pNode = pSibling;
    }
        
    // Set focus on the first item in the combobox
    SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
    
Error:
    if (psi)
    {
        // Free it up
        delete [] psi->pwszPropertyName;
        delete [] psi->pwszDisplayName;
        delete [] psi->pwszDefault;
        delete psi;
    }

⌨️ 快捷键说明

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