MFC7 COleVariant and CString classes
-
Good people, Does anybody know why the following code, compiled under .NET 2003, prints junk instead of the expected “Hello, World!”?. Thanks, Serge #include "stdafx.h" int main() { COleVariant v; v.SetString("Hello, World!", VT_BSTRT); CString s; // why 's = v.pcVal' works, but 's = v' does not? s = v; std::cout << s << std::endl; return 0; }
-
Good people, Does anybody know why the following code, compiled under .NET 2003, prints junk instead of the expected “Hello, World!”?. Thanks, Serge #include "stdafx.h" int main() { COleVariant v; v.SetString("Hello, World!", VT_BSTRT); CString s; // why 's = v.pcVal' works, but 's = v' does not? s = v; std::cout << s << std::endl; return 0; }
Only use VT_BSTRT if you are using an ANSI string in a UNICODE build, else use VT_BSTR.
v.SetString("Hello, World!", VT_BSTR);
When you output a CString via std::cout you have to cast your CString variable to an LPCTSTR
std::cout << (LPCTSTR)s << std::endl;
At least that is what I have to do in .NET 2002.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
Honoured as one of The Most Helpful Members of 2004
-
Only use VT_BSTRT if you are using an ANSI string in a UNICODE build, else use VT_BSTR.
v.SetString("Hello, World!", VT_BSTR);
When you output a CString via std::cout you have to cast your CString variable to an LPCTSTR
std::cout << (LPCTSTR)s << std::endl;
At least that is what I have to do in .NET 2002.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
Honoured as one of The Most Helpful Members of 2004
PJ, thanks, it works, but it does not make any sense… 1) check out what MSDN says on this: A DAO recordset in a non-UNICODE build expects strings to be ANSI. Thus, for DAO functions that use COleVariant objects, if you are not creating a UNICODE recordset, you must use the COleVariant::COleVariant( lpszSrc, vtSrc ) form of constructor with vtSrc set to VT_BSTRT (ANSI) or use SetString with vtSrc set to VT_BSTRT to make ANSI strings. For example, the CDaoRecordset functions CDaoRecordset::Seek and CDaoRecordset::SetFieldValue use COleVariant objects as parameters. These objects must be ANSI if the DAO recordset is not UNICODE. 2) It breaks backward compatibility with MFC6, namely this one will print just one letter “H”: #include "stdafx.h" int main() { COleVariant v; v.SetString("Hello, World!", VT_BSTR); CString s; // why 's = v.pcVal' works, but 's = v' does not? s = v.pcVal; std::cout << (LPCSTR)s << std::endl; return 0; } so the backward compatible version of a non-Unicode build should be like this: #include "stdafx.h" int main() { COleVariant v; v.SetString("Hello, World!", #if _MFC_VER >= 0x0700 // represents MFC version 7 and later VT_BSTR); #else VT_BSTRT); #endif CString s; // why 's = v.pcVal' works, but 's = v' does not? #if _MFC_VER >= 0x0700 // represents MFC version 7 and later s = v; #else s = v.pcVal; #endif std::cout << (LPCSTR)s << std::endl; return 0; } but does it make any sense? Thanks, Serge
-
PJ, thanks, it works, but it does not make any sense… 1) check out what MSDN says on this: A DAO recordset in a non-UNICODE build expects strings to be ANSI. Thus, for DAO functions that use COleVariant objects, if you are not creating a UNICODE recordset, you must use the COleVariant::COleVariant( lpszSrc, vtSrc ) form of constructor with vtSrc set to VT_BSTRT (ANSI) or use SetString with vtSrc set to VT_BSTRT to make ANSI strings. For example, the CDaoRecordset functions CDaoRecordset::Seek and CDaoRecordset::SetFieldValue use COleVariant objects as parameters. These objects must be ANSI if the DAO recordset is not UNICODE. 2) It breaks backward compatibility with MFC6, namely this one will print just one letter “H”: #include "stdafx.h" int main() { COleVariant v; v.SetString("Hello, World!", VT_BSTR); CString s; // why 's = v.pcVal' works, but 's = v' does not? s = v.pcVal; std::cout << (LPCSTR)s << std::endl; return 0; } so the backward compatible version of a non-Unicode build should be like this: #include "stdafx.h" int main() { COleVariant v; v.SetString("Hello, World!", #if _MFC_VER >= 0x0700 // represents MFC version 7 and later VT_BSTR); #else VT_BSTRT); #endif CString s; // why 's = v.pcVal' works, but 's = v' does not? #if _MFC_VER >= 0x0700 // represents MFC version 7 and later s = v; #else s = v.pcVal; #endif std::cout << (LPCSTR)s << std::endl; return 0; } but does it make any sense? Thanks, Serge
There are two things to remember, one: MSDN is not always correct, two: not everything is backwards compatible. Serge Krynine wrote: #if _MFC_VER >= 0x0700 // represents MFC version 7 and later VT_BSTR); #else VT_BSTRT); #endif There are obviously differences between COleVariant v6 and v7 as they act differently. Just right click on VT_BSTRT in both VC6 and VC7 and you will be brought to different definitions. Serge Krynine wrote: CString s; // why 's = v.pcVal' works, but 's = v' does not? #if _MFC_VER >= 0x0700 // represents MFC version 7 and later s = v; #else s = v.pcVal; #endif CString in VC6 does not have an
operator = const VARIANT&
and VC7 does. Try different settings, and use the debugger's variable watch window to see what is happening.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
Honoured as one of The Most Helpful Members of 2004