powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
8 сообщений из 8, страница 1 из 1
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #36518519
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_One,

вот этот пример, что вы привели:
GetOpenFileName: Set an Open/Save Dialog\'s Initial Listview View
http://vbnet.mvps.org/code/hooks/fileopensavedlghooklvview.htm

в этой теме

/topic/735867&hl=

Он замечательный.
Код: plaintext
Public Const SHVIEW_ICON As Long = &H7029\nPublic Const SHVIEW_LIST As Long = &H702B\nPublic Const SHVIEW_REPORT As Long = &H702C\nPublic Const SHVIEW_THUMBNAIL As Long = &H702D\nPublic Const SHVIEW_TILE As Long = &H702E\n...\n               \'hwndLv = FindWindowEx(hWndParent, 0, "SHELLDLL_DefView", vbNullChar)\n               hwndLv = GetDlgItem(hWndParent, ID_LIST)\n               If hwndLv >  0  Then\n                  Call SendMessage(hwndLv, WM_COMMAND, ByVal m_lvInitialView, ByVal  0 &)\n                  \'Call SendMessage(hwndLv, WM_COMMAND, ByVal SHVIEW_THUMBNAIL, ByVal  0 &)

Хотя бесполезный для Висты, ибо там вид каждой папки запоминается итак системно, и данный код ничего кроме бардака не даст.
Но для XP очень так ничего.

Собственно вопрос в чем.
Юзер может выбирать вид Listview: иконки,таблица,report из системного тулбар в диалоге.

Т.е. как спросить у Диалога (у Listview) напр. перед закрытием диалога: а в каком состоянии ты сейчас находишься (миниатюры, иконки, report)? Чтобы запомнить это значение и отображать в след. раз в том же виде?
Чтоб не лепить в программе лишних настроек, но эту возможность использовать неявно.

Я попробовал покопать в сторону
LVM_GETVIEW Message и LVM_SETVIEW Message
Код: plaintext
Public Const LV_VIEW_ICON = &H0&        \'= &H0000\nPublic Const LV_VIEW_DETAILS = &H1&      \'= &H0001\nPublic Const LV_VIEW_SMALLICON = &H2&   \'= &H0002\nPublic Const LV_VIEW_LIST = &H3&        \'= &H0003\nPublic Const LV_VIEW_TILE = &H4&        \'= &H0004

но это совсем не то, нужно именно в рамках той модели что в указанном примере
т.е. как получить
Sendmessage (hwnd(ID_LIST), Get(SHVIEW_) ) =SHVIEW_THUMBNAIL? SHVIEW_REPORT ?SHVIEW_LIST...
...
Рейтинг: 0 / 0
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #36518775
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно, вышеуказанный пример т.е. строчка по типу
Код: plaintext
Call SendMessage(hwndLv, WM_COMMAND, ByVal SHVIEW_THUMBNAIL, ByVal  0 &)
это некий трюк (односторонний).
Надо по сути вот что:
http://www.codeproject.com/KB/winsdk/Win32TipsAndTricks.aspx?msg=2516578

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
IShellBrowser *shBrowser=(IShellBrowser*)SendMessage(hWnd,WM_GETISHELLBROWSER, 0 , 0 );
IShellView *shView=NULL;
if (shBrowser->QueryActiveShellView(&shView)==S_OK) {
  IFolderView *folder=NULL; // requires Win XP

  if (shView->QueryInterface(IID_IFolderView,(void **)&folder)==S_OK) {
    folder->SetCurrentViewMode(g_ViewMode);
    folder->Release();
  }
  shView->Release();
}
http://msdn.microsoft.com/en-us/library/bb775578(VS.85).aspx
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
IFolderView::GetCurrentViewMode Method
Gets an address containing a value representing the folder's current view mode.

Syntax
HRESULT GetCurrentViewMode(          UINT *pViewMode
);
Parameters

pViewMode
[out] A pointer to a memory location at which to store the folder's current view mode.
The value at that address is one of the following FOLDERVIEWMODE values.

FVM_ICON
Medium icons
FVM_SMALLICON
Small icons
FVM_LIST
List view without details
FVM_DETAILS
Show details (size, type, last modification date)
FVM_THUMBNAIL
Thumbnail view
FVM_TILE
Large icons
FVM_THUMBSTRIP
Filmstrip view

Только фиг с этим разберешься в переложении на VB.
SHELLBROWSER это как бы VB-объект Internet Explorer (и там кстати все эти FVM_THUMBNAIL есть в свойствах), только как это увязать...
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #38279444
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IShellBrowser --> IFolderView я не осилил.
Но решил следующим образом:
hwnd (Common Control Dialog) которая передается в OFNHookProc имеет родителя hWndParent = GetParent(hwnd)
У hWndParent есть Child - окно класса "SHELLDLL_DefView" (которое и управляет "видами"), а сам ListView является является child-ом для "SHELLDLL_DefView"

Код: vbnet
1.
2.
hWndParent <- hwnd (Common Control Dialog)
hWndParent <-hwndLv ("SHELLDLL_DefView") -< hwndLVIEW("SysListView32", Common Controls)



hwndLv ("SHELLDLL_DefView") получает сообщения вида
Код: vbnet
1.
2.
3.
4.
5.
6.
Public Const SHVIEW_ICON As Long = &H7029
Public Const SHVIEW_LIST As Long = &H702B
Public Const SHVIEW_REPORT As Long = &H702C
Public Const SHVIEW_THUMBNAIL As Long = &H702D
Public Const SHVIEW_TILE As Long = &H702E
Call SendMessage(hwndLv, WM_COMMAND, ByVal m_lvInitialView, ByVal 0&)


Эти сообщения можно слать "ручками"
Вот этот пример:
GetOpenFileName: Set an Open/Save Dialog's Initial Listview View

Но переключатель в Common Control Dialog (который Вид->Иконки, Эскизы, Таблица) делает абсолютно то же самое.
Т.е. если отловить WM_COMMAND и прочесть wParam, то это и будет "Current Listview View".


1. При запуске Common Dialog вычисляем hwndLv ("SHELLDLL_DefView") и сабклассим его:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
     Case WM_NOTIFY
               
       If IsWinVista = False Then
         If bLvSetupDone = False Then
                   
           'hwnd is the handle to the dialog
           'hwndParent is the handle to the common control
           'hwndLv is the handle to the "SHELLDLL_DefView"
           hWndParent = GetParent(hwnd)
           hwndLv = FindWindowEx(hWndParent, 0, "SHELLDLL_DefView", vbNullChar)
                   
           If hwndLv > 0 Then
             'сабклассим "SHELLDLL_DefView" окно на предмет изменения Folder View
             'в том числе со стороны стандартных менюшек Common Dialog
             OldFolderViewWindowProc = SetWindowLong( _
              hwndLv, GWL_WNDPROC, _
              AddressOf NewFolderViewWindowProc)
             'здесь устанавливаем m_lvInitialView, (кот. запомнили из предыдущего диалога)
             Call SendMessage(hwndLv, WM_COMMAND, ByVal m_lvInitialView, ByVal 0&)
                    
             bLvSetupDone = True
           End If  'hwndLv
         End If  'bLvSetupDone
       End If



2. А дальше просто ловим WM_COMMAND и читаем wParam, естественно "левые" значения wParam игнорируем:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
Private Function NewFolderViewWindowProc( _
 ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, lParam As Long) As Long
 
 Select Case Msg
   Case WM_COMMAND
     Select Case wParam
       Case SHVIEW_ICON
         Debug.Print "Folder View changed to 'Icon (Large)'"
         Form1.List1.Text = "Icon (Large)"
         m_lvInitialView = wParam
       Case SHVIEW_LIST
         Debug.Print "Folder View changed to 'List (default view)'"
         Form1.List1.Text = "List (default view)"
         m_lvInitialView = wParam
       Case SHVIEW_REPORT
         Debug.Print "Folder View changed to 'Details (Report view)'"
         Form1.List1.Text = "Details (Report view)"
         m_lvInitialView = wParam
       Case SHVIEW_THUMBNAIL
         Debug.Print "Folder View changed to 'Thumbnails'"
         Form1.List1.Text = "Thumbnails"
         m_lvInitialView = wParam
       Case SHVIEW_TILE
         Debug.Print "Folder View changed to 'Tiles'"
         Form1.List1.Text = "Tiles"
         m_lvInitialView = wParam
       Case Else
     End Select
   Case Else
 End Select



Т.е. "Folder View" всегда устанавливается из меню диалога (по человечески), и программа помнит его для следующих запусков.
Ну это для XP конечно.
На Висте это не нужно и вредно. Там совершенно другой набор команд и понятий (иконки не очень большие, очень большие и т.д.).
И Виста всегда сама запоминает индивидуальный вид для каждой папки.
========================================================
Можно конечно добраться до самого Listview: hwndLVIEW("SysListView32", Common Controls)
И это даст какую-то информацию. Но она будет не полной, т.к.
LV_VIEW_ICON
не делает различий между Icon large и Thumbnails (на Висте соотв. между "большими" и "не очень большими" иконками).
Как-то так
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
         Case CDN_HELP 'Help clicked (that is "Listview")
           'MsgBox "'Listview' clicked"
           
           hWndParent = GetParent(hwnd)
           hwndLv = FindWindowEx(hWndParent, 0, "SHELLDLL_DefView", vbNullChar) 'hwndLv is the handle to the "SHELLDLL_DefView"
           'hwndLVIEW = FindWindowEx(hwndLv, 0&, vbNullString, "FolderView")'так
           hwndLVIEW = FindWindowEx(hwndLv, 0&, "SysListView32", vbNullString) 'или так 'hwndLVIEW is the handle to the listview itself
           Dim the_view As Long
           Dim the_view_str As String
           the_view = SendMessage(hwndLVIEW, LVM_GETVIEW, 0, 0)
           Select Case the_view
             Case LV_VIEW_ICON
               Debug.Print "LV_VIEW_ICON (Icon large or Thumbnails)"
               the_view_str = "LV_VIEW_ICON (Icon large or Thumbnails)"
             Case LV_VIEW_DETAILS
               Debug.Print "LV_VIEW_DETAILS (Details)"
               the_view_str = "LV_VIEW_DETAILS (Details)"
             Case LV_VIEW_SMALLICON
               Debug.Print "LV_VIEW_SMALLICON"
               the_view_str = "LV_VIEW_SMALLICON"
             Case LV_VIEW_LIST
               Debug.Print "LV_VIEW_LIST (List)"
               the_view_str = "LV_VIEW_LIST (List)"
             Case LV_VIEW_TILE
               Debug.Print "LV_VIEW_TILE (Tiles)"
               the_view_str = "LV_VIEW_TILE (Tiles)"
           End Select
           MsgBox the_view_str


=============================
Т.е. второй вариант не (совсем) правильный.

Если интересно, я допилил и приложил упомянутый проект (не с нуля ж этот тест делать).
...
Рейтинг: 0 / 0
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #38279445
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поясню на всякий случай суть сделанного:
...
Рейтинг: 0 / 0
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #38280219
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

если до ViewMode можно добраться через IFolderView, то не так-то сложно это сделать. Нужна всего-то соответствующая библиотека типов. И она есть, olelib.tlb .
Если подключить её в пример http://vbnet.mvps.org/code/hooks/fileopensavedlghooklvview.htm , то получим:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
Private Const WM_USER             As Long = &H400&
Private Const WM_GETISHELLBROWSER As Long = WM_USER + 7
...
Public Function OFNHookProc(ByVal hwnd As Long, ...
 Dim hWndParent As Long
 ...   
 Dim shBrowser As IShellBrowser
 Dim pShellBrowser As Long
 Dim shView As IShellView
 Dim Folder As IFolderView
 Dim vmFolder As FOLDERVIEWMODE
...
 hWndParent = GetParent(hwnd)
 pShellBrowser = SendMessage(hWndParent, WM_GETISHELLBROWSER, 0, ByVal 0&)
 If pShellBrowser Then
    MoveMemory shBrowser, pShellBrowser, 4
    Set shView = shBrowser.QueryActiveShellView
    Set Folder = shView
      
    Folder.GetCurrentViewMode vmFolder 'получили режим

    Set Folder = Nothing
    Set shView = Nothing
      
    MoveMemory shBrowser, 0&, 4 'Нельзя делать Set Nothing
 End If
...
End Sub

Теперь о более грустном, о размере иконок в Вистах и т. д. Через IFolderView его не получишь, нужен интерфейс IFolderView2 и его метод GetViewModeAndIconSize. IFolderView2 в olelib не описан. Если поступать цивилизованно, то надо либо добавить его в olelib (заодно расширив под текущие реалии FOLDERVIEWMODE), либо написать свою (это не страшно, она маленькая получится) библиотеку типов. Если поступать нецивилизованно (ввиду отсутствия в VB цивилизованных способов вызова функции по адресу), то можно получить ссылку на IFolderView2 и обойтись вызовом метода IFolderView2::GetViewModeAndIconSize() по адресу в vtbl.

Кодом сейчас помочь не смогу. Да и форум читаю редко.
...
Рейтинг: 0 / 0
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #38280610
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,

Да думал я об этих tlb.
Только постоянно натыкался на ISHF_Ex.tlb а там нужного интерфейса нет.

В принципе (с твоей подачи) я все сделал чуть по-другому правда. Проект прилагаю.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
         Case CDN_HELP 'Help clicked
           
           hWndParent = GetParent(hwnd)
           '// undocumented message to get IShellBrowser from the file dialog
           '
           '#define WM_GETISHELLBROWSER (WM_USER+7)
           '
           'IShellBrowser *shBrowser=(IShellBrowser*)SendMessage(hWnd,WM_GETISHELLBROWSER,0,0);
           'IShellView *shView=NULL;
           'if (shBrowser->QueryActiveShellView(&shView)==S_OK) {
           '  FOLDERSETTINGS settings;
           '  shView->GetCurrentInfo(&settings);
           '  g_ViewMode=settings.ViewMode;
           '  shView->Release();
           '}
           '
           '// experiments show that shBrowser doesn't need to be Released

           pShellBrowser = SendMessage(hWndParent, WM_GETISHELLBROWSER, 0, ByVal 0&)
           'MsgBox pShellBrowser
           If pShellBrowser <> 0 Then
             MoveMemory shBrowser, pShellBrowser, 4
             Set shView = shBrowser.QueryActiveShellView
             shView.GetCurrentInfo settings
             g_ViewMode = settings.ViewMode
             MsgBox g_ViewMode
             Debug.Print g_ViewMode
             Set shView = Nothing
             MoveMemory shBrowser, 0&, 4 'Нельзя делать Set Nothing
           End If



БенедиктТеперь о более грустном, о размере иконок в Вистах и т. д. Через IFolderView его не получишь, нужен интерфейс IFolderView2...
А что грустить-то. Thumbnales этот метод от Icons отличает, т.е.на XP он дает исчерпывающий ответ.
А что касается вистообразных, там эти махинации как я писал вообще не нужны, она итак все сама помнит.
Но если очень нужно, можно использовать мой метод:
сабклассить "SHELLDLL_DefView" окно. На висте wParam для больших и не очень больших видов будет выдавать РАЗНЫЕ значения -в районе 28750+/- (можете глянуть через Debug в приложенном проекте). На XP сообщения другие - те константы типа 28717+/- что приведены выше.

Если использовать IMetods, то есть вопрос. Я запрашиваю "View" по команде. И я честно не знаю в каком месте (т.е. в последний момент перед закрытием диалога) в хуке Open/Save это запросить (чтоб сохранить для будущего использования).
Т.е. есть CDN_OK (а если Cancel?) но не вижу CDN_CLOSE.

Посему мой метод мне кажется лучше, он при смене вида генерирует событие (в сабклассинге) и результат сохраняется автоматом.

Но я другой глюк счас обнаружил в своем методе. Если пользователь ушел в другую папку , то мой механизм работать перестает.
Так понимаю, "SHELLDLL_DefView" меняется и сабклассинг загибается.
Видимо надо переинициализировать сабклассинг всякий раз по событию CDN_ (Folder Changed). Посмотрю что можно сделать.

И еще, я не понимаю где и как этот сабклассинг снять. По хорошему опять же нужен "CDN_CLOSE". Или можно не снимать?


БенедиктЕсли поступать цивилизованно, то надо либо добавить его в olelib ... Если поступать нецивилизованно (ввиду отсутствия в VB цивилизованных способов вызова функции по адресу), то можно получить ссылку ...и обойтись вызовом метода ...по адресу в vtbl.
А нецивилизованно это как? Как я с Win7 Audio сделал? Типа PInvoke и пробуем циферки методом тыка?
...
Рейтинг: 0 / 0
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #38280614
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так, вот эту olelib.tlb я в проект вложить не смог, пишет файл велик.
...
Рейтинг: 0 / 0
А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
    #38280668
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Но я другой глюк счас обнаружил в своем методе. Если пользователь ушел в другую папку , то мой механизм работать перестает.
Так понимаю, "SHELLDLL_DefView" меняется и сабклассинг загибается.
Видимо надо переинициализировать сабклассинг всякий раз по событию CDN_ (Folder Changed). Посмотрю что можно сделать.

И еще, я не понимаю где и как этот сабклассинг снять. По хорошему опять же нужен "CDN_CLOSE". Или можно не снимать?
Ну, так и сделал.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
   Static hwndLv As Long

        Case CDN_FOLDERCHANGE
           Debug.Print "CDN_FOLDERCHANGE"
           If IsWinVista = False Then
             'снимаем предыдущий сабклассинг "SHELLDLL_DefView"
             SetWindowLong hwndLv, GWL_WNDPROC, OldFolderViewWindowProc
             hWndParent = GetParent(hwnd)
             hwndLv = FindWindowEx(hWndParent, 0, "SHELLDLL_DefView", vbNullChar)
             Debug.Print hwndLv
             If hwndLv > 0 Then
               'сабклассим "SHELLDLL_DefView" заново (hwndLv другой)
               OldFolderViewWindowProc = SetWindowLong( _
                hwndLv, GWL_WNDPROC, _
                AddressOf NewFolderViewWindowProc)
             End If
           End If


Если не снимать сабклассинг перед его "перезапуском", то прога схлопывается.

А вот "крайний" сабклассинг как снять (и надо ли) не знаю. Не буду снимать. Вроде все работает.
Приложил исправленный проект (без IMetods).
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / А как узнать текущий Open/Save Dialog's Listview (THUMBNAIL,REPORT)?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]