Windows programming

Moderators: None (Apply to moderate this forum)
Number of threads: 3711
Number of posts: 9173

This Forum Only
Post New Thread
Single Post View       Linear View       Threaded View      f

Report
problem with console app Posted by forumember on 4 Jul 2004 at 3:29 AM
here is a relevent snippets:
TCHAR buf[20]; 

fdwMode = ENABLE_LINE_INPUT |       //ReadConsole() should wait and read 
                                   // characters until ENTER is pressed 
                 ENABLE_ECHO_INPUT |   // show characters as you type 
                 ENABLE_PROCESSED_INPUT;    // let system process all 
                                                // control keystrikes 
SetConsoleMode(hStdin, fdwMode) ; 
        
fdwMode = ENABLE_PROCESSED_OUTPUT; 
SetConsoleMode(hStdout, fdwMode); 


while (1) 
{ 
    WriteConsole(hStdout, "\npress [1] for codepage: ", 25, &ch, NULL); 
     ReadConsole(hStdin,buf,1,&ch,NULL); 
     buf[ch]='\0'; 
     FlushConsoleInputBuffer(hStdin); 
    WriteConsole(hStdout, buf, 3, &ch, NULL); 
}


the problem is that the first time while executes everything is ok:
i get on screen:

press [1] for codepage:


i enter 1 and press enter then it prints the character.

from this point something strange happens...
while loop continue to execute two more times despite the fact that ReadConsole() should wait for input...

anyone understand where is the problem?


Report
Re: problem with console app Posted by AsmGuru62 on 4 Jul 2004 at 7:20 AM

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/console_functions.asp

Se my corrections below (they are not tested).
Check out my console class at:

http://www.codexxi.com/MyBlocks.html


: here is a relevent snippets:
:
: TCHAR buf[20]; 
: 
: fdwMode = ENABLE_LINE_INPUT |       //ReadConsole() should wait and read 
:                                    // characters until ENTER is pressed 
:                  ENABLE_ECHO_INPUT |   // show characters as you type 
:                  ENABLE_PROCESSED_INPUT;    // let system process all 
:                                                 // control keystrikes 
: SetConsoleMode(hStdin, fdwMode) ; 
:         
: fdwMode = ENABLE_PROCESSED_OUTPUT; 
^^^ This will override your earlier setting.
: SetConsoleMode(hStdout, fdwMode); 
: 
: 
: while (1) 
: { 
:     WriteConsole(hStdout, "\npress [1] for codepage: ", 25, &ch, NULL); 
:      ReadConsole(hStdin,buf,4,&ch,NULL); 
^^^ Get more symbols here
:      buf[ch]='\0'; 
:      FlushConsoleInputBuffer(hStdin); 
:     WriteConsole(hStdout, buf, 3, &ch, NULL); 
^^^ Why this? You enabled echo already.
: }
: 

:
: the problem is that the first time while executes everything is ok:
: i get on screen:
:
:
press [1] for codepage:

:
: i enter 1 and press enter then it prints the character.
:
: from this point something strange happens...
: while loop continue to execute two more times despite the fact that ReadConsole() should wait for input...
:
: anyone understand where is the problem?
:
:
:

Report
Re: problem with console app Posted by forumember on 4 Jul 2004 at 9:04 AM
This message was edited by forumember at 2004-7-4 9:8:12

fdwMode = ENABLE_PROCESSED_OUTPUT;
^^^ This will override your earlier setting.

what you mean by saying that i'm overriding?
this flag makes possible to process escape sequences inside strings that i print with WriteConsole.

ReadConsole(hStdin,buf,4,&ch,NULL);
^^^ Get more symbols here
also you say that i reading too little characters, but i need to read only single character and checkk it.

the problem is that i get following output:

press [1] for codepage: 1
1
press [1] for codepage:
press [1] for codepage:

press [1] for codepage: 1
1
press [1] for codepage:
press [1] for codepage:

press [1] for codepage:


when i want it to be:
press [1] for codepage: 1
1
press [1] for codepage: 1
1
press [1] for codepage:


ReadConsole() for some reason doesn't block and while executes 2 more times.
till now i know that i press '1' and 'enter'
so these characters stored in input buffer and this explains the output i get.
but the strange thing is that after ReadConsole() call, i call also to FlushConsoleInputBuffer() which should discard line-feed and carriage-return character from input buffer.
but obviously that doesn't happen





Report
Re: problem with console app Posted by AsmGuru62 on 4 Jul 2004 at 1:58 PM
: This message was edited by forumember at 2004-7-4 9:8:12

: fdwMode = ENABLE_PROCESSED_OUTPUT;
: ^^^ This will override your earlier setting.
Yes. You are fine here... I did not see you are using
different handles for IN and OUT consoles.

:
: what you mean by saying that i'm overriding?
: this flag makes possible to process escape sequences inside strings that i print with WriteConsole.
:
: ReadConsole(hStdin,buf,4,&ch,NULL);
: ^^^ Get more symbols here
: also you say that i reading too little characters, but i need to read only single character and checkk it.
You set up a full line input, meaning that this function will
return when ENTER will be pressed. I think it will accept also that
same ENTER symbol into buffer, so you need some room for it...


:
: the problem is that i get following output:
:
:
: press [1] for codepage: 1
: 1
: press [1] for codepage:
: press [1] for codepage:
: 
: press [1] for codepage: 1
: 1
: press [1] for codepage:
: press [1] for codepage:
: 
: press [1] for codepage:
: 
: 

: when i want it to be:
:
: press [1] for codepage: 1
: 1
: press [1] for codepage: 1
: 1
: press [1] for codepage:
: 

:
: ReadConsole() for some reason doesn't block and while executes 2 more times.
: till now i know that i press '1' and 'enter'
: so these characters stored in input buffer and this explains the output i get.
: but the strange thing is that after ReadConsole() call, i call also to FlushConsoleInputBuffer() which should discard line-feed and carriage-return character from input buffer.
: but obviously that doesn't happen
:
:
:
:
:
:

Report
Re: problem with console app Posted by forumember on 4 Jul 2004 at 2:13 PM
This message was edited by forumember at 2004-7-4 14:13:47

You set up a full line input, meaning that this function will
return when ENTER will be pressed. I think it will accept also that 
same ENTER symbol into buffer, so you need some room for it...[/blue]


but here is the two catches:
1)
the ms docs say that - i'm qoute:

If the input buffer is being read by ReadFile or ReadConsole, other
 control keys are processed by the system and are not returned in 
the ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode 
is also enabled, backspace, carriage return, and linefeed characters 
are handled by the system.

here is the link:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/readconsole.asp

2)
why flushconsoleinputbuffer() doesn't remove new-line characters from the input buffer?



Report
Re: problem with console app Posted by AsmGuru62 on 5 Jul 2004 at 6:07 AM
: This message was edited by forumember at 2004-7-4 14:13:47

:
: You set up a full line input, meaning that this function will
: return when ENTER will be pressed. I think it will accept also that 
: same ENTER symbol into buffer, so you need some room for it...[/blue]
: 

:
: but here is the two catches:
: 1)
: the ms docs say that - i'm qoute:
:
:
: If the input buffer is being read by ReadFile or ReadConsole, other
:  control keys are processed by the system and are not returned in 
: the ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode 
: is also enabled, backspace, carriage return, and linefeed characters 
: are handled by the system.
: 

: here is the link:
: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/readconsole.asp
:
: 2)
: why flushconsoleinputbuffer() doesn't remove new-line characters from the input buffer?
:
Yeah... that's strange - flush supposed to work...

Did you try a code that reads more symbols than one?
I posted earlier a link to a code sample - did you look at that?
Try debugger on these lines... what is returned in 'ch' when you enter "1"?

Report
Re: problem with console app Posted by forumember on 5 Jul 2004 at 6:18 AM
yes,
if i read more character that removes also new-line characters...

but i don't want to use workarounds because next time i will do something i don't now what will happen...

and the problem not only in flush method but the new-line characters should not be put to input buffer according to docs

i talked to someone on IRC and he also was puzzled...
he even tried something else...
first he called FlushConsoleInputBuffer() and then called GetNumberOfConsoleInputEvents() and it returned non-zero result...

could it be a ms bug?

Report
Re: problem with console app Posted by AsmGuru62 on 5 Jul 2004 at 8:36 AM
: yes,
: if i read more character that removes also new-line characters...
:
: but i don't want to use workarounds because next time i will do something i don't now what will happen...
:
: and the problem not only in flush method but the new-line characters should not be put to input buffer according to docs
:
: i talked to someone on IRC and he also was puzzled...
: he even tried something else...
: first he called FlushConsoleInputBuffer() and then called GetNumberOfConsoleInputEvents() and it returned non-zero result...
:
: could it be a ms bug?
:
:
That can happen, because the input events are also mouse movements... I do not think that it is workaround. You want a line and you read only one symbol - not logical...

Report
Re: problem with console app Posted by forumember on 5 Jul 2004 at 8:54 AM
but it should work according to docs that is:

readsconsole() waits for input...

i press '1' and press 'enter'...

readconsole() sees 'enter', gets '1' and 'enter' is pulled out from input buffer by system...

i empty the input buffer with flushbufferinput() to verify no mo characters left behind...

next the code reaches readconsole(), the input buffer is empty and readconsole() waits again...

that the order of things to happen as i see it...
but something is not right
Report
Re: problem with console app Posted by Lundin on 6 Jul 2004 at 7:22 AM
This message was edited by Lundin at 2004-7-6 7:23:7

: yes,
: if i read more character that removes also new-line characters...
:
: but i don't want to use workarounds because next time i will do something i don't now what will happen...
:
: and the problem not only in flush method but the new-line characters should not be put to input buffer according to docs
:
: i talked to someone on IRC and he also was puzzled...
: he even tried something else...
: first he called FlushConsoleInputBuffer() and then called GetNumberOfConsoleInputEvents() and it returned non-zero result...
:
: could it be a ms bug?
:
:


I tried your code and I also think that this is a bug.
FlushConsoleInputBuffer() isn't following the function spec:

"The FlushConsoleInputBuffer function flushes the console input buffer. All input records currently in the input buffer are discarded."

Well, CR+LF are obviously not discarded.

Here is the code I tried it with:
(same result with both gcc & Borland)

while (1) 
{ 
     DWORD x;
     
     WriteConsole(hStdout, "\npress [1] for codepage: ", 25, &x, NULL);
     if(WaitForSingleObject(hStdin,INFINITE)==WAIT_OBJECT_0)
     {
       ReadConsole(hStdin,buf,1,&x,NULL);
       while(!FlushConsoleInputBuffer(hStdin))
         ;
       GetNumberOfConsoleInputEvents(hStdin,&x);
       cout << x << endl; // I get 0 here

     }
}



Report
Re: try this... Posted by AsmGuru62 on 5 Jul 2004 at 12:27 PM
This message was edited by AsmGuru62 at 2004-7-5 12:29:33

I just tested this code on VC++ 6.0.
Works perfectly without all flushes and all that...
Reading the line and acting upon it.

#include <windows.h>

#define STR_OUT(s)	WriteConsole (hOut, s, strlen (s), &dwCount, NULL)

int main (int argc, char* argv [])
	{
	HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
	HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);

	SetConsoleMode (hIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
	SetConsoleMode (hOut, ENABLE_PROCESSED_OUTPUT);

	CHAR strLine [8];
	PCHAR pstrPrompt = "\n*** COMMAND [1,2,3] (4 - QUIT): ";
	DWORD dwCount;
	BOOL bRunning = TRUE;

	while (bRunning) {
		STR_OUT (pstrPrompt);
		ReadConsole (hIn, strLine, 8, &dwCount, NULL);
		// strLine [dwCount] = '\0';
		// You can put it for your purposes, but
		// atoi() will stop at first non-digit.
		
		switch (atoi (strLine)) {
			case 1:
				STR_OUT ("\tAction 1 executed.");
				break;
			case 2:
				STR_OUT ("\tAction 2 executed.");
				break;
			case 3:
				STR_OUT ("\tAction 3 executed.");
				break;
			case 4:
				bRunning = FALSE;
				break;
			}
		}

	return 0;
	}



Report
Re: try this... Posted by forumember on 5 Jul 2004 at 1:03 PM
: This message was edited by AsmGuru62 at 2004-7-5 12:29:33

: I just tested this code on VC++ 6.0.
: Works perfectly without all flushes and all that...
: Reading the line and acting upon it.

:
: #include <windows.h>
: 
: #define STR_OUT(s)	WriteConsole (hOut, s, strlen (s), &dwCount, NULL)
: 
: int main (int argc, char* argv [])
: 	{
: 	HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
: 	HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
: 
: 	SetConsoleMode (hIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
: 	SetConsoleMode (hOut, ENABLE_PROCESSED_OUTPUT);
: 
: 	CHAR strLine [8];
: 	PCHAR pstrPrompt = "\n*** COMMAND [1,2,3] (4 - QUIT): ";
: 	DWORD dwCount;
: 	BOOL bRunning = TRUE;
: 
: 	while (bRunning) {
: 		STR_OUT (pstrPrompt);
: 		ReadConsole (hIn, strLine, 8, &dwCount, NULL);
: 		// strLine [dwCount] = '\0';
: 		// You can put it for your purposes, but
: 		// atoi() will stop at first non-digit.
: 		
: 		switch (atoi (strLine)) {
: 			case 1:
: 				STR_OUT ("\tAction 1 executed.");
: 				break;
: 			case 2:
: 				STR_OUT ("\tAction 2 executed.");
: 				break;
: 			case 3:
: 				STR_OUT ("\tAction 3 executed.");
: 				break;
: 			case 4:
: 				bRunning = FALSE;
: 				break;
: 			}
: 		}
: 
: 	return 0;
: 	}
: 

:
:
:
your exapmle works but it is a still workaround...
if don't believe, try instead '1' write '12345678'...
then we back to my case again

Report
Re: try this... Posted by AsmGuru62 on 6 Jul 2004 at 5:52 AM
: : This message was edited by AsmGuru62 at 2004-7-5 12:29:33

: : I just tested this code on VC++ 6.0.
: : Works perfectly without all flushes and all that...
: : Reading the line and acting upon it.

: :
: : #include <windows.h>
: : 
: : #define STR_OUT(s)	WriteConsole (hOut, s, strlen (s), &dwCount, NULL)
: : 
: : int main (int argc, char* argv [])
: : 	{
: : 	HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
: : 	HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
: : 
: : 	SetConsoleMode (hIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
: : 	SetConsoleMode (hOut, ENABLE_PROCESSED_OUTPUT);
: : 
: : 	CHAR strLine [8];
: : 	PCHAR pstrPrompt = "\n*** COMMAND [1,2,3] (4 - QUIT): ";
: : 	DWORD dwCount;
: : 	BOOL bRunning = TRUE;
: : 
: : 	while (bRunning) {
: : 		STR_OUT (pstrPrompt);
: : 		ReadConsole (hIn, strLine, 8, &dwCount, NULL);
: : 		// strLine [dwCount] = '\0';
: : 		// You can put it for your purposes, but
: : 		// atoi() will stop at first non-digit.
: : 		
: : 		switch (atoi (strLine)) {
: : 			case 1:
: : 				STR_OUT ("\tAction 1 executed.");
: : 				break;
: : 			case 2:
: : 				STR_OUT ("\tAction 2 executed.");
: : 				break;
: : 			case 3:
: : 				STR_OUT ("\tAction 3 executed.");
: : 				break;
: : 			case 4:
: : 				bRunning = FALSE;
: : 				break;
: : 			}
: : 		}
: : 
: : 	return 0;
: : 	}
: : 

: :
: :
: :
: your exapmle works but it is a still workaround...
: if don't believe, try instead '1' write '12345678'...
: then we back to my case again
:
:
You being too strict to OS...
I would not call it a bug, though.
Always leave room in a buffer - good practice.

Report
Re: try this... Posted by forumember on 6 Jul 2004 at 7:43 AM
: : : #include <windows.h>
: : : 
: : : #define STR_OUT(s)	WriteConsole (hOut, s, strlen (s), &dwCount, NULL)
: : : 
: : : int main (int argc, char* argv [])
: : : 	{
: : : 	HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
: : : 	HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
: : : 
: : : 	SetConsoleMode (hIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
: : : 	SetConsoleMode (hOut, ENABLE_PROCESSED_OUTPUT);
: : : 
: : : 	CHAR strLine [8];
: : : 	PCHAR pstrPrompt = "\n*** COMMAND [1,2,3] (4 - QUIT): ";
: : : 	DWORD dwCount;
: : : 	BOOL bRunning = TRUE;
: : : 
: : : 	while (bRunning) {
: : : 		STR_OUT (pstrPrompt);
: : : 		ReadConsole (hIn, strLine, 8, &dwCount, NULL);
: : : 		// strLine [dwCount] = '\0';
: : : 		// You can put it for your purposes, but
: : : 		// atoi() will stop at first non-digit.
: : : 		FlushConsoleInputBuffer(hIn);
//try to enter more chracters than your buffer permits and use
// FlushConsoleInputBuffer to get rid of unread characters...
: : : 		switch (atoi (strLine)) {
: : : 			case 1:
: : : 				STR_OUT ("\tAction 1 executed.");
: : : 				break;
: : : 			case 2:
: : : 				STR_OUT ("\tAction 2 executed.");
: : : 				break;
: : : 			case 3:
: : : 				STR_OUT ("\tAction 3 executed.");
: : : 				break;
: : : 			case 4:
: : : 				bRunning = FALSE;
: : : 				break;
: : : 			}
: : : 		}
: : : 
: : : 	return 0;
: : : 	}


programming have to be strict otherwise how can say that your code works?
maybe it works today but tomorrow it won't...
and i agree to leave space in the buffer
but there is another frustrating thing with FlushConsoleInputBuffer
because it simply doesn't work.
if i enter more characters than buffer lenght,and the user might do so, FlushConsoleInputBuffer() doesn't do nothing...
how this can be?


Report
Re: try this... Posted by AsmGuru62 on 6 Jul 2004 at 9:22 AM
This message was edited by AsmGuru62 at 2004-7-6 9:23:53

: but there is another frustrating thing with FlushConsoleInputBuffer
: because it simply doesn't work.
: if i enter more characters than buffer lenght,and the user might do so, FlushConsoleInputBuffer() doesn't do nothing...
: how this can be?
:
:
:
Probably, a bug in Windows... nobody is safe from software bugs, even mighty Microsoft.

There is a way to fully control the input buffer, so you will not get any overruns. There are a pile of functions in Console API which can be used:
DWORD dwMaxRecs = 256;
DWORD dwRecs;
INPUT_RECORD* arr = new INPUT_RECORD [dwMaxRecs];
BOOL bRun = TRUE;
HANDLE hInput = GetStdHandle (...);

if (arr) {
  while (bRun) {
    if (ReadConsoleInput (hInput, arr, dwMaxRecs, &dwRecs)) {
      for (DWORD i=0; i<dwRecs; i++) {
        // Pick up every record from 'arr' using 'i' as an index
        // and analyse every event, catching only keys and if the
        // printable symbols comes in - accumulate it in a string.
        // Here you can make sure user will not overrun the buffer.
        // Do not forget to echo symbols to 'hOutput'.
        // When carriage return comes in - terminate the line with
        // '\0' and react on that line, considering it as a command
        // from user. When a termination signal comes in - set 'bRun'
        // to FALSE ending the session.
      }
    }
  }
  delete [] arr;
}
This way ^^^ you work on a lower level then ReadConsole() and if bugs are there - you will 'fix' them with your own code and be OK and in full control over the input process.

Nice code sample too:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/reading_input_buffer_events.asp



Report
Re: try this... Posted by forumember on 6 Jul 2004 at 9:34 AM
i know about ReadConsoleInput function...
i guess i'll make a bug report to microsoft and will avoid using flush routine...

THANKS for your pantience with me

Report
Re: try this... Posted by AsmGuru62 on 6 Jul 2004 at 3:37 PM
: i know about ReadConsoleInput function...
: i guess i'll make a bug report to microsoft and will avoid using flush routine...
:
: THANKS for your pantience with me
:
:
I doubt that your report will be even investigated... but who knows?.. I sent a few reports in myself, but... Microsoft is too big to care about that, but they will respond to the "big" issues, like browser security or something of a sort.

BTW:

http://support.microsoft.com/default.aspx?scid=fh;EN-US;KBHOWTO

That is a good link to find out about Microsoft issues - they often post here issues and solutions. It is like a GOOGLE for Microsoft technologies.

I found this:

http://support.microsoft.com/default.aspx?scid=kb;en-us;137195

Maybe, we should not mix the ReadConsole() with FlushConsoleInputBuffer() too?.. I dunno...

Report
Re: try this... Posted by forumember on 6 Jul 2004 at 5:39 PM
i not actually submitted a bug report
i went to msdn newsgroups to ask there... right now i talking to someone...maybe he will say something additional that only ms guys can know...
if you interested i will put here his final answer...

as for this article about readconsole() and readconsoleinput()... it's said that the behaviour is by design. so you can't mix these two functions...
it is like mixing memory allocation methods in c++: new and malloc...
i guess it possible that flushconsoleinputbuffer() function can't be used with readconsole() but only with readconsoleinput()...
Report
Re: try this... Posted by AsmGuru62 on 7 Jul 2004 at 6:42 AM
: i not actually submitted a bug report
: i went to msdn newsgroups to ask there... right now i talking to someone...maybe he will say something additional that only ms guys can know...
: if you interested i will put here his final answer...
:
: as for this article about readconsole() and readconsoleinput()... it's said that the behaviour is by design. so you can't mix these two functions...
: it is like mixing memory allocation methods in c++: new and malloc...
: i guess it possible that flushconsoleinputbuffer() function can't be used with readconsole() but only with readconsoleinput()...
:
You've done some good diggin'!.. Nice... post the answer, if any...
Report
Re: try this... Posted by forumember on 10 Jul 2004 at 3:40 AM
finally i got a sutisfying answer.

To summarize things:

ReadConsole and FlushConsoleInputBuffer work as expected.
What happens is the following:
When LINE_INPUT mode is active ReadConsole reads input string till it encounters 'newline' character
So here is the catch... even when the input string is longer than the buffer, ReadConsole reads the entire string and stores it in some temporary buffer,THUS EMPTYING THE INPUT BUFFER.
So when the FlushConsoleInputBuffer is called, it has nothing left to do...THE INPUT BUFFER IS ALREADY EMPTY

by the way,i also got a recomendation not to use INPUT_LINE mode...

Report
Re: Thanks! Posted by AsmGuru62 on 10 Jul 2004 at 4:33 AM
Great work!..

1 2  Next



 

Recent Jobs

Official Programmer's Heaven Blogs
Web Hosting | Browser and Social Games | Gadgets

Popular resources on Programmersheaven.com
Assembly | Basic | C | C# | C++ | Delphi | Flash | Java | JavaScript | Pascal | Perl | PHP | Python | Ruby | Visual Basic
© Copyright 2011 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Operated by CommunityHeaven, a BootstrapLabs company.