|
I'm unsure if this is a "correct" solution (COM threading is still a bit mysterious to me):
* I have COM object which needs to live asynchronously from a certain point in time (i.e. after the host has called a "start" method)
* I want it to be able to send events to the host
* I want it to be able to serve the host at any time (i.e., the host should be able to call any method during the COM objects life time)
Is this is viable solution? (Pseudo-code follows)
coclass MyThreadedClass : ISomeInterface, IConnectionPointImpl<...> {
STDMETHODIMP Start() {
CreateThread(..., BootStrapFunc, this);
}
STDMETHODIMP Stop() {
}
private:
static DWORD WINAPI BootStrapFunc(LPVOID param) {
MyThreadedClass* pThis = (MyThreadedClass)param;
pThis->ThreadLoop();
return 0;
}
void ThreadLoop() {
}
};
If I get this to work, there will be an article about it
FreeBSD is sexy.
<< This space for rent >>
|
|
|
|
|
The COM Mailslot object that I develop in this article does that kind of stuff. It has it's own thread and fires async events into VB whilst allowing VB to call into it whenever it likes...
Len Holgate
www.jetbyte.com
The right code, right now.
|
|
|
|
|
Thanks for the reply! I'll check out the article right away.. (I can sleep when I die.. )
FreeBSD is sexy.
<< This space for rent >>
|
|
|
|
|
I think I've understood how to implement my asynchronous object(s). I seriously need to buy some hard core COM-books. I should have known about marshalling interfaces.
Thanks alot for your article! Now if I get some time over this week, I'll complete what I've started so that I write an article about it. (About time I gave something back for all the stuff I've downloaded and used here.. )
FreeBSD is sexy.
<< This space for rent >>
|
|
|
|
|
I am considering developing some COM based Office Add-ins using ATL, and was wondering if my following understanding is reasonably correct.
To develop add-ins there is an interface called IDTExtensibility2, which features functions such as OnConnection, OnDisconnection etc. As parameters to these functions there are pointers to the main application, which is what enables the developer to access the application, manipulate toolbars etc.
If this is the case, all I have to do is find out the structure of these interfaces etc. (which from what I remember is in a type library) and then build in my own code correct?
Once I've done that its a case of running regsvr32 and putting in the relevent registry keys and off we go? I presume ATL is the best way to go for developing such objects?
As I said, I'm new to this COM thing So any encouragement that I'm on the right lines is appreciated!
Paul
|
|
|
|
|
You are definetly on the right track.
although I have almost no experience with COM Add-ins, from my previous experience with COM it looks good.
a few comments:
you can try to work with VB for a start. it helps to get familiar with unknowm (...) interfaces.
A great article about add-ins (if I remeber it corectly) is Developing COM Add-Ins for Microsoft Office 2000 in the MSDN.
have fun
Noam
Noam Ben Haim
Web Developer
Intel
noam.ben.chaim@intel.com
|
|
|
|
|
Is there any tool like java2idl that can directly change MFC code into ATL code???
I am now modify some MFC code ,in order to change it into a COM .But there are lots of problems, such as,type dismatch, return value .
Anyone have some ideas about the steps how to proceed .
I will preciate it.
regards.
|
|
|
|
|
Changing from MFC to ATL is a complicated procedure as you have found out. You don't need to go through the pain. You can make a MFC COM object although that has it's own pains.
|
|
|
|
|
I plan to copy all the MFC Class ,Including GUI Class ,such as Frmae,View, to the Atl Project .And it can be complied successfully. Then I can further modify the Atl project based on that. I will add some interface in Atl project to call function instead of the automation message loop . In this way , I think I could let the Atl dll run in VB GUI,with his own GUI (Frame ,view,Dialog ) just loaded in memory and not shown.
This is my idea . What do you think of it ? I just want to get a general structrue ,and then I can modify the Atl code into more simple project,such as change Frame,view into other substitutes. In this way ,I can achieve my goal.
Expecting your advice.
Now I have copied all the MFC Class ,Including GUI Class ,such as Frmae,View,from the MFC Project to the Atl Project .And it can be complied successfully.
But when I attempt to register the DLL I get the following error:
Debug Assertion Failed!
Program: C:\WINNT\System32\regsvr32.exe
File: D:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\APPCORE.CPP
Line: 85
Expression: ASSERT(AfxGetThread() == NULL);
So what does this really tell me and what can I do to correct it?
Any ideas???
|
|
|
|
|
Bliven wrote:
Is there any tool like java2idl that can directly change MFC code into ATL code???
I am now modify some MFC code ,in order to change it into a COM .But there are lots of problems, such as,type dismatch, return value .
There is no tool that I know of, because it is *difficult*
What kind of MFC code do you want to change to ATL ? It is a simple COM object, ActiveX control, or full blown MFC app ?
In any case, I wish you luck
V
|
|
|
|
|
Hey all, I have a question for you geniuses out there. I have a button in Word and I need to figure out the button has been clicked. I am not using ATL and I am using the "Automation and Eventing With Microsoft Word" article as an example. I noticed that all his functions work but I have not figured out how to capture the button and call the click function. Any ideas????
|
|
|
|
|
I have made an ActiveX control and I was working with it in a MFC application that uses the CMultiPageDHtmlDialog class.
The problem is that when I close the aplication an assert ocurs. The message is : dwCookie != 0 && dCookie <= (DWORD)m_nSize.
The assert is placed in a method called GetUnknow.The code of the method is:
IUnknown* WINAPI GetUnknown(DWORD dwCookie)
{
#ifndef _ATL_OLEDB_CONFORMANCE_TESTS
ATLASSERT(dwCookie != 0 && dwCookie <= (DWORD)m_nSize);
#endif
if (dwCookie != 0 && dwCookie <= (DWORD)m_nSize)
return GetAt(dwCookie-1);
else
return NULL;
}
This method is called when the application is breaking the event connections (I think). Please give me some help. Thanks.
|
|
|
|
|
I want to display the thumbnails of images in some folder, using VC++. I tried using the IExtractImage interface, provided by the shell (supposedly!)
I get a compile-time error about the interface not being found. I use Windows2000, so I believe it's not a problem with the shell version. I could not find IExtractImage in shlobj.h.
I tried out the sample code given at the site
http://netez.com/2xExplorer/shellFAQ/bas_infos.html
Is there any way for getting the thumbnails?
Thanks.
Logic is a systematic method of coming to the wrong conclusion with
confidence.
|
|
|
|
|
I guess you need the latest PSDK and also
have to define WIN32_NT (or what it is called, no progstuff here)
to 0x0500
/M
- Don't sweat the petty things, and don't pet the sweaty things.
|
|
|
|
|
I'm trying to write a COM .exe server that creates a small modeless dialog box when properly called. Unfortunately, when I call the COM object from my application, it always returns E_NOINTERFACE from CoCreateInstance when given the correct IID of my COM interface (ICObject in this case, for test purposes). According to MFC documentation, this error occurs when the QueryInterface call does not support the requested interface. However, if I create the same exact COM project using an in-proc .dll file, without changing a single line of code in the calling application (except the CLSCTX_ string in CoCreateInstance), it works fine. I am using MFC's ATL/COM wizard to create both the .exe and the .dll projects. Both settings are for apartment model threading, custom interface, no aggregation and connection points. Here's my application code:
//////////////////////////////////////////////
#include "..\COMObject\COMObject.h"
#include "..\COMObject\COMObject_i.c"
...
HRESULT hr;
//instantiate it
hr = CoCreateInstance(CLSID_CObject, NULL, CLSCTX_LOCAL_SERVER /*CLSCTX_INPROC_SERVER for DLL*/, IID_ICObject, (void **) &m_pObject);
//do something with it
if(SUCCEEDED(hr))
{
m_pObject->StartDialog();
}
//////////////////////////////////////////////
Does anyone have any idea why it works with an in-proc .dll and not an out-of-proc .exe?
|
|
|
|
|
Are you sure CLSID_CObject and IID_ICObject are the same in .DLL and .EXE COM implementation? Check .IDL files they have to be the same for both types of projects (.EXE and .DLL) or just use one .IDL file for both projects.
soptest
|
|
|
|
|
I just tried creating a wholly other .exe server in a new directory with a new interface CLSID and IID. Still has the same methods as the previous attempts and the application still gave the E_NOINTERFACE error. For some reason it will not find the interface requested for an .exe server. I searched through the messages and there's one other one back in the annals describing the same exact problem (search for NOINTERFACE).
|
|
|
|
|
Your CLSID_CObject and IID_ICObject are different (EXE_Project::CLSID_CObject == DLL_Project::CLSID_CObject AND EXE_Project::IID_ICObject == DLL_Project::IID_ICObject). Read my previous post.
soptest
|
|
|
|
|
You should use (and register) the proxy/stub for your EXE server.
Or you should use the dual interfaces, derived from IDispatch, or/and oleautomation interfaces, derived from IUnknown, with standard OLE marshalling. For it, you should use the oleautomation compatible types of data, such as long, double, BSTR and so on.
In this case, you don't need any additional proxy/stub.
With best wishes,
Vita
|
|
|
|
|
Ahhh, thank you very much. I believe this is the answer I was looking for. I had started to suspect that it had something to do with the [oleautomation] tag, but I'm not knowledgeable yet enough to know what I'm doing. Thanks a lot!
|
|
|
|
|
Hi COM Expert.
I have a ms word automation, dos-based, application that support MFC.
The programming is running perfectly right now. and a few minues later i got " Couldn't create MS Word Application Object". at
<br />
app.CreateDispatch("Word.Application");<br />
But I restart the computer and the program works again. why is that? is it because of OLE did not get initialized? why i have to restart the computer in order to work fine. what is wrong with that?
here are my code
<br />
<br />
#include "stdafx.h"<br />
#include "PrintMSWord.h"<br />
#include <ole2.h>
#include <stdio.h><br />
#include "msword9.h"<br />
<br />
#ifdef _DEBUG<br />
#define new DEBUG_NEW<br />
#undef THIS_FILE<br />
static char THIS_FILE[] = __FILE__;<br />
#endif<br />
<br />
<br />
CWinApp theApp;<br />
<br />
using namespace std;<br />
<br />
<br />
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])<br />
{<br />
int nRetCode = 0;<br />
<br />
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))<br />
{<br />
cerr << _T("Fatal Error: MFC initialization failed") << endl;<br />
nRetCode = 1;<br />
}<br />
else<br />
{<br />
CString fileName;<br />
for (int i = 1; i < argc; i++)<br />
{ <br />
fileName += argv[i]; <br />
fileName += " ";<br />
}<br />
cout<<"Opening "<<(const char*)fileName<<" ..."<<endl;<br />
<br />
CoInitialize(NULL);<br />
<br />
_Application app;
if(!app.CreateDispatch("Word.Application"))<br />
{<br />
AfxMessageBox("Could not create MS Word Application Object.");<br />
return 1;<br />
}<br />
LPDISPATCH lpDisp;
COleVariant covTrue((short)TRUE),covFalse((short)FALSE),covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);<br />
<br />
lpDisp = app.GetDocuments();
Documents documents;<br />
documents.AttachDispatch(lpDisp);<br />
COleVariant vOpt(DISP_E_PARAMNOTFOUND, VT_ERROR);
<br />
_Document document = documents.Open(COleVariant((CString)fileName), vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt);<br />
app.SetVisible(TRUE);
<br />
cout<<"Formatting documents..."<<endl;<br />
PageSetup pagesetup = document.GetPageSetup();<br />
float bottomMargin = pagesetup.GetBottomMargin();
if(bottomMargin < 70 ) <br />
pagesetup.SetBottomMargin(bottomMargin+20);
<br />
float leftMargin = pagesetup.GetLeftMargin();<br />
if(leftMargin< 70)<br />
pagesetup.SetLeftMargin(leftMargin+20);<br />
float rightMargin = pagesetup.GetRightMargin();<br />
if(rightMargin < 70)<br />
pagesetup.SetRightMargin(rightMargin+20);<br />
<br />
float headerMargin = pagesetup.GetHeaderDistance();<br />
if(headerMargin < 60 )<br />
pagesetup.SetHeaderDistance(headerMargin+10);<br />
float topMargin = pagesetup.GetTopMargin();<br />
if(topMargin <60)<br />
pagesetup.SetTopMargin(topMargin +20);<br />
<br />
float footerDistance = pagesetup.GetFooterDistance();<br />
pagesetup.SetFooterDistance(footerDistance + 10);<br />
documents.ReleaseDispatch();<br />
cout<<"Printting document...";<br />
document.PrintOut(COleVariant((short)false), vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt, vOpt);<br />
<br />
document.Close(COleVariant((short)false), vOpt, vOpt);<br />
<br />
VARIANT x;<br />
x.vt = VT_I4;<br />
x.lVal = 1;<br />
app.Quit(covFalse,covOptional,covOptional);<br />
CoUninitialize();<br />
<br />
}<br />
<br />
return nRetCode;<br />
}<br />
<br />
<br />
Thank you
|
|
|
|
|
I don't know MFC very well, but in VB you have to set all your office objects to nothing when you are done with them. Otherwise, the reference stays alive despite app.quit. Try to find a way to nullify or destroy all your reference objects rather than just letting them go out of scope. I see that you call CoUninitialize() and ReleaseDispatch(), but like I said I don't know enough about MFC to know how these work. Maybe try testing your objects before you return to see if they are fully destroyed.
Hope I helped.
|
|
|
|
|
what do you mean by saying
<br />
Try to find a way to nullify or destroy all your reference objects rather than just letting them go out of scope
I'm using network though. this program has been 4 days.. it works fine now and later it is not.. i have no clue at all coz this is my very first COM or Automation application.
I tried so hard to understand what is really going on within my application that sometimes works and mostly not. I couldn't find any book that's talk about why i can't get my word.application. I though it is because I couldn't initialize OLE libs. Anybody Anyone can tell me what is wrong with my code? what is causing my application not to app.createdispatch("Word.Applicaiton");
|
|
|
|
|
If it works at first and then suddenly stops working, then unreleased references are likely the cause. Try to set your Word.Application object to null or something of that sort. I wish I could help more, but I don't know MFC well enough.
Hopefully someone on CP can be more useful.
|
|
|
|
|
Thanks for your explaination. You are helping me and I don't know VB either but I think as long as the classes or functions is win32 API, both VB and C++ programmers can use in the same way, ofcourse the syntax will be different.
Anyway..Let's talk about my problem. Let me tell you one thing I just found out. As I told you, I'm using Network. I have
C:\,J:\,I:\,H:\,G:\...etc.
C:\ and G:\ drives is only I can access. It is private. but J:\, I:\ and H:\ are public. All the users can access to those drives. J:\ is a common one. All the users are on J:\ all the time.
My program give me a message "Couldn't create MS Word Application Object ",
<br />
_Application app<br />
if(!app.CreateDispatch("Word.Application"))<br />
{ <br />
AfxMessageBox("Couldn't create MS Word Application Object ");<br />
return 1;<br />
}<br />
but not from other running from C:\ and G:\. So can you give me any suggestion what do I need to change or do inorder to let my program run correctly on J:\?oh.. it is only works on my machine.. i mean even I copy my program and paste other users' c:\(machines). still it doesn't work.. the same message is giving me...
|
|
|
|
|