tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルVB6 上で表示化け
記事No16457
投稿日: 2018/09/29(Sat) 18:05
投稿者ちぬ
お世話になっております。
久しぶりの投稿ですがよろしくお願いします。

環境
OS Windows XP
VB6 SP6

あるアプリケーションを VB6 上で実行すると、フォームのタイトル名、
メニューバーやタブ・ボタン・ラベル等、フォーム上の文字表示される
表示が化けます。(違うコントロールの Caption を表示している)
(画像を送れないのでうまく説明できませんが・・・)

各フォームのデザイン画面上では正常に表示しています。

他のアプリケーションは正常に動作します。

問題のアプリケーションは、前回修正後にバックアップを取っており、
バックアップファイルを上書き更新しても表示化けします。
(前回修正時には正常動作していました)

このPCは、VB6で作成したアプリケーション修正用で、普段は電源は切っており、
最近は1か月に1回電源を入れるかどうかくらいの頻度です。
今回もたまたま VB6 上で実行して不具合がわかった次第です。

”文字化け”で検索し他のサイトで VB6JP.dll があるかとか、アクセス権がないとかの記述があり、
確認しましたが VB6JP.dll は C:\Windows\system32 にありますし、アクセス権も問題ありませんでした。
念の為、Visual Basic 6.0 Service Pack6:ランライム再頒布可能パッケージ を
再インストールしましたが、改善されませんでした。

このアプリケーションのファイルがこわれているのか、VB6 が悪いのか、
私の力量では手に負えない状態です。

どなたか、原因・修正の方法教えていただけないでしょうか。

よろしくお願いします。

[ツリー表示へ]
タイトルRe: VB6 上で表示化け
記事No16460
投稿日: 2018/10/04(Thu) 16:17
投稿者魔界の仮面弁士
> メニューバーやタブ・ボタン・ラベル等、フォーム上の文字表示される
> 表示が化けます。

メニューバーやフォームのキャプションも正しく表示されないのですね?

これが TextBox や Label の文字化けなら、
「Label1.Font.Charset が 128 になっていない」などの理由も
思い当たりますが、メニューやキャプションは OS 側の管轄なので、
VB 側でできることは少なさそうです。

OS のフォントキャッシュが破損しているかもしれないので、
フォントキャッシュを削除してみてはいかがでしょうか。


> (違うコントロールの Caption を表示している)
どういう意味でしょうか。また、どのような破損の仕方になっているのでしょうか。
化けた状態のキャプチャを、雑談用掲示板などに貼ることはできますか?


> 念の為、Visual Basic 6.0 Service Pack6:ランライム再頒布可能パッケージ を
> 再インストールしましたが、改善されませんでした。
そのパッケージというのが
https://www.microsoft.com/ja-jp/download/details.aspx?id=24417
の事だとしたら、ここに含まれているのは、最小限のライブラリだけです。

msvbvm60.dll と、OLE 関係のアップデートファイルは含まれていますが、
VB6JP.DLL や各種 OCX は同梱されていないのでご注意を。

[ツリー表示へ]
タイトルRe^2: VB6 上で表示化け
記事No16462
投稿日: 2018/10/10(Wed) 21:26
投稿者ちぬ
魔界の仮面弁士様、ご回答ありがとうございました。
返信が遅くなり、申し訳ありません。

> OS のフォントキャッシュが破損しているかもしれないので、
> フォントキャッシュを削除してみてはいかがでしょうか。
具体的にどうすればいいのか教えていただけないでしょうか。

> > (違うコントロールの Caption を表示している)
> どういう意味でしょうか。また、どのような破損の仕方になっているのでしょうか。
> 化けた状態のキャプチャを、雑談用掲示板などに貼ることはできますか?
各コントロールに設定した文字が、実行すると違うコントロールの
キャプションを表示しています。
雑談用掲示板に設定画面と実行画面の画像を貼り付けてみます。

よろしくお願いします。

[ツリー表示へ]
タイトルRe^3: VB6 上で表示化け
記事No16463
投稿日: 2018/10/11(Thu) 11:22
投稿者魔界の仮面弁士
>> OS のフォントキャッシュが破損しているかもしれないので、
>> フォントキャッシュを削除してみてはいかがでしょうか。
> 具体的にどうすればいいのか教えていただけないでしょうか。

セーフモードで、C:\Windows\System32\FONTCACHE.DAT を削除します。
具体的な手順は『XP フォントキャッシュ 削除』などで検索してみてください。

あるいは、こんなツールもあるようで。
https://opentype.jp/delfontcachetool.htm



> 雑談用掲示板に設定画面と実行画面の画像を貼り付けてみます。
正しく表示されるパターンも見たいです。
「デザイン画面上では正常に表示」されるのですよね?

化けている文字は、全角長音記号「ー」などかと推察しますが、他にもあるようで。
(印刷物ではなく画面表示系なのに、ゴシックではなく明朝系フォントが
 使われているあたりに違和感がありますが……意図的にそういう設計なのかな)



フォントキャッシュの削除で解決しないようであれば、
各コントロールのフォント設定が何になっているのかを再確認してください。
正確なフォント名とフォントサイズが分かるなら、提示してもらえると助かります。

それと先に述べたように、フォントの Charset プロパティは 128 になっていることを確認します。
(デザイン時に確認する場合は、フォントダイアログの「文字セット」が日本語であること)
 
まとめて確認したい場合は、*.frm ファイルをメモ帳で開いて、
BeginProperty Font〜EndProperty ブロックを確認する方が早いかもしれません。


> 各コントロールに設定した文字が、実行すると違うコントロールの
> キャプションを表示しています。
別コントロールのキャプションが表示されるということは、プログラム内に
「実行時に Caption や Text を書き換える処理」があるのかもしれません。
で、その部分の処理に問題があったとか……設定元となる文字列リソースに不都合があったとか……。

[ツリー表示へ]
タイトルRe^4: VB6 上で表示化け
記事No16464
投稿日: 2018/10/11(Thu) 22:34
投稿者ちぬ
アドバイスありがとうございます。

フォントキャッシュを削除しましたが、結果は変わらずでした。

> 正確なフォント名とフォントサイズが分かるなら、提示してもらえると助かります。
フォント名は MS明朝、フォントサイズは 10 です。

> それと先に述べたように、フォントの Charset プロパティは 128 になっていることを確認します。
> (デザイン時に確認する場合は、フォントダイアログの「文字セット」が日本語であること)
>  
> まとめて確認したい場合は、*.frm ファイルをメモ帳で開いて、
> BeginProperty Font〜EndProperty ブロックを確認する方が早いかもしれません。

フォントの Charset プロパティは 128 になっています。
ただ、このソフトは英語表示もするようにしています。
起動時に日本語表示か英語表示かのフラグを読み込んで
フォントの名称やCharsetをプログラムで設定してメインフォームを表示します。
今は、日本語表示での起動になっています。

> 正しく表示されるパターンも見たいです。
> 「デザイン画面上では正常に表示」されるのですよね?
雑談用掲示板に貼り付けたように、デザイン画面上では正常に表示されています。
おかしくなる前に作成した exe ファイルを起動して正常な画面を貼り付けます。

このソフトは作成して13年経っています。
今までに、かなりの修正を積み重ねてきました。
それまでは正常にVB6上でも実行できてたのですが・・・

よろしくお願いします。

[ツリー表示へ]
タイトルRe^5: VB6 上で表示化け
記事No16465
投稿日: 2018/10/12(Fri) 01:33
投稿者魔界の仮面弁士
> > 正確なフォント名とフォントサイズが分かるなら、提示してもらえると助かります。
> フォント名は MS明朝、フォントサイズは 10 です。

それは≪正確な≫フォント名では無いように見えます。

"MS明朝" や "MS明朝" ではなく、
"MS 明朝" なのではありませんか? (英語表記では "MS Mincho")

ちなみにプロポーショナル版の方は、
"MS P明朝" が正式表記です。(英語表記では "MS PMincho")

※多言語対応アプリケーションの場合、英語表記での指定をお奨めします。


たとえば下記の場合、Label1 や Label2 のフォント名はシステムに存在しないため、
代替フォント(たとえば、"MS Pゴシック" や "Arial" など)で表示される可能性があります。

Private Sub Form_Load()
    Label1.Font.Name = "MS明朝"
    Label2.Font.Name = "MS明朝"
    Label3.Font.Name = "MS 明朝"
    Label4.Font.Name = "MS Mincho"
    
    '下記が無いと、欧文フォント(Charset = 0)になってしまう
    Label1.Font.Charset = 128
    Label2.Font.Charset = 128
    Label3.Font.Charset = 128
    Label4.Font.Charset = 128
    
    Label1.Caption = Label1.Font.Name
    Label2.Caption = Label2.Font.Name
    Label3.Caption = Label3.Font.Name
    Label4.Caption = Label4.Font.Name
End Sub




> 起動時に日本語表示か英語表示かのフラグを読み込んで
> フォントの名称やCharsetをプログラムで設定してメインフォームを表示します。

切り替えるための文字列情報は、どこから得ていますか?
外部ファイル? プログラム内に Const 等で埋め込み?

もしも、VB6 の LoadResString 関数を用いて読み込んでいるのだとしたら、
ストリングテーブルの ID がズレているのでは無いでしょうか。

古いバージョンの exe は正常表示されているとのことなので、
古い exe を、埋め込みリソースを読めるアプリ(Visual Studio 6.0 など)で
開いてみて、文字列リソースの内容を比較してみると良いかもしれません。


また、多言語対応実装ということで「ロケールID」の扱いは大丈夫でしょうか。
たとえば、StrConv の第 3 引数などで使われる ID のことです。(GetUserDefaultLCID API など)
https://msdn.microsoft.com/ja-jp/library/cc392381.aspx
http://www1.kokusaika.jp/advisory/org/ja/vb_resource.html



> 雑談用掲示板に貼り付けたように、デザイン画面上では正常に表示されています。
> おかしくなる前に作成した exe ファイルを起動して正常な画面を貼り付けます。
メニューの [ファイル(&F)] が、[終了(&F)] になっているのは『文字化け』とは違いそうですが、
その隣の [ヘルプ(&H)] が [ホル?把持長(&H)] は『文字化け』っぽいですね…。


プログラムで Caption を書き換えているようなので、
 mnuHelp.Caption = 新しい文字列
の行を、
 Dim raw() As Byte
 raw = 新しい文字列
 mnuHelp.Caption = raw
  Dim dump As String
 With CreateObject("Microsoft.XMLDOM").createElement("h")
  .DataType = "bin.hex"
  .NodeTypedValue = raw
  dump = .Text
 End With
  MsgBox dump, vbInformation Or vbSystemModal, raw
に置き換えて、そもそも想定通りの文字列を渡しているかどうかを、
文字コードのレベルから確認してみてはいかがでしょう。

[ツリー表示へ]
タイトルRe^6: VB6 上で表示化け
記事No16466
投稿日: 2018/10/13(Sat) 16:16
投稿者ちぬ
アドバイスありがとうございます。

> "MS明朝" や "MS明朝" ではなく、
> "MS 明朝" なのではありませんか? (英語表記では "MS Mincho")
フォント名を正確に入力する意識がなかったので、"MS明朝" と
記述してしまいましたが、コード上では "MS Mincho" で処理しています。

> プログラムで Caption を書き換えているようなので、
>  mnuHelp.Caption = 新しい文字列
> に置き換えて、そもそも想定通りの文字列を渡しているかどうかを、
> 文字コードのレベルから確認してみてはいかがでしょう。
このアドバイスで、mnuFile.Caption を Form.Load イベントの
コードで、どこで変わっているのかを調べてみました。

すると原因がわかりました!

日本語と英語の画面表示ができることは前述していますが、
以前に韓国語の対応と言う事で、韓国語のデータを入れていました。

各内容毎に CSV ファイルで日本語,英語,韓国語と入力していましたが
これが文字化けや改行コード化けとなり、
正常な読み込みができずに、現状の表示化けとなっていました。

元の日本語,英語のCSVファイルに戻すと正常に表示するようになりました。

三カ国語表示対応の問題は残っていますが、
(CSVファイルに日本語と韓国語を混在する事が間違っている?)
原因がわかり、正常動作するようになったのが何よりの収穫です。

ご丁寧なアドバイスありがとうございました。

[ツリー表示へ]
タイトルRe^7: VB6 上で表示化け
記事No16467
投稿日: 2018/10/13(Sat) 22:00
投稿者魔界の仮面弁士
> (CSVファイルに日本語と韓国語を混在する事が間違っている?)

シフトJIS の日本語ファイルと
Latin-1 の英語ファイルと
KS コードの韓国語ファイル
…という感じで分けているわけではなく、
UTF-16 あるいは UTF-8 名ファイルの中に
多言語文字列をセットしている、ということでしょうか。

標準ステートメントの Line Input # や Input # を使うわけにも行かないと思いますが、
そのファイルの読み取りはどのような方法で行っていますか?
TextStream? あるいは ADO の Stream?

[ツリー表示へ]
タイトルRe^8: VB6 上で表示化け
記事No16468
投稿日: 2018/10/16(Tue) 21:41
投稿者ちぬ
返信が遅くなりました。

> シフトJIS の日本語ファイルと
> Latin-1 の英語ファイルと
> KS コードの韓国語ファイル
> …という感じで分けているわけではなく、
> UTF-16 あるいは UTF-8 名ファイルの中に
> 多言語文字列をセットしている、ということでしょうか。
その通りです。
入力は Excel で入力し、CSV で出力するという流れで作成していました。
日本語と英語の時は、これで良かったのですが、
取り急ぎ韓国語も同じやり方で作成したのですが、これが間違いの元でした。
韓国語を対応するとなると、各言語ごとにファイルを分けないと
いけないかと思います。

>
> 標準ステートメントの Line Input # や Input # を使うわけにも行かないと思いますが、
> そのファイルの読み取りはどのような方法で行っていますか?
> TextStream? あるいは ADO の Stream?
Line Input # で読み込んでいます。
読み込んだ1行分の文字列を "," で区切って読み込む処理をしています。
今回は改行コードが化けて複数行のデータを1行のデータとして処理したので、
表示がおかしくなりました。

[ツリー表示へ]
タイトルRe^9: VB6 上で表示化け
記事No16469
投稿日: 2018/10/16(Tue) 23:49
投稿者魔界の仮面弁士
> 入力は Excel で入力し、CSV で出力するという流れで作成していました。
> 日本語と英語の時は、これで良かったのですが、
> 取り急ぎ韓国語も同じやり方で作成したのですが、これが間違いの元でした。

多言語ファイルを、UTF-8(UTF-16 でも可)な CSV ファイルとして
保持しているのであれば、それは特に間違っていないと思います。
しかし、Shift_JIS な CSV だとしたら NG です。

※ Excel 2016 の場合、2016 年 10 月の機能更新によって、xlCSVUTF8 すなわち
  『CSV UTF-8 (カンマ区切り) (*.csv)』形式での保存がサポートされています。


> Line Input # で読み込んでいます。
> 読み込んだ1行分の文字列を "," で区切って読み込む処理をしています。

問題はここ。多言語ファイルを Line Input # で読み取ってはいけません。

Line Input # は、既定のコードページで読み込むための物なので、
たとえば、Latin-1 な英語ファイルを日本語環境で Line Input # するのさえ NG です。

UTF-8 を対象とするなら、ADODB.Stream を使うようにしてみてください。
また、UTF-16 の場合は Scripting.TextStream を使うこともできます。


''Microsoft ActiveX Data Object を参照設定している場合
'Dim stm As ADODB.Stream
'Set stm = New ADODB.Stream
'
''追加の参照設定を含めていない場合
Dim stm As Object
Set stm = CreateObject("ADODB.Stream")


stm.Charset = "UTF-8"
stm.Open

'このファイルは UTF-8 で保存された CSV ファイルであることを前提としている。
stm.LoadFromFile "C:\path\utf8.csv"


Dim strAllText As String
'strThreeCharacter = stm.ReadText(3)  '文字数(Long値)を渡すと、指定した文字数だけ読み取り
'strSingleLine = stm.ReadText(-2)     'adReadLine(-2)を渡すと、1 行ずつ読み取り
strAllText = stm.ReadText(-1)         'adReadAll(-1)を渡すと、すべてのテキストをまとめて読み取り

stm.Close


' 先頭に Byte Order Mark があれば取り除く。
' 通常は自動判定で取り除かれるはずだが念のため。
If Left(strAllText, 1) = ChrW(&HFEFF) Then
  strAllText = Mid(strAllText, 2)
End If


'CR改行、LF改行、CRLF改行が混在していた場合に、「CRLF改行」に統一する場合はこれを実行。
strAllText = Replace(Replace(Replace(strAllText, vbCrLf, vbLf), vbCr, vbLf), vbLf, vbCrLf)
'ただしセル内改行された Excel 製 CSV などの場合は、セル内改行(LF)とレコード区切り(CRLF)が
'区別されているので、上記の置換処理を行ってはいけない。


'改行とカンマごとに Split で区切って、csv(rowIndex)(colIndex) 形式のジャグ配列に変換する処理
Dim csv As Variant

Dim rows As Object, cols As Object
Set rows = CreateObject("Scripting.Dictionary")
Set cols = CreateObject("Scripting.Dictionary")
Dim vntRow As Variant, vntCol As Variant
For Each vntRow In Split(strAllText, vbCrLf, -1, vbBinaryCompare)  'vbBinaryCompare を忘れずに
    If vntRow <> "" Then
        cols.RemoveAll
        For Each vntCol In Split(vntRow, ",", -1, vbBinaryCompare)  'vbBinaryCompare を忘れずに
            cols.Add "C" & CStr(cols.Count), vntCol
        Next
        rows.Add "R" & CStr(rows.Count), cols.Items()
    End If
Next
csv = rows.Items()
Set rows = Nothing
Set cols = Nothing


'--- 以下確認処理:配列を列挙して内容を一行ずつ表示 ---
Dim varCell As Variant, varLine As Variant
Dim strLine As String, result As VbMsgBoxResult

'  Debug.Print や MsgBox は Unicode 非対応のため、これだと確認できない
For Each varLine In csv
    '表示用に、各列を「◆」で再結合
    strLine = Join(varLine, "◆")
    result = MsgBox(strLine, vbInformation Or vbOKCancel, "MsgBox だと化ける")
    If result = vbCancel Then Exit For  'キャンセルされたら列挙終了
    
    '同じ内容を Debug.Print で出力
    For Each varCell In varLine
        Debug.Print varCell,
    Next
    Debug.Print
Next


'  WshShell.Popup メソッドは Unicode を表示できる
Dim wshShell As Object
Set wshShell = CreateObject("WScript.Shell")
For Each varLine In csv
    '表示用に、各列を「◆」で再結合
    strLine = Join(varLine, "◆")
    result = wshShell.Popup(strLine, 0, "WshShell.Popup なら化けない", vbInformation Or vbOkCancel)
    If result = vbCancel Then Exit For  'キャンセルされたら列挙終了
Next

[ツリー表示へ]
タイトルRe^10: VB6 上で表示化け
記事No16471
投稿日: 2018/10/18(Thu) 21:10
投稿者ちぬ
> > Line Input # で読み込んでいます。
> > 読み込んだ1行分の文字列を "," で区切って読み込む処理をしています。
>
> 問題はここ。多言語ファイルを Line Input # で読み取ってはいけません。
>
> Line Input # は、既定のコードページで読み込むための物なので、
> たとえば、Latin-1 な英語ファイルを日本語環境で Line Input # するのさえ NG です。
>
> UTF-8 を対象とするなら、ADODB.Stream を使うようにしてみてください。
> また、UTF-16 の場合は Scripting.TextStream を使うこともできます。
>
Line Input # はNGだったのですね。
ありがとうございます。
まだまだ勉強が足らないようです。

サンプルプログラムも記述いただき、ありがとうございました。

現在、本格的に修正に入る事ができない状況で、
韓国語対応も正式に対応するかはまだ未定です。

サンプルプログラムを元に修正を行い、
上手くいかなかった時は、こちらにお世話になると思います。

その時は、よろしくお願い致します。

[ツリー表示へ]