|
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
|
|
|
|
|
Greetings,
I am working on an ActiveX control based on an ATL control (in VS .NET). I wish to add an event, but there is no such option anywhere. I have tried right clicking on everything, all the drop down menus etc, but nothing....
How does one add an event to an ATL based ActiveX control?
Thanks,
Aristotel
|
|
|
|
|
My application has one usercontrol which act as drawing canvas. Here's how it works.
First user selects bitmap to be loaded, which gets painted in usercontrol hosted on form. Then, User draws basic shapes like rectangle, circle on drawing canvas to specify :-Dcertain areas of bitmap. Now, the problem is when user draws first shape after selecting shape type from toolbar, form shifts a bit up. After doing a bit of google I found that autoscroll propertly is bit tricky, and I have this propertly set to true (bcoz user may load a larger image than a drawing canvas).....So, Do I need to set some code in UserControl_Paint event or Form_Paint event....
Any help regarding this would greatly be apprciated...
REgards.
MaulikCE
Life is a game, full of surprises.
|
|
|
|
|
I HTML there is character representation in form xx. I can get hex value of the character but how to replace xx with character.
|
|
|
|
|
Hi,
I am researching the ability to build an IE toolbar that will allow IE to block a user from loading a site based on the IP address of the domain the user is browsing to.
I have found a variety of information relating to IE toolbars, but nothing really about this topic. I tried popup blockers, but this just prevented new windows.
Anybody got any tips on this or links to articles/source?
Thanks
Mark
|
|
|
|
|
Hi
You can filter web content either at your proxy/gateway (by installing some 3rd party content blocker) or try to prevent it on the client (which sounds more like what you're trying to do).
The first option is (in the standard internet kiosk scenario) the better of the 2 - relieves the client app from content filtering - ie. do you want to re-compile/-configure the clients when filter rules change or just the central server.
With the second option, I assume you're talking about general hosting of the IE control (???) With this I've found that implementing IInternetSecurityManager (and accompanying interfaces - see Security Zones in MSDN) in the host application is the most comprehensive - gives you not only facility to inspect URLs as they are visited, but control activating scripts, etc - ie. programmatic control of all the standard features available in the IE Security Options.
HTH
Martin
|
|
|
|
|
Cool, thanks for the "link".
What I'm actually trying to do is develop a IE toolbar control that will sit inside the standard IE interface [i.e like the GoogleBar], and each time IE requests a URL, it matches to domains IP address against a list of banned addresses, if it is on the list the request is denied.
Hence, I cannot use proxying, as the client must continue using its standard proxying mechanism.
I read up about TInternetSecurityManager in MSDN. It seems to be I can only implement a custom handler when I host MSHTML in an application of my own, like on say a dialog in an MFC application. For BHO's in IE itself, I can only ask the SecurityManager to authorize an action using IInternetHostSecurityManager::ProcessUrlAction.
Is one able to do filtering at a BHO level?
|
|
|
|
|
OK - I see what you're doing.
I'm not familiar with BHOs - but would guess they don't get much vote - on the basis that since the hosting environment is customizable through IInternetSecurityManager, it implies you're pretty blocked-out from anywhere else - as you've found out by being on the wrong side of the ProcessURLAction method.
Maybe setting the zone as a whole when the toolbar is active will give you what you want - the zone is customizable and can be published to the Registry I believe. Using IInternetSecurityManager::SetZoneMapping ?
Even more hacky, would be to trap DWebBrowserEvents2::BeforeNavigate2 and cancel the navigation (...I'm going to wash my mouth out immediately for saying that...).
Martin
|
|
|
|
|
Hi,
My question is really two-fold, I'm more looking for direction that actual code answers!
First, I want to use display a clock in my applicatio that uses an atomic clock to sync its time with. What is the recommended way to do this/links to useful info?
Second, I also need to display the time of other timezones, say I'm in LA, and want to diplay the time for London and NY. Does any body have links to information on how one would go about determing the time in other timezones,area. My biggest issue is with how the user can pick his location and how the software knows the timezone/etc at that location?
Many thanks in advance,
Mark
|
|
|
|
|
Hi
I'll only comment on the second part of your question. You'll have to enumerate the time zones and their offsets from a reference zone (eg. US Pacific time is -8 hours from GMT) and then apply that to what you believe the time to be in the reference zone - eg. if it's thought to be 10:23am in London (GMT being your reference zone for example), assume it to be 10:23am - 8 hours in California, and so forth.
Roughly it means that if you change the time on the London machine, the times in all the other zones change.
HTH
Martin
|
|
|
|
|
At the moment I have a Menu Resource with a "Languages" so when a user clicks it, it will change the language to whatever they select, However its all typed in the resource.
What i've been trying to do is get it to scan the /languages/ folder and add item's to the menu acordingly..
I'm not sure if this is possible with WTL or not? and if it is how would handle the clicks?
Thanks..
|
|
|
|
|
I Have two buttons on a form, when i click one i want the other one's style to change to WS_EX_STATICEDGE
I've tryed using:
CButton m_Ok;
m_Ok.Attach( GetDlgItem(IDC_TEST) );
m_Ok.ModifyStyleEx(0,WS_EX_STATICEDGE, 1);
m_Ok.Detach();
On the click of the first button, but it doesn't work.. How would you do this (if you can?)
Any Help would be greatly appreciated, Thanks.
|
|
|
|
|
|
|
Hi,
I am building a simple deskbar.
The deskbar consists of a toolbar as its main window.
On this toolbar is a edit box window, and next to that a toolbar with a single button with the combo-box drop-down style.
The toolbar window class is:
class CMyBar: public CWindowImpl<cmybar>
{
public:
DECLARE_WND_SUPERCLASS(TEXT("MYBAR"), TOOLBARCLASSNAME)
...
}
The problem is when the mose is not hovering over this toolbar button, its background is always rendering black. In practice of course I want it transparent, so one sees the toolbar below it.
I tried applying the style
DWORD dwStyle =
/*Window styles:*/ WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_VISIBLE | WS_CLIPCHILDREN | WS_TABSTOP |
/*Toolbar styles:*/ TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_LIST | //TBSTYLE_CUSTOMERASE |
/*Common Control styles:*/ CCS_TOP | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE ;
but this makes no difference what so ever.
Does anybody have any ideas how I could stop this from happening?
Thanks in advance,
Mark
|
|
|
|
|
i had added the button in outlook Express but the button turns invisible when New Button( for New Mail Message) is clicked on second menu bar in outlook.I want the button to remain visible as before.
Plz help
Thanks in advance
devom
|
|
|
|
|
I am having a database application which talks to any kind of databse. I tried to fetch the data from a table and insert into another. I am new to OLEDB. I am able to insert a interger value but not a string value. I am using CDynamicAccessor class. I read in MSDN that there shud be a special handling for string data which am nt able to do. Please help me out.
Thanks in advance
Chitra
|
|
|
|
|
Serach FOR Browser Helper Object or BHO in you LOCAL copy of MSDN.
or read more about IHTMLElement2
"I Think this Will Help"
Alok Gupta visit me at http://www.thisisalok.tk
|
|
|
|
|