|
aha, CodeProject to the rescue.
http://www.codeproject.com/wtl/mix_wtl_mfc.asp
Apparently there are some #define's you can set to cause WTL to not define symbols that will clash with MFC (which puts everything in the global namespace)
|
|
|
|
|
Please not that is for VC6/ATL3. It may not work with your development environment if it's VS.NET/ATL7.
Come to think of it, there is some wizard in VS.NET that allows "adding ATL support to MFC projects". Please try that before trying my previous response.
And the #define stuff mentioned in the article too.
--
He just smiled and gave me a vegemite sandwich.
|
|
|
|
|
WTL7.1 in an ATL7 environment (VS.NET and later) will assume there is a global variable called _AtlBaseModule .
I can't remember all functions it must have, but you'll figure it out as you see the compilation errors. I know it needs a function called GetResourceHandle() . It should just return the HINSTANCE for your resources.
I would suggest that you do something like this in your stdafx.h:
#include "youratlbasemodule.h"
extern YourAtlBaseModuleEmulator _AtlBaseModule;
#include <atlapp.h>
#include <atlctrls.h>
...
And then in your youratlbasemodule.h:
class class YourAtlBaseModuleEmulator {
HINSTANCE m_hInstance;
public:
void SetResourceInstance(HINSTANCE hInstance) { m_hInstance = hInstance; }
HINSTANCE GetResourceInstance() { return m_hInstance; }
};
And then in your "main" cpp file:
#include "youratlbasemodule.h"
...
YourAtlBaseModuleEmulator _AtlBaseModule;
...
_AtlBaseModule.SetResourceInstance(hInstance);
I think something along those lines should work. I have never done it before.
--
He just smiled and gave me a vegemite sandwich.
|
|
|
|
|
Thanks for the explicit examples!
There are so many hot (trendy?) WTL controls out there that I'd love to use in my apps, but getting the code to compile together has always been a bottle neck.
|
|
|
|
|
I want to harness the power of STL in my code. But I am not able to become comfortable with STL. May be because of my inexperience.
Presently I am working with string . What I want to pass from a dll a function which will accept List of employees and Number of employees and I will save it in a class member variable. How to do it is the question?
|
|
|
|
|
Hello everyone:
Could you teach me how to read file line by line?
If having some samples, please send to me by email.
Thank you.
-Freehawk.
|
|
|
|
|
freehawk wrote:
Could you teach me how to read file line by line?
Look up getline.
freehawk wrote:
If having some samples, please send to me by email.
No. If you won't look here again for your answer, especially when the site sends you an email to say you've been replied to, why should we send you an email and risk ending up on a spam list somewhere ?
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
Thank you for the reply.
where is the "getline"? Could I use it in a wtl7.1 project?
-Freehawk
|
|
|
|
|
the beauty of solutions like using getline are that they are part of C++, not part of any framework. Therefore you can use them in any C++ project. I *think* getline lives in iostream ( NOT iostream.h ). ifstream lives in fstream.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
Here is the solution using std::getline().
std::string sInput;
std::getline(inputStream, sInput);
Kuphryn
|
|
|
|
|
Thank you very much.
It is just what I need.
I will try it.
-Freehawk
|
|
|
|
|
Hello everyone:
Example I receive some messages and want to do somethings same with clicking the button of toolbar, how to realize?
and how to disble/enable the buttons of toolbar?
Thank you.
-Freehawk.
|
|
|
|
|
|
Thank you very much.
I will try it.
-Freehawk
|
|
|
|
|
Hello everyone:
I want to transfer a function pointer from a WTL project to a MFC dll.
Do I need to make the function as a CALLBACK function?
How to transfer it?
-Freehawk
|
|
|
|
|
Through a function call perhaps? How would you do it otherwise?
Just define the function pointer type in a header file which the MFC dll and WTL project has access to during compile time. And add a function in the MFC dll which can deliver the function pointer.
I.e.:
typedef void (*FuncPtr)(type, type2, type3);
void InstallFunctionCallback(FuncPtr fptr);
And implement InstallFunctionCallback accordingly in your MFC dll.
--
Try walking in my shoes. You stumble in my footsteps.
|
|
|
|
|
Thank you for the reply.
I finished it, but I have not made the function as a callback function.
could you tell me what difference is between a function and a callback function translated
to dll as a function pointer?
-Freehawk
|
|
|
|
|
freehawk wrote:
tell me what difference is between a function and a callback function translated
to dll as a function pointer?
There is no difference really. Callback is just a semantic label for programmers.
--
Try walking in my shoes. You stumble in my footsteps.
|
|
|
|
|
Thank you for the reply.
I did it.
-Freehawk
|
|
|
|
|
I need to allocate and fill a large block of bytes in an ATL object, then pass that memory back to the client, which can delete it when it wants to.
i tried this:
<br />
[id(3), helpstring("method MFIGetFrame")] HRESULT MFIGetFrame([in] ULONG FrameIdx, [out] unsigned char **FrameArray, [out,retval] ULONG* Retval);<br />
but the COleDispatchDriver wrapper returns DISP_E_BADVARTYPE, because it doesn't know what to do with the "unsigned char **" .
i've tried using:
[id(3), helpstring("method MFIGetFrame")] HRESULT MFIGetFrame([in] ULONG FrameIdx, [out] SAFEARRAY(unsigned char)*FrameArray, [out,retval] ULONG* Retval);<br />
but the compiler keeps giving me: "error C2061: syntax error : identifier 'tagSAFEARRAY'".
i'm using VS.Net, which seems to make everything twice as hard as it needs to be.
any ideas?
ClickPic | ImgSource | CheeseWeasle
|
|
|
|
|
First, if you are returning an array in COM/IDL, you need to make it "conformant". You do that by indicating the number of elements in your array. I.e.:
HRESULT MFIGetFrame([in] ULONG FrameIdx, [out] ULONG* ArraySize, [out, size_is(1, *ArraySize)] unsigned char** FrameArray, [out, retval] ULONG* Retval)
At least that's what Essential IDL by Martin Gudgin told me last night.
As for the SAFEARRAY business, have you tried importing oaidl.idl? import "oaidl.idl"; It should be imported by default if I'm not mistaken though.
--
Try walking in my shoes. You stumble in my footsteps.
|
|
|
|
|
Jörgen Sigvardsson wrote:
have you tried importing oaidl.idl? import "oaidl.idl";
i tried that. but the error is actually happening in the "__interface" section of the ATL object's .H header (not in the IDL). apparently VC7 puts the IDL stuff right in the .H file, instead of an external IDL... ?
and, i can't figure out how to do an import in that __interface section.
ClickPic | ImgSource | CheeseWeasle
|
|
|
|
|
Just out of curiosity.. if you are calling the object using COleDispatchDriver, why not call using the vtable instead? Or is the interface a pure dispinterface, and you cannot in any way make the interface dual?
--
Try walking in my shoes. You stumble in my footsteps.
|
|
|
|
|
Jörgen Sigvardsson wrote:
why not call using the vtable instead?
never done that before. i've always used COleDispatchDriver (and the project i'm doing this for is designed to use them).
i'm about to scrap the whole COM/ATL thing and just go back to plain old C-interfaced DLLs. ATL is far more trouble than it's worth.
ClickPic | ImgSource | CheeseWeasle
|
|
|
|
|
Hello Chris,
Don't give up yet, Chris .
>> ... i've always used COleDispatchDriver
Looks like your COM Server is meant to be IDispatch-based or dual interfaced. I did some experiments based on your sample code and came up with the following :
interface IMFIObject : IDispatch
{
[id(1), helpstring("method MFIGetFrame")] HRESULT MFIGetFrame([in] long FrameIdx, [out] VARIANT *pFrameArray, [out,retval] long* Retval);
};
In essence, I changed your second parameter from :
[out] unsigned char **FrameArray
and
[out] SAFEARRAY(unsigned char)*FrameArray
to :
[out] VARIANT *pFrameArray
This is how I implemented the method :
STDMETHODIMP CMFIObject::MFIGetFrame(long FrameIdx, VARIANT *pFrameArray, long *Retval)
{
// TODO: Add your implementation code here
LPBYTE lpbyToReturn = NULL;
SAFEARRAY* lpSafeArrayOfBytes = NULL;
lpbyToReturn = (LPBYTE)malloc(1024);
memset (lpbyToReturn, 'B', 1024);
// Wrap up lpbyToReturn in a SAFEARRAY.
CreateSafeArrayFromBytes
(
(LPBYTE)lpbyToReturn,
(ULONG)1024,
(SAFEARRAY**)&lpSafeArrayOfBytes
);
if (lpSafeArrayOfBytes)
{
// Note well that this function should always return a
// pointer to what is logically returned.
V_VT(pFrameArray) = VT_ARRAY | VT_UI1;
V_ARRAY(pFrameArray) = lpSafeArrayOfBytes;
}
if (lpbyToReturn)
{
free (lpbyToReturn);
lpbyToReturn = NULL;
}
*Retval = 1024;
return S_OK;
}
Here is a summary of what happens in the function :
1. I allocate an array of 1024 bytes and point to it via "lpbyToReturn". The number 1024 is not important. I simply wanted to "allocate and fill a large block of bytes in an ATL object" which is also what you wanted to achieve.
2. I then set all bytes in the array to the letter 'B'. This is done for verification purposes only.
3. I then create a SAFEARRAY and copy the data from the "lpbyToReturn" array to the SAFEARRAY.
4. I then take the second parameter "pFrameArray", which is a pointer to a VARIANT, and make it a valid VARIANT which holds a SAFEARRAY of BYTEs and make the VARIANT point to the newly created SAFEARRAY.
5. Note that I will now need to free the memory of the original array "lpbyToReturn". This is because the SAFEARRAY already contains the same BYTE values in "lpbyToReturn" .
6. Note that I do not free the SAFEARRAY because this is the memory block that is passed back to the client and the client is free to delete it whenever it wants to.
By the way, Chris, I've also supplied the source codes to CreateSafeArrayFromBytes() :
long CMFIObject::CreateSafeArrayFromBytes
(
LPBYTE lpbyBytes,
ULONG ulSize,
SAFEARRAY** ppSafeArrayReceiver
)
{
HRESULT hrRetTemp = S_OK;
SAFEARRAY* pSAFEARRAYRet = NULL;
SAFEARRAYBOUND rgsabound[1];
ULONG ulIndex = 0;
long lRet = 0;
// Initialise receiver.
if (ppSafeArrayReceiver)
{
*ppSafeArrayReceiver = NULL;
}
if (lpbyBytes)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = ulSize;
pSAFEARRAYRet = (SAFEARRAY*)SafeArrayCreate
(
(VARTYPE)VT_UI1,
(unsigned int)1,
(SAFEARRAYBOUND*)rgsabound
);
}
for (ulIndex = 0; ulIndex < ulSize; ulIndex++)
{
long lIndexVector[1];
lIndexVector[0] = ulIndex;
SafeArrayPutElement
(
(SAFEARRAY*)pSAFEARRAYRet,
(long*)lIndexVector,
(void*)(&(lpbyBytes[ulIndex]))
);
}
if (pSAFEARRAYRet)
{
*ppSafeArrayReceiver = pSAFEARRAYRet;
}
return lRet;
}
Now, over to client code. I made sure that my client code will also use the COleDispatchDriver class :
void CVCTestDlg::OnBnClickedButtonGetdynamicarrayfromobject()
{
// TODO: Add your control notification handler code here
IDispatch* pIDispatch = NULL;
COleDispatchDriver ole_disp_driver;
SAFEARRAY* pSafeArrayOfBytes = NULL;
m_spIMFIObject -> QueryInterface (IID_IDispatch, (void**)&pIDispatch);
if (pIDispatch)
{
long lRet = 0;
long lRet2 = 0;
BYTE byParamInfo[2 * 2 + 1];
VARIANTARG pVar;
VariantInit(&pVar);
VariantClear(&pVar);
ole_disp_driver.AttachDispatch(pIDispatch, FALSE);
sprintf ((LPTSTR)byParamInfo, TEXT("%s%s"), VTS_I4, VTS_PVARIANT);
ole_disp_driver.InvokeHelper(0x01, DISPATCH_METHOD, VT_I4, (void*)&lRet, byParamInfo, 1, &pVar);
pIDispatch -> Release();
pIDispatch = NULL;
pSafeArrayOfBytes = pVar.parray;
}
if (pSafeArrayOfBytes)
{
SafeArrayDestroy (pSafeArrayOfBytes);
pSafeArrayOfBytes = NULL;
}
return;
}
Notice that I defined a pointer to a SAFEARRAY object "pSafeArrayOfBytes" which will be filled by the MFIGetFrame() method which is of ordinal 0x01 in my example.
At the end of the function, I will actually delete the SAFEARRAY :
if (pSafeArrayOfBytes)
{
SafeArrayDestroy (pSafeArrayOfBytes);
pSafeArrayOfBytes = NULL;
}
I hope that the above code will be useful to you. Email me if you should want the full scource codes to the above sample. My email address is :
bllim@singnet.com.sg
Best Regards,
Bio.
|
|
|
|