Prev: Releated to JIT Error
Next: Apology to Joe
From: Hector Santos on 25 Mar 2010 19:51 I never did this before under MFC C/C++. I added COM components to the Toolbar right click the ToolBox | Choose Items and selected some Microsoft components, specifically the Microsoft TabStrip component. It was added to the palette and now I can drop the control into the dialog form. Then I right click the control and "Add Variable" to create a m_tabs class member. When you do this, the TLB information is used to a class wrapper for the dispatch commands. In this case, it created, TabStrip2.h and TabStrips2.cpp. What I want to get access to is the SelectedItem, which it has these get/put functions to be used in property members: LPDISPATCH get_SelectedItem() { LPDISPATCH result; InvokeHelper(0xf, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL); return result; } void putref_SelectedItem(LPDISPATCH newValue) { static BYTE parms[] = VTS_DISPATCH ; InvokeHelper(0xf, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms, newValue); } void put_SelectedItem(VARIANT * newValue) { static BYTE parms[] = VTS_PVARIANT ; InvokeHelper(0xf, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); } The question is how do use these in properties with LPDISPATCH? For example, it is easier for a BOOL types such as get_ShowTips and put_ShowTips: BOOL get_ShowTips() { BOOL result; InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); return result; } void put_ShowTips(BOOL newValue) { static BYTE parms[] = VTS_BOOL ; InvokeHelper(0x3, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue); } By adding the following property to the TabStrip2.h class: _declspec(property(get=get_ShowTips,put=put_ShowTips)) BOOL ShowTips; I now can access this member in m_tabs: m_tabs.ShowTips = FALSE; What class or object is get_SelectedItem returning? I looked overall google on this and there is no MFC C/C++ example with this. I'm just explore it really, not sure if I will use it or not. Thanks -- HLS
From: Goran on 26 Mar 2010 04:44 On Mar 26, 12:51 am, Hector Santos <sant9...(a)nospam.gmail.com> wrote: > I never did this before under MFC C/C++. I added COM components to > the Toolbar > > right click the ToolBox | Choose Items > > and selected some Microsoft components, specifically the Microsoft > TabStrip component. It was added to the palette and now I can drop > the control into the dialog form. Then I right click the control and > "Add Variable" to create a m_tabs class member. When you do this, the > TLB information is used to a class wrapper for the dispatch commands. > In this case, it created, TabStrip2.h and TabStrips2.cpp. > > What I want to get access to is the SelectedItem, which it has these > get/put functions to be used in property members: > > LPDISPATCH get_SelectedItem() > { > LPDISPATCH result; > InvokeHelper(0xf, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, > NULL); > return result; > } > void putref_SelectedItem(LPDISPATCH newValue) > { > static BYTE parms[] = VTS_DISPATCH ; > InvokeHelper(0xf, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms, > newValue); > } > void put_SelectedItem(VARIANT * newValue) > { > static BYTE parms[] = VTS_PVARIANT ; > InvokeHelper(0xf, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, > newValue); > } > > The question is how do use these in properties with LPDISPATCH? > > For example, it is easier for a BOOL types such as get_ShowTips and > put_ShowTips: > > BOOL get_ShowTips() > { > BOOL result; > InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_BOOL, (void*)&result, NULL); > return result; > } > void put_ShowTips(BOOL newValue) > { > static BYTE parms[] = VTS_BOOL ; > InvokeHelper(0x3, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, > newValue); > } > > By adding the following property to the TabStrip2.h class: > > _declspec(property(get=get_ShowTips,put=put_ShowTips)) BOOL ShowTips; > > I now can access this member in m_tabs: > > m_tabs.ShowTips = FALSE; > > What class or object is get_SelectedItem returning? I looked overall > google on this and there is no MFC C/C++ example with this. OleView says that SelectedItem is returning an ITab*. (There's two MS tab strips on my system, I picked one in mscomctl.ocx). Overall, for better results, try to open the type library in OleView (you can find this in your Win32 SDK, in Bin\OleView.Exe, but I would guess it lurks somewhere else in VS installation, too). BTW, from the type library, you should be able to find out where is the help file for it's component(s) (if there is a help file). For mscomctl.ocx on my machine, it's "cmctl198.chm". In all honesty, I always preferred stuff provided by compiler COM support ("#import") to what MFC wizards spit out. I'd recommend using this, if you are ready to take the plunge into COM world (it really IS a different world). You can e.g. use VS help to, say, drop control onto a dialog, then just use stuff #import gives you (take LPDISPATCH from the control, turn it into corresponding smart pointer from *.tlh generated through #import and work with that). Beware, by default, #import-generated stuff uses throws _com_error to report errors, which is bad in context of MFC. So you need to either: * try-catch-demarcate all calls to #import-generated stuff * use _set_com_error_handler to turn COM errors into MFC exceptions (IMO best approach by a long stretch, but curiously, this function was never documented by MS, although it exists since, I dunno, forever) * use "raw" interfaces only (I personally would never bother with that PITA) HTH, Goran.
From: Liviu on 26 Mar 2010 15:28 "Goran" <goran.pusic(a)gmail.com> wrote... > > In all honesty, I always preferred stuff provided by compiler COM > support ("#import") to what MFC wizards spit out. I'd recommend using > this, if you are ready to take the plunge into COM world (it really IS > a different world). You can e.g. use VS help to, say, drop control > onto a dialog, then just use stuff #import gives you (take LPDISPATCH > from the control, turn it into corresponding smart pointer from *.tlh > generated through #import and work with that). I share the same preference. One general advice, though, especially on "first dates" with #import, would be to debug a small snippet and step all the way into the wrappers to get a feeling for what they do for (and hide from) you - automatic type conversions, QIs etc. > Beware, by default, #import-generated stuff uses throws _com_error to > report errors, which is bad in context of MFC. So you need to either: > > * try-catch-demarcate all calls to #import-generated stuff > * use _set_com_error_handler to turn COM errors into MFC exceptions > (IMO best approach by a long stretch, but curiously, this function was > never documented by MS, although it exists since, I dunno, forever) I remember it wasn't, other maybe than "the source code is its best documentation" ;-) but now that you mentioned it, I find that it's been published <http://msdn.microsoft.com/en-us/library/ff357023.aspx>. One other caveat about #import, for those who care about controlled and repeatable builds... If one just writes "#import <mscomctl.ocx>" the compiler will happily oblige, locate the .ocx in the %path% (such as %systemroot%\system32), and use whatever it found. But if a colleague rebuilds the same sources, he may well have a different .ocx on his machine. Same if one applies some system updates, changes machines or OSs, and rebuilds later. While in theory COM interfaces are immutable and this shouldn't matter much, yet in practice it adds an element of hazard to the build process. (Then, there is also the case where one develops against COM interfaces not present on the build machine e.g. ms-office automation without the target office version installed.) This problem can be circumvented in a few different ways: - #import once to generate the .tlh/.tli files, then archive those and change #import to just #include the .tlh; drawback is that this would need to be done again when the compiler changes since different versions may #import differently; - copy the binary file (in this case .ocx) to a known location and arrange the build paths so that it's always picked up from there; drawback is that the entire binary file becomes part of the "source package" while in fact just its type library is needed (in this case it'd be a 1MB .ocx for what's essentially a 140KB .tlb); - extract the .tlb from the binary file and #import that, instead; use your favorite resource editor to locate and save the first "typelib" resource; to doublecheck, open the original PE file and the saved ..tlb in OleView and save the .idl's - they should compare identical. To be clear, the above only applies to cases where (a) there is no separate .tlb available already, and (b) one prefers not to #import directly from the PE file because of versioning/logistics reasons. Liviu
From: Hector Santos on 26 Mar 2010 17:54 Goran wrote: >> By adding the following property to the TabStrip2.h class: >> >> _declspec(property(get=get_ShowTips,put=put_ShowTips)) BOOL ShowTips; >> >> I now can access this member in m_tabs: >> >> m_tabs.ShowTips = FALSE; >> >> What class or object is get_SelectedItem returning? I looked overall >> google on this and there is no MFC C/C++ example with this. > > OleView says that SelectedItem is returning an ITab*. (There's two MS > tab strips on my system, I picked one in mscomctl.ocx). Geez, I totally forgot about OleView. I was focusing it was a wrapper around the TCITEM class members. > In all honesty, I always preferred stuff provided by compiler COM > support ("#import") to what MFC wizards spit out. I'd recommend using > this, if you are ready to take the plunge into COM world (it really IS > a different world). Tell me about it. We are 100% RPC. COM/ACTIVEX for the few VB6 and some Delphi based client side product utilities, but the rest all C/C++ MFC by design to stay away from historical COM/ACTIVEX installation deployment and security issues. But most of the COM/DCOM/COM+ experience came for the SDK to expose the SDK to COM ready languages. But I put that aside 2 years ago to use .NET instead to kill two birds with one. It was a nightmare trying to figure out how to best take our RPC IDL files and move it COM. So we started fresh with .NET by using one of CPP2xxxxxxx Language converters and with the help of a 3rd party developer we have a complete .NET interop interface. http://www.winserver.com/public/wcsdk I used .NET to create drop controls to add to to toolbox and had fun learning how create the property editor, especially for the events. :) For our 14 year old product "Makeover Stategy", what I am trying to do now is explore "making fancy" some of the MFC applets using some COM controls. Many of the apps are simple enough to port to .NET, most likely VB.NET or C#. But I'm going to wait until VS2010 comes in to explore what this yet another method, WPF, is all about. Anyway, ITab is the right interface. I am currently looking to if I can get a generic dispatch wrapper to handle this and others using templates. I wonder why "adding the variable" for the component class only addd TabStrip but not the others Tabs and Tab. I am refreshing my understanding of COM based IDL, TLB and the auto produced imported source. Thanks. -- HLS
From: Hector Santos on 26 Mar 2010 18:32 This is why I didn't work to much with the the auto generated stuff. The COM work, beside trying to use it now a MFC application, it was mostly for the SDK considerations. Take a look at the interop marshalling API files created for .NET for the main RPC client DLLs to get a feel of what we were facing and trying to automatic: http://www.winserver.com/public/wcsdk The .NET DLLs created from these allow me to create COM interfaces as well. Since we are RPC, the IDL are "almost" the same but different. Before ..NET, we had a VARIANT proxy dll for some of the API functions, i.e, returning a BSTR or VB based string collection. That was for VB6 SDK support. But the need to do a complete COM for OOPS like languages was difficult, do with create a UDT for each typedef structure? Do we create class interfaces, etc. To make a long story short, .NET helped here. Beside the lack of VARIANT support, or harder to do now, .NET made it simpler. Before .NET, we have a CPP2xxxxx language convert that takes our .H files and create the appropriate API for the language. VB WIN32 imports plus a proxy for string based or array functions DELPHI Win32 Java A streaming I/O proxy class based framework. PHP A similar streaming I/O proxy for functional programming, plus PHP class wrappers. So before .NET, to create a COM interface do we: 1) Write a CPP2COM converter, using the CPP2Java or CPP2PHP model, 2) Use the existing RPC IDL as input for a COM IDL By the time that tedious work decision was made, coupled that we falling behind .NET, it was easily just to write it in .NET and expose a COM interface as well. That worked so far. :) Liviu wrote: > "Goran" <goran.pusic(a)gmail.com> wrote... >> In all honesty, I always preferred stuff provided by compiler COM >> support ("#import") to what MFC wizards spit out. I'd recommend using >> this, if you are ready to take the plunge into COM world (it really IS >> a different world). You can e.g. use VS help to, say, drop control >> onto a dialog, then just use stuff #import gives you (take LPDISPATCH >> from the control, turn it into corresponding smart pointer from *.tlh >> generated through #import and work with that). > > I share the same preference. One general advice, though, especially on > "first dates" with #import, would be to debug a small snippet and step > all the way into the wrappers to get a feeling for what they do for (and > hide from) you - automatic type conversions, QIs etc. > >> Beware, by default, #import-generated stuff uses throws _com_error to >> report errors, which is bad in context of MFC. So you need to either: >> >> * try-catch-demarcate all calls to #import-generated stuff >> * use _set_com_error_handler to turn COM errors into MFC exceptions >> (IMO best approach by a long stretch, but curiously, this function was >> never documented by MS, although it exists since, I dunno, forever) > > I remember it wasn't, other maybe than "the source code is its best > documentation" ;-) but now that you mentioned it, I find that it's been > published <http://msdn.microsoft.com/en-us/library/ff357023.aspx>. > > One other caveat about #import, for those who care about controlled and > repeatable builds... If one just writes "#import <mscomctl.ocx>" the > compiler will happily oblige, locate the .ocx in the %path% (such as > %systemroot%\system32), and use whatever it found. But if a colleague > rebuilds the same sources, he may well have a different .ocx on his > machine. Same if one applies some system updates, changes machines or > OSs, and rebuilds later. While in theory COM interfaces are immutable > and this shouldn't matter much, yet in practice it adds an element of > hazard to the build process. (Then, there is also the case where one > develops against COM interfaces not present on the build machine > e.g. ms-office automation without the target office version installed.) > > This problem can be circumvented in a few different ways: > > - #import once to generate the .tlh/.tli files, then archive those and > change #import to just #include the .tlh; drawback is that this would > need to be done again when the compiler changes since different versions > may #import differently; > > - copy the binary file (in this case .ocx) to a known location and > arrange the build paths so that it's always picked up from there; > drawback is that the entire binary file becomes part of the "source > package" while in fact just its type library is needed (in this case > it'd be a 1MB .ocx for what's essentially a 140KB .tlb); > > - extract the .tlb from the binary file and #import that, instead; use > your favorite resource editor to locate and save the first "typelib" > resource; to doublecheck, open the original PE file and the saved > .tlb in OleView and save the .idl's - they should compare identical. > > To be clear, the above only applies to cases where (a) there is no > separate .tlb available already, and (b) one prefers not to #import > directly from the PE file because of versioning/logistics reasons. > > Liviu > > -- HLS
|
Pages: 1 Prev: Releated to JIT Error Next: Apology to Joe |