|
-
Jan 8th, 2003, 02:01 AM
#1
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 ?
-
Jan 8th, 2003, 03:44 AM
#2
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 ?
-
Jan 8th, 2003, 04:55 AM
#3
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.
-
Jan 8th, 2003, 12:23 PM
#4
Thanks
How about for Variant ??
Where can I find a list of all the VB types that I can use in my COM object ?
-
Jan 8th, 2003, 12:28 PM
#5
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.
-
Jan 8th, 2003, 12:30 PM
#6
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.
-
Jan 8th, 2003, 04:14 PM
#7
Thanks for that code, it helped me figure out some things...
Another question yet 
How do you make Properties ? (with Get/Let)
-
Jan 8th, 2003, 04:20 PM
#8
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.
-
Jan 8th, 2003, 04:23 PM
#9
Don't know how to get to the wizad....
-
Jan 8th, 2003, 05:04 PM
#10
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.
-
Jan 9th, 2003, 04:47 PM
#11
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:
Private Sub Form_Load()
Dim K As Integer, C As New CLinkList
Debug.Print C.AppendItem("Hello"),
Debug.Print C.AppendItem("how"),
Debug.Print C.AppendItem("are"),
Debug.Print C.AppendItem("you"),
Debug.Print C.AppendItem("today"),
Debug.Print C.AppendItem("?")
C.GoToIndex 1
Debug.Print "GetItem", C.Item
Debug.Print "GetItem", C.Item
C.Item = "aaaa"
Debug.Print "GetItem", C.Item
Debug.Print "GetItem", C.Item '<- IT WILL CRASH HERE !!!
End Sub
I don't understand why it's crashing the second time I call the Item after i modify the data...
-
Jan 9th, 2003, 05:05 PM
#12
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.
-
Jan 9th, 2003, 05:26 PM
#13
It show this screen, and then the hole VB closes...
-
Jan 9th, 2003, 05:32 PM
#14

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.
-
Jan 9th, 2003, 05:33 PM
#15
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.
-
Jan 9th, 2003, 07:01 PM
#16
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)
-
Jan 9th, 2003, 07:04 PM
#17
By the way... Is there a document on how to properly use a VARIANT ? (I mean, the way VB likes it)
-
Jan 9th, 2003, 07:50 PM
#18
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...
-
Jan 9th, 2003, 10:32 PM
#19
FINALLY !!
I had to use the VariantCopyInd to copy the Variants instead of the = ...
-
Jan 11th, 2003, 08:48 AM
#20
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.
-
Jan 12th, 2003, 03:11 AM
#21
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...
-
Jan 12th, 2003, 05:16 AM
#22
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.
-
Jan 12th, 2003, 05:17 AM
#23
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.
-
Jan 12th, 2003, 04:00 PM
#24
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)
-
Jan 12th, 2003, 05:50 PM
#25
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|