Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Перехват F4 в проводнике Windows для открытия выделенного файла в заданном редакторе (http://forum.oszone.net/showthread.php?t=213094)

Vadikan 12-08-2011 00:35 1730209

Перехват F4 в проводнике Windows для открытия выделенного файла в заданном редакторе
 
Привет, коллеги!

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

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

Возможно?

Спасибо!

madmasles 13-08-2011 09:30 1730929

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

Yashied 13-08-2011 13:24 1731010

Вложений: 1
Код:

#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 1731048

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 1731441

Я использую в основном (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 1731610

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

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


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

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

madmasles 14-08-2011 16:42 1731629

Цитата:

Цитата Vadikan
Впрочем, насчет #4 я не очень понял »

Я имел в виду - надо ли открывать выделенную папку.

Vadikan 14-08-2011 23:14 1731866

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

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


Время: 11:05.

Время: 11:05.
© OSzone.net 2001-