1

Тема: AHK: Окно проводника

Есть способ блокировать появление окна


OnMessage(0x44, "OnMsgBox")  
FileSelectFile, SelectedFile, 3, , Open a file, Text Documents (*.txt; *.doc) 
Return
	
OnMsgBox() { 
    DetectHiddenWindows, On
    Process, Exist 
    If (WinExist("ahk_class #32770 ahk_pid " . ErrorLevel)) {
		MsgBox % hInputBox := WinExist() 
    }
}

а есть ли способ блокировать его закрытие? То есть в данном случае при выборе файла по двойному клику, энтер, или ещё как то получить сообщение с выбранным файлом, но чтобы окно не закрывалось.

Или может кто встречал кастомное окно с ListView?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

2 (изменено: Malcev, 2023-03-31 13:01:05)

Re: AHK: Окно проводника

https://www.autohotkey.com/boards/viewtopic.php?t=43898
Или создавай своё common item dialog
https://learn.microsoft.com/en-us/windo … ile-dialog
и отлавливай OnFileOk.
https://learn.microsoft.com/en-us/windo … s-onfileok
qwerty12 уже предоставлял примеры отлова событий.
https://www.autohotkey.com/boards/viewtopic.php?t=29934

3

Re: AHK: Окно проводника

Имеешь ввиду что в OFNHookProc надо что то ловить?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

4

Re: AHK: Окно проводника

Зависит от того какое апи ты хочешь использовать.
Если старое, то да.

5

Re: AHK: Окно проводника

Я по аналогии с SetWindowsHookEx, поставил return 1, но это не отменяет закрытие окна, в отличие с хуком с кнопкой.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

6

Re: AHK: Окно проводника

Malcev пишет:

Зависит от того какое апи ты хочешь использовать.
Если старое, то да.

10ку.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

7

Re: AHK: Окно проводника

Последние 2 сообщения не понял.
Есть 2 апи - до висты и после.
Ahk v1 использует то, которое до.
Ahk v2 уже использует современное.

8

Re: AHK: Окно проводника

Malcev пишет:

Есть 2 апи - до висты и после.
Ahk v1 использует то, которое до.
Ahk v2 уже использует современное.

Это я дремучий, я про апи после висты, но я не знал что Ahk v1 не может использовать апи 10ки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

9 (изменено: serzh82saratov, 2023-03-31 19:49:37)

Re: AHK: Окно проводника

Malcev пишет:

Если старое, то да.

serzh82saratov пишет:

по аналогии с SetWindowsHookEx, поставил return 1

Тут я не понял, почему тогда по факту не блокирует?

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance force
DetectHiddenWindows, On

VarSetCapacity(OPENFILENAMEW, (cbOFN := A_PtrSize == 8 ? 152 : 88), 0)
NumPut(cbOFN, OPENFILENAMEW,, "UInt") ; lStructSize
NumPut(A_ScriptHwnd, OPENFILENAMEW, A_PtrSize, "Ptr") ; hwndOwner

filters := [ "Text Documents", "*.txt"
			,"Test",           "*.nfo"
			,"All files",      "*.*"]

if (IsObject(filters) && Mod(filters.MaxIndex(), 2) == 0) {
	finalFilterString := ""
	for _, filter in filters
		finalFilterString .= Mod(A_Index, 2) ? filter . " (" : filter . ")|" . filter . "|"

	while ((char := DllCall("ntdll\wcsrchr", "Ptr", &finalFilterString, "UShort", Asc("|"), "CDecl Ptr")))
		NumPut(0, char+0,, "UShort")

	NumPut(&finalFilterString, OPENFILENAMEW, A_PtrSize*3, "Ptr") ; lpstrCustomFilter
	NumPut(1, OPENFILENAMEW, A_PtrSize*(5 + (A_PtrSize == 4)), "UInt") ; nFilterIndex
}

VarSetCapacity(vPath, (260+2)*2, 0) ; if keeping the option to select multiple files, consider raising the size
vPath .= "*.txt"
NumPut(&vPath, OPENFILENAMEW, A_PtrSize*(6 + (A_PtrSize == 4)), "Ptr") ; lpstrFile
NumPut(260, OPENFILENAMEW, A_PtrSize*(7 + (A_PtrSize == 4)), "UInt") ; nMaxFile

initialDir := A_Desktop
title := "Open"
NumPut(&initialDir, OPENFILENAMEW, A_PtrSize*(10 + (A_PtrSize == 4)), "Ptr") ; lpstrInitialDir
NumPut(&title, OPENFILENAMEW, A_PtrSize*(11 + (A_PtrSize == 4)), "Ptr") ; lpstrTitle

NumPut((cb := RegisterCallback("OFNHookProc")), OPENFILENAMEW, A_PtrSize == 8 ? 120 : 68, "Ptr")
;OFN_ENABLESIZING := 0x00800000
;OFN_EXPLORER := 0x00080000
;OFN_ALLOWMULTISELECT := 0x00000200
;OFN_ENABLEHOOK := 0x00000020
;OFN_HIDEREADONLY := 0x00000004
vOFNFlags := 0x00880024
NumPut(vOFNFlags, OPENFILENAMEW, A_PtrSize*(12 + (A_PtrSize == 4)), "UInt") ; Flags

if (DllCall("comdlg32\GetOpenFileNameW", "Ptr", &OPENFILENAMEW)) {
	dirOrFile := StrGet(&vPath,, "UTF-16") 
	if (InStr(FileExist(dirOrFile), "D")) {
		; Multiple files selected
		fileNames := &vPath + (NumGet(OPENFILENAMEW, A_PtrSize == 8 ? 100 : 56, "UShort") * 2)
		while (*fileNames) {
			MsgBox % dirOrFile . "\" . (filename := StrGet(fileNames,, "UTF-16"))
			fileNames += (DllCall("ntdll\wcslen", "Ptr", fileNames, "CDecl Ptr") * 2) + 2
		}
	} else {
		MsgBox %dirOrFile%
	}
	if (ColorSelection)
		MsgBox % ColorSelection
}
DllCall("GlobalFree", "Ptr", cb, "Ptr")
return

;==================================================

OFNHookProc(hdlg, uiMsg, wParam, lParam)
{
	DetectHiddenWindows, On
	global ColorSelection
	return 1
	if (uiMsg == 4932)
		return 1
	if (uiMsg == 0x0110) { ; WM_INITDIALOG
		hWndParent := DllCall("GetParent", "Ptr", hdlg, "Ptr")
		ControlGet, hCtl1, Hwnd, , Static4, % "ahk_id " hWndParent
		ControlGet, hCtl2, Hwnd, , ComboBox3, % "ahk_id " hWndParent
		JEE_ControlGetPosClient(hWndParent, hCtl1, vPosX1, vPosY1, vPosW1, vPosH1)
		JEE_ControlGetPosClient(hWndParent, hCtl2, vPosX2, vPosY2, vPosW2, vPosH2)

		WinMove, % "ahk_id " hdlg, , , , , % vPosH2+15
		vPosX1 += 1, vPosY1 += vPosH1+15, vPosW1 *=0.69, vPosH1 *= 5
		vPosY2 += vPosH2+8
		
		Gui, Add, Text, x%vPosX1% y%vPosY1% w%vPosW1% h%vPosH1% hWndhCtl1, &Encoding:
		;note: for 'Gui, Add, DropDownList', h determines the height of the popup list not the ComboBox
		Gui, Add, DropDownList, x%vPosX2% y%vPosY2% w%vPosW2% hwndhCtl2 vColorSelection, ANSI||Unicode|Unicode big endian|UTF-8
		DllCall("SetParent", "Ptr", hCtl1, "Ptr", hWndParent, "Ptr")
		DllCall("SetParent", "Ptr", hCtl2, "Ptr", hWndParent, "Ptr")

		;resize window - including this line will not resize the window as desired
		;WinMove, % "ahk_id " hWndParent, , 0, 0, 800, 600

		;centre window
		;WinGetPos,,, Width, Height, % "ahk_id " hWndParent
		;WinMove, % "ahk_id " hWndParent,, (A_ScreenWidth/2)-(Width/2), (A_ScreenHeight/2)-(Height/2)
	} else if (uiMsg == 0x004E) { 
		if (NumGet(lParam+0, A_PtrSize * 2, "UInt") == 4294966690) { ; CDN_FILEOK
			Gui submit 
		}
	} else if (uiMsg == 0x0002) { ; WM_DESTROY 
		Gui Destroy 
	}
	return 0
}

;==================================================

JEE_ControlGetPosClient(hWnd, hCtl, ByRef vPosX, ByRef vPosY, ByRef vPosW, ByRef vPosH)
{
	VarSetCapacity(RECT, 16, 0)
	DllCall("GetWindowRect", Ptr,hCtl, Ptr,&RECT)
	DllCall("MapWindowPoints", Ptr,0, Ptr,hWnd, Ptr,&RECT, UInt,2)
	vPosX := NumGet(RECT, 0, "Int"), vPosY := NumGet(RECT, 4, "Int")
	vPosW := NumGet(RECT, 8, "Int")-vPosX, vPosH := NumGet(RECT, 12, "Int")-vPosY
	return
}
OFNHookProc(hdlg, uiMsg, wParam, lParam)
{
	DetectHiddenWindows, On
	global ColorSelection
	return 1
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10

Re: AHK: Окно проводника

Что значит блокирует?
Тут ни слова о блокировке нету:
https://learn.microsoft.com/en-us/windo … fnhookproc

11 (изменено: Malcev, 2023-03-31 20:11:24)

Re: AHK: Окно проводника

serzh82saratov пишет:

я не знал что Ahk v1 не может использовать апи 10ки.

Ahk может использовать всё, ну или почти всё.
Только самому надо интерфейсы создавать.
Это касается и второй версии тоже.
https://www.autohotkey.com/boards/viewt … 75#p187375
Но имхо проще создавать 1 колбек и вызывать методы через A_EventInfo.
Как, например, тут:
http://forum.script-coding.com/viewtopic.php?id=17643

12

Re: AHK: Окно проводника

Malcev пишет:

Что значит блокирует?
Тут ни слова о блокировке нету:
https://learn.microsoft.com/en-us/windo … fnhookproc

SetWindowsHookEx нажатие кнопки например, хочешь блокирует, хочешь пропускает.
В #9 возможно как то блокировать закрытие окна? Если ты говоришь что там нет про блокировку, какой смысл тогда отлавливать OnFileOk?

Malcev пишет:

Как, например, тут:

Жуть, я там до старости не разберусь).

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

13

Re: AHK: Окно проводника

OnFileOk мы отлавливаем в новом апи:
https://learn.microsoft.com/en-us/windo … ile-dialog
Ты привел код из старого:
https://learn.microsoft.com/en-us/windo … nfilenamew
В старом мы отлавливаем CDN_FILEOK:
https://learn.microsoft.com/en-us/windo … cdn-fileok
В справке читаем:

If the hook procedure returns zero, the dialog box accepts the specified file name and closes.

To reject the specified file name and force the dialog box to remain open, return a nonzero value from the hook procedure and call the SetWindowLong function to set a nonzero DWL_MSGRESULT value.

14

Re: AHK: Окно проводника

Новое апи мы же не будем юзать в старом анк. А в старом я привёл пример что возвращаю не ноль, но окно закрывается, про SetWindowLong ничего не понятно, когда его вызывать если функция уже отработала, и что во втором параметре? В первом хэндл окна, в третьем не ноль.
https://learn.microsoft.com/en-us/windo … indowlonga

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

15 (изменено: serzh82saratov, 2023-04-01 16:57:40)

Re: AHK: Окно проводника

serzh82saratov пишет:

когда его вызывать если функция уже отработала

Так наверное.

Return 1, DllCall("SetWindowLong" . (A_PtrSize = 8 ? "Ptr" : ""), Ptr, h, Int, ?, Ptr, 1)
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

16

Re: AHK: Окно проводника

Вроде дошло, но скрипт зависает при выборе файла.


#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance force
DetectHiddenWindows, On

VarSetCapacity(OPENFILENAMEW, (cbOFN := A_PtrSize == 8 ? 152 : 88), 0)
NumPut(cbOFN, OPENFILENAMEW,, "UInt") ; lStructSize
NumPut(A_ScriptHwnd, OPENFILENAMEW, A_PtrSize, "Ptr") ; hwndOwner

filters := [ "Text Documents", "*.txt"
			,"Test",           "*.nfo"
			,"All files",      "*.*"]

if (IsObject(filters) && Mod(filters.MaxIndex(), 2) == 0) {
	finalFilterString := ""
	for _, filter in filters
		finalFilterString .= Mod(A_Index, 2) ? filter . " (" : filter . ")|" . filter . "|"

	while ((char := DllCall("ntdll\wcsrchr", "Ptr", &finalFilterString, "UShort", Asc("|"), "CDecl Ptr")))
		NumPut(0, char+0,, "UShort")

	NumPut(&finalFilterString, OPENFILENAMEW, A_PtrSize*3, "Ptr") ; lpstrCustomFilter
	NumPut(1, OPENFILENAMEW, A_PtrSize*(5 + (A_PtrSize == 4)), "UInt") ; nFilterIndex
}

VarSetCapacity(vPath, (260+2)*2, 0) ; if keeping the option to select multiple files, consider raising the size
vPath .= "*.txt"
NumPut(&vPath, OPENFILENAMEW, A_PtrSize*(6 + (A_PtrSize == 4)), "Ptr") ; lpstrFile
NumPut(260, OPENFILENAMEW, A_PtrSize*(7 + (A_PtrSize == 4)), "UInt") ; nMaxFile

initialDir := A_Desktop
title := "Open"
NumPut(&initialDir, OPENFILENAMEW, A_PtrSize*(10 + (A_PtrSize == 4)), "Ptr") ; lpstrInitialDir
NumPut(&title, OPENFILENAMEW, A_PtrSize*(11 + (A_PtrSize == 4)), "Ptr") ; lpstrTitle

NumPut((cb := RegisterCallback("OFNHookProc")), OPENFILENAMEW, A_PtrSize == 8 ? 120 : 68, "Ptr")
;OFN_ENABLESIZING := 0x00800000
;OFN_EXPLORER := 0x00080000
;OFN_ALLOWMULTISELECT := 0x00000200
;OFN_ENABLEHOOK := 0x00000020
;OFN_HIDEREADONLY := 0x00000004
vOFNFlags := 0x00880024
NumPut(vOFNFlags, OPENFILENAMEW, A_PtrSize*(12 + (A_PtrSize == 4)), "UInt") ; Flags

if (DllCall("comdlg32\GetOpenFileNameW", "Ptr", &OPENFILENAMEW)) {
	dirOrFile := StrGet(&vPath,, "UTF-16") 
	if (InStr(FileExist(dirOrFile), "D")) {
		; Multiple files selected
		fileNames := &vPath + (NumGet(OPENFILENAMEW, A_PtrSize == 8 ? 100 : 56, "UShort") * 2)
		while (*fileNames) {
			MsgBox % dirOrFile . "\" . (filename := StrGet(fileNames,, "UTF-16"))
			fileNames += (DllCall("ntdll\wcslen", "Ptr", fileNames, "CDecl Ptr") * 2) + 2
		}
	} else {
		MsgBox %dirOrFile%
	}
	if (ColorSelection)
		MsgBox % ColorSelection
}
DllCall("GlobalFree", "Ptr", cb, "Ptr")
return

;==================================================

OFNHookProc(hdlg, uiMsg, wParam, lParam)
{
	DetectHiddenWindows, On
	global ColorSelection 
 
	if (uiMsg == 0x0110) { ; WM_INITDIALOG
		hWndParent := DllCall("GetParent", "Ptr", hdlg, "Ptr")
		ControlGet, hCtl1, Hwnd, , Static4, % "ahk_id " hWndParent
		ControlGet, hCtl2, Hwnd, , ComboBox3, % "ahk_id " hWndParent
		JEE_ControlGetPosClient(hWndParent, hCtl1, vPosX1, vPosY1, vPosW1, vPosH1)
		JEE_ControlGetPosClient(hWndParent, hCtl2, vPosX2, vPosY2, vPosW2, vPosH2)

		WinMove, % "ahk_id " hdlg, , , , , % vPosH2+15
		vPosX1 += 1, vPosY1 += vPosH1+15, vPosW1 *=0.69, vPosH1 *= 5
		vPosY2 += vPosH2+8
		
		Gui, Add, Text, x%vPosX1% y%vPosY1% w%vPosW1% h%vPosH1% hWndhCtl1, &Encoding:
		;note: for 'Gui, Add, DropDownList', h determines the height of the popup list not the ComboBox
		Gui, Add, DropDownList, x%vPosX2% y%vPosY2% w%vPosW2% hwndhCtl2 vColorSelection, ANSI||Unicode|Unicode big endian|UTF-8
		DllCall("SetParent", "Ptr", hCtl1, "Ptr", hWndParent, "Ptr")
		DllCall("SetParent", "Ptr", hCtl2, "Ptr", hWndParent, "Ptr")

		;resize window - including this line will not resize the window as desired
		;WinMove, % "ahk_id " hWndParent, , 0, 0, 800, 600

		;centre window
		;WinGetPos,,, Width, Height, % "ahk_id " hWndParent
		;WinMove, % "ahk_id " hWndParent,, (A_ScreenWidth/2)-(Width/2), (A_ScreenHeight/2)-(Height/2)
	} else if (uiMsg == 0x004E) { 
		if (NumGet(lParam+0, A_PtrSize * 2, "UInt") == 4294966690) { ; CDN_FILEOK
			; Gui submit 
			Return 1, DllCall("SetWindowLong" . (A_PtrSize = 8 ? "Ptr" : ""), Ptr, hdlg, Int, -4, Ptr, 1)
		}
	} else if (uiMsg == 0x0002) { ; WM_DESTROY 
		Gui Destroy 
	}
	return 0
}

;==================================================

JEE_ControlGetPosClient(hWnd, hCtl, ByRef vPosX, ByRef vPosY, ByRef vPosW, ByRef vPosH)
{
	VarSetCapacity(RECT, 16, 0)
	DllCall("GetWindowRect", Ptr,hCtl, Ptr,&RECT)
	DllCall("MapWindowPoints", Ptr,0, Ptr,hWnd, Ptr,&RECT, UInt,2)
	vPosX := NumGet(RECT, 0, "Int"), vPosY := NumGet(RECT, 4, "Int")
	vPosW := NumGet(RECT, 8, "Int")-vPosX, vPosH := NumGet(RECT, 12, "Int")-vPosY
	return
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

17

Re: AHK: Окно проводника

serzh82saratov пишет:

Новое апи мы же не будем юзать в старом анк.

Почему не будем?
Просто там надо подзапариться с ком интерфейсами, хотя об этом уже позаботился qwerty12.
А почему тут у тебя -4?

DllCall("SetWindowLong" . (A_PtrSize = 8 ? "Ptr" : ""), Ptr, hdlg, Int, -4, Ptr, 1)

18

Re: AHK: Окно проводника

Блин, уведомления не приходят на почту.

Malcev пишет:

А почему тут у тебя -4?

Предположил.

Ценить Значение
GWL_EXSTYLE
-20
Устанавливает новый расширенный стиль окна .
GWL_HINSTANCE
-6
Задает новый дескриптор экземпляра приложения.
GWL_ID
-12
Устанавливает новый идентификатор дочернего окна. Окно не может быть окном верхнего уровня.
SEE_STYLE
-16
Устанавливает новый стиль окна .
GWL_USERDATA
-21
Устанавливает пользовательские данные, связанные с окном. Эти данные предназначены для использования приложением, создавшим окно. Его значение изначально равно нулю.
GWL_WNDPROC
-4
Устанавливает новый адрес оконной процедуры.
Вы не можете изменить этот атрибут, если окно не принадлежит тому же процессу, что и вызывающий поток.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

19

Re: AHK: Окно проводника

serzh82saratov пишет:

Предположил.

С другими исчезает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

20 (изменено: Malcev, 2023-04-01 18:56:21)

Re: AHK: Окно проводника

https://learn.microsoft.com/en-us/windo … indowlonga

The following values are also available when the hWnd parameter identifies a dialog box.
Value Meaning

DWL_DLGPROC
DWLP_MSGRESULT + sizeof(LRESULT)

Sets the new address of the dialog box procedure.

DWL_MSGRESULT
0

Sets the return value of a message processed in the dialog box procedure.

DWL_USER
DWLP_DLGPROC + sizeof(DLGPROC)

Sets new extra information that is private to the application, such as handles or pointers.

21

Re: AHK: Окно проводника

Malcev пишет:

DWL_MSGRESULT

А я по невнимательности его как третий параметр воспринял).
Заработало, Спасибо!

Но так как GetOpenFileName не завершается, так понимаю узнать выбранный файл можно только из строки внизу, точнее не файл а его имя, но папка неизвестна.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

22

Re: AHK: Окно проводника

Разобрался, подумал что DllCall возвращает выбранное, всё работает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

23

Re: AHK: Окно проводника

Никак с lpstrInitialDir не разберусь, это стартовая папка, мне даже _Struct не помог).
Ещё хотел выяснить как изменить стиль окна, вроде бывает с деревом слева, но добавления флагов не сработало.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

24

Re: AHK: Окно проводника

serzh82saratov пишет:

Никак с lpstrInitialDir не разберусь, это стартовая папка

Так в коде же написано куда ее пихать:

initialDir := A_Desktop
title := "Open"
NumPut(&initialDir, OPENFILENAMEW, A_PtrSize*(10 + (A_PtrSize == 4)), "Ptr") ; lpstrInitialDir

А вот со вторым вопросом, похоже, придется таки разбираться с созданием ком интерфейсов:
https://tannerhelland.com/2013/01/16/ho … notes.html

25

Re: AHK: Окно проводника

Malcev пишет:

Так в коде же написано куда ее пихать

Плохи дела).
https://www.youtube.com/watch?v=L0g-rWPVC-I

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

26 (изменено: serzh82saratov, 2023-04-02 01:03:57)

Re: AHK: Окно проводника

Malcev пишет:

А вот со вторым вопросом, похоже, придется таки разбираться с созданием ком интерфейсов:

О, типа возможно любые опции выбирать. Нормальный вариант был бы. Можно в интерфейс свой добавить например, рамки обрезать, setparent, и считай как новый контрол.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

27

Re: AHK: Окно проводника

Ещё мешает закрытие по ESC, отлов WM_DESTROY не помогает.

Malcev пишет:

Почему не будем?
Просто там надо подзапариться с ком интерфейсами, хотя об этом уже позаботился qwerty12.

А ты тут имел ввиду что его пример сложно переделать под SelectFile?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

28

Re: AHK: Окно проводника

Нет, я имел в виду написание интерфейса, хотя и это не сложно, если есть внятная документация.

29

Re: AHK: Окно проводника

Malcev пишет:

написание интерфейса

А него что написано, или ты как то по другому пишешь?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

30

Re: AHK: Окно проводника

Я имел в виду, что раз у него написано, то и париться не о чем. А esc проще всего блокировать при активном диалоге.

31

Re: AHK: Окно проводника

У него про папки только.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

32

Re: AHK: Окно проводника

Там просто стоит опция FOS_PICKFOLDERS.
У него интерфейс расписан практически со всеми пояснениями.

33

Re: AHK: Окно проводника

Malcev пишет:

Там просто стоит опция FOS_PICKFOLDERS.

Ого, заработало.

Malcev пишет:

У него интерфейс расписан практически со всеми пояснениями.

Да уж, там в какие то дебри надо лезть. Например нужно SetDefaultFolder, так понял нужен её индекс. У SetOptions указано 9, но откуда он взялся? Помню ты как то объяснял, что в исходниках надо копать.

Про настройки видов так тебя понял, что совсем сложно. Дерево скрыть, вид файлов и.т.п.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

34 (изменено: serzh82saratov, 2023-04-02 18:13:04)

Re: AHK: Окно проводника

Начал вспоминать, нашёл исходник, нужен был SetFolder. Про настройки видов пока ничего.

+ открыть спойлер


if ((fde := IFileDialogEvents_new())) {  
	MsgBox % SelectFolder(fde, A_TEMP)
	ObjRelease(fde)
} 

+Esc:: ExitApp

IFileDialogEvents_new()
{
	vtbl := IFileDialogEvents_Vtbl()
	; VarSetCapacity apparently tries to emulate the peculiarities of stack allocation so use GlobalAlloc here
	fde := DllCall("GlobalAlloc", "UInt", 0x0000, "Ptr", A_PtrSize + 4, "Ptr") ; A_PtrSize to store the pointer to the vtable struct + sizeof unsigned int to store this object's refcount
	if (!fde)
		return 0

	NumPut(vtbl, fde+0,, "Ptr") ; place pointer to vtable in beginning of the IFileDialogEvents structure (you know how all this works from the other side)
	NumPut(1, fde+0, A_PtrSize, "UInt") ; Start with a refcount of one (thanks, just me)

	return fde
}

IFileDialogEvents_Vtbl(ByRef vtblSize := 0)
{
	/* This vtable approach is quite rigid and unflexible in its approach. 
		I mean, ideally, you'd want each object to have its own set of methods that are called.
		With this, however, nope - same methods, just a different "this".
	
		I leave fixing that part up to you. I imagine it involves each object getting its own
		vtable (you could leave all the callback pointers inside the IFileDialogEvents struct after the vtable pointer)
		instead of sharing this one, with the functions to be called for each object determined at creation. Or something like that.
	*/
	static vtable ; This mustn't be freed automatically when it goes out of scope
	if (!VarSetCapacity(vtable)) {
		; Three IUnknown methods that must be implemented, along with the many methods IFileDialogEvents adds on top
		extfuncs := ["QueryInterface", "AddRef", "Release", "OnFileOk", "OnFolderChanging", "OnFolderChange", "OnSelectionChange", "OnShareViolation", "OnTypeChange", "OnOverwrite"]

		; Create IFileDialogEventsVtbl struct
		VarSetCapacity(vtable, extfuncs.Length() * A_PtrSize)

		for i, name in extfuncs
			NumPut(RegisterCallback("IFileDialogEvents_" . name), vtable, (i-1) * A_PtrSize)
	}
	if (IsByRef(vtblSize))
		vtblSize := VarSetCapacity(vtable)
	return &vtable
}

; Called on a "ComObjQuery"
IFileDialogEvents_QueryInterface(this_, riid, ppvObject)
{
	static IID_IUnknown, IID_IFileDialogEvents
	if (!VarSetCapacity(IID_IUnknown))
		VarSetCapacity(IID_IUnknown, 16), VarSetCapacity(IID_IFileDialogEvents, 16)
		,DllCall("ole32\CLSIDFromString", "WStr", "{00000000-0000-0000-C000-000000000046}", "Ptr", &IID_IUnknown)
		,DllCall("ole32\CLSIDFromString", "WStr", "{973510db-7d7f-452b-8975-74a85828d354}", "Ptr", &IID_IFileDialogEvents)

	; If someone calls our QI asking for IUnknown or IFileDialogEvents, then respond by:
	if (DllCall("ole32\IsEqualGUID", "Ptr", riid, "Ptr", &IID_IFileDialogEvents) || DllCall("ole32\IsEqualGUID", "Ptr", riid, "Ptr", &IID_IUnknown)) {
		NumPut(this_, ppvObject+0, "Ptr") ; filling in the pointer to a pointer with the address of this object
		IFileDialogEvents_AddRef(this_)
		return 0 ; S_OK
	}

	; Else
	NumPut(0, ppvObject+0, "Ptr") ; no object for the caller
	return 0x80004002 ; E_NOINTERFACE
}

; Called on an "ObjAddRef"
IFileDialogEvents_AddRef(this_)
{
	; get and increment our reference count member inside the IFileDialogEvents struct
	NumPut((_refCount := NumGet(this_+0, A_PtrSize, "UInt") + 1), this_+0, A_PtrSize, "UInt")
	return _refCount ; new refcount must be returned
}

; Called on an "ObjRelease"
IFileDialogEvents_Release(this_) {
	_refCount := NumGet(this_+0, A_PtrSize, "UInt") ; read current refcount from IFileDialogEvents struct
	if (_refCount > 0) {
		_refCount -= 1 ; decrease it
		NumPut(_refCount, this_+0, A_PtrSize, "UInt") ; store it
		if (_refCount == 0) ; if it's zero, then
			DllCall("GlobalFree", "Ptr", this_, "Ptr") ; it's time for this object to free itself
	}
	return _refCount ; new refcount must be returned
}

IFileDialogEvents_OnFileOk(this_, pfd)
{
IFileDialogEvents_OnSelectionChange(this_, pfd)
return 1
	return 0x80004001 ; E_NOTIMPL ("[IFileDialogEvents] methods that are not implemented should return E_NOTIMPL.")
}

IFileDialogEvents_OnFolderChanging(this_, pfd, psiFolder)
{
	return 0x80004001 ; E_NOTIMPL
}

IFileDialogEvents_OnFolderChange(this_, pfd)
{
	return 0x80004001 ; E_NOTIMPL
}

IFileDialogEvents_OnSelectionChange(this_, pfd)
{
	if (DllCall(NumGet(NumGet(pfd+0)+14*A_PtrSize), "Ptr", pfd, "Ptr*", psi) >= 0) { ; IFileDialog::GetCurrentSelection
         GetDisplayName := NumGet(NumGet(psi + 0, "UPtr"), A_PtrSize * 5, "UPtr")
         If !DllCall(GetDisplayName, "Ptr", psi, "UInt", 0x80028000, "PtrP", StrPtr) { ; SIGDN_DESKTOPABSOLUTEPARSING
            SelectedFolder := StrGet(StrPtr, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "Ptr", StrPtr)
			ToolTip % SelectedFolder
		 }
		ObjRelease(psi)
	}
	return 0 ; S_OK
}

IFileDialogEvents_OnShareViolation(this_, pfd, psi, pResponse)
{
	return 0x80004001 ; E_NOTIMPL
}

IFileDialogEvents_OnTypeChange(this_, pfd)
{
	return 0x80004001 ; E_NOTIMPL
}

IFileDialogEvents_OnOverwrite(this_, pfd, psi, pResponse)
{
	return 0x80004001 ; E_NOTIMPL
}

; ---

SelectFolder(fde := 0, StartFolder := "") {
   ; Common Item Dialog -> https://msdn.microsoft.com/en-us/library/bb776913%28v=vs.85%29.aspx
   ; IFileDialog        -> https://msdn.microsoft.com/en-us/library/bb775966%28v=vs.85%29.aspx
   ; IShellItem         -> https://msdn.microsoft.com/en-us/library/bb761140%28v=vs.85%29.aspx
   Static OsVersion := DllCall("GetVersion", "UChar")
   Static Show := A_PtrSize * 3
   Static SetOptions := A_PtrSize * 9
   Static SetFolder := A_PtrSize * 12
   Static GetResult := A_PtrSize * 20
   
   SelectedFolder := ""
   If (OsVersion < 6) { ; IFileDialog requires Win Vista+
      FileSelectFolder, SelectedFolder
      Return SelectedFolder
   }
   If !(FileDialog := ComObjCreate("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}", "{42f85136-db7e-439c-85f1-e4075d135fc8}"))
      Return ""
	  ; https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-_fileopendialogoptions
   VTBL := NumGet(FileDialog + 0, "UPtr")
   DllCall(NumGet(VTBL + SetOptions, "UPtr"), "Ptr", FileDialog, "UInt", 0x00000008, "UInt") ; FOS_NOCHANGEDIR | FOS_PICKFOLDERS
    
	DllCall(NumGet(VTBL + SetFolder, "UPtr"), "Ptr", FileDialog, "Ptr", GetShellItem(pItem := StartFolder), "UInt")  
	ObjRelease(pItem)
	
	if (fde) {
		DllCall(NumGet(NumGet(FileDialog+0)+7*A_PtrSize), "Ptr", FileDialog, "Ptr", fde, "UInt*", dwCookie := 0)
	}

	showSucceeded := DllCall(NumGet(VTBL + Show, "UPtr"), "Ptr", FileDialog, "Ptr", 0) >= 0

	if (dwCookie)
		DllCall(NumGet(NumGet(FileDialog+0)+8*A_PtrSize), "Ptr", FileDialog, "UInt", dwCookie)

   If (showSucceeded) {
	   If !DllCall(NumGet(VTBL + GetResult, "UPtr"), "Ptr", FileDialog, "PtrP", ShellItem, "UInt") {
         GetDisplayName := NumGet(NumGet(ShellItem + 0, "UPtr"), A_PtrSize * 5, "UPtr")
         If !DllCall(GetDisplayName, "Ptr", ShellItem, "UInt", 0x80028000, "PtrP", StrPtr) ; SIGDN_DESKTOPABSOLUTEPARSING
            SelectedFolder := StrGet(StrPtr, "UTF-16"), DllCall("Ole32.dll\CoTaskMemFree", "Ptr", StrPtr)
         ObjRelease(ShellItem)
      }
   }

   ObjRelease(FileDialog)
   Return SelectedFolder
}

GetShellItem(Item) {
   VarSetCapacity(IID, 16, 0)
   DllCall("Ole32.dll\IIDFromString", "WStr", "{43826d1e-e718-42ee-bc55-a1e261c37bfe}", "Ptr", &IID, "UInt")
   DllCall("Shell32.dll\SHCreateItemFromParsingName", "WStr", Item, "Ptr", 0, "Ptr", &IID, "PtrP", pShellItem, "UInt")
   Return pShellItem
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

35

Re: AHK: Окно проводника

serzh82saratov пишет:

Про настройки видов пока ничего.

Ну как же ничего.
Из ссылки из второго поста:

try if ((FileDialogCustomize := ComObjQuery(FileDialog, "{e6fdd21a-163f-4975-9c8c-a69f1ba37034}"))) {

36

Re: AHK: Окно проводника

Спасибо.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

37

Re: AHK: Окно проводника

https://www.autohotkey.com/boards/viewt … 36#p231879
Тут все опции расписаны, осталось всё в кучу собрать.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui