|
Trying to write an in-process component whose threading model will be "both". I want it to be instantiated in the same apartment as the client, irrespective of whether the client has entered an STA or MTA. If I understand right, the main criteria for writing this kind of component pertains to how I can perform callbacks to the client.
thanks
Man Learns from History that he never learns from History
|
|
|
|
|
That's right. If your component might use the client object on the thread other than STA (if the client is in STA), you'd have to do marshalling/unmarshalling of the client object "manually".
Edward
|
|
|
|
|
So would this work? When I decide I need to do a callback, I check the thread id of the current thread. If it matches the one that passed the callback pointer(which I would have stored somewhere), I make a direct call. If not, I call it via a proxy which I implement with custom marshalling.
BTW, if I dont use callbacks in the component, can I go ahead and implement it as "both" without worrying about anything else?
thanks!!
Man Learns from History that he never learns from History
|
|
|
|
|
I wouldn't bother with checking threadid, you rcomponent might be called from MTA.
If your object pointer is not being passed directly to another thread (for instance one of object's methods created thread and from this thread you invoke one of the objects methods) you do not have to worry about this at all.
And you are right, if you do not use other objects (callbacks or internally created com objects) in your component you don't have to worry about all this (of course synchronization must be taken care of).
As for marshalling, in case it's necessary, I usually prefer using GIT (global interface table, works on NT sp3, Win95 with dcom): for instance when object gets created I'd register it in the GIT (IGlobalInterfaceTable::RegisterInterfaceInGlobal) and then all other threads that need to use the object would get the interface pointer from GIT (GetInterfaceFromGlobal) instead of using it directly, this way none the object itself can use any internal com objects (callbacks) safely.
HTH,
Edward
|
|
|
|
|
So we do not need "custom" marshalling here, only "manual" invocation of the facilities already available. When the component gets the interface pointer to the callback object, it checks it into the GIT. When the client needs to be notified of something, the interface pointer is checked out from the GIT and the callback performed.
thanks
Steve
|
|
|
|
|
I am converting COM stuff to C#, but i'm not entirely sure about IEnumIDList.Next, or what exactly it returns.
HRESULT Next( ULONG celt,
LPITEMIDLIST *rgelt,
ULONG *pceltFetched
);
Now, celt is supposed to be the size of the LPITEMIDLIST right? So this enables people to look up multiple items in one go?
The pCeltFetched is a value that indicates how many items are actualy returned of the ones you desire?
Am I right here?
I've written some code that uses this interface and appears to work fine (Note, I get the IEnumIDList via the SHGetDesktopFolder, and the methods call ok when the result is cast). But No matter how big I make Celt, i always get back 17 (I have 12 non Shortcut Items, 7 shortcut items and recycle bin on my desktop) different <rgelt> values before it begins returning null pointers (No S_False value is returned, always returns 0). Also, the pCeltFetched is always 1, until the 7th value is reached, and then it is 0.
I can't determine what is being returned in the array as I haven't casted rGelt.
This is an array of ITEMIDLIST's? Or a pointer to ITEMIDLIST that is an array?
Could someone explain this method to me, as it's mildly confusing - being new to COM and all.
Cheers
Cata
NOTE: Not sure if this is any help, but here is the sample of code that I am using to call the function. It has no purpose, i'm just experimenting, but it might show what's wrong:
<br />
ArrayList MyIntPtrArray = new ArrayList();<br />
int myInt = 0;<br />
IntPtr item = new IntPtr();<br />
int result;<br />
<br />
do<br />
{<br />
result = IDList.Next(10, ref item, out myInt);<br />
if (item.ToInt32() != IntPtr.Zero.ToInt32())<br />
{<br />
MyIntPtrArray.Add(item);<br />
}<br />
<br />
}while(item.ToInt32() != IntPtr.Zero.ToInt32());<br />
<br />
Where result is always 0. myInt is 1 until the method retuns null pointers. Item is new for every iteration up to 17 (that's the arraylist count when the program finishes).
|
|
|
|
|
The Catalyst wrote:
Am I right here?
Yes you are. For reference, see IEnumXXX in the MSDN docs.
The Catalyst wrote:
This is an array of ITEMIDLIST's? Or a pointer to ITEMIDLIST that is an array?
It's an array of LPITEMIDLIST which is an array of pointers to ITEMIDLISTs.
Now, I'm no C#/COM guru, but I think your sample code is wrong. It should probably be something like this:
IntPtr arr[] = new IntPtr[10];
int num;
do {
IDList.Next(10, out arr, out num);
for(int i = 0; i < num; ++i) {
doSomething(arr[i]);
}
} while(num == 10);
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
Hi all,
I am new in ATL COM, I have created a Simple Object using ATL Object wizard,
and one simple Method.
The appwizard generated something like this
<br />
class ATL_NO_VTABLE CSimpleObject :
public CComObjectRootEx<CComSingleThreadModel>,<br />
public CComCoClass<CSimpleObject, &CLSID_SimpleObject>,<br />
public IDispatchImpl<ISimpleObject, &IID_ISimpleObject, &LIBID_FIRSTLib><br />
{<br />
}<br />
Now i am trying to use this component in client(mfc app), for that i have imported the header file of the component(simpleobject.h) in my mfc app.
When i try to compile my mfc app.
Its gives me
error C2079: 'CSimpleObject' uses undefined class 'ATL_NO_VTABLE
Can anybody tell what is error in ATL world??
Thanks in advance,
Abhi Lahare
|
|
|
|
|
It's a macro which expands to __declspec(novtable) for Visual C++. This is a hint to the compiler not to set the virtual function table pointer in the constructor. From the documentation:
"This form of __declspec can be applied to any class declaration, but should only be applied to pure interface classes, that is, classes that will never be instantiated on their own. The __declspec stops the compiler from generating code to initialize the vfptr in the constructor(s) and destructor of the class. In many cases, this removes the only references to the vtable that are associated with the class and, thus, the linker will remove it. Using this form of __declspec can result in a significant reduction in code size.
"If you attempt to instantiate a class marked with novtable and then access a class member, you will receive an access violation (AV)."
You don't normally use an ATL object derived from CComObjectRootEx directly; instead, the ATL class factory generates a CComObject<CSimpleObject> when it's asked to by COM. Eliminating the vtable can save on both code size (through not setting the vfptr) and on data size (through omitting CSimpleObject's vtable).
If you don't want to use CSimpleObject as a COM object, remove ATL_NO_VTABLE, all of the CComXxx base classes, and IDispatchImpl .
If instead you want to use the COM object from your MFC application (leaving the object implementation in the DLL), use ClassWizard or a #import statement to reference the type library. You could also use the interface headers generated from the IDL file that describes the object's interfaces. Use CoCreateInstance to create the object.
|
|
|
|
|
Hi Mike,
I want to do
MiKe:
If instead you want to use the COM object from your MFC application leaving the object implementation in the DLL), use ClassWizard or a #import statement to reference the type library. You could also use the interface headers generated from the IDL file that describes the object's interfaces. Use CoCreateInstance to create the object
but how??. (i.e how my client (mfc app) will know the defination of "CSimpleObject")
Again Thanks in Advance.,
Abhi Lahare
|
|
|
|
|
Actually i am developing a class in which it will take any com object and will be able to set and get the properties. Now i have taken the clsid of the component. Now how can i get its properties as GetIdsofNames function of IDispatch takes names. Please Guide me briefly with a little example or tell me some article
Thanx in advance
Regards
minamkhan
Inam
|
|
|
|
|
GetIDsOfNames accepts property names too, but I think you want to know the names of supported properties instead. You need to read the object's type information.
You can ask an object if it can provide type information by calling the GetTypeInfo method of IDispatch . You can then find out how many properties it has by calling ITypeInfo::GetTypeAttr . You can get information on the properties with ITypeInfo::GetVarDesc .
|
|
|
|
|
Sir Actually i have only the progId of the component now i want to also know how i will get the interfaces in this component dynamically than how can i get the names and return types of the properties in the interface dynamically. so that i will be able to get and set the properties in that interface. Sir please explain me little briefly as i am new to this topic. or if possible gave me a little example too.
Thanx in advance
Regards
minamkhan
Inam
|
|
|
|
|
Does anyone know of a "commercial" ActiveX control that utilizes a CListCtrl/CListView?
Charlie Roderick
|
|
|
|
|
Hmm.. what do you mean with utilizes? Are you looking for an activex control which behaves just like CListCtrl, or are you just curious whether anyone have been "bold enough" to use CListCtrl commercially?
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
Either and/or both.
Charlie Roderick
|
|
|
|
|
I'm trying to get a file path from a pointer to a PIDL.
This is using the following function:
BOOL SHGetPathFromIDList(
LPCITEMIDLIST pidl,
LPTSTR pszPath
);
where pidl is an IntPtr to a pidl pulled from the SHBrowseForFolder.
I am using the following lines of code to call it:
<br />
IntPtr pidl = SHBrowseForFolder(lpbi);<br />
string filePath = new string(' ', 200);<br />
SHGetPathFromIDList(pidl,out filePath);<br />
via the wrapped method:
<br />
[DllImport("shell32.dll", CharSet=CharSet.Auto)]<br />
public static extern int SHGetPathFromIDList(<br />
IntPtr pidl,<br />
[Out, MarshalAs(UnmanagedType.BStr)]<br />
out string pszPath); <br />
The problem is that while pidl has a value, the method crashes when I try and interpret a file / folder greater than 1 depth.
And if it does not crash, I get the unmodified string returned to me.
Any ideas what I'm doing wrong?
Cheers
Cata
Edit: I suppose the question is - How do I construct a buffer of size Max_Path, and then create a pointer to it?
|
|
|
|
|
Solved it, no need to reply ^^
|
|
|
|
|
Use a StringBuilder . Note: wrong forum, please use the NET Framework forum for .NET questions.
|
|
|
|
|
I'm new to COM, so I am experimenting with some simple functions. I've had a degree of success with the SHBrowseForFolder function, in that I can open the dialog, setup the flags, rename it etc.
These are all parameters in the in/out structure struct_browseinfo.
The problem I have is, this inout structure is supposed to return a field pszDisplayName which contains the path of the folder right?
I've tried marshaling it as a number of different types of strings, and even an intptr (I am using C#), but it's always null, no matter what I do.
I'm using no owner for the dialog, no pidl root value, and the function still returns a folder index, But no string name.
Any idea why this is?
Cheers
Cata
|
|
|
|
|
I've looked into it a bit further, and the pszDisplayName is a pointer to a buffer of MAX_PATH charachters.
How would I go about marshaling this in C#?
I'm assuming that is what causes it to be a null value...
Any help appreciated.
Cheers
Cata
|
|
|
|
|
Ok, I've solved it using a pre initialised string. Thank you VS.NET for helpful error messages ^^
Anyway, Does this dialog box return the full path? Or am I stuck with only getting the folders name...
There has to be some way to fetch the full path... but i'll carry on looking at the tutorial now I have this solved.
Regards
Cata
|
|
|
|
|
Hello
Can I overload my COM object methods? I want to have two methods:
addMyObject(BSTR name);
addMyObject(BSTR name, BSTR address);
Can I do this? If not, is there a way of doing it or must I use different names for my methods?
|
|
|
|
|
No, use different names. Technically it's possible, but it's a nightmare. Using different names is easier.
From an "official" point of view, the names of the methods are irrelevant, unless it's IDispatch based, but it's sooo much easier with different names;
addMyObject(BSTR name);
addMyObjectWithAddress(BSTR name, BSTR address);
Remember, the IDL will produce a header file; it could be used in a C++ app, which supports overloading, or in a C app, which doesn't...
Steve S
|
|
|
|
|
Thank you
|
|
|
|
|