Что нового

Диалоговое окно для CMD

lorents

Новичок
Сообщения
82
Репутация
1
Добрый вечер!
есть скрипт для открытия диалоговых окон из окна cmd - DlgMsgBox. Автор скрипта - madmasles (скрипт был создан специально для меня, и за это благодарю madmasles). К сожалению, у madmasles нет времени поддерживать скрипт, и хотел, может ли кто-нибудь его изменить?

В текущей версии, скрипт сам определяет из какого окна cmd его запустили. Проблема в том, что из-за особенностей работы cmd, скрипт не определяет окно cmd.

Например:
Код:
for /f "tokens=* delims=" %%a in ('dlgmsgbox "Folder3" "Image Catalyst" "Выберите каталог для выходных файлов:"') do set "outdir=%%~a"

Хотел попросить сделать так, чтобы:
1. скрипт сам не определял окна запуска cmd
2 добавить параметры командной строки, чтобы я мог сам указать или заголовок окна cmd, или его pid. Например:
dlgmsgbox "-name:Image Catalyst"
dlgmsgbox "-pid:1025"

http://dl.dropbox.com/u/26599219/DlgMsgBox.7z

Проект dlgmsgbox используется, как часть проекта Image Catalyst

Код:
#NoTrayIcon

Opt('MustDeclareVars', 1)
Opt('WinWaitDelay', 0)
Opt('WinTitleMatchMode', 2)

Global $iNo_Encoding, $sWhatDo, $sTitleBox, $sTextBox, $sFlagMsg, $iTimeMsg, $hWinCMD, _
		$aPosCMD, $iNoErrorCMD, $iOption

If $CmdLine[0] And StringInStr($CmdLine[1], 'help') Then
	If Not FileInstall('Help.txt', @TempDir & '\Help.txt', 1) Then Exit 100
	ShellExecuteWait(@TempDir & '\Help.txt')
	FileDelete(@TempDir & '\Help.txt')
	Exit
EndIf
If $CmdLine[0] < 3 Then _ConsoleWrite(-1)
For $i = 1 To 3
	If StringIsSpace($CmdLine[$i]) Then _ConsoleWrite(-1)
Next

$sWhatDo = $CmdLine[1]
$iNo_Encoding = Int(StringLeft($sWhatDo, 1))
If $iNo_Encoding Then $sWhatDo = StringTrimLeft($sWhatDo, 1)
$iOption = Int(StringRight($sWhatDo, 1))
If Not $iOption Or $iOption > 3 Then $iOption = 2
$sWhatDo = StringTrimRight($sWhatDo, 1)
$sTitleBox = $CmdLine[2]
$sTextBox = $CmdLine[3]
_CMD_Info($hWinCMD, $aPosCMD, $iNoErrorCMD)
Switch $sWhatDo
	Case 'Folder'
		_FolderDlg()
	Case 'File'
		_FileDlg()
	Case 'Msg'
		_MsgBox()
	Case Else
		_ConsoleWrite(-1)
EndSwitch

#region Func
Func _MsgBox()
	Local $i_Flag = 0, $i_Return, $i_TimeOut = 0, $s_Text, $a_Temp
	Switch $CmdLine[0]
		Case 4
			_GetFlagMsg($i_Flag)
		Case 5
			_GetFlagMsg($i_Flag)
			$i_TimeOut = Abs(Int($CmdLine[5]))
	EndSwitch
	If StringInStr($sTextBox, '|') Then
		$a_Temp = StringSplit($sTextBox, '|')
		For $i = 1 To $a_Temp[0]
			$s_Text &= $a_Temp[$i] & @CRLF
		Next
		$s_Text = StringTrimRight($s_Text, 2)
	Else
		$s_Text = $sTextBox
	EndIf
	If $iNoErrorCMD Then
		_ExecuteScript(3)
		Sleep(500)
	EndIf
	$i_Return = MsgBox($i_Flag, $sTitleBox, $s_Text, $i_TimeOut, $hWinCMD)
	If $i_Return Then
		_ConsoleWrite(0, $i_Return)
	Else
		_ConsoleWrite(3)
	EndIf
EndFunc   ;==>_MsgBox

Func _GetFlagMsg(ByRef $i_Flag)
	Local $s_Ico = StringLeft($CmdLine[4], 1), $i_Button = Int(StringRight($CmdLine[4], 1))
	If $i_Button > 6 Then $i_Button = 0
	Switch $s_Ico
		Case 'S'
			$i_Flag += 16
		Case 'Q'
			$i_Flag += 32
		Case 'E'
			$i_Flag += 48
		Case 'I'
			$i_Flag += 64
	EndSwitch
	Switch $iOption
		Case 2
			$i_Flag += 256
		Case 3
			$i_Flag += 512
	EndSwitch
	$i_Flag += $i_Button
EndFunc   ;==>_GetFlagMsg

Func _FileDlg()
	Local $s_Path, $a_Temp, $s_InitDir = @DesktopDir & '\'
	If $iNoErrorCMD Then
		_ExecuteScript(2)
		Sleep(200)
	EndIf
	If $iOption = 1 Then $s_InitDir = @MyDocumentsDir & '\'
	$s_Path = FileOpenDialog($sTitleBox, $s_InitDir, $sTextBox, 5, '', $hWinCMD)
	If @error Or Not $s_Path Then _ConsoleWrite(2)
	If StringInStr($s_Path, '|') Then
		$a_Temp = StringSplit($s_Path, '|')
		$s_Path = ''
		For $i = 2 To $a_Temp[0]
			$s_Path &= '"' & $a_Temp[1] & '\' & $a_Temp[$i] & '"' & @CRLF
		Next
		$s_Path = StringTrimRight($s_Path, 2)
	Else
		$s_Path = '"' & $s_Path & '"'
	EndIf
	_ConsoleWrite(0, $s_Path)
EndFunc   ;==>_FileDlg

Func _FolderDlg()
	;From APIConstants.au3
	Local Const $_BIF_NEWDIALOGSTYLE = 0x00000040
	Local Const $_BIF_RETURNONLYFSDIRS = 0x00000001
	Local Const $_BIF_EDITBOX = 0x00000010
	Local Const $_BIF_VALIDATE = 0x00000020

	Local $i_Flag = BitOR($_BIF_NEWDIALOGSTYLE, $_BIF_RETURNONLYFSDIRS, $_BIF_EDITBOX, $_BIF_VALIDATE), _
			$s_Path, $h_BrowseProc, $p_BrowseProc
	If $iOption <> 2 Then
		If $iNoErrorCMD Then
			_ExecuteScript(1)
			Sleep(200)
		EndIf
	EndIf
	$h_BrowseProc = DllCallbackRegister('_BrowseProc', 'int', 'hwnd;uint;long;ptr')
	$p_BrowseProc = DllCallbackGetPtr($h_BrowseProc)
	$s_Path = _WinAPI_BrowseForFolderDlg(@DesktopDir, $sTextBox, $i_Flag, $p_BrowseProc, '', $hWinCMD)
	DllCallbackFree($h_BrowseProc)
	If Not StringInStr(FileGetAttrib($s_Path), 'd') Then _ConsoleWrite(1)
	_ConsoleWrite(0, '"' & $s_Path & '"')
EndFunc   ;==>_FolderDlg

Func _BrowseProc($h_Wnd, $i_Msg, $w_Param, $l_Param)
	;From APIConstants.au3
	Local Const $_BFFM_INITIALIZED = 1
	Local $i_X, $i_Y, $h_Button
	If $i_Msg = $_BFFM_INITIALIZED Then
		WinSetTitle($h_Wnd, '', $sTitleBox)
		_CalculateMove($i_X, $i_Y, $h_Wnd)
		If Not @error Then
			WinMove($h_Wnd, '', $i_X, $i_Y)
		EndIf
	EndIf
	Return 0
EndFunc   ;==>_BrowseProc

Func _CMD_Info(ByRef $hWinCMD, ByRef $aPosCMD, ByRef $iNoErrorCMD)
	Local $s_TitleCMD = '[Class:ConsoleWindowClass]', $a_ListCMD, $i_PID_CMD
	$i_PID_CMD = _WinAPI_GetParentProcess()
	If @error Then
		$iNoErrorCMD = 0
		Return
	EndIf
	$a_ListCMD = WinList($s_TitleCMD)
	If Not IsArray($a_ListCMD) Or Not $a_ListCMD[0][0] Then
		$iNoErrorCMD = 0
		Return
	EndIf
	For $i = 1 To $a_ListCMD[0][0]
		If WinGetProcess($a_ListCMD[$i][1]) = $i_PID_CMD Then
			$hWinCMD = $a_ListCMD[$i][1]
			ExitLoop
		EndIf
	Next
	If $hWinCMD Then
		$iNoErrorCMD = 1
		$aPosCMD = WinGetPos($hWinCMD)
		If @error Or UBound($aPosCMD) <> 4 Then
			$iNoErrorCMD = 0
		Else
			$iNoErrorCMD = 1
		EndIf
	Else
		$iNoErrorCMD = 0
	EndIf
EndFunc   ;==>_CMD_Info

Func _ExecuteScript($i_Index)
	Local $s_TempFile, $h_File
	Local $s_ScriptText = "#NoTrayIcon" & @CRLF & "Opt('WinWaitDelay',0)" & @CRLF & _
			"Opt('WinTitleMatchMode',2)" & @CRLF & "$hWinCMD=HWnd(" & $hWinCMD & ")" & @CRLF & _
			"If Not $hWinCMD Then Exit" & @CRLF & "$h_Win=WinWait('[Title:" & $sTitleBox & ";Class:#32770]','',5)" & @CRLF & _
			"If Not $h_Win Then Exit" & @CRLF & "$h_Win=0" & @CRLF & "For $j=1 To 250" & @CRLF & _
			"$a_List=WinList('[Title:" & $sTitleBox & ";Class:#32770]')" & @CRLF & _
			"If Not IsArray($a_List) Or Not $a_List[0][0] Then ExitLoop" & @CRLF & _
			"For $i=1 To $a_List[0][0]" & @CRLF & "If _WinAPI_GetParent($a_List[$i][1])=$hWinCMD Then" & @CRLF & _
			"$h_Win=$a_List[$i][1]" & @CRLF & "ExitLoop 2" & @CRLF & "EndIf" & @CRLF & _
			"Next" & @CRLF & "Sleep(2)" & @CRLF & "Next" & @CRLF & "If Not $h_Win Then Exit" & @CRLF
	Switch $i_Index
		Case 1
			$s_ScriptText &= "$h_Button=ControlGetHandle($h_Win,'','[CLASS:Button;INSTANCE:" & $iOption & "]')" & @CRLF & _
					"If Not $h_Button Then Exit" & @CRLF & "ControlFocus($h_Win,'',$h_Button)" & @CRLF & _
					"DllCall('user32.dll','none','SendMessageW','hwnd',$h_Button,'uint',0xF4,'wparam',0x0001,'lparam',True)" & @CRLF & _
					"DllCall('user32.dll','none','UpdateWindow','hwnd',$h_Button)" & @CRLF & "Exit"
		Case 2
			$s_ScriptText &= "$a_PosWin=WinGetPos($h_Win)" & @CRLF & "If @error Or UBound($a_PosWin)<>4 Then Exit" & @CRLF & _
					"WinMove($h_Win,''," & $aPosCMD[0] & "+(" & $aPosCMD[2] & "-$a_PosWin[2])/2," & $aPosCMD[1] & ")" & @CRLF & "Exit"
		Case 3
			$s_ScriptText &= "WinSetState($h_Win,'',@SW_HIDE)" & @CRLF & "$a_PosWin=WinGetPos($h_Win)" & @CRLF & _
					"If @error Or UBound($a_PosWin)<>4 Then" & @CRLF & "WinSetState($h_Win,'',@SW_SHOW)" & @CRLF & "Exit" & @CRLF & _
					"EndIf" & @CRLF & "WinMove($h_Win,''," & $aPosCMD[0] & "+(" & $aPosCMD[2] & "-$a_PosWin[2])/2," & _
					$aPosCMD[1] & "+(" & $aPosCMD[3] & "-$a_PosWin[3])/2)" & @CRLF & "WinSetState($h_Win,'',@SW_SHOW)" & @CRLF & "Exit"
	EndSwitch
	$s_ScriptText &= @CRLF & "Func _WinAPI_GetParent($hWnd)" & @CRLF & "Local $aResult = DllCall('user32.dll', 'hwnd', 'GetParent', 'hwnd', $hWnd)" & @CRLF & _
			"If @error Then Return SetError(@error, @extended, 0)" & @CRLF & "Return $aResult[0]" & @CRLF & "EndFunc"
	Do
		$s_TempFile = ''
		For $i = 1 To 5
			$s_TempFile &= Chr(Random(48, 57, 1))
		Next
		$s_TempFile = @TempDir & '\~' & $s_TempFile & '.dmb'
	Until Not FileExists($s_TempFile)
	$h_File = FileOpen($s_TempFile, 2)
	FileWrite($h_File, $s_ScriptText)
	FileClose($h_File)
	Run('"' & @AutoItExe & '" /AutoIt3ExecuteScript "' & $s_TempFile & '"')
EndFunc   ;==>_ExecuteScript

Func _CalculateMove(ByRef $i_X, ByRef $i_Y, $h_Wnd)
	Local $a_PoshWnd = WinGetPos($h_Wnd)
	If @error Or UBound($a_PoshWnd) <> 4 Then Return SetError(1)
	If $iNoErrorCMD Then
		$i_X = $aPosCMD[0] + ($aPosCMD[2] - $a_PoshWnd[2]) / 2
		$i_Y = $aPosCMD[1]
	Else
		$i_X = (@DesktopWidth - $a_PoshWnd[2]) / 2
		$i_Y = (@DesktopHeight - $a_PoshWnd[3]) / 2
	EndIf
EndFunc   ;==>_CalculateMove

Func _ConsoleWrite($i_Exit, $s_Text = '')
	If Not $i_Exit Then
		If Not $iNo_Encoding Then
			$s_Text = _Encoding_ANSIToOEM($s_Text)
		EndIf
		ConsoleWrite($s_Text)
	EndIf
	FileDelete(@TempDir & '\*.dmb')
	Exit $i_Exit
EndFunc   ;==>_ConsoleWrite
#endregion Func

#region From Encoding.au3
;http://autoit-script.ru/index.php/topic,510.0.html
Func _Encoding_ANSIToOEM($strText)
	Local $sBuffer = DllStructCreate('char[' & StringLen($strText) + 1 & ']')
	Local $aRet = DllCall('User32.dll', 'int', 'CharToOem', 'str', $strText, 'ptr', DllStructGetPtr($sBuffer))
	If Not IsArray($aRet) Then Return SetError(1, 0, '')
	If $aRet[0] = 0 Then Return SetError(2, $aRet[0], '')
	Return DllStructGetData($sBuffer, 1)
EndFunc   ;==>_Encoding_ANSIToOEM
#endregion From Encoding.au3

#region From WinAPIEx.au3
;http://autoit-script.ru/index.php/topic,47.0.html
Func _WinAPI_BrowseForFolderDlg($sRoot = '', $sText = '', $iFlags = 0, $pBrowseProc = 0, $lParam = 0, $hParent = 0)
	Local $tBROWSEINFO = DllStructCreate('hwnd;ptr;ptr;ptr;int;ptr;uint_ptr;int;wchar[' & (StringLen($sText) + 1) & '];wchar[260]')
	Local $PIDL = 0, $Path, $Result = ''
	If StringStripWS($sRoot, 3) Then
		$Path = _WinAPI_PathSearchAndQualify($sRoot, 1)
		If @error Then
			$Path = $sRoot
		EndIf
		$PIDL = _WinAPI_ShellILCreateFromPath($Path)
		If @error Then
		EndIf
	EndIf
	DllStructSetData($tBROWSEINFO, 1, $hParent)
	DllStructSetData($tBROWSEINFO, 2, $PIDL)
	DllStructSetData($tBROWSEINFO, 3, DllStructGetPtr($tBROWSEINFO, 10))
	DllStructSetData($tBROWSEINFO, 4, DllStructGetPtr($tBROWSEINFO, 9))
	DllStructSetData($tBROWSEINFO, 5, $iFlags)
	DllStructSetData($tBROWSEINFO, 6, $pBrowseProc)
	DllStructSetData($tBROWSEINFO, 7, $lParam)
	DllStructSetData($tBROWSEINFO, 8, 0)
	DllStructSetData($tBROWSEINFO, 9, $sText)
	Local $Ret = DllCall('shell32.dll', 'ptr', 'SHBrowseForFolderW', 'ptr', DllStructGetPtr($tBROWSEINFO))
	If @error Then
		Return SetError(1, 0, '')
	Else
		If Not $Ret[0] Then
			Return ''
		EndIf
	EndIf
	$Result = _WinAPI_ShellGetPathFromIDList($Ret[0])
	_WinAPI_CoTaskMemFree($Ret[0])
	If $PIDL Then
		_WinAPI_CoTaskMemFree($PIDL)
	EndIf
	If Not $Result Then
		Return SetError(1, 0, '')
	EndIf
	Return $Result
EndFunc   ;==>_WinAPI_BrowseForFolderDlg

Func _WinAPI_CoTaskMemFree($hMemory)
	DllCall('ole32.dll', 'int', 'CoTaskMemFree', 'ptr', $hMemory)
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	Return 1
EndFunc   ;==>_WinAPI_CoTaskMemFree

Func _WinAPI_PathSearchAndQualify($sPath, $fExists = 0)
	Local $Ret = DllCall('shlwapi.dll', 'int', 'PathSearchAndQualifyW', 'wstr', $sPath, 'wstr', '', 'int', 4096)
	If (@error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, '')
	EndIf
	If ($fExists) And (Not FileExists($Ret[2])) Then
		Return SetError(2, 0, '')
	EndIf
	Return $Ret[2]
EndFunc   ;==>_WinAPI_PathSearchAndQualify

Func _WinAPI_ShellGetPathFromIDList($PIDL)
	Local $Ret = DllCall('shell32.dll', 'int', 'SHGetPathFromIDListW', 'ptr', $PIDL, 'wstr', '')
	If (@error) Or (Not $Ret[0]) Then
		Return SetError(1, 0, '')
	EndIf
	Return $Ret[2]
EndFunc   ;==>_WinAPI_ShellGetPathFromIDList

Func _WinAPI_ShellILCreateFromPath($sPath)
	Local $Ret = DllCall('shell32.dll', 'uint', 'SHILCreateFromPath', 'wstr', $sPath, 'ptr*', 0, 'dword*', 0)
	If @error Then
		Return SetError(1, 0, 0)
	Else
		If $Ret[0] Then
			Return SetError(1, $Ret[0], 0)
		EndIf
	EndIf
	Return $Ret[2]
EndFunc   ;==>_WinAPI_ShellILCreateFromPath

Func _WinAPI_GetParentProcess($PID = 0)
	If Not $PID Then
		$PID = @AutoItPID
	EndIf
	Local $hSnapshot = DllCall('kernel32.dll', 'ptr', 'CreateToolhelp32Snapshot', 'dword', 0x00000002, 'dword', 0)
	If (@error) Or (Not $hSnapshot[0]) Then
		Return SetError(1, 0, 0)
	EndIf
	Local $tPROCESSENTRY32 = DllStructCreate('dword Size;dword Usage;dword ProcessID;ulong_ptr DefaultHeapID;dword ModuleID;dword Threads;dword ParentProcessID;long PriClassBase;dword Flags;wchar ExeFile[260]')
	Local $pPROCESSENTRY32 = DllStructGetPtr($tPROCESSENTRY32)
	Local $Ret, $Result = 0
	$hSnapshot = $hSnapshot[0]
	DllStructSetData($tPROCESSENTRY32, 'Size', DllStructGetSize($tPROCESSENTRY32))
	$Ret = DllCall('kernel32.dll', 'int', 'Process32FirstW', 'ptr', $hSnapshot, 'ptr', $pPROCESSENTRY32)
	While (Not @error) And ($Ret[0])
		If DllStructGetData($tPROCESSENTRY32, 'ProcessID') = $PID Then
			$Result = DllStructGetData($tPROCESSENTRY32, 'ParentProcessID')
			ExitLoop
		EndIf
		$Ret = DllCall('kernel32.dll', 'int', 'Process32NextW', 'ptr', $hSnapshot, 'ptr', $pPROCESSENTRY32)
	WEnd
	_WinAPI_CloseHandle($hSnapshot)
	If Not $Result Then
		Return SetError(1, 0, 0)
	EndIf
	Return $Result
EndFunc   ;==>_WinAPI_GetParentProcess
#endregion From WinAPIEx.au3

#region From WinAPI.au3
Func _WinAPI_CloseHandle($hObject)
	Local $aResult = DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hObject)
	If @error Then Return SetError(@error, @extended, False)
	Return $aResult[0]
EndFunc   ;==>_WinAPI_CloseHandle
#endregion From WinAPI.au3
 
Автор
L

lorents

Новичок
Сообщения
82
Репутация
1
Хотел еще обратится, может кто поможет с реализацией вышеописанной функцией, буду очень признателен?
 
Автор
L

lorents

Новичок
Сообщения
82
Репутация
1
Добрый день!
Подскажите, пожалуйста, что надо изменить, чтобы DlgMsgBox из какого окна cmd его запустили?

Я хочу сделать так, чтобы сам batch передавал ему значения pid.

Код:
@echo off
set "name=Image Catalyst"
title %name%
for /f "tokens=1,2" %%a in ('tasklist /v ^| findstr /c:"%name%" 2^>nul') do set "pid=%%b"
echo.%pid%
pause

Всех С Новым Годом!


Добавлено:
Сообщение автоматически объединено:

Подскажите, пожалуйста, как можно ускорить скорость запуска приложения?
 
Верх