News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

How to detect if a Console window is currently in Mark-mode?

Started by pcMike, January 01, 2022, 09:51:45 AM

Previous topic - Next topic

pcMike

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




jj2007

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

pcMike

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. :-)

jj2007

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

pcMike

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?


six_L

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.
Say you, Say me, Say the codes together for ever.

pcMike

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]

jj2007

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.

jj2007

The CreateThread method doesn't work, but external control is ok. Extract all files to a folder, then launch GetCpuUse.exe

six_L

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
Say you, Say me, Say the codes together for ever.

jj2007

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.

six_L

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.
Say you, Say me, Say the codes together for ever.

jj2007

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...

xandaz