|
|
I am converting an old VB COM object (which I didn't write) to C++ using ATL. One of the methods, according to the IDL, takes an IDispatch* as a parameter and the documentation and samples for this method claim that you can pass either a string (which is the progid of an object that will be created and used by the control) or an IDispatch* to an object that has already been created. How on earth do I implement this in ATL?
For example, the IDL:
[id(1)] HRESULT Test(IDispatch* obj);
The samples (which are all JScript):
obj.Test("foo.bar");
or
var someObject = new ActiveXObject("foo.bar");
obj.Test(someObject);
To make matters even more bizarre the actual VB code that implements this method actually declares the 'obj' parameter as a string! However, it all seems to work.
Can you even pass a string to a COM method that takes an IDispatch* ? If so, can I determine that the IDispatch* is actually a string in my C++ ATL code? Even better, if it's an IDispatch that implements a specific interface I will want to call methods on it, or instantiate an object if it's a string.
I think that fact that JScript is in play here could be crucial (for example, JScript doesn't pass arrays as a SAFEARRAY and requires some magic to extract the length and the value of each element.)
|
|
|
|
|
Rob - firstly - can you examine the type library of the old VB object, to verify that the IDL declaration matches it? Use the OLE/COM object viewer that's part of the Windows SDK and use the File->View TypeLib... option to do that.
Because what your saying makes me think the method's parameter is actually a VARIANT ...that would certainly allow a client to pass string or IDispatch with impunity.Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
CodeProject MVP for 2010 - who'd'a thunk it!
|
|
|
|
|
That's what I concluded and have changed my ATL object to use a VARIANT with a check for VT_DISPATCH or VT_BSTR accordingly - and it works a treat.
|
|
|
|
|
Excellent! Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
CodeProject MVP for 2010 - who'd'a thunk it!
|
|
|
|
|
Hi All.
I develope an addon based on MotleyFool example. User must do login to that, for using its functionality. In IE 8 when adding new tab or opening new IE window, new login is need. This occures beacause new instance of this addon creates.
How I can share any instance between multiple tab or multiple IE win?
Excuse me for weakness of my language.
thanks a'lot.
|
|
|
|
|
Can you think about some communication between the multiple instances of the add-ons? Like when user has logged on with an instance, then all other instances are notified about it. And any new instance can check a shared value if the user has logged on or not. Something like that.
|
|
|
|
|
Creating an WMP visualization (VS2005, Win2003 sdk, ATL)
Created an array of values.
Need to create an checkbox for each value in the array.
Currently my OnInit() looks like this
extern CSimpleArray<CString> sPorts;
for (int x = 0; x < sPorts.GetSize(); ++x)
{
::MessageBox (NULL, sPorts[x], TEXT ("COM PORT FOUND"), 0);
}
Basically below is the download for my current project. Everything so far is working but im having difficulty is setting up the properties box for the visualization. What i need is;
1 - Create an checkbox for each value in sPorts array.
2 - On 'Ok' save the checked items back to an array
http://www.4shared.com/file/228431443/1538a24d/USBGlowLight.html[^]
Anyone able/willing to help as i've hit an brick wall and am kinda an noob to c++ as havent done any in abt 6 years.
|
|
|
|
|
You can create check boxes dynamically using the CreateWindow API.
Specify "BUTTON" as the class name and BS_CHECKBOX as one of its styles.
|
|
|
|
|
You have already been given a solution here[^], which you said was working. txtspeak is the realm of 9 year old children, not developers. Christian Graus
|
|
|
|
|
Good afternoon I currently write a IcopyHook shell using visual studio 2008 and atl I have this compile error:
Error 1 error C2259: 'ATL::CComObject<Base>' : cannot instantiate abstract class c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\atlcom.h 1801
this is a piece of code I use to do so:
#ifndef __MYHOOK_H_
#define __MYHOOK_H_
#include "resource.h"
class ATL_NO_VTABLE CMyHook :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyHook, &CLSID_MyHook>,
public ICopyHook,
public IDispatchImpl<IMyHook, &IID_IMyHook, &LIBID_COPYHOOKLib>
{
public:
CMyHook()
{
}
STDMETHOD_(UINT,CopyCallback) (HWND hwnd, UINT wFunc, UINT wFlags, LPCWSTR pszSrcFile, DWORD dwSrcAttribs,
LPCWSTR pszDestFile, DWORD dwDestAttribs);
DECLARE_REGISTRY_RESOURCEID(IDR_MYHOOK)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMyHook)
COM_INTERFACE_ENTRY_IID(IID_IShellCopyHook , CMyHook)
COM_INTERFACE_ENTRY(IMyHook)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
};
#endif //__MYHOOK_H_
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "CopyHook.h"
#include "CopyHook_i.c"
#include "MyHook.h"
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_MyHook, CMyHook)
END_OBJECT_MAP()
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID )
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance, &LIBID_COPYHOOKLib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE;
}
STDAPI DllCanUnloadNow(void)
{
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
STDAPI DllRegisterServer(void)
{
return _Module.RegisterServer(TRUE);
}
STDAPI DllUnregisterServer(void)
{
return _Module.UnregisterServer(TRUE);
}
Thank you
|
|
|
|
|
Are you sure you're creating a wide version of ICopyHook? Why not use ICopyHookW and IID_ICopyHookW to make 100% sure. Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
CodeProject MVP for 2010 - who'd'a thunk it!
|
|
|
|
|
Hi,
I have serveral MFC Client applications connecting to ATL Exe server. I have the following problem where if one of the client applications crashes, the Server never shutdown gracefully. I noticed the reference count is never decremented. Is there a way to address this?
Thanks
Marko
|
|
|
|
|
Fixing the client app's crash would be an option. And in addition to that you can consider using smart pointers (if you are not already using it) so that smart pointers will take care of addref and release automatically. It will properly release interface pointers during a exception.modified on Monday, February 22, 2010 11:48 PM
|
|
|
|
|
Hey
Guess this is a very common question. In my case it obtains to DirectX (9... d3d9, whatever ^^). I've read that DirectX 9 comes around with COM interfaces and can be used from ATL. Now I am writing a library which should use Direct3D types (Such as D3DVECTOR, D3DCOLOR,...) after raping google for days now without some usefull code I decidet to post my question here hoping to get an awnser.
Well, my problem is that I want to pass DirectX types to interface methods. Something like this:
interface ITest : IUnknown
{
[propget, helpstring("BackroundColor")] HRESULT BackroundColor([out, retval] D3DCOLOR* pVal);
[propput, helpstring("BackroundColor")] HRESULT BackroundColor([in] D3DCOLOR newVal);
};
So far so good, but somehow the MIDL compiler must know the D3DCOLOR type. I've read about redefining it in this way:
cpp_quote("#if 0")
typedef DWORD D3DCOLOR;
cpp_quote("#else")
cpp_quote("#include <d3d9.h>")
cpp_quote("#endif")
But this does not work for structures (like D3DVECTOR). Now I've tried tons of alternative solutions, but none worked. Unfortunately there is no d3d9.idl file shipping with the DirectX SDK and just refering to the d3d9.dll library using importlib wont work since the statement must only be used in the library block, but I need the types in the interface definitions!
Is there any solution to do this? Would be really cool if you have any ideas
Thanks,
- Aschratt.http://www.aschratt.com
|
|
|
|
|
Aschratt wrote: this does not work for structures (like D3DVECTOR
You can define your own structures in idl if you know what the type e.g. D3DVECTOR contains (it has to be composed of idl types) e.g.
typedef struct tagD3DVECTOR
{
unsigned long D1;
unsigned short D2 y;
unsigned char Data[4];
} D3DVECTOR;
and then use is as a parameter. When compiled to produce a C++ this may then conflict with your DirectX types so perhaps you could rename it, say _D3DVECTOR or MyD3DVECTOR.
|
|
|
|
|
OK, thanks for the awnser. So I need to create the structures on my own... hmm. That's not so bad, but I hoped there is a way to import the DirectX structures... thanks anyway http://www.aschratt.com
|
|
|
|
|
I'm not saying there isn't, just I don't know if there is without playing around. Al Major's book: COM IDL and Interface Design says to include the ontents of other files you have three options:
#include stdio.h in, say, example.idl and 'all legitimate declarations ... would make their way into the generated example.h file'.
import 'is the standard method for bringing in definitions from other IDL, ODL or C/C++ header files into the main IDL file'.
and:
importlib 'which can only occur in the body of the library statement'. For this need a type library such as .tlb or as can be contained within a COM .dll.
|
|
|
|
|
Yes, but none of those 3 ways are making sense for me. I need types from the "d3d9.h" or "d3dx9.h" file. So why this does not work?
- #include <d3d9.h> will not work since the content could not be understood by the MIDL compiler.
- import [...] will not work since Microsoft does not ship an "d3d9.idl" (or any IDL source) with the DirectX SDK for some reason...
- importlib("d3d9.dll") is the solution which makes most sense, but importlib can only be used inside the library block and this is too late. MIDL needs to know the types when it compiles the interfaces and it first gets to know them after it does.
So I do not brake a leg with creating those types on my own (there are not much I need... just some vectors and matrixes). Using them it should be no problem to create some conversion methods which are only accessible internally. So I could convert those new custom types to DirectX types for using them. http://www.aschratt.com
|
|
|
|
|
I did a couple of searches on my PC and found D3DCOLOR defined in in vmr9.idl:
cpp_quote("#if 0")
typedef DWORD IDirect3DDevice9;
typedef DWORD IDirect3DSurface9;
typedef DWORD D3DFORMAT;
typedef DWORD D3DCOLOR;
typedef DWORD D3DPOOL;
typedef LONGLONG REFERENCE_TIME;
typedef DWORD* HMONITOR;
typedef struct {DWORD dw1; DWORD dw2;} AM_MEDIA_TYPE;
cpp_quote ("#endif")
and in dxtrans.idl I found:
#ifndef DDSURFACEDESC
cpp_quote("#if 0")
cpp_quote("// Bogus definition used to make MIDL compiler happy")
typedef void DDSURFACEDESC;
typedef void D3DRMBOX;
typedef void D3DVECTOR;
typedef void D3DRMMATRIX4D;
typedef void* LPSECURITY_ATTRIBUTES;
cpp_quote("#endif")
#endif
So looks like you're not the only one to come accross this problem.
|
|
|
|
|
Yes, I also found this file around the net... but if I try to define interfaces that way it allways tells me...
error MIDL2011 : unresolved type declaration : IDirect3DDevice9 [ Parameter 'device' of Procedure 'Initialize' ( Interface 'ICamera' ) ]
... if I define the interface that way:
cpp_quote("#if 0")
interface IDirect3DDevice9;
cpp_quote("endif")
And if I define it as an DWORD...
typedef DWORD IDirect3DDevice9;
... the compiler pops up an error "Redefinition of 'IDirect3DDevice9' with different base types".
Still I have no idea how to get the IDirect3DDevice9 interface passed to my interface... any ideas?
// EDIT: at the moment I am simply passing an IUnknown pointer to the method and query back the interface to IDirect3DDevice9...http://www.aschratt.com
modified on Sunday, February 21, 2010 10:55 AM
|
|
|
|
|
Aschratt wrote: Still I have no idea how to get the IDirect3DDevice9 interface passed to my interface... any ideas?
Sorry I'm out of ideas if an IDL definition for IDirect3DDevice9 can't be found - apart from using IUnknown as you mention, .
|
|
|
|
|
Hm thanks anyway... perhaps it is not the "best" solution I am working with, but it is an solution and it does it's work. Thank you very much http://www.aschratt.com
|
|
|
|
|
Hello,
I want to create installation of ATL COM component. I can create .MSI file using setup and deployment project in VS2005. But I want to create .exe file which does not require any MSI installation on machine.
Thanks
abm
|
|
|
|
|
It seems, the VS Setup & Deployment wizard doesn't support single exe setup
|
|
|
|