📄 subject_17104.htm
字号:
<p>
序号:17104 发表者:静风 发表日期:2002-10-08 14:51:15
<br>主题:谁能解释一下OLESTR类型,他究竟和普通str有什么关系,就是说他们之间如何来转化(急)
<br>内容:如题
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:徐景周 回复日期:2002-10-08 15:34:07
<br>内容:<BR>可参看下面:<BR><BR>COleVariant var; // 字段类型<BR> var.ChangeType(VT_BSTR, NULL);<BR> CString strName<BR>strName = (LPCSTR)var.pbstrVal;
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:徐景周 回复日期:2002-10-08 15:41:10
<br>内容:如下:<BR>CString to BSTR <BR>When programming with ActiveX, you will sometimes need a value represented as a type BSTR. A BSTR is a counted string, a wide-character (Unicode) string on Intel platforms and can contain embedded NUL characters. <BR>You can convert at CString to a BSTR by calling the CString method AllocSysString: <BR>CString s;<BR>s = ... ; // whatever<BR>BSTR b = s.AllocSysString()<BR> The pointer b points to a newly-allocated BSTR object which is a copy of the CString, including the terminal NUL character. This may now be passed to whatever interface you are calling that requires a BSTR. Normally, a BSTR is disposed of by the component receiving it. If you should need to dispose of a BSTR, you must use the call <BR>::SysFreeString(b);<BR>to free the string. <BR>The story is that the decision of how to represent strings sent to ActiveX controls resulted in some serious turf wars within Microsoft. The Visual Basic people won, and the string type BSTR (acronym for "Basic String") was the result. <BR>BSTR to CString <BR> Since a BSTR is a counted Unicode string, you can use standard conversions to make an 8-bit CString. Actually, this is built-in; there are special constructors for converting ANSI strings to Unicode and vice-versa. You can also get BSTRs as results in a VARIANT type, which is a type returned by various COM and Automation calls. <BR>For example, if you do, in an ANSI application, <BR>BSTR b;<BR>b = ...; // whatever<BR>CString s(b == NULL ? L"" : s)<BR>works just fine for a single-string BSTR, because there is a special constructor that takes an LPCWSTR (which is what a BSTR is) and converts it to an ANSI string. The special test is required because a BSTR could be NULL, and the constructors Don't Play Well with NULL inputs (thanks to Brian Ross for pointing this out!). This also only works for a BSTR that contains only a single string terminated with a NUL; you have to do more work to convert strings that contain multiple NUL characters. Note that embedded NUL characters generally don't work well in CStrings and generally should be avoided. <BR>Remember, according to the rules of C/C++, if you have an LPWSTR it will match a parameter type of LPCWSTR (it doesn't work the other way!). <BR>In UNICODE mode, this is just the constructor <BR><code>CString::CString(LPCTSTR);<BR>As indicated above, in ANSI mode there is a special constructor for <BR><code>CString::CString(LPCWSTR); <BR>this calls an internal function to convert the Unicode string to an ANSI string. (In Unicode mode there is a special constructor that takes an LPCSTR, a pointer to an 8-bit ANSI string, and widens it to a Unicode string!). Again, note the limitation imposed by the need to test for a BSTR value which is NULL. <BR>There is an additional problem as pointed out above: BSTRs can contain embedded NUL characters; CString constructors can only handle single NUL characters in a string. This means that CStrings will compute the wrong length for a string which contains embedded NUL bytes. You need to handle this yourself. If you look at the constructors in strcore.cpp, you will see that they all do an lstrlen or equivalent to compute the length. <BR>Note that the conversion from Unicode to ANSI uses the ::WideCharToMultiByte conversion with specific arguments that you may not like. If you want a different conversion than the default, you have to write your own. <BR>If you are compiling as UNICODE, then it is a simple assignment: <BR><code>CString convert(BSTR b)<BR> {<BR> if(b == NULL)<BR> return CString(_T(""));<BR> CString s(b); // in UNICODE mode<BR> return s;<BR> }<BR>If you are in ANSI mode, you need to convert the string in a more complex fashion. This will accomplish it. Note that this code uses the same argument values to ::WideCharToMultiByte that the implicit constructor for CString uses, so you would use this technique only if you wanted to change these parameters to do the conversion in some other fashion, for example, specifying a different default character, a different set of flags, etc. <BR><code>CString convert(BSTR b)<BR> {<BR> CString s;<BR> if(b == NULL)<BR> return s; // empty for NULL BSTR<BR>#ifdef UNICODE<BR> s = b;<BR>#else<BR> LPSTR p = s.GetBuffer(SysStringLen(b) + 1); <BR> ::WideCharToMultiByte(CP_ACP, // ANSI Code Page<BR> 0, // no flags<BR> b, // source widechar string<BR> -1, // assume NUL-terminated<BR> p, // target buffer<BR> SysStringLen(b)+1, // target buffer length<BR> NULL, // use system default char<BR> NULL); // don't care if default used<BR> s.ReleaseBuffer();<BR>#endif<BR> return s;<BR> }<BR>Note that I do not worry about what happens if the BSTR contains Unicode characters that do not map to the 8-bit character set, because I specify NULL as the last two parameters. This is the sort of thing you might want to change. <BR>VARIANT to CString <BR>Actually, I've never done this; I don't work in COM/OLE/ActiveX where this is an issue. But I saw a posting by Robert Quirk on the microsoft.public.vc.mfc newsgroup on how to do this, and it seemed silly not to include it in this essay, so here it is, with a bit more explanation and elaboration. Any errors relative to what he wrote are my fault. <BR>A VARIANT is a generic parameter/return type in COM programming. You can write methods that return a type VARIANT, and which type the function returns may (and often does) depend on the input parameters to your method (for example, in Automation, depending on which method you call, IDispatch::Invoke may return (via one of its parameters) a VARIANT which holds a BYTE, a WORD, an float, a double, a date, a BSTR, and about three dozen other types (see the specifications of the VARIANT structure in the MSDN). In the example below, it is assumed that the type is known to be a variant of type BSTR, which means that the value is found in the string referenced by bstrVal. This takes advantage of the fact that there is a constructor which, in an ANSI application, will convert a value referenced by an LPCWCHAR to a CString (see BSTR-to-CString). In Unicode mode, this turns out to be the normal CString constructor. See the caveats about the default ::WideCharToMultibyte conversion and whether or not you find these acceptable (mostly, you will). <BR>VARIANT vaData;<BR><BR>vaData = m_com.YourMethodHere();<BR>ASSERT(vaData.vt == VT_BSTR);<BR><BR>CString strData(vaData.bstrVal);<BR>Note that you could also make a more generic conversion routine that looked at the vt field. In this case, you might consider something like: <BR>CString VariantToString(VARIANT * va)<BR> {<BR> CString s;<BR> switch(va->vt)<BR> { /* vt */<BR> case VT_BSTR:<BR> return CString(vaData->bstrVal);<BR> case VT_BSTR | VT_BYREF:<BR> return CString(*vaData->pbstrVal);<BR> case VT_I4:<BR> s.Format(_T("%d"), va->lVal);<BR> return s;<BR> case VT_I4 | VT_BYREF:<BR> s.Format(_T("%d"), *va->plVal);<BR> case VT_R8:<BR> s.Format(_T("%f"), va->dblVal);<BR> return s;<BR> ... remaining cases left as an Exercise For The Reader<BR> default:<BR> ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)<BR> return CString("");<BR> } /* vt */<BR> }<BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:静风 回复日期:2002-10-08 15:57:41
<br>内容:OLESTR和COleVariant 又有什么关系?
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:Erica 回复日期:2002-11-10 04:14:23
<br>内容:OLESTR是COM中的字符串类型。在不同的平台上定义不同如WIN32上被定义成16bit的UNICODE,
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -