|
You're on the right track. But missing one detail - IOleObject::GetClientSite
Here's a code snip that I used in a recent ATL based ActiveX control to get the IHTMLDocument2 interface of the parent IE WebBrowser. Sure it goes a little farther than what you want by getting the document (one extra call), but it demonstrates the concept.
inline HRESULT GetIEDocument(IOleObject* pObject, IHTMLDocument2 ** ppDocument2 )
{
CComPtr<IOleClientSite> spClientSite;
CComPtr<IServiceProvider> spSrvProv;
CComPtr<IWebBrowser2> spWebBrowser;
CComPtr<IHTMLDocument2> spHTMLDoc2;
if( !ppDocument2 || !pObject )
{
ATLASSERT(!"Bad pointer param");
return E_POINTER;
}
HRESULT hr = pObject->GetClientSite((IOleClientSite **)&spClientSite);
if( FAILED(hr) )
return hr;
hr = spClientSite->QueryInterface(IID_IServiceProvider, (void **)&spSrvProv);
if( FAILED(hr) )
return hr;
hr = spSrvProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&spWebBrowser);
if( FAILED(hr) )
return hr;
hr = spWebBrowser->get_Document((LPDISPATCH*)&spHTMLDoc2);
if( FAILED(hr) )
return hr;
(*ppDocument2) = spHTMLDoc2;
(*ppDocument2)->AddRef();
return S_OK;
}
BTW, To the best of my knowlege ActiveX controls don't work in Nutscrape. Did you find a way for them to work?
[ Jason De Arte | Toy Maker | 1001010.com ]
|
|
|
|
|
Thanks Jason!
I only had to make a few changes to get your code working in my app.
I didn't need to pass the "IOleObject* pObject" object, since this code was in the same class as the main ATL ActiveX control. Aside from that, I just had to add the template definitions for the ATL classes used (IOleClientSite,IServiceProvider,IWebBrowser2). Also, "m_sLandingPage" is a global char* to the URL to navigate to. I think this code should work in almost any ATL ActiveX control.
And no, unfortunately, we weren't able to figure out a way to get ActiveX controls to work in Netscape, after much effort. The conclusion we came to was that it would require so much of Java wrapper that it was impractical.
<br />
bool Ccompctrl::LaunchURL()<br />
{<br />
CComPtr<IOleClientSite> spClientSite;<br />
CComPtr<IServiceProvider> spSrvProv;<br />
CComPtr<IWebBrowser2> spWebBrowser;<br />
<br />
HRESULT hr = GetClientSite((IOleClientSite **)&spClientSite);<br />
if( FAILED(hr) )<br />
return false;<br />
<br />
hr = spClientSite->QueryInterface(IID_IServiceProvider, (void **)&spSrvProv);<br />
if( FAILED(hr) )<br />
return false;<br />
<br />
hr = spSrvProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&spWebBrowser);<br />
if( FAILED(hr) )<br />
return false;<br />
<br />
CComVariant vNull;<br />
CComBSTR bsLandingPage = m_sLandingPage;<br />
hr = spWebBrowser->Navigate(bsLandingPage, &vNull, &vNull, &vNull, &vNull);<br />
if( FAILED(hr) )<br />
return false;<br />
<br />
return true;<br />
}<br />
|
|
|
|
|
I guess the same thing happened to you that just happened to me. The the template definitions, which were inclosed in "<>" were lost because it was considered HTML.
Here are the correct first three lines :
CComPtr<IOleClientSite> spClientSite;
CComPtr<IServiceProvider> spSrvProv;
CComPtr<IWebBrowser2> spWebBrowser;
|
|
|
|
|
d'oh!
Updated.
[ Jason De Arte | Toy Maker | 1001010.com ]
|
|
|
|
|
How can i use this for MSFLEXGRID control?
I use this, but it has runtime error!
void CMyViewEx::OnInitialUpdate()
{
AddResizedControl(IDC_MSFLEXGRID1, TOP_LEFT, BOTTOM_RIGHT);
CResizableFormView::OnInitialUpdate();
AnchorControls(); //Error here
}
|
|
|
|
|
Sir,
I m implementing std::maps and new to maps
I am using int as the key and the class as the value.
I have declared it like this
But my main is to insert a int as the key and the entire class as the value.
Also by giving the key ,I want to get the value using find function
How to achieve this.
Pls correct me if I am wrong.
#include <iostream>
#include <string>
#include
class one
{
int age;
int sal;
}one1;
typedef map<int,one1> Map1;
int main()
{
Map theMap1;
Map::iterator theIterator1;
one.age =50;
theMap1.insert(Map::value_type(0,one.age));
theMap1.insert(Map::value_type(1,one.age));
return 0;
}
I am getting errors
Regards
|
|
|
|
|
You seem to have a confusion between Map1 and Map , between one1 and one , or are these just typos in the post?
What are your errors?
Paul
|
|
|
|
|
I need to map an int to a class.
so this is the code.I hope I am clear.
#include <iostream>
#include <string>
#include
sing namespace std;
class one
{
int age;
int sal;
}one1;
typedef map<int,one1> Map;
int main()
{
Map theMap;
Map::iterator theIterator;
//Open the file
//Read each line of file and store in class variables
index = 0;
while(!file.eof())
{
one.age =50;
one sal = 1000;
theMap.insert(Map::value_type(index,one));
index++;
}
//to get the class
theIterator = theMap.find(0);
//Get the entire first record ?How should I achieve this which is stored in a class?
cout << endl << "The class "<< (*theIterator).first;
cout << endl << "The class "<< (*theIterator).second << endl ;
return 0;
}
|
|
|
|
|
i had a little time to delve into this, so here you go:
It appears that your map declaration is incomplete:
typedef map Map
should look like:
typedef map<int, one=""> Map
stl maps are templated classes, meaning at declartion time
the coder needs to tell the map what is being stored
in the map, in this case, an integer and a One object are
being stored in the map.
--
your One class should have the age
and salary members public (for the quicky example);
I changed your One class to look like
class One
{
public:
One() {age = -1; sal = -1;}; //ctor
int age; // these could be private wwith public accessors..
int sal;
protected:
private:
};
--
also in your while loop, you should
instantiate a new One object (either
on the heap with 'new' or on the stack like below):
when assigning the int and the One object to the
map, stl will use the One object's copy constructor
to make a copy of the object to store in the map;
while(!file.eof())
{
One newOne; // create new Oneobject on the stack
newOne.age = 50;
newOne.sal = 1000;
theMap.insert(Map::value_type(index, newOne));
index++;
}
--------
when printing out your map, your code as written assumes the One
class has an overloaded operator <<; you can also print the indiviudals members like so (note the accessing of the One object's members):
cout << endl << "The class "<< (*theIterator).first;
cout << endl << "The class "<< ((*theIterator).second).age << " | " << ((*theIterator).second).sal << endl ;
--
here's a cut and paste of my changes to your example:
i compile it but did not execute it, btw...
class One
{
public:
One() {age = -1; sal = -1;}; //ctor init of members
int age;
int sal;
protected:
private:
};
typedef map<int, one=""> Map;
int main()
{
Map theMap;
Map::iterator theIterator;
//Open the file
//Read each line of file and store in class variables
int index = 0;
while(!file.eof())
{
One newOne;
newOne.age =50;
newOne.sal = 1000;
theMap.insert(Map::value_type(index, newOne));
index++;
}
//to get the class
theIterator = theMap.find(0);
//Get the entire first record ?How should I achieve this which is stored in a class?
cout << endl << "The class "<< (*theIterator).first;
cout << endl << "The class "<< ((*theIterator).second).age << " | " << ((*theIterator).second).sal << endl ;
return 0;
}
sas
|
|
|
|
|
my first posting had a cut and paste error in it;
the map declaration should look like:
typedef map<int, one=""> Map;
--
sas
|
|
|
|
|
my cut and paste of the map declaration is getting
altered somehow; the angle brackets and template
parameters are getting stripped out.. wierd..
try paranthesis for visual sake
typedef map(int, One) Map
sas
|
|
|
|
|
Does this help?
#include <iostream>
#include <map>
class ClassOne
{
public :
int age;
int sal;
} ;
typedef std::map<int, ClassOne> Map ;
int main()
{
Map theMap;
Map::iterator theIterator;
for ( int i = 0; i < 1000; ++i )
{
ClassOne one ;
one.age = 40 ;
one.sal = 1000 ;
theMap.insert ( Map::value_type ( i, one )) ;
}
theIterator = theMap.find(0);
if ( theIterator != theMap.end ())
{
std::cout << "The index " << (*theIterator).first << std::endl ;
std::cout << "The class, age = " << (*theIterator).second.age << ", sal = " << (*theIterator).second.sal << std::endl ;
}
return 0;
}
There are other ways to manage insertion, for instance,
>#include <iostream>
#include <map>
class ClassTwo
{
private :
int age;
int sal;
public :
ClassTwo () : age ( 0 ), sal ( 0 )
{
}
void Set ( int a, int s )
{
age = a ;
sal = s ;
}
int Age () const
{
return age ;
}
int Sal () const
{
return sal ;
}
} ;
typedef std::map<int, ClassTwo> Map ;
int _tmain(int argc, _TCHAR* argv[])
{
Map theMap;
Map::iterator theIterator;
for ( int i = 0; i < 1000; ++i )
{
std::pair<Map::iterator,bool> itp = theMap.insert ( Map::value_type ( i, ClassTwo ())) ;
if ( itp.second )
{
theIterator = itp.first ;
(*theIterator).second.Set ( 40, 1000 ) ;
}
}
theIterator = theMap.find(0);
if ( theIterator != theMap.end ())
{
std::cout << "The index " << (*theIterator).first << std::endl ;
std::cout << "The class, age = " << (*theIterator).second.age << ", sal = " << (*theIterator).second.sal << std::endl ;
}
return 0;
}
Paul
|
|
|
|
|
The following is my code which use a IStream interface to dispaly JPEG.But after about 24 hours, an Assert error happened at NO.622 line in atlbase.h
//////////////////////////////////////////////////////////////////////////
IStream* pStream=NULL;
HGLOBAL hMemory=0;
BOOL bIsPicture ;
hMemory = ::GlobalAlloc( GMEM_MOVEABLE, iBufferLength );
ASSERT( hMemory != NULL );
LPVOID pData = ::GlobalLock( hMemory );
ASSERT( pData != NULL );
ASSERT(iBufferLength>=0);
memcpy(pData,buf,iBufferLength);
::GlobalUnlock(hMemory );
::CreateStreamOnHGlobal(hMemory,TRUE,&pStream );
ASSERT( pStream != NULL );
//here is other code
if(pStream)
{
pStream->Release();
}
if(hMemory)
{
::GlobalFree(hMemory);
hMemory=NULL;
}
please contact:
ctbpl_xiayi@yahoo.com.cn
|
|
|
|
|
No idea where line 622 is. So I would suggest reading about "Return Values" and making proper use of them.
Todd Smith
|
|
|
|
|
Hi there
The line 622 in atlbase.h is the -> operator of the CComQIPtr< > class template, and I don't see you are using any instance of it in the code you posted, so I suggest you to open the "Call stack" (Alt + 7) when you get the assert, and follow you way up until you reach the line in your code which is calling the -> operator on an instance of CComQIPtr<>, and then take a look why that pointer is NULL.
Regards,
Fabian
|
|
|
|
|
A long time ago I came up with a bunch of COM interfaces that were all defined in one IDL file. I created a number of COM objects that supported those interfaces by having the object's IDL file include the first idl file. It worked. All was well with the world.
Now, I am trying to make some changes, so I created a Ixxxx2 interface that inherits from Ixxxx in that first IDL file. When I try to get my ATL object to inherit from Ixxxx2 I get compiler error C2504, base class undefined. I've compiled the new version of the IDL file. The new interface is defined exactly the same in the .h file as all the other older interfaces. What am I doing wrong?
Thanks,
Tim
|
|
|
|
|
Hello everybody,
I am a beginner in com programming, and i have a question:
I have created an ATL 3.0 project including a simple object named MyObj with the attribute of 'appobject' on it's coclass. It has a property named MyString that holds string values. I have successfully built it and then tested it from vb. I have access to MyString property directly without instantiating MyObj. everythings is Ok.
but I have problem with VC. From a Console application which has access to that type library (via import directive) MyString property cannot be accessed without qualification. With the statement:
MyString = "Hello world!";
compiler generates following error:
error C2065: 'MyString' : undeclared identifier
what is the problem? do you think i should use a special syntax?
if so, would you please help me to know how i can use it?
thanks in advance
Roozbeh
|
|
|
|
|
Hi
I made ActiveX and it work fine.But some stranger behaviour is appeared.I compiled my project under Win2000 and then try register this component under Win98, raised error 0x000045a.But when i compile my project under Win98 ,this component registered fine both Win98 and Win2000.
Where trouble here??
Thanks.
|
|
|
|
|
at a quick glance, the error 0x000045a - "A dynamic link library (DLL) initialization routine failed" is probably
caused by differences in a DLL's version (methods, behaviour) between win98 and win2000. When compiling on win2000,
the compile initialization routines may be calling entry points
that are not in the older win98 version of the DLL in
question.
You may want to create an installation program (setup.exe)
with a tool (like installshield or wise or whatever) when
moving from a newer OS to an older OS. these install
programs identify the required versions of the needed
dlls and prompts you to install them during running
og the setup.exe program.
hope this helps at least a little bit.
sas
|
|
|
|
|
what is the preferred way to share instantiations between
different "instances" of the explorer shell (explorer.exe)?
I have read the Dunn articles on shell programming and
can't seem to share object instantiations between
explorer.exe "instances".
I have a ATL created shell extension that implements the
context menu interfaces and in a single instance
of the explorer, the code works fine;
If i fire up a second instance of explorer.exe
from the start task bar, and right click
on a file, the code crashes, and the debugger
takes me to the windows malloc.c src file.
my memory model is such that I keep instantiated objects in
the main application object (derived from public CWinApp),
and want to use these objects from the new instances
of the coclass that implements the IShellExtInit interfaces.
I have used the SHGetMalloc call to get an IMalloc interface
and use that for my mallocs.
one of the objects is a iDispatch class generated from
a typlib via the class wizard.. other classes are straight C++
impl classes that hold session data.
--
Any help is appreciated!
-
steves
sas
|
|
|
|
|
From my experince on shell extension you should never initialise anything during InitInstance or thread attach/detach calls.
All initialization should be in the IShellExtInit interface implementation only.
The call to initinstance is very unpredictable and should not be used to initialise internal data.
For example, When the dll it registered, at that time too initinstance is called, and your design could fail if you are assumeing that initinstance is called due to loading of dll by explorer.
I'll write a suicide note on a hundred dollar bill - Dire Straits
|
|
|
|
|
thanks for the reply.
THe IshellExitInit initialize method is called each time
the file's context menu is displayed;
At the very least, I need to to persist certain data in memory
across context menu invocations (which works, btw).
best case
scenario is when I can persist data in memory across
invocations of the explorer.exe
(which I can't get working yet)
Has anyone had experience with doing the above, short
of serializing and deserializing at every menu
IshellExitInit::initialize call?
sas
|
|
|
|
|
Are you tring to presist interface pointer(s) across different instance of the explorer ?
I'll write a suicide note on a hundred dollar bill - Dire Straits
|
|
|
|
|
thanks again for the help.
I'm trying to persist instations of
native contructs (like stl maps)
and a straight C++ class instantations across
different "instances" of explorer.exe. by "instances"
of explorer.exe I mean invocations from the start menu
(looking in the task manager process table; there is only
one explorer.exe process however).
from what i understand, IShellExtInit releated coclass
gets created every time the user right clicks on a
file name (bringing up the context menu). I want these
instances of the coclass to be able to access
my instantiations of my straight C++ class
that lives at the app level (CWinApp dervied class).
i'm pretty sure my problem is memory related;
--
is there a good description on how the shell works
when executing a new isntance of the explorer?
It appearsthat the Esposito Shell programming book
is out of print; this book probably has good info in it.
--
any info is further appreciated.
sas
|
|
|
|
|
Hi,
I'm writing my first ATL control that will be used inside an HTML page. I used the project wizard to create a simple control, I build it and tested it in the ActiveX test container. Now I want to start making my own changes and stepping through the code a bit to see how it works. How can I test a control and set breakpoints in the Visual Studio debugger so that it stops at that point, just like a 'normal' program? Thanks.
|
|
|
|