Что нового

Как устроено окно консоли (CMD.exe)

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Решил посмотреть классы элементов консольного окна и заметил что в этом окне нет ни одного элемента, с помощью AutoIt Window Info навёл на заголовок окна, мне показало класс - ConsoleWindowClass, потом навёл на чёрный регион окна - думал что это Edit, оказалось нет, тоже ConsoleWindowClass, как тогда пишется текст в этом окне, вообще хочу полностью повторить консольное окно простым AutoIt'овским, говорить что можно скомпилитровать скрипт как Console - мне не надо, я это знаю

Этот вариант я попытался сделать с применением Edit
Код:
#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>
#Include <EditConstants.au3>
#Include <WinAPIEx.au3>

OnAutoItExitRegister('OnAutoItExit')

Global $BkColor = 0x000000
Global $TextColor = 0xC0C0C0
Global $hBitmap = CaretBitmap()
Global $Duration = Default

_WinAPI_SetThemeAppProperties(0)

$hForm = GUICreate('Командная строка', 669, 338, -1, -1, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS), $WS_EX_ACCEPTFILES)
$iSize = WinGetClientSize($hForm)
$iEdit = GUICtrlCreateEdit('', 0, 0, $iSize[0], $iSize[1], $WS_VSCROLL + 0x1000)
GUICtrlSetData($iEdit, CmdHeader())
GUICtrlSetBkColor($iEdit, $BkColor)
GUICtrlSetColor($iEdit, $TextColor)
GUICtrlSetFont($iEdit, 9, 500, 0, 'Terminal')
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			Switch _WinAPI_LoWord($wParam)
				Case $iEdit
					Switch _WinAPI_HiWord($wParam)
						Case $EN_KILLFOCUS
							_WinAPI_HideCaret($lParam)
							_WinAPI_DestroyCaret()
							_WinAPI_SetCaretBlinkTime($Duration)
							$Duration = Default
						Case $EN_SETFOCUS
							$Duration = _WinAPI_SetCaretBlinkTime(500)
							_WinAPI_CreateCaret($lParam, $hBitmap)
							_WinAPI_ShowCaret($lParam)
					EndSwitch
			EndSwitch
	EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func OnAutoItExit()
	_WinAPI_DeleteObject($hBitmap)
	If $Duration <> Default Then
		_WinAPI_SetCaretBlinkTime($Duration)
	EndIf
EndFunc

Func CaretBitmap()
	$hDC = _WinAPI_GetDC(0)
	$hDestDC = _WinAPI_CreateCompatibleDC($hDC)
	$hBitmap = _WinAPI_CreateCompatibleBitmapEx($hDC, 8, 12, $TextColor)
    $hDestSv = _WinAPI_SelectObject($hDestDC, $hBitmap)
	$hCaret = _WinAPI_CreateSolidBitmap(0, $BkColor, 8, 9)
	_WinAPI_DrawBitmap($hDestDC, 0, 0, $hCaret)
	_WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_SelectObject($hDestDC, $hDestSv)
    _WinAPI_DeleteDC($hDestDC)
	Return $hBitmap
EndFunc

Func CmdHeader()
	$Product = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'ProductName')
	$Version = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion')
	$Header = $Product & ' [Версия ' & $Version & '.' & @OSBuild & ']' & @CRLF & '(C) Корпорация Майкрософт, 1985-2012.' & @CRLF & @CRLF & @UserProfileDir & '>'
    Return _WinAPI_CharToOem($Header)
EndFunc

А вот этот полностью повторяет консоль, но не пойму как писать текст, как поставить каретку? :wacko:
Код:
#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>
#Include <EditConstants.au3>
#Include <WinAPIEx.au3>

Global $BkColor = 0x000000
Global $TextColor = 0xC0C0C0

_WinAPI_SetThemeAppProperties(0)

$hForm = GUICreate('Командная строка', 669, 338, -1, -1, BitOR($WS_SIZEBOX, $WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_VSCROLL), BitOR($WS_EX_CLIENTEDGE, $WS_EX_ACCEPTFILES))
GUISetBkColor($BkColor)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
В Windows любая программа (процесс) имеет хотя бы одно GUI, в противном случае это консольное приложение. Обычными методами с такими приложениями работать нельзя. Для более подробной информации ищите материал в сети. Запись и чтение данных в консольное приложение в AutoIt делается с помощью функций ConsoleWrite() и ConsoleRead() соответственно. Но можно и расширить список функций с помощью API.
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Сейчас поищу, но как тогда создаётся окно консоли :wacko: , наверное при компиляции консольного приложения пишется какая то метка чтоб система распознала что это консольное приложение и создаёт свое консольное окно?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Код:
#Region
#AutoIt3Wrapper_Change2CUI=y
#EndRegion

#NoTrayIcon

ConsoleWrite('This is console.' & @CRLF & @CRLF)
Sleep(1000)
Run(@ComSpec)

While 1
	Sleep(1000)
WEnd



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

Viktor1703 сказал(а):
...вообще хочу полностью повторить консольное окно...

Зачем? Вас не устраивает вид окна в XP? Вообще, есть хорошая замена (обертка) для cmd.exe - вот. Я ей тоже пользовался в XP.
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Это я понимаю, но хотелось сделать свою консоль со своими командами, не DOS'овскими, с Edit будет очень сложно, без Edit просто не возможно, в принципе можно и с Edit построить, но тогда опять же назревает проблема, как сделать часть текста чтоб стиралась по нажатию на Backspace, а часть нет... :wacko:

Обёртка меня устраивает, вобщем всё устраивает, только команды вводимые в мою консоль будут другие, не DOS
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А поиском воспользоваться...

*click*

Там есть все, что вам нужно.
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
Кстати в этой UDF где то ошибка, всё запускает работает, но при выходе пишет:

Код:
!<Console.au3>:
	Launching process on own...
+	CmdLine:"D:\Program Files\AutoIt3\autoit3.exe" "D:\Documents and Settings\Admin\Мои документы\Downloads\Example.au3" /Console=True

>	Example.au3 returned -1073741510 (0xC000013A)
!>22:12:14 AutoIT3.exe ended.rc:-1073741510
>Exit code: -1073741510    Time: 6.988



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

Нашёл исправленную чуть ниже, только почему автор не заменил в первом посте на рабочую :scratch:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Вот так я когда то пытался сделать нечто подобное (немного подправил):

Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <ScrollBarConstants.au3>
#include <WindowsConstants.au3>
#include <GUIEdit.au3>
#include <GUIMenu.au3>
#include <Misc.au3>
#include <File.au3>
#include <WinAPIEx.au3>

Opt("ExpandEnvStrings", 1)
Opt("ExpandVarStrings", 1)

Global $aSupported_Cmds = _GetCommandsArr(0)
Global $sApp_Title = "Console"
Global $sConsole_Font = "Courier New"
Global $sConsole_BkColor = 0x000000
Global $sConsole_TxtColor = 0xFFFFFF
Global $sConsole_InptTxtColor = 0xF3B214
Global $iGUI_W = 630
Global $iGUI_H = 400

_WinAPI_SetThemeAppProperties(0)

$hGUI = GUICreate($sApp_Title, $iGUI_W, $iGUI_H)
GUISetIcon( "shell32.dll", 42)

$nConsole_Edit = GUICtrlCreateEdit("" , 4, 4, $iGUI_W - 10, $iGUI_H - 25, BitOR($ES_READONLY, $WS_VSCROLL, $ES_AUTOHSCROLL), 0)
GUICtrlSetBkColor(-1, $sConsole_BkColor) 
GUICtrlSetFont(-1, 9, 400, 4, $sConsole_Font)
GUICtrlSetColor(-1, $sConsole_TxtColor)

$nDummy_Menu = GUICtrlCreateDummy()
$nContext_Menu = GUICtrlCreateContextMenu($nDummy_Menu)
$hContext_Menu = GUICtrlGetHandle($nContext_Menu)
$nCopy_MItem = GUICtrlCreateMenuItem("Copy", $nContext_Menu)
GUICtrlCreateMenuItem("", $nContext_Menu)
$nExit_MItem = GUICtrlCreateMenuItem("Exit", $nContext_Menu)

$nCommand_Input = GUICtrlCreateInput("", 4, $iGUI_H - 20, $iGUI_W - 10, 15, -1, 0)
GUICtrlSetBkColor(-1, $sConsole_BkColor)
GUICtrlSetFont(-1, 9, 400, 4, $sConsole_Font)
GUICtrlSetColor(-1, $sConsole_InptTxtColor)

$nSend_Bttn = GUICtrlCreateButton("Send", $iGUI_W - 55, $iGUI_H - 23, 50, 20)
GUICtrlSetState(-1, $GUI_HIDE)

Dim $aAccelKeys[1][2] = [["{ENTER}", $nSend_Bttn]]
GUISetAccelerators($aAccelKeys)
GUISetState(@SW_SHOW)

_Console_SetHeader()

While 1 
	$aCurInfo = GUIGetCursorInfo($hGUI)
	
	If $aCurInfo[3] = 1 And ($aCurInfo[4] = $nConsole_Edit Or $aCurInfo[4] = $nCommand_Input) Then
		_GUICtrlMenu_TrackPopupMenu($hContext_Menu, $hGUI)
	EndIf
	
    Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE, $nExit_MItem
			GUIDelete($hGUI)
			Exit
		Case $nCopy_MItem
			Local $sSelEditText = ControlCommand($hGUI, "", $nConsole_Edit, "GetSelected")
			If Not @error And $sSelEditText <> "" Then ClipPut($sSelEditText)
		Case $nSend_Bttn
			_Send()
    EndSwitch
WEnd

Func _Console_SetHeader()
	Local $sProductName = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'ProductName')
    Local $sVersion = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'CurrentVersion')
	
	_Console_Write( _
		$sProductName & ' [Версия ' & $sVersion & '.' & @OSBuild & ']' & @CRLF & '(C) Корпорация Майкрософт, 1985-2012.' & @CRLF & @CRLF & _
		"You are logged as: " & @UserName & @CRLF & _
		"Computer: " & @ComputerName & @CRLF & _
		"IP Address: " & @IPAddress1 & @CRLF & _
		"Administrator Rights: " & _Iif(IsAdmin(), "Yes", "No") & @CRLF & _
		"Help: Type Help or /? then hit ENTER to send the command to the console" & @CRLF & @CRLF & _
		@WorkingDir & '>')
EndFunc

Func _Console_Write($sText, $iAppend = 1)
    GUICtrlSetData($nConsole_Edit, $sText, $iAppend)
	GUICtrlSetData($nCommand_Input, "")
EndFunc

Func _Send()
	If Not _IsFocused($hGUI, $nCommand_Input) Then Return
	
	$sCommand_Input_Read = GUICtrlRead($nCommand_Input)
	
	If $sCommand_Input_Read = "" Then
        _Console_Write(@CRLF & @WorkingDir & ">")
		_GUICtrlEdit_Scroll($nConsole_Edit, $SB_SCROLLCARET)
		Return
	Else
		_Console_Write($sCommand_Input_Read)
        
		If $sCommand_Input_Read = "Help" Or StringRight($sCommand_Input_Read, 2) = "/?" Then
			_ShowHelp($sCommand_Input_Read)
			_GUICtrlEdit_Scroll($nConsole_Edit, $SB_SCROLLCARET)
			Return
		EndIf
	EndIf
	
	If _IsSupportedCmd($aSupported_Cmds, $sCommand_Input_Read) Then
		If $sCommand_Input_Read = "Clear" Or $sCommand_Input_Read = "Cls" Then
			_Console_Write("", 0)
			_GUICtrlEdit_Scroll($nConsole_Edit, $SB_SCROLLCARET)
			Return
		EndIf
		
		If StringLeft($sCommand_Input_Read, 4) = "Beep" Then
			Local $TempCommandRead = StringTrimLeft($sCommand_Input_Read, 4)
			
			$VarsArr = StringSplit($TempCommandRead, ",")
			
			If IsArray($VarsArr) And UBound($VarsArr) > 2 Then
				$Frequency = StringStripWS($VarsArr[1], 3)
				$Duration = StringStripWS($VarsArr[2], 3)
				
				Beep($Frequency , $Duration)
			Else
				_Console_Write(@CRLF & $sCommand_Input_Read & ": Incorrect parameters in command / Wrong number of arguments in command call.")
			EndIf
		EndIf
		
		If StringLeft($sCommand_Input_Read, 5) = "Print" Then
			Local $TempCommandRead = StringTrimLeft($sCommand_Input_Read, 6)
			
			If $TempCommandRead <> "" Then
				_Console_Write($TempCommandRead)
			Else
				_Console_Write(@CRLF & $sCommand_Input_Read & ": Wrong number of arguments in command call.")
			EndIf
		EndIf
		
		If StringLeft($sCommand_Input_Read, 1) = "!" Then
			If $sCommand_Input_Read = "!ip" Then
				_Console_Write(@IPAddress1)
			Else
				Local $TempCommandRead = "@" & StringTrimLeft($sCommand_Input_Read, 1) & "@"
				
				If $TempCommandRead <> "@@" Then
					_Console_Write($TempCommandRead)
				Else
					_Console_Write(@CRLF & $sCommand_Input_Read & ": Unknown Macro.")
				EndIf
			EndIf
		EndIf
		
		If StringRegExp($sCommand_Input_Read, "(?i)\%(.*)\%") Then
			If $sCommand_Input_Read <> "%%" Then
				_Console_Write($sCommand_Input_Read)
			Else
				_Console_Write(@CRLF & $sCommand_Input_Read & ": Unknown Variable." & @CRLF)
			EndIf
		EndIf
		
		_Console_Write(@CRLF & @WorkingDir & ">")
		
		If StringLeft($sCommand_Input_Read, 5) = "Exit" Then Exit
		_GUICtrlEdit_Scroll($nConsole_Edit, $SB_SCROLLCARET)
		
		Return
	EndIf
	
	Run($sCommand_Input_Read)
	
	If @error Then
		_Console_Write(@CRLF & $sCommand_Input_Read & ": Not supported command / Programm not found" & @CRLF & @CRLF & @WorkingDir & ">")
	EndIf
	
	_GUICtrlEdit_Scroll($nConsole_Edit, $SB_SCROLLCARET)
EndFunc

Func _ShowHelp($nCommand_Input="")
	Local $ReadConsole = GUICtrlRead($nConsole_Edit)
	Local $ComandsArr = _GetCommandsArr(1)
	Local $HelpToShowStr = "", $CurrentValue
	
	For $i = 1 To UBound($ComandsArr)-1
		$CurrentValue = $ComandsArr[$i]
		$HelpToShowStr &= $CurrentValue & @CRLF
		If StringStripWS(StringTrimRight($nCommand_Input, 2), 3) = StringLeft($CurrentValue, StringInStr($CurrentValue, " -")-1) Then
			$HelpToShowStr = $CurrentValue
			ExitLoop
		EndIf
	Next
	
	_Console_Write($ReadConsole & @CRLF & $HelpToShowStr)
EndFunc

Func _GetCommandsArr($Raw=1)
	Local $TotalCommands = 23
	Local $nCommand_InputsArr[1]
	
	Local $Descript_1 = "Help - takes you here to view all the commands"
	Local $Descript_2 = "Clear - clears the console"
	Local $Descript_3 = "Beep - plays back a beep noise, example: Beep 500, 1000 - where 500 is Frequency, and 1000 is Duration"
	Local $Descript_4 = "Print - Like Echo in CmdLine"
	Local $Descript_5 = "!IP - tells you your current ip"
	Local $Descript_6 = "!UserName - tells you the logged on user name"
	Local $Descript_7 = "!OSTYPE - returns WIN32_NT for NT/2000/XP/2003 and returns WIN32_WINDOWS for 95/98/Me"
	Local $Descript_8 = "!Connected - tells you if your online"
	Local $Descript_9 = "!OSLang - shows you your serial for your copy of windows 2000 and xp only"
	Local $Descript_10 = "CdTray - opens or closes a cd tray or type all to open or close all trays, example: CdTray C:"
	Local $Descript_11 = "Trans - makes a console window transparent 0-255, example: Trans 150"
	Local $Descript_12 = "ClipPut - writes text to the clipboard, example: ClipPut Text"
	Local $Descript_13 = "ClipGet - Show text (and only text) from the clipboard"
	Local $Descript_14 = "DirCreate - creates a directory/folder, example: DirCreate 'c:\my dir'"
	Local $Descript_15 = "FileGetSize - returns file size in bytes, example: FileGetSize 'c:\log.txt'"
	Local $Descript_16 = "FileWrite - writes to a file, example: FileWrite 'C:\myfile.txt', this is my line of text"
	Local $Descript_17 = "ReplaceInFile - Perform replacing in certain file, example: ReplaceInFile 'c:\test.txt', OldText, NewText"
	Local $Descript_18 = "SoundSetWaveVolume - sets the wave volume 0-100, example: SoundSetWaveVolume 50"
	Local $Descript_19 = "Hide - Hide window by title, example: Hide(@) - will hide the console window !"
	Local $Descript_20 = "ProcessList - list all processes"
	Local $Descript_21 = "ProcessClose - close a process, example: ProcessClose notepad.exe"
	Local $Descript_22 = "Credits - credits of who made console"
	Local $Descript_23 = "Exit - exits console"
	
	Local $CurrentVal
	
	For $i = 1 To $TotalCommands
		$CurrentVal = Eval("Descript_" & $i)
		ReDim $nCommand_InputsArr[UBound($nCommand_InputsArr)+1]
		
		If $Raw Then
			$nCommand_InputsArr[UBound($nCommand_InputsArr)-1] = $CurrentVal
		Else
			$nCommand_InputsArr[UBound($nCommand_InputsArr)-1] = StringLeft($CurrentVal, StringInStr($CurrentVal, " -")-1)
		EndIf
	Next
	
	$nCommand_InputsArr[0] = UBound($nCommand_InputsArr)-1
	Return $nCommand_InputsArr
EndFunc

Func _IsSupportedCmd(ByRef $aSupported_Cmds, $Cmd)
	For $i = 1 To UBound($aSupported_Cmds)-1
		$TrimCmd = StringLeft($Cmd, StringLen($aSupported_Cmds[$i]))
		If $Cmd = $aSupported_Cmds[$i] Or $aSupported_Cmds[$i] = $TrimCmd Then Return True
		If StringRegExp($Cmd, "(?i)\%(.*)\%") Then Return True
		If StringLeft($Cmd, 1) = "!" Then Return True
	Next
	
	Return False
EndFunc

Func _IsFocused($hWnd, $nCID)
    Return ControlGetHandle($hWnd, '', $nCID) = ControlGetHandle($hWnd, '', ControlGetFocus($hWnd))
EndFunc
 
Верх