|
From a quick skim of your link, yes, this is all you need to do to get a connection point up and running. It should work OK out-of-process, from without your additions. Having written the object in ATL,
I'd advise writing a simple test client using a Win32 project in C++ that creates the object, calls advise and then tests your event without the complications of C# and .NET.
|
|
|
|
|
I have 2 DLLs, one is inheriting and implementing functions from the other. After implementing these functions, they are visible to other applications.(c# interop) I would like to add yet another function to the inheriting DLL(of my own making). I have done this but the method never shows up to external apps. I am using the format(among others):
public:
STDMETHOD(FunctionName)(Args);
The inheriting DLL does not provide an interface, but the functions *do* show up and I can call them fine. But no matter how I add that 1 function, I cannot get it to export. I have even tried creating a completely separate(3rd) ATL object with a single interface exporting a single function and inheriting/implementing that as well. Everything builds and runs fine, just no function. I just used the nifty little "Implement Interface" wizard and it created all the necessary spaghetti.
So the question is: How do I export a public function from an ATL object?
Note: The original DLL I am inheriting from is not mine, it's part of an SDK and I have no control over it. I just use it.
I am confident this all stems from my completely perverted understanding of interfaces and how they work, but this got dumped in my lap with the obligatory truncated timetable.
I am using XP SP3, VS2003 for the unmanaged code(SDK mandates that I use 2003), and VS2005 for the managed stuff. Thanks!
|
|
|
|
|
It's a bit hard to solve your problem without more information. I can't decide if you're trying to export a new function from a dll or expose a new COM interface or new COM interface method.
|
|
|
|
|
Thanks for the response and sorry for the confusion. This is probably like asking a blind man to describe what his attacker looked like, but:
My dll inherits from another dll and implements it's functions. These functions are visible to outside objects. I want to add another function(public, interface, however) that originates only in my dll but is also visible to outside objects. My dll is a COM dll with MFC and ATL support. When I look at it in the Class View, there is no interface listed for my class. I found an article on MSDN that gave some sketchy instructions for adding an interface to an existing COM object both manually and through a wizard.
I added the interface manually into the IDL and everything compiled fine. The interface showed up in the Class View and I was able to add a method to it fine. The problem was, the wizard never put the stubs in the .h and .cpp files. I added them manually as well and compiled. C# then complained that QueryInterface failed with a "NOINTERFACE" when I tried to use the interface.
Then I tried to add an interface via the "Implement Interface" wizard, but it will only use interfaces via an existing TLB. This is when I created another separate ATL simple object with an interface and single method. I used the wizard on this tlb and it created everything(including the stubs) perfectly. Still when I try to use the interface, while it does not complain, my single function does not show up.
So I'm guessing my specific question is; how do I add a *new* interface to an *existing* COM object?
I realize I'm probably asking you to describe what shape I'm thinking of, so feel free to forward me to a tarot reader.
|
|
|
|
|
asdfhjkasdf dfhjksdf wrote: complained that QueryInterface failed with a "NOINTERFACE"
Sounds like you need to add code to your ATL Objects QueryInterface method that will provide your interface when it's asked for as that's where the error code E_NOINTERFACE is returned if you have'nt done this.
|
|
|
|
|
Perhaps this is my problem. My object doesn't have a QueryInterface method. Isn't this added automatically when the object is created or ATL support is added?
|
|
|
|
|
Any interface e.g. IMyInterface should inherit from the IUnknown interface and its the IUnknown that has three methods: QueryInterface AddRef and Release. Without seeing the code it's hard to say whats going on.
The ATL Wizard usually create these for you.
Two possibilities come to mind:
Add a QueryInterface method and see if you get complaints about one already existing so you can find it
or:
Create a simple Win32 exe in the same VS solution, After using OLEInitialise create an instance of your COM object using CoCreateInstance and then call QueryInterface and step in to see what's going on.
|
|
|
|
|
I just started the entire dll from scratch. New ATL project, added a simple ATL object and inherited from CAxDialog and the other class just like the old dll. I now have a valid interface and I can add my method to it. Everything works great and I can see my new method plus the inherited ones from c# since I finally have a %#@#$ interface. I started copying in chunks of code from the old class used to implement the inherited interface. There are a couple of calls to _Module that it's crapping out on. So I added it to Stdafx.h like the other class. In the form of:
#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
Now the build errors on this line stating:
error C2146: syntax error : missing ';' before identifier '_Module'
If I comment out the line, it builds fine.
Why the heck would they waterboard at Gitmo when they could just sit them down and make them learn COM/ATL?
|
|
|
|
|
You'll find _Module is used for entry points such as DllGetClassObject and DllRegisterServer. You can either read up on it or you could try creating a new (temporary) Dll with the ATL Wizard in a new solution just to see where Module is used and to find where your project is missing it. I have a feeling it was remamed at some point, perhaps after VC6, so it could be just the name that's different.
|
|
|
|
|
You're exactly right. I found out about 9pm last night that the CComModule stuff gets put in there by 6.0. If you create a project in 6.0 and import it into 2003, 2003 builds it fine. If you just add in the code in 2003, sheer panic. So I created the entire project from scratch in 6.0, imported it into 2003, and added all the necessary inheritance/implementation stuff, and IT WORKS! Just like I wanted.
Almost.
Everything works as planned except that when I access it from c# and call my method, there is a global var in the module that is set by another application that my function needs. It always turns up null. I think it's because c# instantiates a new instance of the module and that var hasn't been set yet. So now I am off to try to figure out how set up a singleton ATL object. So far I've been unable to find out how to do this via a wizard.
Thanks for your help!
|
|
|
|
|
If a component was implemented in a exe server, the owner of the exe process would be created when a client use ::CoCreateInstance to retrieve such a interface. I want to run the server in a hide mode, i use ShellExecute with SW_HIDE flag to start the exe server, but the exe still runs as normal. So, i want to create another new desktop and create the target process on that desktop, but the problem is, the ::CoCreateInstance would fail. The steps look like following:
HDESK hDesk = ...
if(hDesk){
SetThreadDesktop(hDesk);
...
hr = ::CoCreateInstance(...);
}
If so, how should i fix such problem?
|
|
|
|
|
You could try CreateProcess with the wShowWindow member of the STARTUPINFO structure set to SW_HIDE .
Also remember to set the STARTF_USESHOWWINDOW flag in the dwFlags member.
|
|
|
|
|
oh, i forgot to say, this method still can't start the exe server in background
|
|
|
|
|
Hi,
I want to get the full path of specified path. I use following function as
DWORD dwRet = 0;
TCHAR szPath[500];
LPTSTR lpszFilePart;
dwRet = GetFullPathName(_T("MyFile.txt"),
sizeof(szPath) / sizeof(TCHAR),
szPath, &lpszFilePart);
In above function i get path in szPath variable. but this path is always shows path in desktop, thought myfile.txt is placed in D: drive in othere folder.Also if file name not exists, though it show path with specied file name.
How can I get full path of file by giving file name as input parameter.
Thanks
Abm
|
|
|
|
|
If you read the MSDN documentation, under Remarks is says:
GetFullPathName merges the name of the current drive and directory with a specified file name to determine the full path and file name of a specified file...This function does not verify that the resulting path and file name are valid, or that they see an existing file on the associated volume.
I think you will find that the current directory is set to the desktop which is why you are getting the result you are. If you want a full path to a different directory you will have to change the working directory.
|
|
|
|
|
Hi,
I have a need to resize the ATL dialogs based on the screen resolution.
In the resource editor, If I just change the font of the dialog, then the dialog gets resized automatically. I need the same to do at runtime. This could be done in MFC by means of PreCreateDialog metod which could be implemented by the applications and the framework calls it whenever any dialog gets created. In this method we can make use of CDialogTemplate class and set a different font which actually resizes the whole dialog as well as all the controls on it automatically at runtime.
Is there any similar way for ATL. I know about the win32 API: DialogBoxIndirectParam(...) but don't know how to make use of it in ATL to load a dialog resource, modify the font and then launch the dialog.
Any help would be greatly appreciated.
Thanks
|
|
|
|
|
Hi,
Look at the code for ATL::CDialogImplBaseT<>::ExecuteDlgInit() in atlwin.h. That's what it does.
cheers,
AR
|
|
|
|
|
Hi,
I have been trying to develop a sidebar for windows media player similar to freeware iLike. Could anyone give some suggestions on how to attach a window to the media player.
Thanks
Smitha
|
|
|
|
|
I originally posted this on the C/C++/MFC forum but should have posted it here.
This program runs fine except when I try to delete/remove/erase an item as indicated below. No matter what I've tried with erase the program crashes.
Could someone please help here.
Thanks
Alan Kurlansky
PS. When I cut and pasted some characters got changed. I hope I fixed alll of them. I didn't see the options available below.
This program runs fine except when I try to delete/remove/erase an item as indicated below.
Thanks
Alan Kurlansky
PS. When I cut and pasted some characters got changed. I hope I fixed alll of them.
// MultiMap.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
using namespace std;
void testmultimap();
#include <tchar.h>
struct ASK {
int ival;
string key;
};
multimap<string, ASK *> mymm2;
multimap<string, ASK *>::iterator iter;
pair<multimap<string, ASK> ::iterator,multimap<string, ASK *>::iterator> ret;
int _tmain(int argc, _TCHAR* argv[])
{
testmultimap();
return 0;
}
//----------------------------------------------------------------------------------------------------------------
void testmultimap()
{
string key;
key.clear();
key.append("a");
ASK * Iptr = new ASK;
Iptr->ival = 10;
Iptr->key.clear();
Iptr->key.append(key);
mymm2.insert(pair<string,ASK *>(key, Iptr));
key.clear();
key.append("a");
Iptr = new ASK;
Iptr->ival = 20;
Iptr->key.clear();
Iptr->key.append(key);
mymm2.insert(pair<string,ASK *>(key, Iptr));
key.clear();
key.append("b");
Iptr = new ASK;
Iptr->ival = 30;
Iptr->key.clear();
Iptr->key.append(key);
mymm2.insert(pair<string,ASK *>(key, Iptr));
key.clear();
key.append("a");
ret = mymm2.equal_range(key);
int cnt(0);
for (iter=ret.first; iter!=ret.second; ++iter) {
printf("ival:%d key:[%s]\n", (*iter).second->ival, (*iter).second->key.c_str() );
// delete this single entry
// mymm2.erase(????);
}
printf("\n");
printf("2nd pass after 'a' erase\n");
ret = mymm2.equal_range(key);
for (iter=ret.first; iter!=ret.second; ++iter) {
printf("ival:%d key:[%s]\n", (*iter).second->ival, (*iter).second->key.c_str() );
}
printf("\n");
key.clear();
key.append("b");
ret = mymm2.equal_range(key);
for (iter=ret.first; iter!=ret.second; ++iter) {
printf("ival:%d key:[%s]\n", (*iter).second->ival, (*iter).second->key.c_str() );
}
printf("\n");
}
//----------------------------------------------------------------------------------------------------------------
|
|
|
|
|
I don't know how you compiled the code successfully.
I have to change the definition of ret to:
pair<multimap<string, ask*=""> ::iterator,multimap<string, ask="" *="">::iterator> ret;
The code runs well here.
and if you want to delete some items, you should save a temp iterator first, and forward the original iterator as normal like:
iter = ret.first;
while(iter!=ret.second){
printf("ival:%d key:[%s]\n", (*iter).second->ival, (*iter).second->key.c_str() );
multimap<string,ASK*>::iterator it = iter;
++iter;
mymm2.erase(it);
}
I think it will work as you want.
modified on Thursday, December 3, 2009 12:56 AM
|
|
|
|
|
Hello,
I have a VC++ 6.0 ATL Project.
I insert in this project a ActiveX OCX Component with following import routine in the header files.
I have access to the methods/function of the ActiveX with for example CComPtr<_grdView> pGrid;
The line #import "ActiveX_Name.ocx" creates a ActiveX_Name.thl .It was create by VC++6.0 compiler.
It's C++ source equivalent of Win32 type library ActiveX_Name.ocx.
I can look for the clsid id and register(CoGetClassObject( GetClsid(), CLSCTX_ALL, NULL, IID_IClassFactory2, (void**)&ipCF2); ) it in my programm.
Problem: How can I insert the event handler functions?
The BEGIN_MSG_MAP(MyClassName)function is only for the application Windows Message, not for the
message of the ActiveX Component.
Can you help me?
I a MFC Project with the same ActiveX ,there is the ActiveX message .BEGIN_EVENTSINK_MAP.. ON_EVENT ...
Greetings, jens
<<<<<<example of="" code="">>>>>>
#import "ActiveX.ocx" raw_interfaces_only, raw_native_types, no_namespace, named_guids
class MyClassName:
public CWindowImpl< MyClassName, CAxWindow >
{
public:
DECLARE_WND_SUPERCLASS(_T("MyClassName"), CAxWindow::GetWndClassName());
BEGIN_MSG_MAP(MyClassName)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLeftMouseButton)//left doubleclick in activeX doesn't work
END_MSG_MAP()
// Handler prototypes:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
CComPtr<_grdView> pGrid;
CComPtr<iunknown> pUnkCont;
CComPtr<iunknown> ipUk;
CLSID const& GetClsid() //CLSID_grdView
{
static CLSID const clsid
= {0x5ff50e07,0x9af6,0x4f2e,{0x81,0x4d,0x23,0x5c,0xad,0xc8,0x6b,0x73}};
return clsid;
}
<<<<<<<<>>>>>>>>
|
|
|
|
|
from memory, you need to handle 'event sinks' with an event sink ?map (much like a message map) - but Im afraid Ive forgotten the fine details - Im just trying to find an example to point you at ...
'g'
|
|
|
|
|
|
Does anybody know a tutorial for handle the described event from an activeX component without MFC?
Alternate, an VC++ 6.0 example project of an any activeX library will be also fine.
|
|
|
|
|
VC++6 on XP Pro
greetings all,
I've created an STL list object that stores =references= to objects. I've overloaded the less-than operator like numerous examples on the 'net say to do. The following code compiles and executes but does not sort - actually the order does change but not in a sorted order. I'm stumped - there must be some nuance I'm missing.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <list>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
struct pstchip_pin_wor {
string primitive;
string pin_name;
string pin_number;
pstchip_pin_wor( string aa, string bb, string cc) {
primitive = aa;
pin_name = bb;
pin_number = cc;
}
pstchip_pin_wor& pstchip_pin_wor::operator = (const pstchip_pin_wor &itemToCopy) {
this->primitive = itemToCopy.primitive;
this->pin_name = itemToCopy.pin_name;
this->pin_number = itemToCopy.pin_number;
return *this;
}
int pstchip_pin_wor::operator == ( const pstchip_pin_wor& itemToCompare) const {
if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name ) return 1;
return 0;
}
int pstchip_pin_wor::operator < ( const pstchip_pin_wor& itemToCompare) const {
if( this->primitive < itemToCompare.primitive ) return 1;
if( this->primitive == itemToCompare.primitive && this->pin_name < itemToCompare.pin_name) return 1;
return 0;
}
};
int main(int argc, char* argv[]) {
int nRetCode = 0;
list<pstchip_pin_wor*> wors_pstchip_pins;
wors_pstchip_pins.push_back( new pstchip_pin_wor( "Europe", "Spain", "Madrid" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "USA", "Washington DC" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "Canada", "Ottawa" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "Europe", "Germany", "Berlin" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "South America", "Brazil", "Sao Paulo" ) );
wors_pstchip_pins.push_back( new pstchip_pin_wor( "North America", "Mexico", "Mexico City" ) );
cout << "before sorting" << endl << endl;
for( list<pstchip_pin_wor*>::iterator ka = wors_pstchip_pins.begin(); ka != wors_pstchip_pins.end(); ka++ ) {
cout << (*ka)->primitive << "==" << (*ka)->pin_name << "==" << (*ka)->pin_number << endl;
}
wors_pstchip_pins.sort();
cout << endl << "after sorting" << endl << endl;
for( list<pstchip_pin_wor*>::iterator zm = wors_pstchip_pins.begin(); zm != wors_pstchip_pins.end(); zm++ ) {
cout << (*zm)->primitive << "==" << (*zm)->pin_name << "==" << (*zm)->pin_number << endl;
}
return nRetCode;
}
Would someone be kind enough to point what I'm doing wrong/not doing right?
TIA,
kerchunk
|
|
|
|
|