标题: [特效代码] bat脚本中获取、控制光标位置 [打印本页]
作者: lltlo 时间: 2022-8-8 18:01 标题: bat脚本中获取、控制光标位置
各位大佬好,
楼主也是一位计算从业人员,写代码、用脚本也好多年了。脚本也只是简单应用,脚本问题还是会经常来这儿搜索学习。
关于控制光标位置的方法(tab和backspace方法)其实一早就用过,但是win10上不好使,一直没有去研究。
上周工作中又用到了,想着这次一定好好研究研究,然后翻遍了互联网,发现也没有好的方法,不过倒是学习到了很多其他技巧,然后自己应用到光标的获取和控制上,效果还行。
发出来分享给大家,顺便问问还有没有更好法。
另外,这个脚本启动时会打印// 2>nul这一行,大家有没有好的办法优化一下?- // 2>nul & @goto :batch_start
- /*
- :batch_start
- @echo off
- setlocal
- setlocal ENABLEDELAYEDEXPANSION
-
- rem 必须执行的步骤,初始化c#辅助程序
- call :init_cursor_control
-
- rem 下面的代码主要是为了清除屏幕第二行输出的// 2>nul,会有闪烁。如果觉得不好,可以删掉,或者用cls清屏。
- rem 但是cls清屏会把屏幕所有都清掉,包括非本脚本输出内容。
- call :get_cursor_info Current_X Current_Y Max_X Max_Y
- set /a Init_Y=%Current_Y% - 1
- call :set_cursor_position 0 %Init_Y%
- call :get_back_space BackSpace
- set "BlankSpace="
- for /l %%a in (1,1,%Max_X%) do set "BlankSpace=!BlankSpace! "
- echo %BackSpace%%BlankSpace%
- set /a Init_Y=%Current_Y% - 2
- call :set_cursor_position 0 %Init_Y%
-
-
- rem 脚本加在下面位置,其他地方不要动
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- echo 按B键退出
- call :get_cursor_info Current_X Current_Y Max_X Max_Y
-
- :test_loop
- call :set_cursor_position 0 %Current_Y%
- echo %date% %time%
- choice /t 1 /n /c wb /d w>nul
- if %errorlevel%==2 goto :batch_end
- goto :test_loop
-
- rem 脚本加在上面位置,其他地方不要动
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- rem 脚本最后退出位置,下面的代码不要更改
- :batch_end
- endlocal
- exit /b %errorlevel%
-
- rem 获取backspace回退键
- :get_back_space
- for /F %%a in ('"prompt $h & for %%b in (1) do rem"')do set "%~1=%%a"
- goto :eof
-
- rem 设置光标位置
- :set_cursor_position
- "%cursor_control_exe_file_path%" setcursorposition %~1 %~2
- goto :eof
-
- rem 获取当前窗口光标位置以及窗口尺寸
- :get_cursor_info
- "%cursor_control_exe_file_path%" getcursorposition
- set /p %~1= <"%cursor_control_exe_file_path%.CurrentX"
- set /p %~2= <"%cursor_control_exe_file_path%.CurrentY"
- set /p %~3= <"%cursor_control_exe_file_path%.MaxX"
- set /p %~4= <"%cursor_control_exe_file_path%.MaxY"
- goto :eof
-
- rem 初始化c#辅助程序,如果未找到就进行编译
- :init_cursor_control
- :: find csc.exe
- set "csc="
- for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do set "csc=%%#"
- if not exist "%csc%" (
- echo no .net framework installed
- exit /b 10
- )
- set cursor_control_exe_file_path=%tmp%\cursor_control.exe
- if not exist "%cursor_control_exe_file_path%" (
- call %csc% /nologo /warn:0 /out:"%cursor_control_exe_file_path%" "%~dpsfnx0" || (
- exit /b %errorlevel%
- )
- )
- goto :eof
-
- */
-
- using System;
- using System.Runtime.InteropServices;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
-
- namespace SetConsoleCursorPosition
- {
- class Program
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern IntPtr GetStdHandle(int nStdHandle);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern bool SetConsoleCursorPosition(
- IntPtr hConsoleOutput,
- COORD dwCursorPosition);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern bool GetConsoleScreenBufferInfo(
- IntPtr hConsoleOutput,
- ref CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern uint GetLastError();
-
- public struct COORD
- {
- public short X;
- public short Y;
- };
-
- public struct SMALL_RECT
- {
- public ushort Left;
- public ushort Top;
- public ushort Right;
- public ushort Bottom;
- };
-
- public struct CONSOLE_SCREEN_BUFFER_INFO
- {
- public COORD dwSize;
- public COORD dwCursorPosition;
- public ushort wAttributes;
- public SMALL_RECT srWindow;
- public COORD dwMaximumWindowSize;
- };
-
- const int STD_INPUT_HANDLE = -10;
- const int STD_OUTPUT_HANDLE = -11;
- const int STD_ERROR_HANDLE = -12;
-
- static void WriteFile(string filepath, int value)
- {
- FileStream fileStream = File.Create(filepath);
- byte[] bytes = new UTF8Encoding(true).GetBytes(Convert.ToString(value));
- fileStream.Write(bytes, 0, bytes.Length);
- fileStream.Close();
- }
-
- static int Main(string[] args)
- {
- try
- {
- if (0 == args.Length)
- {
- return 87; // ERROR_INVALID_PARAMETER
- }
-
- IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (args[0].ToLower() == "getcursorposition")
- {
- CONSOLE_SCREEN_BUFFER_INFO oCONSOLE_SCREEN_BUFFER_INFO = new CONSOLE_SCREEN_BUFFER_INFO();
- bool bRes = GetConsoleScreenBufferInfo(iStdOut, ref oCONSOLE_SCREEN_BUFFER_INFO);
- if (!bRes)
- {
- uint uiLastErrorCode = GetLastError();
- return (int)uiLastErrorCode;
- }
-
- string strAppPath = Process.GetCurrentProcess().MainModule.FileName;
-
- WriteFile(strAppPath + ".CurrentX", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.X);
- WriteFile(strAppPath + ".CurrentY", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.Y);
- WriteFile(strAppPath + ".MaxX", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.X);
- WriteFile(strAppPath + ".MaxY", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.Y);
-
- return 0;
- }
- else if (args[0].ToLower() == "setcursorposition")
- {
- if (args.Length < 3)
- {
- return 87; // ERROR_INVALID_PARAMETER
- }
- COORD oCursorPosition;
- oCursorPosition.X = short.Parse(args[1]);
- oCursorPosition.Y = short.Parse(args[2]);
- bool bRes = SetConsoleCursorPosition(iStdOut, oCursorPosition);
- if (!bRes)
- {
- uint uiLastErrorCode = GetLastError();
- return (int)uiLastErrorCode;
- }
- return 0;
- }
-
- return 87; // ERROR_INVALID_PARAMETER
- }
- catch (Exception ex)
- {
- Console.WriteLine("exception: " + ex.ToString());
- return 87; // ERROR_INVALID_PARAMETER
- }
- }
- }
- }
复制代码
作者: lltlo 时间: 2022-8-9 11:33
优化了下,用findstr\for\more从脚本里查找c#辅助代码,生成新的c#源代码文件,原脚本开头就是标准的bat脚本了,就不会出现// 2>nul这个啦:- :batch_start
- @echo off
- setlocal
- setlocal ENABLEDELAYEDEXPANSION
-
- rem 必须执行的步骤,初始化c#辅助程序
- call :init_cursor_control
-
- rem 脚本加在下面位置,其他地方不要动
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- echo 按B键退出
- call :get_cursor_info Current_X Current_Y Max_X Max_Y
-
- :test_loop
- call :set_cursor_position 0 %Current_Y%
- echo %date% %time%
- choice /t 1 /n /c wb /d w>nul
- if %errorlevel%==2 goto :batch_end
- goto :test_loop
-
- rem 脚本加在上面位置,其他地方不要动
- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
-
- rem 脚本最后退出位置,下面的代码不要更改
- :batch_end
- endlocal
- exit /b %errorlevel%
-
- rem 获取backspace回退键
- :get_back_space
- for /F %%a in ('"prompt $h & for %%b in (1) do rem"')do set "%~1=%%a"
- goto :eof
-
- rem 设置光标位置
- :set_cursor_position
- "%cursor_control_exe_file_path%" setcursorposition %~1 %~2
- goto :eof
-
- rem 获取当前窗口光标位置以及窗口尺寸
- :get_cursor_info
- "%cursor_control_exe_file_path%" getcursorposition
- set /p %~1= <"%cursor_control_exe_file_path%.CurrentX"
- set /p %~2= <"%cursor_control_exe_file_path%.CurrentY"
- set /p %~3= <"%cursor_control_exe_file_path%.MaxX"
- set /p %~4= <"%cursor_control_exe_file_path%.MaxY"
- goto :eof
-
- rem 初始化c#辅助程序,如果未找到就进行编译
- :init_cursor_control
- :: find csc.exe
- set "csc="
- for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do set "csc=%%#"
- if not exist "%csc%" (
- echo no .net framework installed
- exit /b 10
- )
- set cursor_control_exe_file_path=%tmp%\cursor_control.exe
- if not exist "%cursor_control_exe_file_path%" (
- call :gen_helper_csharp_source
- call %csc% /nologo /warn:0 /out:"%cursor_control_exe_file_path%" "%cursor_control_exe_file_path%.cs" || (
- exit /b %errorlevel%
- )
- )
- goto :eof
-
- :gen_helper_csharp_source
- for /f "tokens=1,2 delims=: " %%n in ('findstr /N /C:"helper_csharp_start" "%~dpsfnx0"') do (
- ::echo %%n "%%o"
- if "%%o"=="helper_csharp_start" (
- set /a helper_csharp_start_line=%%n+1
- ::echo helper_csharp_start_line=!helper_csharp_start_line!
- more +!helper_csharp_start_line! "%~dpsfnx0" > "%cursor_control_exe_file_path%.cs"
- goto :eof
- )
- )
- goto :eof
-
- rem c#辅助程序开始位置
- :helper_csharp_start
-
- using System;
- using System.Runtime.InteropServices;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
-
- namespace SetConsoleCursorPosition
- {
- class Program
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern IntPtr GetStdHandle(int nStdHandle);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- internal static extern bool SetConsoleCursorPosition(
- IntPtr hConsoleOutput,
- COORD dwCursorPosition);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern bool GetConsoleScreenBufferInfo(
- IntPtr hConsoleOutput,
- ref CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern uint GetLastError();
-
- public struct COORD
- {
- public short X;
- public short Y;
- };
-
- public struct SMALL_RECT
- {
- public ushort Left;
- public ushort Top;
- public ushort Right;
- public ushort Bottom;
- };
-
- public struct CONSOLE_SCREEN_BUFFER_INFO
- {
- public COORD dwSize;
- public COORD dwCursorPosition;
- public ushort wAttributes;
- public SMALL_RECT srWindow;
- public COORD dwMaximumWindowSize;
- };
-
- const int STD_INPUT_HANDLE = -10;
- const int STD_OUTPUT_HANDLE = -11;
- const int STD_ERROR_HANDLE = -12;
-
- static void WriteFile(string filepath, int value)
- {
- FileStream fileStream = File.Create(filepath);
- byte[] bytes = new UTF8Encoding(true).GetBytes(Convert.ToString(value));
- fileStream.Write(bytes, 0, bytes.Length);
- fileStream.Close();
- }
-
- static int Main(string[] args)
- {
- try
- {
- if (0 == args.Length)
- {
- return 87; // ERROR_INVALID_PARAMETER
- }
-
- IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (args[0].ToLower() == "getcursorposition")
- {
- CONSOLE_SCREEN_BUFFER_INFO oCONSOLE_SCREEN_BUFFER_INFO = new CONSOLE_SCREEN_BUFFER_INFO();
- bool bRes = GetConsoleScreenBufferInfo(iStdOut, ref oCONSOLE_SCREEN_BUFFER_INFO);
- if (!bRes)
- {
- uint uiLastErrorCode = GetLastError();
- return (int)uiLastErrorCode;
- }
-
- string strAppPath = Process.GetCurrentProcess().MainModule.FileName;
-
- WriteFile(strAppPath + ".CurrentX", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.X);
- WriteFile(strAppPath + ".CurrentY", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.Y);
- WriteFile(strAppPath + ".MaxX", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.X);
- WriteFile(strAppPath + ".MaxY", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.Y);
-
- return 0;
- }
- else if (args[0].ToLower() == "setcursorposition")
- {
- if (args.Length < 3)
- {
- return 87; // ERROR_INVALID_PARAMETER
- }
- COORD oCursorPosition;
- oCursorPosition.X = short.Parse(args[1]);
- oCursorPosition.Y = short.Parse(args[2]);
- bool bRes = SetConsoleCursorPosition(iStdOut, oCursorPosition);
- if (!bRes)
- {
- uint uiLastErrorCode = GetLastError();
- return (int)uiLastErrorCode;
- }
- return 0;
- }
-
- return 87; // ERROR_INVALID_PARAMETER
- }
- catch (Exception ex)
- {
- Console.WriteLine("exception: " + ex.ToString());
- return 87; // ERROR_INVALID_PARAMETER
- }
- }
- }
- }
复制代码
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |