|
I'm guessing this is not a UNICODE build
If this isn't an option, then you can use various methods to convert the BSTR to a regular char 'string'.
There's an atlconv.h which you can include, then have code like this;
{
USES_CONVERSION;
TCHAR* p = W2T( bBuff );
TextOut(....);
}
Alternatively if your client uses MFC you can use
CString tmp( yourBSTR );
since CString has a conversion method.
Another alternative is to use WideCharToMultiByte to do the conversion. (It's what the conversion macros in atlconv.h use, I believe...)
Steve S
|
|
|
|
|
Thanx. that was a great help to me. I am using Win32 SDK. Is development in Win32SDK has more overhead then that of MFC?
I use WIn32SDK because I am able to understand the flow, while I tried MFC at times and it seems to be overwhelming.
|
|
|
|
|
Development can take longer using raw SDK. Depends how well you 'grok' the framework. I tend to use WTL rather than MFC, unless I have a particular need for MFC specific features, such as support for OLE compound documents.
In many cases, the framework obscures your view of what's happening, until you understand it, and then it accelerates development; class = code you don't have to write.
Lots of my test apps though are pure SDK, but short.
Steve S
|
|
|
|
|
Even eaiser:
::TextOutW(...)
No need for conversion at all
Edward
|
|
|
|
|
Continuing same discussion. What I want to do is to pass a BSTR from a ATL DLL to a Client? Now since Interface method can return only HRESULT. I will store the values in a Global Variable and use it in the client. Is there in Flaw on Design? I need feedback.
By the way I didn't see anything like TextOutW in MSDN. Please help
|
|
|
|
|
My fellow poster with no name is correct that you can use TextOutW. But unfortunately, if you run your client app on Win9x or WinME, then it won't work, as that doesn't implement TextOutW, which is why I didn't suggest it (you didn't say it was NT/2K/XP/03, so I assumed it could be any.
Many API calls that take strings or characters as parameters have two versions, an ANSI version, and a UNICODE (or wide character) version. Although you use TextOut, in reality you're using either TextOutA or TextOutW, depending on whether you're compiling with _UNICODE and UNICODE defined. If you examine some of the Windows header files, you'll see definitions for both A and W functions, and then a macro which defines the base name (without A or W) as one or the other.
If you've unintentionally screwed up a parameter list to CWnd::SetWindowText, for example, the compiler will often complain about 'SetWindowTextA' or 'SetWindowTextW', rather than SetWindowText, because it's getting the definition of what the word 'SetWindowText' should be from a windows header.
Any time you see a reference to a function that ends with W or A, try looking in MSDN for the name without that trailing letter.
MEANWHILE, back to your original question;
There is a BIG flaw in your design. In the case of an in-proc ATL DLL, the global would be addressable, but that sure isn't how it's supposed to be done.
Although the method can only return an HRESULT, you can pass pointers to things in, and have the method assign values indirectly (equivalent to VB's ByRef, rather than ByVal).
An example would be:
IDL Definition:
HRESULT GetMyName( [out, retval] BSTR* pName );
HRESULT CMyObj::GetMyName( BSTR* pName)
{
if (pName == NULL)
{
return E_POINTER; // Bad address passed in...
}
*pName = SysAllocString(L"Steve Spencer");
return S_OK;
}
Client code:
BSTR t = NULL; // Empty BSTR
if (SUCCEEDED(pObj->GetMyName( &t )))
{
// woohoo! We got a result...
}
else
{
// Handle your error gracefully...
}
This works because a BSTR is a pointer; you pass in the address of the pointer, and the server (your ATL DLL) fills in the value for the pointer (hence '*pName' instead of 'pName'). You also have to mark the parameter as [out] so that the marshalling code knows how to transfer data. It's marked as [retval] so that VB programmers can use your object and treat that interface method as returning a string. (BSTR means 'BASIC String')
Hope this helps
Steve S
|
|
|
|
|
I have found the best way!!!
CComBSTR some(CString("some"));
CString some1= some;
CComBSTR and CString are exellent together!!!
================================
My Home is here!
|
|
|
|
|
I wish to work with the main window area in Internet Explorer and I want to get its coordinates. I have used the following:
long lpl = 0, lpt = 0, lpw = 0, lph = 0;
m_spWebBrowser2->get_Left(&lpl);
m_spWebBrowser2->get_Top(&lpt);
m_spWebBrowser2->get_Height(&lph);
m_spWebBrowser2->get_Width(&lpw);
then converted the client points to Windows points:
int npl = 0, npt = 0, npr = 0, npb = 0;
npt = (int) lpt; //top
npl = (int) lpl; //left
npr = (int) lpw + npl; //right
npb = (int) lph + npt; //bottom
m_spWebBrowser2->ClientToWindow(&npt, &npl); //top left
m_spWebBrowser2->ClientToWindow(&npb, &npr); // bottom right
Unfortunately this does not seem to work. First I noticed that the values returned for the top left corridnates of the window are not consistant. Everytime I open the browser they change position even though the browser opens in the same size and location. secondly, if I create a RECT out of these corridnates and pass that into a create dialog function the window created does not cover the whole area.
RECT rctB = {npl, npt, npr, npb};
m_hwndDialog = m_dlgDialog.Create(NULL, rctB, lpWindowName, 0, 0, 0, NULL);
m_dlgDialg.ShowWindow(SW_SHOW);
Thanks in advnace
|
|
|
|
|
Hi.
I have a ATL inproc server that manages CWindowImpl derived window* internally.
The client need to get the internal window pointer, but I wanna return CWnd* instead ,because the client just need the basic windows behaviors of my control.
My control derived like this.
class CChartChildWnd : public CWindowImpl<cchartchildwnd,cwindow,ccontrolwintraits>,public CObject...
CChartChildWnd* pChartWnd = NULL; This is my actual control window.
and find the required window pointer.
if(!m_mapChartWnds->Lookup(strKey, (CObject*&)pChartWnd))
return E_FAIL;
VariantInit(varWnd);
varWnd->vt = VT_R4 | VT_BYREF;
And.. finally I need to set CWnd* as a return...
varWnd->byref = ?;
Thanks for..
|
|
|
|
|
You can use CWnd::Attach(), but be sure not
to pass the CWnd between threads.
I would pass the HWND instead, shuffling around MFC
objects and they just end up biting you in the a** is my experience.
/Magnus
- I don't necessarily agree with everything I say
|
|
|
|
|
I second Magnus' response. In fact, it's probably the only way to accomplish what you are trying to do. CWindow and CWnd is pure C++ and cannot reliably be passed between COM objects unless you're using local interfaces only. And judging by the use of variants, I suspect there may be other clients in your system not written in C++.
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
I have a Browser Helper Object that contains code I want to execute after a user logs into my website and only after logging into my website. What is the best way to start the code execution?
I have thought of creating a hidden field named "start" on the web page and setting the field value to some unique string. Then searching for that field and testing the for the known value. Is there a cleaner solution.
Thank you in advance for your suggestions.
|
|
|
|
|
Well, you could just hook the browser events (onload,ondocumentcomplete,ect..) and then check the current document location before doing whatever you need to do.
|
|
|
|
|
Yes but if I did that my url would need to be hardcoded. I have a product that I will be marketing and as a result mey be host on a variety of web sites.
I guess I could create a hidden field and set the value to some string like: {2F94BC6A-9E91-4010-B991-EA0E22F9FED4}
and test for it. But I was hoping there would be a cleaner solution.
|
|
|
|
|
Hello everyone:
How to add a help file into a wtl dialog?
Thank you.
-Freehawk
|
|
|
|
|
I reinstalled Visual Studio. Now I am creating a ATL Dll using wizard. After compilation following error occurs.
<br />
fatal error C1083: Cannot open include file: 'ATLServer_i.c': No such file or directory
_i.c is not getting created. Is any settings required to do create _i.c.
|
|
|
|
|
Have you add a COM object to your server properly?
Then try "Build All"
I am seeking...
For what?
Why did you ask me for what? I don't know!
|
|
|
|
|
Hi all,
ATL question:
suppose I have two interfaces (IFirst, ISecond), and both
interfaces have a method Test(). Now I would like to implement
both IFirst and ISecond in a single object, but still have two
separate implementations of the Test() method.
Any pointers on how this can be done ?
Thanks,
Alwin
|
|
|
|
|
Use rename when importing the typelib?
Only way i can think of...
/Magnus
- I don't necessarily agree with everything I say
|
|
|
|
|
What you may have to do is what's sometimes called forwarding shims. The trick is to "prebind" the virtual methods. Observe:
class IFirstFwd : public IFirst {
public:
HRESULT Test() {
return IFirst_Test();
}
virtual HRESULT IFirst_Test() = 0;
};
class ISecondFwd : public ISecond {
public:
HRESULT Test() {
return ISecond_Test();
}
virtual HRESULT ISecond_Test() = 0;
};
class CYourComClass : public IFirstFwd, public ISecondFwd {
public:
HRESULT IFirst_Test() {
...
}
HRESULT ISecond_Test() {
...
}
}; I know it looks clumbsy, but since C++ does not have a feature for renaming inherited methods, this is the most type safe way to do it. Ok, so know that you know how it works, let's cut off those extra 8 bytes from the vtable (on wintel ia32) by adding templates:
template <typename T>
class IFirstFwd : public IFirst {
public:
HRESULT Test() {
return static_cast<T*>(this)->IFirst_Test();
}
};
template <typename T>
class ISecondFwd : public ISecond {
public:
HRESULT Test() {
return static_cast<T*>(this)->ISecond_Test();
}
};
class CYourComClass : public IFirstFwd<CYourComClass>, public ISecondFwd<CYourComClass> {
public:
HRESULT IFirst_Test() {
...
}
HRESULT ISecond_Test() {
...
}
}; There is another way - although not very pretty IMHO. It will only work well once the interfaces have finalized. I.e., this is very bad during development, because you lose all the help from the type system, and the bugs you may potentially have will be less than fun to figure out:
class ISecondFake {
virtual __stdcall HRESULT ISecond_Test() = 0;
};
class CYourComClass : public IFirst, public ISecondFake {
public:
HRESULT Test() {
...
}
HRESULT ISecond_Test() {
...
}
}; This'll work as long as your ISecondFake is vtable-compatible with ISecond. But should you change the vtable layout or method signature of ISecond in any way, don't forget to update ISecondFake or you'll be in for quite the ride..
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
Actually i am developing a class in which it will take any com object and will be able to set and get the properties. Now i have taken the clsid of the component. Now how can i get its properties as GetIdsofNames function of IDispatch takes names. Please Guide me briefly with a little example or tell me some article
Thanx in advance
Regards
minamkhan
Inam
|
|
|
|
|
|
Hello everyone
I have a wtl7.1 project and a mfc(VC6.0) dll.
Is there any way to use CString data to be transfered rightly between wtl project and mfc dll?
Thank you.
-Freehawk
|
|
|
|
|
freehawk wrote:
Is there any way to use CString data to be transfered rightly between wtl project and mfc dll?
Yes, if you pass LPCTSTR between them, then you have nothing to worry about.
I.e. in WTL project:
CString strYourString = "data";
Vc6Function(strYourString); in MFC project:
void Vc6Function(LPCTSTR lpszString) {
CString strLocalString = lpszString;
...
} This is one way to do it.
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
Hello everyone:
In a wtl project, there is a CListViewCtrl in a dialog.
After clicked one row of list, could you teach me how to get the double-click message?
Thank you
-Freehawk
|
|
|
|