Уважаемые коллеги! Не сталкивался ли кто с такой проблемой: Имеется консольное приложение. Для ввода данных из stdin используется небольшой буфер (16 байт для определенности). Нужно организовать ввод с помощью winapi (желательно CreateFile("CONIN$", ....) / ReadFile()) так, чтобы пользователь не мог ввести данных больше, чем вмещает буфер. Поясню на примере: Код (Text): #include <windows.h> CHAR Buff[16]; void main() { HANDLE hStdOut = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(hStdOut == INVALID_HANDLE_VALUE) ExitProcess(0); HANDLE hStdIn = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hStdIn == INVALID_HANDLE_VALUE) { CloseHandle(hStdOut); ExitProcess(0); } DWORD dwTemp; do { ReadFile(hStdIn, Buff, sizeof(Buff), &dwTemp, NULL); dwTemp = dwTemp < 2 ? 0 : dwTemp - 2; Buff[dwTemp] = 0; WriteFile(hStdOut, Buff, lstrlen(Buff), &dwTemp, NULL); WriteFile(hStdOut, "\n", 1, &dwTemp, NULL); } while(lstrcmp(Buff, "exit")); CloseHandle(hStdIn); CloseHandle(hStdOut); ExitProcess(0); } Пользователь может ввести до 256-и байт (по крайней мере в win2k sp4), после чего выполнится несколько итераций цикла. Долго курил в MSDN и гугл, все что нашел - топик на rsdn 2004 года без единого ответа. В итоге пришел к такому методу: Код (Text): #include <windows.h> HANDLE hStdIn, hStdOut; DWORD dwTemp; CHAR Buff[16]; // Ввод одного символа CHAR InChar() { DWORD dwTemp; CHAR nChar = 0; ReadFile(hStdIn, &nChar, 1, &dwTemp, NULL); return nChar; } // Вывод одного символа VOID OutChar(CHAR nChar) { DWORD dwTemp; WriteFile(hStdOut, &nChar, 1, &dwTemp, NULL); } // Ввод строки из stdin посимвольно DWORD InString(PCHAR szString, DWORD dwBuffSize) { DWORD dwSaveSize, dwSize = 0; PCHAR lpStr = szString; CHAR nChar; // оставляем один байт под терминатор dwBuffSize--; while((nChar = InChar()) != '\r') { dwSaveSize = dwSize; if(nChar == '\x08') { // backspace if(dwSize) { lpStr--; dwSize--; WriteFile(hStdOut, "\x08\x20\x08", 3, &dwTemp, NULL); } continue; } // игнорируем служебные символы // в частности - табуляцию, ибо одним пробелом при // нажатии backspace не затрешь if(((BYTE)nChar >= 32)&&(dwSize < dwBuffSize)) { dwSize++; *lpStr++ = nChar; OutChar(nChar); } } OutChar('\n'); *lpStr = 0; return dwSize; } int main() { hStdOut = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(hStdOut == INVALID_HANDLE_VALUE) ExitProcess(0); hStdIn = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hStdIn == INVALID_HANDLE_VALUE) { CloseHandle(hStdOut); ExitProcess(0); } // для посимвольного ввода-вывода SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), 0); do { InString(Buff, sizeof(Buff)); WriteFile(hStdOut, Buff, lstrlen(Buff), &dwTemp, NULL); WriteFile(hStdOut, "\n", 1, &dwTemp, NULL); } while(lstrcmp(Buff, "exit")); CloseHandle(hStdIn); CloseHandle(hStdOut); ExitProcess(0); return 0; } Тут все работает, как надо, но нет таких удобных вещей, как истории ввода, работающих кнопочек home/end и тп... Хотелось бы реализовать сабж как-нибудь попроще, но пока не получается. Пользоваться ReadConsoleInput() что-то совсем не хочется. Посоветуйте что-нибудь.
n0hack немного не уловил идею ну что с того, что он введет данных больше?? считываются только 16 байт, не больше. уточни задачу обрисуй предельно ясно т.к. ничего не понятно, что ты хочешь сделать
driver Пардон? ((((: Magnum А Вы подумайте, что будет, если я попрошу пользователя ввести сначала его имя, а потом фамилию первым способом
Есть конечно сделать Buff[256], но меня интересует именно как не позволить юзверю ввести более N символов.
n0hack чисто интуитивно что-то мне подсказывает, что там где есть CreateFile, там есть и SetFilePointer и GetFilePointer следовательно запомнить метку начала ввода и далее через GetFilePointer считать число введенных символов
Magnum Ага, я тоже так думал Не канает SetFilePointer с консолью. И к тому же эту функцию можно использовать только по схеме "позволить пользователю ввести сколько ему захочется, а потом отбросить лишнее, чтобы не мешалось при следующем чтении". А задача стоит - НЕ ДАТЬ пользователю ввести более, чем положено.
n0hack да в цикл возьми если длина строки > заданной --- тогда очишаешь строчку в консоли, возвращаешь указатель на место и пусть вводит строку повторно
девайс, я чего то тоже неуловил про "наш сайт" =\ n0hack, красиво всё, и в коде будет красиво, и на экране( ты только представь: сейчас хрен где найдёшь консольную прогу, которая с цветами работает или позицию курсора устанавливает! )
Ну, как выяснилось, работать с конcолью "на низком уровне" в терминологии MS не так страшно - пара вечеров, примерно 500 строк кода на си и все работает, как часы. Но я бы не советовал никому этим заниматься без явной нужды. Код не выкладываю - сыроват пока.