i am actually using C++, but my question is language independent and more of a API question.
I've tried searching for the answer in several different places, but i cant figure out the correct keywords to describe the question because they all all very common words related to windows console programming. Finally:
How would i ask for input with a default value. Ex:
"Name: Joe"
and you can press backspace up to "Name: "
Right now i am guessing i might just have to launch another thread, ask for input, and than the separate thread will just simulate the keypresses, that just does not sound ideal. anyone have done anything like this before?
Misc:
Target is windows 7 (Version 6.1.7600) but don't think anything related has changed in API for a long time.
hi Joe
that's a good question - lol
i have never played with it, but you might try WriteConsoleInput
Thanks. don't need a second thread works fine:
int WriteInput(std::string s)
{
static HANDLE hConIn = GetStdHandle(STD_INPUT_HANDLE);
std::vector <INPUT_RECORD> ir;
DWORD n=0;
ir.resize(s.size());
for ( unsigned int i=0 ; i < ir.size(); i++ )
{
ir[i].EventType = KEY_EVENT;
ir[i].Event.KeyEvent.bKeyDown = TRUE;
ir[i].Event.KeyEvent.dwControlKeyState = 0;
ir[i].Event.KeyEvent.uChar.UnicodeChar = s[i];
ir[i].Event.KeyEvent.wRepeatCount = 1;
ir[i].Event.KeyEvent.wVirtualKeyCode = s[i];
ir[i].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(s[i], MAPVK_VK_TO_VSC);
}
WriteConsoleInput(hConIn,&ir[0],ir.size(),&n);
return 0;
}
int main()
{
WriteInput("Joe");
std::string x;
std::cout<< "Name: ";
std::cin>>x;
std::cout<<x;
return 0;
}
spoken like a true C programmer :P
Doesnt work with over 4 characters, oh well i figure something out. atleast in right direction now.
i am guessing that is because the OS is only allowing 4 keys to be pressed at once
for each char in the string, you need 2 event structures - one for key down, one for key up
(i would build them on the stack in a loop, then spit them out)
i can foresee another issue that you may run into
that is - a real key event occurs
this could ball up the works pretty nicely :P
although - the function is pretty fast
still, it might be prudent to flush the input buffer just before the WriteConsoleInput call
Quote from: joemc on June 24, 2011, 04:49:19 PM
Doesnt work with over 4 characters, oh well i figure something out. atleast in right direction now.
Try the attachment :bg
Quoteinclude \masm32\MasmBasic\MasmBasic.inc ; download (http://www.masm32.com/board/index.php?topic=12460.0)
Init
Open "O", #1, "YourData.txt"
PrintLine #1, Input$("Hobbies:\t", "Assembler, ") ; the prompt can contain a tab escape,
PrintLine #1, Input$("Profession:\t", "Programmer") ; and you can define a prefilled string
Close
Print "Bye"
Delay 1000
Exit
end start
that Jochen guy is SUCH a show off :P
i played with some code, but i must have a bug someplace
i may look at it again, tomorrow
push 0 ; looks unprofessional but it works better without MapVirtualKey
thanks :) works now
Quote from: joemc on June 25, 2011, 07:56:08 AM
push 0 ; looks unprofessional but it works better without MapVirtualKey
thanks :) works now
Yeah, it took me a while to test this out. With MVK, behaviour was a bit erratic; and MSDN says it may return 0 if translation is not needed. Besides, even umlauts work fine with the current version, so I'll leave it "as is".
that was my problem, as well
it is really strange that the only key-related member that needs to be set is "char"
;---------------------------------------------------------------------------------------------
ConInDefStr PROTO :DWORD,:DWORD,:DWORD,:DWORD
;---------------------------------------------------------------------------------------------
OPTION PROLOGUE:None
OPTION EPILOGUE:None
ConInDefStr PROC lpBuf:DWORD,dwLen:DWORD,szPrmptStr,szDefStr:DWORD
;Console Input with Prompt and Default Strings
;DednDave 6-2011
;
;Call With: lpBuf = address of input buffer
; dwLen = length of input buffer, less 1 for the terminator
; szPrmptStr = address of prompt string
; szDefStr = address of default input string
;
; Returns: EAX = length of user-input (buffer) string
;[EBP+28] = szDefStr
;[EBP+24] = szPrmtpStr
;[EBP+20] = dwLen
;[EBP+16] = lpBuf
;[EBP+12] = RET address
;[EBP+8] = saved EBX value
;[EBP+4] = saved ESI value
;[EBP] = saved EBP value
;[EBP-4] = standard input handle
;[EBP-8] = length of default string
push ebx
push esi
push ebp
mov ebp,esp
INVOKE GetStdHandle,STD_INPUT_HANDLE
push eax ;[EBP-4] = standard input handle
print [ebp+24] ;szPrmptStr
mov esi,[ebp+28] ;szDefStr
push 1
INVOKE StrLen,esi
pop ecx ;ECX = 1 (TRUE, KEY_EVENT, wRepeatCount)
xor edx,edx ;EDX = 0 (FALSE)
push eax ;[EBP-8] = length of szDefStr
jmp short Cids01
Cids00: movzx ebx,byte ptr [esi+eax]
shl ebx,16
;key up record
push edx ;KEY_EVENT_RECORD.dwControlKeyState = 0
push ebx ;KEY_EVENT_RECORD.wVirtualScanCode = 0, char = character
push ecx ;KEY_EVENT_RECORD.wRepeatCount = 1, wVirtualKeyCode = 0
push edx ;KEY_EVENT_RECORD.bKeyDown = FALSE (key up)
push ecx ;INPUT_RECORD.EventType = KEY_EVENT
;key down record
push edx ;KEY_EVENT_RECORD.dwControlKeyState = 0
push ebx ;KEY_EVENT_RECORD.wVirtualScanCode = 0, char = character
push ecx ;KEY_EVENT_RECORD.wRepeatCount = 1, wVirtualKeyCode = 0
push ecx ;KEY_EVENT_RECORD.bKeyDown = TRUE (key down)
push ecx ;INPUT_RECORD.EventType = KEY_EVENT
Cids01: dec eax
jns Cids00
INVOKE FlushConsoleInputBuffer,[ebp-4]
mov eax,[ebp-8]
mov edx,esp
shl eax,1
jz Cids02
push ecx
INVOKE WriteConsoleInput,[ebp-4],edx,eax,esp
pop eax
Cids02: push ecx
mov eax,esp
INVOKE ReadConsole,[ebp-4],[ebp+16],[ebp+20],eax,NULL
pop eax
leave
pop esi
pop ebx
ret 16
ConInDefStr ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;---------------------------------------------------------------------------------------------
attached is a demo program with source...
One more - source (30 lines) will come tonight :bg
:bg
Hobbies: Assembler
Profession: Script Kiddie
These are your hobbies: [Assembler]
... and your profession is [Script Kiddie]
Write to MyData.txt (y) ?
Quoteinclude \masm32\MasmBasic\MasmBasic.inc ; download (http://www.masm32.com/board/index.php?topic=12460.0)
Init
lea ebx, [4+Locate(y)] ; get current Y position, add 4 lines
xor ecx, ecx ; flag "round 2 needed"
.Repeat
.if ecx
Locate(0, ebx-1) ; set position to column 0, row ebx-1
PrintLine " Do not confuse hobby and profession, please!!", Chr$(7) ; bark at user
.endif
Locate(0, ebx) ; set position to column 0, row ebx
Let esi="These are your hobbies: ["+Input$(" Hobbies:\t", "Assembler")+"]"
Let edi=Input$(" Profession:\t", "Programmer") ; prompts may contain tabs
mov ecx, Instr_(edi, "program", 1) ; check for bad words, 1=case-insensitive
.Until !ecx
Inkey CrLf$, esi, CrLf$, "... and your profession is [", edi, "]", CrLf$, CrLf$, "Write to MyData.txt (y) ? "
.if al=="y"
Open "A", #1, "MyData.txt" ; append your strings to this file
Print #1, esi, CrLf$, "Prof=", edi, CrLf$
Close
.endif
Exit
end start
So it can be done in 22 lines :bg
(the bad news is you need at least MB version 30 June...)