C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: コモンダイアログの初期表示フォルダ'(windows7環境)


(過去ログ 115 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■67556 / inTopicNo.1)  コモンダイアログの初期表示フォルダ'(windows7環境)
  
□投稿者/ ほっけ (1回)-(2013/08/09(Fri) 13:06:28)

分類:[VB6 以前] 

windowsXpで作成したVB6のアプリを、
windows7上で動作させると、
ファイルエクスプローラーの表示されるフォルダの場所が異なります。

コモンダイアログのコントロールを貼り付け、
.initDirにフォルダを設定、
.FileNameを初期化
.ShowOpenでダイアログを表示

この場合、windowXpでは毎回.initDirのフォルダが最初に開かれますが、
window7では初回のみ.initDirのフォルダが開かれ、
2回目から前回開いたファイルのフォルダが開かれてしまいます。

window7でも毎回.initDirのフォルダを開きたいのですが、
何かいい方法はないでしょうか?

VBランタイムも同じ状態に更新してみましたが、
解消しません。

よろしくお願い致します。
引用返信 編集キー/
■67558 / inTopicNo.2)  Re[1]: コモンダイアログの初期表示フォルダ'(windows7環境)
□投稿者/ 魔界の仮面弁士 (302回)-(2013/08/09(Fri) 13:32:11)
No67556 (ほっけ さん) に返信
> window7では初回のみ.initDirのフォルダが開かれ、
> 2回目から前回開いたファイルのフォルダが開かれてしまいます。

手元で再現しないので、手順を確認させてください。

2回目の .InitDir と .FileName は、何が設定されていますか?
(毎回セットしているのか、初回だけセットしているのか)

また、.Flags プロパティの内容は、初回と 2回目以降で同一ですか?
(.Flags 値は、ダイアログが閉じられたときにも書き換わります)


――気になるのは上記ですね。

各回の .InitDir, .FileName, .Flags のプロパティが、ShowOpen の前後で
どのような値になっているか、XP と 7 とで比較してみては如何でしょう。
引用返信 編集キー/
■67559 / inTopicNo.3)  Re[2]: コモンダイアログの初期表示フォルダ'(windows7環境)
□投稿者/ ほっけ (2回)-(2013/08/09(Fri) 14:01:31)
魔界の仮面弁士さん

さっそくご回答ありがとうございます。

.Flagsの設定は行っていません。

--コード--
Private Sub Command1_Click()
CommonDialog1.InitDir = "c:\"
CommonDialog1.FileName = ""
CommonDialog1.ShowOpen
End Sub
-----------

上記のコードで、
window7から下記の操作を行うと2回目以降にinitDirのフォルダを開いてくれません。
1. ボタンを押下してダイアログの表示 (「c:\」が開かれる)
2. ディスクトップの適当なファイルを選択して、「開く」ボタンを押下
3. 再度ボタンを押下(「c:\」ではなく「ディスクトップ」が開かれてしまう)

コンポーネントは「MicrosoftCommonDialogControl6.0(SP6)」、
を使用しています。

ご確認よろしくお願いいたします。
引用返信 編集キー/
■67562 / inTopicNo.4)  Re[3]: コモンダイアログの初期表示フォルダ'(windows7環境)
□投稿者/ 魔界の仮面弁士 (303回)-(2013/08/09(Fri) 16:43:22)
2013/08/10(Sat) 14:58:44 編集(投稿者)
# 当方の実験結果を記載しました。

■No67559 (ほっけ さん) に返信
> .Flagsの設定は行っていません。
これは、0 をセットしている、ということでしょうか。
(少なくとも、デザイン時に設定された値があるはず)

先にも書きましたように、ShowOpen 後に .Flags が変化する場合
(たとえば cdlOFNExtensionDifferent が加わるなど)があります。

ディレクトリ制御に関わるフラグ値(cdlOFNNoChangeDir)もありますので、
.Flags は明示してしておいた方が良いです。


それ以外で可能性があるとすると…カレントディレクトの差ですかね。
「MsgBox CurDir()」の結果が前後で異なっていませんか?
ShowOpen 前にカレントディレクトリを制御することで、動作が変わりますか?


> 上記のコードで、
デザイン時設定は何も弄っていないのでしょうか?


以下、当方 Win7 での結果です。
なお、下記の「DialogLog」は、CommonDialog1 の各プロパティを
Debug.Print するために用意した Sub プロシージャです。

'CommonDialog1 は、デザイン時のプロパティ設定なし(初期値のまま)
Private Sub Form_Load()
    With Me.CommonDialog1
        '.Flags = cdlOFNHideReadOnly Or cdlOFNExplorer
        .Flags = 0
        .DefaultExt = ".txt"
        .Filter = "Text|*.txt|Batch|*.cmd;*.bat"
        .FilterIndex = 1
        .InitDir = "C:\Tools\"
        .FileName = "Sample.txt"
    End With
    DialogLog "Load直後"
End Sub

Private Sub Command1_Click()
    Static cnt As Long
    cnt = cnt + 1
    
    Me.CommonDialog1.InitDir = "C:\"
    Me.CommonDialog1.FileName = ""
    Me.CommonDialog1.ShowOpen

    DialogLog CStr(cnt) & "回目直後"
End Sub


「パターン1」
 (1) <1回目>InitDir = C:\ で ShowOpen
 (2) <1回目>C:\ が表示される
 (3) <1回目>E:\ に移動
 (4) <1回目>ファイル欄に 存在しないファイル名.TXT と入力指定
 (5) <2回目>InitDir = C:\ で ShowOpen
 (6) <2回目>C:\ が表示される ★期待動作

「パターン2」
 (1) <1回目>InitDir = C:\ で ShowOpen
 (2) <1回目>C:\ が表示される
 (3) <1回目>C:\temp に移動
 (4) <1回目>ファイル欄に C:\Windows\explorer.exe と入力指定
 (5) <2回目>InitDir = C:\ で ShowOpen
 (6) <2回目>C:\ が表示される ★期待動作

「パターン3」
 (1) <1回目>InitDir = C:\ で ShowOpen
 (2) <1回目>C:\ が表示される
 (3) <1回目>E:\ に移動
 (4) <1回目>そこにあった既存ファイル(sql.txt)を選択指定
 (5) <2回目>InitDir = C:\ で ShowOpen
 (6) <2回目>C:\ が表示される ★期待動作

「パターン4」
 (1) <1回目>InitDir = C:\ で ShowOpen
 (2) <1回目>C:\ が表示される
 (3) <1回目>C:\AAA\ に移動
 (4) <1回目>そこにあった既存ファイル(log.txt)を選択指定
 (5) <2回目>InitDir = C:\ で ShowOpen
 (6) <2回目>C:\ が表示される ★期待動作

「パターン5」
 (1) <1回目>InitDir = C:\ で ShowOpen
 (2) <1回目>C:\ が表示される
 (3) <1回目>C:\app\ に移動
 (4) <1回目>キャンセルで閉じる
 (5) <2回目>InitDir = C:\ で ShowOpen
 (6) <2回目>C:\ が表示される ★期待動作



> ご確認よろしくお願いいたします。
具体的な手順等も分かるとありがたいです。
先の回答で述べた「〜〜で比較してみては如何でしょう」の確認もよろしくお願いいたします。


> 2. ディスクトップの適当なファイルを選択して、「開く」ボタンを押下
> 3. 再度ボタンを押下(「c:\」ではなく「ディスクトップ」が開かれてしまう)
「ディスクトップ」では、円盤の上になってしまいます。
机の上を表す「デスクトップ」ですね。

引用返信 編集キー/
■67567 / inTopicNo.5)  Re[1]: コモンダイアログの初期表示フォルダ'(windows7環境)
□投稿者/ Azulean (189回)-(2013/08/10(Sat) 00:35:47)
回答ではありませんが、Windows 7 あたりから Initial directory に関する仕様が変更されています。

http://msdn.microsoft.com/en-us/library/ms646839

Windows 7:
1.If lpstrInitialDir has the same value as was passed the first time the application used an Open or Save As dialog box, the path most recently selected by the user is used as the initial directory.
(以下略)

同じ InitialDir を渡していると、ユーザーが最近使用したフォルダーを優先するように Windows 側で配慮しています。
それに逆らってでもディレクトリを固定したいのであれば、MSDN 記述のアルゴリズムを理解した上でうまく特性をつかないといけないと思います。


ただし、Windows がそのようになるように振る舞っているのに、あえて違う挙動を無理矢理実現しなければならないのか、他のアプリと比べて使い勝手が違う環境を提供して問題ないのかといった点は考慮すべき事柄です。
引用返信 編集キー/
■67568 / inTopicNo.6)  Re[2]: コモンダイアログの初期表示フォルダ'(windows7環境)
□投稿者/ ロートル・プログラマ (1回)-(2013/08/10(Sat) 00:44:28)
Windows 7で自分がただ1つだけ便利になったなと思った仕様をわざわざ変更したい方が
おられる点になんか感動。
引用返信 編集キー/
■67591 / inTopicNo.7)  Re[4]: コモンダイアログの初期表示
□投稿者/ Azulean (195回)-(2013/08/11(Sun) 12:41:07)
2013/08/11(Sun) 12:53:12 編集(投稿者)

No67562 (魔界の仮面弁士 さん) に返信

書かれているコードを用いて、手元で実験しました。
デバッグ実行されている(厳密には VB6.exe の中で実行している)と再現しないと思われます。
ファイルメニューから exe を作成していただき、それで実行すれば再現させられるはずです。
(うまく再現できない場合は exe 名を変えてみてください。すでに別の InitDir でキャッシュされている可能性があるため)

VB6.exe で最初に指定された初期ディレクトリと実験で指定している初期ディレクトリが異なるであろうことから、現象を再現できないはずです。
(コモンダイアログコントロールを追加する、プロジェクトを開く、プロジェクトを保存するなど、実験する前に MSDN で言う "the first time the application used an Open or Save As dialog box" は過ぎてしまっている)
プロセスで一つと言うよりは、実行ファイルにつき一つなので、プロセスを再起動しても Windows 7 の初期パスは維持されます。



このあたりはレジストリに記録されています。
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32

推測するに FirstFolder に exe 名と渡された InitDir が記録されており、ここの InitDir と一致する InitDir を渡すと、LastVisitedPidlMRU などに記録されているフォルダーを参照するのでしょう。
VB6.exe の該当する InitDir は、手元環境(コモンダイアログ ocx を参照時)では「なし」みたいなので、InitDir = "C:\" だと一致せず、必ず C:\ が参照できると考えられます。
引用返信 編集キー/
■67594 / inTopicNo.8)  Re[5]: コモンダイアログの初期表示
□投稿者/ 魔界の仮面弁士 (306回)-(2013/08/11(Sun) 17:17:28)
No67567 (Azulean さん) に返信
> 回答ではありませんが、Windows 7 あたりから Initial directory に関する仕様が変更されています。
過去の SDK も含めて調べてみました。
Windows 7 どころか、以前から少しずつ変更されていたようですね。
(Win8, Win8.1 向けの記述は見つけられませんでした…)


Windows 95/NT:
1. lpstrInitialDir メンバで指定されたディレクトリが初期ディレクトリになります。
2. lpstrInitialDir メンバが 0 (NULL) であり、かつ、lpstrFile メンバが指すバッファに
   パスが格納されている場合、そのパスが初期ディレクトリになります。
3. カレントディレクトが初期ディレクトリになります。


Windows 98/Me:
1. lpstrInitialDir メンバで指定されたディレクトリが初期ディレクトリになります。
2. lpstrInitialDir メンバが 0 (NULL) であり、かつ、lpstrFile メンバが指すバッファに
   パスが格納されている場合、そのパスが初期ディレクトリになります。
3. 指定されたフィルタタイプのファイルがカレントディレクトに存在する場合には、
   カレントディレクトリが初期ディレクトリになります。
4. 現在のユーザーのパーソナルファイルディレクトリが初期ディレクトリになります。


Windows 2000/XP/Vista:
1. lpstrFile メンバが指すバッファにパスが格納されている場合、そのパスが初期ディレクトリになります。
2. lpstrInitialDir メンバで指定されたディレクトリが初期ディレクトリになります。
3. 以前に『開く』または『名前を付けて保存』ダイアログボックスを使用している場合には、
   最後に使用したパスが初期ディレクトリとして選択されます。ただし、アプリケーションが
   長い間実行されていない場合には、保存されている選択パスの情報は破棄されます。
4. lpstrInitialDir メンバが 0 (NULL) であり、かつ、指定されたフィルタタイプのファイルが
   カレントディレクトに存在する場合には、カレントディレクトリが初期ディレクトリになります。
5. 現在のユーザーのパーソナルファイルディレクトリが初期ディレクトリになります。
6. デスクトップフォルダが初期ディレクトリになります。


Windows 7:
1. lpstrInitialDir メンバが、以前に『開く』または『名前を付けて保存』ダイアログボックスを
   初回起動した時の値と同じ場合、最後に使用したパスが初期ディレクトリになります。
2. lpstrFile メンバにパス情報が含まれている場合、それが初期ディレクトリになります。
3. lpstrInitialDir が 0 (NULL) でない場合、それが初期ディレクトリになります。
4. lpstrInitialDir が 0 (NULL) であり、かつ、指定されたフィルタタイプのファイルが
   カレントディレクトに存在する場合には、カレントディレクトリが初期ディレクトリになります。
5. 現在のユーザーのパーソナルファイルディレクトリが初期ディレクトリになります。
6. デスクトップフォルダが初期ディレクトリになります。


以前のパスが使われる件、2000/XP/Vista の第3項では、
 However, if an application is not run for a long time, its saved selected path is discarded.
 (ただし、アプリが長い間実行されていない場合には、保存されていた選択パスの情報は破棄される)
と書かれていましたが、Win7 の第1項には見当たりませんね…。


■No67591 (Azulean さん) に返信
> ファイルメニューから exe を作成していただき、それで実行すれば再現させられるはずです。
> (うまく再現できない場合は exe 名を変えてみてください。すでに別の InitDir でキャッシュされている可能性があるため)

再現できました。ありがとうございます。


> このあたりはレジストリに記録されています。
> HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32

バイナリで読み難かったので、WshShell で列挙。こちらも確認できました。

Option Explicit

Private Sub Form_Load()
    Dim S As String
    S = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\FirstFolder\"
    
    List1.Clear
    On Error Resume Next
    Dim L As Long, Path As String
    Dim value() As Variant
    With CreateObject("WScript.Shell")
        L = 0
        Do
            value = .RegRead(S & CStr(L))
            If Err.Number <> 0 Then
                Exit Do
            End If
            Path = Replace(CStr(ToBinary(value)), vbNullChar, "|")
            List1.AddItem Path
            L = L + 1
        Loop
    End With
End Sub

Private Function ToBinary(ByRef value() As Variant) As Byte()
    Dim bin() As Byte
    ReDim bin(UBound(value))
    Dim n As Long
    For n = 0 To UBound(bin)
        bin(n) = CByte(value(n))
    Next
    ToBinary = bin
End Function


> それに逆らってでもディレクトリを固定したいのであれば、MSDN 記述のアルゴリズムを理解した上でうまく特性をつかないといけないと思います。
スマートな回避策は思いつきませんが、無理矢理逆らってみました。

Option Explicit

Private Sub Form_Load()
    With Me.CommonDialog1
        '.Flags = cdlOFNHideReadOnly Or cdlOFNExplorer Or cdlOFNNoChangeDir
        .Flags = 0
        .DefaultExt = ".txt"
        .Filter = "Text|*.txt|Batch|*.cmd;*.bat"
        .FilterIndex = 1
        .InitDir = "C:\Tools"
        .FileName = "Sample.txt"
    End With
End Sub

Private Static Sub Command1_Click()
    Dim cyclic As Boolean
    
    cyclic = Not cyclic
    If cyclic Then
        Me.CommonDialog1.InitDir = "C:\.\"
    Else
        Me.CommonDialog1.InitDir = "C:\"
    End If
    Me.CommonDialog1.FileName = ""
    Me.CommonDialog1.ShowOpen
End Sub

引用返信 編集キー/
■67709 / inTopicNo.9)  Re[3]: コモンダイアログの初期表示フォルダ'(windows7環境)
□投稿者/ ほっけ (3回)-(2013/08/26(Mon) 13:41:34)
魔界の仮面弁士さん
Azuleanさん

情報ありがとうございます!
Windows7から仕様が変更されたのは知りませんでした。

魔界の仮面弁士さんに記載して頂いた、
2回目のダイアログ表示時にInitDirの値を変更することで、
解決することが出来ました。

>「ディスクトップ」では、円盤の上になってしまいます。
>机の上を表す「デスクトップ」ですね。
固有名詞みたいな感じで覚えてしまっていました。
ご指摘ありがとうございます。



解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -