|
Hi,
I have a toolbar and I am trying to access the IWebBrowser2 in WM_LBUTTONDOWN, when someone clicks on a control on my toolbar with the following code:
BSTR bstrUrl;
CComPtr<iwebbrowser2> browser;
browser->get_LocationURL(&bstrUrl);
I am getting a debug assertion failed!
p!=0
I know there should be more to the code. Can somebody help?
|
|
|
|
|
Hi
Assuming p refers to the interface pointer in CComPtr, you need to initialise it first - CComPtr needs to hold a valid reference to an IWebBrowser2 interface.
HTH
Martin
|
|
|
|
|
Sorry, but how would I initialize it? I am a newbie to ATL. Sorry, I forgot to mention that I have instantiated a webbrowser object in the toolbar class in another file with:
IWebBrowser2* m_pBrowser;
|
|
|
|
|
Nice question =)
Here is an example of 'SetSite' function for your toolbar.
So, you will get IWebBrowser2* to m_pWebBrowser variable.
IWebBrowser2 * m_pWebBrowser;
...
STDMETHODIMP CToolBarImpl::SetSite(IUnknown* pUnkSite)
{
...
IServiceProviderPtr pServiceProvider = pUnkSite;
if (m_pWebBrowser) m_pWebBrowser = NULL;
if (FAILED(pServiceProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)&m_pWebBrowser))) return E_FAIL;
if (m_pWebBrowser==NULL) return E_INVALIDARG;
...
return S_OK;
}
|
|
|
|
|
Thanks for the reply.
My toolbar class already has a SetSite function that basically does what your function does. I, however, also have a seperate file that is used the by the toolbar. The file is a non-class, with a function that converts a Static control into hyperlink, and then when the hyperlink is clicked, it does a ShellExecute to send you to a certain url.
Problem is, in that function that sends you to the certain, I need to obtain the browser object to do a get_LocationUrl, which is what I've been having problems with.
|
|
|
|
|
Hi,
can anyone tell me how macromedia does their silent install of the flashplayer?
thanks
badi
|
|
|
|
|
You have flash.ocx or swflash.ocx sw(shockwave)component ActiveX distribuited for Macromedia , you must do in your instalation regsvr32 /s flash.ocx..
Instance Interface ocx .. Call methods & properties ... is easy
Good Lucky!
Sorry for my bad english.
I hope that You can excuse me )
|
|
|
|
|
My ATL service crashes when it is being stopped by the system (its startup mode is "automatic"). This happens only if the service is running on Windows XP and is being stopped automatically (not manually).
The source code:
HRESULT CMyServiceModule::PostMessageLoop()<br />
{<br />
RevokeClassObjects();<br />
LogEvent(_T("Service stopped"));<br />
CoUninitialize();<br />
<br />
SetServiceStatus(SERVICE_STOPPED);
<br />
return CAtlServiceModuleT<CLegnLicenceServiceModule, IDS_SERVICENAME>::PostMessageLoop();<br />
}
The debugger shows that m_hServiceStatus is NULL.
Thank you in advance for any ideas.
|
|
|
|
|
Hi
It's a bit weird since m_hServiceStatus is a member of the statically allocated CMyServiceModule class.
Anyway, what I'll try to do is;
see if the m_hServiceStatus is non-NULL when the PostMessageLoop function is entered. If so, RevokeClassObjects or CoUnitialize (or another thread) will be fiddling with the module object.
If you can't find whatever code is setting the m_hServiceStatus to NULL, you may find it's address (say after the service is started) and set a breakpoint that monitors an address (ie. set a Condition to 'when (*(int*) 0x12345678) changes' and 0x12345678 is the address of the m_hServiceStatus data member).
Are you sure it's not CoUnitialize causing the exception? - typically things will go bonkers if you still have outstanding COM references and call CoUninitialize. Could it be another app still has COM references to objects allocated by the ATL service?
Martin
|
|
|
|
|
Home > Software > Internet Explorer IE5 Programming Components Browser Control > How to open Web...
Post 1 of 1
Topic 259 of 260
How to open Web Browser from Outlook Addin
by "devom" <devom@rediffmail.com> Jan 14, 2005 at 02:30 AM
I had created an Outlook Addin using VC++ ATL.There I had created button on
Outlook Toolbar.I
want to open a Web Browser window on clicking on the button.The web
Browser Window could not have any
Buttons,Toolbars etc.eg.I just want to open www.rediff.com in the window
upon initialisation.Next, I want to capture
click events on the rediff page.(Eg. on what picture in the html page did
the user clicked)
How should .I move forward .Plz explain with steps
Thanks in advance
|
|
|
|
|
Why you do'nt create SDI-HtmlView with WTL wizard no toolbar no status etc..?
You must be put your "http::\yourwebpage" in parameters creation view and works finished..
If you want capture click events etc.. you must get IWebBrowser2 Interface, You can read this article http://www.codeproject.com/wtl/wtlbrowser.asp
Good Lucky!
|
|
|
|
|
You can start from this:
IWebBrowser2* RunIe( bool show )
{
IWebBrowser2 *pIE = NULL;
HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&pIE);
if (SUCCEEDED(hr) && show) pIE->put_Visible(VARIANT_TRUE);
return pIE;
}
So, you will have IWebBrowser2* to control IE window then (remove toolbars, set the size, set even handlers, etc...)
|
|
|
|
|
Hello,
I have text in bstr string. Text is in some code page.
How to convert text from code page to UTF8 and put it in wchar_t?
|
|
|
|
|
Hello,
I am beginner in STL and never use it in MSVC. I am developing an application DLL that I have a template for it which is based on STL. When I am trying to compile the template I will get the following error for this line of code. What is the problem and how can I solve it? Is it related to the way that I setup my MSVC?
I am using MSVC 6 on window XP sp1:
Line that generate error:
typedef vector<string>::value_type value_type;
Error message:
error C2653: 'vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >' : is not a class or namespace name
I check and it seems that vector is included to the file.
Best regards
Mansour
|
|
|
|
|
|
Hi i writing my own OLEDb provider so some other application.
for this i need to replace the existing Connection and Advanced tab
provided by Microsoft OLEDB.
so if any body can help me out then it will be really great assistance to me
I am using VC++ 6.0 with service pack 6.
Thanks in advanced
Zeeshan
|
|
|
|
|
Hi,
I am using ATL to create a toolbar with a initially positioned static control in it with the following code in my Toolbar Class:
CWindow m_TextWindow;
LRESULT CToolbar::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HWND m_Text = CreateWindow("STATIC", "Test Text", WS_CHILD | WS_VISIBLE, 465, 4, 15, 20, m_hWnd, NULL, NULL, NULL);
m_TextWindow.Attach(m_Text);
return 0;
}
In my OnSize function, I have the following code:
LRESULT CToolbar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RECT staticRect;
::GetClienRect(m_TextWindow, &staticRect);
staticRect.right -= 100;
return 0
}
However, I can not position the Static Control whenever I size the window.
Thanks in advance.
|
|
|
|
|
tdnxxx444 wrote:
LRESULT CToolbar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RECT staticRect;
::GetClienRect(m_TextWindow, &staticRect);
staticRect.right -= 100;
return 0
}
before you return 0, you have to call
m_TextWindow.MoveWindow()
to actually change the position/size of the control.
|
|
|
|
|
--------------------------------------------------------------------------------
Hello, I am newbie to Visual C++ / ATL Programming with a question:
I have a toolbar class in which I have an instance of IWebBrowser2 that is used by the toolbar to naviagate Internet Explorer to various urls. I also have a seperate hyperlink function, not part of any class, that converts static controls into hyperlinks. The hyperlink function catches whenever the hyperlinked static control is clicked. I need to do it so that whenever the control is clicked, the current url is grabbed and something is done with it by the event in the hyperlink function. I have tried to create another instance of IWebBrowser2 in the hyperlink function and then use the get_LocationUrl to try to get the current Url, however there
is a runtime error. Please help.
Thanks in advance.
|
|
|
|
|
I have looked into this - honest and really beating my head against a wall. This is one of my first forays into COM and ATL and can't get over the first hurdle. Using the ATL wizard, I created a ATL COM Server, added a Simple COM object, and then added a single property with get and put. It should simply set and get a string - in this case - _firstname . COM class below, with the IDL snippet and implementation for the property get/put methods...
I eventually 'got' the property into my MFC dialog but can't set it. That follows the COM code...
class ATL_NO_VTABLE CFamily :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CFamily, &CLSID_Family>,
public IDispatchImpl<IFamily, &IID_IFamily, &LIBID_TESTCOM_V6Lib>
{
public:
CFamily()
{
_firstname = "Angel";
}
DECLARE_REGISTRY_RESOURCEID(IDR_FAMILY)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CFamily)
COM_INTERFACE_ENTRY(IFamily)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
public:
STDMETHOD(get_FirstName)( BSTR *pVal);
STDMETHOD(put_FirstName)( BSTR newVal);
private:
CComBSTR _firstname;
};
STDMETHODIMP CFamily::get_FirstName(BSTR *pVal)
{
*pVal = _firstname.Copy();
return S_OK;
}
STDMETHODIMP CFamily::put_FirstName(BSTR newVal)
{
_firstname.m_str = newVal;
return S_OK;
}
And now the MFC dialog stuff....I've #IMPORT ed the library so I can use the smart pointers...
#import "../debug/TestCOM_V6.dll" no_namespace
void CComTesterDlg::OnSetFirstName()
{
UpdateData();
::CoInitialize(NULL);
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
first->PutFirstName(m_FirstName.AllocSysString());
first = NULL;
::CoUninitialize();
}
void CComTesterDlg::OnShowFirstName()
{
::CoInitialize(NULL);
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
m_ShowFirstName = (char*)(first->GetFirstName());
UpdateData(FALSE);
}
The OnShowFirstName retrieves the string from the COM but I can't set it with OnSetFirstName . The CreateInstances both work as I've stepped through it. I appreciate you should initialse the COM object once, but this is just a test harness. Also, (in for a penny(cent) in for a pound(dollar) ), if I uncomment the ::CoUninitialize in the OnShowFirstName the app bombs out with a 'read error'.
So
1) Why is the CComBSTR _firstname not being set in my COM object when I call OnSetFirstName ?
2) Is my get implementation the best method of doing this?
3) Why does the ::CoUninitialize crash on the second method but not the first?
4) I am really sorry for these 'hopefully trivial' questions...
Regards
Angel.
*********************************************
The sooner you fall behind, the longer you have to catch up.
|
|
|
|
|
Hi
I have 3 points to make;
1. Looking at the following code;
STDMETHODIMP CFamily::put_FirstName(BSTR newVal)
{
_firstname.m_str = newVal;
return S_OK;
}
You should use the CComBSTR's assignment operator, like so;
STDMETHODIMP CFamily::put_FirstName(BSTR newVal)
{
_firstname = newVal; // makes a copy of (the client allocated) newVal, and SysFrees the old string in _firstname.m_str
return S_OK;
}
Otherwise, by just calling _firstname.m_str = newVal, you end up leaking the (old) value in _firstname.m_str and taking ownership of the client allocated string newVal and end up calling SysFree in both the COM server and client.
2. You're leaking a BSTR when calling PutFirstName;
void CComTesterDlg::OnSetFirstName()
{
UpdateData();
::CoInitialize(NULL);
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
first->PutFirstName(m_FirstName.AllocSysString());
first = NULL;
::CoUninitialize();
}
You're calling AllocSysString, without a corresponding SysFreeString. If you're passing a BSTR to a COM client as a read-only (IDL in) parameter, the client both allocates and frees the BSTR, if the server wishes to hold on to it, it should make a copy (as demonstrated in point 1.)
So change the code to read;
void CComTesterDlg::OnSetFirstName()
{
UpdateData();
::CoInitialize(NULL);
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
first->PutFirstName(CComBSTR(m_FirstName));
first = NULL;
::CoUninitialize();
}
where the CComBSTR class will both allocate and free the (client-side) BSTR.
3. Using smart pointers and CoUnitialize;
void CComTesterDlg::OnShowFirstName()
{
::CoInitialize(NULL);
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
m_ShowFirstName = (char*)(first->GetFirstName());
::CoUninitialize();
UpdateData(FALSE);
}
The reason the ::CoUninitialize is causing problems there, is because the COM interface reference kept in the IFamilyPtr first has not been released yet. Change it to this;
void CComTesterDlg::OnShowFirstName()
{
::CoInitialize(NULL);
{
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
m_ShowFirstName = (char*)(first->GetFirstName());
} // smartpointer's destructor (~IFamilyPtr) calls Release on the IFamily interface
::CoUninitialize(); // everything's released now, leave COM apartment
UpdateData(FALSE);
}
or (equivalent to calling 'first = NULL;')
void CComTesterDlg::OnShowFirstName()
{
::CoInitialize(NULL);
IFamilyPtr first;
HRESULT hr = first.CreateInstance(__uuidof(Family));
if (SUCCEEDED(hr))
m_ShowFirstName = (char*)(first->GetFirstName());
first.Release(); // smartpointer calls Release on the IFamily interface !! note the use of '.' and NOT '->' !!
::CoUninitialize(); // everything's released now, leave COM apartment
UpdateData(FALSE);
}
BTW: You can call ::CoInitialize once in CWinApp::InitInstance and ::CoUninitialize in ExitInstance, or use the MFC equivalent AfxOleInit in InitInstance only.
HTH
Martin
|
|
|
|
|
You had three points to make and you made them very well - many thanks for spending the time on this. I sussed the Release() one just now, but I am still leaking BSTRs all over the shop. Thanks for the BSTR/CComBSTR info - should plug a few holes.
One more quick question (nothing like taking advantage is there...BTW I rated you a 5 on your previous answer ) - what is the concept of apartments? You said in one of your comments 'leave COM apartment' - what is the apartment? I know you can have single threaded apartments, free apartments (multi threaded?) but what is an apartment?
Thanks again.
*********************************************
The sooner you fall behind, the longer you have to catch up.
|
|
|
|
|
Hi
When a Win32 thread calls CoInitialize, it is said to enter a COM apartment. When it calls CoUninitialize, the thread leaves the COM apartment. If it hasn't called any of these functions, it is known to NOT be in a COM apartment. If a thread is not in a COM apartment, it cannot meaningfully use COM, eg. call CoCreateInstance, etc. - this includes using COM interface pointers acquired by other threads.
So, all COM clients should enter an apartment, ie. call CoInitialize/CoUninitialize.
COM components served up by an in-process (DLL) COM server, don't need to explicitly enter a COM apartment, since they're loaded into the process space of the client and as such inherit the client's apartment type. However, specifying a ThreadingModel Registry value under the component's HKCR\CLSID\{clsid} key, allows the overriding of this, specifying a preferred apartment type for components activated from that DLL server. This then prompts the COM layer to create an apartment (ie. thread) for that preferred apartment type, and activate the component therein by some COM proxy/black magic.
COM components served up from a out-of-process (EXE/local) server, require explicitly entering an apartment since they live in a separate process and subsequently separate threads - and as such cannot share the client's apartment.
To enter a COM apartment, you have 2 choices (maybe more on later platforms);
call CoInitialize(0) which has the thread enter an single threaded apartment (STA), or
call CoInitializeEx(0, COINIT_MULTITHREADED) to enter a multi-threaded apartment (MTA).
Calling CoInitializeEx(0, COINIT_APARTMENTTHREADED) is the same as CoInitialize(0).
CoInitializeEx is available if '_WIN32_WINNT >= 0x0400' or '_WIN32_DCOM' is defined - I usually add the following at the top of my code;
#define _WIN32_WINNT 0x0500 // i'm (lucky and) using win2k and up
When COM clients and components interact, the apartment type influences the way methods are synchronized - loosely speaking, when accessing a component present in an STA, the COM layer ensures that no more than 1 thread accesses it at the same time (by injecting a proxy, driven by or relying upon a message pump).
MTA access implies standard Win32 multi thread access, leaving the component implementor to provide appropriate multi-thread access safeguards where necessary.
I believe the COM apartment information is attached to the thread with thread local storage (TLS), but I'm not sure and wonder why one should care.
No doubt more informed explanations exist.
Martin
|
|
|
|
|
Martin Koorts wrote:
No doubt more informed explanations exist.
...but not in plain English like this! I really appreciate the time / effort you've taken on the last two entries (haven't you got a job to do though?).
Best regards
Angel
*********************************************
The sooner you fall behind, the longer you have to catch up.
|
|
|
|
|
Well, yes of course
I use my left hand for that!
;-D
|
|
|
|
|