The xtopmost macro is very restrictive because it makes closing the window quite difficult. Users might feel annoyed. You should avoid using it unless you have a real good reason.
Code: Select all
@echo off
setlocal DisableDelayedExpansion
:: setlocal EnableDelayedExpansion
call :init_topmost
call :init_xtopmost
echo(&echo set topmost
%topmost% 1
if errorlevel 1 (echo error) else echo success
pause
echo(&echo reset
%topmost% 0
if errorlevel 1 (echo error) else echo success
pause
echo(&echo set topmost (extended)
%xtopmost% 1
if errorlevel 1 (echo error) else echo success
pause
echo(&echo reset
%xtopmost% 0
if errorlevel 1 (echo error) else echo success
pause
exit /b
:: place the window above all windows and maintain this order
:init_topmost
setlocal DisableDelayedExpansion
set topmost=for %%i in (1 2) do if %%i==2 (^
%=% for /f %%j in ("^^!arg^^! x") do powershell -nop -ep Bypass -c ^"try{$c=Add-Type -Name pInv -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")] public static extern int SetWindowPos(IntPtr wnd,IntPtr insertAfter,int x,int y,int cx,int cy,uint flags);^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr GetConsoleWindow();';^
%=====% $flag=0;^
%=====% if(-not [Int32]::TryParse(\"%%~j\",[ref]$flag) -or ($flag -ne 0 -and $flag -ne 1)){^
%=========% [Console]::Error.WriteLine(\"Syntax Error`r`n Usage:`r`n%%topmost%% flag`r`n`tflag`t1 set topmost, 0 restore defaults\");^
%=========% exit 1;}^
%=====% exit ($c::SetWindowPos($c::GetConsoleWindow(),[IntPtr]($flag-2),0,0,0,0,3) -eq 0);}catch{exit 1;}^"^&endlocal^
%=% ) else setlocal EnableDelayedExpansion^&set arg=
endlocal&set "topmost=%topmost%"
if !!# neq # set "topmost=%topmost:^^=%"
exit /b
:: place the window above all windows and maintain this order; disable minimizing, maximizing, and closing of the window; no task bar icon
:init_xtopmost
setlocal DisableDelayedExpansion
set xtopmost=for %%i in (1 2) do if %%i==2 (^
%=% for /f %%j in ("^^!arg^^! x") do powershell -nop -ep Bypass -c ^"try{$c=Add-Type -Name pInv -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")] public static extern int SetWindowLong(IntPtr wnd,int idx,int newLong);^
%=====% [DllImport(\"user32.dll\")] public static extern Int64 SetWindowLongPtr(IntPtr wnd,int idx,Int64 newLong);^
%=====% [DllImport(\"user32.dll\")] public static extern int GetWindowLong(IntPtr wnd,int idx);^
%=====% [DllImport(\"user32.dll\")] public static extern Int64 GetWindowLongPtr(IntPtr wnd,int idx);^
%=====% [DllImport(\"user32.dll\")] public static extern int SetWindowPos(IntPtr wnd,IntPtr insertAfter,int x,int y,int cx,int cy,uint flags);^
%=====% [DllImport(\"user32.dll\")] public static extern IntPtr GetSystemMenu(IntPtr wnd,int revert);^
%=====% [DllImport(\"user32.dll\")] public static extern int DeleteMenu(IntPtr menu,uint id,uint flags);^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr GetConsoleWindow();';^
%=====% $flag=0;^
%=====% if(-not [Int32]::TryParse(\"%%~j\",[ref]$flag) -or ($flag -ne 0 -and $flag -ne 1)){^
%=========% [Console]::Error.WriteLine(\"Syntax Error`r`n Usage:`r`n%%xtopmost%% flag`r`n`tflag`t1 set topmost, 0 restore defaults\");^
%=========% exit 1;}^
%=====% $wnd=$c::GetConsoleWindow();^
%=====% if($flag -eq 1){^
%=========% if([IntPtr]::Size -eq 4){$null=$c::SetWindowLong($wnd,-16,$c::GetWindowLong($wnd,-16) -bAnd -bNot 131072 -bAnd -bNot 65536);^
%=============% $null=$c::SetWindowLong($wnd,-20,($c::GetWindowLong($wnd,-20) -bAnd -bNot 262144) -bOr 128);}^
%=========% else{$null=$c::SetWindowLongPtr($wnd,-16,$c::GetWindowLongPtr($wnd,-16) -bAnd -bNot [Int64]131072 -bAnd -bNot [Int64]65536);^
%=============% $null=$c::SetWindowLongPtr($wnd,-20,($c::GetWindowLongPtr($wnd,-20) -bAnd -bNot [Int64]262144) -bOr [Int64]128);}^
%=========% exit ($c::DeleteMenu($c::GetSystemMenu($wnd,0),61536,0) -eq 0 -or $c::SetWindowPos($wnd,[IntPtr]-1,0,0,0,0,3) -eq 0);}^
%=====% if([IntPtr]::Size -eq 4){$null=$c::SetWindowLong($wnd,-20,($c::GetWindowLong($wnd,-20) -bAnd -bNot 128) -bOr 262144);^
%=========% $null=$c::SetWindowLong($wnd,-16,$c::GetWindowLong($wnd,-16) -bOr 131072 -bOr 65536);}^
%=====% else{$null=$c::SetWindowLongPtr($wnd,-20,($c::GetWindowLongPtr($wnd,-20) -bAnd -bNot [Int64]128) -bOr [Int64]262144);^
%=========% $null=$c::SetWindowLongPtr($wnd,-16,$c::GetWindowLongPtr($wnd,-16) -bOr [Int64]131072 -bOr [Int64]65536);}^
%=====% exit ($c::GetSystemMenu($wnd,1) -ne [IntPtr]::Zero -or $c::SetWindowPos($wnd,[IntPtr]-2,0,0,0,0,3) -eq 0);}catch{exit 1;}^"^&endlocal^
%=% ) else setlocal EnableDelayedExpansion^&set arg=
endlocal&set "xtopmost=%xtopmost%"
if !!# neq # set "xtopmost=%xtopmost:^^=%"
exit /b
Code: Select all
:: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ magic numbers used in the code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
:: use Get/SetWindowLong for a 32 bit process, but Get/SetWindowLongPtr for a 64 bit process
:: 4 size of a memory address in a 32 bit process (it's 8 bytes for a 64 bit process), the size of IntPtr reflects this fact
::
:: window styles
:: -16 GWL_STYLE index used to get/set style information
:: 65536 WS_MAXIMIZEBOX used to show/hide the maximize button
:: 131072 WS_MINIMIZEBOX used to show/hide the minimize button
::
:: extended window styles
:: -20 GWL_EXSTYLE index used to get/set extended style information
:: 128 WS_EX_TOOLWINDOW does not appear in the task bar
:: 262144 WS_EX_APPWINDOW default appearance of a console window
::
:: ID to access the close menu item
:: 61536 SC_CLOSE used to delete the close item in the context menu and to gray the X button
::
:: Z order
:: [IntPtr]-1 HWND_TOPMOST place the window above all non-topmost windows and maintain this order
:: [IntPtr]-2 HWND_NOTOPMOST default behavior of a window regarding its Z order
:: 3 SWP_NOSIZE | SWP_NOMOVE do not resize or move the window when SetWindowPos is called