windowswindows-xpautoitwindows-xp-sp3

Create new folder and highlight it for renaming


I was trying to create an AutoIt script to create a new folder and then highlight it for renaming like if we right click and create a new folder.

Here is my script. What I wanted to achieve is create the new folder, highlight it, then press F2.

#include <WinAPI.au3>

HotKeySet("#y", "NewFolder")

While 1
    Sleep(200)
WEnd

Func NewFolder()
    Local $hWnd = WinGetHandle("[ACTIVE]")
    Local $class = _WinAPI_GetClassName($hWnd)
    If StringCompare($class, "CabinetWClass") = 0 Then
        Local $sSelected_Path = _GetWindowsExplorerPath($hWnd) & "\NewFolder" & $count
        Local $iFileExists = FileExists($sSelected_Path)
        If $iFileExists Then
            $count += 1
        Else
            Local $success = DirCreate($sSelected_Path)
            Sleep(500)
            If $success = 1 Then
                Local $Finditem = ControlListView($hWnd, "", "[CLASS:SysListView32; INSTANCE:1]", "Finditem", "NewFolder")
                MsgBox(0, "", $Finditem)
                Local $Select = ControlListView($hWnd, "", "[CLASS:SysListView32; INSTANCE:1]", "Select", $Finditem)
                $count += 1
            EndIf
        EndIf
    EndIf
EndFunc

Func _GetWindowsExplorerPath($hWnd)
    Local $pv, $pidl, $return = "", $ret, $hMem, $pid, $folderPath = DllStructCreate("char[260]"), $className
    Local $bPIDL = False
    Local Const $CWM_GETPATH = 0x400 + 12;

    ; Check the classname of the window first
    $className = DllCall("user32.dll", "int", "GetClassName", "hwnd", $hWnd, "str", "", "int", 4096)
    If @error Then Return SetError(2, 0, "")
    If ($className[2] <> "ExploreWClass" And $className[2] <> "CabinetWClass") Then Return SetError(1, 0, "")

    ; Retrieve the process ID for our process
    $pid = DllCall("kernel32.dll", "int", "GetCurrentProcessId")
    If @error Then Return SetError(2, 0, "")

    ; Send the CWM_GETPATH message to the window
    $hMem = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $CWM_GETPATH, "wparam", $pid[0], "lparam", 0)
    If @error Then Return SetError(2, 0, "")
    If $hMem[0] = 0 Then Return SetError(1, 0, "")

    ; Lock the shared memory
    $pv = DllCall("shell32.dll", "ptr", "SHLockShared", "uint", $hMem[0], "uint", $pid[0])
    If @error Then Return SetError(2, 0, "")
    If $pv[0] Then
        $pidl = DllCall("shell32.dll", "ptr", "ILClone", "uint", $pv[0]) ; Clone the PIDL
        If @error Then Return SetError(2, 0, "")
        $bPIDL = True
        DllCall("shell32.dll", "int", "SHUnlockShared", "uint", $pv) ; Unlock the shared memory
    EndIf
    DllCall("shell32.dll", "int", "SHFreeShared", "uint", $hMem, "uint", $pid) ; Free the shared memory

    If $bPIDL Then
        ; Retrieve the path from the PIDL
        $ret = DllCall("shell32.dll", "int", "SHGetPathFromIDList", "ptr", $pidl[0], "ptr", DllStructGetPtr($folderPath))
        If (@error = 0) And ($ret[0] <> 0) Then $return = DllStructGetData($folderPath, 1) ; Retrieve the value
        DllCall("shell32.dll", "none", "ILFree", "ptr", $pidl[0]) ; Free up the PIDL that we cloned
        Return SetError(0, 0, $return) ; Success
    EndIf

    Return SetError(2, 0, "") ; Failed a WinAPI call
EndFunc

Solution

  • This works for me in Win7 - should work in xp as long as address bar is turned on. MUCH simpler than using the DLL calls. I left you a little bit of work to do :)

    HotKeySet("#y","_NewFolder")
    HotKeySet("#n","_EXIT")
    
    While 1
        Sleep(250)
    WEnd    
    
    FUNC _NewFolder() ; make all vars local
    $TEXT = WinGetText("[active]")
    ; handle error here
    $SPLIT = StringSplit($TEXT,@CR & @LF & @CRLF) ;split on new lines (idk which one of the three it uses)
    IF IsArray($SPLIT) Then
        ; trigger = true
        FOR $I = 1 to $SPLIT[0]
            IF StringInStr($SPLIT[$i],"Address: ") Then
                ; trigger = false
                $STRING = StringReplace($SPLIT[$i],"Address: ","")
                $INPUT = InputBox("New Folder","Name your new folder")
                ; add some enforcement to input box, i like do until loops
                $PATH = $STRING & "\" & $INPUT
                $CREATE = DirCreate($PATH)
                ; handle error here
                Return SetError(0,0,$PATH)
            EndIf
        Next
        ; if trigger then error
    Else
        Return SetError(1,0,0) ;if split is not an array - could add some more here in case address is the only line returned
    EndIf
    EndFunc
    
    Func _Exit()
        Exit
    EndFunc