COleVariant in WinAPI (afxdisp.h)
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 26

Thread: COleVariant in WinAPI (afxdisp.h)

Hybrid View

  1. #1
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    COleVariant in WinAPI (afxdisp.h)

    Hey ho...

    guess i need some help of experts again.. wanna export listview to MS excel. i found a really nice article on this:
    http://www.codeproject.com/Articles/...mation-Using-C

    however the only one thing that does not seem to work with my OLE is COleVariant class.
    It's simply not declared. I tried adding afxdisp.h but it's not a standard lib in my Microsoft Visual Visual Studio Express 2012 and it seems to be very specific to MFC.

    I tried to add it manually from internet but it's then referring (calling) to other *.h

    is there any way to either replace COleVariant with VARIANT (or something) or add afxdisp.h (and all connected libs) to my program?
    i wanna achieve this :

    Code:
    IDispatch* pRange;
    	{
    		COleVariant oleRange(szCell);
    		VARIANT result;
    		VariantInit(&result);
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, oleRange.Detach());
    		pRange = result.pdispVal;
    	}
    will be grateful for any hint!
    thanks
    .

  2. #2
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    3,845

    Re: COleVariant in WinAPI (afxdisp.h)

    COleVariant is a c++ wrapper class around VARIANT
    so yes, you can use VARIANT but you'll have to do all the conversions to/from yourself.

  3. #3
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    Re: COleVariant in WinAPI (afxdisp.h)

    it doesnt really help coz i simply donno how to do this.
    i would like to use ATL and MFC libs in my VC Express 2012 version. i tried few links with using SDK but all refer to old version of SDK and VC Express 2008 which is completely different to mine.
    There must be some way to put those lib into my program.

  4. #4
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    Re: COleVariant in WinAPI (afxdisp.h)

    Ok.. I tried to run it with ATL and MFC libs, i installed 30days version of VC Prof 2012, and although COleVariant worked, there is a lot of dependencies when i started adding ATL libs. i cannot even compile my program with windows.h anymore coz ATL does not go along with win32 app, i got hundred of warnings and errors, i permanently gave up with this approach.
    I guess my last chance now is to find some way to convert COleVariant to something else.

    original code:
    Code:
    IDispatch* pRange;
    {
    LPCTSTR szRange = "a1";
    COleVariant oleRange(szRange);
    VARIANT result;
    VariantInit(&result);
    m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, oleRange.Detach());
    pRange = result.pdispVal;
    }
    i would like to change it to something like this:

    Code:
    IDispatch* pRange;
    {
    VARIANT xx;
    xx.vt=VT_I1;
    xx.pcVal="a1";
    VARIANT result;
    VariantInit(&result);
    m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, functionDetach(xx));
    pRange = result.pdispVal;
    }
    does anyone have any idea how that functionDetach(xx) should look like to give me the same result as COleVariantClass.Detach()?

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,360

    Re: COleVariant in WinAPI (afxdisp.h)

    Quote Originally Posted by berkov View Post
    i would like to change it to something like this:

    Code:
    IDispatch* pRange;
    {
    VARIANT xx;
    xx.vt=VT_I1;
    xx.pcVal="a1";
    VARIANT result;
    VariantInit(&result);
    m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, functionDetach(xx));
    pRange = result.pdispVal;
    }
    Sorry! I missed this erroneos assignments.
    VT_I1 means theat the value is of type char (one and only one char symbol!) while you are trying to pass in the char* (a ponther to char array)
    Try to change your code to be:
    Code:
    VARIANT xx;
    xx.vt=VT_BSTR;
    xx.pcVal= L"a1";
    Victor Nijegorodov

  6. #6
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    Re: COleVariant in WinAPI (afxdisp.h)

    Ah, you are right, didn't see it.

    i tried it and now it seems the BSTR does not take the UNICODE:
    IntelliSense: a value of type "const wchar_t *" cannot be assigned to an entity of type "CHAR *"

    i had to remove that "L" and put it like this:
    xx.pcVal = "a1";

    and unfortunately i got the same error on runtime as at the beginning.
    any other ideas?

  7. #7
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    3,845

    Re: COleVariant in WinAPI (afxdisp.h)

    Quote Originally Posted by VictorN View Post
    Try to change your code to be:
    Code:
    VARIANT xx;
    xx.vt=VT_BSTR;
    xx.pcVal= L"a1";
    this doesn't create a proper VARIANT to a BSTR, even if you fixed it to set it to bstrVal instead of pcVal.
    it creates a variant of type VT_BSTR with the BSTR part pointing to a static wide character string. Wide char string != BSTR.

    Depending on how the receiving function works. This can either work without any form of issue, or it can have all kinds of failures.

    BSTR's are BSTR's, they are NOT simply pointers to any type of wide character strings.



    The above would be correct if you used a VT_LPWSTR type, but not everything accepting a VARIANT will handle that type properly (a lot don't).
    If you pass a VT_BSTR, make sure you have an actual BSTR, meaning, it should be allocated via SysAllocString() or it should be NULL indicating an empty string (not a NULL string). There are C++ wrapper classes such as CComBSTR (ATL/MFC) and _bstr_t (compiler COM support) to help you manage BSTR's.
    Last edited by OReubens; May 27th, 2013 at 07:44 AM.

  8. #8
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,360

    Re: COleVariant in WinAPI (afxdisp.h)

    Quote Originally Posted by OReubens View Post
    this doesn't create a proper VARIANT to a BSTR, even if you fixed it to set it to bstrVal instead of pcVal.
    it creates a variant of type VT_BSTR with the BSTR part pointing to a static wide character string. Wide char string != BSTR.
    ...
    If you pass a VT_BSTR, make sure you have an actual BSTR, meaning, it should be allocated via SysAllocString() ...
    Right!
    And sorry for my incorrect suggestion.

    Frankly, I never use row VARIANT and BSTR data types. Only their wrapper: usually _variant_t and _bstr_t and rarely COleVarinat and CComBSTR, so I never have to use SysAllocString/SysFreeString. I has just forgotten these function exist and are used by the wrapper classes!
    Victor Nijegorodov

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,360

    Re: COleVariant in WinAPI (afxdisp.h)

    MSDN does know it for sure!
    COleVariant:etach
    So just pass in your xx instead of "functionDetach(xx)"!
    Victor Nijegorodov

  10. #10
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    Re: COleVariant in WinAPI (afxdisp.h)

    Hi Victor,
    tried that but then the OLEMethod function breaks at Invoking:
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp, pvResult, NULL, NULL);


    The code of OLEMethod:
    Code:
    HRESULT OLEMethod(int nType, VARIANT *pvResult, IDispatch *pDisp,LPOLESTR ptName, int cArgs...)
    {
    	if(!pDisp) return E_FAIL;
    
    	va_list marker;
    	va_start(marker, cArgs);
    
    	DISPPARAMS dp = { NULL, NULL, 0, 0 };
    	DISPID dispidNamed = DISPID_PROPERTYPUT;
    	DISPID dispID;
    	char szName[200];
    
    
    	// Convert down to ANSI
    	WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
    
    	// Get DISPID for name passed...
    	HRESULT hr= pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
    	if(FAILED(hr)) {
    		return hr;
    	}
    	// Allocate memory for arguments...
    	VARIANT *pArgs = new VARIANT[cArgs+1];
    	// Extract arguments...
    	for(int i=0; i<cArgs; i++) {
    		pArgs[i] = va_arg(marker, VARIANT);
    	}
    
    	// Build DISPPARAMS
    	dp.cArgs = cArgs;
    	dp.rgvarg = pArgs;
    
    	// Handle special-case for property-puts!
    	if(nType & DISPATCH_PROPERTYPUT) {
    		dp.cNamedArgs = 1;
    		dp.rgdispidNamedArgs = &dispidNamed;
    	}
    
    	// Make the call!
    	hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp, pvResult, NULL, NULL);
    	if(FAILED(hr)) {
    		return hr;
    	}
    	// End variable-argument section...
    	va_end(marker);
    
    	delete [] pArgs;
    	return hr;
    }

    The error says:
    Unhandled exception at 0x750E80EE (oleaut32.dll) in Kredens (OLE aut).exe: 0xC0000005: Access violation writing location 0x010B8074



    I will only add that the OLEMethod works correctly coz it does NOT break at e.g:
    Code:
    IDispatch *pSheet;
    	{
    		VARIANT result;
    		VariantInit(&result);
    		VARIANT itemn;
    		itemn.vt = VT_I4;
    		itemn.lVal = 1;
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheets, L"Item", 1, itemn);
    		pSheet = result.pdispVal;
    	}

  11. #11
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,360

    Re: COleVariant in WinAPI (afxdisp.h)

    Is your build an ANSI or UNICODE?
    Anyway, you should always use _T() macro for text/symbol constants.
    Victor Nijegorodov

  12. #12
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    Re: COleVariant in WinAPI (afxdisp.h)

    The project is "Use Multi-Byte Character Set".
    i tried it with _T("a1") and still the same error.

  13. #13
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,360

    Re: COleVariant in WinAPI (afxdisp.h)

    Ok, then let's begin from the very begin! What error exactly do you have? Where? Please, show your actual code.
    Victor Nijegorodov

  14. #14
    Join Date
    Apr 2013
    Location
    Prague / Cracow
    Posts
    47

    Re: COleVariant in WinAPI (afxdisp.h)

    hmm.. the code is very long, it has a lot of pages as i've been writing it for 4 months now.
    but i will try to copy the most important parts:

    xls.cpp:
    Code:
    #include <windows.h>
    #include "xls.h"
    #include "classes.h"
    #include "resources.h"
    #include "Tchar.h"
    
    
    HRESULT hr2;
    HRESULT OLEMethod(int nType, VARIANT *pvResult, IDispatch *pDisp,LPOLESTR ptName, int cArgs...)
    {
    	if(!pDisp) return E_FAIL;
    
    	va_list marker;
    	va_start(marker, cArgs);
    
    	DISPPARAMS dp = { NULL, NULL, 0, 0 };
    	DISPID dispidNamed = DISPID_PROPERTYPUT;
    	DISPID dispID;
    	char szName[200];
    
    
    	// Convert down to ANSI
    	WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
    
    	// Get DISPID for name passed...
    	HRESULT hr= pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
    	if(FAILED(hr)) {
    		return hr;
    	}
    	// Allocate memory for arguments...
    	VARIANT *pArgs = new VARIANT[cArgs+1];
    	// Extract arguments...
    	for(int i=0; i<cArgs; i++) {
    		pArgs[i] = va_arg(marker, VARIANT);
    	}
    
    	// Build DISPPARAMS
    	dp.cArgs = cArgs;
    	dp.rgvarg = pArgs;
    
    	// Handle special-case for property-puts!
    	if(nType & DISPATCH_PROPERTYPUT) {
    		dp.cNamedArgs = 1;
    		dp.rgdispidNamedArgs = &dispidNamed;
    	}
    
    	// Make the call!
    	hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, nType, &dp, pvResult, NULL, NULL);
    	if(FAILED(hr)) {
    		return hr;
    	}
    	// End variable-argument section...
    	va_end(marker);
    
    	delete [] pArgs;
    	return hr;
    }
    CMSExcel::CMSExcel(void)
    {
    	m_hr=S_OK;
    	m_pEApp=NULL;
    	m_pBooks=NULL;
    	m_pActiveBook=NULL;
    }
    HRESULT CMSExcel::Initialize(bool bVisible)
    {
    	CoInitialize(NULL);
    	CLSID clsid;
    	m_hr = CLSIDFromProgID(L"Excel.Application", &clsid);
    	if(SUCCEEDED(m_hr))
    	{
    		m_hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void **)&m_pEApp);
    		if(FAILED(m_hr)) m_pEApp=NULL;
    	}
    	{
    		m_hr=SetVisible(bVisible);
    	}
    	return m_hr;
    }
    HRESULT CMSExcel::SetVisible(bool bVisible)
    {
    
    	if(!m_pEApp) return E_FAIL;
    	VARIANT x;
    	x.vt = VT_I4;
    	x.lVal = bVisible;
    	m_hr=OLEMethod(DISPATCH_PROPERTYPUT, NULL, m_pEApp, L"Visible", 1, x);
    
    	return m_hr;
    }
    
    HRESULT CMSExcel::NewExcelBook(bool bVisible)
    {
    	if(m_pEApp==NULL) 
    	{
    		if(FAILED(m_hr=Initialize(bVisible)))
    			return m_hr;
    	}
    
    	{
    		VARIANT result;
    		VariantInit(&result);
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, m_pEApp, L"Workbooks", 0);
    		m_pBooks = result.pdispVal;
    	}	
    
    	{
    		VARIANT result;
    		VariantInit(&result);
    		m_hr=OLEMethod(DISPATCH_METHOD, &result, m_pBooks, L"Add", 0);
    		m_pActiveBook = result.pdispVal;
    	}
    	return m_hr;
    }
    
    HRESULT CMSExcel::SetExcelValue(LPCTSTR szRange,LPCTSTR szValue,bool bAutoFit, int nAlignment)
    {
    	if(!m_pEApp) return E_FAIL;
    	if(!m_pActiveBook) return E_FAIL;
    	IDispatch *pSheets;
    	{
    		VARIANT result;
    		VariantInit(&result);
    
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, m_pActiveBook, L"Sheets", 0);
    		pSheets = result.pdispVal;
    	}
    	IDispatch *pSheet;
    	{
    		VARIANT result;
    		VariantInit(&result);
    		VARIANT itemn;
    		itemn.vt = VT_I4;
    		itemn.lVal = 1;
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheets, L"Item", 1, itemn);
    		pSheet = result.pdispVal;
    	}
    	
    	IDispatch* pRange;
    	{
    		//COleVariant oleRange(szRange);
    		VARIANT xx;
    		xx.vt=VT_BSTR;
    		xx.pcVal = _T("a1");
    	
    		VARIANT result;
    		VariantInit(&result);
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, xx);
    		pRange = result.pdispVal;
    	}
    
    	{
    		//COleVariant oleValue(szValue);
    		m_hr=OLEMethod(DISPATCH_PROPERTYPUT, NULL, pRange, L"Value", 1, "aa");
    	}
    
    
    	if(bAutoFit)
    	{
    		IDispatch* pEntireColumn;
    		{
    			VARIANT result;
    			VariantInit(&result);
    			m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pRange, L"EntireColumn",0);
    			pEntireColumn= result.pdispVal;
    		}
    
    		{
    			m_hr=OLEMethod(DISPATCH_METHOD, NULL, pEntireColumn, L"AutoFit", 0);
    		}	
    		pEntireColumn->Release();
    	}
    
    	{
    		VARIANT x;
    		x.vt = VT_I4;
    		x.lVal = nAlignment;
    		m_hr=OLEMethod(DISPATCH_PROPERTYPUT, NULL, pRange, L"HorizontalAlignment", 1, x);
    	}
    
    	pRange->Release();
    	pSheet->Release();
    	pSheets->Release();
    	return m_hr;
    }
    
    HRESULT CMSExcel::Quit()
    {
    	if(m_pEApp==NULL) return E_FAIL;
    	DISPID dispID;
    	LPOLESTR ptName=(LPOLESTR)"Quit";// LPOLESTR ptName=_T("Quit");
    	m_hr = m_pEApp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
    	
    	if(SUCCEEDED(m_hr))
    	{
    		DISPPARAMS dp = { NULL, NULL, 0, 0 };
    		m_hr = m_pEApp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, 
    									&dp, NULL, NULL, NULL);
    	}
    	m_pEApp->Release();
    	m_pEApp=NULL;
    	return m_hr;
    }
    
    
    CMSExcel::~CMSExcel(void)
    {
    	Quit();
    	CoUninitialize();
    }

    xls.h:
    Code:
    #include "classes.h"
    #ifndef xls_h
    #define xls_h
    
    class CMSExcel
    {
    protected:
    	HRESULT m_hr;
    	IDispatch*	m_pEApp;
    	IDispatch*  m_pBooks;
    	IDispatch*	m_pActiveBook;
    private:
    	HRESULT Initialize(bool bVisible=true);
    public:
    	CMSExcel(void);
    	~CMSExcel(void);
    	HRESULT SetVisible(bool bVisible=true);
    	HRESULT NewExcelBook(bool bVisible=true);
    	HRESULT SetExcelValue(LPCTSTR szRange,LPCTSTR szValue,bool bAutoFit, int nAlignment);
    	HRESULT Quit();
    };
    
    HRESULT OLEMethod(int nType, VARIANT *pvResult, IDispatch *pDisp,LPOLESTR ptName, int cArgs...);
    
    
    
    
    #endif


    and let's say that i call this somewhere from main.cpp:
    Code:
    CMSExcel xx;
    xx.NewExcelBook(true);
    xx.SetExcelValue("a2","1",true,1);




    The error is:
    Unhandled exception at 0x00B996C3 in Kredens (OLE aut).exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.

    and it's caused in OLEMEthos function at the line:
    WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);


    where this OLEMethod is called by (/from):
    m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, xx);

    I guess i did some stupid mistake when i was copying the code from some example, not fully understanding it.
    I believe you are right saying that it must have somethign to do with that conversion thing which i dont quite understand yet.

  15. #15
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Wallisellen (ZH), Switzerland
    Posts
    17,360

    Re: COleVariant in WinAPI (afxdisp.h)

    Quote Originally Posted by berkov View Post
    Code:
    ...
    	IDispatch* pRange;
    	{
    		//COleVariant oleRange(szRange);
    		VARIANT xx;
    		xx.vt=VT_BSTR;
    		xx.pcVal = _T("a1");
    	
    		VARIANT result;
    		VariantInit(&result);
    		m_hr=OLEMethod(DISPATCH_PROPERTYGET, &result, pSheet, L"Range", 1, xx);
    		pRange = result.pdispVal;
    	}
    ...
    Well, Did you read the documentation about VARIANT in MSDN?
    It states that for pcVal you have to use VT_BYREF | VT_I1. And if you set the type as VT_BSTR you have to set the bstrVal, not a B]pcVal[/B].

    And again: why do you use such a mixture of L"...", T("...") and "..."?
    Victor Nijegorodov

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center