tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルファイルパスの機種依存文字を取得する方法について
記事No16027
投稿日: 2014/11/28(Fri) 11:50
投稿者マサタロウ
VBは数年前から勉強しています。
ExcelのVBAの資格(APIなし最初の)を取得しています。

VB5.0で、コモンダイアログで選択したファイルのパスに含まれる
機種依存文字を取得する方法を考えています。


以下のページで機種依存文字を表示させる方法を確認しました。
  http://okwave.jp/qa/q4522107.html#

ページ内の「文字コード」について検索してみると、
"数値文字参照"の文字であるということがわかりました。
  http://www.pentan.info/doc/sjis_list.html
  http://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E5%8F%82%E7%85%A7

"数値文字参照"の文字について検索中に、文字列を数値実体参照の
形に変換してくれるページを見つけました。
  http://yasu.asuka.net/orkut/conv.html

上記検索で見つけた方法を利用してコモンダイアログで選択した
ファイルのパスに含まれる機種依存文字を取得する方法を
考えましたが、取得したい機種依存文字を入力して文字コードを
調べ、VB5.0で確認してみると、"?"が表示されコモンダイアログの
Filenameプロパティのパスと同じになります。
VB5.0での確認方法は、http://okwave.jp/qa/q4522107.html#
改造して確認しました。

VB5.0のテキストボックスに取得したい機種依存文字を入力して
Enterを押すと"?"に変わります。

使用中のPCは、NEC VALUESTAR です。

VB5.0で、コモンダイアログで選択したファイルのパスに含まれる
機種依存文字を取得できるか確認したいです。


コモンダイアログで選択したファイルのパスに含まれる
機種依存文字を取得する方法は、自作のビューアー、
プログラムランチャー、ファイルのパスの文字数を確認する、
というファイルのパスを必要とするプログラムを作成中に、
不具合がないか確認している時に出てきた事です。

[ツリー表示へ]
タイトルRe: ファイルパスの機種依存文字を取得する方法について
記事No16028
投稿日: 2014/11/28(Fri) 12:27
投稿者魔界の仮面弁士
> ExcelのVBAの資格(APIなし最初の)を取得しています。
> VB5.0で、コモンダイアログで選択したファイルのパスに含まれる

開発言語は、下記の(1)ということで宜しいでしょうか。

 (1) Visual Basic 5.0
 (2) Visual Basic 6.0
 (3) VBA5.0
 (4) VBA6.0
 (5) VBA6.1
 (6) VBA7.0
 (7) VBA7.1
 (8) 上記以外


> 機種依存文字を取得する方法を考えています。
ここでいう「機種依存文字」とは、何を意味していますか?
ウムラウト記号やハングルを含んだファイル名などは許容されますか?


たとえば、「SPY++.EXE」というファイル名の場合、
現行の Windows 上では扱えますが、VB1 などからは扱えません。
また、同ファイルを Web 上に公開する場合、システムによっては
+ が空白文字と誤解されるケースがあります。

また、ファイル名として
 (a) ABC.txt
 (b) abc.txt
 (c) ABC.txt
 (d) abc.txt
とあった場合、これらは
 NT 系(Windows 2000 や Windows 8 など)…… aとb、cとdを同一視する(aとcは区別される)
 9x 系(Windows 95 や Windows ME など)…… aとbを同一視するが、cとdは区別される
 NTFS …… Unicode で管理される。a、b、c、d はそれぞれ別のファイル名となる
 FAT32…… 既定のコードページにて大文字で管理される。CP932では aとbが同一視され、cとdは別物。
となるはずです。


システムによって扱える文字は異なってきますので、実際のところ
そう単純にはいかなかったりします。そのため、API などにおいても
それらを判断するための関数は用意されておらず、実際のファイル操作時に
「処理が失敗したかどうか」で判定させることが多いようです。

[ツリー表示へ]
タイトルRe^2: ファイルパスの機種依存文字を取得する方法について
記事No16029
投稿日: 2014/11/28(Fri) 14:54
投稿者マサタロウ
どうも。マサタロウです。
魔界の仮面弁士さんには、他ページで回答頂いた記憶があります
(Programming Library - 2007/03/08)。
ありがとうございます。


> 開発言語は、下記の(1)ということで宜しいでしょうか。
開発言語は、Visual Basic Learning Edition Version 5.0です。


> ここでいう「機種依存文字」とは、何を意味していますか?
自分が意図的に入力したフォルダ名やファイル名です。
  例:D:\アプリケーション\「機種依存文字」\「機種依存文字」.exe 等

"D:\アプリケーション\"までは正しく読み、それ以降が"?"に
なってエラーになると思われます。
自分が取得したい機種依存文字のことだったでょうか?


> ウムラウト記号やハングルを含んだファイル名などは許容されますか?
> + が空白文字と誤解されるケースがあります。

コモンダイアログで"+"を含んだフォルダ名の内部に移動できます。


> システムによって扱える文字は異なってきますので、実際のところ
> そう単純にはいかなかったりします。そのため、API などにおいても
> それらを判断するための関数は用意されておらず、実際のファイル操作時に
> 「処理が失敗したかどうか」で判定させることが多いようです。
判定させる事のみが目的なら、検索で調べた方法を使用しなくても良いと
思います。
Windowsフォトギャラリー(使用OSがVista)では、パスに機種依存文字が
含まれる画像ファイルを表示できます。どの様にパスを取得しているか
不明です。

[ツリー表示へ]
タイトルRe^3: ファイルパスの機種依存文字を取得する方法について
記事No16031
投稿日: 2014/11/28(Fri) 16:31
投稿者魔界の仮面弁士
> 自分が取得したい機種依存文字のことだったでょうか?

VB5 では String 型の内部データは Unicode ベースで管理されていますが、
その読み書き(テキストボックス、Open ステートメント、MsgBox 関数などなど)は、
すべて「既定のコードページ」で行われます。日本語版なら Shift_JIS 相当ですね。
(なお、日本語版以外の環境では、Shift_JIS とは異なるコードページが使われます)

そのため VB5 では、『Shift_JIS で扱えない文字は、すべて化ける』ことになります。
たとえば、
 Call MsgBox( ChrW(&H4F60) & ChrW(&H597D) )
というコードは、
 VB5 や VBA では「?好」
 VB.NET や VBScript では、(漢字2文字の)ニイハオ
と表示されます。


また、『Shift_JIS では区別されるが、Unicode では同じ文字として扱われる文字は区別できない』仕様です。
たとえば、Shift_JIS では平方根記号が Chr(&H8795) と Chr(&H81E3) の二箇所にマップされていますが、
VB5 は Unicode で管理される都合上、いずれも ChrW(&H221A) となってしまい、両者を区別できません。

ReDim sjis1(1) As Byte
ReDim sjis2(1) As Byte
sjis1(1) = &H95: sjis1(0) = &H87
sjis2(1) = &HE3: sjis2(0) = &H81

Dim s1 As String, s2 As String
s1 = StrConv(sjis1, vbUnicode, &H411)
s2 = StrConv(sjis2, vbUnicode, &H411)
Debug.Print s1 = s2
's1 と s2 は同じ文字になってしまう


> パスに機種依存文字が含まれる画像ファイルを表示できます。
ファイル名も同様です。

VB5 の標準機能、たとえば Open ステートメントでは、
ファイル名に Shift_JIS 相当の文字しか使えませんが、
ADO などでは、Unicode のファイル名も扱えます。


Const adSaveCreateOverWrite = 2
Dim filePath1 As String, filePath2 As String
Dim stm As Object
'漢字2文字「ニイハオ」を含むファイル名。ニイの文字は非日本語な漢字。
filePath1 = Environ("TEMP") & "\NIHAO1(" & ChrW(&H4F60) & ChrW(&H597D) & ").TXT"
filePath2 = Environ("TEMP") & "\NIHAO2(" & ChrW(&H4F60) & ChrW(&H597D) & ").TXT"

'ADODB.Stream は、Unicode パスをサポートしている
Set stm = CreateObject("ADODB.Stream")
stm.Open
stm.WriteText "Ni-Hao"
stm.SaveToFile filePath1, adSaveCreateOverWrite
stm.Close

'Open ステートメントは、Unicode パスをサポートしていない
Dim fno As Integer
fno = FreeFile()
Open filePath2 For Output As #fno   '★エラーになる
Print #fno, "Ni-Hao";
Close #fno


> Windowsフォトギャラリー(使用OSがVista)では、パスに機種依存文字が
> 含まれる画像ファイルを表示できます。どの様にパスを取得しているか
> 不明です。
Unicode ベースのアプリケーションかどうかが鍵となります。

たとえば、そのアプリが Wide バージョンの CreateFile API を呼び出しているのなら、
「ニイハオ」というファイル名も開けますが、ANSI バージョンの CreateFile API なら、
「ニイハオ」というファイル名は開けず、「?好」などと化けて処理されてしまうでしょう。


VB5 であれば、comdlg32.ocx のコモンダイアログを使うのではなく、
comdlg32.dll の GetOpenFileNameW でファイル名を指定させるようにすれば、
上記「ニイハオ」なパスなども受け取れるようにはなります。

ただし、そのファイル名を MsgBox や Debug.Print で表示させたり、
Open ステートメント等で読み書きするといったことはできませんので、
それぞれ、Unicode 対応バージョンの仕組みに置き換える手間は発生します。

Unicode 文字列の読み書きが発生するのであれば、VB.NET に乗り換えた方が良いですよ。

[ツリー表示へ]
タイトルRe^4: ファイルパスの機種依存文字を取得する方法について
記事No16032
投稿日: 2014/11/28(Fri) 18:06
投稿者マサタロウ
マサタロウです。

> また、『Shift_JIS では区別されるが、Unicode では同じ文字として扱われる文字は区別できない』仕様です。
> たとえば、Shift_JIS では平方根記号が Chr(&H8795) と Chr(&H81E3) の二箇所にマップされていますが、
> VB5 は Unicode で管理される都合上、いずれも ChrW(&H221A) となってしまい、両者を区別できません。
>
> ReDim sjis1(1) As Byte
> ReDim sjis2(1) As Byte
> sjis1(1) = &H95: sjis1(0) = &H87
> sjis2(1) = &H81: sjis2(0) = &HE3
>
> Dim s1 As String, s2 As String
> s1 = StrConv(sjis1, vbUnicode)
> s2 = StrConv(sjis1, vbUnicode)
> 's1 と s2 は同じ文字になってしまう
配列変数を再宣言して配列変数に文字コードを格納。
文字列型変数に、変数sjis1の内容を変換した文字列を格納。
sjis1はどこで宣言しているのか?
s1とs2は同じコードなので同じ結果になることが分かる。


サンプルコードを実行したところ、ADODB.Streamでテキストファイルが
作成できました。
非日本語な漢字のニイを含むファイル名です。
デスクトップにパスを変更しても作成できました。

ADODB.Stream で検索したところ、以下のページを見つけました。
  http://www.k-sugi.sakura.ne.jp/windows/vb/3650/

上記ページのコードでパスとファイル名を変更して実行してみると、
自作拡張子のファイル内の内容がイミディエイトウィンドウで確認
できました。
パスとファイル名がきちんとしていませんでしたが、
上記ページの方法でうまくいくか試してみます。


> Const adSaveCreateOverWrite = 2
> Dim filePath1 As String, filePath2 As String
> Dim stm As Object
> '漢字2文字「ニイハオ」を含むファイル名。ニイの文字は非日本語な漢字。
> filePath1 = Environ("TEMP") & "\NIHAO1(" & ChrW(&H4F60) & ChrW(&H597D) & ").TXT"
> filePath2 = Environ("TEMP") & "\NIHAO2(" & ChrW(&H4F60) & ChrW(&H597D) & ").TXT"
>
> 'ADODB.Stream は、Unicode パスをサポートしている
> Set stm = CreateObject("ADODB.Stream")
> stm.Open
> stm.WriteText "Ni-Hao"
> stm.SaveToFile filePath1, adSaveCreateOverWrite
> stm.Close

[ツリー表示へ]
タイトルRe^5: ファイルパスの機種依存文字を取得する方法について
記事No16033
投稿日: 2014/11/28(Fri) 19:14
投稿者魔界の仮面弁士
> 配列変数を再宣言して配列変数に文字コードを格納。
ここでいう「文字コード」とは、具体的には何を指定していますか?
先の回答の平方根記号の例などもありますので、どのように得た値なのかも重要です。


> sjis1はどこで宣言しているのか?

ここです。
> > ReDim sjis1(1) As Byte
> > sjis1(1) = &H95: sjis1(0) = &H87

宣言としては「Dim sjis() As Byte」相当ですが、このコードでは
配列確保のための ReDim ステートメントのみで済ませています。



> s1とs2は同じコードなので同じ結果になることが分かる。
提示のコードでは、バイナリデータを StrConv で文字列化する際の
vbUnicode 変換について示したものですが、VB の文字列処理では、
こうした vbUnicode / vbFromUnicode 変換が各所で行われていたりします。
ファイル操作然り、Left/Mid/Right 等の文字列操作然り。


たとえば、『√記号』という 3 文字が書かれた、
Shift_JIS のファイルを、メモ帳等で作っておくとします。

それをバイナリエディタを使って開いた場合、恐らくは
81,E3,8B,4C,8D,86 と表示されることでしょう。(※1)

そのファイルをもう一つ用意し、一方のファイルの先頭 2 バイトを
バイナリエディタで書き換え、95,87,8B,4C,8D,86 という内容に変更して、
そのまま上書き保存します。(※2)

先ほどとは異なるバイナリで保存されていますが、Shift_JIS (コードページ932)の
テキストファイルとしてみた場合、いずれも『√記号』という 3 文字を意味します。

さて、この 2 つのファイルの内容を、VB5 で String 変数に読み込んだ場合、
Shift_JIS から Unicode (UTF-16リトルエンディアン)への変換が発生し、
いずれの内容も 1A,22,18,8A,F7,53 なバイナリの文字列となります。(※3)


扱うバイナリが異なるだけで、※1〜3 はいずれも『√記号』という文字列を
表していることには変わりません。ただし、※3 から ※2 の文字への復元が
行えなくなったという意味では、これも一種の「文字化け」です。


そのため、この 81,E3 な文字も、「機種依存文字」の一種とみなされます。
(この手の機種依存文字は、『NECのIBM拡張文字』などと呼ばれることがあります)


> サンプルコードを実行したところ、ADODB.Streamでテキストファイルが
> 作成できました。
同様に、FileSystemObject なども、Unicode ファイル名に対応しています。


ファイルパスについては、こうした Shift_JIS / Unicode の問題だけでなく、
名前付きストリームパスへの対応状況の差異もあります。


(0) あらかじめ、C:\TEMP\ というフォルダーを用意しておく。

(1) メモ帳で「あいうえお」と記述し、[ファイル]-[名前を付けて保存]を開き、
  文字コード ANSI とした上で、ファイル名の欄に「"C:\TEMP\TEST.TXT"」と
  ダブルクォーテーションも含めてフルパスで指定し、保存して閉じる。

(2) [Win]+[R] キーで『ファイル名を指定して実行』画面を表示し、そこに
  「NOTEPAD "C:\TEMP\TEST.TXT:Stream1"」と記述して OK を押す。
  メモ帳が起動し、ファイルの新規作成の確認が行われるので[はい]と答え、
  「かきくけこ」の 5 文字を入力して [ファイル]-[上書き保存] して閉じる。

(3) 再度、[Win]+[R] キーで『ファイル名を指定して実行』画面を表示し、
  「NOTEPAD "C:\TEMP\TEST.TXT:Stream1"」と記述して OK を押す。
  メモ帳にて「かきくけこ」が表示されるかを確認する。


上記の状況において、VB5 から「かきくけこ」と書かれたファイル内容を読み取る場合、
VB 標準の Open ステートメントでは対応できません。たとえば、
 Open "C:\TEMP\TEST.TXT:Stream1" For Input As #1
などと記述してみても、実行時エラーになってしまうことでしょう。



蛇足ですが、この名前付きストリーム(代替データストリーム)は、
ブラウザ等からダウンロードしたファイルに対して、
 「このファイルは、インターネット上の場所から取得されており、安全でない可能性があります。」
などと表示させるためにも使われています。
たとえば、「NOTEPAD "C:\TEMP\sample.gif:Zone.Identifier"」などのように、
ファイル名の末尾に、"Zone.Identifier" というストリーム名をコロンで繋いで
『ファイル名を指定して実行』から開くと、その内容を読み取ることが出来ます。
(コマンドプロンプトなら、DIR コマンドの /R オプションでストリームを列挙できます)



> ADODB.Stream で検索したところ、以下のページを見つけました。
>   http://www.k-sugi.sakura.ne.jp/windows/vb/3650/
確かに、文字コードに関して記載されていますが、そこに書かれている内容は、
『テキストファイルの内容』を読み取る際に、どの文字コードでデコードするかを
紹介したものです。ニイハオ.TXT な例で挙げた『ファイルのパス』が化ける話とは無関係です。

[ツリー表示へ]
タイトルRe: ファイルパスの機種依存文字を取得する方法について
記事No16035
投稿日: 2014/11/29(Sat) 15:56
投稿者魔界の仮面弁士
> 機種依存文字を取得する方法を考えています。

文字列が、Shift_JIS として文字化けするかどうかを判定するための関数を作ってみました。

半角カナとか、NECのIBM拡張文字とか、x-mac-japanese などが原因で生じる
機種依存文字をチェックするものでは無いという点にはご注意下さい。



下記の関数は、文字列の内容すべてが、Shift_JIS として扱える文字列ならば True を返します。
Shift_JIS 範囲外の Unicode 文字を含んでいた場合は False を返します。
(たとえば、No16033 の例に挙げた「ニイハオ」を渡すと False が返されます。


Option Explicit

'指定した文字列が、CP932(Shift_JIS)で表現可能かどうかを判断する。
' 戻り値が False の場合、Shift_JIS で表せない文字が混入している。
Public Function CanConvertSJIS(ByVal Text As String) As Boolean
    With CreateObject("ADODB.Stream")
        .Open
        .Charset = "Shift_JIS"
        .WriteText Text
        .Position = 0
        CanConvertSJIS = (.ReadText() = Text)
        .Close
    End With
End Function

[ツリー表示へ]
タイトルRe^2: ファイルパスの機種依存文字を取得する方法について
記事No16038
投稿日: 2014/12/01(Mon) 15:49
投稿者マサタロウ
> > 配列変数を再宣言して配列変数に文字コードを格納。
> ここでいう「文字コード」とは、具体的には何を指定していますか?
> 先の回答の平方根記号の例などもありますので、どのように得た値なのかも重要です。
No.16031でいう「文字コード」とは、
sjis1(1) = &H95: sjis1(0) = &H87
この部分です。
> たとえば、Shift_JIS では平方根記号が Chr(&H8795) と Chr(&H81E3) の二箇所にマップされていますが、
となっていたため、sjis1に格納されて&H8795となると思いました。
sjis1に格納するコードがないですが、sjis1の値は何になるのでしょうか?
s1とs2で同じ変数を使用しているため、sjis2に値が格納されても結果は
同じになると考えました。
上のReDimと下のDimをまとめて実行した場合の結果ですよね?


> ニイハオ.TXT な例で挙げた『ファイルのパス』が化ける話とは無関係です。
ファイル名が機種依存文字の場合にファイル内の内容を読み込むために必要と
思いました。読み込んだファイルの内容を変数に格納する方法を探します。


> (たとえば、No16033 の例に挙げた「ニイハオ」を渡すと False が返されます。
No.16031ではないですか?


> 文字列が、Shift_JIS として文字化けするかどうかを判定するための関数を作ってみました。
判定するプログラムは『ファイルのパス』が化ける事の回避で
使用しますか?
コモンダイアログでファイルパスに機種依存文字が含まれる場合に
"?"が表示されます。"?"はファイル名やフォルダ名で使用できない
ため、パスに"?"が含まれる場合は機種依存文字と判定できるのでは?
(For〜Next、Mid等で)

comdlg32.dll の GetOpenFileNameW(関数?)のみで文字化けは回避できますか?
GetOpenFileNameWについて調べてみます。

[ツリー表示へ]
タイトルRe^3: ファイルパスの機種依存文字を取得する方法について
記事No16039
投稿日: 2014/12/01(Mon) 17:24
投稿者魔界の仮面弁士
> s1とs2で同じ変数を使用しているため、
ごめんなさい!!
No.16031 のコードが大幅に間違っていました。あれじゃ意味が分からないですよね…。
No.16031 を修正しましたので、再度御確認願います。


同種の問題を抱えた文字の一覧として、下記の資料も参考にしてみてください。
http://support.microsoft.com/kb/170559/ja



> > たとえば、Shift_JIS では平方根記号が Chr(&H8795) と Chr(&H81E3) の二箇所にマップされていますが、
> となっていたため、sjis1に格納されて&H8795となると思いました。

以下、修正した No.16031 をお読みいただいた上での話になりますが:
sjis1 も sjis2 も、バイト型の一次元配列(2 Byte分)です。
その中身は「平方根記号を Shift_JIS にてエンコードした値」です。

一方、s1 と s2 は、可変長文字列型です。バイト型の一次元配列でも代用可能ですけれども。
その中身は「平方根記号を UTF-16(リトルエンディアン) にてエンコードした値」です。



↓↓ 以下蛇足 ↓↓


ご存知かと思いますが、Shift_JIS バイナリから Unicode(UTF-16)バイナリへの変換には、
「StrConv 関数と vbUnicode 定数」が使われます。逆変換なら vbFromUnicode 定数ですね。

 Label1.Caption = StrConv(sjisBinary, vbUnicode, &H411)

上記は、第一引数を Shift_JIS(CP932) 相当のバイナリとみなした上で、
それを Unicode バイナリへと変換せよ、という意味になります。

第 3 引数に指定した &H411 (1041) は、日本語版 Windows のロケールIDです。
http://msdn.microsoft.com/ja-jp/library/cc392381.aspx

日本語環境で動かす前提であれば、第3引数は省略可能です。
(第3引数を省略するかゼロを指定した場合、現在のカルチャが利用されます)

 Label1.Caption = StrConv(sjisBinary, vbUnicode)


ちなみに、UTF-16 バイナリを String 型にする場合には、このように書きます。
 Debug.Print StrConv(binUnicode, 0, &H411)
 Debug.Print StrConv(binUnicode, 0)
 Debug.Print CStr(binUnicode)
 Debug.Print binUnicode


↑↑ 蛇足ここまで ↑↑



> > ニイハオ.TXT な例で挙げた『ファイルのパス』が化ける話とは無関係です。
> ファイル名が機種依存文字の場合にファイル内の内容を読み込むために必要と
> 思いました。読み込んだファイルの内容を変数に格納する方法を探します。
先述した『ADODB.Stream』を試してみてください。
これの LoadFromFile メソッドが Unicode パスに対応しています。
(LoadFromFile は、ファイルの内容をストリームにロードするためのメソッドです)
http://msdn.microsoft.com/ja-jp/library/cc364272.aspx


『ADODB.Stream』は、Type プロパティで「バイナリデータ」モードと
「テキストデータモード」を切り替えられます。

テキストモードの場合:
 WriteText メソッドで、ストリームに文字列を書き込む。
 ReadText メソッドで、ストリームから文字列を読み込む。
 Charset プロパティで、読み書きに使う文字コードを指定。
 LineSeparator プロパティで、読み書きに使う改行文字を指定。

バイナリモードの場合:
 Write メソッドで、ストリームにバイト配列を書き込む。
 ReadText メソッドで、ストリームからバイト配列を読み込む。



> > (たとえば、No16033 の例に挙げた「ニイハオ」を渡すと False が返されます。
> No.16031ではないですか?
16031 ですね。済みません。


> コモンダイアログでファイルパスに機種依存文字が含まれる場合に
> "?"が表示されます。"?"はファイル名やフォルダ名で使用できない
化けてしまった後の文字列で判定しても意味がありません。
化ける前の文字列で判定できるよう、処理を見直してみてください。


> 判定するプログラムは『ファイルのパス』が化ける事の回避で
> 使用しますか?
たとえば、
 「ファイル名をデータベース等から入手しており、
  それを用いて、Open ステートメントで保存したいが、
  Unicode 文字が含まれていると保存に失敗してしまうので
  事前検証のために使いたい」
といった使い方が出来ます。


この判定関数をどのように使うかは自由ですが、下記の点に注意してみて下さい。

(1) VB6 のすべての標準コントールおよび一部のActiveXコントロールは、
 Unicode 文字列の読み書きに対応しておらず、「ニイハオ」などの文字を扱えません。
 ※ TextBox、InputBox、MSComDlg 等々がこれにあたります。

(2) Unicode 対応の AcitveX コントロールとしては、
 MSDataGrid や WebBrowser などが挙げられます。
 http://yaplog.jp/orator/archive/15
 http://yaplog.jp/orator/archive/80

(3) クリップボードは Unicode 文字列の入出力に対応していますが、
 VB6 の Clipboard オブジェクトは、Unicode テキストに非対応です。もしも
 Unicode のまま読み書きしたい場合は、Get/SetClipboardData API などで対応します。
 http://yaplog.jp/orator/archive/17
 http://yaplog.jp/orator/archive/16


> ため、パスに"?"が含まれる場合は機種依存文字と判定できるのでは?
> (For〜Next、Mid等で)
"?" を検出したいだけなら、ループせずとも、
  If strData LIKE "*[?]*" Then
    MsgBox "? が含まれています"
  End If
とか
  If InStr(1, strData, "?", vbBinaryCompare) > 0 Then
    MsgBox "? が含まれています"
  End If
などと書けますよ。



> comdlg32.dll の GetOpenFileNameW(関数?)のみで文字化けは回避できますか?
はい、「ニイハオ」を含んだパスなどを、文字化けすることなく取得することが可能です。
そのパスを、(VB 標準のステートメントではなく) ADODB.Stream で読み書きすればよいでしょう。

なお、受け取ったパスを MsgBox とか ウォッチウィンドウ とか 各種コントロールなどに
受け渡した場合、Shift_JIS に無い文字は表示が化けてしまうことになります。


> GetOpenFileNameWについて調べてみます。
『Unicode対応版「ファイルを開く」ダイアログ』というコードを
サンプル投稿掲示板に投稿しておきました。参考になれば。
http://www.hanatyan.sakura.ne.jp/patio/patio.cgi

[ツリー表示へ]
タイトルRe^4: ファイルパスの機種依存文字を取得する方法について
記事No16040
投稿日: 2014/12/02(Tue) 17:13
投稿者マサタロウ
どうも。

> 第 3 引数に指定した &H411 (1041) は、日本語版 Windows のロケールIDです。
Visual Basic Learning Edition Version 5.0 では第 3 引数は無いようです。

http://www.k-sugi.sakura.ne.jp/windows/vb/3650/
上記ページの"Charset"プロパティを"Shift_JIS"に変更したら
機種依存文字が含まれてない場合は正しく読み込みました。


> 2) Unicode 対応の AcitveX コントロールとしては、
変数のように使用するためのもの?
これがあれば、コントロールのプロパティを取得して
『ADODB.Stream』で読み書き可能?
コモンダイアログのFilenameプロパティを格納しても文字化けしない?

プログラムランチャーや、ファイルのパスの文字数を確認するプログラムで
ラベルにパスを表示させています。
パスの取得だけでなく表示方法も考える必要がありました。
検索で魔界の仮面弁士さんが回答されてる記事を参考にしましたが、
難しそうです。
VB2005がありますが、VB5.0でやりたいです。


http://yaplog.jp/orator/archive/15
http://yaplog.jp/orator/archive/80
上記ページよりダウンロードしたデータは、VB5.0ではエラーで
開けませんでした。


> 『Unicode対応版「ファイルを開く」ダイアログ』というコードを
『ADODB.Stream』で画像ファイルは読み込めますか?

[ツリー表示へ]
タイトルRe^5: ファイルパスの機種依存文字を取得する方法について
記事No16041
投稿日: 2014/12/02(Tue) 19:29
投稿者魔界の仮面弁士
> > 第 3 引数に指定した &H411 (1041) は、日本語版 Windows のロケールIDです。
> Visual Basic Learning Edition Version 5.0 では第 3 引数は無いようです。

そういえば VB5 でしたね。第三引数は VB6 からの機能です、済みません。


> http://www.k-sugi.sakura.ne.jp/windows/vb/3650/
> 上記ページの"Charset"プロパティを"Shift_JIS"に変更したら
> 機種依存文字が含まれてない場合は正しく読み込みました。

(α) ファイル名やフォルダ名に、Shift_JIS に無い文字が使われているか否か。

(β) テキストファイルの中身が、Shift_JIS なのか UTF-8 なのか UTF-16 なのか。

いったんココで、上記の 2 つの違いを明確にしておきましょう。



「"Charset"プロパティを"Shift_JIS"に変更」という話は、(β) のことを示しています。

しかし元々、今回の質問は題名にもあるように
  『ファイルパスの機種依存文字を取得する方法について』
を話題にしていたはずです。先に解決すべき問題は (α) の方ですよね。

そしてこの問題については、
 ・ファイル名の指定には、 comdlg32.ocx ではなく、GetOpenFileNameW API を使う。
 ・ファイルの読み書きには、ADODB.Stream オブジェクトを使う。
という回避策を提示しており、実際のソースコードも提示しています。


また、ここでいう「ファイルパスの機種依存文字」とは、(α) における
「Shift_JIS で表現できない文字」を示していると思ってください。

具体例を挙げれば、「立方メートル記号」や「'ニイハオ'の1文字目」を含むパスのことです。

インターネットで『機種依存文字』について調べてみると、先の「平方根記号」問題ですとか、
「半角カナ」、「丸囲み漢字」、「〜」の文字などを機種依存文字に含めることが多いのですが、
今回話題にしている (α) においては、これら半角カナや丸囲み漢字などは問題視されませんので
調査する際には、それらを混同しないようご注意ください。



> > 2) Unicode 対応の AcitveX コントロールとしては、

この場合、(β)の方の問題も関わってきます。
コモンダイアログコントロールなら、(α) と (β)の両方が影響しますね。


VB5 は、言語仕様的には Unicode 対応となっていますが、開発環境はそうではありません。
表示・入力する際には、常に Shift_JIS 相当の文字列しか扱えないのでご注意下さい。

Unicode 対応 API を呼び出したり、Unicode 対応 ActiveX コントロールを
利用するのであれば、Shift_JIS に無い文字を VB5 で扱うことが出来ますが、
VB5 の開発環境は、ソースコード中に Unicode 文字を直接記載することはできませんし、
標準で付属するコントロールの中にも、Unicode 対応のものはありません。
付属コントロールの少ない Learning Edition であるなら尚のこと。ここが今回の難点といえます。

(VB.NET であれば、開発環境も含め、Unicode にきちんと対応しているのですけれどね)


そして、VB5 などで Unicode 対応コントロールが必要な場合には、
 ・Microsoft Office 付属の FM20.DLL のコントロール群(Microsoft は非推奨としている)
 ・サードパーティ製の Unicode 対応コントロールを購入
などという対処方法を採ることになります。

ただ、VB5 向けのコントロールが、今でも入手可能かどうかは分かりません。
VB6 用は見つかりましたが…流石に開発ツールとしては古すぎますね。
http://www.cyberactivex.com/UnicodeTutorialVb.htm


> 変数のように使用するためのもの?

そのあたりは、ちょっと認識が違うかも知れません。

32bit 版の Visual Basic の文字列型は、常に Unicode で管理される仕様なので、
特に難しいことをせずとも、As String な変数さえ用意しておけば、その中に
任意の文字を格納させることができます。この段階で文字化け等が発生することはありません。

たとえば、ニイハオの最初の『イ尓』っぽい字とか、立方メートル記号の『m3』っぽい字でも
問題なく保持できますし、それを Left 関数や Mid 関数などで切り出すこともできます。


問題となるのは、「その文字列をどのように表示するのか、入力させるのか」です。
言語仕様としては取り扱えても、表示や入力などは別の問題であり、たとえば

・MsgBox 関数では表示できないので、MessageBoxW API で表示する。
・ファイル名の指定時なら、コモンダイアログコントロールでは扱えないので、
 コモンダイアログ API を使う。
・ファイルのパスであるのなら、Open ステートメントでは開けないので、
 Stream オブジェクトを使う。

などといった、それぞれ個別の対処が必要になるということです。


> これがあれば、コントロールのプロパティを取得して
先述したように、VB5 のコントロールは Unicode 文字を扱えません。
別途、Unicode 対応コントロールを用意する必要があります。


> 『ADODB.Stream』で読み書き可能?
はい。Stream オブジェクトの LoadFromFile メソッドやSaveToFile メソッドは、
Unicode 文字を含んだパスであっても、問題なく取り扱えます。

また、Stream オブジェクトには、バイナリであれテキストであれ、
任意のデータを書き込んだり、あるいは取り出したり出来ます。
今回は使いませんが、文字コードの自動判定機能などもあります。


> コモンダイアログのFilenameプロパティを格納しても文字化けしない?
先述したように、標準のコモンダイアログコントロールは、Unicode 文字を
扱えないため、コモンダイアログ API に置き換える必要があります。
具体的なサンプルコードは、既にお見せしましたよね。


> プログラムランチャーや、ファイルのパスの文字数を確認するプログラムで
> ラベルにパスを表示させています。
Label は使えません。
Label は標準コントロール(≠ActiveX コントロール)であり、Unicode 非対応です。
TextOutW API を用いて「描画」することで回避してみて下さい。


> VB2005がありますが、VB5.0でやりたいです。
VB5 って、17年前の代物ですよ? (VB2005 でも古すぎるぐらい…)

標準でサポートしていないことを、API などを使って回避していくわけですから、
実現するためには、上級者レベルの知識と経験が必要になることは覚悟しておいてください。



> http://yaplog.jp/orator/archive/15
> http://yaplog.jp/orator/archive/80
> 上記ページよりダウンロードしたデータは、VB5.0ではエラーで
> 開けませんでした。

MSDATGRD.OCX は、VB5 Learning Edition には付属していません。

WebBrowser コントロールなら使えますが、VB5 は IE3 時代の言語なので、
扱えるのはせいぜい IE4.01 まででしょうね。(IE5 以降の動作が保証されていない)


> 『ADODB.Stream』で画像ファイルは読み込めますか?
Stream で対応できるのは、画像のバイナリデータを読み取るところまでですね。
バイナリフォーマットを解析できるなら、PSet ステートメント併用で
無理やり表示することもできますが、現実的では無いでしょうね。

ファイルパスに、Unicode 文字を含む画像ファイルを表示するのであれば、
案としてはこんなところかな。

 (案1) FileSystemObject などを用いて、Unicode 名な画像ファイルを、
  別のファイル名(C:\TEMP\123.BMP など)にコピーし、その後で
  改めて LoadPicture 関数で表示する。

 (案2) 画像のバイナリから、Picture オブジェクトを生成する。
  http://yaplog.jp/orator/archive/19

 (案3) GDI+ Flat APIを使って描画する。
 http://msdn.microsoft.com/en-us/library/windows/desktop/ms533969.aspx

[ツリー表示へ]
タイトルRe^6: ファイルパスの機種依存文字を取得する方法について
記事No16042
投稿日: 2014/12/03(Wed) 11:33
投稿者マサタロウ
マサタロウです。

・質問した『ファイルパスの機種依存文字を取得する方法について』は、
  (α) の方法で行います。
 GetOpenFileNameW API で呼び出したダイアログボックスで選択した
 ファイルのパス(プロパティ)を、『ADODB.Stream』のLoadFromFile
 プロパティに格納して自分で設定した拡張子のファイルを読み込む。
 ファイル内には実行(プログラムランチャー)するプログラムの
 パスが記録されている。

・(β)の内容は、『ADODB.Stream』でファイルの内容を読み込んだ場合に
 内容を変数に格納するためにファイル内の内容がメモ帳などで開いた
 内容と同じにならないといけないと思いました。
 『ADODB.Stream』で読み込んだ内容を変数に格納する方法の処理の1つ
 で必要と思います。『 内容を変数に格納する方法が1つわかりました 』
 と記述する必要があったと思います。

・Unicode 対応の AcitveX コントロール は、下記にも記述しましたが、
 表示可能の場合は使用しません。


> > これがあれば、コントロールのプロパティを取得して
> 先述したように、VB5 のコントロールは Unicode 文字を扱えません。
> 別途、Unicode 対応コントロールを用意する必要があります。
用意したUnicode 対応コントロールのプロパティを取得(TextやCaption)して
『ADODB.Stream』で読み書き可能かという意味でした。
Unicode 対応コントロールのプロパティにパスの文字列を格納してある
場合です。またUnicode 対応コントロールを用意してあるだけでも
ありません。
用意するUnicode 対応コントロールは、たとえば
http://yaplog.jp/orator/archive/80のコントロールとか。


> > コモンダイアログのFilenameプロパティを格納しても文字化けしない?
> 先述したように、標準のコモンダイアログコントロールは、Unicode 文字を
> 扱えないため、コモンダイアログ API に置き換える必要があります。
コモンダイアログでファイルを選択(パスを取得)した時点で文字化けますか?
表示の仕様のみで、管理では取得されているということはないですか?
『ADODB.Stream』のLoadFromFileで読み込むパスをCommonDialog1.filenameに
変更するとエラーになるので文字化ける・・?


> > プログラムランチャーや、ファイルのパスの文字数を確認するプログラムで
> > ラベルにパスを表示させています。
> Label は使えません。
> Label は標準コントロール(≠ActiveX コントロール)であり、Unicode 非対応です。
> TextOutW API を用いて「描画」することで回避してみて下さい。
機種依存文字を含むパスの表示は、この方法で表示してみます。
この方法でうまくいけばUnicode 対応コントロールは使用しません。


>  (案1) FileSystemObject などを用いて、Unicode 名な画像ファイルを、
>   別のファイル名(C:\TEMP\123.BMP など)にコピーし、その後で
>   改めて LoadPicture 関数で表示する。
機種依存文字を含むパスのある画像ファイルの表示は、この方法で表示してみます。
オブジェクトの生成は、勉強が必要です。
GDI+ Flat APIのページは英文でC言語で書かれてますよね?
"AV"というVBのAPIの宣言をコピーできるフリーソフトにもないので
自分では理解できないと思います。


> > VB2005がありますが、VB5.0でやりたいです。
> VB5 って、17年前の代物ですよ? (VB2005 でも古すぎるぐらい…)
>
> 標準でサポートしていないことを、API などを使って回避していくわけですから、
> 実現するためには、上級者レベルの知識と経験が必要になることは覚悟しておいてください。
VBのバージョンが最新になると質問した
ファイルパスの機種依存文字を取得する方法について
などの内容も対応されている・・?
VBのバージョンが最新になると標準でサポートされている内容が増える・・・?

[ツリー表示へ]
タイトルRe^7: ファイルパスの機種依存文字を取得する方法について
記事No16043
投稿日: 2014/12/03(Wed) 12:50
投稿者魔界の仮面弁士
> またUnicode 対応コントロールを用意してあるだけでもありません。

Label の代用とする、TextOutW API のサンプルを書いてみました。

下記では説明のため、フォーム上から直接 API を呼んでいますが、
描画処理を UserControl 化しておくと、通常の Label の代用として使えるかと。

Option Explicit

Private Declare Function TextOutW Lib "GDI32" (ByVal hDC As OLE_HANDLE, ByVal nXStart As Long, ByVal nYStart As Long, ByVal lpString As Long, ByVal cbString As Long) As Long

'第1引数:Form/PictureBox/Printerのいずれかの hDC プロパティ
'第2引数:描画させたい文字列
'第3、第4引数:描画先の座標
Private Sub DrawText(ByVal h As OLE_HANDLE, ByVal Text As String, ByVal x As Integer, ByVal y As Integer)
    '2014/12/09 削除
    'Dim s As String
    's = Text & vbNullChar
    'TextOutW h, x, y, StrPtr(s), Len(s)

    '2014/12/09 差し替え
    TextOutW h, x, y, StrPtr(Text), Len(Text)
End Sub

Private Sub Form_Load()
    Picture1.AutoRedraw = True
    Picture1.ScaleMode = vbPixels
    Picture1.BorderStyle = 0
End Sub

Private Sub Command1_Click()
    'Picture1.Cls
    DrawText Picture1.hDC, "[" & ChrW(&H33A5) & "]立方メートル", 30, 30
    Picture1.Refresh

    'PictureBox や Form を渡す場合は、描画完了後に
    'Refresh メソッドを呼び出すことで、
    'API からの描画結果を反映させる
End Sub

Private Sub Command2_Click()
    Printer.Print " ";
    DrawText Printer.hDC, "[" & ChrW(&H33A5) & "]立方メートル", 30, 30
    Printer.EndDoc
    
    '印刷情報が何も無いときには、Printer.EndDoc を呼び出しても
    '何も出力されない。そのため、Printer に対して API で描画する場合は、
    'あらかじめ、空白文字を Print しておくと良い。
End Sub


> コモンダイアログでファイルを選択(パスを取得)した時点で文字化けますか?
試してみていただければ分かるかと思いますが、ダイアログの表示が
化けるわけではありません。化けるのは、String 型プロパティの内容です。

具体的には、FileName プロパティ、InitDir プロパティ、DialogTitle プロパティなどです。

そのため、今回問題としているようなファイルパスを扱おうとすると、
選択されたファイル名を正しく受け取れず、"?" などに化けてしまいます。
取得だけではなく、初期表示のパスを指定する場合も同様です。


> 表示の仕様のみで、管理では取得されているということはないですか?

コントロールが内部で呼び出している API が違うので、どうしようもありません。

コモンダイアログ コントロールが内部で呼び出しているのは
GetOpenFileNameA API であり、文字列は ANSI 文字列(Shift_JIS 相当)となります。
GetOpenFileNameW API であれば、Wide 文字列(Unicode)になるのですけれどね。


> GDI+ Flat APIのページは英文でC言語で書かれてますよね?
C++ 言語ではないでしょうか? C 言語ではなく。


> "AV"というVBのAPIの宣言をコピーできるフリーソフトにもないので
> 自分では理解できないと思います。
GDI+ Flat API を使ったサンプルは、過去に何度か投稿していますが、
そのものズバリなコードを毎回作っているわけでは無いので、
API 仕様を見て、自分で記述できるだけの力量が求められますね…。



> ファイルパスの機種依存文字を取得する方法について
> などの内容も対応されている・・?

はい。.NET 世代の VB は、Unicode パスを問題なく扱うことが出来ます。

そうでないバージョン(VB5、VB6、VBA6.x、VBA7.x など)においては、
今回述べてきたように、Unicode パスを扱う機能を備えていません。


そもそも Windows 3.1 の頃は、Unicode を扱えませんでした。
これは VB2 や VB4/16 などの時代ですね。

Windows 95 の登場時に、少数の Unicode API、いわゆる「〜W 系」の API が
サポートされましたが、大部分は「〜A 系」な ANSI バージョンのままでした。
これは VB4/32 や VB5 の時代ですね。


ただしこれらの時代であっても、Windows NT 系列の OS であれば、Unicode API が
採用されていました。ただし互換性のため、同じ機能を持つ ANSI バージョンの API も
同時に用意されていました。


このことから、
・「〜A 系」API なら、WinNT 系でも Win9x系 でも 動作する。
・「〜W 系」API だと、WinNT 系では動くが、Win9x 系で動作しない。
という状況が生まれます。

このような事情から、VB4〜VB6 においては、言語仕様的には Unicode 対応ですが、
OS 機能の呼び出しには、基本的に ANSI バージョンの API を使う仕組みになっています。

中には、OS の種別に応じて、〜A と 〜W を切り替えるような実装としたコントロールも
あるのですが、少なくとも VB5 Learning 付属のコントロールはそうなっていないということです。


> VBのバージョンが最新になると標準でサポートされている内容が増える・・・?
バージョンアップすれば、新しい機能が追加されていくのは確かにその通りですが、
逆に、不要とされた機能が廃止される可能性もありますよ。

たとえば、VB5 の OLEオブジェクトコントロールは、VB.NET には用意されていません。
(旧VB と VB.NET の違いについては過去に何度か話題になっていますので、過去ログを参照してみて下さい)


それはさておき:

必ずしも、常に「最新」バージョンを追い続ける必要は無いと思いますが、
だからといって、あまりにも古いバージョンに固執することはお奨めしません。

サポートの切れた古いツールを使い続けることには限界があるので、
VB201x 世代の新しいバージョンへの移行を検討しておくのが賢明かと思います。

なお、VB.NET 2002/2003 世代も避けておきましょう。今となっては旧世代の言語仕様です。
少なくとも VB2005 以降(できれば 2008 以降)がお奨めです。最新は 2013 ですね。

[ツリー表示へ]
タイトルRe^8: ファイルパスの機種依存文字を取得する方法について
記事No16044
投稿日: 2014/12/09(Tue) 14:33
投稿者マサタロウ
> 描画処理を UserControl 化しておくと、通常の Label の代用として使えるかと。
Visual Basic Learning Edition Version 5.0ではActiveX コントロールを作成できません。
PictureBoxとサンプルコードで表示します。


> Label の代用とする、TextOutW API のサンプルを書いてみました。
サンプルを参考にして、機種依存文字を表示させることができました。

DrawText内の"s = Text & vbNullChar"はC言語風文字列で宜しいですか(下記ページ参考にしました)?
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_p07.htm
"s = Text & vbNullChar"で実行すると、機種依存文字の後に
半角中点が表示されます。"s = Text"で表示できました。

TextOutWは宣言で全てLong型となっているため、数値で判断して
描画を行う事がわかります。
DrawTextを呼び出すときに引数を設定すると、引数の値は数値になりますか?
変数の格納されている場所(アドレス)内の値(文字列)は、対応する数値になりますか
(StrPtr(s)のs、イミディエイトウィンドウでは数値でした、数値は格納場所の意味?)?
関数(DrawText)を使用してTextOutWを実行するのは、数値を取得するためですか?

DrawText(Call DrawText)後のPictureBoxのRefreshは、
実行しなくても表示できました。

PictureBoxのプロパティは、デザイン時に設定します。

Printerについては使用しないため確認してません。


サンプルのUnicode対応コモンダイアログについて、
そのまま使用するとうまくいかないので、以下のコードに変更して、
表示、初期ディレクトリの設定、選択可能ファイルの種類設定、
コモンダイアログボックスのタイトル設定、ファイル選択、
は正しくできました。
ReplaceはVB5.0にはありませんでした。

Private Sub Command8_Click()

Dim s As String

    s = DlgShowOpen("C:\Program Files\", "実行ファイル(*.exe,*.lnk)|*.exe", "ファイル")

'▼以下でもできました。
'Dim FP As String
    
    'FP = "実行ファイル(*.exe,*.lnk)" & vbNullChar & "*.exe"
    's = DlgShowOpen("C:\Program Files\", FP, "ファイル")

End Sub

Public Function DlgShowOpen(ByVal initialDirectory As String, ByVal filterPattern As String, Optional ByVal dialogTitle As String = vbNullString) As String

Const OFN_FILEMUSTEXIST As Long = &H1000
Const OFN_HIDEREADONLY As Long = &H4
Const OFN_EX_NOPLACESBAR As Long = &H1

Dim ofnFlags As Long
    ofnFlags = OFN_FILEMUSTEXIST Or OFN_HIDEREADONLY
    
Dim strFile As String
    strFile = String(512, 0)

Dim strFileFilter As String
    Mid(filterPattern, 20, 1) = vbNullChar '変数"FP"を使用しない場合。
    strFileFilter = filterPattern

Dim udtOFN As OPENFILENAME

    With udtOFN

        .lStructSize = Len(udtOFN)

        .hwndOwner = Form1.hWnd

        .hInstance = App.hInstance
        
        .lpstrFilter = StrPtr(filterPattern)
        .nFilterIndex = 1
        
        .lpstrFile = strFile
        
        .nMaxFile = Len(strFile)
        
        .lpstrInitialDir = StrPtr(initialDirectory)
        
        .lpstrTitle = StrPtr(dialogTitle)
        
        .Flags = ofnFlags
        .FlagsEx = 0&

        .nFileOffset = 0
        .nFileExtension = 0
        .nMaxCustFilter = 0&
        .lpstrFileTitle = 0&
        .nMaxFileTitle = 0&
        .lpstrCustomFilter = 0&
        .nMaxCustFilter = 0&
        .lpstrDefExt = 0&
        .lCustData = 0&
        .lpfnHook = 0&
        .lpTemplateName = 0&
        .pvReserved = 0&
        .dwReserved = 0&

    End With

Ret = GetOpenFileNameW(udtOFN)

TextOutW関数で、.lpstrFileのプロパティが数値で表示されるため、
型をString型に変更して上記のコードで実行すると、パス名を表示できました。
引数TextにStrConvでUnicodeから変換して格納しました。
しかし、正しく表示できるパスと化けるパスがある様です
(半角カタカナが化ける)。
また、TextOutW関数で表示すると、パス以外の文字が表示されます
(半角中点)。バッファのサイズ分表示され、パス以外の余分な文字も
表示されるのでしょうか?
バッファのサイズを再設定するとうまく表示できません
(Ret = GetOpenFileNameW(udtOFN)の後でstrFile = String(256, 0)など)。
For〜Next、Mid、Leftでパスのみ取得できるか試しています。
Shell関数でStrConvでUnicodeから変換した.lpstrFileプロパティの
.exeや.lnkファイルを実行する事は出来ました。


バージョンについて、
VB2005はフリーのVisual Basic 2005 Express Edition をダウンロードして
所持しているという意味でした。外観やプログラム方法が似ているため、
VB2005で慣れてからでないと最新版をインストールしないと思います。
VB5.0を希望しているのは、作成している自作プログラムがVB5.0の勉強のために
作成したもので、言語を換えたくない気持ちがあるためです。

[ツリー表示へ]
タイトルRe^9: ファイルパスの機種依存文字を取得する方法について
記事No16047
投稿日: 2014/12/09(Tue) 20:43
投稿者魔界の仮面弁士
> > 描画処理を UserControl 化しておくと、通常の Label の代用として使えるかと。
> Visual Basic Learning Edition Version 5.0ではActiveX コントロールを作成できません。
ActiveX コントロールにする必要は無く、UserControl で十分なのですが、
UserControl の作成も駄目なんでしたっけ? (済みません、把握できていません)


> DrawText内の"s = Text & vbNullChar"はC言語風文字列で宜しいですか(下記ページ参考にしました)?

ひとまず、その認識で OK です。(風、が付いているのがナイス!)

正確には LPCTSTR 型(LPCWSTR 型)相当のデータが渡されますが、
ここでは、NULL 終端文字は必須ではありません。

終端文字は念のためにつけただけですが、それがかえって問題になっていますね。
改めて No16043 のコードを見直してみたのですが、提示コードの
 TextOutW h, x, y, StrPtr(s), Len(s)
というのは誤りでした。NULL 終端を含まない長さを指定するべきなので、この場合は、
 TextOutW h, x, y, StrPtr(s), Len(Text)
もしくは
 TextOutW h, x, y, StrPtr(Text), Len(Text)
が適切です。コードの修正をお願いします。 ( No16043 のコードは修正済みです)



> TextOutWは宣言で全てLong型となっているため、数値で判断して
> 描画を行う事がわかります。
TextOutW API の引数は、以下の意味です。
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145133.aspx


第一引数(HWND) 描画対象となるデバイスコンテキストのハンドルを指定します。
  通常は、描画先コントロールの hDC プロパティを指定することになります。
  (hDC プロパティは、Form、PictureBox、Printer に備わっています)

第二引数(int) X 座標を指定します。ピクセル単位系です。

第三引数(int) Y 座標を指定します。ピクセル単位系です。

第四引数(LPCSTR) Unicode 文字列の先頭アドレスを指定します。
 VB5 から渡す場合は、
  (案1) ByRef As Byte で宣言して、「Byte 型一次元配列」の 0 番目の要素を渡す。
  (案2) ByVal As Long で宣言して、「StrPtr( 文字列型変数 )」を渡す。
 などとします。今回は 案2 ですね。詳しい話は後述。

第五引数(UINT) 第四引数の文字数を指定します。(バイト数ではなく文字数です)



> 関数(DrawText)を使用してTextOutWを実行するのは、数値を取得するためですか?
そもそも、今回のサンプルにある DrawText は『関数』ではありません。
自作 Sub プロシージャーの名前です。

API には DrawText という同名関数もありますが、サンプル中のそれとは
無関係です。紛らわしい名前をつけてしまって済みません。

ちなみに、API としての DrawText 関数は、TextOut 関数の上位バージョン的な位置づけです。
TextOut が、描画先の左上座標を指定して文字列を描画していたのに対し、
DrawText は四角形の領域を指定しての描画となります。下揃え・右寄せ・中央揃えなどの位置調整や
長い文字列を折り返したり、あるいは末尾を切り抜くなどの高度な指定が行えます。



> (StrPtr(s)のs、イミディエイトウィンドウでは数値でした、数値は格納場所の意味?)?
StrPtr は、文字列の先頭アドレスを返すための隠し関数です。

ANSI API の場合は、String 型変数をそのまま渡せるのですが、VB5 でこれを
やってしまうと、Shift_JIS ←→ Unicode の変換が行われてしまいます。

たとえば "弁士" という文字列を、ANSI 系 API に ByVal As String で渡すと、
(Unicode バイナリの) 5F01, 58EB ではなく、
(Shift_JIS 相当の) 95D9, 8E6D が渡される仕様です。

一方、同じ文字列を、Wide 系 API に、StrPtr などで渡す場合は、
(Unicode バイナリの) 5F01, 58EB をそのまま渡すことが出来ます。



文字列型のメモリ配置を図で示すとこんな感じ。画像はネットからの拾い物です。
http://blog-imgs-70.fc2.com/n/a/o/naotamin/VBAString1.png

 黄色:「文字列型変数」を管理する 4 バイトの領域。
  この領域の先頭アドレスは、VarPtr(s) で得られます。
  この場所には、青部の左端のアドレスが記録されています。
  ※ vbNullString の場合は、青部のアドレスのかわりに &H0& が記録されています。

 青色:「文字列の本体」が管理されています。
  この領域の先頭アドレスは、StrPtr(s) で得られます。黄色領域はここを参照しています。

 黄緑:「文字列の長さ」を管理する 4 バイトの領域。内容は LenB(s) と同じものです。

 灰色:NULL 終端文字列。4 バイトの 0 vbNullChar に相当します。

--------

たとえば s = "弁士" なら、
 黄色部のアドレス
 = VarPtr(s) が指し示す数値

 黄色部の値
 = 文字列本体の格納場所を示す
 = すなわち、青色部の先頭アドレス
 = StrPtr(s) が指し示す数値

 青色部の値
 = 文字列本体の内容を示す
 = "弁士" という 2 文字
 = ChrW(&H5F01) & ChrW(&H58EB)
 = ChrB(&H01) & ChrB(&H5F) & ChrB(&HEB) & ChrB(&H58)
 = 青色部の値は [01][5F][EB][58] の 4 バイト

 黄緑部のアドレス
 = 青色部の直前に配置される(4 バイト)

 灰色部のアドレス
 = 青色部の直後に配置される(4 バイト)

 黄緑部の値
 = 青色部のデータ長を示す
 = LenB(s) が指し示す値

 灰色部の値
 = [00][00] 固定

というわけです。


> DrawText(Call DrawText)後のPictureBoxのRefreshは、
> 実行しなくても表示できました。
AutoRedraw = False の場合は、Refresh 無しでも描画されます。
その代わり、再描画時には消えてしまうため、AutoRedraw = False 時は、
描画処理を「Private Sub Picture1_Paint()」内で行う必要があります。

一方、AutoRedraw = True の場合は、自動再描画が行われます。
たとえば Form_Load 内で描画しておいた場合には、Refresh は不要です。
そもそも描画が発生するタイミングと言うのは、たとえば
 ・自コントロールの Refresh メソッドを呼び出したとき
 ・親コントロールの Refresh メソッドを呼び出したとき
 ・自コントロールのサイズが変更したとき
 ・自コントロールの Visible プロパティが変更されたとき
 ・上に別のウィンドウが被さっていて、それが取り除かれたとき
などです。何らかの描画タイミングがあれば、Refresh 以外の要因でも
描画されますが、それが不定な場合は Refresh で強制再描画させます。


> ReplaceはVB5.0にはありませんでした。
そういえばそうでしたたね。それに Split も。

VB5 での代替コードはこちら。
http://support.microsoft.com/kb/188007/ja


> TextOutW関数で、.lpstrFileのプロパティが数値で表示されるため、
> 型をString型に変更して上記のコードで実行すると、パス名を表示できました。

それは、TextOutA を使う場合のやり方です。TextOutW では String にしてはいけません。

String 型を使うと、自動的に Shift_JIS 変換されてから受け渡されますので、
それを避けるため、String 型ではなく、そのアドレスを渡しているというわけです。
(これが VB.NET なら、String を ANSI/Wide いずれで受け渡すのかを指定できるのですけれどね)


> 引数TextにStrConvでUnicodeから変換して格納しました。
その方法でうまく渡せた文字があったとしても、それはただの偶然です。

そもそも、StrConv した時点で破損していませんか?


たとえば vbFromUnicode 変換の場合:

Dim S As String
Dim bin() As Byte

S = ChrW(&H33A5)            '立方メートル
Debug.Print Hex(AscW(S))    '33A5 なら成功

bin = StrConv(S, vbFromUnicode)     'Unicode バイナリを「Unicode→Shift_JIS変換」
Debug.Print Hex(bin(0))     'Shift_JIS に無い文字なので「?」などに化ける


ChrW(&H33A5) ではなく、Shift_JIS にある文字なら、VB 内では破損しませんが、
それを API に String で渡すと「Shift_JIS バイナリを、Unicode→Shift_JIS 変換して渡す」という
謝った処置が行われるので、どちらにせよ破損することになります。



もしも vbUnicode だとしたら、「Unicode バイナリを、Shift_JIS→Unicode変換」して壊してから、
それを API に渡して「壊れたバイナリを、Unicode→Shift_JIS変換」してさらに壊すという流れです。
中には、偶然元に戻る文字もあるかも知れませんが、意図した処理では無いですよね。


> Shell関数で
Shell 関数は、NT系列の OS 上で動かす場合に限り、Unicode 文字を扱えたと思います。
手元に検証環境が無いのでうろ覚えですが。


> VB2005はフリーのVisual Basic 2005 Express Edition をダウンロードして
> 所持しているという意味でした。
今なら、Visual Studio Community 2013 の方が良いでしょう。
個人利用なら無償で利用できる上に、機能制限もありません。
http://www.microsoft.com/ja-jp/dev/products/community.aspx

業務利用の場合は、Visual Studio Express 2013 ですかね。
機能制限はありますが、こちらも無償です。


なお、2012 や 2013 のバージョンは、Windows XP や Windows Vista では利用できません。
Vista までの古い OS を使っている場合には、2010 以下のバージョンをご利用下さい。


> VB2005で慣れてからでないと最新版をインストールしないと思います。
VB5 は、複数のバージョン(VB4 や VB6)とは同居させられませんでしたよね。
http://support.microsoft.com/kb/412579/ja

しかし、VB2005 と VB2008 以降については同居可能です。
というよりも、VB5(または VB6)から VB.NET への移行組ならば、
VB2005(または VB2008)も入れておいた方が良いでしょう。
VB2010 以降では「VB6 コードの変換機能」が廃止されていますので…。


> VB5.0を希望しているのは、作成している自作プログラムがVB5.0の勉強のために
> 作成したもので、言語を換えたくない気持ちがあるためです。
VB5 が登場したのは 17 年前ですね。

発売したばかりの新車より、17年前の中古車が好きな人も居るわけですから、
新しい言語の学習コストと、古い設計ゆえに発生する手間を比較した上で、
その上で VB5 の方に価値があると判断されるのであれば、それは個人の判断でしょね。
(自分も、未だに VB6 をちょくちょく併用しています)


ですから、今回のプログラムを今のまま修正できそうであれば、あえて新言語で
書きなおしたりはせず、VB5 を使い続けるというのも、一つの選択肢だと思います。

しかし、もしも『勉強』を主目的としているのであれば、現行バージョンを学ぶべきかと。



そもそも、Visual Basic 5.0 の対応 OS は、Windows 95、Windows 98 までとなっています。
NT 系は 3.51 Workstation まで(Server 版は非対応)なので、幾らなんでも古すぎますね。
Windows Me、NT4、2000、XP 等はサポート対象外であり、現行 OS は言わずもがな。

開発環境ではなく、実行環境としての利用に限るのであれば、後継 OS であっても
VB5 製アプリが運良く動作する可能性は高いです。
(未だに VB2 を動かしている現場もあったりするぐらいですし)

とはいえ、VB5 向けの情報はネット上でもどんどん失われている状況ですし、
今回の問題以外にもいろいろと問題をかかえています。
(たとえば、ライセンス上の問題により、現行 OS 上では、
セットアップウィザードによるインストーラー作成が行えないなど)

古い環境をどうしても生かさねばならない事情があるのならば已むを得ませんが、
新しい情報が入ってこない以上、発生する問題を自力で解決する能力が求められるので、
難易度はむしろ高くなる可能性があることは覚悟しておいた方が良いと思いますよ。


なお、今から移行するつもりなのであれば、VB2005 は少々古いように思えます。
せっかく覚えても、慣れたころににはまた陳腐化してしまうというのでは勿体無い…。

[ツリー表示へ]
タイトルRe^10: ファイルパスの機種依存文字を取得する方法について
記事No16048
投稿日: 2014/12/11(Thu) 11:44
投稿者マサタロウ
>  TextOutW h, x, y, StrPtr(s), Len(s)
>  TextOutW h, x, y, StrPtr(Text), Len(Text)
GetOpenFileName関数で試しましたが、
半角中点は表示されたままでした。
For〜Next、Mid、Leftで、GetOpenFileName関数の
.lpstrFileプロパティのパスのみ取得する事ができました。
同様の方法で、GetOpenFileNameW関数のパスのみ取得する
事ができると思います。


> > 関数(DrawText)を使用してTextOutWを実行するのは、数値を取得するためですか?
> そもそも、今回のサンプルにある DrawText は『関数』ではありません。
DrawTextという関数があることは知りませんでした。
自作の関数と思いました。

Subプロシージャー DrawTextで、TextOutWに文字列の先頭アドレスを
指定すると文字列が描画できる仕組みがはっきりしません。
文字列変数が格納されている場所を指定する(StrPtr)と
文字列が描画できるということはわかります。


> > TextOutW関数で、.lpstrFileのプロパティが数値で表示されるため、
> > 型をString型に変更して上記のコードで実行すると、パス名を表示できました。
>
> それは、TextOutA を使う場合のやり方です。TextOutW では String にしてはいけません。
GetOpenFileNameW関数の.lpstrFileプロパティの内容が数値になります。
.lpstrFileプロパティの内容を文字列に変換できますか?

 DrawText Picture1.hDC, StrPtr(udtOFN.lpstrFile), 1, 0

では数値が表示されます。

[ツリー表示へ]
タイトルRe^11: ファイルパスの機種依存文字を取得する方法について
記事No16049
投稿日: 2014/12/11(Thu) 16:48
投稿者魔界の仮面弁士
> 半角中点は表示されたままでした。

ここでいう「半角中点」が、どの文字を示しているのか分かりませんが、
表示させようとしているデータに問題があるのかもしれません。
(vbNullChar が描画されているわけでは無いのですよね?)

表示させようとしている文字列を下記のプロシージャに渡してみて、
どのような内容がイミディエイトに表示されるか、教えていただけ無いでしょうか。


Public Sub Dump(ByRef Unicode As Variant)
    Select Case VarType(Unicode)
        Dim bin() As Byte, v As Variant, n As Long
        Case vbString, vbByte Or vbArray
            bin = Unicode
            n = 0
            Debug.Print "*** 文字数:"; Len(Unicode)
            For Each v In bin
                If n = 0 Then Debug.Print Tab(1);
                Debug.Print Right("00" & Hex(v), 2);
                If n = 7 Then
                    Debug.Print " ";
                ElseIf n >= 15 Then
                    Debug.Print
                End If
                n = n + 1
            Next
            Debug.Print Tab(1); String(33, "=")
    End Select
End Sub



> 自作の関数と思いました。
Visual Basic において、関数とは「0 個以上の引数を受け取って、戻り値を返すもの」を指します。
自作されるものとしては、Function プロシージャ の事ですね。Sub ではなく。

言語系によっては、戻り値を返さない関数(または無効値を返す関数)というものが
定義されている場合もあるのですが、VB はそうではありません。

以下、VB5 Books Online / VB6 MSDN Library より抜粋:

》 Visual Basic には、Sqr、Cos、Chr などの組み込み関数がありますが、
》 ユーザー定義の関数を作成することもできます。関数を作成するには、
》 Function ステートメントを使って Function プロシージャを記述します。



> GetOpenFileNameW関数の.lpstrFileプロパティの内容が数値になります。
文字列バッファのアドレスを、数値として指定しています。
文字列が「数値になる」わけではありません。


> .lpstrFileプロパティの内容を
厳密には「プロパティ」では無く、ユーザー定義型のメンバーですね。

> 文字列に変換できますか?
出来ますが、今回は .lpstrFile の数値を直接読み取る必要はありません。
ご自身が宣言された文字列変数を指し示すポインタに過ぎないからです。

たとえば、.lpstrFile フィールドに対して、
 .lpstrFile = StrPtr(strFile)
として指定していた場合、API 呼出し後には、strFile 変数の中身が
既に書き換わった状態になっています。.lpstrFile を読み直す必要はありません。

サンプル掲示板に投稿した内容も、そのように処理されていますよね。

[ツリー表示へ]
タイトルRe^12: ファイルパスの機種依存文字を取得する方法について
記事No16050
投稿日: 2014/12/11(Thu) 17:46
投稿者マサタロウ
> そもそも、StrConv した時点で破損していませんか?
>
>
> たとえば vbFromUnicode 変換の場合:
>
> Dim S As String
> Dim bin() As Byte
>
> S = ChrW(&H33A5)            '立方メートル
> Debug.Print Hex(AscW(S))    '33A5 なら成功
>
> bin = StrConv(S, vbFromUnicode)     'Unicode バイナリを「Unicode→Shift_JIS変換」
> Debug.Print Hex(bin(0))     'Shift_JIS に無い文字なので「?」などに化ける
忘れていました。イミディエイトウィンドウには、
  33A5
  3F
と表示されます。Hex(bin(0))は「?」になってません。
「3F」の意味は文字化け?


> 表示させようとしている文字列を下記のプロシージャに渡してみて、
> どのような内容がイミディエイトに表示されるか、教えていただけ無いでしょうか。
 最初は表示させたい機種依存文字の一つ
  *** 文字数: 1
  6126
  =================================
 2014/12/11/18:24 修正(下記、例)のパスを入力)
  *** 文字数: 62
  43003A005C004400 6F00630075006D00
  65 00 6E 00 74 00 73 00 20 00 61
  00 6E 00 64 00 20 00 53 00 65 00
  74 00 74 00 69 00 6E 00 67 00 73
  00 5C 00 75 00 73 00 65 00 72 00
  4E 00 61 00 6D 00 65 00 5C 00 C7
  30 B9 30 AF 30 C8 30 C3 30 D7 30
  5C 00 D7 30 ED 30 B0 30 E9 30 E0
  30 2E 00 65 00 78 00 65 00 65 FF
  65 FF 65 FF 65 FF 65 FF 65 FF 65
  FF 65 FF 65 FF 65 FF 65 FF 65 FF
  65 FF 65 FF 65 FF
  =================================

以上でした。


> > 自作の関数と思いました。
> Visual Basic において、関数とは「0 個以上の引数を受け取って、戻り値を返すもの」を指します。
> 自作されるものとしては、Function プロシージャ の事ですね。Sub ではなく。
Subプロシージャでした。


> たとえば、.lpstrFile フィールドに対して、
>  .lpstrFile = StrPtr(strFile)
> として指定していた場合、API 呼出し後には、strFile 変数の中身が
> 既に書き換わった状態になっています。.lpstrFile を読み直す必要はありません。
>
> サンプル掲示板に投稿した内容も、そのように処理されていますよね。
文字列の表示ができました。


> > 半角中点は表示されたままでした。
>
> ここでいう「半角中点」が、どの文字を示しているのか分かりませんが、
> 表示させようとしているデータに問題があるのかもしれません。
> (vbNullChar が描画されているわけでは無いのですよね?)
上記、文字列の表示で、For〜Nextから抜ける条件に"vbNullChar"を
指定しているため、"vbNullChar"が表示されているのでしょうか?

  例) C:\Documents and Settings\userName\デスクトップ\プログラム.exe・・・・・・・・・・・・・・・

[ツリー表示へ]
タイトルRe^13: ファイルパスの機種依存文字を取得する方法について
記事No16051
投稿日: 2014/12/11(Thu) 19:18
投稿者魔界の仮面弁士
> 忘れていました。イミディエイトウィンドウには、
>   33A5
>   3F
> と表示されます。Hex(bin(0))は「?」になってません。
> 「3F」の意味は文字化け?

ChrW(&H33A5) は、「立方メートル記号」ですし、
ChrW(&H3F) は、「(半角の)疑問符記号」、いわゆるクエスチョンマークです。

本当に "?" という文字を扱おうとしているのなら、3F で問題ありませんが、
それ以外の文字が 3F と出力されているとしたら、データ破損確定です。

そもそも今回の案件で、vbFromUnicode や vbUnicode の出番は無いはずです。


> > 表示させようとしている文字列を下記のプロシージャに渡してみて、
> > どのような内容がイミディエイトに表示されるか、教えていただけ無いでしょうか。
>   *** 文字数: 1
>   6126
>   =================================

ChrW(&H2661) ということは、「白抜きハートマーク」の文字ですね。

U+2661 'WHITE HEART SUIT'
http://www.fileformat.info/info/unicode/char/2661/index.htm


まず、表示させようとしている文字がハートマーク記号であるかどうかを確認して下さい。
ハートマークで無いのだとしたら、この String データはすでに破損していることになります。

データ自体は 61,26 のハート文字で正しいけれども、それを表示させると「半角中点」に化けるのであれば、
 ・Unicode 非対応な方法で表示させようとしている。
 ・Unicode 対応の API に渡しているが、呼び出しのコードが間違っている。
 ・呼び出しは正しいが、使用しているフォントが、ハートのグリフを持っておらず、半角中点で代用されている。
のいずれかです。その点を考慮して、もう一度処理内容を見直してみてください。



>   例) C:\Documents and Settings\userName\デスクトップ\プログラム.exe・・・・・・・・・・・
この文字列は、サンプル掲示板(No.340)のコードで得たものでしょうか。

だとすれば、あのサンプルでは、変数 strFile を、API との通信に用いるための
「最大で512文字分のパスを受け取るためのメモリ領域」として利用しています。

この変数には、初期値として、
  strFile = String(512, 0)
を事前にセットしてあります。
これは、ChrW(&H0) (すなわち vbNullChar)を、512 個並べた文字列という意味ですね。


そして GetOpenFileNameW API に対しては、こうして確保しておいた文字列型変数のメモリ領域を
 .lpstrFile = StrPtr(strFile)  'パス文字列を書き込むためのメモリ領域
 .nMaxFile = Len(strFile)    '上記 .lpstrFile のメモリ領域が確保している文字数
のように指定して渡しています。

そして API 側では、ファイルが選択されたときに、そのフルパス情報を
「.lpstrFile と .nMaxFile で指定された、VB 側のメモリ領域」に書き込むようになっています。

ここに指定した値は、VB 上の変数 strFile (の文字列情報のエリア)のアドレスを
指し示していますので、そこに書き込むことで、変数 strFile の内容も変化することになります。

たとえば、"C:\Dir1\File.txt" が選択されたとしたら、この 512 文字分の領域のうち、
   1文字目〜16文字目 → "C:\Dir1\File.txt" (パス情報)
  17文字目      → ChrW(&H0) (文字列の終端を表す)
  18文字目〜512文字目 → 何もしない(呼び出し前の情報のまま)
の文字にそれぞれ書き換わるという仕組みです。


実際のパスは、17文字目の終端文字の直前までですので、先のサンプルでは

  DlgShowOpen = Split(strFile & vbNullChar, vbNullChar, 2, vbBinaryCompare)(0)

というコードで、それを切り出しています。
VB5 の場合は Split 関数がありませんので、かわりに

  Dim p As Integer
  p = InStr(1, strFile, vbNullChar, vbBinaryCompare)    '最初に見つかった vbNullChar の位置を取得
  If p > 0 Then
   DlgShowOpen = Left(strFile, p - 1)     'Left 関数で、vbNullChar の直前までの文字列を切り出す
  Else
   DlgShowOpen = vbNullString             'vbNullChar が見つからなかった場合・
  End If

などと書き換えてみてください。

[ツリー表示へ]
タイトルRe^14: ファイルパスの機種依存文字を取得する方法について
記事No16052
投稿日: 2014/12/12(Fri) 10:56
投稿者マサタロウ
> ここでいう「半角中点」が、どの文字を示しているのか分かりませんが、

> 表示させようとしている文字列を下記のプロシージャに渡してみて、
> どのような内容がイミディエイトに表示されるか、教えていただけ無いでしょうか。
>
>
> Public Sub Dump(ByRef Unicode As Variant)
サンプル掲示板(No.340)のコードで取得したパスを渡した結果の
方だったでしょうか?
「白抜きハートマーク」の文字を含むパスは表示できました。

  例) C:\Documents and Settings\userName\デスクトップ\プログラム.exe・・・・・・・・・・・・・・・

「・・・・・・・・・・・・・・・」部分を半角中点と表現しました。


> >   例) C:\Documents and Settings\userName\デスクトップ\プログラム.exe・・・・・・・・・・・
> この文字列は、サンプル掲示板(No.340)のコードで得たものでしょうか。
http://www.hanatyan.sakura.ne.jp/patio/read.cgi?no=340
で取得したパスです。
書き換えのサンプルで実行したら、For〜Next、Mid、Leftと
同じ結果が得られました。

[ツリー表示へ]
タイトルRe: ファイルパスの機種依存文字を取得する方法について
記事No16053
投稿日: 2014/12/12(Fri) 11:14
投稿者魔界の仮面弁士
スレッドが長くなってきたので、いったん仕切りなおして。

VB5 からの Unicode 文字列の扱いについて、ここまで

・TextOutW API による、画面上への描画
・GetOpenFileNameW API による、「ファイル名を指定して開く」ダイアログの利用
・MessageBoxW API による、Unicode 対応メッセージボックス

という対処方法を、具体例を交えて述べてきたわけですが、
「自作のビューアー」「プログラムランチャー」へ実装は
行えそうでしょうか。それとも、まだ他に何か問題点が残っていますか?

[ツリー表示へ]
タイトルRe^2: ファイルパスの機種依存文字を取得する方法について
記事No16057
投稿日: 2014/12/15(Mon) 12:39
投稿者マサタロウ
> ・TextOutW API による、画面上への描画
「プログラムランチャー」の目的部分の一つへ実装出来てます。
同じ作業を残り部分に設定し、PictureBoxのサイズをパスのサイズに合わせる
作業を行います。機種依存文字を含まないパスの場合は、既存のコードで
実行させるため、No.16035の関数を使用させてもらいました。
「自作のビューアー」は、画面上ではパスを表示させません。


> ・GetOpenFileNameW API による、「ファイル名を指定して開く」ダイアログの利用
「プログラムランチャー」で実装出来てます。「自作のビューアー」も同様の作業なので、
問題ないと思います。


> ・MessageBoxW API による、Unicode 対応メッセージボックス
自作プログラムでの利用は今のところありません。


> 行えそうでしょうか。それとも、まだ他に何か問題点が残っていますか?
質問の内容から外れますが、次に実装が必要な作業の一部についてです。

『ADODB.Stream』でファイルの内容を読み込んだ場合に内容を変数に格納する方法で、
ファイルの内容を1行ずつ読み込む方法は分かりました(下記ページ参考)。
  http://msdn.microsoft.com/ja-jp/library/cc389881.aspx
変数の内容を「プログラムランチャー」に設定するのは、既存のコードで
問題ないと思います。

FileSystemObject などを用いて、Unicode 名入り画像ファイルを
別のファイル名にコピーして表示させる方法は、「自作のビューアー」に
GetOpenFileNameW API 実装後に FileSystemObject でコピーを作成して、
既存のコードで表示できると思います。

[ツリー表示へ]