|
Hi COM gurus,
I have a doubt regarding Inheritence in COM
If I have a COM cleint (lets say Client) and another COM class (Parent) and a child C++ class (Child)
Child (c++ class)inherits from Parent(COM class)
//this is not the real program just to make things
//clear so donot go for syntax and all
Parent
{
virtual foo() = 0;
}
Child : public Parent
{
foo()
{
"Hello";
}
}
Client
{
Parent* p;
p = new Child();
p->foo() ; //this calls child method
}
so is this possible p = new Child()
how will queryinterface and all will be taken care.
Thanks in advance,
Gaurav
Gaurav
|
|
|
|
|
my assumption is that you're confusing the Server and the Client.
On the server (i.e.: in the DLL for in-proc server and in the executable or out-of-process server) you will use some language (C++, VB, VB.NET, other) to implement the functionality you expose using COM. How you implement it isnt really important as long as you follow the rules of COM like the rule mentioned for QueryInterface that says that no matter which Interface i Query for, i can query for any other type of interface that object exposes and get a new valid interface pointer to the same object (or something of that kind). i.e.: If i get an IUnknown interface pointer, i can Query it for an IDispatch interface pointer, and from it i can Query for an IUnknown interface pointer and i will get the same interface pointer i started from.
On the client, all you know about is the interfaces exposed. An interface pointer is nothing more than a pointer to pointers ..etc of functions. The server needs to expose 1 COClass for any object you want to be able to create or get access to using a ClassId or a ProgId. So, on the client you will never use "new" because the client doesnt know about class "Child" or class "Parent", but it knows about interface "Parent". If you want to get a new Object, you use CreateObject() or CoGetClass() etc .. and they return to you an IUnknown interface pointer from which you can query to get further functionality.
Hope this clarifies things a bit ?
|
|
|
|
|
I am very new to COM, and don't have a full understanding of what it does. I'd like the opinions of some seasoned COM programmers before I continue down the COM path.
I have a program with a server and several clients, which all run on the same CPU. The server sends and recieves very simple (four byte) messages from the clients. I want a client to be an executable that someone starts, and, if the server is not running, starts the server. Outside of that, the messages should be treated as mailbox messages. I also want to allow other people to develop thier own clients.
The question I have is, should I be using COM, windows-messaging, or a combination of the two?
Thanks
John
|
|
|
|
|
Hi all,
This might be a stupid question, When we write any Win32 Program we start with these steps
1. RegisterWinodwClass
2. CreateWindow()
3. Showwindow()
4. UPdateWindow()
5 Infinite winodw Loop break on WM_QUIT.
6 return
But when is the message map is created for given window and who creates it? and at what particular stage it is created and do we any control over that ?
Thanks
Abhi Lahare
|
|
|
|
|
I have a much terrible problem . I need a dll to accomplish a Dictionary(dll 's name) which contain any object called VB6.0. The Dictionary using c++ ' s stl std::map<anytype key="" ,="" anytype="" object=""> , the key type must adapt for a self defined class or a object , that is the method Add(para1, para2 ) can also deliver that argument para1 is object. The destination goal is Add(Object obj1, Object obj2).
can you help me ? thank you in advance!
following is the source :
project name : TestDictionary
// TestDictionary.cpp : Implementation of CTestDictionary
#include "stdafx.h"
#include "TestDictionary.h"
#include ".\testdictionary.h"
// CTestDictionary
STDMETHODIMP CTestDictionary::Add(BSTR key, VARIANT object)
{
// TODO: Add your implementation code here
wstring keystirng(key);
_map[keystirng] = object;
return S_OK;
}
STDMETHODIMP CTestDictionary::get_Items(BSTR key, VARIANT* pVal)
{
// TODO: Add your implementation code here
wstring keystirng(key);
*pVal = _map[keystirng];
return S_OK;
}
STDMETHODIMP CTestDictionary::put_Items(BSTR key, VARIANT newVal)
{
// TODO: Add your implementation code here
wstring keystirng(key);
_map[keystirng] = newVal;
return S_OK;
}
head source:
// TestDictionary.h : Declaration of the CTestDictionary
#pragma once
#include "resource.h" // main symbols
// ITestDictionary
[
object,
uuid("AB33763D-A604-42CF-9F86-4EA61D8B51EA"),
dual, helpstring("ITestDictionary Interface"),
pointer_default(unique)
]
__interface ITestDictionary : IDispatch
{
[id(1), helpstring("method Add")] HRESULT Add([in] BSTR key, [in] VARIANT object);
[propget, id(2), helpstring("property Items")] HRESULT Items([in] BSTR key, [out, retval] VARIANT* pVal);
[propput, id(2), helpstring("property Items")] HRESULT Items([in] BSTR key, [in] VARIANT newVal);
};
[
object,
uuid("{8FA3C023-1EF5-4b1b-91F7-41815B8A5294}"),
dual, helpstring("ITestEnumrator Interface"),
pointer_default(unique)
]
__interface ITestEnumrator : IDispatch
{
[id(1), helpstring("method Next")] HRESULT Next([out,retval] VARIANT* pObject);
};
// CTestDictionary
[
coclass,
threading("apartment"),
vi_progid("ComLib.TestDictionary"),
progid("ComLib.TestDictionary.1"),
version(1.0),
uuid("B610EB97-5CEC-451A-90D9-A13EED57C168"),
helpstring("TestDictionary Class")
]
class ATL_NO_VTABLE CTestDictionary :
public ITestDictionary,
public ITestEnumrator
{
public:
CTestDictionary()
{
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD(Add)(BSTR key, VARIANT object);
private:
map<wstring,variant> _map;
map<wstring,variant>::iterator _iter;
public:
STDMETHOD(get_Items)(BSTR key, VARIANT* pVal);
STDMETHOD(put_Items)(BSTR key, VARIANT newVal);
};
thank u
|
|
|
|
|
can u be more specific, why you need key type as an object. why can't u put that object as a member/property of the value type object. ie param1 object as a data member/property of param2.
rgds..mil10
|
|
|
|
|
Thank you Mil10 for the answer. Our system referenced a Dictionary , which is component of Microsoft scripting runtime , the disigner used it filled with variable case ,included set object(self defined class) as container 's key. My project leader check the our system to find memory leak, and the leak 's destinate position just is the referenced Dictionary . so , be going to write a component to replace it .
I want to accomplish a COM interface Add(key , item). The first argument "key" is deliver any basic type and self defined class or object , and the second argument "object" does not to explain. How to implement this ?
I am very puzzled . I try to using stl template map class , such as std::map <variant ,="" variant="">, but when I add into container with element , the result did not accomplish my goal. The problem is the first argemnt VARIANT that i could not process it .
Can you help me ? Can you have others method ? thank u in advance.
thank u
|
|
|
|
|
Good day,
I'm creating a simple in-process server(dll) which has only 1 interface-> STDMETHOD (ShowFolder)() PURE;
and on the implementation :
STDMETHODIMP FolderSelectClass::ShowFolder()
{
CFolderSelect myfolder;
int response=myfolder.DoModal();
if (response == IDOK){ }
else if (response == IDCANCEL) { }
AfxMessageBox("Successfull Call on this Interface...");
return S_OK;
}
CFolderSelect is a dialog class.
I've created a client (also a dialog with a button to call this interface). Upon pressing this button, the interface
is successfully called because it executes ->AfxMessageBox("Successfull Call on this Interface...");
but it does not launch the DoModal of the CFolderSelect Dialog. Why is that upon calling DoModal it wont launch the dialog?
Thanks.
|
|
|
|
|
am making a program and it need support for viewing and browsing web pages how would i use MS COMs to do this
|
|
|
|
|
See IWebBrowser2 Interface and "Reusing the WebBrowser Control" topic in MSDN
for prowsing webpages from your program. There are also good topics in CP
http://www.codeproject.com/internet/CustomBrowser.asp
Thanks,
Abhi Lahare
|
|
|
|
|
So I have one project in VC 7 that I'd like to use COM events with. I successfully set up the event server by using the __event __interface, and __raise attributes. I even set up a client program in VB 6 that worked and caught the event.
The problem is that I can't get another C++/COM project to work with it. This project is done already and it's not an attributed project and dosen't work by adding __hook attributes. I tried setting it up to catch the events through IDispEventSimpleImpl and adding an entry to the sink map. This is the way I'd like to do it anyway, because I handle events from other objects in this prject this way and I'd like to keep it consistant.
Anyway, everything seemed to go smoothly until I ran it and got a Run-Time Check Failure #0 that says the value of ESP was not properly saved across the function call, usually indicating a function pointer declared with a different calling convention than the function.
my SINK_MAP looks like this:
BEGIN_SINK_MAP(CClass)
...
SINK_ENTRY_INFO(10,__uuidof(IEvents),/*dispinterface*/0xf001,OnEvent,&EventInfo)
END_SINK_MAP()
My handler looks like this:
void __stdcall OnEvent(int i, int j, BSTR bstrMessage)
{
::MessageBox(NULL,_bstr_t(bstrMessage),NULL,MB_OK);
}
and I have my info struct defined like this:
_ATL_FUNC_INFO EventInfo={CC_STDCALL,VT_EMPTY,3,{VT_INT, VT_INT, VT_BSTR}};
Any ideas of what could be wrong? Or does mixing the attributed server with the client using IDispEventSimpleImpl just not work?
|
|
|
|
|
New to COM Events wrote:
Anyway, everything seemed to go smoothly until I ran it and got a Run-Time Check Failure #0 that says the value of ESP was not properly saved across the function call, usually indicating a function pointer declared with a different calling convention than the function.
It's only one reason, the second is the mismatching of account and types of parameters.
Can you show the IDL description of "OnEvent" method?
With best wishes,
Vita
|
|
|
|
|
Hey Vita, here is what th IDL for the events looks like.
[
object,
uuid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"),
helpstring("IEvents Interface")
]
__interface IEvents
{
[id(1), helpstring("method Event")] HRESULT Event([in] int i1, [in] int i2, [in] BSTR bstrMessage);
};
Thanks alot for the reply. I haven't figured this out yet.
|
|
|
|
|
IMHO, this interface doesn't derived from IDispatch, therefore the IDispEventSimpleImpl is inapplicable.
With best wishes,
Vita
|
|
|
|
|
Well, It needs to be derived from IDispatch because it needs to be used in VB as well as C++. Otherwise, sure...there's easier/simpler ways to do it.
Thanks anyway.
|
|
|
|
|
I have a function that "clicks" a link in a document. Basically it finds and 'a' tag and gets the href from it. Then it calls IHTMLDocument2::get_parentWindow and retrieves an IHTMLWindow2 pointer and then calls IHTMLWindow2::navigate passing the url it got from the href. Everything works great in IE 5.5 and 6, but it sometimes opens a new IE window in IE 5.0. And I can't figure out why it's opening new windows sometimes and not other (it's always consistant by the way).
Any ideas?
|
|
|
|
|
The problem is caused by different pages defining different default "target frames" for links. In an HTML document you can define a default target frame which can be one of these (there are others I can't remember right now and haven't listed):
_self: load new page in same window
_blank: load new page in new window
_top: load new page in the top frame window
All you have to do to get constant behavior is use the lpszTargetFrameName variable in the navigate or navigate2 function, like this:
<br />
navigate(sURL, 0, "_self");<br />
This will cause the new page to be loaded in the same window.
Hope that helps!
Sincerely,
Alexander Wiseman
Est melior esse quam videri
It is better to be than to seem
|
|
|
|
|
hey Alexander, Thanks for the reply. Unfortunately, IHTMLDocument::navigate and IHTMLWindow::navigate don't support specifying the target frame. They only take the URL as a parameter. Also, they don't have a navigate2 function. IWebBrowser does. I think I might have something else going on here though, so I'll just have to look at it some more. Any other suggestions would be great though. Thanks.
|
|
|
|
|
You quite right, I must have misread your original post. You still might check the pages for the default frame, though I think I agree with you that there is probably something else going on. When you say it opens a new window, do you mean a new IExplorer window?
Sorry for the mistake, I'll see if I can figure anything else out.
Sincerely,
Alexander Wiseman
Est melior esse quam videri
It is better to be than to seem
|
|
|
|
|
Right, It opens a new Internet Explorer window. I haven't been able to check yet, but it's possible that I'm getting a different href than I think. In that case, I could possibly be passing a javascript call into navigate that might be opening a new window...but it's so weird that it's only doing this on IE 5.0 and not on later versions. hmmm...I'll keep looking. Thanks for your help.
|
|
|
|
|
Hi,
I'm new to COM programming and in need of a little help. I'm trying to test some DirectX Filters which are COM objects and have done the following:
I took a DirectX interface called IAMTVTuner and renamed it IAMTest. I want to see if it will still work under it's new name because I am going to end up doing some funky things with it. The problem I think is that the GUID is still associated with IAMTVTuner. I'm not sure how to either: associate the GUID with the IAMTest OR give the IAMTest a new GUID.
Is the association of GUIDs with COM objects and interfaces done in .idl files? I tried running Midl.exe on a file that I changed but I get errors. I'm not even sure if I'm on the right track.
Thanks
|
|
|
|
|
I want to use my interface pointer in new thread and this component is written by pure C++ not using ATL or MFC,my codes as below:
const CLSID clsid={0x7D519042,0x1645,0x4a8c,{0xBD,0xE0,0x0F,0x4A,0x44,0xFC,0x38,0xC4}};
const IID iid1={0x7D519040,0x1645,0x4a8c,{0xBD,0xE0,0x0F,0x4A,0x44,0xFC,0x38,0xC4}};
HRESULT hr=CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
if(FAILED(hr))
{
MessageBox("CoInitialize Failed");
CoUninitialize();
return;
}
ISimpleInterface* ptr1=NULL;
hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,iid1,(void**)&ptr1);
if(FAILED(hr))
{
HLOCAL buf=NULL;
BOOL fOK=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|FORMAT_MESSAGE_ALLOCATE_BUFFER,0,hr,
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
(LPTSTR) &buf,0,0);
if(NULL!=buf)
{
MessageBox((LPCTSTR)LocalLock(buf));
LocalFree(buf);
}
return ;
}
hr=CoMarshalInterThreadInterfaceInStream(iid1,ptr1,&pStream);
if(S_OK != hr)
{
ptr1->Release();
HLOCAL buf=NULL;
BOOL fOK=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_ALLOCATE_BUFFER,0,hr,
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
(LPTSTR)&buf,0,0);//Error:Interface not registered
if(NULL!=buf)
{
MessageBox((LPCTSTR)LocalLock(buf));
LocalFree(buf);
}
return ;
}
DWORD dwThreadId=0;
CreateThread(0,0,ThreadFun,0,0,&dwThreadId);
hr=ptr1->Sum();
if(FAILED(hr))
{
ptr1->Release();
MessageBox("DoSimpleMsgBox Failure");
return ;
}
ptr1->Release();
CoUninitialize();
How to modify that error,Using functiong of RpcServerRegisterIf2 to Register??? I don't know what to do next,please help me,thanks a lot
|
|
|
|
|
After much research I believe the function CreateObjrefMoniker will solve my problem.
When I look in objbase.h I find this is missing so my project will not compile.
How can I use this function.
Using Visual C++ 6.0 SP5 and MFC
Sara
|
|
|
|
|
I'm trying to print an HTML file using AxWebBrowser.ExecWB in a C# app but it gives a run time error "Trying to revoke a drop target that has not been registered". Does anyone have any suggestions?
axWebBrowser1.QueryStatusWB(SHDocVw.OLECMDID.OLECMDID_PRINT);
object o = "";
SHDocVw.OLECMDID Print = SHDocVw.OLECMDID.OLECMDID_PRINT;
SHDocVw.OLECMDEXECOPT PromptUser = SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER;
axWebBrowser1.ExecWB(Print, DontPromptUser, ref o, ref o);
Thanks.
|
|
|
|
|
Hi All,
It seems when using attributed COM object in VC7, defaultvalue parameters do not work correctly in late-binding environment.
Asseme I have a method:
[id(1), helpstring("method AA")] HRESULT AA([in, defaultvalue("1")] LONG abc);
In VBScript, I can call it as:
Object.AA 1
but can't use shorter syntax:
Object.AA
If the same method is declated in non-attrbited library (i.e. separate IDL and H file), all works fine. Also, all works fine when early-binding is used in VB6.
I tried to add optional attribute to method, oleautomation and nonextensible to class, but all of this does not help.
Of course, it's possible to forget attributes and write old-style separate IDL/H objects, but it does not seem to be graceful solution.
Regards,
Alex
|
|
|
|
|