PDA

Показать полную графическую версию : [решено] Перехват F4 в проводнике Windows для открытия выделенного файла в заданном редакторе


Vadikan
12-08-2011, 00:35
Привет, коллеги!

Прошу прощения за потребительский подход, но если у кого-то возникнет желание нарисовать скрипт, я буду признателен :)

Total Commander по F4 стандартно открывает выделенный файл в указанном текстовом редакторе. Хочется тоже самое получить в проводнике Windows 7. Для примера пойдет notepad.

Возможно?

Спасибо!

madmasles
13-08-2011, 09:30
Vadikan,
1. А если выделено более одного файла, то что должен делать скрипт в этом случае?
2. Как я понимаю, работать скрипт должен только для активного окна проводника?
3. Открывать выделенный файл скрипт должен независимо от его расширения в блокноте или программой по умолчанию?
4. Если программой по умолчанию, то надо ли обрабатывать выделенную папку?

Yashied
13-08-2011, 13:24
#AutoIt3Wrapper_Icon=F4.ico

#NoTrayIcon

#Include <HotKey.au3>
#Include <Misc.au3>

Opt('TrayMenuMode', 3)

_Singleton('F42Notepad')

_HotKeyAssign(0x73, '_F4', -1, '[REGEXPCLASS:(Explore|Cabinet)WClass]')

$Exit = TrayCreateItem('Exit')
TraySetIcon(@ScriptFullPath)
TraySetToolTip('F42Notepad')

While 1
Switch TrayGetMsg()
Case $Exit
Exit
EndSwitch
WEnd

Func _F4()

Local $aList = _WindowsExplorer_ExtractSelectedDirAndFiles(WinGetHandle(''))

If Not @error Then
For $i = 2 To $aList[0] + 1
If Not StringInStr(FileGetAttrib($aList[$i]), 'D') Then
Run(@SystemDir & '\Notepad.exe "' & $aList[$i] & '"')
EndIf
Next
EndIf
EndFunc ;==>_F4

; ==================================================================================================== ===============
; Name...........: _WindowsExplorer_ExtractSelectedDirAndFiles
; Description....: Function to extract LocationURL and selected files from a "Windows Explorer" Window
; Syntax.........: _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd)
; Parameters.....: $hWnd - Windows handle of an "Windows Explorer" Window
; AutoIt Version.: 3.3.6.1
; Return values..: Success - Array
; Array[0] = Number of files selected in right-hand Listview
; Array[1] = LocationURL - selected in left-hand Treeview or Window Rebar
; Array[2] - Array[n] = URL of selected files in right-hand Listview
; Failure - Array
; Array[0] = 0
; Array[1] = ""
; Sets the @error flag to non-zero.
; @error = 1 - $hwnd is not a valid window handle
; @error = 2 - $hwnd is not a window handle for an "Windows Explorer" Window
; @error = 3 - "Shell.Application" object could not be created
; @error = 4 - "$oShellApp.Windows()" object could not be created
; Author.........: Ascend4nt, KaFu, klaus.s
; ==================================================================================================== ===============

Func _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd, $oError = 0)
Local $aExplorerSelectedFiles[2] = [0, ""]
If Not IsHWnd($hWnd) Then Return SetError(1, 0, $aExplorerSelectedFiles)
Local $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")
While 1
For $i = 1 To UBound($aWinList) - 1
If $hWnd = $aWinList[$i][1] Then ExitLoop 2
Next
Return SetError(2, 0, $aExplorerSelectedFiles)
WEnd
If Not IsObj($oError) And Not ObjEvent("AutoIt.Error") Then $oError = ObjEvent("AutoIt.Error", "_WindowsExplorer_ExtractSelectedDirAndFiles")
Local $fErrorHandling = False
If IsObj($oError) Then $fErrorHandling = True
Local $oShellApp = ObjCreate("Shell.Application")
If Not IsObj($oShellApp) Then Return SetError(3, 0, $aExplorerSelectedFiles)
Local $oShellApp_Windows = $oShellApp.Windows()
If Not IsObj($oShellApp_Windows) Then Return SetError(4, 0, $aExplorerSelectedFiles)
For $oShellApp_Inst In $oShellApp_Windows
If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop
Next
Local $iShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.Document.SelectedItems.Count
If $fErrorHandling And $oError.number Then Return SetError(5, 0, $aExplorerSelectedFiles)
Local $sShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL
Local $aRet = DllCall('shlwapi.dll', 'long', 'PathCreateFromUrlW', 'wstr', $sShellApp_Inst_LocationURL, 'wstr', '', 'dword*', 65534, 'dword', 0)
If Not @error And $aRet[0] = 0 Then $sShellApp_Inst_LocationURL = $aRet[2]
$aExplorerSelectedFiles[0] = $iShellApp_Inst_SelectedItems_Count
$aExplorerSelectedFiles[1] = $sShellApp_Inst_LocationURL
ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]
Local $oShellApp_Inst_SelectedItems = $oShellApp_Inst.Document.SelectedItems
If $fErrorHandling And $oError.number Then Return SetError(6, 0, $aExplorerSelectedFiles)
Local $iCounter = 2
For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems
$aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path
$iCounter += 1
Next
Return $aExplorerSelectedFiles
EndFunc ;==>_WindowsExplorer_ExtractSelectedDirAndFiles

madmasles
13-08-2011, 14:34
Yashied,
Вы меня опередили. :)
Мой вариант (чуть-чуть отличается):#NoTrayIcon
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=icon.ico
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_Run_Obfuscator=y
#Obfuscator_Parameters=/striponly
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Obfuscator_Ignore_Funcs= _OpenWith, _WindowsExplorer_ExtractSelectedFiles, _Exit, _RegRun, _RegRunDel, _ScriptDestroy
#include <HotKey.au3>;Yashied, http://autoit-script.ru/index.php/topic,296.0.html
#include <WinAPIEx.au3>;Yashied, http://autoit-script.ru/index.php/topic,47.0.html
#include <File.au3>

Opt('MustDeclareVars', 1)

Global Const $VK_ESCAPE = 0x1B
Global Const $VK_F4 = 0x73
Global $sTitleScript = @ScriptName & '{[/@$@\]}'

If WinExists($sTitleScript) Then Exit
AutoItWinSetTitle($sTitleScript)
;ключи:
If $CmdLine[0] Then
Switch $CmdLine[1]
Case '-RunYes' ;поместить в автозагрузку текущего пользователя
_RegRun()
Case '-RunNo' ;удалить из автозагрузки текущего пользователя
_RegRunDel()
Case '-Del' ;удалить утилиту
_RegRunDel()
_ScriptDestroy()
EndSwitch
EndIf

_HotKeyAssign($VK_F4, '_OpenWith', $HK_FLAG_DEFAULT, '[REGEXPCLASS:(Explore|Cabinet)WClass]');F4
_HotKeyAssign(BitOR($CK_CONTROL, $CK_SHIFT, $VK_ESCAPE), '_Exit');Ctrl+Shift+Esc - выход
_WinAPI_EmptyWorkingSet()
While 1
Sleep(10)
WEnd

Func _Exit()
Exit
EndFunc ;==>_Exit

Func _OpenWith()
Local $h_Win_Handle, $a_List_Active, $s_Program = @WindowsDir & '\notepad.exe'
$h_Win_Handle = WinGetHandle('[ACTIVE]')
$a_List_Active = _WindowsExplorer_ExtractSelectedFiles($h_Win_Handle)
If Not @error And $a_List_Active[0] Then
For $i = 1 To $a_List_Active[0]
Run($s_Program & ' "' & $a_List_Active[$i] & '"')
Next
Else
_WinAPI_MessageBeep(2)
EndIf
_WinAPI_EmptyWorkingSet()
EndFunc ;==>_OpenWith

;trancexx, http://www.autoitscript.com/forum/topic/89833-windows-explorer-current-folder/page__view__findpost__p__875866
Func _WindowsExplorer_ExtractSelectedFiles($h_Wnd, $o_Error = 0)
Local $a_ExplorerSelectedFiles[1] = [0], $a_WinList, $f_ErrorHandling, $o_ShellApp, $o_ShellApp_Windows, _
$i_ShellApp_Inst_SelectedItems_Count, $o_ShellApp_Inst_SelectedItems, $i_Counter, $s_Path_Selected, _
$s_Attrib_Selected
If Not IsHWnd($h_Wnd) Then Return SetError(1, 0, $a_ExplorerSelectedFiles)
$a_WinList = WinList('[REGEXPCLASS:(Explore|Cabinet)WClass]')
While 1
For $i = 1 To UBound($a_WinList) - 1
If $h_Wnd = $a_WinList[$i][1] Then ExitLoop 2
Next
Return SetError(2, 0, $a_ExplorerSelectedFiles)
WEnd
If Not IsObj($o_Error) And Not ObjEvent('AutoIt.Error') Then $o_Error = ObjEvent('AutoIt.Error', '_WindowsExplorer_ExtractSelectedFiles')
If IsObj($o_Error) Then $f_ErrorHandling = True
$o_ShellApp = ObjCreate('Shell.Application')
If Not IsObj($o_ShellApp) Then Return SetError(3, 0, $a_ExplorerSelectedFiles)
$o_ShellApp_Windows = $o_ShellApp.Windows()
If Not IsObj($o_ShellApp_Windows) Then Return SetError(4, 0, $a_ExplorerSelectedFiles)
For $o_ShellApp_Inst In $o_ShellApp_Windows
If $o_ShellApp_Inst.hwnd = $h_Wnd Then ExitLoop
Next
$i_ShellApp_Inst_SelectedItems_Count = $o_ShellApp_Inst.Document.SelectedItems.Count
If $f_ErrorHandling And $o_Error.number Then Return SetError(5, 0, $a_ExplorerSelectedFiles)
$o_ShellApp_Inst_SelectedItems = $o_ShellApp_Inst.Document.SelectedItems
If $f_ErrorHandling And $o_Error.number Then Return SetError(6, 0, $a_ExplorerSelectedFiles)
For $o_ShellApp_Inst_SelectedItem In $o_ShellApp_Inst_SelectedItems
$s_Path_Selected = $o_ShellApp_Inst_SelectedItem.path
If $f_ErrorHandling And $o_Error.number Then Return SetError(7, 0, $a_ExplorerSelectedFiles)
$s_Attrib_Selected = FileGetAttrib($s_Path_Selected)
If Not StringInStr($s_Attrib_Selected, 'D') Then
$i_Counter += 1
ReDim $a_ExplorerSelectedFiles[$i_Counter + 1]
$a_ExplorerSelectedFiles[$i_Counter] = $s_Path_Selected
$a_ExplorerSelectedFiles[0] = $i_Counter
EndIf
Next
Return SetError(0, 0, $a_ExplorerSelectedFiles)
EndFunc ;==>_WindowsExplorer_ExtractSelectedFiles

Func _RegRun()
Local $s_RegRun = 'HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
If RegRead($s_RegRun, @ScriptName) = '' Or RegRead($s_RegRun, @ScriptName) <> '"' & @ScriptFullPath & '"' Then
RegWrite($s_RegRun, @ScriptName, 'REG_SZ', '"' & @ScriptFullPath & '"')
EndIf
EndFunc ;==>_RegRun

Func _RegRunDel()
Local $s_RegRun = 'HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
RegDelete($s_RegRun, @ScriptName)
EndFunc ;==>_RegRunDel

Func _ScriptDestroy()
Local $s_Temp, $s_Path, $s_Temp, $s_Text_Del, $h_File
$s_Temp = _TempFile(@TempDir, '~', '.bat')
$s_Path = FileGetShortName(@ScriptFullPath)
$s_Text_Del = '@echo off' & @CRLF & ':loop' & @CRLF & 'del ' & $s_Path & @CRLF & 'if exist ' & _
$s_Path & ' goto loop' & @CRLF & 'del ' & $s_Temp
$h_File = FileOpen($s_Temp, 2)
FileWrite($h_File, $s_Text_Del)
FileClose($h_File)
Run($s_Temp, '', @SW_HIDE)
Exit
EndFunc ;==>_ScriptDestroy

madmasles
14-08-2011, 11:15
Я использую в основном (90%) AkelPad, поэтому предлагаю вариант с F4 - AkelPad и Shift+F4 - notepad:#NoTrayIcon
#region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=icon.ico
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_Run_Obfuscator=y
#Obfuscator_Parameters=/striponly
#endregion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Obfuscator_Ignore_Funcs= _OpenWith, _WindowsExplorer_ExtractSelectedFiles, _Exit, _RegRun, _RegRunDel, _ScriptDestroy
#include <HotKey.au3>;Yashied, http://autoit-script.ru/index.php/topic,296.0.html
#include <WinAPIEx.au3>;Yashied, http://autoit-script.ru/index.php/topic,47.0.html
#include <File.au3>

Opt('MustDeclareVars', 1)

Global Const $VK_ESCAPE = 0x1B
Global Const $VK_F4 = 0x73
Global $sTitleScript = @ScriptName & '{[/@$@\]}'

If WinExists($sTitleScript) Then Exit
AutoItWinSetTitle($sTitleScript)
;ключи:
If $CmdLine[0] Then
Switch $CmdLine[1]
Case '-RunYes' ;поместить в автозагрузку текущего пользователя
_RegRun()
Case '-RunNo' ;удалить из автозагрузки текущего пользователя
_RegRunDel()
Case '-Del' ;удалить утилиту
_RegRunDel()
_ScriptDestroy()
EndSwitch
EndIf

_HotKeyAssign($VK_F4, '_OpenWith', BitOR($HK_FLAG_DEFAULT, $HK_FLAG_EXTENDEDCALL), _
'[REGEXPCLASS:(Explore|Cabinet)WClass]');F4 - AkelPad.exe
_HotKeyAssign(BitOR($CK_SHIFT, $VK_F4), '_OpenWith', BitOR($HK_FLAG_DEFAULT, $HK_FLAG_EXTENDEDCALL), _
'[REGEXPCLASS:(Explore|Cabinet)WClass]');Shift+F4 - notepad.exe
_HotKeyAssign(BitOR($CK_CONTROL, $CK_SHIFT, $VK_ESCAPE), '_Exit');Ctrl+Shift+Esc - выход
_WinAPI_EmptyWorkingSet()
While 1
Sleep(10)
WEnd

Func _Exit()
Exit
EndFunc ;==>_Exit

Func _OpenWith($iKey)
Local $a_List_Active, $s_Program
If BitAND($iKey, $CK_SHIFT) Then
$s_Program = '"' & @WindowsDir & '\notepad.exe"'
Else
$s_Program = '"' & @ProgramFilesDir & '\AkelPad\AkelPad.exe"'
EndIf
$a_List_Active = _WindowsExplorer_ExtractSelectedFiles()
If Not @error And $a_List_Active[0] Then
For $i = 1 To $a_List_Active[0]
Run($s_Program & ' "' & $a_List_Active[$i] & '"')
Next
Else
_WinAPI_MessageBeep(2)
EndIf
_WinAPI_EmptyWorkingSet()
EndFunc ;==>_OpenWith

;trancexx, http://www.autoitscript.com/forum/topic/89833-windows-explorer-current-folder/page__view__findpost__p__875866
Func _WindowsExplorer_ExtractSelectedFiles($o_Error = 0)
Local $a_ExplorerSelectedFiles[1] = [0], $h_Wnd, $a_WinList, $f_ErrorHandling, $o_ShellApp, $o_ShellApp_Windows, _
$i_ShellApp_Inst_SelectedItems_Count, $o_ShellApp_Inst_SelectedItems, $i_Counter, $s_Path_Selected, _
$s_Attrib_Selected
$a_WinList = WinList('[REGEXPCLASS:(Explore|Cabinet)WClass]')
While 1
For $i = 1 To UBound($a_WinList) - 1
If WinActive($a_WinList[$i][1]) Then
$h_Wnd = $a_WinList[$i][1]
ExitLoop 2
EndIf
Next
Return SetError(1)
WEnd
If Not IsObj($o_Error) And Not ObjEvent('AutoIt.Error') Then $o_Error = ObjEvent('AutoIt.Error', '_WindowsExplorer_ExtractSelectedFiles')
If IsObj($o_Error) Then $f_ErrorHandling = True
$o_ShellApp = ObjCreate('Shell.Application')
If Not IsObj($o_ShellApp) Then Return SetError(1)
$o_ShellApp_Windows = $o_ShellApp.Windows()
If Not IsObj($o_ShellApp_Windows) Then Return SetError(1)
For $o_ShellApp_Inst In $o_ShellApp_Windows
If $o_ShellApp_Inst.hwnd = $h_Wnd Then ExitLoop
If $f_ErrorHandling And $o_Error.number Then Return SetError(1)
Next
$i_ShellApp_Inst_SelectedItems_Count = $o_ShellApp_Inst.Document.SelectedItems.Count
If $f_ErrorHandling And $o_Error.number Then Return SetError(1)
ReDim $a_ExplorerSelectedFiles[$i_ShellApp_Inst_SelectedItems_Count + 1]
$o_ShellApp_Inst_SelectedItems = $o_ShellApp_Inst.Document.SelectedItems
If $f_ErrorHandling And $o_Error.number Then Return SetError(1)
For $o_ShellApp_Inst_SelectedItem In $o_ShellApp_Inst_SelectedItems
$s_Path_Selected = $o_ShellApp_Inst_SelectedItem.path
If $f_ErrorHandling And $o_Error.number Then Return SetError(1)
$s_Attrib_Selected = FileGetAttrib($s_Path_Selected)
If Not StringInStr($s_Attrib_Selected, 'D') Then
$i_Counter += 1
$a_ExplorerSelectedFiles[$i_Counter] = $s_Path_Selected
EndIf
Next
ReDim $a_ExplorerSelectedFiles[$i_Counter + 1]
$a_ExplorerSelectedFiles[0] = $i_Counter
Return SetError(0, 0, $a_ExplorerSelectedFiles)
EndFunc ;==>_WindowsExplorer_ExtractSelectedFiles

Func _RegRun()
Local $s_RegRun = 'HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
If RegRead($s_RegRun, @ScriptName) = '' Or RegRead($s_RegRun, @ScriptName) <> '"' & @ScriptFullPath & '"' Then
RegWrite($s_RegRun, @ScriptName, 'REG_SZ', '"' & @ScriptFullPath & '"')
EndIf
EndFunc ;==>_RegRun

Func _RegRunDel()
Local $s_RegRun = 'HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
RegDelete($s_RegRun, @ScriptName)
EndFunc ;==>_RegRunDel

Func _ScriptDestroy()
Local $s_Temp, $s_Path, $s_Temp, $s_Text_Del, $h_File
$s_Temp = _TempFile(@TempDir, '~', '.bat')
$s_Path = FileGetShortName(@ScriptFullPath)
$s_Text_Del = '@echo off' & @CRLF & ':loop' & @CRLF & 'del ' & $s_Path & @CRLF & 'if exist ' & _
$s_Path & ' goto loop' & @CRLF & 'del %0'
$h_File = FileOpen($s_Temp, 2)
FileWrite($h_File, $s_Text_Del)
FileClose($h_File)
Run($s_Temp, '', @SW_HIDE)
Exit
EndFunc ;==>_ScriptDestroy
В принципе, можно добавить редакторы еще и на Ctrl + F4, и на Win + F4, и на Alt + F4, и т.д.

Vadikan
14-08-2011, 16:18
О, а я-то поначалу подумал, что тишина в теме намекает на то, что мне надо сначала самому кривой скрипт написать хоть какой-нибудь :) Я, кстати, нагугливал HotKey на русском форуме autoit, но мне все равно не осилить такую задачу.

Yashied, madmasles, спасибо большое за варианты! Все работает!


madmasles, вы правильно ответили на все свои вопросы своим кодом :) Впрочем, насчет #4 я не очень понял - подразумевается открытие всех файлов в выделенной папке? Честно говоря, мне такое и не нужно даже.

Отдельное спасибо за вариант с SHIFT+F4! А Блокнот я привел для примера, у меня Notepad++ основной.

madmasles
14-08-2011, 16:42
Впрочем, насчет #4 я не очень понял »Я имел в виду - надо ли открывать выделенную папку.

Vadikan
14-08-2011, 23:14
madmasles, а как можно открыть папку в редакторе? Или просто открыть в проводнике - типа, не тупи, я тебе тут папку открыл уже? :)

Не, это не нужно. Я и так доволен!




© OSzone.net 2001-2012