· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.WIN32 —› console problem

Посл.отвђт Сообщенiе


Дата: Ноя 16, 2003 21:14:54

У меня проблема с консольным выводом. При использовании WriteConsole иногда, особенно при скором завершении программы, данные предварительно не до конца выводятся. И еще, как реализовать алгоритм в win "нажмите любую клавишу" с помощью api?


Дата: Ноя 16, 2003 22:05:16

Стандартный алгоритм:
1.Пишешь на С++ прогу с вызовом нужной функции(#include <conio.h>.... getch())
2.Компилишь её под Windows (option -W ),посмотри опции.
3.Открываешь .EXE файл HIEW (6.81),там и будет
push param2
push param1
...
call NeedProcName (getch()-->API)
4.Пишешь код на ASM.


Дата: Ноя 17, 2003 04:22:36

use_32
WriteConsole иногда ... данные ... не до конца выводятся.
Что возвращается в lpNumberOfCharsWritten?

реализовать алгоритм в win "нажмите любую клавишу"
WaitKey proc
  LOCAL NumOfEvents:DWORD
  LOCAL NumOfEventsRead:DWORD
  LOCAL ir:INPUT_RECORD
  LOCAL fDone:BOOL

  push ebx

  mov fDone,FALSE
  .while fDone != TRUE
    invoke GetNumberOfConsoleInputEvents, hCon, addr NumOfEvents
    xor ebx,ebx
    .while (ebx < NumOfEvents) && (fDone != TRUE)
      invoke ReadConsoleInput, hCon, addr ir, 1, addr NumOfEventsRead
      .if (ir.EventType == KEY_EVENT) && (ir.Event.KeyEvent.bKeyDown == TRUE)
        move fDone,TRUE
      .endif
      inc ebx
    .endw
  .endw
  pop ebx
  ret
WaitKey endp


Дата: Ноя 17, 2003 06:47:57 · Поправил: Grenader

q_q

"A process can specify a console input buffer handle in one of the wait functions to determine when there is unread console input. When the input buffer is not empty, the state of a console input buffer handle is signaled."
WaitKey proc
  local buffer: dword
  local NumberOfCharsRead: dword

WaitForKey:
  invoke WaitForSingleObject, hCon, INFINITE
  invoke ReadConsole, hCon, addr buffer, 1, addr NumberOfCharsRead, NULL
  cmp NumberOfCharsRead, 0 ; если кликнули мышкой и т.п.
  je WaitForKey

  ret
WaitKey endp

Примерно такой код проще, на мой взгляд.


Дата: Ноя 17, 2003 08:34:54

Grenader
Примерно говоришь. Ты его пробовал?
Для hCon = GetStdHandle(STD_INPUT_HANDLE), WaitForSingleObject сразу возвращает WAIT_OBJECT_0.
Консоль должна быть сконфигурирована так, чтобы ReadConsole завершался по любому символу, а не после <Enter> плюс, наверняка ненужно эхо.


Дата: Ноя 17, 2003 10:00:03

q_q
Для hCon = GetStdHandle(STD_INPUT_HANDLE), WaitForSingleObject сразу возвращает WAIT_OBJECT_0
Ты немного не прав. Мы ждем появления в буфере ЛЮБЫХ событий. И нет никакой гарантии, что к моменту вызова WaitForxxx буфер будет пуст. Если же вызвать FlushConsoleInputBuffer перед WaitForxxx, то все прекрасно работает. Вот пример рабочего кода (только что тестил):
Getch:
        push    eax
        invoke  GetConsoleMode, hCon, esp
        invoke  SetConsoleMode, hCon, ENABLE_PROCESSED_INPUT

        invoke  FlushConsoleInputBuffer, hCon
        invoke  WaitForSingleObject, hCon, INFINITE

        push    eax
        mov     eax, esp
        push    edx
        mov     edx, esp
        invoke  ReadConsole, hCon, eax, 1, edx, NULL
        add     esp, 8h

        invoke  SetConsoleMode, hCon
        ret


Можно и в этом случае использовать ReadConsoleInput - но зачем усложнять...


Дата: Ноя 17, 2003 11:09:21

Grenader
пример рабочего кода (только что тестил)
Точно тестил, где второй параметр второго SetConsoleMode?

ждем появления в буфере ЛЮБЫХ событий
Flush не решает всех возможных проблем.
Попробуй забрать фокус у консоли, например, мышкой активизировать другое окно, и WaitForSingleObject вернет управление.

use_32 > алгоритм ... "нажмите любую клавишу
Попробуй своим кодом поймать не символьную кнопку (eg Esc, Fn).


Дата: Ноя 17, 2003 13:41:36 · Поправил: Grenader

q_q

Точно тестил, где второй параметр второго SetConsoleMode?
Этот параметр уже в стеке, см. начало процедуры (push eax)

Попробуй своим кодом поймать не символьную кнопку
Надо ESC? Легко! :)
WaitKey proc
        local   ir: INPUT_RECORD
        local   count: dword

  WaitForEvent:
        invoke  WaitForSingleObject, hCon, INFINITE
        invoke  GetNumberOfConsoleInputEvents, hCon, addr count
        mov     edi, [esp]
        xor     ebx, ebx
  ReadInput:
        invoke  ReadConsoleInput, hCon, ir, 1, addr count
        cmp     ir.EventType, KEY_EVENT
        jne     @f
        cmp     ir.Event.KeyEvent.bKeyDown, 0
        sete    bl
  @@:
        dec     edi
        jnz     ReadInput
        test    ebx, ebx
        jz      WaitForKey
        ret
WaitKey endp

Пришлось конечно юзать ReadConsoleInput - но принцип тот же.


Дата: Ноя 18, 2003 04:08:04

Grenader
Этот параметр уже в стеке
Это я понимаю, почему бы не использовать call ведь invoke хочет два параметра.

Легко! ... принцип тот же
Куда это подевался Flush?
Еще немного подумаешь, избавишься от WaitFor и твой WaitKey практически не отличить от моего.


Дата: Ноя 18, 2003 09:32:41

q_q
Это я понимаю, почему бы не использовать call ведь invoke хочет два параметра
Мой invoke - не требует :) И вобще - я на FASM пишу, а на остальные диалекты транслирую - когда удачно, когда не очень. Но я согласен - надо получше тестить.

Еще немного подумаешь, избавишься от WaitFor и твой WaitKey практически не отличить от моего
Дело в принципе. Твой код использует цикл, внутри которого постоянно вызвает GetNumberOfConsoleInputEvents - ты не пробовал смотреть на загрузку процессора в этот момент? Это в старые добрые времена ДОС так писать можно было - а сейчас для приостановки потоков используются WaitForxxx. Мой код напрасно процессор не гоняет. Вот, собвственно, и вся разница. Принципиальная.
А Flush я взял так, скорее ради примера, что бы показать, что утверждение "Для hCon = GetStdHandle(STD_INPUT_HANDLE), WaitForSingleObject сразу возвращает WAIT_OBJECT_0" немного не верно :)
Чей вариант правильнее - думаю, любой программер скажет, даже не задумываясь.

PS Я отнюдь не стремлюсь всеми силами показать свою крутость, и непогрешимость. И всегда готов признать, что бываю (как и все) иногда неправ. Так что давай не будем превращать этот топик в выяснение отношений - "кто у кого больше ошибок найдет". Ок?


Дата: Ноя 18, 2003 10:07:19

Grenader
пробовал смотреть на загрузку процессора
С точки зрения теории Wait правильнее.
На практике, внутри подобных циклов я использую Sleep(100), что снижает загрузку процессора. В реальной жизни не сталкивался с необходимостью только ждать, обычно необходимо проверять, и если событий нет, то что-либо делать.

Ок?
q


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.087