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 + -
显示快捷键?