Results 1 to 25 of 25

Thread: How to make an MFC Class to be used in VB6 ??

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    How to make an MFC Class to be used in VB6 ??

    I am using C++ .NET, and I want to make a class (MFC DLL) to be used in VB6.0.

    I made the class, I've added the DLL to the references.

    But when I go to "Object Browser" (F2), it shows only the class, but without my public members, just the class, that's it....

    Code:
    class BinaryCollection : public CWnd
    {
    	DECLARE_DYNAMIC(BinaryCollection)
    
    public:
    	BinaryCollection();
    	virtual ~BinaryCollection();
    	virtual void OnFinalRelease();
    
    	long AddItem(long str);
    
    protected:
    	DECLARE_MESSAGE_MAP()
    	DECLARE_DISPATCH_MAP()
    	DECLARE_INTERFACE_MAP()
    };
    Right now I have only the AddItem, and as you can see it's public...

    So what else do I have to do, so I can use it in VB ?

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Nevermind... I'm using the wrong file type thing... it's supposed to be a COM component...

    But now I have another question:

    I made a ATL COM component, I added a class, and the function, but my problem now is:
    What variable type i use for the equivalent of the String ?

  3. #3
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    BSTR
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Thanks

    How about for Variant ??

    Where can I find a list of all the VB types that I can use in my COM object ?

  5. #5
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    VARIANT*

    I don't know where to find a full list.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  6. #6
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    And before you ask me about arrays...
    Code:
    // This function decodes a string to a byte array, wrapped up in a variant.
    STDMETHODIMP CBase64Coder::DecodeStringToByteArray(BSTR strIn, VARIANT* arByteOut)
    {
    	// Many functions have a HRESULT as return value.
    	HRESULT hr;
    	// A pointer to move over the input buffer
    	const wchar_t *p;
    	// Random loop index
    	UINT i=0;
    
    	// Check for error conditions.
    	// The output pointer could point to nothing.
    	if(arByteOut == NULL)
    	{
    		return E_POINTER;
    	}
    	// If strIn is NULL this may have two causes: an error may have occured or
    	// (more likely) the passed string is empty. For some reason VB passes NULL in that
    	// case. So let's just return an empty variant.
    	if(strIn == NULL)
    	{
    		// This most probably means that "" was passed.
    		VariantInit(arByteOut);
    		return S_OK;
    	}
    
    	// Find the length of the encoded data.
    	UINT uiSourceLength = SysStringLen(strIn);
    
    	// It's easier to work with CAtlString than with BSTR
    	CAtlStringW strUse;
    
    	// first go through string and kick out everything invalid
    	for(p=(const wchar_t *)strIn, i=0; i<uiSourceLength &&
    		(i==0 || (*(p-1) != L'=' || (*(p-1) == L'=' && *p == L'='))); ++p, ++i)
    	{
    		if(isbase64(*p))
    			strUse += *p;
    		else if(!isbase64allowed(*p))
    		{
    			// this character should not be there
    			// possible reactions:
    			// 1) warn
    			// 2) ignore <- I have chosen this.
    			// 3) fail
    		}
    	}
    
    	// There should be padding characters so that the character count is an exact
    	// multiple of 4. If not then something is wrong.
    	UINT pad = (UINT)strUse.GetLength() % 4;
    	if(pad != 0)
    	{
    		// again two options:
    		// 1) add padding so that it works and maybe warn
    		// 2) fail <-
    		return E_INVALIDARG;
    	}
    
    	// Initialize the output value and set its type to byte array.
    	VariantInit(arByteOut);
    	arByteOut->vt = VT_ARRAY | VT_UI1;
    
    	// Create a 1-dimensional array (1 to whatever is needed).
    	SAFEARRAYBOUND bound;
    	bound.cElements = strUse.GetLength()/4*3;
    	bound.lLbound = 1;
    	V_ARRAY(arByteOut) = SafeArrayCreateEx(VT_UI1, 1, &bound, NULL);
    	// The only real reason this call could fail is because there is no memory
    	// to allocate the array.
    	if(V_ARRAY(arByteOut) == NULL)
    		return E_OUTOFMEMORY;
    
    	// Now access the data
    	PBYTE pOut;
    	hr = SafeArrayAccessData(V_ARRAY(arByteOut), (void **)&pOut);
    	if(FAILED(hr))
    		return hr;
    
    	// Decode the string
    	for(p=strUse; *p; p+=4, pOut+=3)
    	{
    		GrabByteTriple(pOut, p);
    	}
    
    	// Clean up
    	hr = SafeArrayUnaccessData(V_ARRAY(arByteOut));
    	if(FAILED(hr))
    		return hr;
    
    	return S_OK;
    }
    isbase64, isbase64allowed and GrabByteTriple are functions defined by me, all others are API or ATL.
    Last edited by CornedBee; Jan 8th, 2003 at 12:33 PM.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Thanks for that code, it helped me figure out some things...

    Another question yet

    How do you make Properties ? (with Get/Let)

  8. #8
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    With the wizard. Right-click the interface, choose Add->Property and proceed from there.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  9. #9

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Don't know how to get to the wizad....

  10. #10
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    VC++6 or 7?
    Don't know how in 6, but in 7 you go to the solution explorer in class view, right-click the interface of your object (IYourObject or whatever) and choose Add->Property.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    OK, Have a problem, and I can't understand what's wrong...
    Code:
    class node
    {
    public:
    	node *prev;
    	node *next;
    	VARIANT data;
    
    	node(node *p, const VARIANT *s, node *n):prev(p), next(n)
    	{
    		VariantInit(&data);
    		data = *s;
    	}
    };
    
    node *curr;
    
    STDMETHODIMP CLinkList::get_Item(VARIANT* pVal)
    {
    	if(pVal)
    		if(!curr) *pVal = nothing;
    		else *pVal = curr->data;
    	
    	return S_OK;
    }
    
    STDMETHODIMP CLinkList::put_Item(VARIANT newVal)
    {
    	if(curr)
    	{	VariantClear(&(curr->data));
    		curr->data = newVal;
    	}
    
    	return S_OK;
    }
    VB Code:
    1. Private Sub Form_Load()
    2.     Dim K As Integer, C As New CLinkList
    3.    
    4.     Debug.Print C.AppendItem("Hello"),
    5.     Debug.Print C.AppendItem("how"),
    6.     Debug.Print C.AppendItem("are"),
    7.     Debug.Print C.AppendItem("you"),
    8.     Debug.Print C.AppendItem("today"),
    9.     Debug.Print C.AppendItem("?")
    10.    
    11.     C.GoToIndex 1
    12.     Debug.Print "GetItem", C.Item
    13.     Debug.Print "GetItem", C.Item
    14.     C.Item = "aaaa"
    15.     Debug.Print "GetItem", C.Item
    16.     Debug.Print "GetItem", C.Item    '<-  IT WILL CRASH HERE !!!
    17. End Sub

    I don't understand why it's crashing the second time I call the Item after i modify the data...

  12. #12
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Interesting indeed...

    Have you tried debugging? Compile the test VB app to an exe. Set a breakpoint in VC++ and press F5. It will ask you for a startup app. Browse for the VB app, and it will start the VB app and stop at your breakpoint.

    That way you can see why it crashes.

    Oh, btw, any specific message when it crashes?
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    It show this screen, and then the hole VB closes...


  14. #14
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594


    Microsoft...
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  15. #15
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    BTW, looks like VB somehow creates an access violation - as if some VARIANT was in a weird state.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  16. #16

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Do you know what this means ?
    I get this in the output window, debug

    HEAP[MikeClassesTest.exe]: Invalid Address specified to RtlSizeHeap( 00140000, 00402DE0 )
    Unhandled exception at 0x77f767cd in MikeClassesTest.exe: User breakpoint.

    And it never goes to this method:
    STDMETHODIMP CLinkList:: put_Item(VARIANT newVal)

  17. #17

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    By the way... Is there a document on how to properly use a VARIANT ? (I mean, the way VB likes it)

  18. #18

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    I just discovered....

    When I run the EXE, everything is fine... it does not crash, and it does everything properly...

    So what could it be then ?

    I want to be able to run my application from VB too...

  19. #19

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    FINALLY !!

    I had to use the VariantCopyInd to copy the Variants instead of the = ...

  20. #20
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Ah.

    The only docs I know of are MSDN. Start at VARIANT and follow the links from there.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    How can I do the equivalent of "Optional" in an ATL COM component ??

    I tried stuf like:
    HRESULT CreateJumpPoints([in] LONG Points = 0, [in] LONG JumpCount = 0, [out, retval] VARIANT_BOOL *retval = NULL);

    So, from VB, I just wanna call it by: myclass.CreateJumpPoints
    instead of: myclass.CreateJumpPoints 0, 0

    But it does not work...

  22. #22
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    I think optional is only possible for VARIANTs and would be
    [in, optional] VARIANT arg
    The resulting argument could either be VT_EMPTY or VT_ERROR.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  23. #23
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    ms-help://MS.VSCC/MS.MSDNVS/vcattrib/html/vcrefOptional.htm
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  24. #24

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Thanks... you've been very helpfull as usual...

    But now, how do I check if the user passed a long, or nothing (VT_EMPTY) ?

    Actually, how do I check what type user passed (in general) ?
    (later on in my class I will also have to check for String type in a VARIANT)

  25. #25

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803
    Ow... nevermind, I just saw it in your previous example

    arByteOut->vt = VT_ARRAY | VT_UI1;

Posting Permissions

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



Click Here to Expand Forum to Full Width