VCで中国語を設定するDLLを作成し、VBからそれを呼び出して変換するようなアプリを作成を下
記の順序で行っています。
①VBからUNICODEで記載された中国語をGetPrivateProfileStringで読み込む。
(読み込みは、String型です)
②読み込んだ中国語のデータでDLLをコールする。
(DLLの型は、Char*です)
VBはUNICODE対応なので、意識する必要はないと思っていたのですが、VCのDLLの型がまずいの
でしょうか?
> GetPrivateProfileString
のDeclare宣言文はどのようになっていますか?
読み込む対象のテキストファイルはUNICODEなんですよね?
(2)の意味がイマイチわかりませんね。。。
Web上の掲示板では、丸付き数字等の文字は機種依存文字なので使用は控えてください。
回答ありがとうございます。
作成するのはDLLではなく、OCXの間違いです。すみません。
>のDeclare宣言文はどのようになっていますか?
>読み込む対象のテキストファイルはUNICODEなんですよね?
Declare宣言文は下記で行っています。
Declare Function GetPrivateProfileString Lib kernel32
Alias GetPrivateProfileStringA _
(ByVal lpAppName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, _
ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As
String) As Long
又、読み込む対象のテキストファイルはUNICODEです。
>(2)の意味がイマイチわかりませんね。。。
上記は、OCXで宣言している関数の引数の型のことを意味したつもりでした。読み飛ばしてくだ
さい。
又、OCX内では、UNICODEデータ(中国語)は表示できていました。
(テスト用の関数を作成し、その中でUNICODEデータの取得及び表示を行っています)
(OCX側)
ソースファイル
DISP_FUNCTION_ID(OCXCLASS, SetData, DISPID_ABOUTBOX + 5, SetData,
VT_BOOL,VTS_BSTR)
BOOL OCXCLASS::SetData(LPCTSTR Moji1)
{
ここに中国語フォントにSetFontしてメッセージを出力!
return TRUE;
}
ヘッダファイル
afx_msg BOOL SetData(LPCTSTR Moji1);
プライマリ ディスパッチ インターフェイスです。
[id(DISPID_ABOUTBOX + 5)] BOOL SetData(LPCTSTR Moji1);
(VB側)
Dim buff As String * 256
ret = GetPrivateProfileString(sec, key, ", buff, 256, chi.ini)
OCX.SetData(buff)
> Declare Function GetPrivateProfileString Lib kernel32
> Alias GetPrivateProfileStringA _
この宣言の仕方だと GetPrivateProfileStringA から分かると思いますが、
Unicode用のINIファイル読込用ではありません。
GetPrivateProfileStringW としないといけません。
(Wはワイド文字列という意味です。UNICODEは2バイトで1文字(ワイド文字)ですから。)
>(Wはワイド文字列という意味です。UNICODEは2バイトで1文字(ワイド文字)ですから。)
そういう意味だったのですね。基本的なことがわかっていませんでした。
しかし、GetPrivateProfileStringA を GetPrivateProfileStringW にかえてみたのです
が、今度は取得に失敗してしまいました。
2バイト文字を処理する為には、Stringでも問題ないと思っていたのですが、宣言も他に変更
の必要があるのでしょうか?
Declare Function GetPrivateProfileString Lib kernel32
Alias GetPrivateProfileStringW _
(ByVal lpAppName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, _
ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As
String) As Long
よろしくお願いします。
> Stringでも問題ない
Stringでの指定は全てダメっぽいです。
DLLに渡すときに勝手に文字コードを変換してしまうので
(UNICODE文字列を勝手にASCII文字列にしてしまう)
ByVal s As String
を全て
ByRef s As Long
としないといけないでしょう。
それでGetPrivateProfileStringを使うときは Long型の配列の先頭要素を渡す感じにな
るかと。
> ByRef s As Long
じゃなくて、
ByVal s As Long
かも。
> それでGetPrivateProfileStringを使うときは Long型の配列の先頭要素を渡す感じに
なるかと。
StrPtrでいいかも。
参考にしたサイトのGoogleキャッシュ(海外の掲示板ですが)
http://64.233.167.104/search?
q=cache:TDMqpW3LMQ4J:www.codehound.com/groups/thread.asp%3Ft%
3D6,286,1,1_3c74bb2c%240%241600%241dc6e903%
40news.corecomm.net_286+GetPrivateProfileStringW+VB&hl=ja
てもとに、VBがないのでExcelVBAで確認したところ
> 参考にしたサイトのGoogleキャッシュ(海外の掲示板ですが)
のまんまコードを書けばうまくいきました。
StrPtrをつかうので、全て変数に一時格納してあげないといけないそう。
>のまんまコードを書けばうまくいきました。
>StrPtrをつかうので、全て変数に一時格納してあげないといけないそう。
恐らく下記のコードと思うのですが、うまくコードを返してもらえません。(cChars=0)
Declare Function GetPrivateProfileString Lib kernel32 Alias
GetPrivateProfileStringW _
(ByVal lpApplicationName As Long, _
ByVal lpKeyName As Long, _
ByVal lpDefault As Long, _
ByVal lpReturnedString As Long, _
ByVal nSize As Long, _
ByVal lpFileName As Long) As Long
Dim sBuffer As String
Dim cChars As Long
sBuffer = String$(MAX_BUFFER, vbNullChar)
cChars = GetPrivateProfileString(StrPtr(SectionName), StrPtr(KeyName),
StrPtr(DefaultValue), StrPtr(Buffer), Len(Buffer), StrPtr(FileName))
GetPrivateProfileStringの呼び出しのところで、
StrPtr(Buffer), Len(Buffer)→StrPtr(sBuffer), Len(sBuffer)の間違いだと
思うのですが、他に宣言で間違いがあるのでしょうか?
Dim SectionName as String
Dim KeyNameas String
Dim FileNameas String
SectionName = Section
KeyNameas = Key
FileNameas = aaa.ini
下記のようにLenの長さを固定にすることでcCharsには正しい文字数を取得することができまし
た。
しかしBufferには何も設定されてないように思えるのですが、アドレスが取得できているとい
うことなのでしょうか?
もしそうだとしたら、C側(OCX)の引数へはどのように引き継げばよいのでしょうか?
現在はパラメータはTCHAR*にしています。
cChars = GetPrivateProfileString(StrPtr(SectionName), StrPtr(KeyName),
StrPtr(DefaultValue), StrPtr(Buffer), Len(Buffer), StrPtr(FileName))
↓
cChars = GetPrivateProfileString(StrPtr(SectionName), StrPtr(KeyName),
StrPtr(DefaultValue), StrPtr(Buffer), 256, StrPtr(FileName))
いろいろ(StrConvやLong配列等)やってみましたが、
> のまんまコードを書けばうまくいきました。
は勘違いだったようです。どうもうまくいきませんね。
原因がよく分からないので、自宅に帰って
VB6とVCでDLL作って文字列がちゃんときているかをデバッグで確認してみます。
Private Declare Function GetPrivateProfileString _
Lib kernel32 Alias GetPrivateProfileStringW _
(ByVal lpApplicationName As Long,
ByVal lpKeyName As Long,
ByVal lpDefault As Long, _
ByVal lpReturnedString As Long,
ByVal nSize As Long,
ByVal lpFileName As Long) As Long
で、
Dim strSection As String
Dim strKey As String
Dim strDefault As String
Dim strReturn As String
Dim strFile As String
Dim lngRet As Long
strSection = Section
strKey = Key
strDefault = Default
strFile = E:\VBProject\Ini\aaa.ini
strReturn = String$(256, vbNullChar)
lngRet = GetPrivateProfileString(StrPtr(strSection), _
StrPtr(strKey), _
StrPtr(strDefault), _
StrPtr(strReturn), _
256, _
StrPtr(strFile))
で取れたんだけど、なんか指定してある文字列によって取れないケースがある。
(VCでやってみたけどとれないでした。おって追跡中)
どうも、
> GetPrivateProfileStringW としないといけません。
> (Wはワイド文字列という意味です。UNICODEは2バイトで1文字(ワイド文字)ですか
ら。)
の認識が間違っていました。
テキストファイルはAでもWでもSfit_JISでした。
取得した文字列がワイド文字列かマルチバイト文字列かの扱いで、
エンコード形式は直接関係なかったです。
# VCでWritePrivateProfileStringWでファイルを新規に作ってみたら
# Shift_JISエンコードでした。
結局、UnicodeのテキストをGetPrivateProfileString APIで読むことは不可能っぽい。
Blueさんいろいろ参考になりました。
ありがとうございました。
で、結局どうしたの?