I have written a Windows Console application, and I find it annoying that when the Console Quick_Edit_Mode is enabled (either in the Console properties, or by using the SetConsoleMode API), the console output is paused while Console is in Mark-Mode, thereby freezing the application/thread. Mark-Mode is enabled when the mouse has clicked on the Console (causing a white block to appear), or when the mouse has been used to select an area to copy. Mark-Mode remains enabled until a key is pressed while the Console window is currently in focus.
I do not want to disable Quick_Edit_Mode in my program. I wish to check if Mark-Mode is currently enabled or not. I would also like to find a way to programmatically turn off Mark-Mode if it is on. Is it possible?
Mark-Mode is described here:
https://superuser.com/questions/459609/what-does-it-do-exactly-if-i-click-in-the-window-of-cmd
.XCREF
.NoList
INCLUDE \Masm32\Include\Masm32rt.inc
.List
.DATA
;###############################################################################################
.DATA?
hWnd dd ? ; Handle of Console Window
hStdIn dd ? ; Handle of Standard Input
hStdOut dd ? ; Handle of Standard Output
;###############################################################################################
.CODE
_main PROC
invoke GetStdHandle,STD_OUTPUT_HANDLE ; Define Output Handle
mov hStdOut,eax
invoke GetStdHandle, STD_INPUT_HANDLE
mov hStdIn,eax
invoke GetConsoleWindow
mov hWnd,eax
; Make sure that MOUSE_INPUT AND QUICK_EDIT_MODE are enabled
invoke SetConsoleMode,hStdIn,ENABLE_EXTENDED_FLAGS or \
ENABLE_MOUSE_INPUT or \
ENABLE_QUICK_EDIT_MODE or \
ENABLE_LINE_INPUT or \
ENABLE_ECHO_INPUT or \
ENABLE_PROCESSED_INPUT or \
ENABLE_EXTENDED_FLAGS
xor ebx,ebx
testloop:
inc ebx
print "Hello World "
print uhex$(ebx),13,10
invoke Sleep, 100
call crt__kbhit
test eax, eax
jz testloop
print "The End",13,10
ret
_main ENDP
Just ask for it, see attachment.
Happy New Year, Jochen
push eax ; create a slot on the stack
invoke GetConsoleMode, rv(GetStdHandle, STD_INPUT_HANDLE), esp
Thank you for the reply Jochen, but I was not asking how to determine the current console mode. I wish to know if the Console is currently being paused by Mark-mode, which will occur if these 2 things take place:
1. The Console has QUICK_EDIT mode (and MOUSE_MODE) flags enabled.
2. The user has clicked on the console with the mouse, or has selected a block of text with the mouse.
When both of these things occur, there will be a white square, or a white block of selected text on the console screen, and no output will occur until the user presses a key.
See an example screen-shot here:
https://superuser.com/questions/459609/what-does-it-do-exactly-if-i-click-in-the-window-of-cmd
I would also like to be able to abort Mark-Mode if it is enabled, without having to stuff a key into the input buffer. :-)
Alright, now I understand what you mean. The process pauses here, inside the WriteFile API:
Address Hex dump Command Comments
753212D5 /$ B8 02200000 mov eax, 2002 ; kernel32.753212D5(guessed Arg1,Arg2,Arg3,Arg4,Arg5)
753212DA |. B9 00000000 mov ecx, 0
753212DF |. 8D5424 04 lea edx, [esp+4]
753212E3 |. 64:FF15 C0000 call near fs:[0C0] ; <<<<<<<<<<<<<<<
753212EA |. 83C4 04 add esp, 4
753212ED \. C2 1400 retn 14
Here is a demo. Run it, press a key to start the output, then double-click the number and watch in Task Manager what happens with Cpu use.
include \masm32\include\masm32rt.inc
.code
start:
push eax ; create a slot on the stack
invoke GetConsoleMode, rv(GetStdHandle, STD_INPUT_HANDLE), esp
invoke SetConsoleMode, rv(GetStdHandle, STD_INPUT_HANDLE), ENABLE_EXTENDED_FLAGS or \
ENABLE_MOUSE_INPUT or \
ENABLE_QUICK_EDIT_MODE or \
ENABLE_LINE_INPUT or \
ENABLE_ECHO_INPUT or \
ENABLE_PROCESSED_INPUT or \
ENABLE_EXTENDED_FLAGS
push eax
invoke GetConsoleMode, rv(GetStdHandle, STD_INPUT_HANDLE), esp
pop ecx
print hex$(ecx), " is the new mode", 13, 10
pop ecx
inkey hex$(ecx), " is the old mode", 13, 10, "--- hit any key to start, then watch cpu use in Task Manager after selecting the number ---", 13, 10
push 999999
.Repeat
mov ecx, [esp]
print str$(ecx), 13
xor ecx, ecx
.Repeat
inc ecx
.Until Sign?
dec dword ptr [esp]
.Until Sign?
pop edx
exit
end start
JJ, I ran the demo and I see the CPU usage drops a bit when I either single or double click the number (or any other console text), and the output is paused, but I don't understand what importance the CPU usage is.
Are you suggesting the CPU usage can be monitored to determine when the Mark-mode is pausing the console output?
QuoteENABLE_QUICK_EDIT_MODE 0x0040 This flag enables the user to use the mouse to select and edit text. To enable this mode, use ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS. To disable this mode, use ENABLE_EXTENDED_FLAGS without this flag.
Thanks six_L, but I do not want to remove QUICK_EDIT mode entirely. I just want to prevent the console from being paused forever by Mark-mode when a user accidently clicks the console with the mouse and walks away.
I suspect there is no way of programmatically detecting when Mark-mode is in progress (suspending all console output).
An ugly kluge to this is to disable QUICK_EDIT by default, and allow the user to enable it just for a moment by pressing a specific key to toggle QUICK_EDIT mode on or off.
A slightly better kluge would be for this key to only turn QUICK_EDIT mode on for one minute, so there is no chance that the user will forget to turn it off afterwards. I tried doing this, but I found that if Mark-mode is currently in progress (for example the user has accidently clicked the mouse on the console and either walked away or switched focus to a different app, then the following command to turn off QUICK_EDIT mode will fail:
invoke SetConsoleMode,hStdIn, ENABLE_LINE_INPUT or \
ENABLE_ECHO_INPUT or \
ENABLE_PROCESSED_INPUT or \
ENABLE_EXTENDED_FLAGS
I attempted to overcome this issue by first forcing an "Enter" key into the keyboard buffer just before the SetConsole Command, to ensure that Mark-mode is aborted first by using this code:
invoke keybd_event,VK_RETURN,1Ch,0,0
invoke keybd_event,VK_RETURN,1Ch,KEYEVENTF_KEYUP,0
This almost solved the problem, but it only works if the Console application has focus. If the user has switched focus to another program, then the Enter key gets sent to that application instead. Is there a way of sending a key to just the Console program? Another solution would be to send an Alternate-Click (which is usually Right-Click) to the Console application. I suspect if I can figure out how to do so using keybd_event or even using SendInput I will run into the same issue of not being able to send it to the application if it is no longer in focus.
[Edit: typo]
Quote from: pcMike on January 01, 2022, 02:56:55 PM
JJ, I ran the demo and I see the CPU usage drops a bit when I either single or double click the number (or any other console text), and the output is paused, but I don't understand what importance the CPU usage is.
Zero cpu use tells you that your process is suspended.
QuoteAre you suggesting the CPU usage can be monitored to determine when the Mark-mode is pausing the console output?
The lpUserTime arg of GetProcessTimes could indeed do that, in theory. The problem is you can't do it because, well.... your process is suspended :rolleyes:
So you would have it to do from outside, or maybe from a routine started with CreateThread.
The CreateThread method doesn't work, but external control is ok. Extract all files to a folder, then launch GetCpuUse.exe
if a Console window is currently in Mark-mode, then set No; if a Console window isn't currently in Mark-mode, then set YES;
QuoteHow to detect if a Console window is currently in Mark-mode?
invoke GetConsoleMode,hStdIn, addr dwStdMode
.if rax == NULL
invoke ErrorExit,CStr("Error: GetConsoleMode")
.endif
.if dwStdMode & ENABLE_QUICK_EDIT_MODE ;to detect if a Console window is currently in Mark-mode,YES
invoke ss_printf,CStr("YES!")
mov eax, dwStdMode
and eax, not ENABLE_QUICK_EDIT_MODE
mov dwStdMode,eax
.else ;NO
invoke ss_printf,CStr("NO!")
mov eax, dwStdMode
or eax, ENABLE_QUICK_EDIT_MODE or ENABLE_EXTENDED_FLAGS
mov dwStdMode,eax
.endif
invoke SetConsoleMode,hStdIn, dwStdMode
.if rax == NULL
invoke ErrorExit,CStr("Error: SetConsoleMode")
.endif
six_L,
I wouldn't have done so much acrobatics if it was that simple. Read again what OP really wants. You need to control the process from outside, as done in my most recent post above.
hi,JJ2007
1, I don't understand. Why use two processes for the work that can be done by one process?
2, If a console window happens "FOCUS_EVENT" , toggle QUICK_EDIT mode off; happens "FOCUS_EVENT" again, toggle QUICK_EDIT mode on.
Quote from: six_L on January 07, 2022, 08:32:54 AM
hi,JJ2007
1, I don't understand. Why use two processes for the work that can be done by one process?
2, If a console window happens "FOCUS_EVENT" , toggle QUICK_EDIT mode off; happens "FOCUS_EVENT" again, toggle QUICK_EDIT mode on.
Quote from: pcMike on January 02, 2022, 03:33:57 AMI just want to prevent the console from being paused forever by Mark-mode when a user accidently clicks the console with the mouse and walks away.
While
the process is paused, you cannot detect the mark mode. There is no such thing as a FOCUS_EVENT, unfortunately. That's why you need to detect the "event" from outside, i.e. from a separate process. Test it (http://masm32.com/board/index.php?action=dlattach;topic=9738.0;attach=12432)...
Thanks JJ. Apreciatted
.