|
It's possible, but the solutions are definately "twisted", I would suggest they are worse then the problem. You could do this:
class clsA
{
public:
clsB obj1;
clsC obj2;
char name[10];
void show();
};
HRESULT DirtyHack_PassInCPPObject([in]INT_PTR pObj);
STDMETHODIMP CYouCOMObject::DirtyHack_PassInCPPObject(INT_PTR pObj)
{
clsA* pA = reinterpret_cast<clsA*>(pObj);
return S_OK;
}
clsA a;
spObj->DirtyHack_PassInCPPObject(reinterpret_cast<INT_PTR>(&a));
As you've probably guessed, I do not approve of this - But you wanted twisted. None of your coworkers will thank you for putting this in production code - If I were a manager I'd fire someone for doing so. COM objects written in any language can be called from any other language, this is one of the reasons for using COM. Breaking the rules like this destroys all this.
Steve
|
|
|
|
|
You are right steve... its real twisted...
but u think such a situation never comes..? like the need to pass a collection
of values which are dependent on each other..? If such a situation comes, wat is the
perfect way to do it..?
thanks,
ann
|
|
|
|
|
Model the data as a COM object. Once that's done you can consume the data from any COM compatible langauge. e.g. C/C++, JavaScript, VB, any of the dotNET langauges, etc......
Steve
|
|
|
|
|
sorry to bug u again steve...But can u explain a bit more on modelling the data a COM object
using the example i gave before as i am pretty new to COM..
Ann
|
|
|
|
|
It would help if I knew how the COM server was implemented. Does it use ATL, MFC, etc....
Steve
|
|
|
|
|
yup... currently it is done using ATL...
Ann
|
|
|
|
|
annjose24 wrote: Now if i create an object of clsA say obj3, is it possible to passobj3 to the COM client.
The "clean" way to do that is implementing COM objects to expose the funcionality of clsA, clsB and clsC. So you will have IClsA implemented by clsA, IClsB implemented by clsB, and so on...
Then, instead of passing the object, you can pass the interface via COM. In your current COM object you need a method like:
(I suppose that you have a pointer to an object of type ClsA in your COM object called m_pClsa)
HRESULT CYourCOMObject::GetObjectClsA ( IClsA ** ppObjClsA)
{
HRESULT hr = m_pClsa->QueryInterface(IID_IClsa, (void**)ppObjClsA);
if (SUCCEEDED(hr))
return S_OK
*ppObjClsa = NULL;
return S_FALSE;
}
The same methods for ClsB and ClsC should be in ClsA.
Do you get the idea more or less?
Regards.
|
|
|
|
|
As Stephen said, you can't, but you have the alternative of modeling the objects you want to pass with COM interfaces, as you can pass via COM that interfaces. I'm not sure if I was clear... This alternative is much more tedious but is better than nothing.
Regards.
|
|
|
|
|
Can u explain a bit more on what you meant by modelling the
objects.
Thanks,
ann
|
|
|
|
|
I'm having difficulty intializing a variable of type ENTRYLIST and I think I'm just missing something simple. I need to call IMAPIFolder::CopyMessage and the first variable is to be an LPENTRYLIST. So my code has
ENTRYLIST elMessage[] = {1, &messageEID};
m_Folder->CopyMessage(&elMessage, ...
The compiler is not liking my initialization where the variable messageEID is of type ENTRYID and is the entry ID of a message within an Exchange folder. The error from the compiler makes sense, but I'm still unsure what needs to be change.
error C2440: 'initializing' : cannot convert from 'ENTRYID *' to 'struct _SBinary *'
What type of cast or type conversion do I need to do? Thanks.
Chris Meech
I am Canadian. [heard in a local bar]
When I want privacy, I'll close the bathroom door. [Stan Shannon]
Nice sig! [Tim Deveaux on Matt Newman's sig with a quote from me]
|
|
|
|
|
This code is passing all compiler rules okay and I believe it is the correct way to set it up
SBinary sbMessage[] = {1, pMessageEID->abFlags};
ENTRYLIST elMessages[] = {1, sbMessage};
HRESULT hr = m_pFolder->CopyMessages(elMessages, N... However the call to CopyMessage is returning an error which indicates that I do not have permissions to create a message in the folder I'm trying to copy to. I suspect at the moment that my initialisation of elMessages[] is incorrect, but I don't know what else I can use to identify the message that I want to have copied.
I'm still searching but if anyone can shed some more light on extended MAPI, that whould help me out. Thanks.
Chris Meech
I am Canadian. [heard in a local bar]
When I want privacy, I'll close the bathroom door. [Stan Shannon]
Nice sig! [Tim Deveaux on Matt Newman's sig with a quote from me]
|
|
|
|
|
Hello All,
i have an com dll which implemts the IShellPropSheet Interface.
Now i will call the function AddPages from an application.
The Property Page from the comm dll should be showing in the application on an Tab Control.
All i must do is to call the function
AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam).
I don't understand the LPFNADDPROPSHEETPAGE parameter. I think it is an callback function, but how must i implement it in my application?
Thanks for you help.
If something is unclear, because my english is bad, please let me know.
|
|
|
|
|
hi,
i want to send my custom error message to vb (or asp) from my c++ com object. i wrote a simple dll with one method
// C++ code
STDMETHODIMP _Test::TestErr ( ){
//AFX...
AfxThrowOleDispatchException( 1001 , "error occured" ); //just wrote this but tried many other methods
return S_OK;
}
'' VB code
Public Sub Test()
Dim obj as object
set obj = CreateObject("TestObj.Test")
on error goto ErrOccured
obj.TestErr
set obj = nothing
exit sub
ErrOccured:
MsgBox err.Description
set obj = nothing
End Sub
i want to see "error occured" message and also get 1001 as error number from vb exe.
i have tried many things but couldnot solve it.
Help needed!!!
thanx.
NOTE: com dll registrations WORKS, if i do not throw exception then no problem but i want to throw some error message to vb...
|
|
|
|
|
Does your object implement the ISupportErrorInfo interface?
|
|
|
|
|
gizzo,
yes and i solved the problem .
thanks.
|
|
|
|
|
hi,
i'm trying to write a shell extension for printers in c#. i use the IContextMenu and IShellExtInit interfaces to insert the menu item in the context menu - it works fine. my problem is to find out to which printer the context menu belongs.
example:
i have three printers installed on my system.
1. name: hp 5p port: lpt1
2. name: hp 1160 port: usb001
3. name: local hostprinter port: lpt1
when i click on the 'hp 1160' printer and then on my context menu item the port of 'local hostprinter' has change to 'usb001'. to do this so i need to know the name of the printer... how can i do it?
thx
eisbär
|
|
|
|
|
hi,
here is the IShellExtInit.Initialize to get the printername:
int IShellExtInit.Initialize(
IntPtr pidlFolder,
IntPtr lpdobj,
uint hKeyProgID)
{
try
{
uint CFSTR_PRINTERGROUP;
CFSTR_PRINTERGROUP =
DllImports.RegisterClipboardFormat("PrinterFriendlyName");
m_dataObject = null;
if (lpdobj != (IntPtr)0)
{
m_dataObject = (IDataObject)Marshal.GetObjectForIUnknown(lpdobj);
FORMATETC fmt = new FORMATETC();
fmt.cfFormat = CFSTR_PRINTERGROUP; fmt.ptd = 0;
fmt.dwAspect = DVASPECT.DVASPECT_CONTENT;
fmt.lindex = -1;
fmt.tymed = TYMED.TYMED_HGLOBAL;
STGMEDIUM medium = new STGMEDIUM();
m_dataObject.GetData(ref fmt, ref medium);
m_hDrop = medium.hGlobal;
uint nselected = DllImports.DragQueryFile(m_hDrop,
0xffffffff,
null,
0);
if (nselected == 1)
{
StringBuilder sb = new StringBuilder(1024);
DllImports.DragQueryFile(m_hDrop, 0, sb, sb.Capacity + 1);
string objectname = sb.ToString();
}
}
}
catch (Exception e)
{
sting err = e.ToString();
}
return 0;
}
eisbär
|
|
|
|
|
Hi
I have a ICopyHook extension DLL. But this DLL is coming to effect only when i restart my explorer i.e, by lkilling the explorer.exe. If i register the DLL, i will have to kill the explorer.exe to make it work. Is there any way by which i can make the DLL work wihtout restarting the explorer.
|
|
|
|
|
Hi,
I made a COM-client in C++ which uses the import directive and
_COM_SMARTPTR_TYPEDEF(Iclogmanager, __uuidof(Iclogmanager));
to access the methods of the COM-Server via a smart pointer.
Iclogmanager is a dispinterface and the COM-Object which implements it is a Visual-Fox-Pro COM-Server. Its image is in an exe-file and it runs as a separate process on an other machine.
I was surprised to see, that the client crashed, after I released a new version of the server, although I did not even add additional methods. It was just a line of additional code I added within a method.
To be exact, it crashed at
HRESULT _hr = raw_doQuery(tcFilterMethode, toCollParameters, &_result);
After recompilation it worked fine again.
This is absolutely not consistent with my idea of COM.
Any idea?
Thanks an best regards
Werner
|
|
|
|
|
what is an interface ?
difference between interface and a abstract class >
Vikas Amin
Embin Technology
Bombay
|
|
|
|
|
Essentially an interface is an abstract base class, but their are limitations of what is allowed to ensure compatible vtable layout between different compilers:
- No virtual destructors (as different compilers implement it differently).
- Only single inheritance (as different compilers implement multiple inheritance differently).
Probably other stuff I forgot.
Steve
|
|
|
|
|
A interface is an abstract class in c++.it's methods are not defined.A interface shows some aspects of a com component (coclass) like we have "human" component then IHand and IMouth could be it's interfaces.
danishjibbran
|
|
|
|
|
hi guys;
the IMediaSeeking @ Duration didn't work, any thougth about that?
the code would be:
#pragma once
using namespace System;
using namespace System::Runtime::InteropServices;
namespace QuartzTypeLib
{
[StructLayout(LayoutKind::Sequential), ComVisible(false)]
public ref class DsOptInt64
{
public:
DsOptInt64( long Value )
{
this->Value = Value;
}
long Value;
};
[Flags, ComVisible(false)]
public enum class SeekingCapabilities // AM_SEEKING_SeekingCapabilities AM_SEEKING_SEEKING_CAPABILITIES
{
CanSeekAbsolute = 0x001,
CanSeekForwards = 0x002,
CanSeekBackwards = 0x004,
CanGetCurrentPos = 0x008,
CanGetStopPos = 0x010,
CanGetDuration = 0x020,
CanPlayBackwards = 0x040,
CanDoSegments = 0x080,
Source = 0x100 // Doesn't pass thru used to count segment ends
};
[Flags, ComVisible(false)]
public enum class SeekingFlags // AM_SEEKING_SeekingFlags AM_SEEKING_SEEKING_FLAGS
{
NoPositioning = 0x00, // No change
AbsolutePositioning = 0x01, // Position is supplied and is absolute
RelativePositioning = 0x02, // Position is supplied and is relative
IncrementalPositioning = 0x03, // (Stop) position relative to current, useful for seeking when paused (use +1)
PositioningBitsMask = 0x03, // Useful mask
SeekToKeyFrame = 0x04, // Just seek to key frame (performance gain)
ReturnTime = 0x08, // Plug the media time equivalents back into the supplied LONGLONGs
Segment = 0x10, // At end just do EC_ENDOFSEGMENT, don't do EndOfStream
NoFlush = 0x20 // Don't flush
};
[ComVisible(true), ComImport,
Guid("36b73880-c2c8-11cf-8b46-00805f6cef60"),
InterfaceType( ComInterfaceType::InterfaceIsIUnknown )]
public interface class IMediaSeeking
{
[PreserveSig]
int GetCapabilities(SeekingCapabilities &pCapabilities );
[PreserveSig]
int CheckCapabilities( [In, Out] SeekingCapabilities &pCapabilities );
[PreserveSig]
int IsFormatSupported( [In] Guid& pFormat );
[PreserveSig]
int QueryPreferredFormat( [Out] Guid& pFormat );
[PreserveSig]
int GetTimeFormat( [Out] Guid& pFormat );
[PreserveSig]
int IsUsingTimeFormat( [In] Guid& pFormat );
[PreserveSig]
int SetTimeFormat( [In] Guid& pFormat );
[PreserveSig]
int GetDuration( long& pDuration );
[PreserveSig]
int GetStopPosition( long& pStop );
[PreserveSig]
int GetCurrentPosition( long &pCurrent );
[PreserveSig]
int ConvertTimeFormat( long& pTarget, [In] Guid& pTargetFormat,
long& Source, [In] Guid& pSourceFormat );
[PreserveSig]
int SetPositions(
[In, Out, MarshalAs(UnmanagedType::LPStruct)] DsOptInt64^ pCurrent,
SeekingFlags dwCurrentFlags,
[In, Out, MarshalAs(UnmanagedType::LPStruct)] DsOptInt64^ pStop,
SeekingFlags dwStopFlags );
[PreserveSig]
int GetPositions( long &pCurrent, long &pStop );
[PreserveSig]
int GetAvailable( long &pEarliest, long &pLatest );
[PreserveSig]
int SetRate( double dRate );
[PreserveSig]
int GetRate( double& pdRate );
[PreserveSig]
int GetPreroll( long &pllPreroll );
};
}
thanks
|
|
|
|
|
Hi,
I am trying to send a simple string from a ActiveX written in C++ and pop a messageBox out in VB .NET with this string in it. I have tried everything and spoke to many people about this problem.
When I attempt to run the VB Application I get a error telling me
System.Runtime.Services.COMException and with further detail it tells me it is a type Mismatch
I have written a sample program that has a simple function called GetString,
The MessageBox in the function GetString doesnt even pop up
Here is the .IDL File
<code>
#include <idispids.h>
[ uuid(597DC433-D3AC-484E-A91E-3CB9752A7C8A), version(1.0),
helpfile("Test.hlp"),
helpstring("Test ActiveX Control module"),
control ]
library TestLib
{
importlib(STDOLE_TLB);
// Primary dispatch interface for CTestCtrl
[ uuid(444429CA-5912-4EB6-B56F-714EC166420C),
helpstring("Dispatch interface for Test Control")]
dispinterface _DTest
{
properties:
methods:
[id(DISPID_ABOUTBOX)] void AboutBox();
[id(1), helpstring("method GetString")] void GetString(BSTR* str);
};
// Event dispatch interface for CTestCtrl
[ uuid(1EA5A597-A8EE-4A61-A0B5-0CB32CD9ADF2),
helpstring("Event interface for Test Control") ]
dispinterface _DTestEvents
{
properties:
// Event interface has no properties
methods:
};
// Class information for CTestCtrl
[ uuid(2FA19712-DF56-49B0-9DA0-E148FECB25A7),
helpstring("Test Control"), control ]
coclass Test
{
[default] dispinterface _DTest;
[default, source] dispinterface _DTestEvents;
};
};
</code>
Here is the TestCtrl.cpp File
<code>
// TestCtrl.cpp : Implementation of the CTestCtrl ActiveX Control class.
#include "stdafx.h"
#include "Test.h"
#include "TestCtrl.h"
#include "TestPropPage.h"
#include ".\testctrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CTestCtrl, COleControl)
// Message map
BEGIN_MESSAGE_MAP(CTestCtrl, COleControl)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
// Dispatch map
BEGIN_DISPATCH_MAP(CTestCtrl, COleControl)
DISP_FUNCTION_ID(CTestCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
DISP_FUNCTION_ID(CTestCtrl, "GetString", dispidGetString, GetString, VT_EMPTY, VTS_PBSTR)
END_DISPATCH_MAP()
// Event map
BEGIN_EVENT_MAP(CTestCtrl, COleControl)
END_EVENT_MAP()
// Property pages
// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CTestCtrl, 1)
PROPPAGEID(CTestPropPage::guid)
END_PROPPAGEIDS(CTestCtrl)
// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CTestCtrl, "TEST.TestCtrl.1",
0x2fa19712, 0xdf56, 0x49b0, 0x9d, 0xa0, 0xe1, 0x48, 0xfe, 0xcb, 0x25, 0xa7)
// Type library ID and version
IMPLEMENT_OLETYPELIB(CTestCtrl, _tlid, _wVerMajor, _wVerMinor)
// Interface IDs
const IID BASED_CODE IID_DTest =
{ 0x444429CA, 0x5912, 0x4EB6, { 0xB5, 0x6F, 0x71, 0x4E, 0xC1, 0x66, 0x42, 0xC } };
const IID BASED_CODE IID_DTestEvents =
{ 0x1EA5A597, 0xA8EE, 0x4A61, { 0xA0, 0xB5, 0xC, 0xB3, 0x2C, 0xD9, 0xAD, 0xF2 } };
// Control type information
static const DWORD BASED_CODE _dwTestOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CTestCtrl, IDS_TEST, _dwTestOleMisc)
// CTestCtrl::CTestCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CTestCtrl
BOOL CTestCtrl::CTestCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: Verify that your control follows apartment-model threading rules.
// Refer to MFC TechNote 64 for more information.
// If your control does not conform to the apartment-model rules, then
// you must modify the code below, changing the 6th parameter from
// afxRegApartmentThreading to 0.
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_TEST,
IDB_TEST,
afxRegApartmentThreading,
_dwTestOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
// CTestCtrl::CTestCtrl - Constructor
CTestCtrl::CTestCtrl()
{
InitializeIIDs(&IID_DTest, &IID_DTestEvents);
// TODO: Initialize your control's instance data here.
}
// CTestCtrl::~CTestCtrl - Destructor
CTestCtrl::~CTestCtrl()
{
// TODO: Cleanup your control's instance data here.
}
// CTestCtrl::OnDraw - Drawing function
void CTestCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
// TODO: Replace the following code with your own drawing code.
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
}
// CTestCtrl::DoPropExchange - Persistence support
void CTestCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
}
// CTestCtrl::OnResetState - Reset control to default state
void CTestCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
// TODO: Reset any other control state here.
}
// CTestCtrl::AboutBox - Display an "About" box to the user
void CTestCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_TEST);
dlgAbout.DoModal();
}
// CTestCtrl message handlers
void CTestCtrl::GetString(BSTR* str)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// MessageBox( "This is a test" );
// CString tmp = "Hello World";
// *str = tmp.AllocSysString();
}
</code>
And Here is the TestCtrl.h
<code>
#pragma once
// TestCtrl.h : Declaration of the CTestCtrl ActiveX Control class.
// CTestCtrl : See TestCtrl.cpp for implementation.
class CTestCtrl : public COleControl
{
DECLARE_DYNCREATE(CTestCtrl)
// Constructor
public:
CTestCtrl();
// Overrides
public:
virtual void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid);
virtual void DoPropExchange(CPropExchange* pPX);
virtual void OnResetState();
// Implementation
protected:
~CTestCtrl();
DECLARE_OLECREATE_EX(CTestCtrl) // Class factory and guid
DECLARE_OLETYPELIB(CTestCtrl) // GetTypeInfo
DECLARE_PROPPAGEIDS(CTestCtrl) // Property page IDs
DECLARE_OLECTLTYPE(CTestCtrl) // Type name and misc status
// Message maps
DECLARE_MESSAGE_MAP()
// Dispatch maps
DECLARE_DISPATCH_MAP()
afx_msg void AboutBox();
// Event maps
DECLARE_EVENT_MAP()
// Dispatch and event IDs
public:
enum {
dispidGetString = 1L
};
protected:
void GetString(BSTR* str);
};
</code>
The VB Application is as follows:
<code>
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents AxTest1 As AxTestLib.AxTest
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1))
Me.AxTest1 = New AxTestLib.AxTest
CType(Me.AxTest1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'AxTest1
'
Me.AxTest1.Enabled = True
Me.AxTest1.Location = New System.Drawing.Point(16, 16)
Me.AxTest1.Name = "AxTest1"
Me.AxTest1.OcxState = CType(resources.GetObject("AxTest1.OcxState"), System.Windows.Forms.AxHost.State)
Me.AxTest1.Size = New System.Drawing.Size(184, 192)
Me.AxTest1.TabIndex = 0
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.AxTest1)
Me.Name = "Form1"
Me.Text = "Form1"
CType(Me.AxTest1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim test As String
AxTest1.GetString(test) 'ERROR HAPPENS HERE
End Sub
End Class
</code>
|
|
|
|
|
The first thing that catches my eye is this line in the .ODL file:
[id(1), helpstring("method GetString")] void GetString(BSTR* str);<br />
This should read:
[id(1), helpstring("method GetString")] void GetString([out, retval]BSTR* str);<br />
Steve
-- modified at 22:00 Sunday 22nd January, 2006
ADDED:
The retval means you should be able to write something like this on the dotNET side:
<br />
s = obj.GetString()<br />
|
|
|
|
|