CoInitialize required in MFC app on XP but not Vista/Win7? - web-services

I have written a SOAP Web Service that I'm trying to consume from an MFC application. The MFC application was not generated with ActiveX control support or Automation. When I run the MFC application from Vista or Win7, there's no problem accessing the Web Service. When I run the MFC application from XP (SP3), the Web Service call fails with 0x800401F0 CO_E_NOTINITIALIZED "CoInitialize has not been called". Calling CoInitialize(NULL) fixes the XP problem.
Why is the MFC app in XP behaving differently than Vista/Win7 in this case?
EDIT2: Auto-generated web service access code added
net_webservicexwww.h
//
// sproxy.exe generated file
// do not modify this file
//
// Created: 08/15/2013#13:09:29
//
#pragma once
#if !defined(_WIN32_WINDOWS) && !defined(_WIN32_WINNT) && !defined(_WIN32_WCE)
#pragma message("warning: defining _WIN32_WINDOWS = 0x0410")
#define _WIN32_WINDOWS 0x0410
#endif
#include <atlsoap.h>
namespace USZip
{
template <typename TClient = CSoapSocketClientT<> >
class CUSZipT :
public TClient,
public CSoapRootHandler
{
protected:
const _soapmap ** GetFunctionMap();
const _soapmap ** GetHeaderMap();
void * GetHeaderValue();
const wchar_t * GetNamespaceUri();
const char * GetServiceName();
const char * GetNamespaceUriA();
HRESULT CallFunction(
void *pvParam,
const wchar_t *wszLocalName, int cchLocalName,
size_t nItem);
HRESULT GetClientReader(ISAXXMLReader **ppReader);
public:
HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
{
if (ppv == NULL)
{
return E_POINTER;
}
*ppv = NULL;
if (InlineIsEqualGUID(riid, IID_IUnknown) ||
InlineIsEqualGUID(riid, IID_ISAXContentHandler))
{
*ppv = static_cast<ISAXContentHandler *>(this);
return S_OK;
}
return E_NOINTERFACE;
}
ULONG __stdcall AddRef()
{
return 1;
}
ULONG __stdcall Release()
{
return 1;
}
CUSZipT(ISAXXMLReader *pReader = NULL)
:TClient(_T("http://www.webservicex.net/uszip.asmx"))
{
SetClient(true);
SetReader(pReader);
}
~CUSZipT()
{
Uninitialize();
}
void Uninitialize()
{
UninitializeSOAP();
}
HRESULT GetInfoByAreaCode(
BSTR USAreaCode,
BSTR* GetInfoByAreaCodeResult
);
HRESULT GetInfoByCity(
BSTR USCity,
BSTR* GetInfoByCityResult
);
HRESULT GetInfoByState(
BSTR USState,
BSTR* GetInfoByStateResult
);
HRESULT GetInfoByZIP(
BSTR USZip,
BSTR* GetInfoByZIPResult
);
};
typedef CUSZipT<> CUSZip;
struct __CUSZip_GetInfoByAreaCode_struct
{
BSTR USAreaCode;
BSTR GetInfoByAreaCodeResult;
};
extern __declspec(selectany) const _soapmapentry __CUSZip_GetInfoByAreaCode_entries[] =
{
{
0x529BE19C,
"USAreaCode",
L"USAreaCode",
sizeof("USAreaCode")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_IN | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByAreaCode_struct, USAreaCode),
NULL,
NULL,
-1,
},
{
0xCB1A9C5A,
"GetInfoByAreaCodeResult",
L"GetInfoByAreaCodeResult",
sizeof("GetInfoByAreaCodeResult")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_OUT | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByAreaCode_struct, GetInfoByAreaCodeResult),
NULL,
NULL,
-1,
},
{ 0x00000000 }
};
extern __declspec(selectany) const _soapmap __CUSZip_GetInfoByAreaCode_map =
{
0xFBDA3B2A,
"GetInfoByAreaCode",
L"GetInfoByAreaCodeResponse",
sizeof("GetInfoByAreaCode")-1,
sizeof("GetInfoByAreaCodeResponse")-1,
SOAPMAP_FUNC,
__CUSZip_GetInfoByAreaCode_entries,
sizeof(__CUSZip_GetInfoByAreaCode_struct),
1,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
struct __CUSZip_GetInfoByCity_struct
{
BSTR USCity;
BSTR GetInfoByCityResult;
};
extern __declspec(selectany) const _soapmapentry __CUSZip_GetInfoByCity_entries[] =
{
{
0xCC4AFAC1,
"USCity",
L"USCity",
sizeof("USCity")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_IN | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByCity_struct, USCity),
NULL,
NULL,
-1,
},
{
0xE3D245BF,
"GetInfoByCityResult",
L"GetInfoByCityResult",
sizeof("GetInfoByCityResult")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_OUT | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByCity_struct, GetInfoByCityResult),
NULL,
NULL,
-1,
},
{ 0x00000000 }
};
extern __declspec(selectany) const _soapmap __CUSZip_GetInfoByCity_map =
{
0x2121D1CF,
"GetInfoByCity",
L"GetInfoByCityResponse",
sizeof("GetInfoByCity")-1,
sizeof("GetInfoByCityResponse")-1,
SOAPMAP_FUNC,
__CUSZip_GetInfoByCity_entries,
sizeof(__CUSZip_GetInfoByCity_struct),
1,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
struct __CUSZip_GetInfoByState_struct
{
BSTR USState;
BSTR GetInfoByStateResult;
};
extern __declspec(selectany) const _soapmapentry __CUSZip_GetInfoByState_entries[] =
{
{
0x56D19209,
"USState",
L"USState",
sizeof("USState")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_IN | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByState_struct, USState),
NULL,
NULL,
-1,
},
{
0x271736E7,
"GetInfoByStateResult",
L"GetInfoByStateResult",
sizeof("GetInfoByStateResult")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_OUT | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByState_struct, GetInfoByStateResult),
NULL,
NULL,
-1,
},
{ 0x00000000 }
};
extern __declspec(selectany) const _soapmap __CUSZip_GetInfoByState_map =
{
0x4967ACF7,
"GetInfoByState",
L"GetInfoByStateResponse",
sizeof("GetInfoByState")-1,
sizeof("GetInfoByStateResponse")-1,
SOAPMAP_FUNC,
__CUSZip_GetInfoByState_entries,
sizeof(__CUSZip_GetInfoByState_struct),
1,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
struct __CUSZip_GetInfoByZIP_struct
{
BSTR USZip;
BSTR GetInfoByZIPResult;
};
extern __declspec(selectany) const _soapmapentry __CUSZip_GetInfoByZIP_entries[] =
{
{
0x0631331B,
"USZip",
L"USZip",
sizeof("USZip")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_IN | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByZIP_struct, USZip),
NULL,
NULL,
-1,
},
{
0xD0D29D79,
"GetInfoByZIPResult",
L"GetInfoByZIPResult",
sizeof("GetInfoByZIPResult")-1,
SOAPTYPE_STRING,
SOAPFLAG_NONE | SOAPFLAG_OUT | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL | SOAPFLAG_NULLABLE,
offsetof(__CUSZip_GetInfoByZIP_struct, GetInfoByZIPResult),
NULL,
NULL,
-1,
},
{ 0x00000000 }
};
extern __declspec(selectany) const _soapmap __CUSZip_GetInfoByZIP_map =
{
0x4F970009,
"GetInfoByZIP",
L"GetInfoByZIPResponse",
sizeof("GetInfoByZIP")-1,
sizeof("GetInfoByZIPResponse")-1,
SOAPMAP_FUNC,
__CUSZip_GetInfoByZIP_entries,
sizeof(__CUSZip_GetInfoByZIP_struct),
1,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
extern __declspec(selectany) const _soapmap * __CUSZip_funcs[] =
{
&__CUSZip_GetInfoByAreaCode_map,
&__CUSZip_GetInfoByCity_map,
&__CUSZip_GetInfoByState_map,
&__CUSZip_GetInfoByZIP_map,
NULL
};
template <typename TClient>
inline HRESULT CUSZipT<TClient>::GetInfoByAreaCode(
BSTR USAreaCode,
BSTR* GetInfoByAreaCodeResult
)
{
if ( GetInfoByAreaCodeResult == NULL )
return E_POINTER;
HRESULT __atlsoap_hr = InitializeSOAP(NULL);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_INITIALIZE_ERROR);
return __atlsoap_hr;
}
CleanupClient();
CComPtr<IStream> __atlsoap_spReadStream;
__CUSZip_GetInfoByAreaCode_struct __params;
memset(&__params, 0x00, sizeof(__params));
__params.USAreaCode = USAreaCode;
__atlsoap_hr = SetClientStruct(&__params, 0);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_OUTOFMEMORY);
goto __skip_cleanup;
}
__atlsoap_hr = GenerateResponse(GetWriteStream());
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_GENERATE_ERROR);
goto __skip_cleanup;
}
__atlsoap_hr = SendRequest(_T("SOAPAction: \"http://www.webserviceX.NET/GetInfoByAreaCode\"\r\n"));
if (FAILED(__atlsoap_hr))
{
goto __skip_cleanup;
}
__atlsoap_hr = GetReadStream(&__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_READ_ERROR);
goto __skip_cleanup;
}
// cleanup any in/out-params and out-headers from previous calls
Cleanup();
__atlsoap_hr = BeginParse(__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_PARSE_ERROR);
goto __cleanup;
}
*GetInfoByAreaCodeResult = __params.GetInfoByAreaCodeResult;
goto __skip_cleanup;
__cleanup:
Cleanup();
__skip_cleanup:
ResetClientState(true);
memset(&__params, 0x00, sizeof(__params));
return __atlsoap_hr;
}
template <typename TClient>
inline HRESULT CUSZipT<TClient>::GetInfoByCity(
BSTR USCity,
BSTR* GetInfoByCityResult
)
{
if ( GetInfoByCityResult == NULL )
return E_POINTER;
HRESULT __atlsoap_hr = InitializeSOAP(NULL);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_INITIALIZE_ERROR);
return __atlsoap_hr;
}
CleanupClient();
CComPtr<IStream> __atlsoap_spReadStream;
__CUSZip_GetInfoByCity_struct __params;
memset(&__params, 0x00, sizeof(__params));
__params.USCity = USCity;
__atlsoap_hr = SetClientStruct(&__params, 1);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_OUTOFMEMORY);
goto __skip_cleanup;
}
__atlsoap_hr = GenerateResponse(GetWriteStream());
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_GENERATE_ERROR);
goto __skip_cleanup;
}
__atlsoap_hr = SendRequest(_T("SOAPAction: \"http://www.webserviceX.NET/GetInfoByCity\"\r\n"));
if (FAILED(__atlsoap_hr))
{
goto __skip_cleanup;
}
__atlsoap_hr = GetReadStream(&__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_READ_ERROR);
goto __skip_cleanup;
}
// cleanup any in/out-params and out-headers from previous calls
Cleanup();
__atlsoap_hr = BeginParse(__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_PARSE_ERROR);
goto __cleanup;
}
*GetInfoByCityResult = __params.GetInfoByCityResult;
goto __skip_cleanup;
__cleanup:
Cleanup();
__skip_cleanup:
ResetClientState(true);
memset(&__params, 0x00, sizeof(__params));
return __atlsoap_hr;
}
template <typename TClient>
inline HRESULT CUSZipT<TClient>::GetInfoByState(
BSTR USState,
BSTR* GetInfoByStateResult
)
{
if ( GetInfoByStateResult == NULL )
return E_POINTER;
HRESULT __atlsoap_hr = InitializeSOAP(NULL);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_INITIALIZE_ERROR);
return __atlsoap_hr;
}
CleanupClient();
CComPtr<IStream> __atlsoap_spReadStream;
__CUSZip_GetInfoByState_struct __params;
memset(&__params, 0x00, sizeof(__params));
__params.USState = USState;
__atlsoap_hr = SetClientStruct(&__params, 2);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_OUTOFMEMORY);
goto __skip_cleanup;
}
__atlsoap_hr = GenerateResponse(GetWriteStream());
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_GENERATE_ERROR);
goto __skip_cleanup;
}
__atlsoap_hr = SendRequest(_T("SOAPAction: \"http://www.webserviceX.NET/GetInfoByState\"\r\n"));
if (FAILED(__atlsoap_hr))
{
goto __skip_cleanup;
}
__atlsoap_hr = GetReadStream(&__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_READ_ERROR);
goto __skip_cleanup;
}
// cleanup any in/out-params and out-headers from previous calls
Cleanup();
__atlsoap_hr = BeginParse(__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_PARSE_ERROR);
goto __cleanup;
}
*GetInfoByStateResult = __params.GetInfoByStateResult;
goto __skip_cleanup;
__cleanup:
Cleanup();
__skip_cleanup:
ResetClientState(true);
memset(&__params, 0x00, sizeof(__params));
return __atlsoap_hr;
}
template <typename TClient>
inline HRESULT CUSZipT<TClient>::GetInfoByZIP(
BSTR USZip,
BSTR* GetInfoByZIPResult
)
{
if ( GetInfoByZIPResult == NULL )
return E_POINTER;
HRESULT __atlsoap_hr = InitializeSOAP(NULL);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_INITIALIZE_ERROR);
return __atlsoap_hr;
}
CleanupClient();
CComPtr<IStream> __atlsoap_spReadStream;
__CUSZip_GetInfoByZIP_struct __params;
memset(&__params, 0x00, sizeof(__params));
__params.USZip = USZip;
__atlsoap_hr = SetClientStruct(&__params, 3);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_OUTOFMEMORY);
goto __skip_cleanup;
}
__atlsoap_hr = GenerateResponse(GetWriteStream());
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_GENERATE_ERROR);
goto __skip_cleanup;
}
__atlsoap_hr = SendRequest(_T("SOAPAction: \"http://www.webserviceX.NET/GetInfoByZIP\"\r\n"));
if (FAILED(__atlsoap_hr))
{
goto __skip_cleanup;
}
__atlsoap_hr = GetReadStream(&__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_READ_ERROR);
goto __skip_cleanup;
}
// cleanup any in/out-params and out-headers from previous calls
Cleanup();
__atlsoap_hr = BeginParse(__atlsoap_spReadStream);
if (FAILED(__atlsoap_hr))
{
SetClientError(SOAPCLIENT_PARSE_ERROR);
goto __cleanup;
}
*GetInfoByZIPResult = __params.GetInfoByZIPResult;
goto __skip_cleanup;
__cleanup:
Cleanup();
__skip_cleanup:
ResetClientState(true);
memset(&__params, 0x00, sizeof(__params));
return __atlsoap_hr;
}
template <typename TClient>
ATL_NOINLINE inline const _soapmap ** CUSZipT<TClient>::GetFunctionMap()
{
return __CUSZip_funcs;
}
template <typename TClient>
ATL_NOINLINE inline const _soapmap ** CUSZipT<TClient>::GetHeaderMap()
{
static const _soapmapentry __CUSZip_GetInfoByAreaCode_atlsoapheader_entries[] =
{
{ 0x00000000 }
};
static const _soapmap __CUSZip_GetInfoByAreaCode_atlsoapheader_map =
{
0xFBDA3B2A,
"GetInfoByAreaCode",
L"GetInfoByAreaCodeResponse",
sizeof("GetInfoByAreaCode")-1,
sizeof("GetInfoByAreaCodeResponse")-1,
SOAPMAP_HEADER,
__CUSZip_GetInfoByAreaCode_atlsoapheader_entries,
0,
0,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
static const _soapmapentry __CUSZip_GetInfoByCity_atlsoapheader_entries[] =
{
{ 0x00000000 }
};
static const _soapmap __CUSZip_GetInfoByCity_atlsoapheader_map =
{
0x2121D1CF,
"GetInfoByCity",
L"GetInfoByCityResponse",
sizeof("GetInfoByCity")-1,
sizeof("GetInfoByCityResponse")-1,
SOAPMAP_HEADER,
__CUSZip_GetInfoByCity_atlsoapheader_entries,
0,
0,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
static const _soapmapentry __CUSZip_GetInfoByState_atlsoapheader_entries[] =
{
{ 0x00000000 }
};
static const _soapmap __CUSZip_GetInfoByState_atlsoapheader_map =
{
0x4967ACF7,
"GetInfoByState",
L"GetInfoByStateResponse",
sizeof("GetInfoByState")-1,
sizeof("GetInfoByStateResponse")-1,
SOAPMAP_HEADER,
__CUSZip_GetInfoByState_atlsoapheader_entries,
0,
0,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
static const _soapmapentry __CUSZip_GetInfoByZIP_atlsoapheader_entries[] =
{
{ 0x00000000 }
};
static const _soapmap __CUSZip_GetInfoByZIP_atlsoapheader_map =
{
0x4F970009,
"GetInfoByZIP",
L"GetInfoByZIPResponse",
sizeof("GetInfoByZIP")-1,
sizeof("GetInfoByZIPResponse")-1,
SOAPMAP_HEADER,
__CUSZip_GetInfoByZIP_atlsoapheader_entries,
0,
0,
-1,
SOAPFLAG_NONE | SOAPFLAG_PID | SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL,
0x8833C2E7,
"http://www.webserviceX.NET",
L"http://www.webserviceX.NET",
sizeof("http://www.webserviceX.NET")-1
};
static const _soapmap * __CUSZip_headers[] =
{
&__CUSZip_GetInfoByAreaCode_atlsoapheader_map,
&__CUSZip_GetInfoByCity_atlsoapheader_map,
&__CUSZip_GetInfoByState_atlsoapheader_map,
&__CUSZip_GetInfoByZIP_atlsoapheader_map,
NULL
};
return __CUSZip_headers;
}
template <typename TClient>
ATL_NOINLINE inline void * CUSZipT<TClient>::GetHeaderValue()
{
return this;
}
template <typename TClient>
ATL_NOINLINE inline const wchar_t * CUSZipT<TClient>::GetNamespaceUri()
{
return L"http://www.webserviceX.NET";
}
template <typename TClient>
ATL_NOINLINE inline const char * CUSZipT<TClient>::GetServiceName()
{
return NULL;
}
template <typename TClient>
ATL_NOINLINE inline const char * CUSZipT<TClient>::GetNamespaceUriA()
{
return "http://www.webserviceX.NET";
}
template <typename TClient>
ATL_NOINLINE inline HRESULT CUSZipT<TClient>::CallFunction(
void *,
const wchar_t *, int,
size_t)
{
return E_NOTIMPL;
}
template <typename TClient>
ATL_NOINLINE inline HRESULT CUSZipT<TClient>::GetClientReader(ISAXXMLReader **ppReader)
{
if (ppReader == NULL)
{
return E_INVALIDARG;
}
CComPtr<ISAXXMLReader> spReader = GetReader();
if (spReader.p != NULL)
{
*ppReader = spReader.Detach();
return S_OK;
}
return TClient::GetClientReader(ppReader);
}
} // namespace USZip
EDIT: Source code added.
MFC Application created from VS2005 "MFC Application" template. All default wizard values except chose "Dialog based" Application Type and unchecked "ActiveX controls" from the Advanced features wizard settings.
The Web Service call in the code below (OnBnClickedCallWebWervice) works when run from Vista and Win7 systems. When run from an XP system, the call fails with CO_E_NOTINITIALIZED as the HRESULT. If I add CoInitialize(NULL) to the InitInstance method, the Web Service call works on all three platforms.
TestApp.cpp
// TestApp.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "TestApp.h"
#include "TestAppDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CTestAppApp
BEGIN_MESSAGE_MAP(CTestAppApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CTestAppApp construction
CTestAppApp::CTestAppApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CTestAppApp object
CTestAppApp theApp;
// CTestAppApp initialization
BOOL CTestAppApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
CTestAppDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
TestAppDlg.cpp
// TestAppDlg.cpp : implementation file
//
#include "stdafx.h"
#include "TestApp.h"
#include "TestAppDlg.h"
#include "WebService.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CTestAppDlg dialog
CTestAppDlg::CTestAppDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestAppDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CTestAppDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTestAppDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON_CALLWEBSERVICE, &CTestAppDlg::OnBnClickedCallWebWervice)
END_MESSAGE_MAP()
// CTestAppDlg message handlers
BOOL CTestAppDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CTestAppDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTestAppDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestAppDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTestAppDlg::OnBnClickedCallWebWervice()
{
USZip::CUSZip* c = new USZip::CUSZip();
BSTR bstrResult;
HRESULT hr = c->GetInfoByZIP(CComBSTR(_T("90814")), &bstrResult);
if (SUCCEEDED(hr))
{
CString csResult(bstrResult);
GetDlgItem(IDC_STATIC_MSG)->SetWindowText(csResult);
}
else
{
CString csResult;
csResult.Format(_T("Call to web service failed with HRESULT=0x%0x"), hr);
GetDlgItem(IDC_STATIC_MSG)->SetWindowText(csResult);
}
delete c;
}

Related

Drag and drop from my app's ListView to external apps (such as Windows Explorer)

I have a a ListView containing a list of files:
hList = CreateWindowEx(0, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, 500, 400, hWnd, (HMENU)ID_LISTVIEW, hInst, NULL);
Let's say it contains a row c:\temp\hello.txt.
How to enable drag and drop of this file from my application's ListView to external applications (such as Windows Explorer) as "Copy"?
The GUI part of the question might be obvious (or not?) via:
case WM_NOTIFY:
{
...
case LVN_BEGINDRAG:
But here this question is about the actual sending of the file to external applications, such as Windows Explorer. How to do this?
Implement IDropSource, IDropSourceNotify (optional) and IDataObject and call DoDragDrop:
If you are developing an application that can act as a data source for an OLE drag-and-drop operation, you must call DoDragDrop when you detect that the user has started an OLE drag-and-drop operation.
The DoDragDrop function enters a loop in which it calls various methods in the IDropSource and IDropTarget interfaces. (For a successful drag-and-drop operation, the application acting as the data source must also implement IDropSource, while the target application must implement IDropTarget.)
SHCreateDataObject can provide a IDataObject instance for you but you often end up having to code your own because the shell provided implementation is not perfect.
IDragSourceHelper can help you to get a fancy drag image.
See also:
Dragging a shell object, part 1: Getting the IDataObject
What a drag: Dragging a virtual file (HGLOBAL edition)
What a drag: Dragging a virtual file (IStream edition)
What a drag: Dragging a virtual file (IStorage edition)
Here is some code that implements all that is required to perform such a ListView file drag&drop. First some includes:
#define CINTERFACE
#define COBJMACROS
#include "ShObjIdl.h"
#include "ShlObj.h"
#include "oleidl.h"
Then this in the WinMain function, to initialize OLE operations.
OleInitialize(NULL);
InitCommonControls();
Then, the IDropSource part:
typedef struct __DSV_TDropSource {
IDropSource This;
IDropSourceVtbl Func;
ULONG RefCnt;
} __DSV_TDropSource;
HRESULT WINAPI __DSV_QueryInterface(IDropSource *This, REFIID riid, void **ppvObject)
{
IUnknown *punk = NULL;
if (riid == IID_IUnknown)
{
punk = (IUnknown*)This;
}
else if (riid == IID_IDropSource)
{
punk = (IUnknown*)This;
}
*ppvObject = punk;
if (punk)
{
IUnknown_AddRef(punk);
return S_OK;
}
else {
return E_NOINTERFACE;
}
}
ULONG WINAPI __DSV_AddRef(IDropSource *This)
{
__DSV_TDropSource *pThis = (__DSV_TDropSource*)This;
return pThis->RefCnt++;
}
ULONG WINAPI __DSV_Release(IDropSource *This)
{
__DSV_TDropSource *pThis = (__DSV_TDropSource*)This;
LONG iRes = (LONG)pThis->RefCnt - 1;
if (iRes < 1) { iRes = 0; }
pThis->RefCnt = iRes;
if (iRes == 0) { free(pThis); }
return iRes;
}
HRESULT WINAPI __DSV_QueryContinueDrag(IDropSource *This, BOOL fEscapePressed, DWORD grfKeyState)
{
if (fEscapePressed) { return DRAGDROP_S_CANCEL; }
if (!(grfKeyState & (MK_LBUTTON | MK_RBUTTON))) { return DRAGDROP_S_DROP; }
return S_OK;
}
HRESULT WINAPI __DSV_GiveFeedback(IDropSource *This, DWORD dwEffect)
{
return DRAGDROP_S_USEDEFAULTCURSORS;
}
IDropSource* CreateDropSource()
{
__DSV_TDropSource *pResu = (__DSV_TDropSource*)malloc(sizeof(__DSV_TDropSource));
if (!pResu) { return 0; }
pResu->This.lpVtbl = &(pResu->Func);
pResu->Func.QueryInterface = __DSV_QueryInterface;
pResu->Func.AddRef = __DSV_AddRef;
pResu->Func.Release = __DSV_Release;
pResu->Func.QueryContinueDrag = __DSV_QueryContinueDrag;
pResu->Func.GiveFeedback = __DSV_GiveFeedback;
pResu->RefCnt = 1;
return (IDropSource*)pResu;
}
void** GetFileUiObject(TCHAR *ptFile, REFIID riid)
{
void** pInterfaceResu = 0;
IShellFolder *pFolder;
PIDLIST_RELATIVE pFile;
PIDLIST_ABSOLUTE pITEMDLIST_File;
HRESULT iResu;
pITEMDLIST_File = ILCreateFromPath(ptFile);
if (!pITEMDLIST_File)
return 0;
iResu = SHBindToParent(pITEMDLIST_File, IID_IShellFolder, (void**)&pFolder, (PCUITEMID_CHILD*)&pFile);
if (iResu != S_OK)
return 0;
const ITEMIDLIST* pArray[1] = { pFile };
iResu = IShellFolder_GetUIObjectOf(pFolder, NULL, 1, pArray, riid, NULL, (void**)&pInterfaceResu);
if (iResu != S_OK)
return 0;
IShellFolder_Release(pFolder);
return pInterfaceResu;
}
Lastly, this should be performed in the message loop:
case WM_NOTIFY:
pdi = (NMLVDISPINFO*) lParam;
nmlv = (NMLISTVIEW*) lParam;
switch (pdi->hdr.code)
{
case LVN_BEGINDRAG:
wstring fName = L"C:\\test.txt";
IDataObject *pObj;
IDropSource *pSrc;
pObj = (IDataObject*)GetFileUiObject(LPWSTR(fName.c_str()), IID_IDataObject);
if (!pObj)
break;
pSrc = CreateDropSource();
if (!pSrc)
{
IDataObject_Release(pObj);
break;
}
DWORD dwEffect;
DoDragDrop(pObj, pSrc, DROPEFFECT_COPY | DROPEFFECT_LINK, &dwEffect);
IDropSource_Release(pSrc);
IDataObject_Release(pObj);
break;

using GetEditBoxText in IFileSaveDialog

The folowing code is a part of my application.
I want to get a value from file save dialog using a editbox.
So i use AddEditBox function and GetEditBoxText to return value.
I enter "2000.0" in the editbox but the rturn value is Empty.
what is the problem?
wstring GetSaveFileForMakeDif(double & MinDistance) {
const DWORD CONTROL_GROUP = 5001;
const DWORD CONTROL_LABEL = 5002;
const DWORD CONTROL_EDITBOX_MINDIST = 5003;
wstring ret(L"");
HRESULT hr = S_FALSE;
IFileDialogCustomize *pfdc = NULL;
// Create a new common open file dialog.
IFileSaveDialog *pfd = NULL;
hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr))
{
DWORD dwOptions;
hr = pfd->GetOptions(&dwOptions);
// Set the title of the dialog.
if (SUCCEEDED(hr)) {
hr = pfd->SetTitle(L"Select Files");
hr = pfd->SetFileName(L"outputfile");
hr = pfd->SetDefaultExtension(L"txt");
}
// Set up the customization.
hr = pfd->QueryInterface(IID_PPV_ARGS(&pfdc));
if (SUCCEEDED(hr))
{
hr = pfdc->StartVisualGroup(CONTROL_GROUP, L"");
if (SUCCEEDED(hr))
hr = pfdc->AddText(CONTROL_LABEL, L"Min Distance:");
if (SUCCEEDED(hr))
hr = pfdc->AddEditBox(CONTROL_EDITBOX_MINDIST, L"2000.0");
pfdc->EndVisualGroup();
}
// Show the open file dialog.
if (SUCCEEDED(hr))
{
hr = pfd->Show(hMainWindow);
if (SUCCEEDED(hr))
{
IShellItem *psi = NULL;
hr = pfd->GetResult(&psi);
wchar_t *pszPath = new wchar_t[MAX_PATH];
psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
if (SUCCEEDED(hr))
{
ret = pszPath;
wchar_t * txt = NULL;
hr = pfdc->GetEditBoxText(CONTROL_EDITBOX_MINDIST, &txt);
//txt return L""
MinDistance = _wtof(txt);
}
}
}
pfd->Release();
}
pfdc->Release();
return ret;
};
Event handling is needed to catch the values before the dialog closes.
There is a complete MSDN example available here:
Common File Dialog Sample
At the moment the download link does not seem to be available. The example below shows how to catch the event in OnFileOk
Note that you need CoTaskMemFree to release memory which had been allocated by GetEditBoxText
#include <windows.h>
#include <shobjidl.h>
#include <shlwapi.h>
#include <new>
#pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma comment(lib, "Shlwapi.lib")
// Controls
#define CONTROL_GROUP 2000
#define CONTROL_LABEL 5002
#define CONTROL_EDITBOX_MINDIST 5003
class CDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents
{
public:
// IUnknown methods
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) {
static const QITAB qit[] = {
QITABENT(CDialogEventHandler, IFileDialogEvents),
QITABENT(CDialogEventHandler, IFileDialogControlEvents),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(ULONG) AddRef() {
return InterlockedIncrement(&_cRef);
}
IFACEMETHODIMP_(ULONG) Release() {
long cRef = InterlockedDecrement(&_cRef);
if (!cRef)
delete this;
return cRef;
}
// IFileDialogEvents methods
IFACEMETHODIMP OnFileOk(IFileDialog *pfd);
IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) { return S_OK; };
IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnSelectionChange(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; };
IFACEMETHODIMP OnTypeChange(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; };
// IFileDialogControlEvents methods
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize *, DWORD, DWORD) { return S_OK; };
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; };
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize *, DWORD, BOOL) { return S_OK; };
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize *, DWORD) { return S_OK; };
CDialogEventHandler() : _cRef(1) { };
private:
~CDialogEventHandler() { };
long _cRef;
};
// Instance creation helper
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
{
*ppv = NULL;
CDialogEventHandler *pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
hr = pDialogEventHandler->QueryInterface(riid, ppv);
pDialogEventHandler->Release();
}
return hr;
}
//EDIT BEGIN ***************************
// IFileDialogEvents methods
IFACEMETHODIMP CDialogEventHandler::OnFileOk(IFileDialog *fileDialog)
{
IFileDialogCustomize *fileCustomize = NULL;
fileDialog->QueryInterface(IID_PPV_ARGS(&fileCustomize));
wchar_t *buf;
fileCustomize->GetEditBoxText(IDC_EDTI1, &buf);
MessageBox(0, buf, 0, 0);
CoTaskMemFree(buf);
fileCustomize->Release();
return S_OK;
}
//EDIT END *****************************
// This code snippet demonstrates how to add custom controls in the Common File Dialog.
HRESULT AddCustomControls()
{
// CoCreate the File Open Dialog object.
IFileDialog *pfd = NULL;
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr))
{
// Create an event handling object, and hook it up to the dialog.
IFileDialogEvents *pfde = NULL;
DWORD dwCookie = 0;
hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
if (SUCCEEDED(hr))
{
// Hook up the event handler.
hr = pfd->Advise(pfde, &dwCookie);
if (SUCCEEDED(hr))
{
// Set up a Customization.
IFileDialogCustomize *pfdc = NULL;
if (SUCCEEDED(pfd->QueryInterface(IID_PPV_ARGS(&pfdc))))
{
pfdc->StartVisualGroup(CONTROL_GROUP, L"");
pfdc->AddText(CONTROL_LABEL, L"Min Distance:");
pfdc->AddEditBox(CONTROL_EDITBOX_MINDIST, L"2000.0");
pfdc->EndVisualGroup();
pfdc->Release();
}
else
{
// Unadvise here in case we encounter failures before we get a chance to show the dialog.
pfd->Unadvise(dwCookie);
}
}
pfde->Release();
}
if (SUCCEEDED(hr))
{
// Now show the dialog.
hr = pfd->Show(NULL);
if (SUCCEEDED(hr))
{
// You can add your own code here to handle the results.
}
// Unhook the event handler.
pfd->Unadvise(dwCookie);
}
pfd->Release();
}
return hr;
}
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
AddCustomControls();
CoUninitialize();
return 0;
}

How to set window text by its handle in another process?

For my purposes I need to set text for a window that belongs to another process using its HWND handle. I came up with the following code, but it doesn't seem to work:
BOOL SetWindowTextInAnotherProcess(HWND hWnd, LPCTSTR pStrText)
{
//Set text of the 'hWnd' (assuming that 'hWnd' is in another process)
//'pStrText' = ASCIIZ string to set
//RETURN:
// = TRUE if done
BOOL bRes = FALSE;
if(hWnd &&
pStrText)
{
DWORD dwProcID = 0;
::GetWindowThreadProcessId(hWnd, &dwProcID);
if(dwProcID)
{
HANDLE hProc = ::OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwProcID);
if(hProc)
{
int nLn = lstrlen(pStrText);
int ncbSzStr = (nLn + 1) * sizeof(TCHAR);
VOID* pVMem = ::VirtualAllocEx(hProc, NULL, ncbSzStr, MEM_COMMIT, PAGE_READWRITE);
if(pVMem)
{
SIZE_T sztWrtn = 0;
if(::WriteProcessMemory(hProc, pVMem, pStrText, ncbSzStr, &sztWrtn))
{
if(sztWrtn == ncbSzStr)
{
DWORD_PTR dwMsgRes = 0xCCCCABAB;
if(::SendMessageTimeout(hWnd, WM_SETTEXT, NULL, (LPARAM)pVMem,
SMTO_NORMAL | SMTO_ABORTIFHUNG | SMTO_ERRORONEXIT,
1000 * 2,
&dwMsgRes))
{
//Check result
if(dwMsgRes != 0xCCCCABAB &&
dwMsgRes == TRUE)
{
//Done
bRes = TRUE;
}
}
}
}
//Free mem
::VirtualFreeEx(hProc, pVMem, ncbSzStr, MEM_DECOMMIT);
}
::CloseHandle(hProc);
}
}
}
return bRes;
}
SendMessageTimeout returns FALSE and GetLastError returns 0.
Any idea what am I doing wrong?
PS. Both processes are running non-elevated on the same desktop.

Filtering file types with CMFCShellTreeCtrl

I'm using a CMFCShellTreeCtrl derived class called CShellTreeCtrl in an CMFCOutlookBar object to display files and I'd like to filter file types and later be able to drag and drop files from it.
I've managed to display files as well as folders, but struggling to understand how to use IEnumIDList to achieve the file type filtering.
int CBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMFCOutlookBar::OnCreate(lpCreateStruct) == -1)
return -1;
CMFCOutlookBarTabCtrl* pOutlookBar = (CMFCOutlookBarTabCtrl*)GetUnderlyingWindow();
if (pOutlookBar != NULL)
{
pOutlookBar->SetImageList(IDB_PAGES_HC, 24);
pOutlookBar->SetToolbarImageList(IDB_PAGES_SMALL_HC, 16);
pOutlookBar->EnableInPlaceEdit(FALSE);
RecalcLayout();
}
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
// can float, can autohide, can resize, CAN NOT CLOSE
DWORD dwStyle = AFX_CBRS_AUTOHIDE | AFX_CBRS_RESIZE;
CRect rectDummy(0, 0, 0, 0);
const DWORD dwTreeStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_INFOTIP;
m_pDirList = new CShellTreeCtrl;
m_pDirList->Create(dwTreeStyle, rectDummy, this, ID_SHELLDRILL);
m_pDirList->SetFlags(m_pDirList->GetFlags() | SHCONTF_NONFOLDERS);
pOutlookBar->AddControl(m_pDirList, _T("Folders"), 2, FALSE, dwStyle);
}
Got it working with the following code adapted from this similar question
HRESULT EnumObjects(HTREEITEM hParentItem, LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent)
{
ASSERT_VALID(this);
ASSERT_VALID(afxShellManager);
LPENUMIDLIST pEnum = NULL;
HRESULT hr = pParentFolder->EnumObjects(NULL, m_dwFlags, &pEnum);
if (FAILED(hr) || pEnum == NULL)
{
return hr;
}
LPITEMIDLIST pidlTemp;
DWORD dwFetched = 1;
// Enumerate the item's PIDLs:
while (SUCCEEDED(pEnum->Next(1, &pidlTemp, &dwFetched)) && dwFetched)
{
TVITEM tvItem;
ZeroMemory(&tvItem, sizeof(tvItem));
// Fill in the TV_ITEM structure for this item:
tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
// AddRef the parent folder so it's pointer stays valid:
pParentFolder->AddRef();
// Put the private information in the lParam:
LPAFX_SHELLITEMINFO pItem = (LPAFX_SHELLITEMINFO)GlobalAlloc(GPTR, sizeof(AFX_SHELLITEMINFO));
ENSURE(pItem != NULL);
pItem->pidlRel = pidlTemp;
pItem->pidlFQ = afxShellManager->ConcatenateItem(pidlParent, pidlTemp);
pItem->pParentFolder = pParentFolder;
tvItem.lParam = (LPARAM)pItem;
CString strItem = OnGetItemText(pItem);
tvItem.pszText = strItem.GetBuffer(strItem.GetLength());
tvItem.iImage = OnGetItemIcon(pItem, FALSE);
tvItem.iSelectedImage = OnGetItemIcon(pItem, TRUE);
// Determine if the item has children:
DWORD dwAttribs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DISPLAYATTRMASK | SFGAO_CANRENAME | SFGAO_FILESYSANCESTOR;
pParentFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pidlTemp, &dwAttribs);
tvItem.cChildren = (dwAttribs & (SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR));
// Determine if the item is shared:
if (dwAttribs & SFGAO_SHARE)
{
tvItem.mask |= TVIF_STATE;
tvItem.stateMask |= TVIS_OVERLAYMASK;
tvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image
}
// Fill in the TV_INSERTSTRUCT structure for this item:
TVINSERTSTRUCT tvInsert;
tvInsert.item = tvItem;
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = hParentItem;
string str = strItem;
if (tvItem.cChildren & SFGAO_HASSUBFOLDER)
{
InsertItem(&tvInsert);
}
else
{
if ((str.substr(str.find_last_of(".") + 1) == "pdf"))
{
InsertItem(&tvInsert);
}
}
dwFetched = 0;
}
pEnum->Release();
return S_OK;
}

Working with transparent PNG in Windows mobile 6.x using C++

I have been trying to add to resource and use some semi transparent PNG files in my windows mobile 6.x application. After days of looking around and experimenting with different methods, I decided to dynamically load and use gdiplus.dll and use the flat APIs. everything works except function GdipCreateHBITMAPFromBitmap returns NotImplemented (6). any idea how to fix this problem? I have 3 files that I am attaching here.
GdiPlusDynamic.cpp:
#include "GdiPlusDynamic.h"
#include "GdiPlusDynamicTools.h"
#include <string>
TAutoStream::TAutoStream(HGLOBAL m_hBuffer)
{
pStream = NULL;
switch(::CreateStreamOnHGlobal(m_hBuffer, TRUE, &pStream))
{
case E_NOINTERFACE:
throw std::wstring(L"The specified interface is not supported");
break;
case E_OUTOFMEMORY:
throw std::wstring(L"Not enough memory");
break;
default:
break;
}
}
TAutoStream::~TAutoStream(void)
{
if(NULL != pStream)
pStream->Release();
}
IStream* TAutoStream::get(void)
{
return pStream;
}
AutoGlobal::AutoGlobal(UINT uFlags, SIZE_T dwBytes) : len(0)
{
m_hBuffer = ::GlobalAlloc(uFlags, dwBytes);
if(IsOk())
{
memset(m_hBuffer, 0, dwBytes);
len = dwBytes;
}
}
AutoGlobal::~AutoGlobal(void)
{
if(IsOk())
::GlobalFree(m_hBuffer);
}
bool AutoGlobal::IsOk(void)
{
return (NULL != m_hBuffer);
}
HGLOBAL AutoGlobal::get(void)
{
return m_hBuffer;
}
TAutoLockedBuff::TAutoLockedBuff(UINT uFlags, SIZE_T dwBytes) : AutoGlobal(uFlags, dwBytes)
{
pBuffer = NULL;
if(AutoGlobal::IsOk())
pBuffer = GlobalLock(m_hBuffer);
}
TAutoLockedBuff::~TAutoLockedBuff(void)
{
if(IsOk())
GlobalUnlock(m_hBuffer);
}
bool TAutoLockedBuff::IsOk(void)
{
return (AutoGlobal::IsOk() && (NULL != pBuffer));
}
void TAutoLockedBuff::CopyFrom(const void* pSrcData, SIZE_T srcLen)
{
if(IsOk())
CopyMemory(pBuffer, pSrcData, min(srcLen, len));
}
TDynamicGdiPlus::TDynamicGdiPlus(void) : everythigOK(false)
{
GdiplusStartupInput dpStartupInfo;
token = 0;
pGdiplusStartup = NULL;
pGdiplusShutdown = NULL;
pGdipCreateBitmapFromStream = NULL;
pGdipCreateHBITMAPFromBitmap = NULL;
pGdipFree = NULL;
hGdiPlus = ::LoadLibrary(L"gdiplus.dll");
if(NULL == hGdiPlus)
throw std::wstring(L"Unable to load 'gdiplus.dll'");
pGdiplusStartup = (TGdiplusStartup)GetProcAddress(hGdiPlus, L"GdiplusStartup");
if(NULL == pGdiplusStartup)
throw std::wstring(L"Unable to get the address of 'GdiplusStartup'");
pGdiplusShutdown = (TGdiplusShutdown)GetProcAddress(hGdiPlus, L"GdiplusShutdown");
if(NULL == pGdiplusShutdown)
throw std::wstring(L"Unable to get the address of 'GdiplusShutdown'");
pGdipCreateBitmapFromStream = (TGdipCreateBitmapFromStream)GetProcAddress(hGdiPlus, L"GdipCreateBitmapFromStreamICM");
if(NULL == pGdipCreateBitmapFromStream)
throw std::wstring(L"Unable to get the address of 'GdipCreateBitmapFromStreamICM'");
pGdipCreateHBITMAPFromBitmap = (TGdipCreateHBITMAPFromBitmap)GetProcAddress(hGdiPlus, L"GdipCreateHBITMAPFromBitmap");
if(NULL == pGdipCreateHBITMAPFromBitmap)
throw std::wstring(L"Unable to get the address of 'GdipCreateHBITMAPFromBitmap'");
pGdipFree = (TGdipFree)GetProcAddress(hGdiPlus, L"GdipFree");
if(NULL == pGdipFree)
throw std::wstring(L"Unable to get the address of 'GdipFree'");
if(Status::Ok != pGdiplusStartup(&token, &dpStartupInfo, NULL))
throw std::wstring(L"Unable to start 'GDI Plus'");
else
everythigOK = true;
}
TDynamicGdiPlus::~TDynamicGdiPlus(void)
{
if((0 != token) && (NULL != pGdiplusShutdown))
pGdiplusShutdown(token);
if(NULL != hGdiPlus)
FreeLibrary(hGdiPlus);
}
HBITMAP TDynamicGdiPlus::LoadImageFromResource(HINSTANCE hInst, LPCTSTR lpName, LPCTSTR lpType)
{
HBITMAP retVal = NULL;
if(everythigOK)
{
HRSRC hResource = ::FindResource(hInst, lpName, lpType);
if (NULL != hResource)
{
DWORD imageSize = ::SizeofResource(hInst, hResource);
if (0 < imageSize)
{
const void* pResourceData = ::LockResource(::LoadResource(hInst, hResource));
if (NULL != pResourceData)
{
TAutoLockedBuff m_Buffer(GMEM_MOVEABLE, imageSize + 1);
void* pBmp;
m_Buffer.CopyFrom(pResourceData, imageSize);
TAutoStream m_Stream(m_Buffer.get());
pGdipCreateBitmapFromStream(m_Stream.get(), &pBmp);
if (NULL != pBmp)
{
pGdipCreateHBITMAPFromBitmap(pBmp, &retVal, 0x00FFFFFF); // this returns NotImplemented
pGdipFree(pBmp);
if(NULL == retVal)
throw std::wstring(L"Unable to extract HBITMAP from Gdiplus::Bitmap");
}
else
throw std::wstring(L"Unable to extract Gdiplus::Bitmap from stream");
}
else
throw std::wstring(L"Unable to lock resource");
}
else
throw std::wstring(L"Size of resource is 0");
}
else
throw std::wstring(L"Unable to find resource");
}
return retVal;
}
GdiPlusDynamic.h
#pragma once
typedef enum {
Ok = 0,
GenericError = 1,
InvalidParameter = 2,
OutOfMemory = 3,
ObjectBusy = 4,
InsufficientBuffer = 5,
NotImplemented = 6,
Win32Error = 7,
WrongState = 8,
Aborted = 9,
FileNotFound = 10,
ValueOverflow = 11,
AccessDenied = 12,
UnknownImageFormat = 13,
FontFamilyNotFound = 14,
FontStyleNotFound = 15,
NotTrueTypeFont = 16,
UnsupportedGdiplusVersion = 17,
GdiplusNotInitialized = 18,
PropertyNotFound = 19,
PropertyNotSupported = 20,
ProfileNotFound = 21
} Status;
enum DebugEventLevel
{
DebugEventLevelFatal,
DebugEventLevelWarning
};
// Callback function that GDI+ can call, on debug builds, for assertions
// and warnings.
typedef VOID (WINAPI *DebugEventProc)(DebugEventLevel level, CHAR *message);
// Notification functions which the user must call appropriately if
// "SuppressBackgroundThread" (below) is set.
typedef Status (WINAPI *NotificationHookProc)(OUT ULONG_PTR *token);
typedef VOID (WINAPI *NotificationUnhookProc)(ULONG_PTR token);
struct GdiplusStartupInput
{
UINT32 GdiplusVersion; // Must be 1 (or 2 for the Ex version)
DebugEventProc DebugEventCallback; // Ignored on free builds
BOOL SuppressBackgroundThread; // FALSE unless you're prepared to call
// the hook/unhook functions properly
BOOL SuppressExternalCodecs; // FALSE unless you want GDI+ only to use
// its internal image codecs.
GdiplusStartupInput(
DebugEventProc debugEventCallback = NULL,
BOOL suppressBackgroundThread = FALSE,
BOOL suppressExternalCodecs = FALSE)
{
GdiplusVersion = 1;
DebugEventCallback = debugEventCallback;
SuppressBackgroundThread = suppressBackgroundThread;
SuppressExternalCodecs = suppressExternalCodecs;
}
};
struct GdiplusStartupOutput
{
// The following 2 fields are NULL if SuppressBackgroundThread is FALSE.
// Otherwise, they are functions which must be called appropriately to
// replace the background thread.
//
// These should be called on the application's main message loop - i.e.
// a message loop which is active for the lifetime of GDI+.
// "NotificationHook" should be called before starting the loop,
// and "NotificationUnhook" should be called after the loop ends.
NotificationHookProc NotificationHook;
NotificationUnhookProc NotificationUnhook;
};
typedef Status (WINAPI *TGdiplusStartup)(ULONG_PTR* token, const GdiplusStartupInput *input, GdiplusStartupOutput *output);
typedef void (WINAPI *TGdiplusShutdown)(ULONG_PTR token);
typedef Status (WINAPI *TGdipCreateBitmapFromStream)(IStream* stream, void **bitmap);
typedef Status (WINAPI *TGdipCreateHBITMAPFromBitmap)(void* bitmap, HBITMAP* hbmReturn, DWORD background);
typedef void (WINAPI *TGdipFree)(void* ptr);
class TDynamicGdiPlus
{
private:
bool everythigOK;
protected:
HMODULE hGdiPlus;
TGdiplusStartup pGdiplusStartup;
TGdiplusShutdown pGdiplusShutdown;
TGdipCreateBitmapFromStream pGdipCreateBitmapFromStream;
TGdipCreateHBITMAPFromBitmap pGdipCreateHBITMAPFromBitmap;
TGdipFree pGdipFree;
ULONG_PTR token;
public:
TDynamicGdiPlus(void);
virtual ~TDynamicGdiPlus(void);
HBITMAP LoadImageFromResource(HINSTANCE hInst, LPCTSTR lpName, LPCTSTR lpType);
};
and GdiPlusDynamicTools.h
#pragma once
class TAutoStream
{
protected:
IStream* pStream;
public:
TAutoStream(HGLOBAL m_hBuffer);
virtual ~TAutoStream(void);
IStream* get(void);
};
class AutoGlobal
{
protected:
HGLOBAL m_hBuffer;
SIZE_T len;
public:
AutoGlobal(UINT uFlags, SIZE_T dwBytes);
virtual ~AutoGlobal(void);
bool IsOk(void);
HGLOBAL get(void);
};
class TAutoLockedBuff : public AutoGlobal
{
protected:
void* pBuffer;
public:
TAutoLockedBuff(UINT uFlags, SIZE_T dwBytes);
virtual ~TAutoLockedBuff(void);
bool IsOk(void);
void CopyFrom(const void* pSrcData, SIZE_T srcLen);
};
You can use IImagingFactory service instead GDI+
This service can render png, bmp with alpha channel.
We use this service for real project under Windows Mobile 6.x
This code mockup:
CComPtr<IImagingFactory> spImageFactory;
spImageFactory.CoCreateInstance(__uuidof(ImagingFactory);
HRSRC hRes = FindResource(hInstance, MAKEINTRESOURCE(resID), _T("PNG"));
DWORD imageSize = SizeOfResource(hInstance, hRes);
HGLOBAL hGlobal = LoadResource(hInstance, hRes);
CComPtr<IImage> spImage;
spImageFactory->CreateImageFromBuffer(LockResource(hGlobal, imageSize), BufferDisposalFlagNone, &spImage);
ImageInfo info = {0};
spImage->GetImageInfo(&info);
CRect rect(x, y, x+info.Width, y+info.Height);
spImage->Draw(hDc, &rect, NULL);