Создание консольных приложений в 64-разрядной Windows

Тема в разделе "WASM.X64", создана пользователем Mikl___, 15 мар 2019.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786
    Создаю папку masm64, в каталоге masm64 создаю подкаталоги bin, include, lib, examples. В каталоги include, lib копирую содержимое masm64.zip Содержимое для каталога bin (cvtres.exe, link.exe, ml64.exe, msobj80.dll, mspdb80.dll, msvcp80.dll, msvcp90.dll, msvcr80.dll, msvcr90.dll, rc.exe, rc.hlp, rcdll.dll) взято из комплекта C++ компиляторов от Microsoft Microsoft Windows SDK for Windows 7 and .NET Framework 4 (распространяется бесплатно)
    Создаю в папке Include файл win64a.inc следующего содержания
    Код (ASM):
    1. OPTION DOTNAME
    2. OPTION PROLOGUE:rbpFramePrologue
    3. OPTION EPILOGUE:none
    4. include win64.inc
    5. include temphls.inc
    6. include kernel32.inc
    7. includelib kernel32.lib
    8. include ntdll.inc
    9. includelib ntdll.lib
    10. include user32.inc
    11. includelib user32.lib
    12. ;---------------------------
    13. pushaddr macro x
    14. db 68h
    15. dd x
    16. endm
    17. IMAGE_BASE equ 400000h
    18. ;---------------------------------
    19. include gdi32.inc
    20. includelib gdi32.lib
    21. ;---------------------------------
    22. include comctl32.inc
    23. includelib comctl32.lib
    24. include comdlg32.inc
    25. includelib comdlg32.lib
    26. include shell32.inc
    27. includelib shell32.lib
    28. ;--------------------------------
    29. du macro string
    30. local bslash
    31. bslash = 0
    32. irpc c,<string>
    33. if bslash eq 0
    34. if '&c' eq "/"
    35.         bslash = 1
    36. elseif '&c'gt 127
    37. db ('&c'- 0B0h),4
    38. else
    39. dw '&c'
    40. endif
    41. else
    42.            bslash = 0
    43.            if '&c' eq "n"
    44.            DW 0Dh,0Ah
    45.            elseif '&c' eq "/"
    46.            dw '/'
    47.            elseif '&c' eq "r"
    48.            dw 0Dh
    49.            elseif '&c' eq "l"
    50.            dw 0Ah
    51.            elseif '&c' eq "s"
    52.            dw 20h
    53.            elseif '&c' eq "c"
    54.            dw 3Bh
    55.            elseif '&c' eq "t"
    56.            dw 9
    57.    endif
    58. endif
    59. endm
    60. dw 0
    61. endm
    Пишу bat-файл следующего содержания
    Код (Text):
    1. cls
    2. set masm64_path=\masm64\
    3. set filename= <--- здесь будет имя asm-файла
    4. del %filename%.exe
    5. %masm64_path%bin\ml64 /Cp /c /I"%masm64_path%Include" %filename%.asm || exit
    6. %masm64_path%bin\link /SUBSYSTEM:CONSOLE /LIBPATH:"%masm64_path%Lib" ^
    7. /entry:WinMain %filename%.obj /LARGEADDRESSAWARE:NO ^
    8. /ALIGN:16 /SECTION:.text,W /BASE:0x400000 || exit
    9. del %filename%.obj
    Запрос и освобождение консоли
    Программа, работающая в консольном режиме, либо наследует текущую консоль, либо открывает новую, если наследовать нечего. Примеры программ ниже создают для себя собственную консоль. Любые изменения в окне консоли будут касаться только этой консоли и не будут отражаться в наследованной консоли. Для создания консоли используется функция AllocConsole. Функция не имеет аргументов и предоставляет вызвавшей ее программе новую консольную сессию. При успешном завершении функция AllocConsole возвращает ненулевое значение, при возникновении ошибки ― ноль. Все выделенные консоли автоматически освобождаются при завершении запросившей их программы.
    При выделении консоли будет создано окно, которое имеет те же свойства (почти :)), что и окно Windows в GUI-программе. Оно содержит заголовок, системное меню, кнопки минимизации, полноэкранной развертки, закрытия окна и вертикальную и горизонтальную линейки прокрутки.
    Программа, которая будет работать в консольном режиме и будет использовать собственную консоль, прежде чем запросить новую консоль должна освободить унаследованную консоль с помощью функции FreeConsole. Функция не имеет аргументов. При успешном завершении функция FreeConsole возвращает ненулевое значение, при возникновении ошибки ― ноль.
    Все программы ниже будут начинаться с
    Код (ASM):
    1.    invoke  FreeConsole;освободить существующую консоль
    2.    invoke  AllocConsole;создать консоль для себя
    Даже если родительская консоль отсутствует, вызов FreeConsole не повлечет за собой нежелательных последствий и новая консоль будет создана. Консоль, предоставленная программе автоматически освобождается при завершении программы, либо программа может принудительно освободить консоль функцией FreeConsole.
    Определение заголовка окна консоли
    Для формирования строки заголовка используется функция SetConsoleTitle. Если в строке заголовка есть кириллица, то заголовок должен быть сохранен в кодировке 866cp. Если функцию SetConsoleTitle не использовать, то в заголовке консольного окна будет отображается полный путь до консольного приложения. При успешном завершении функция SetConsoleTitle возвращает ненулевое значение, при возникновении ошибки ― ноль.
    Получение стандартных дескрипторов ввода и вывода
    Большинству функций, которые поддерживают консольный интерфейс, для выполнения операций ввода/вывода требуются стандартные дескрипторы связанные со стандартными потоками ввода и вывода. Стандартный поток ввода связан с клавиатурой, мышью, файлами. Стандартный поток вывода ― с экраном, принтером, файлами. Для получения стандартного дескриптора используется функция GetStdHandle с единственным аргументом dwStdDev
    dwStdDevзначениеназначение
    STD_INPUT_HANDLE
    -10​
    стандартный поток ввода
    STD_OUTPUT_HANDLE
    -11​
    стандартный поток вывода
    STD_ERROR_HANDLE
    -12​
    стандартный поток ошибок
    Функция GetStdHandle возвращает дескриптор запрашиваемого потока либо значение INVALID_HANDLE_VALUE в случае ошибки.
    Вывод текста в консоли
    Один из способов вывести текст в консоль ― использовать функцию WriteConsole
    Код (C):
    1. BOOL WriteConsole (
    2.            HANDLE hConOut, // дескриптор потока вывода
    3.            CONST VOID * lpString, // указатель на выводимую строку
    4.            DWORD dwLen, // количество выводимых символов
    5.            LPDWORD lpdwNumWritten, // действительное количество выводимых символов
    6.            LPVOID lpNotUsed /* зарезервирован */
    7. );
    Строка выводится с текущими цветовыми атрибутами для текста и фона. Вывод начинается с текущей позиции курсора. Позиция курсора автоматически изменяется после вывода очередной строки.
    При успешном завершении функция WriteConsole возвращает ненулевое значение, при возникновении ошибки ― ноль.
    Ввод из консоли
    Для чтения из клавиатуры используется функция ReadConsole
    Код (C):
    1. BOOL ReadConsole (
    2.            HANDLE hConIn, // дескриптор входного потока
    3.            LPVOID * lpBuf, // указатель на массив символов, в который будет записана строка
    4.            DWORD dwLen, // возможное количество вводимых символов (величина буфера)
    5.            LPDWORD lpdwNumRead, // количество фактически введенных символов
    6.            LPVOID lpNotUsed /* зарезервирован */
    7. );
    При успешном завершении функция ReadConsole возвращает ненулевое значение, при возникновении ошибки ― ноль. Действие функции ReadConsole определяется с помощью функции SetConsoleMode
    Установка позиции курсора
    Текущая позиция курсора на экране устанавливается функцией SetConsoleCursorPosition
    Код (C):
    1. SetConsoleCursorPosition (
    2.            HANDLE hConOut, // дескриптор стандартного вывода
    3.            COORD XY /* структура типа COORD, содержащая координаты нового курсора*/
    4. );
    Код (ASM):
    1. COORD struct
    2.    dw X
    3.    dw Y
    4. COORD ends
    При успешном завершении функция SetConsoleCursorPosition возвращает ненулевое значение, при возникновении ошибки ― ноль.
    содержимое asm-файла
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. BLACK   equ 0
    4. BLUE    equ 1
    5. GREEN   equ 2
    6. CYAN    equ 3
    7. RED equ 4
    8. PURPLE  equ 5
    9. YELLOW  equ 6
    10. SYSTEM  equ 7
    11. GREY    equ 8
    12. BRIGHTBLUE equ 9
    13. BRIGHTGREEN equ 10
    14. BRIGHTCYAN equ 11
    15. BRIGHTRED equ 12
    16. BRIGHTPURPLE equ 13
    17. BRIGHTYELLOW equ 14
    18. WHITE   equ 15
    19. MAXSCREENX = 80
    20. MAXSCREENY = 25
    21. buffersize = 200
    22. X = 0
    23. Y = 10
    24. .code
    25. WinMain proc
    26. local LENS:qword ;количество выведенных символов
    27. local BUFF[buffersize]:byte
    28. local ConsoleWindow:SMALL_RECT
    29.  
    30.         invoke  FreeConsole;освободить существующую консоль
    31.         invoke  AllocConsole;создать консоль для себя
    32.         invoke  GetStdHandle,STD_OUTPUT_HANDLE;получить handle для вывода
    33.         mov hOut,rax
    34.         invoke  GetLargestConsoleWindowSize,eax
    35. ;   rax return in 31-16 bits: dwCoord.y
    36. ;                 15-00 bits: dwCoord.x
    37.         lea r8d,ConsoleWindow
    38.         and dword ptr [r8+SMALL_RECT.Left],0;mov [r8+SMALL_RECT.Left],0
    39.                                            ;mov [r8+SMALL_RECT.Top],0
    40.          sub ax, MAXSCREENX
    41.         sbb edx, edx
    42.         and ax, dx
    43.        add ax, MAXSCREENX-1
    44. mov [r8+SMALL_RECT.Right],ax
    45. shr eax, 16
    46. sub eax, MAXSCREENY
    47. sbb edx, edx
    48. and eax, edx
    49. add eax, MAXSCREENY-1
    50. mov [r8+SMALL_RECT.Bottom],ax
    51.                   invoke  SetConsoleWindowInfo,hOut,TRUE
    52. invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX;establish the new size of a window of the console
    53.         invoke  SetConsoleTitle,&STR2     ;создать заголовок окна консоли
    54.         invoke  SetConsoleCursorPosition,hOut,Y*10000h+X;установить позицию курсора
    55.         invoke  SetConsoleTextAttribute,hOut,BRIGHTGREEN ;задать цветовые атрибуты выводимого текста
    56.         invoke  WriteConsole,hOut,&STR1,sizeof STR1,&BUFF,0 ;вывести строку
    57.         invoke  GetStdHandle,STD_INPUT_HANDLE        ;получить HANDLE для ввода
    58.         invoke  ReadConsole,eax,&BUFF,buffersize,&LENS,0     ;ждать ввода строки
    59.         invoke  SetConsoleTextAttribute,hOut,BRIGHTCYAN ;задать цветовые атрибуты выводимого текста
    60.         lea     r9d,LENS
    61.         mov     r8d,[r9]        ;длина вводимой строки
    62.         invoke  WriteConsole,hOut,&BUFF,,,0
    63.         invoke  Sleep,3000        ;небольшая задержка
    64.         invoke  FreeConsole     ;закрыть консоль
    65.         invoke RtlExitUserProcess,NULL;завершить программу
    66. WinMain endp
    67. STR1 db 'Enter line of any symbols and press "Enter":',13,10
    68. STR2 db 'Iczelion''s tutorial #38a',0
    69. hOut dq ?
    70. end
    Здесь исходный текст программы и ехе-файл
    0.png
    Очередные улучшения
    Добавляю в папку bin файл stubby.exe следующего содержания:
    немного меняю содержимое bat-файла
    Код (Text):
    1. cls
    2. set masm64_path=\masm64\
    3. set filename= <--- здесь будет имя asm-файла
    4. del %filename%.exe
    5. %masm64_path%bin\ml64 /Cp /c /I"%masm64_path%Include" %filename%.asm || exit
    6. %masm64_path%bin\link /SUBSYSTEM:CONSOLE /LIBPATH:"%masm64_path%Lib" ^
    7. /entry:WinMain %filename%.obj /LARGEADDRESSAWARE:NO ^
    8. /ALIGN:16 /SECTION:.text,W /BASE:0x400000 /STUB:%masm64_path%\bin\stubby.exe || exit
    9. del %filename%.obj
    Это на сотню байтов уменьшает исходный ехе-файл.
    Установка цвета символов и цвета фона в консольном приложении
    В отличие от GUI-приложений, где можно использовать всю цветовую палитру системы, в консольном приложении цвет задается всего одним байтом, младшие 4 разряда отвечают за цвет текста, а старшие 4 разряда ― за цвет фона. Соответственно, доступны комбинации из 24=16 цветов фона и столько же цветов для текста.
    константачислоцвет
    деся-
    тич-
    ное​
    двоичное
    inten-
    sity
    redgreenblue
    BLACK
    0​
    0​
    0​
    0​
    0​
    BLUE
    1​
    0​
    0​
    0​
    1​
    GREEN
    2​
    0​
    0​
    1​
    0​
    CYAN
    3​
    0​
    0​
    1​
    1​
    RED
    4​
    0​
    1​
    0​
    0​
    PURPLE
    5​
    0​
    1​
    0​
    1​
    YELLOW
    6​
    0​
    1​
    1​
    0​
    SYSTEM
    7​
    0​
    1​
    1​
    1​
    GREY
    8​
    1​
    0​
    0​
    0​
    BRIGHTBLUE
    9​
    1​
    0​
    0​
    1​
    BRIGHTGREEN
    10​
    1​
    0​
    1​
    0​
    BRIGHTCYAN
    11​
    1​
    0​
    1​
    1​
    BRIGHTRED
    12​
    1​
    1​
    0​
    0​
    BRIGHTPURPLE
    13​
    1​
    1​
    0​
    1​
    BRIGHTYELLOW
    14​
    1​
    1​
    1​
    0​
    WHITE
    15​
    1​
    1​
    1​
    1​
    По умолчанию цвет фона в консоли черный, а цвет символов ― белый. Цвета можно изменить при помощи функции SetConsoleTextAttribute
    Код (C):
    1. SetConsoleTextAttribute (
    2.            HANDLE hConOut, // дескриптор потока вывода
    3.            color /* формируется путем объединения цветов фона и символов */
    4. );
    константачислоЗначение
    hexдвоичное
    ФонТекст
    ii
    FOREGROUND_BLUE
    1​
    00000001Цвет текста содержит синюю компоненту
    FOREGROUND_GREEN
    2​
    00000010Цвет текста содержит зеленую компоненту
    FOREGROUND_RED
    4​
    00000100Цвет текста содержит красную компоненту
    FOREGROUND_INTENSITY
    8​
    00001000Цвет текста имеет повышенную интенсивность
    BACKGROUND_BLUE
    10​
    00010000Цвет фона содержит синюю компоненту
    BACKGROUND_GREEN
    20​
    00100000Цвет фона содержит зеленую компоненту
    BACKGROUND_RED
    40​
    01000000Цвет фона содержит красную компоненту
    BACKGROUND_INTENSITY
    80​
    10000000Цвет фона имеет повышенную интенсивность
    Содержимое asm-файла
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. LEFT       = 8
    6. TOP    = 4
    7. buffersize   = 100
    8. .code
    9. WinMain proc
    10. local BUFF[buffersize]:byte
    11. local result:qword
    12. local ConsoleWindow:SMALL_RECT
    13. local cci:CONSOLE_CURSOR_INFO
    14. local MOUSE_KEY:INPUT_RECORD
    15. local color:qword
    16. local coord:COORD
    17.  
    18.         invoke FreeConsole
    19.         invoke AllocConsole
    20.         invoke GetStdHandle,STD_INPUT_HANDLE
    21.         mov hIn,rax
    22.         invoke GetStdHandle,STD_OUTPUT_HANDLE
    23.         mov hOut,rax
    24. invoke GetLargestConsoleWindowSize,eax
    25. ;   eax return in 31-16 bits: dwCoord.y
    26. ;                 15-00 bits: dwCoord.x
    27.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    28.     and dword ptr [r8+SMALL_RECT.Left],0;mov [r8+SMALL_RECT.Left],0
    29.     ;mov [r8+SMALL_RECT.Top],0
    30.     sub ax,MAXSCREENX
    31.     sbb edx,edx
    32.     and ax,dx
    33.     add ax,MAXSCREENX-1
    34.     mov [r8+SMALL_RECT.Right],ax
    35.     shr eax,16
    36.     sub eax,MAXSCREENY
    37.     sbb edx,edx
    38.     and eax,edx
    39.     add eax,MAXSCREENY-1
    40.     mov [r8+SMALL_RECT.Bottom],ax
    41.     invoke  SetConsoleWindowInfo,hOut,TRUE
    42.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX;establish the new size of a window of the console
    43.     invoke  SetConsoleTitle,&Str1
    44. ;прячем курсор----------------------------------------
    45.     invoke  GetConsoleCursorInfo,hOut,&cci
    46.         lea edx,cci             ; lpConsoleCursorInfo
    47.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    48.     invoke  SetConsoleCursorInfo,hOut
    49. ;------------------------------------------------------
    50.         invoke WriteConsole,hOut,&Str2,sizeof Str2,&result,0
    51.         mov coord.x,LEFT
    52.         and color,0
    53. @0:     mov coord.y,TOP
    54. @@:     invoke SetConsoleCursorPosition,hOut,coord
    55.         ; To establish color and a background of the text of the console
    56.         ; 4-7 бит - background color
    57.         ; 0-3 бит - text color
    58.         ; other bits aren't used
    59.         invoke SetConsoleTextAttribute,hOut,color
    60. invoke wsprintf,&BUFF,&fmt,color
    61.         invoke WriteConsole,hOut,&BUFF,eax,&result,0
    62.         inc coord.y
    63.        inc color
    64.        cmp coord.y,TOP+16
    65.        jb @b
    66.       add coord.x,4
    67.       cmp coord.x,16*4+LEFT
    68.       jb @0
    69. @@:    invoke ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    70.         lea eax,MOUSE_KEY
    71.         cmp [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    72.     je @b
    73.     cmp [rax+INPUT_RECORD.EventType],KEY_EVENT
    74.     jne @b
    75.     cmp [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    76.     jne @b
    77.         invoke FreeConsole
    78.         invoke RtlExitUserProcess,NULL
    79. WinMain endp
    80. Str1 db 'Installation of color of symbols and background of the text of the console',0
    81. Str2 db 'For exit press ESC or CTRL+C'
    82. fmt  db '%.3d',0
    83. hIn dq ?
    84. hOut dq ?
    85. end
    Для установки цвета текста в консоли, перед выводом текста используется функция SetConsoleTextAttribute.
    Здесь исходный текст программы и ехе-файл
    2.png
    Консольное приложение. "Градиентная заливка"
    asm-файл
    Код (ASM):
    1.  
    2. ; CONSOLE #
    3. include win64a.inc
    4. MAXSCREENX = 80
    5. MAXSCREENY = 25
    6. LEFT       = 8
    7. TOP    = 4
    8. buffersize = 100
    9. .code
    10. WinMain proc
    11. local BUFF[buffersize]:byte
    12. local result:qword
    13. local ConsoleWindow:SMALL_RECT
    14. local cci:CONSOLE_CURSOR_INFO
    15. local MOUSE_KEY:INPUT_RECORD
    16. local color:dword
    17. local count:dword
    18. local coord:COORD
    19.  
    20.         invoke  FreeConsole
    21.         invoke  AllocConsole
    22.         invoke  GetStdHandle,STD_INPUT_HANDLE
    23.         mov hIn,rax
    24.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    25.         mov     hOut,rax
    26.         invoke GetLargestConsoleWindowSize,eax
    27. ;   eax return in 31-16 bits: dwCoord.y
    28. ;                 15-00 bits: dwCoord.x
    29.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    30.         and dword ptr [r8+SMALL_RECT],0
    31. ;   ConsoleWindow.Left = 0
    32. ;   ConsoleWindow.Top = 0
    33.     sub ax, MAXSCREENX
    34.     sbb edx, edx
    35.     and ax, dx
    36.     add ax, MAXSCREENX-1
    37.     mov [r8+SMALL_RECT.Right],ax
    38.     shr eax, 16
    39.     sub eax, MAXSCREENY
    40.     sbb edx, edx
    41.     and eax, edx
    42.     add eax, MAXSCREENY-1
    43.     mov [r8+SMALL_RECT.Bottom],ax
    44.     invoke SetConsoleWindowInfo,hOut,TRUE
    45.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX  ;establish the new size of a window of the console
    46.     invoke  SetConsoleTitle,&Str1
    47. ;hide cursor----------------------------------------
    48.     invoke  GetConsoleCursorInfo,hOut,&cci
    49.         lea edx,cci                 ; lpConsoleCursorInfo
    50.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    51.     invoke  SetConsoleCursorInfo,hOut
    52. ;------------------------------------------------------
    53.         invoke  WriteConsole,hOut,&Str2,sizeof Str2,&result,0
    54.         mov     count,0Fh
    55.     mov     coord,10000h    ; X=0 Y=1
    56. @0:     mov     color,0Fh
    57. @@:     invoke  SetConsoleCursorPosition,hOut,coord
    58.     ; To establish color and a background of the text of the console
    59.         ; 4-7 bits - background color
    60.         ; 0-3 bits - text color
    61.         ; other bits aren't used
    62.         invoke  SetConsoleTextAttribute,hOut,color
    63.         invoke  WriteConsole,hOut,&Str3,1,&result,0
    64.         inc     color
    65.     inc     coord.x
    66.     cmp     coord.x,MAXSCREENX
    67.     jb @b
    68.     dec     count
    69.     mov eax,count
    70.     mov     color,eax
    71.     inc     coord.y
    72.         mov coord.x,0
    73.     cmp coord.y,MAXSCREENY-1
    74.     jnz @b
    75. ;------------------------------------------------------------------
    76. @@: invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    77.         lea     eax,MOUSE_KEY
    78.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    79.     je @b
    80.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    81.     jne     @b
    82.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    83.     jne     @b
    84.         invoke  FreeConsole
    85.         invoke  RtlExitUserProcess,NULL
    86. WinMain endp
    87. hIn dq ?
    88. hOut dq ?
    89. Str1 db 'Installation of color of symbols and background of the text of the  console application',0
    90. Str2 db 'For exit press ESC or CTRL+C or CTRL+Break'
    91. Str3 db 'o'
    92. end
    Здесь исходный текст программы и ехе-файл
    3.png
    Простое консольное приложение
    asm-файл
    Код (ASM):
    1.  
    2. ; CONSOLE #
    3. include win64a.inc
    4. includelib msvcrt.lib
    5. MAXSCREENX = 80
    6. MAXSCREENY = 25
    7. buffersize = 200
    8. .code
    9. WinMain proc
    10. local coord:COORD
    11. local BUFF[buffersize]:byte
    12. local ConsoleWindow:SMALL_RECT
    13. local result:qword
    14. local dwLength:dword
    15. local cci:CONSOLE_CURSOR_INFO
    16. local MOUSE_KEY:INPUT_RECORD
    17.  
    18.         invoke  FreeConsole         ; release the existing console
    19.         invoke  AllocConsole            ; create the console
    20.         invoke  GetStdHandle,STD_INPUT_HANDLE            ; receive handle for a input
    21.         mov hIn,rax
    22.         invoke  GetStdHandle,STD_OUTPUT_HANDLE            ; receive handle for a output
    23.         mov hOut,rax
    24.     invoke  GetLargestConsoleWindowSize,eax
    25. ;   eax return in 31-16 bits: dwCoord.y
    26. ;                 15-00 bits: dwCoord.x
    27.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    28.     and dword ptr [r8+SMALL_RECT],0
    29. ;   ConsoleWindow.Left = 0  ConsoleWindow.Top = 0
    30.     sub ax, MAXSCREENX
    31.     sbb edx, edx
    32.     and ax, dx
    33.     add ax, MAXSCREENX-1
    34.     mov [r8+SMALL_RECT.Right],ax
    35.     shr eax, 16
    36.     sub eax, MAXSCREENY
    37.     sbb edx, edx
    38.     and eax, edx
    39.     add eax, MAXSCREENY-1
    40.     mov [r8+SMALL_RECT.Bottom],ax
    41. invoke SetConsoleWindowInfo,hOut,TRUE            ; bAbsolute
    42. ;------------------------------------------------------------------
    43.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX  ; establish the new size of console window
    44.     invoke  SetConsoleTitle,&NameConsole         ; definition of a title bar
    45. ;------------------------------------------------------------------------
    46.     invoke  WriteConsole,hOut,&Str1,sizeof Str1,&BUFF,0            ; display a line of symbols
    47. ;hide cursor----------------------------------------
    48.     invoke  GetConsoleCursorInfo,hOut,&cci
    49.     lea edx,cci             ; lpConsoleCursorInfo
    50.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    51.     invoke  SetConsoleCursorInfo,hOut
    52. ;------------------------------------------------------
    53. ;demonstration of positioning of the cursor
    54.         mov coord,10000h    ;y=1 x=0
    55. @@: movzx   r9d,coord.y
    56.     movzx   r8d,coord.x
    57.     invoke  sprintf,&BUFF,&fmt1
    58.     mov     dwLength,eax
    59.         invoke  SetConsoleCursorPosition,hOut,coord    ; establish a cursor position
    60.         invoke  WriteConsole,hOut,&BUFF,dwLength,&result,0            ; display a line of symbols
    61.         add coord,10005h            ; x = x + 5  y = y + 1
    62.     cmp coord.y,10
    63.     jb @b
    64. ; change of color of symbols
    65.     invoke  SetConsoleCursorPosition,hOut,0C0000h    ; establish a cursor position
    66.     invoke SetConsoleTextAttribute,hOut,FOREGROUND_BLUE or BACKGROUND_GREEN     ; set color attributes of the output text
    67.     invoke  WriteConsole,hOut,&Str3,sizeof Str3,&result,0            ; display a line of symbols
    68.     invoke  SetConsoleTextAttribute,hOut,FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED     ; set color attributes of the output text
    69.     invoke  SetConsoleCursorPosition,hOut,0E0000h    ; establish a cursor position
    70.     invoke WriteConsole,hOut,&Str4,sizeof Str4,&result,0            ; display a line of symbols
    71. ; reading the entered line
    72.     invoke  ReadConsole,hIn,&BUFF,80,&result,0         ; wait for input of a line of symbols
    73.     mov rax,result
    74.     lea esi,BUFF
    75.     mov byte ptr [rax+rsi-2],0      ; 2 symbols CR and LF
    76. ; remove ASCII code of the entered symbols
    77.     xor eax,eax
    78.     mov dwLength,eax
    79. @@: lodsb
    80.     or eax,eax
    81.     jz @f
    82.     invoke  printf,&fmt2,eax
    83.     add dwLength,eax
    84.     jmp @b
    85. @@: mov r8d,dwLength
    86.     neg r8                  ; length of the removed line
    87.     invoke  WriteConsole,hOut,&BUFF,,&result,0
    88. ; it is possible to use the functions printf, gets, etc.
    89.     invoke  printf,&Str5
    90.     invoke  gets,&BUFF
    91.     invoke  printf,&fmt3,&BUFF
    92.     invoke  printf,&Str2
    93. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    94.         lea     eax,MOUSE_KEY
    95.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    96.     je @b
    97.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    98.     jne     @b
    99.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    100.     jne     @b
    101.         invoke  FreeConsole;закрываем консоль
    102.     invoke RtlExitUserProcess,NULL
    103. WinMain endp
    104. hOut dq ?
    105. hIn dq ?
    106. NameConsole db 'Simple example of console',0
    107. Str1    db 'This is sample output string',13,10
    108. Str2    db 'For exit from program press ESC or CTRL+C or CTRL+Break',0
    109. Str3    db 'This is Blue text on Green background'
    110. Str4    db 'Enter a line of symbols and you can to see ASCII-code of symbols: ',13,10
    111. Str5    db 0Dh,0Ah,'This is a test. Enter another string: ',13,10,0
    112. fmt1    db "Text position X=%d, Y=%d",0
    113. fmt2    db "%X ",0
    114. fmt3    db "%s",13,10,0
    115. end
    Программа демонстрирует изменение позиции курсора с помощью функции SetConsoleCursorPosition, изменение цветов фона и символов (SetConsoleTextAttribute), чтение введенной строки через ReadConsole, использование printf и gets, вывод ASCII-кода введенных символов строки, завершение программы по нажатию на клавишу "Esc".
    Здесь исходный текст программы и ехе-файл
    4.png
     

    Вложения:

    • 5.png
      5.png
      Размер файла:
      57,1 КБ
      Просмотров:
      3.145
    • masm64.zip
      Размер файла:
      558,8 КБ
      Просмотров:
      1.110
    • asm2.zip
      Размер файла:
      794 байт
      Просмотров:
      766
    • 01.zip
      Размер файла:
      2,2 КБ
      Просмотров:
      753
    Последнее редактирование: 26 сен 2019
    C0deWarri0r, Alex81524, CrawlUp и 5 другим нравится это.
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786
    Прогресс-бар в консольной программе
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. colors1 = 159
    6. colors2 = 249
    7. .code
    8. WinMain proc
    9. local result:qword
    10. local ConsoleWindow:SMALL_RECT
    11. local cci:CONSOLE_CURSOR_INFO
    12. local CSBI:CONSOLE_SCREEN_BUFFER_INFO
    13. local MOUSE_KEY:INPUT_RECORD
    14.  
    15.        invoke FreeConsole
    16.         invoke  AllocConsole
    17.         invoke  GetStdHandle,STD_INPUT_HANDLE
    18.         mov     hIn,rax
    19.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    20.         mov     hOut,rax
    21.         invoke GetLargestConsoleWindowSize,eax
    22. ;   eax return in 31-16 bits: dwCoord.y
    23. ;                 15-00 bits: dwCoord.x
    24.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    25.     and dword ptr [r8],0
    26. ; ConsoleWindow.Left = ConsoleWindow.Top = 0
    27.     sub ax, MAXSCREENX
    28.     sbb edx, edx
    29.     and ax, dx
    30.     add ax, MAXSCREENX-1
    31.     mov [r8+SMALL_RECT.Right],ax
    32.     shr eax, 16
    33.     sub eax, MAXSCREENY
    34.     sbb edx, edx
    35.     and eax, edx
    36.     add eax, MAXSCREENY-1
    37.     mov [r8+SMALL_RECT.Bottom],ax
    38.     invoke SetConsoleWindowInfo,hOut,TRUE
    39.     invoke SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX  ;establish the new size of a window of the console
    40.     invoke SetConsoleTitle,&ConsoleName
    41. ;hide cursor----------------------------------------
    42. invoke GetConsoleCursorInfo,hOut,&cci         ; lpConsoleCursorInfo
    43.         lea edx,cci         ; lpConsoleCursorInfo
    44.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    45.     invoke  SetConsoleCursorInfo,hOut
    46. ;------------------------------------------------------
    47.         invoke  WriteConsole,hOut,&Str2,sizeof Str2,&result,0
    48. ;Get Console Info
    49. ;with Get CursorPosition Start
    50.     invoke  GetConsoleScreenBufferInfo,hOut,&CSBI
    51.     ;Loop of bar 0 - 100
    52.     ;Write procent char (only one time)
    53.     mov procentbar[27], '%'
    54.     ;Write ascii procent
    55. @0: mov     dl,10
    56.     mov     eax,procent
    57.     div     dl
    58.     add     ax,'00'
    59.     mov     word ptr procentbar[24], ax
    60.     cmp al,3Ah
    61.     jnz @f
    62.         mov word ptr procentbar[23],'01'
    63. @@: ;Set CursorPosition Start
    64. mov eax,CSBI.dwCursorPosition
    65.     invoke SetConsoleCursorPosition,hOut,eax
    66.     ;Set Color1
    67. invoke  SetConsoleTextAttribute,hOut,colors1
    68.     ;Write proportial part
    69.     mov     r8d,procent
    70.     shr     r8d,1
    71.     invoke  WriteFile,hOut,&procentbar,,&n,0
    72.     ;Set Color2
    73. invoke SetConsoleTextAttribute,hOut,colors2
    74.     ;Write proportial part end
    75.     mov edx,procent
    76.     shr edx,1
    77.     mov r8d,50
    78.     sub r8d,edx
    79.     add edx,offset procentbar
    80.     invoke WriteFile,hOut,,,&n,0
    81. ;Wait for slow speed
    82.     mov ecx,procent
    83.     shr ecx,2
    84.     add ecx,80
    85.     invoke    Sleep
    86. ;Add procent
    87.     inc procent
    88.     cmp procent,101
    89.     jb  @0
    90. ;Set Text Color on default
    91.     movzx   edx,CSBI.wAttributes
    92.     invoke    SetConsoleTextAttribute,hOut
    93. @@: invoke    ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    94.         lea     eax,MOUSE_KEY
    95.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    96.     je  @b
    97.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    98.     jne     @b
    99.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    100.     jne     @b
    101.         invoke    FreeConsole
    102.         invoke RtlExitUserProcess,NULL
    103. WinMain endp
    104. hIn dq ?
    105. hOut dq ?
    106. ConsoleName db 'Progress bar in console',0
    107. Str2 db 'For exit press ESC or CTRL+C or CTRL+Break',13,10,10,32
    108. procentbar db 50 dup (32),0,0
    109. procent dd 0
    110. n dd 0
    111. end
    Здесь исходный текст программы и ехе-файл
    [​IMG]
    Двоичные часы в консольной программе
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 50
    4. MAXSCREENY = 15
    5. MAX_STACK  = 1000h
    6. BLACK      = 0
    7. BLUE       = 1
    8. GREEN      = 2
    9. CYAN       = 3
    10. RED    = 4
    11. PURPLE     = 5
    12. YELLOW     = 6
    13. SYSTEM     = 7
    14. GREY       = 8
    15. BRIGHTBLUE = 9
    16. BRIGHTGREEN  = 10
    17. BRIGHTCYAN = 11
    18. BRIGHTRED  = 12
    19. BRIGHTPURPLE = 13
    20. BRIGHTYELLOW = 14
    21. WHITE      = 15
    22. LEFT       = 4
    23. TOP    = 4
    24. W      = 3
    25. .code
    26. WinMain proc
    27. local szReadWrite:qword
    28. local ConsoleWindow:SMALL_RECT
    29. local cci:CONSOLE_CURSOR_INFO
    30. local MOUSE_KEY:INPUT_RECORD
    31. local stm:SYSTEMTIME
    32. invoke FreeConsole
    33.         invoke  AllocConsole
    34.     invoke  GetProcessHeap
    35.     mov hHeap,rax
    36.     invoke  RtlAllocateHeap,rax,HEAP_ZERO_MEMORY,4*MAX_STACK
    37.     mov lpStack,rax
    38.         invoke  GetStdHandle,STD_INPUT_HANDLE
    39.         mov hIn,rax
    40.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    41.         mov hOut,rax
    42.     invoke  GetLargestConsoleWindowSize,rax
    43. ;   eax return in 31-16 bits: dwCoord.y
    44. ;                 15-00 bits: dwCoord.x
    45.         lea r8d,ConsoleWindow           ; lpConsoleWindow
    46.     and dword ptr [r8],0
    47. ;   ConsoleWindow.Left = 0  ConsoleWindow.Top  = 0
    48.     sub ax, MAXSCREENX
    49.     sbb edx, edx
    50.     and ax, dx
    51.     add ax, MAXSCREENX-1
    52.     mov [r8+SMALL_RECT.Right],ax
    53.     shr eax, 16
    54.     sub eax, MAXSCREENY
    55.     sbb edx, edx
    56.     and eax, edx
    57.     add eax, MAXSCREENY-1
    58.     mov [r8+SMALL_RECT.Bottom],ax
    59.     invoke  SetConsoleWindowInfo,hOut,TRUE
    60.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX;устанавливаем новый размер окна консоли
    61.     invoke  SetConsoleTitle,&Str1
    62. ;hide cursor----------------------------------------
    63.     invoke  GetConsoleCursorInfo,hOut,&cci
    64.     lea edx,cci                     ; lpConsoleCursorInfo
    65.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    66.     invoke  SetConsoleCursorInfo,hOut
    67. ;------------------------------------------------------
    68.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&szReadWrite,0        ;вывести Str2 на консоль
    69. ;--------------------------------------------------------
    70. ; Run until Esc is pressed
    71. main_loop:
    72.     invoke  Sleep,10          ; dwMilliseconds
    73.     invoke  GetLocalTime,&stm
    74.     mov Y,TOP
    75.     mov X,LEFT+W+1
    76. k = 16
    77. rept 5
    78.         test    stm.wHour,k
    79.     jz  @f
    80.     or  color,10000000y     ;установить в color 7-ой бит в 1
    81. @@: invoke  set
    82. k = k/2
    83. endm
    84. ;-----------------------------------------
    85.     mov X,LEFT
    86.     add Y,W
    87. k = 32
    88. rept 6
    89.     test    stm.wMinute,k
    90.     jz  @f
    91.     or  color,10000000y     ;установить в color 7-ой бит в 1
    92. @@: invoke  set
    93. k = k/2
    94. endm
    95. ;-----------------------------------
    96.         add Y,W
    97.     mov X,LEFT
    98. k = 32
    99. rept 6
    100.     test    stm.wSecond,k
    101.     jz  @f
    102.     or  color,10000000y     ;установить в color 7-ой бит в 1
    103. @@: invoke  set
    104. k = k/2
    105. endm
    106. ;--------------------------------------
    107.     invoke  GetAsyncKeyState,VK_ESCAPE       ; vKey
    108. ; Determine whether a key is up or down
    109.     test    eax, 8000h
    110.     jz  main_loop
    111. EXIT: invoke  CloseHandle,hOut        ; hObject
    112.     invoke  CloseHandle,hIn         ; hObject
    113.     invoke  FreeConsole
    114.         invoke  RtlExitUserProcess,NULL
    115. WinMain endp
    116. set proc
    117. local Csbi:CONSOLE_SCREEN_BUFFER_INFO
    118. local lpRegion:SMALL_RECT
    119.     invoke  GetConsoleScreenBufferInfo,hOut,&Csbi
    120.  
    121.     mov edx, color
    122.     mov ecx, edx
    123.     shl edx, 4
    124.     or  edx, ecx            ; wAttributes
    125.     invoke  SetConsoleTextAttribute,hOut
    126. ;draw-------------------------------------------------------
    127.     invoke  GetConsoleScreenBufferInfo,hOut,&Csbi
    128. ;save------------------------------------------------------
    129.     mov edx,X
    130.     mov lpRegion.Left,dx
    131.     add edx,(W-1)
    132.     mov lpRegion.Right,dx
    133.     mov edx,Y
    134.     mov lpRegion.Top,dx
    135.     add edx,(W-2)
    136.     mov lpRegion.Bottom,dx
    137.     invoke  RtlAllocateHeap,hHeap,HEAP_ZERO_MEMORY,4*W*(W-1)+260
    138.     mov edi,eax         ; edi=lpBuffer
    139.     lea edx,lpRegion
    140.     mov [rsp+20h],rdx       ; lpReadRegion
    141.     invoke  ReadConsoleOutput,hOut,rax,(W-1)*10000h+W,0
    142. ;end save--------------------------------------------------
    143.     mov ecx,W*(W-1)
    144. @@: mov ax,Csbi.wAttributes
    145.     shl eax,16
    146.     stosd
    147.     loop    @b
    148.     sub edi,4*W*(W-1)
    149. ;load------------------------------------------------------
    150.     lea edx,lpRegion
    151.     mov [rsp+20h],rdx       ; lpWriteRegion
    152.     invoke  WriteConsoleOutput,hOut,edi,(W-1)*10000h+W,0
    153. ;освободить память
    154.     invoke  HeapFree,hHeap,0,edi
    155. ;end load--------------------------------------------------
    156. ;end draw---------------------------------------------------
    157.     and color,01111111y     ;сбросить в color 7-ой бит в 0
    158.     add X,W+1
    159.     leave
    160.     retn
    161. set endp
    162. ;-------------------------------------------------------
    163. Str1 db 'Binary clock',0
    164. Str2 db 'For exit press ESC or CTRL+C or CTRL+Break',13,10,10,10,\
    165. 5 dup(20h),'32  16  8   4   2   1',13,10,\
    166. 30 dup(20h),'Hours',13,10,10,10,30 dup(20h),'Minutes',13,10,10,10,30 \
    167. dup(20h),'Seconds'
    168. hOut    dq ?
    169. hIn dq ?
    170. X   dd ?
    171. Y   dd ?
    172. color   dd RED
    173. dwStackTop dd -1
    174. lpStack dq ?
    175. hHeap   dq ?
    176. end
    Здесь исходный текст программы и ехе-файл
    6.png
    Перечисление и установка консольных шрифтов
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. MAX_STACK  = 1000h
    6. TOP_MENU   = 5
    7. RIGHT_MENU = 34
    8. COLS_MENU  = 17
    9. ;----------------------------------------------
    10. CONSOLE_FONT_INFO struct
    11.     index       dd ?
    12.     dwFontSize  COORD <>
    13. CONSOLE_FONT_INFO ends
    14. ;----------------------------------------------
    15. buffersize   = 40
    16. .code
    17. WinMain proc
    18. local n:dword
    19. local count:dword
    20. local new_op:dword
    21. local prev_op:dword
    22. local result:qword
    23. local buffer[buffersize]:byte
    24. local ConsoleWindow:SMALL_RECT
    25. local cci:CONSOLE_CURSOR_INFO
    26. local CSBI:CONSOLE_SCREEN_BUFFER_INFO
    27. local MOUSE_KEY:INPUT_RECORD
    28. local hMem:qword
    29. local coord:COORD
    30.     mov prev_op,1
    31.     mov new_op,1
    32.     mov coord,TOP_MENU*10000h+RIGHT_MENU
    33.         invoke  GetProcessHeap
    34.     mov hHeap,rax
    35.     invoke  RtlAllocateHeap,rax,HEAP_ZERO_MEMORY,4*MAX_STACK
    36.     mov lpStack,rax
    37.     invoke  FreeConsole
    38.         invoke  AllocConsole
    39.         invoke  GetStdHandle,STD_INPUT_HANDLE
    40.         mov     hIn,rax
    41.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    42.         mov     hOut,rax
    43.     invoke  GetLargestConsoleWindowSize,eax
    44. ;   eax return in 31-16 bits: dwCoord.y
    45. ;                 15-00 bits: dwCoord.x
    46.         lea r8d,ConsoleWindow   ; lpConsoleWindow
    47.         and dword ptr [r8],0; ConsoleWindow.Left = 0
    48.                         ; ConsoleWindow.Top = 0
    49.     sub ax, MAXSCREENX
    50.     sbb edx, edx
    51.     and ax, dx
    52.     add ax, MAXSCREENX-1
    53.     mov [r8+SMALL_RECT.Right],ax
    54.     shr eax, 16
    55.     sub eax, MAXSCREENY
    56.     sbb edx, edx
    57.     and eax, edx
    58.     add eax, MAXSCREENY-1
    59.     mov [r8+SMALL_RECT.Bottom],ax
    60.     invoke  SetConsoleWindowInfo,hOut,TRUE
    61.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX  ;establish the new size of a window of the console
    62.         invoke  SetConsoleTitle,&ConsoleName
    63. ;hide cursor----------------------------------------
    64.     invoke  GetConsoleCursorInfo,hOut,&cci
    65.         lea edx,cci         ; lpConsoleCursorInfo
    66.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    67.     invoke  SetConsoleCursorInfo,hOut
    68. ;------------------------------------------------------
    69.         invoke  WriteConsole,hOut,&Str2,sizeof Str2,&result,0
    70. ;------------------------------------------------------
    71.         invoke  GetNumberOfConsoleFonts
    72.     mov count,eax
    73.     shl eax,3
    74.     invoke  GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,eax             ; eax = count * sizeof CONSOLE_FONT_INFO
    75.     mov hMem,rax
    76.     invoke    GetConsoleFontInfo,hOut,TRUE,count,rax
    77. ;Draw menu-----------------------------------------------------------
    78.     invoke    SetConsoleTextAttribute,hOut,BACKGROUND_INTENSITY
    79.     mov r9d,count
    80.     add r9d,4                   ;rows
    81.     invoke    draw,RIGHT_MENU-2,TOP_MENU-2,COLS_MENU+4
    82.     invoke    SetConsoleTextAttribute,hOut,BACKGROUND_BLUE or BACKGROUND_GREEN or \
    83.     BACKGROUND_RED
    84.         mov r9d,count
    85.     add r9d,2                   ;rows
    86.     invoke    draw,RIGHT_MENU-1,TOP_MENU-1,COLS_MENU+2
    87. ;fill memu----------------------------------------------------------
    88.     mov edi,count
    89.     mov rsi,hMem
    90. @@: mov ax,300
    91.     cwd
    92.     div [rsi+CONSOLE_FONT_INFO.dwFontSize.y]
    93.         mov     r9d,eax         ;font width
    94.     mov ax,640
    95.     cwd
    96.     div [rsi+CONSOLE_FONT_INFO.dwFontSize.x]
    97.         invoke    sprintf,&buffer,&fmt,eax
    98.     mov n,eax
    99.     invoke    SetConsoleCursorPosition,hOut,coord;устанавливаем позицию курсора
    100.         invoke    WriteConsole,hOut,&buffer,n,&result,0    ;выводим строку символов
    101.     inc coord.y
    102.     add esi,sizeof CONSOLE_FONT_INFO
    103.     dec edi
    104.     jnz @b
    105.     invoke    GlobalFree,hMem
    106. ; Select first label
    107.     invoke    invert,TOP_MENU
    108. ; Keyboard read loop------------------------------------------------
    109. @@:     invoke    ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    110.         lea     eax,MOUSE_KEY
    111.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    112.     je  @b
    113.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    114.     jne     @b
    115.         cmp     [rax+INPUT_RECORD.KeyEvent.bKeyDown],0
    116.     jne @b
    117.         cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_UP
    118.         je  vkUP
    119.         cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_DOWN
    120.         je  vkDOWN
    121.         cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_RETURN
    122.         je  vkRETURN
    123.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    124.     jne     @b
    125. exit0:  invoke    HeapFree,hHeap,0,lpStack
    126.     invoke    CloseHandle,hOut
    127.     invoke    CloseHandle,hIn
    128.         invoke    FreeConsole
    129.         invoke  RtlExitUserProcess,NULL
    130. ;-----------------------------------------------------
    131. vkUP:   dec     new_op
    132.         jnz     proceed
    133.     mov eax,count
    134.         mov     new_op,eax
    135.     jmp     proceed
    136. vkDOWN: mov eax,count
    137.     inc     new_op
    138.         cmp     new_op,eax
    139.         jbe     proceed
    140.         mov     new_op,1
    141. proceed:                ; Select new label
    142.         mov     ecx,new_op
    143.         add     ecx,TOP_MENU-1
    144.         invoke    invert
    145.         add     prev_op,TOP_MENU-1
    146.         invoke    invert,prev_op
    147.     mov     eax,new_op
    148.         mov     prev_op,eax
    149.         jmp @b
    150. vkRETURN:mov    edx,new_op
    151.     dec edx
    152.     invoke    SetConsoleFont,hOut
    153.         jmp @b
    154. WinMain endp
    155. ;--------------------------------------------------------
    156. draw    proc x:qword, y:qword, cols:qword, rows:qword
    157. local Csbi:CONSOLE_SCREEN_BUFFER_INFO
    158. local lpBuffer:qword
    159. local dwBufferSize:COORD
    160. local lpRegion:SMALL_RECT
    161.     mov x,rcx
    162.     mov y,rdx
    163.     mov cols,r8
    164.     mov rows,r9
    165.     invoke    GetConsoleScreenBufferInfo,hOut,&Csbi
    166. ;---------------------------------------------------------
    167.     mov eax,dword ptr cols
    168.     mov dwBufferSize.x,ax
    169.     mov ecx,dword ptr rows
    170.     mov dwBufferSize.y,cx
    171.     dec eax
    172.     dec ecx
    173.     mov edx,dword ptr x
    174.     mov lpRegion.Left,dx
    175.     add eax,dword ptr x     ;eax=cols-1+x
    176.     mov lpRegion.Right,ax
    177.     mov edx,dword ptr y
    178.     mov lpRegion.Top,dx
    179.     add ecx,edx     ;ecx=rows-1+y
    180.     mov lpRegion.Bottom,cx
    181.     mov eax,dword ptr cols
    182.     mul dword ptr rows
    183.     lea r8d,[rax*4+260] ;eax=4*cols*rows+260  dwBytes
    184.     invoke    RtlAllocateHeap,hHeap,HEAP_ZERO_MEMORY
    185.     mov lpBuffer,rax
    186.     mov edi,eax
    187.     lea edx,lpRegion
    188.     mov [rsp+20h],rdx   ; lpReadRegion
    189.     invoke    ReadConsoleOutput,hOut,eax,dwBufferSize,0
    190. ;---------------------------------------------------------
    191.     mov eax,dword ptr cols
    192.     mul dword ptr rows
    193.     mov ecx, eax
    194.     mov ax,Csbi.wAttributes
    195.     shl eax,16
    196.     rep stosd
    197. ;-----------------------------------------------------------
    198.     lea edx, lpRegion
    199.     mov [rsp+20h],rdx   ; lpWriteRegion
    200.     invoke    WriteConsoleOutput,hOut,lpBuffer,dwBufferSize,0
    201.  
    202.     invoke    HeapFree,hHeap,0,lpBuffer
    203.     leave
    204.     retn
    205. draw    endp
    206. ;-------------------------------------------------------
    207. invert  proc y:qword
    208. local lpRegion:SMALL_RECT
    209.     mov lpRegion.Left,RIGHT_MENU
    210.     mov lpRegion.Right,COLS_MENU+RIGHT_MENU-1
    211.     mov lpRegion.Top,cx
    212.     mov lpRegion.Bottom,cx
    213.     invoke    RtlAllocateHeap,hHeap,HEAP_ZERO_MEMORY,COLS_MENU*4+260
    214.         mov rdi,rax         ; edi=lpBuffer
    215.     lea edx,lpRegion
    216.     mov [rsp+20h],rdx   ; lpReadRegion
    217.     invoke    ReadConsoleOutput,hOut,rax,10000h+COLS_MENU,0
    218. ;---------------------------------------------------------------
    219.     mov rsi,rdi
    220.     mov ecx,COLS_MENU       ; cols
    221. @@: lodsd                   ;eax=xxABxxxx
    222.     ror eax,16          ;eax=xxxxxxAB
    223.     ror al,4            ;eax=xxxxxxBA
    224.     rol eax,16          ;eax=xxBAxxxx
    225.     stosd
    226.     loop    @b
    227.     sub edi,COLS_MENU*4
    228.     lea edx,lpRegion
    229.     mov [rsp+20h],rdx   ; lpWriteRegion
    230.     invoke    WriteConsoleOutput,hOut,edi,10000h+COLS_MENU,0
    231.     invoke    HeapFree,hHeap,0,edi
    232.     leave
    233.     retn
    234. invert  endp
    235. ;-----------------------------------------------------------
    236. ConsoleName db 'Enum and set console fonts',0
    237. Str2 db 'For move into menu press Up or Down Arrow key',13,10,\
    238. 'For set selected font press Enter',13,10,\
    239. 'For exit press ESC or CTRL+C or CTRL+Break',13,10
    240. hOut    dq ?
    241. hIn dq ?
    242. hHeap   dq ?
    243. lpStack dq ?
    244. fmt db 'font size %d x %d',0
    245. end
    Здесь исходный текст программы и ехе-файл
    7.png
    Обработка сообщений мыши в консольном приложении
    Для получения сообщений от мыши используют ReadMouseInput
    Код (C):
    1. ReadMouseInput (
    2.            HANDLE hConIn, // дескриптор входного потока
    3.            PINPUT_RECORD pBuf, /* указатель на структуру (массив структур), которая содержит
    4.            информацию о запрашиваемом событии */
    5.            DWORD dwNum, // количество получаемых информационных записей о событиях
    6.            LPDWORD lpdwNumRead /* указатель на двойное слово в которое записывается
    7.            количество реально возвращаемых записей */
    8. );
    При успешном завершении ReadMouseInput возвращает ненулевое значение, иначе возвращается ноль.
    Каждый раз при нажатии клавиши или при перемещении мыши формируется запись, которая сохраняется в структуре
    Код (ASM):
    1. INPUT_RECORD STRUCT
    2.   EventType             WORD ?
    3.   two_byte_alignment    WORD ?
    4.   UNION
    5.     KeyEvent                KEY_EVENT_RECORD            <>
    6.     MouseEvent              MOUSE_EVENT_RECORD          <>
    7.     WindowBufferSizeEvent   WINDOW_BUFFER_SIZE_RECORD   <>
    8.     MenuEvent               MENU_EVENT_RECORD           <>
    9.     FocusEvent              FOCUS_EVENT_RECORD          <>
    10.   ENDS
    11. INPUT_RECORD ENDS
    поле EventType определяет тип события и может принимать одно из значений
    hexbinтип события
    KEY_EVENT
    1​
    0000.0001нажатие клавиши
    MOUSE_EVENT
    2​
    0000.0010событие мыши
    WINDOW_BUFFER_SIZE_EVENT
    4​
    0000.0100изменение размера окна
    MENU_EVENT
    8​
    0000.1000события меню
    FOCUS_EVENT
    10​
    0001.0000событие фокуса
    При приходе сообщения от мыши поле EventType содержит значение MOUSE_EVENT. Расшифровка сообщения заполнит структуру
    Код (ASM):
    1. MOUSE_EVENT_RECORD STRUCT
    2.   dwMousePosition       COORD <>; значение координат в момент прихода сообщения
    3.   dwButtonState         DWORD ?;состояние кнопок при генерации события
    4.   dwControlKeyState     DWORD ?;состояние управляющих клавиш
    5.   dwEventFlags          DWORD ?; при перемещении MOUSE_MOVED=1 либо при двойном щелчке DOUBLE_CLICK=2
    6. MOUSE_EVENT_RECORD ENDS
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. buffersize = 100
    6. .code
    7. WinMain proc
    8. local BUFF[buffersize]:byte
    9. local result:qword
    10. local MOUSE_KEY:INPUT_RECORD
    11. local ConsoleWindow:SMALL_RECT
    12. local cci:CONSOLE_CURSOR_INFO
    13.  
    14.     invoke  FreeConsole
    15.     invoke  AllocConsole
    16.     invoke  GetStdHandle,STD_INPUT_HANDLE
    17.     mov hIn,rax
    18.     invoke GetStdHandle,STD_OUTPUT_HANDLE
    19.     mov hOut,rax
    20.     invoke  GetLargestConsoleWindowSize,eax
    21. ;   rax return in 31-16 bits: dwCoord.y
    22. ;                 15-00 bits: dwCoord.x
    23.     lea r8d,ConsoleWindow       ; lpConsoleWindow
    24.     and dword ptr [r8],0
    25. ;   ConsoleWindow.Left = 0  ConsoleWindow.Top = 0
    26.     sub ax, MAXSCREENX
    27.     sbb edx, edx
    28.     and ax, dx
    29.     add ax, MAXSCREENX-1
    30.     mov [r8+SMALL_RECT.Right],ax
    31.     shr eax, 16
    32.     sub eax, MAXSCREENY
    33.     sbb edx, edx
    34.     and eax, edx
    35.     add eax, MAXSCREENY-1
    36.     mov [r8+SMALL_RECT.Bottom],ax
    37.     invoke  SetConsoleWindowInfo,hOut,TRUE
    38.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX  ;establish the new size of console window
    39.     invoke  SetConsoleTitle,&NameConsole
    40. ;hide cursor----------------------------------------
    41.     invoke  GetConsoleCursorInfo,hOut,&cci
    42.     lea edx,cci             ; lpConsoleCursorInfo
    43.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    44.     invoke  SetConsoleCursorInfo,hOut
    45. ;------------------------------------------------------
    46.     invoke  WriteConsole,hOut,&Str1,sizeof Str1,&result,0
    47.     invoke  SetConsoleCursorPosition,hOut,0B000Bh         ;Y=11 X=0
    48.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&result,0
    49. @@:     invoke  SetConsoleCursorPosition,hOut,0A0009h         ;Y=10 X=9
    50.     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    51.     lea edx,MOUSE_KEY
    52.     cmp [rdx+INPUT_RECORD.EventType],MOUSE_EVENT
    53.     jne LOO1
    54.     xor eax,eax
    55.     mov ax,[rdx+INPUT_RECORD.MouseEvent.dwMousePosition.y]
    56.     mov [rsp+20h],rax
    57.     mov ax,[rdx+INPUT_RECORD.MouseEvent.dwMousePosition.x]
    58.     mov r8d,[rdx+INPUT_RECORD.MouseEvent.dwButtonState]
    59.     cmp r8d,4
    60.     sbb ecx,ecx
    61.     and r8d,ecx
    62.     invoke  wsprintf,&BUFF,&fmt,,rax
    63.     invoke  WriteConsole,hOut,&BUFF,eax,&result,0
    64.     jmp @b
    65. LOO1:   lea     eax,MOUSE_KEY
    66.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    67.     jne     @b
    68.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    69.     jne     @b
    70.     invoke  FreeConsole
    71.     invoke RtlExitUserProcess,NULL
    72. WinMain endp
    73. hIn dq ?
    74. hOut dq ?
    75. NameConsole db 'Processing of mouse messages',0
    76. fmt db 'Button state: %u, X: %u, Y: %u',0
    77. Str1    db 'For exit press ESC or CTRL+C'
    78. Str2    db 'No clicks = 0',0Dh,0Ah,\
    79. '          Left click = 1',0Dh,0Ah,\
    80. '         Right click = 2',0Dh,0Ah,\
    81. 'Left and Right click = 3',0
    82. end
    Здесь исходный текст программы и ехе-файл
    8.png
    Просмотр главной загрузочной записи
    Функция CreateFile может открывать не только файлы, но и дисковые устройства. Для открытия первого диска компьютера используется имя "\\.\PhysicalDrive0", для открытия логического раздела C: имя "\\.\C:". После открытия устройства можно использовать функции ReadFile и WriteFile, то есть читать и писать непосредственно в кластеры и сектора диска. Функция DeviceIOControl позволяет получить статическую информацию о диске либо выполнить форматирование диска. Программа ниже позволяет прочитать главную загрузочную запись диска (Master Boot Record ― MBR). При открытии устройства "\\.\PhysicalDrive0" главная загрузочная запись диска находится в начале гипотетического файла. После создания exe-файла, добавьте в его свойства "Запуск от имени администратора"
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 49
    4. MAXSCREENY = 36
    5. .code
    6. WinMain proc
    7. local hFile:qword
    8. local szReadWrite:qword
    9. local FileSize:qword
    10. local hMapping:qword
    11. local pMapping:qword
    12. local ConsoleWindow:SMALL_RECT
    13. local cci:CONSOLE_CURSOR_INFO
    14. local MOUSE_KEY:INPUT_RECORD
    15. local i:dword
    16. local buffer1[512+3]:byte
    17. local buffer2[3*512]:byte
    18. local buffer3:qword
    19.  
    20.         invoke  FreeConsole
    21.         invoke  AllocConsole
    22.         invoke GetStdHandle,STD_INPUT_HANDLE
    23.         mov     hIn,rax
    24.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    25.         mov hOut,rax
    26.     invoke  GetLargestConsoleWindowSize,rax
    27. ;   eax return in 31-16 bits: dwCoord.y
    28. ;                 15-00 bits: dwCoord.x
    29.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    30.     and dword ptr [r8],0
    31. ;   ConsoleWindow.Left = 0  ConsoleWindow.Top  = 0
    32.     sub ax, MAXSCREENX
    33.     sbb edx, edx
    34.     and ax, dx
    35.     add ax, MAXSCREENX-1
    36.     mov [r8+SMALL_RECT.Right],ax
    37.     shr eax, 16
    38.     sub eax, MAXSCREENY
    39.     sbb edx, edx
    40.     and eax, edx
    41.     add eax, MAXSCREENY-1
    42.     mov [r8+SMALL_RECT.Bottom],ax
    43.     invoke  SetConsoleWindowInfo,hOut,TRUE              
    44.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX ;establish the new size of a window of the console
    45.         invoke  SetConsoleTitle,&Str0
    46. ;hide cursor----------------------------------------
    47.     invoke  GetConsoleCursorInfo,hOut,&cci
    48.         lea edx,cci                 ; lpConsoleCursorInfo
    49.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],ebx;FALSE
    50.     invoke  SetConsoleCursorInfo,hOut
    51. ;------------------------------------------------------
    52. ;open physical drive
    53.     invoke CreateFile,&filename,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0      ;open file
    54. inc eax         ;eax == INVALID_HANDLE_VALUE ?
    55.     jz  EXIT
    56.     dec eax
    57.     mov hFile,rax
    58. ;alignment on limit of the double word
    59.     lea     eax,buffer1
    60.     add eax,3
    61.     and eax,-4
    62.     mov buffer3,rax
    63. ;read from Partition Table
    64.     invoke ReadFile,hFile,rax,512,&szReadWrite,0
    65. ;-------------------------------------------
    66.     lea edi,buffer2
    67.     mov esi,offset Str2
    68.     mov ecx,sizeof Str2
    69.     rep movsb
    70.     mov rsi,buffer3
    71.     mov FileSize,sizeof Str2
    72.     mov i,ebx
    73. @@: lodsq
    74.     bswap   rax
    75.     mov     r9d,eax
    76.     mov     [rsp+20h],r9
    77.     shr rax,32
    78.         mov     r9d,eax
    79.     lodsq
    80.     bswap   rax
    81.     mov edx,eax
    82.     mov     [rsp+30h],rdx
    83.     shr rax,32
    84.     mov     [rsp+28h],rax
    85.     invoke wsprintf,rdi,&fmt,i
    86.     add edi,eax
    87.     add FileSize,rax
    88.     inc i
    89.     cmp i,512/16
    90.     jb  @b
    91.     mov esi,offset Str1
    92.     mov ecx,sizeof Str1
    93.     rep movsb
    94.         add FileSize,sizeof Str1
    95. ;to bring buffer contents to the console
    96.     invoke  WriteConsole,hOut,&buffer2,FileSize,&szReadWrite,0
    97. ;close handle and file----------------------
    98.     invoke  CloseHandle,hFile ; close file
    99.     invoke  CloseHandle,hOut     ; close file
    100. ;--------------------------------------------------------
    101. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&szReadWrite
    102.         lea eax,MOUSE_KEY
    103.     cmp [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    104.     je  @b
    105.     cmp [rax+INPUT_RECORD.EventType],KEY_EVENT
    106.     jne @b
    107.     cmp [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    108.     jne @b
    109. ;---------------------------------------------------------
    110. EXIT: invoke  CloseHandle,hIn
    111.     invoke  FreeConsole
    112.     invoke RtlExitUserProcess,NULL
    113. WinMain endp
    114. fmt db ' %.04X0 ',0BAh,' %.08X %.08X ',0B3h,' %.08X %.08X ',0BAh,0Dh,0Ah,0
    115. Str0 db 'Master Boot Record',0
    116. Str1 db 7 dup(20h),0C8h,19 dup (0CDh),0CFh,19 dup (0CDh),0BCh,13,10,\
    117. 'For exit press ESC or CTRL+C or CTRL+Break'
    118. filename db "\\.\PhysicalDrive0",0 ;имя устройства (первый диск)
    119. hIn dq ?
    120. hOut dq ?
    121. Str2    db 10 dup(20h),'0 1 2 3  4 5 6 7    8 9 A B  C D E F',0Dh,0Ah,\
    122. 7 dup(20h),0C9h,19 dup (0CDh),0D1h,19 dup (0CDh),0BBh,0Dh,0Ah
    123. end
    Здесь исходный текст программы и ехе-файл
    9.png
    Анимация в консольном приложении
    Считается, что консольное приложение работает ТОЛЬКО В ТЕКСТОВОМ РЕЖИМЕ. На самом деле в консольном приложении наряду с текстовым вводом-выводом можно использовать и графический ввод-вывод. В консольном приложении hWnd можно получить следующими способами:
    1. Код (ASM):
      1.        invoke  GetConsoleWindow
      2.        mov hWnd,rax
    2. Код (ASM):
      1. .data
      2. ClassConsole db 'ConsoleWindowClass',0
      3. . . .
      4.         invoke  FindWindow,&ClassConsole,0
      5.         mov hWnd,rax
    Зная hWnd получаем контекст устройства
    Код (ASM):
    1.        invoke  GetDC,hWnd
    2.        mov hDC,rax
     

    Вложения:

    • 8.png
      8.png
      Размер файла:
      43,9 КБ
      Просмотров:
      849
    • 10.png
      10.png
      Размер файла:
      57 КБ
      Просмотров:
      3.132
    • 11.png
      11.png
      Размер файла:
      48 КБ
      Просмотров:
      3.141
    • 12.png
      12.png
      Размер файла:
      55,2 КБ
      Просмотров:
      3.081
    • stubby.zip
      Размер файла:
      161 байт
      Просмотров:
      488
    • 02.zip
      Размер файла:
      2,3 КБ
      Просмотров:
      522
    • 03.zip
      Размер файла:
      2,3 КБ
      Просмотров:
      500
    • 04.zip
      Размер файла:
      3,2 КБ
      Просмотров:
      528
    • 05.zip
      Размер файла:
      2,6 КБ
      Просмотров:
      504
    • 06.zip
      Размер файла:
      3,3 КБ
      Просмотров:
      462
    • 07.zip
      Размер файла:
      4,2 КБ
      Просмотров:
      481
    • 08.zip
      Размер файла:
      2,4 КБ
      Просмотров:
      492
    • 10.zip
      Размер файла:
      6,8 КБ
      Просмотров:
      475
    • 11.zip
      Размер файла:
      2,3 КБ
      Просмотров:
      457
    • 12.zip
      Размер файла:
      2,3 КБ
      Просмотров:
      492
    __sheva740, Alex81524, murder и 3 другим нравится это.
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. includelib winmm.lib
    4. include winmm.inc
    5. const1     = 68
    6. MAXSCREENX = 80
    7. MAXSCREENY = 25
    8. .code
    9. WinMain proc
    10. local result:qword
    11. local hIn:qword
    12. local IDtimer:qword
    13. local ConsoleWindow:SMALL_RECT
    14. local cci:CONSOLE_CURSOR_INFO
    15. local MOUSE_KEY:INPUT_RECORD
    16.  
    17.         invoke  FreeConsole ;release the existing console
    18.         invoke  AllocConsole    ;create the console
    19.         invoke  GetStdHandle,STD_INPUT_HANDLE
    20.         mov hIn,rax                        ; receive handle for a input
    21.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    22.         mov hOut,rax                       ; receive handle for a output
    23.     invoke  GetLargestConsoleWindowSize,eax
    24. ;   eax return in 31-16 bits: dwCoord.y
    25. ;                 15-00 bits: dwCoord.x
    26.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    27.     and dword ptr [r8],0
    28.     ;ConsoleWindow.Left = 0   ConsoleWindow.Top = 0
    29.     sub ax, MAXSCREENX
    30.     sbb edx, edx
    31.     and ax, dx
    32.     add ax, MAXSCREENX-1
    33.     mov [r8+SMALL_RECT.Right],ax
    34.     shr eax, 16
    35.     sub eax, MAXSCREENY
    36.     sbb edx, edx
    37.     and eax, edx
    38.     add eax, MAXSCREENY-1
    39.     mov [r8+SMALL_RECT.Bottom],ax
    40.     invoke  SetConsoleWindowInfo,hOut,TRUE
    41.     invoke  SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX  ; establish the new size of console window
    42.         invoke  FindWindow,&ClassConsole,0
    43.        mov hWnd,rax
    44.     invoke  GetDC,rax
    45.     mov hDC,rax
    46.         invoke  CreateSolidBrush,0
    47.     mov BlackBrush,rax
    48.     invoke  SelectObject,hDC,rax         ;keep a black brush in a context
    49.         ;load the picture
    50.     invoke  LoadImage,400000h,&bmp,0,0,0,LR_LOADFROMFILE
    51.     mov hBit,rax
    52.         invoke  SetConsoleTitle,&NameConsole     ;definition of a title bar
    53.         invoke  timeSetEvent,100,0,&TIME,0,TIME_PERIODIC
    54.     mov IDTimer,rax
    55. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    56.         lea edx,MOUSE_KEY
    57.     cmp [rdx+INPUT_RECORD.EventType],MOUSE_EVENT
    58.     je  @b
    59.     cmp     [rdx+INPUT_RECORD.EventType],KEY_EVENT
    60.     jne @b
    61.     cmp [rdx+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    62.     jne @b
    63.  
    64.     invoke DeleteObject,BlackBrush    ;delete a black brush
    65.     invoke  DeleteObject,hBit    ;delete drawing
    66.         invoke  ReleaseDC,hWnd,hDC       ;free hDC
    67.     invoke  timeKillEvent,IDTimer
    68.     invoke  FreeConsole ;close console
    69.     invoke RtlExitUserProcess,NULL
    70. WinMain endp
    71. TIME proc
    72. local   memDC:qword
    73. local   result:qword
    74.  
    75.         invoke  SetConsoleCursorPosition,hOut,0;Y=0 X=0
    76.     invoke  WriteConsole,hOut,&STR1,sizeof STR1,&result,0            ;output of a line of symbols to the screen
    77. @@: invoke  CreateCompatibleDC,hDC      ;create compatible DC
    78.     mov memDC,rax
    79.     invoke  SelectObject,rax,hBit
    80.     mov eax,Y
    81.     add eax,const1+1
    82.     mov [rsp+20h],rax
    83.         mov r9d,X
    84.     add r9d,const1+1
    85.     mov r8d,Y
    86.     dec r8d
    87.     mov edx,X
    88.     dec edx
    89.     invoke  Ellipse,hDC         ;remove a black circle to erase the previous image
    90.     cmp     X,640-const1        ;check that the planet is in console limits
    91.     jna     @f          ;otherwise change the direction of the movement
    92.         neg     deltaX
    93. @@: cmp     Y,300-const1
    94.     jna     @f
    95.         neg     deltaY
    96. @@: mov     eax,deltaX
    97.     add     X,eax           ;change planet coordinates
    98.     mov     eax,deltaY
    99.     add     Y,eax
    100.         mov qword ptr [rsp+40h],SRCCOPY ;dwRaster
    101.     mov [rsp+38h],rbx           ;SourceY=0
    102.         mov [rsp+30h],rbx           ;SourceX=0
    103.     mov rax,memDC           ;hSource
    104.         mov [rsp+28h],rax
    105.     mov r9d,const1              ;Width
    106.     mov [rsp+20h],r9            ;const1=height
    107. mov edx,X
    108. mov r8d,Y
    109.     invoke  BitBlt,hDC      ;display the image
    110.     invoke  DeleteDC,memDC        ;release the DC memories
    111.     leave
    112.     retn
    113. TIME endp
    114. .data
    115. bmp     db 'Earth.bmp',0
    116. ClassConsole db 'ConsoleWindowClass',0
    117. STR1    db 'For exit from program press ESC or CTRL+C or CTRL+Break'
    118. NameConsole db 'Console application animation',0
    119. hOut    dq ?
    120. hWnd    dq ?
    121. hDC     dq ?
    122. BlackBrush  dq ?
    123. hBit    dq ?
    124. deltaX  dd 10
    125. deltaY  dd 2
    126. X       dd ?
    127. Y       dd ?
    128. IDTimer dq ?
    129. end
    Здесь исходный текст программы и ехе-файл
    [​IMG]

    Вывод на консоль содержимого текстового файла. Первый вариант
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. .code
    6. WinMain proc
    7. local hFile:qword
    8. local result:qword
    9. local FileSize:qword
    10. local hMem:qword
    11. local ConsoleWindow:SMALL_RECT
    12. local cci:CONSOLE_CURSOR_INFO
    13. local MOUSE_KEY:INPUT_RECORD
    14.  
    15.         invoke FreeConsole
    16.         invoke  AllocConsole
    17.         invoke  GetStdHandle,STD_INPUT_HANDLE
    18.         mov     hIn,rax
    19.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    20.         mov     hOut,rax
    21.         invoke  GetLargestConsoleWindowSize,eax
    22. ;   eax return in 31-16 bits: dwCoord.y
    23. ;                 15-00 bits: dwCoord.x
    24.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    25.     and dword ptr [r8],0
    26. ;   ConsoleWindow.Left = 0  ConsoleWindow.Top = 0
    27.     sub ax, MAXSCREENX
    28.     sbb edx, edx
    29.     and ax, dx
    30.     add ax, MAXSCREENX-1
    31.     mov [r8+SMALL_RECT.Right],ax
    32.     shr eax, 16
    33.     sub eax, MAXSCREENY
    34.     sbb edx, edx
    35.     and eax, edx
    36.     add eax, MAXSCREENY-1
    37.     mov [r8+SMALL_RECT.Bottom],ax
    38.     invoke  SetConsoleWindowInfo,hOut,TRUE
    39.     invoke  SetConsoleTitle,&Str1
    40. ;hide cursor----------------------------------------
    41.     invoke  GetConsoleCursorInfo,hOut,&cci
    42.         lea edx,cci             ; lpConsoleCursorInfo
    43.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    44.     invoke  SetConsoleCursorInfo,hOut
    45. ;------------------------------------------------------
    46.     invoke  CreateFile,&filename,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0      ;to open the file
    47.     inc     eax;cmp eax,-1
    48.     jz      EXIT
    49.     dec     eax
    50.     mov hFile,rax
    51.     invoke  GetFileSize,rax,0
    52.     mov FileSize,rax
    53.     invoke  GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,rax
    54.     mov hMem,rax
    55.     invoke  ReadFile,hFile,rax,FileSize,&result,0        ;to read in the buffer
    56.     invoke  WriteConsole,hOut,hMem,FileSize,&result,0        ;to bring buffer contents to the console
    57.     invoke  CloseHandle,hFile     ;to close the file
    58. ;--------------------------------------------------------
    59.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&result,0        ;to bring Str2 to the console
    60. ;--------------------------------------------------------
    61. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    62.         lea     eax,MOUSE_KEY
    63.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    64.     je  @b
    65.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    66.     jne     @b
    67.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    68.     jne     @b
    69. EXIT:   invoke  FreeConsole
    70.     invoke RtlExitUserProcess,NULL
    71. WinMain endp
    72. hIn dq ?
    73. hOut dq ?
    74. Str1 db 'Output to the console of text file contents. First variant.',0
    75. Str2 db 13,10,'For exit press ESC or CTRL+C or CTRL+Break'
    76. filename db '11.asm'
    77. end
    Здесь исходный текст программы и ехе-файл
    [​IMG]
    Вывод на консоль содержимого текстового файла. Второй вариант
    asm-файл
    Код (ASM):
    1.  
    2. ; CONSOLE #
    3. include win64a.inc
    4. MAXSCREENX = 80
    5. MAXSCREENY = 25
    6. .code
    7. WinMain proc
    8. local hFile:qword
    9. local result:qword
    10. local FileSize:qword
    11. local hMem:qword
    12. local ConsoleWindow:SMALL_RECT
    13. local cci:CONSOLE_CURSOR_INFO
    14. local MOUSE_KEY:INPUT_RECORD
    15.  
    16.         invoke FreeConsole
    17.         invoke  AllocConsole
    18.         invoke  CreateFile,&filenameIn,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0
    19.         mov     hIn,rax                 ; hConsoleInput
    20.         invoke  CreateFile,&filenameOut,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0
    21.         mov     hOut,rax
    22.         invoke  GetLargestConsoleWindowSize,rax
    23. ;   eax return in 31-16 bits: dwCoord.y
    24. ;                 15-00 bits: dwCoord.x
    25.         lea r8d,ConsoleWindow   ;lpConsoleWindow
    26.     and dword ptr [r8],0
    27. ;   lpConsoleWindow.Left = 0 lpConsoleWindow.Top = 0
    28.     sub ax, MAXSCREENX
    29.     sbb edx, edx
    30.     and ax, dx
    31.     add ax, MAXSCREENX-1
    32.     mov [r8+SMALL_RECT.Right],ax
    33.     shr eax, 16
    34.     sub eax, MAXSCREENY
    35.     sbb edx, edx
    36.     and eax, edx
    37.     add eax, MAXSCREENY-1
    38.     mov [r8+SMALL_RECT.Bottom],ax
    39.     invoke  SetConsoleWindowInfo,hOut,TRUE
    40.     invoke  SetConsoleTitle,&ConsoleTitle
    41. ;hide cursor----------------------------------------
    42.     invoke  GetConsoleCursorInfo,hOut,&cci
    43.         lea edx,cci             ; lpConsoleCursorInfo
    44.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],ebx;FALSE
    45.     invoke  SetConsoleCursorInfo,hOut
    46. ;------------------------------------------------------
    47.     invoke  CreateFile,&filename,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0      ;to open the file
    48.     inc     eax;cmp eax,-1
    49.     jz      EXIT
    50.     dec     eax
    51.     mov hFile,rax
    52.     invoke  GetFileSize,rax,0
    53.     mov FileSize,rax
    54.     invoke  GlobalAlloc,GMEM_FIXED or GMEM_ZEROINIT,rax
    55.     mov hMem,rax
    56.     invoke  ReadFile,hFile,rax,FileSize,&result,0        ;to read in the buffer
    57.     invoke  WriteConsole,hOut,hMem,FileSize,&result,0        ;to bring buffer contents to the console
    58.     invoke  CloseHandle,hFile     ;to close the file
    59. ;--------------------------------------------------------
    60.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&result,0        ;to bring Str2 to the console
    61. ;--------------------------------------------------------
    62. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&result
    63.         lea     eax,MOUSE_KEY
    64.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    65.     je  @b
    66. [B]    [/B]cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    67.     jne     @b
    68.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    69.     jne     @b
    70. EXIT:   invoke  FreeConsole
    71.     invoke RtlExitUserProcess,NULL
    72. WinMain endp
    73.  
    74. hIn dq ?
    75. hOut dq ?
    76. ConsoleTitle db 'Output to the console of text file contents. Second variant.',0
    77. Str2 db 13,10,'For exit press ESC or CTRL+C or CTRL+Break'
    78. filename db '12.asm',0
    79. filenameOut db 'CONOUT$',0
    80. filenameIn db 'CONIN$',0
    81. end
    Здесь исходный текст программы и ехе-файл
    [​IMG]
    Управление памятью, файловый ввод/вывод
    через GlobalAlloc/Lock/Unlock и GlobalFree
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. .code
    6. WinMain proc
    7. local hFile:qword
    8. local szReadWrite:qword
    9. local FileSize:qword
    10. local hMem:qword
    11. local pMem:qword
    12. local ConsoleWindow:SMALL_RECT
    13. local cci:CONSOLE_CURSOR_INFO
    14. local MOUSE_KEY:INPUT_RECORD
    15.  
    16.         invoke  FreeConsole
    17.         invoke  AllocConsole
    18.         invoke  GetStdHandle,STD_INPUT_HANDLE
    19.         mov     hIn,rax
    20.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    21.         mov     hOut,rax
    22.         invoke  GetLargestConsoleWindowSize,eax
    23. ;   eax return in 31-16 bits: dwCoord.y
    24. ;                 15-00 bits: dwCoord.x
    25.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    26.     and dword ptr [r8],0
    27. ;   lpConsoleWindow.Left = 0 lpConsoleWindow.Top = 0
    28.     sub ax, MAXSCREENX
    29.     sbb edx, edx
    30.     and ax, dx
    31.     add ax, MAXSCREENX-1
    32.     mov [r8+SMALL_RECT.Right],ax
    33.     shr eax, 16
    34.     sub eax, MAXSCREENY
    35.     sbb edx, edx
    36.     and eax, edx
    37.     add eax, MAXSCREENY-1
    38.     mov [r8+SMALL_RECT.Bottom],ax
    39.     invoke  SetConsoleWindowInfo,hOut,TRUE
    40.     invoke  SetConsoleTitle,&Str1
    41. ;hide cursor----------------------------------------
    42.     invoke  GetConsoleCursorInfo,hOut,&cci
    43.         lea edx,cci             ; lpConsoleCursorInfo
    44.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    45.     invoke  SetConsoleCursorInfo,hOut
    46. ;------------------------------------------------------
    47.     invoke  CreateFile,&filename,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0      ;to open the file
    48.     inc     eax;cmp eax,-1
    49.     jz      EXIT
    50.     dec     eax
    51.     mov hFile,rax
    52.     invoke  GetFileSize,rax,0
    53.     mov FileSize,rax
    54.     invoke  GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,rax
    55.     mov hMem,rax
    56.         invoke  GlobalLock,rax
    57.     mov     pMem,rax
    58.     invoke  ReadFile,hFile,rax,FileSize,&szReadWrite,0        ;to read in the buffer
    59.     invoke  WriteConsole,hOut,pMem,FileSize,&szReadWrite,0        ;to bring buffer contents to the console
    60.     invoke  CloseHandle,hFile     ;to close the file
    61.     invoke  GlobalUnlock,pMem
    62.     invoke  GlobalFree,hMem
    63. ;--------------------------------------------------------
    64.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&szReadWrite,0        ;to bring Str2 to the console
    65. ;--------------------------------------------------------
    66. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&szReadWrite
    67.         lea     eax,MOUSE_KEY
    68.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    69.     je  @b
    70.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    71.     jne     @b
    72.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    73.     jne     @b
    74. EXIT:   invoke  FreeConsole
    75.     invoke RtlExitUserProcess,NULL
    76. WinMain endp
    77. hIn dq ?
    78. hOut dq ?
    79. Str1 db 'Memory Management, File I/O, GlobalAlloc/Lock/Unlock and GlobalFree',0
    80. Str2 db 13,10,'For exit press ESC or CTRL+C or CTRL+Break'
    81. filename db '14.asm',0
    82. end
    Здесь исходный текст программы и ехе-файл
    Управление памятью, файловый ввод/вывод
    через GetProcessHeap, HeapAlloc and HeapFree
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. MEM_SIZE   = 65535
    6. .code
    7. WinMain proc
    8. local hFile:qword
    9. local szReadWrite:qword
    10. local FileSize:qword
    11. local hHeap:qword
    12. local pMem:qword
    13. local ConsoleWindow:SMALL_RECT
    14. local cci:CONSOLE_CURSOR_INFO
    15. local MOUSE_KEY:INPUT_RECORD
    16.  
    17.         invoke FreeConsole
    18.         invoke  AllocConsole
    19.         invoke  GetStdHandle,STD_INPUT_HANDLE
    20.         mov     hIn,rax
    21.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    22.         mov     hOut,rax
    23.         invoke    GetLargestConsoleWindowSize,eax
    24. ;   eax return in 31-16 bits: dwCoord.y
    25. ;                 15-00 bits: dwCoord.x
    26.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    27.     and dword ptr [r8],0
    28. ;   lpConsoleWindow.Left = 0 lpConsoleWindow.Top = 0
    29.     sub ax, MAXSCREENX
    30.     sbb edx, edx
    31.     and ax, dx
    32.     add ax, MAXSCREENX-1
    33.     mov [r8+SMALL_RECT.Right],ax
    34.     shr eax, 16
    35.     sub eax, MAXSCREENY
    36.     sbb edx, edx
    37.     and eax, edx
    38.     add eax, MAXSCREENY-1
    39.     mov [r8+SMALL_RECT.Bottom],ax
    40.     invoke  SetConsoleWindowInfo,hOut,TRUE
    41.         invoke  SetConsoleTitle,&Str1
    42. ;hide cursor----------------------------------------
    43.     invoke  GetConsoleCursorInfo,hOut,&cci
    44.         lea edx,cci             ; lpConsoleCursorInfo
    45.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],ebx;FALSE
    46.     invoke  SetConsoleCursorInfo,hOut
    47. ;------------------------------------------------------
    48.     invoke  CreateFile,&filename,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0      ;to open the file
    49.     inc     eax;cmp eax,-1
    50.     jz      EXIT
    51.     dec     eax
    52.     mov hFile,rax
    53.     invoke  GetFileSize,rax,0
    54.     mov FileSize,rax
    55.     invoke  GetProcessHeap
    56.     mov hHeap,rax
    57.         invoke  RtlAllocateHeap,rax,HEAP_ZERO_MEMORY,MEM_SIZE
    58.     mov     pMem,rax
    59.     invoke  ReadFile,hFile,rax,FileSize,&szReadWrite,0        ;to read in the buffer
    60.     invoke  WriteConsole,hOut,pMem,FileSize,&szReadWrite,0        ;to bring buffer contents to the console
    61.     invoke  CloseHandle,hFile     ;to close the file
    62.         invoke  HeapFree,hHeap,0,pMem
    63. ;--------------------------------------------------------
    64.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&szReadWrite,0        ;to bring Str2 to the console
    65. ;--------------------------------------------------------
    66. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&szReadWrite
    67.         lea     eax,MOUSE_KEY
    68.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    69.     je  @b
    70.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    71.     jne     @b
    72.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    73.     jne     @b
    74. EXIT:   invoke  FreeConsole
    75.     invoke RtlExitUserProcess,NULL
    76. WinMain endp
    77. hIn dq ?
    78. hOut dq ?
    79. Str1 db 'Memory Management, File I/O, GetProcessHeap, HeapAlloc and HeapFree',0
    80. Str2 db 13,10,'For exit press ESC or CTRL+C or CTRL+Break'
    81. filename db '15.asm',0
    82. end
    Здесь исходный текст программы и ехе-файл
    Memory Mapped File
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. MEM_SIZE   = 65535
    6. .code
    7. WinMain proc
    8. local hFile:qword
    9. local szReadWrite:qword
    10. local FileSize:qword
    11. local hMapping:qword
    12. local pMapping:qword
    13. local ConsoleWindow:SMALL_RECT
    14. local cci:CONSOLE_CURSOR_INFO
    15. local MOUSE_KEY:INPUT_RECORD
    16.         invoke  FreeConsole
    17.         invoke  AllocConsole
    18.         invoke  GetStdHandle,STD_INPUT_HANDLE
    19.         mov     hIn,rax
    20.         invoke  GetStdHandle,STD_OUTPUT_HANDLE
    21.         mov     hOut,rax
    22.         invoke  GetLargestConsoleWindowSize,eax
    23. ;   eax return in 31-16 bits: dwCoord.y
    24. ;                 15-00 bits: dwCoord.x
    25.         lea r8d,ConsoleWindow       ; lpConsoleWindow
    26.     and dword ptr [r8],0
    27. ;   lpConsoleWindow.Left = 0 lpConsoleWindow.Top = 0
    28.     sub ax, MAXSCREENX
    29.     sbb edx, edx
    30.     and ax, dx
    31.     add ax, MAXSCREENX-1
    32.     mov [r8+SMALL_RECT.Right],ax
    33.     shr eax, 16
    34.     sub eax, MAXSCREENY
    35.     sbb edx, edx
    36.     and eax, edx
    37.     add eax, MAXSCREENY-1
    38.     mov [r8+SMALL_RECT.Bottom],ax
    39.     invoke  SetConsoleWindowInfo,hOut,TRUE
    40.     invoke  SetConsoleTitle,&Str1
    41. ;hide cursor----------------------------------------
    42.     invoke  GetConsoleCursorInfo,hOut,&cci
    43.         lea edx,cci             ; lpConsoleCursorInfo
    44.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    45.     invoke  SetConsoleCursorInfo,hOut
    46. ;------------------------------------------------------
    47.     invoke  CreateFile,&filename,GENERIC_READ or GENERIC_WRITE,0,0,OPEN_EXISTING,0,0      ;to open the file
    48.     inc     eax;cmp eax,-1
    49.     jz      EXIT
    50.     dec     eax
    51.     mov hFile,rax
    52.     invoke  GetFileSize,rax,0
    53.     mov FileSize,rax
    54. ;creation in memory of object "a file projection"
    55.         invoke  CreateFileMapping,hFile,0,PAGE_READWRITE,0,0,0
    56.     mov hMapping,rax
    57. ;display of a projection of the file to address space of process
    58.         invoke    MapViewOfFile,rax,FILE_MAP_WRITE,0,0,0
    59.     mov     pMapping,rax
    60.     invoke  WriteConsole,hOut,rax,FileSize,&szReadWrite,0        ;to bring buffer contents to the console
    61.     invoke  UnmapViewOfFile,pMapping
    62.     invoke  CloseHandle,pMapping     ;to close the file
    63.         invoke  CloseHandle,hMapping
    64. ;--------------------------------------------------------
    65.     invoke  WriteConsole,hOut,&Str2,sizeof Str2,&szReadWrite,0        ;to bring Str2 to the console
    66. ;--------------------------------------------------------
    67. @@:     invoke  ReadConsoleInput,hIn,&MOUSE_KEY,1,&szReadWrite
    68.         lea     eax,MOUSE_KEY
    69.     cmp     [rax+INPUT_RECORD.EventType],MOUSE_EVENT
    70.     je  @b
    71.     cmp     [rax+INPUT_RECORD.EventType],KEY_EVENT
    72.     jne     @b
    73.     cmp     [rax+INPUT_RECORD.KeyEvent.wVirtualKeyCode],VK_ESCAPE
    74.     jne     @b
    75. EXIT:   invoke  FreeConsole
    76.     invoke RtlExitUserProcess,NULL
    77. WinMain endp
    78. hIn dq ?
    79. hOut dq ?
    80. Str1 db 'Memory Mapped File',0
    81. Str2 db 13,10,'For exit press ESC or CTRL+C or CTRL+Break'
    82. filename db '16.asm',0
    83. end
    Здесь исходный текст программы и ехе-файл
    Вывод графики в консольное приложение
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. ;----------------------------------------------
    4. .code
    5. WinMain proc
    6. local ConsoleWindow:SMALL_RECT
    7. local cci:CONSOLE_CURSOR_INFO
    8. local hWnd:qword
    9. local hDC:qword
    10. local hbitmap:qword
    11. local memDC:qword
    12. local bi:BITMAP
    13. local ScreenX:dword
    14. local ScreenY:dword
    15.     invoke  FreeConsole ; освободим существующую консоль
    16.         invoke  AllocConsole    ; образуем свою консоль
    17.     invoke  SetConsoleTitle,&NameConsole; определение заголовка окна
    18.         invoke  GetStdHandle,STD_OUTPUT_HANDLE    ; получаем handle для вывода
    19.         mov hOut,rax
    20. ; загружаем рисунок в Heap
    21.         invoke  LoadImage,400000h,&bmp_path,0,0,0,LR_LOADFROMFILE
    22.     mov hbitmap,rax
    23.         invoke  GetObject,rax,sizeof BITMAP,&bi
    24.         movzx   eax,bi.mBitsPixel
    25.     shr eax,3           ; eax=bmBitsPixel/8
    26.     mul bi.bmWidth
    27.     mul bi.bmHeight
    28.     mov edi,eax ;eax=bmpBitsPixel*bmpWidth*bmBitsPixel/8
    29.         invoke  GetProcessHeap
    30.     invoke  RtlAllocateHeap,rax,HEAP_NO_SERIALIZE,edi
    31.     mov eax,bi.bmWidth
    32.     shr eax,3
    33.     mov ScreenX,eax     ; eax=bmWidth/8
    34.     mov edx,357913941       ; edx=(2^32)/12
    35.         mov eax,bi.bmHeight
    36.     mul edx
    37.         mov ScreenY,edx         ; edx=bmHeight/12
    38.     invoke    GetLargestConsoleWindowSize,hOut
    39. ;;  eax return in 31-16 bits: dwCoord.y
    40. ;;                15-00 bits: dwCoord.x
    41.         lea r8d,ConsoleWindow
    42.     mov dword ptr [r8],0
    43.     sub eax, ScreenX
    44.     sbb edx, edx
    45.     and ax, dx
    46.     dec eax
    47.     add eax, ScreenX
    48.     mov [r8+SMALL_RECT.Right],ax
    49.     shr eax, 16
    50.     sub eax,ScreenY
    51.     sbb edx, edx
    52.     and eax, edx
    53.     dec eax
    54.     add eax, ScreenY
    55.     mov [r8+SMALL_RECT.Bottom],ax
    56.     invoke  SetConsoleWindowInfo,hOut,TRUE
    57.     mov edx,ScreenY
    58.     shl edx,16                  ; Coord.y=ScreenY
    59.     add edx,ScreenX     ; Coord.x=ScreenX
    60.     invoke  SetConsoleScreenBufferSize,hOut;устанавливаем новый
    61. ;размер окна консоли, который зависит от размера рисунка
    62. ;прячем курсор----------------------------------------
    63.     invoke  GetConsoleCursorInfo,hOut,&cci
    64.         lea edx,cci                 ; lpConsoleCursorInfo
    65.     mov [rdx+CONSOLE_CURSOR_INFO.bVisible],ebx  ; FALSE
    66.     invoke  SetConsoleCursorInfo,hOut
    67. ;-----------------------------------------------------
    68.         invoke  CloseHandle,hOut
    69. ;------------------------------------------------------
    70.     invoke  GetConsoleWindow
    71.     mov hWnd,rax
    72.     invoke  GetDC,rax       ;получить DC
    73.     mov hDC,rax
    74.     invoke  CreateCompatibleDC,rax  ;создать совместимый DC
    75.     mov memDC,rax
    76.     invoke  SelectObject,rax,hbitmap
    77. ;--------------------------------------------------------
    78. @@: invoke  Sleep,150
    79.     mov eax,bi.bmHeight     ;Rect.bottom
    80.     mov [rsp+20h],rax
    81.     mov r9d,bi.bmWidth      ;Rect.right
    82.     invoke  BitBlt,hDC,0,0,,,memDC,0,0,SRCCOPY
    83.         invoke  GetAsyncKeyState,VK_ESCAPE       ; vKey
    84. ; Determine whether a key is up or down
    85.     test    eax, 8000h
    86.     jz  @b
    87. ;---------------------------------------------------------
    88.     invoke  DeleteObject,hbitmap
    89.     invoke  ReleaseDC,hDC,hWnd   ;освободить DC
    90.     invoke  DeleteDC,memDC    ;удаляем виртуальное окно
    91.         invoke  FreeConsole
    92.     invoke RtlExitUserProcess,NULL
    93. WinMain endp
    94. ;---------------------------------------------------------
    95. bmp_path db '47.bmp',0
    96. hOut dq ?
    97. NameConsole db "For exit press 'Esc'",0
    98. end
    Здесь исходный текст программы и ехе-файл
    00.png
    Имитация заряда аккумулятора
    asm-файл
    Код (ASM):
    1. ; CONSOLE #
    2. include win64a.inc
    3. MAXSCREENX = 80
    4. MAXSCREENY = 25
    5. .code
    6. WinMain proc
    7. local Result:dword
    8. local color:dword
    9. local cci:CONSOLE_CURSOR_INFO
    10. local ConsoleWindow:SMALL_RECT
    11.  
    12.         invoke FreeConsole
    13.         invoke AllocConsole ; Allocate the console
    14.         invoke GetStdHandle,STD_OUTPUT_HANDLE
    15.         mov hOut,rax
    16. ;-------------------------------------------------------------------
    17. invoke GetLargestConsoleWindowSize,eax
    18. ; eax return in 31-16 bits: dwCoord.y
    19. ;               15-00 bits: dwCoord.x
    20.         lea r8d,ConsoleWindow
    21. and dword ptr [r8],0               ; ConsoleWindow.Left = 0 ConsoleWindow.Top = 0
    22. sub ax, MAXSCREENX
    23. sbb edx, edx
    24. and ax, dx
    25. add ax, MAXSCREENX-1
    26. mov [r8+SMALL_RECT.Right],ax
    27. shr eax, 16
    28. sub eax, MAXSCREENY
    29. sbb edx, edx
    30. and eax, edx
    31. add eax, MAXSCREENY-1
    32. mov [r8+SMALL_RECT.Bottom],ax
    33. invoke SetConsoleWindowInfo,hOut,TRUE
    34. invoke SetConsoleScreenBufferSize,hOut,MAXSCREENY*10000h+MAXSCREENX;establish the new size of a window of the console
    35. invoke SetConsoleTitle,&Str2 ;definition of a title bar
    36. ;hide the cursor------------------------------------------------------
    37. invoke GetConsoleCursorInfo,hOut,&cci
    38.         lea edx,cci                  ; lpConsoleCursorInfo
    39. mov [rdx+CONSOLE_CURSOR_INFO.bVisible],FALSE
    40. invoke SetConsoleCursorInfo,hOut
    41. ;--------------------------------------------------------------------
    42.         invoke WriteConsole,hOut,&Str3,sizeof Str3,&Result,0 ;remove a line of symbols
    43. main_loop:invoke SetConsoleCursorPosition,hOut,20001h;coord
    44. xor edi,edi
    45. @@: mov edx,edi
    46. shr edx,2
    47. movzx edx,index_color[rdx] ;color
    48.         invoke SetConsoleTextAttribute,hOut
    49.         mov edx,edi
    50. and edx,3
    51. add edx,offset Str4
    52.         invoke WriteConsole,hOut,,1,&Result,0 ;remove a line of symbols
    53. inc edi
    54. invoke GetAsyncKeyState,VK_ESCAPE ; vKey
    55. ; Determine whether a key is up or down
    56. test eax, 8000h
    57. jnz exit0
    58. invoke Sleep,1000
    59. cmp edi,16
    60. jb @b
    61.         invoke SetConsoleCursorPosition,hOut,20001h;coord
    62.         invoke SetConsoleTextAttribute,hOut,0
    63.         invoke WriteConsole,hOut,&Str1,16,&Result,0 ;remove a line of symbols
    64. invoke Sleep,1000
    65. jmp     main_loop
    66. ;--------------------------------------------------------------
    67. exit0: invoke CloseHandle,hOut
    68.         invoke FreeConsole
    69.         invoke RtlExitUserProcess,NULL
    70. WinMain endp
    71. hOut dq ?
    72. Str1 db 16 dup (0)
    73. Str2 db 'Charge accumulator',0
    74. Str3 db 'For an exit from the program press CTRL+C or CTRL+Break key',10,\
    75. 0C9h, 16 dup (0CDh),0BBh,10,\
    76. 0BAh, 16 dup (0),   0BAh,0DDh,10,\
    77. 0C8h, 16 dup (0CDh),0BCh
    78. Str4  db 176,   177,  178, 0DBh
    79. index_color db 4,0Ch,0CEh,0EFh
    80. end
    Здесь исходный текст программы и ехе-файл
    01.png

    Теоретические основы программирования
    консольных приложений

    Консоли. Текстовый пользовательский интерфейс
    (Character User Interface)
    Консоли управляют вводом и выводом (I/O) консольных приложений (character-mode applications) (прикладных программ, которые не предусматривают свой собственный графический интерфейс пользователя (Graphics User Interface ― GUI)) — разновидность интерфейса пользователя, использующая при вводе-выводе и представлении информации исключительно набор буквенно-цифровых символов и символов псевдографики. Характеризуется малой требовательностью к ресурсам аппаратуры ввода-вывода (в частности, памяти) и высокой скоростью отображения информации.
    Недостатком подобного типа интерфейса является ограниченность изобразительных средств по причине ограниченности количества символов, включённых в состав шрифта, предоставляемого аппаратурой.
    Программы с текстовым интерфейсом могут имитировать оконный интерфейс.
    В простейшем случае текстовый интерфейс использует интерфейс командной строки, однако многие программы с помощью интерактивных элементов создают более дружественный интерфейс, приближающийся по удобству к графическому.
    В текстовом интерфейсе реализованы все базовые элементы интерфейса, используемые и в графическом интерфейсе — меню, кнопки, переключатели, флажки, выпадающие списки, полосы прокрутки и так далее.
    На программном уровне для ввода и вывода информации консольные программы используют стандартные устройства ввода-вывода (stdin, stdout, stderr), хотя могут открывать и другие файлы, сетевые соединения и совершать иные действия, доступные в выполняющей их среде. Вывод печатных символов в stdout и stderr приводит к появлению этих символов на устройстве вывода и к получению их пользователем.
     

    Вложения:

    • 18.zip
      Размер файла:
      2,4 КБ
      Просмотров:
      443
    • 17.zip
      Размер файла:
      559,3 КБ
      Просмотров:
      491
    • 16.zip
      Размер файла:
      2,4 КБ
      Просмотров:
      663
    • 15.zip
      Размер файла:
      2,4 КБ
      Просмотров:
      678
    • 14.zip
      Размер файла:
      2,3 КБ
      Просмотров:
      655
    Последнее редактирование: 20 апр 2021
    __sheva740, Alex81524, Коцит и ещё 1-му нравится это.
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786
    Консольная программа не обязана заботиться о реализации самого взаимодействия с пользователем, ограничиваясь вводом-выводом на стандартные устройства. Собственно взаимодействие с пользователем обычно осуществляет операционная система.
    Любая программа, получающая данные путём чтения stdin и отправку данных путём записи в stdout, по определению является консольной программой. Однако, такие программы могут обходиться и без пользователя, поскольку stdin и stdout могут быть связаны не с интерактивными устройствами (клавиатурой и монитором), а с файлами или потоками ввода/вывода других программ.
    Консольные функции дают возможность разного уровня доступа к консоли. Высокоуровневые консольные функции ввода-вывода данных (I/O) дают возможность приложению читать из их стандартного ввода данных, чтобы извлечь введённую информации с клавиатуры, сохраненную во входном буфере консоли. Функции также дают возможность программе записать в стандартный вывод или показать на экране текст стандартной ошибки в экранном буфере консоли. Высокоуровневые функции поддерживают также переадресацию стандартных дескрипторов и управление режимами работы консоли для различных функциональных возможностей ввода-вывода. Низкоуровневые консольные функции I/O дают возможность прикладным программам получит подробный отчет о событиях ввод данных от клавиатуры и мыши, а также о событиях, включающих взаимодействие пользователя с консольным окном. Низкоуровневые функции также дают больше возможностей в управлении выводом данных на экран.
    Консольные приложения ― некогда единственная форма программного обеспечения для работы с пользователем. После широкого распространения программ с графическим интерфейсом, консольные приложения продолжают сохранять своё значение. Постепенно программное обеспечение с GUI практически полностью вытеснило приложения с текстовым интерфейсом из повседневного использования. Однако и сейчас есть консольные приложения, которые могут в большей или меньшей степени конкурировать с программами с графическим интерфейсом, быть полезными при решении разнообразных задач.
    Виды консольных программ:
    • Файловые менеджеры (Far menager)
    • Мультимедиа
    • Веб браузеры
    • Текстовые редакторы
    О консольных приложениях
    Консоли обеспечивают высокоуровневую поддержку для простых консольных приложений, взаимодействующих с пользователем, используя функции, которые читают из стандартного ввода данных и записывают в стандартный вывод или стандартную ошибку. Консоли также предусматривают сложную низкоуровневую поддержку, которая дает прямой доступ к экранному буферу консоли, а это дает возможность прикладным программам получать расширенную входную информацию (такую, как ввод данных от мыши).
    Консоль (console) ― интерфейс, который обеспечивает ввод-вывод данных консольным приложениям. Этот независимый от процессора механизм делает её легкой для поддержания в готовности существующих консольных приложений или создание новых консольных инструментальных средств и прикладных программ.
    Консоль состоит из буфера вводимых данных и одного или нескольких экранных буферов. Буфер вводимых данных (input buffer) содержит очередь записей введенных данных, каждая из которых содержит информацию о событии ввода. Входная очередь всегда включает в себя события отпуска и нажатия клавиши. Она может также включать в себя события с мышью (перемещение указателя и нажатие и отпускание кнопки) и события, в течение которых действия пользователя воздействуют на размер активного экранного буфера. Экранный буфер (screen buffer) ― двухмерный массив символьных данных и данных о цвете для вывода информации в консольном окне.
    Любое число процессов может совместно использовать консоль.
    Функции Windows API дают возможность разного уровня доступа к консоли. Высокоуровневые консольные функции I/O дают возможность приложению читать из стандартного ввода данных, чтобы получать ввод информации от клавиатуры, сохраненный в буфере ввода консоли. Функции дают также возможность прикладной программе записывать в стандартный вывод или показать на экране текст стандартной ошибки в экранном буфере консоли. Высокоуровневые функции также поддерживают переназначение стандартных дескрипторов и управление режимами работы консоли для разных функциональных возможностей ввода-вывода (I/O). Низкоуровневые консольные функции I/O дают возможность прикладным программам получить подробный ввод данных
    о событиях с клавиатурой и мышью, также как и о событиях, включающих взаимодействие пользователя с консольным окном. Низкоуровневые функции к тому же включают большую часть управления выводом на экран.
    Создание консоли
    оригинал на английском
    Система создает новую консоль тогда, когда она запускает консольный процесс (console process), процесс символьного режима, точка входа которого ― функция main. Например, система создает новую консоль, когда она запускает командный процессор. Когда командный процессор запускает новый консольный процесс, пользователь может установить, создает ли система новую консоль для нового процесса или она наследует консоль командного процессора.
    Процесс может создать консоль, используя один из следующих способов:
    • GUI или консольный процесс может использовать функцию CreateProcess с флажком CREATE_NEW_CONSOLE, чтобы создать консольный процесс с новой консолью. (По умолчанию, консольный процесс наследует консоль своего родителя, однако нет гарантии, что вводимые данные получит процесс, для которого они были предназначены).
    • Графический интерфейс пользователя (GUI) или консольный процесс, который в настоящее время не связан с консолью могут использовать функцию AllocConsole для создания новой консоли. (Процесс, который вызывает функцию AllocConsole, не должен подключаться к существующей консоли. Процессы GUI, когда они создаются, не подключаются к консоли. Консольные процессы не связываются с консолью, если они созданы с использованием функции CreateProcess с флажком DETACHED_PROCESS).
    • Как правило, процесс использует функцию AllocConsole, чтобы создать консоль, когда происходит ошибка, требующая взаимодействия с пользователем. Например, процесс GUI может создать консоль, когда происходит ошибка, которая препятствует ему использовать его нормальный графический интерфейс, или консольный процесс, который обычно не взаимодействует с пользователем, может создать консоль, чтобы показать на экране ошибку.
    Процесс может также создать консоль, устанавливая флажок CREATE_NEW_CONSOLE при вызове функции CreateProcess. Этот метод создает новую консоль, которая является доступной для дочернего процесса, но не для родительского процесса. Отдельные консоли дают возможность, и родительским и дочерним процессам взаимодействовать с пользователем без конфликта. Если этот флажок не установлен, когда создается консольный процесс, оба процесса присоединяются на одну ту же консоль, и нет никакой гарантии, что корректный процесс получит ввод данных, предназначенный для него. Прикладные программы могут предотвратить, беспорядок, создавая дочерние процессы, которые не наследуют дескрипторы буфера вводимых данных, или включать одновременно только один дочерний процесс, который наследует дескриптор буфера вводимых данных, в тоже время предотвращая чтение родительским процессом введенных данных консоли, до тех пор, пока не дочерний процесс не закончил.
    Создание новой консоли заканчивается созданием консольного окна, а также отдельных экранных буферов ввода-вывода. Процесс связывается с новой консолью, используя функцию GetStdHandle, чтобы получить дескрипторы экранных буферов и буфера ввода данных новой консоли. Эти дескрипторы дают возможность процессу обращаться к консоли.
    Когда процесс использует функцию CreateProcess, он может определить структуру STARTUPINFO, члены которой управляют характеристиками первой новой консоли (если таковая имеется) созданной для дочернего процесса. Структура STARTUPINFO, определяемая при вызове функции CreateProcess воздействует на созданную консоль, если установлен флажок CREATE_NEW_CONSOLE. Она также воздействует на созданную консоль, если дочерний процесс впоследствии использует функцию AllocConsole. Ниже перечислены параметры консоли, которые могут быть заданы:
    • Размер окна новой консоли, в знакоместах
    • Размещение окна новой консоли в пиксельных экранных координатах
    • Размер экранного буфера консоли, в знакоместах
    • Атрибуты цвет текста и фона экранного буфера новой консоли
    • Экранное имя в строке заголовка нового консольного окна
    • Система использует значения по умолчанию, если значения STARTUPINFO не определены. Дочерний процесс может использовать функцию GetStartupInfo, чтобы установить значения в своей структуре STARTUPINFO.
    Процесс не может изменить местоположение своего консольного окна на экране, но нижеследующим консольным функциям доступно устанавливать или извлекать другие параметры, определяемые в структуре STARTUPINFO.
    ФункцияОписание
    GetConsoleScreenBufferInfoИзвлекает размер окна, размер экранного буфера и атрибуты цвета.
    SetConsoleWindowInfoИзменяет размер окна консоли.
    SetConsoleScreenBufferSizeИзменяет размер экранного буфера консоли.
    SetConsoleTextAttributeУстанавливает атрибуты цвета.
    SetConsoleTitleУстанавливает заголовок окна.
    GetConsoleTitleИзвлекает заголовок окна консоли.
    Процесс может использовать функцию FreeConsole, чтобы отключить себя от унаследованной консоли или от консоли, созданной функцией AllocConsole.
    Присоединение к консоли
    оригинал на английском
    Процесс может использовать функцию AttachConsole, чтобы подключиться к консоли. Процесс может быть подключен к одной консоли.
    Консоль может иметь много процессов связанных с ней. Чтобы получить список процессов, связанных с консолью, вызовите функцию GetConsoleProcessList.
    Закрытие консоли
    оригинал на английском
    Процесс может использовать функцию FreeConsole, чтобы отключить себя от ее консоли. Если другие процессы совместно используют консоль, консоль не разрушается, но процесс, который обратился к функции FreeConsole не сможет обратиться к ней. После вызова FreeConsole, процесс может использовать функцию AllocConsole, чтобы создать новую консоль или функцию AttachConsole, чтобы подключиться к другой консоли.
    Консоль закрывается, когда последний процесс, связанный с ней завершает работу или вызывает функцию FreeConsole.
    Дескрипторы консоли
    оригинал на английском
    Консольный процесс использует дескрипторы для того, чтобы обратиться к буферу ввода данных и экранным буферам своей консоли. Процесс может использовать функцию GetStdHandle, CreateFile или функцию CreateConsoleScreenBuffer, чтобы открыть один из этих дескрипторов
    Функция GetStdHandle обеспечивает механизм для получения дескрипторов стандартного ввода данных (STDIN), стандартного вывода данных (STDOUT) и стандартной ошибки (STDERR), связанных с процессом. В ходе создания консоли, система генерирует эти дескрипторы. Вначале, дескриптор STDIN для буфера вводимых данных консоли, а затем дескрипторы STDOUT и STDERR активного экранного буфера консоли. Однако функция SetStdHandle может переназначать стандартные дескрипторы, изменяя дескриптор, связанный с STDIN, STDOUT или STDERR. Поскольку стандартные дескрипторы родительского элемента наследуются любым дочерним процессом, последующие вызовы к GetStdHandle возвращают переназначенный дескриптор. Дескриптор, возвращенный функцией GetStdHandle, по этой причине может сослаться на что-либо другое, а не на консольный ввод-вывод (I/O). Например, перед созданием дочернего процесса, родительский процесс может использовать SetStdHandle, чтобы установить дескриптор канала, который должен быть дескриптором STDIN и который будет унаследован дочерним процессом. Когда дочерний процесс вызывает функцию GetStdHandle, он получает дескриптор канала. Это означает, что родительский процесс может управлять стандартными дескрипторами дочернего процесса. Дескрипторы, возвращенные функцией GetStdHandle, имеют доступ GENERIC_READ | GENERIC_WRITE, если функция SetStdHandle не была использована для установки стандартного дескриптора, имеющего меньший доступ.
    Значение дескрипторов, возвращенных функцией GetStdHandle ― не 0, 1 и 2, как стандартные предопределенные константы потока в файле Stdio.h (STDIN, STDOUT и STDERR), не могут быть использованы в функциях, которые требуют дескриптора консоли.
    Функция CreateFile дает возможность процессу получить дескриптор для буфера вводимых данных его консоли и активного экранного буфера, даже если STDIN и STDOUT были переназначены. Чтобы открыть дескриптор буфера вводимых данных консоли, при вызове функции CreateFile установите значение CONIN$. Чтобы открыть дескриптор активного экранного буфера консоли, при вызове CreateFile установите значение CONOUT$. Функция CreateFile дает возможность Вам, чтобы определять доступ для чтения ― записи дескриптора, который она возвращает.
    Функция CreateConsoleScreenBuffer создает новый экранный буфер и возвращает дескриптор. Этот дескриптор может быть использован в любой функции, которая принимает дескриптор для консольного вывода данных. Новый экранный буфер не активен до тех пор, пока его дескриптор не определится при вызове к функции SetConsoleActiveScreenBuffer.
    Обратите внимание на то, что этот изменяющийся активный экранный буфер не воздействует на дескриптор, возвращенный GetStdHandle. Точно так же использование функции SetStdHandle, чтобы изменить дескриптор STDOUT не воздействует на активный экранный буфер.
    Консольные дескрипторы, возвращенные функциями CreateFile и CreateConsoleScreenBuffer, могут быть использованы в любой из консольных функций, которые требуют дескриптора буфера вводимых данных или экранного буфера консоли. Дескрипторы, возвращенные функцией GetStdHandle могут быть использованы консольными функциями, если они не были переназначены, чтобы не сослаться на что-либо иное, чем консольный ввод-вывод. Однако, если стандартный дескриптор был переназначен, чтобы сослаться на файл или канал, он может быть использован только функциями ReadFile и WriteFile.
    Процесс может использовать функцию DuplicateHandle, чтобы создать дубликат консольного дескриптора, который имеет другой доступ или наследственность от исходного дескриптора.
    Обратите внимание на то, что, не смотря на это, процесс может создать дубликат дескриптора консоли только для своего собственного использования. Это его отличает от других типов дескрипторов, (таких как файла, канала или мьютекс-объекта), для которых функция DuplicateHandle может создавать дубликат, являющийся допустимым для другого процесса.
    Чтобы закрыть консольный дескриптор, процесс может использовать функцию CloseHandle.
    Буфер вводимых данных консоли
    Каждая консоль имеет буфер вводимых данных, который содержит очередь записей о событиях ввода. Когда окно консоли имеет фокус клавиатуры, консоль оформляет каждое событие ввода (типа отдельного нажатия клавиши, перемещение мыши или щелчка кнопки мыши) как введенное данное, которое оно помещает в буфер вводимых данных консоли.
    Прикладные программы могут обращаться к буферу вводимых данных консоли косвенно при помощи использования высокоуровневых консольных функций I/O или непосредственно при помощи использования низкоуровневых консольных функций ввода. Высокоуровневые функции ввода фильтруют и обрабатывают данные в буфере вводимых данных, возвращая только поток введенных символов. Низкоуровневые функции ввода дают возможность прикладным программам читать введенные данные непосредственно из буфера вводимых данных консоли, или помещать введенные данных в буфер вводимых данных. Чтобы открыть дескриптор буфера вводимых данных консоли, при вызове к функции CreateFile установите значение CONIN$.
    Запись ввода данных ― это структура, содержащая информацию о типе события, которое произошло (клавиатура, мышь, изменение размеров окна, фокус или событие меню), а также конкретные детали о событии. Поле EventType в структуре INPUT_RECORD содержит тип события в записи.
    Фокус и события меню помещаются в буфере вводимых данных консоли для внутреннего использования системой и должны быть игнорироваться прикладными программами.
    События клавиатуры
    События клавиатуры генерируются тогда, когда любая клавиша нажимается или отпускается; это включает в себя управляющие клавиши. Однако клавиша ALT имеет специальное предназначение в системе, когда нажимается и отпускается без объединения с другим символом, и это не передается прямо в приложение. Комбинация клавиш CTRL+C также не передается непосредственно в программу, если введенный дескриптор находится в режиме обработки.
    Если событие ввода ― нажатие клавиши, поле Event в структуре INPUT_RECORD является структурой KEY_EVENT_RECORD, содержащей нижеследующую информацию:
    • Булево значение, указывающее, была ли клавиша нажата или отпущена.
    • Счет повторений, который может быть больше, чем один, когда клавиша удерживается.
    • Код виртуальной клавиши, идентифицирующий данную клавишу не зависящим от устройства способом.
    • Виртуальный ― скэн-код, обозначающий аппаратно-зависимое значение, созданное аппаратными средствами клавиатуры.
    • Преобразованный символ UNICODE или ANSI.
    • Флажковая переменная, которая указывает на состояние управляющих клавиш (клавиши ALT, CTRL, SHIFT, NUM LOCK, SCROLL LOCK и CAPS LOCK) и обозначает, была ли нажата дополнительная клавиша. Дополнительные клавиши для 101-клавишные и 102-клавишные клавиатуры имеют INS, DEL, HOME, END, PAGE UP, PAGE DOWN клавиши и клавиши со стрелкой в блоках слева от цифровой клавиатуры и клавиши делителя (/) и ENTER в цифровой клавиатуре.
    События мыши
    События с мышью генерируются всякий раз, когда пользователь перемещает мышь или нажимает или отпускает одну из кнопок мыши. События с мышью помещаются в буфере вводимых данных, только в том случае, если выполнены нижеследующие условия:
    • Режим ввода консоли установлен в значение ENABLE_MOUSE_INPUT (режим заданный по умолчанию).
    • Консольное окно имеет фокус клавиатуры.
    • Курсор мыши находится в пределах рамок окна консоли.
    Если событие ввода ― событие с мышью, поле Event в структуре INPUT_RECORD является структурой MOUSE_EVENT_RECORD, содержащей нижеследующую информацию:
    • Координаты курсора мыши в переводе на строки и столбцы символьных знакоместа в системе координат экранного буфера консоли
    • Флажковая переменная, обозначающая состояния кнопок мыши.
    • Флажковая переменная, обозначающая состояния управляющих клавиш (клавиши ALT, CTRL, SHIFT, NUM LOCK, SCROLL LOCK и CAPS LOCK) и обозначает, была ли нажата дополнительная клавиша. Дополнительные клавиши для 101-клавишной и 102-клавишной клавиатуры имеют INS, DEL, HOME, END, PAGE UP, PAGE DOWN клавиши и клавиши со стрелкой в блоках слева от цифровой клавиатуры и клавиши делителя (/) и ENTER в цифровой клавиатуре.
    • Флажковая переменная, обозначающая, было ли событие нормальным нажатием кнопки или событием отпуска кнопки, событием перемещения мыши, или вторым щелчком события двойного щелчка.
    Обратите внимание координаты позиции мыши ― в понятиях экранного буфера консоли, не консольное окно. Экранный буфер, может прокручиваться относительно окна, так что верхний левый угол окна ― это не обязательно координата (0,0) экранного буфера консоли. Чтобы отрегулировать координаты мыши относительно системы координат окна, вычтите начальные координаты окна из координат позиции мыши. Чтобы установить начало координат окна, используйте функцию GetConsoleScreenBufferInfo.
    Поле dwButtonState структуры MOUSE_EVENT_RECORD имеет битовое соответствие для каждой кнопки мыши. Бит равен 1, если кнопка нажата, и 0, если кнопка отпущена. Событие отпуска кнопки регистрируется как значение 0 в поле dwEventFlags структуры MOUSE_EVENT_RECORD и изменяется в бите кнопки с 1 на 0. Функция GetNumberOfConsoleMouseButtons получает число кнопок на мыши
    События изменения размера буфера
    Меню консольного окна дает возможность пользователю изменить размер активного экранного буфера; это изменение создает событие изменения размеров буфера. События изменения размеров буфера помещаются в буфере вводимых данных, если режим ввода данных консоли установлен в ENABLE_WINDOW_INPUT (то есть заданный по умолчанию режим заблокирован).
    Если событие ввода данных является событием, изменяющим размеры буфера, поле Event структуры INPUT_RECORD является структурой WINDOW_BUFFER_SIZE_RECORD, содержащей новый размер экранного буфера консоли, выраженного в столбцах и строках символьных знакомест.
    Если пользователь уменьшает размер экранного буфера консоли, любые данные в отброшенной части буфера теряются.
    Изменения размера экранного буфера консоли, как результат вызовов из прикладной программы функции SetConsoleScreenBufferSize, не создают событий изменения размера буфера.
    Экранный буфер консоли
    Экранный буфер (screen buffer) ― двухмерный массив символов и данных о цвете для вывода данных в консольном окне. Консоль может иметь множество экранных буферов. Активный экранный буфер (active screen buffer) ― тот, который отображается на экране.
    Система создает экранный буфер всякий раз, когда она создает новую консоль. Чтобы открыть дескриптор активного экранного буфера консоли, при вызове к функции CreateFile установите значение CONOUT$. Процесс может использовать функцию CreateConsoleScreenBuffer, чтобы создать дополнительные экранные буферы для своей консоли. Новый экранный буфер не активен до тех пор, пока его дескриптор не будет определен при вызове к функции SetConsoleActiveScreenBuffer. Однако к экранным буферам можно обращаться для чтения и записи, независимо, являются ли они активными или неактивными.
    Каждый экранный буфер имеет свой собственный двухмерный массив записей текстовой информации. Данные для каждого символа сохраняются в структуре CHAR_INFO, которая определяет символы Unicode или ANSI, и цвет текста и цвета фона, на котором этот символ отображен.
    Ряд свойств, связанных с экранным буфером может быть установлен независимо для каждого буфера дисплея. Это означает, что изменяющийся активный экранный буфер может иметь негативное влияние на внешний вид консольного окна. Свойства, связанные с экранным буфером включают в себя:
    • Размер экранного буфера, в строках и столбцах символов.
    • Атрибуты текста (цвет текста и цвет фона для отображения на экране текста, который будет написан функцией WriteFile или WriteConsole).
    • Размер окна и расположение (прямоугольная область экранного буфера консоли, которая отображается в консольном окне).
    • Позиция, внешний вид и видимость курсора.
    • Режимы вывода (ENABLE_PROCESSED_OUTPUT и ENABLE_WRAP_AT_EOL_OUTPUT). Для получения дополнительной информации о консольных режимах вывода, см. Высокоуровневые консольные режимы работы.
    Когда экранный буфер создается, он содержит пробелы. Его курсор видим и установлен в начало координат буфера (0,0), а окно устанавливается в его верхний левый угол в начало координат буфера. Размер экранного буфера консоли, размеры окна, текстовые атрибуты и внешний вид курсора определяется пользователем или системными значениями по умолчанию. Чтобы получить текущие значения различных свойств, связанных с экранным буфером консоли, используйте функции GetConsoleScreenBufferInfo, GetConsoleCursorInfo и GetConsoleMode.
    Прикладные программы, которые изменяют любое из свойств экранного буфера консоли, должны или создать свой собственный экранный буфер или сохранить состояние унаследованного буфера дисплея в ходе запуска и восстанавливать его при выходе.
    Внешний вид и позиция курсора
    Курсор экранного буфера может быть видим или скрыт. Когда он видим, его внешний вид может изменяться в пределах от полностью заполненного знакоместа символа до вида как горизонтальная линия внизу ячейки. Чтобы получить информацию о внешнем виде и видимости курсора, используйте функцию GetConsoleCursorInfo. Эта функция сообщает, является ли курсор видимым и описывает внешний вид курсора как процентное отношение от знакоместа символа, которое он заполняет. Чтобы установить внешний вид и видимость курсора, используйте функцию SetConsoleCursorInfo.
     
    Последнее редактирование: 28 май 2019
    Alex81524 и Ronin_ нравится это.
  5. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786
    Символы, написанные высокоуровневыми консольными функциями I/O пишутся в текущем местоположении курсора, продвигая курсор к следующему местоположению. Чтобы определить текущую позицию курсора в системе координат экранного буфера, используйте функцию GetConsoleScreenBufferInfo. Вы можете использовать функцию SetConsoleCursorPosition, чтобы установить позицию курсора и, таким образом, управлять размещением текста, который написан или отображен на экране высокоуровневыми консольными функциями I/O функциями. Если Вы перемещаете курсор, текст в новом местоположении курсора переписывается.
    Позиция, внешний вид и видимость курсора устанавливаются независимо для каждого экранного буфера.
    Атрибуты символов
    Атрибуты символов могут быть поделены на два класса: класс цвета и класс DBCS (double-byte character set) ― набор двухбайтовых комбинаций символов. Нижеследующие атрибуты определяются в заголовочном файле Wincon.h.
    АтрибутПредназначение
    FOREGROUND_BLUEСодержит синий цвет текста
    FOREGROUND_GREENСодержит зеленый цвет текста
    FOREGROUND_REDСодержит красный цвет текста
    FOREGROUND_INTENSITYЦвет текста имеет повышенную интенсивность
    BACKGROUND_BLUEСодержит синий цвет фона
    BACKGROUND_GREENсодержит зеленый цвет фона
    BACKGROUND_REDСодержит красный цвет фона
    BACKGROUND_INTENSITYЦвет фона имеет повышенную интенсивность
    COMMON_LVB_LEADING_BYTEНачальный байт
    COMMON_LVB_TRAILING_BYTEКонцевой байт
    COMMON_LVB_GRID_HORIZONTALВерх горизонтали
    COMMON_LVB_GRID_LVERTICALЛевая вертикаль
    COMMON_LVB_GRID_RVERTICALПравая вертикаль
    COMMON_LVB_REVERSE_VIDEOИзменяет на противоположные атрибуты цвета текста и цвета фона
    COMMON_LVB_UNDERSCOREПодчеркивает
    Атрибуты цвета текста определяют его цвет. Атрибуты фона определяют цвет, который используется для закрашивания фона ячейки. Другие атрибуты используются DBCS.
    Приложение может комбинировать константы цвета текста и фона, чтобы получать разные цвета. Например, нижеследующая комбинация приводит к яркому синему тексту на синем фоне.
    Код (Text):
    1. FOREGROUND_BLUE + FOREGROUND_GREEN + FOREGROUND_INTENSITY + BACKGROUND_BLUE
    Если константа фона не определена, то фон черный, а если константа цвета текста не определена, текст черный. Например, нижеследующая комбинация производит черный текст на белом фоне.
    Код (Text):
    1. BACKGROUND_BLUE + BACKGROUND_GREEN + BACKGROUND_RED
    Каждое знакоместо символа экранного буфера сохраняет атрибуты цвета для цветов, используемых в прорисовке цвета текста (текст) и фона этой ячейки. Приложение может устанавливать данные о цвете для каждого знакоместа символа индивидуально, сохраняя информацию в поле Attributes структуры CHAR_INFO для каждой ячейки. Текущие атрибуты текста каждого экранного буфера используются для символов, впоследствии записываемых или отображаемых на экране высокоуровневыми функциями.
    Приложение может использовать функцию GetConsoleScreenBufferInfo, чтобы регулировать текущие текстовые атрибуты экранного буфера и функцию SetConsoleTextAttribute, чтобы установить атрибуты символов. Изменение атрибутов экранного буфера не воздействует на отображение символов, записанных перед этим. Эти текстовые атрибуты не затрагивают символы, написанные низкоуровневыми консольными функциями I/O (типа функции WriteConsoleOutput или WriteConsoleOutputCharacter), которые или явно устанавливают атрибуты для каждой ячейки, в которой есть запись, или оставляют атрибуты неизменными.
    Атрибуты шрифта
    Функция GetCurrentConsoleFont извлекает информацию о текущем консольном шрифте. Информация, сохраненная в структуре CONSOLE_FONT_INFO включает в себя ширину и высоту каждого символа в шрифте.
    Функция GetConsoleFontSize получает данные о размере шрифта, используемого заданным экранным буфером консоли.
    Окно и размер экранного буфера
    Размер экранного буфера выражается в понятиях координатной сетки, основанной на знакоместах символов. Ширина равна числу символьных знакомест в каждой строке, а высота ― числу строк. С каждым экранным буфером связано окно, которое обуславливает размер и расположение прямоугольной части экранного буфера консоли, отображенного в консольном окне. Окно экранного буфера определяется при помощи установки координат в символьных знакоместах верхней левой и нижней правой ячеек прямоугольника окна.
    Экранный буфер может быть любого размера, ограниченный только доступной памятью. Размеры окна экранного буфера, основанные на текущем размере шрифта (управляемым исключительно пользователем), не могут превышать соответствующие размеры или экранного буфера консоли, или максимального окна, которое может вместиться на экране.
    Функция GetConsoleScreenBufferInfo возвращает нижеследующую информацию об экранном буфере и его окне:
    • Текущий размер экранного буфера консоли
    • Текущее местоположение окна
    • Максимальный размер данного окна при текущем размере экранного буфера, текущий размер шрифта и размер экрана.
    Функция GetLargestConsoleWindowSize возвращает значение максимального размера окна консоли, базирующейся на текущем шрифте и размеры экрана. Эти размеры отличаются от максимального размера окна, возвращаемого функцией GetConsoleScreenBufferInfo, в которой размер экранного буфера консоли игнорируется.

    Чтобы изменить размер экранного буфера, используйте функцию SetConsoleScreenBufferSize. Эта функция терпит неудачу, если любой габарит определяемого размера является меньше, чем соответствующий размер окна консоли.
    Чтобы изменить размер или расположение окна экранного буфера, используйте функцию SetConsoleWindowInfo. Эта функция не выполняет свою задачу, если координаты угла определяемого окна превышают пределы экранного буфера консоли или экрана. Изменение размера окна активного экранного буфера изменяет размер консольного окна, отображенного на экране.
    Процесс может изменить режим ввода данных своей консоли, чтобы дать возможность вводить данные окна так, чтобы процесс был в состоянии получить вводимую информацию, когда пользователь изменяет размер экранного буфера консоли. Если приложение дает возможность ввод данных окна, оно может использовать функцию GetConsoleScreenBufferInfo, чтобы получить окно и размер экранного буфера при автозагрузке. Эта информация может затем использоваться, чтобы определить способ, которым информация будет показана на экране в окне. Если пользователь изменяет размер экранного буфера консоли, приложение может в ответ изменить способ, которым информация показывается на экране. Например, приложение может откорректировать способ автоматического переноса текста на новую строку в конце строки, если число символов в строке изменяется. Если приложение не дает возможности ввод данных в окно, оно должно или использовать унаследованное окно, а экранный буфер изменяет размер, или привести их к желательному размеру в течение запуска и восстанавливать унаследованный буфер, изменяя размер при выходе. Для дополнительной информации о режиме ввода данных окна, смотри раздел Низкоуровневые консольные режимы работы.

    Прокрутка экранного буфера
    Консольное окно показывает на экране часть активного экранного буфера. Каждый экранный буфер поддерживает свой собственный текущий прямоугольник окна, который задает координаты верхних левых и нижних правых символьных знакомест, которые будут показаны на экране в консольном окне. Чтобы установить текущий прямоугольник окна экранного буфера, используйте функцию GetConsoleScreenBufferInfo. Когда экранный буфер создается, верхний левый угол его окна находится в верхнем левом угле экранного буфера консоли в (0,0).

    Прямоугольник окна может изменяться, чтобы отображать различные части экранного буфера консоли. Прямоугольник окна экранного буфера может изменяться в нижеследующих ситуациях:
    • Когда вызывается функция SetConsoleWindowInfo, чтобы установить новый прямоугольник окна, она прокручивает вид экранного буфера консоли, изменяя позицию прямоугольника окна без изменения размеров окна. Примеры прокрутки содержания окна, смотри раздел Прокрутка окна экранного буфера.
    Image6.gif
    • Когда используется функция WriteFile, чтобы сделать запись в экранный буфер, тогда в режиме вывода включается переход в конце строки (EOL) на новую строку, который автоматически перемещает прямоугольник окна, так, что курсор всегда отображается на экране.
    • Когда функция SetConsoleCursorPosition устанавливает новую позицию курсора, которая находится вне границ текущего прямоугольника окна, тогда прямоугольник окна перемещается автоматически, чтобы показать на экране курсор.
    • Когда пользователь изменяет размер консольного окна или использует линейки прокрутки окна, тогда прямоугольник окна активного экранного буфера может измениться. Об этом изменении не сообщается, как о событии, изменяющем размеры окна в буфере вводимых данных.
    В каждой из этих ситуаций, прямоугольник окна перемещается, чтобы показать на экране разные части экранного буфера консоли, но содержание экранного буфера консоли остается в той же самой позиции. Нижеследующие ситуации могут заставить переместить содержание экранного буфера консоли:
    • Когда вызывается функция ScrollConsoleScreenBuffer, прямоугольный блок копируется из одной части экранного буфера в другой
    • Когда используется функция WriteFile, чтобы сделать запись в экранный буфер, тогда в режиме вывода включается переход в конце строки (EOL) на новую строку, содержание экранного буфера консоли автоматически прокручивается
    • Когда используется функция WriteFile, чтобы записать в экранный буфер с автоматическим переходом на новую строку, в случае если встречается конец экранного буфера консоли. Эта прокрутка сбрасывает верхнюю строку экранного буфера консоли.
    Функция ScrollConsoleScreenBuffer устанавливает прямоугольник экранного буфера консоли, который перемещается и новые верхние левые координаты, в которые прямоугольник копируется. Эта функция может прокручивать часть или взятое в целом содержание экранного буфера консоли.

    Иллюстрация показывает действие функции ScrollConsoleScreenBuffer, которая прокручивает несколько верхних строк взятого в целом содержания экранного буфера консоли. Содержание верхних строк отвергается, а строки внизу заполняются заданными символами и цветом.
    Image7.gif
    Действия функции ScrollConsoleScreenBuffer могут быть ограничены, при помощи установки необязательного прямоугольника отсечения по границам так, чтобы содержание экранного буфера консоли вне прямоугольника отсечения было неизменно. Действие отсечения по границам должно создать подокно (прямоугольник отсечения), содержание которого прокручивается без воздействия на остальную часть экранного буфера консоли. Пример, в котором используется, ScrollConsoleScreenBuffer, рассматривается в статье Прокрутка экранного буфера.

    Методы ввода и вывода данных
    Win32 API предоставляет два разных подхода к консольному вводу ― выводу (I/O), выбор которого зависит от того, сколько гибкости и управляемости необходимо приложению. Высокоуровневый метод включает простой символьный поток ввода-вывода, но он ограничивает доступ к буферу ввода данных консоли и экранным буферам. Низкоуровневый метод требует, чтобы разработчики писали большее количество кода и выбирали среди большего количества функций, однако это придает приложению большую гибкость.

    Приложение может использовать функции файлового ввода-вывода, ReadFile и WriteFile, и консольные функции, ReadConsole и WriteConsole, для высокоуровневого ввода-вывода, которые обеспечивают косвенный доступ к вводу данных консоли и экранным буферам. Высокоуровневые функции ввода данных фильтруют и обрабатывают информацию в буфере вводимых данных консоли, чтобы возвратить их как поток символов, не учитывая вводимой информации от мыши и при изменении размеров буфера. Точно так же, высокоуровневые функции вывода данных записывают поток символов, который отображается на экране в текущем местоположении курсора в экранном буфере. Приложение управляет способом работы этой функций, устанавливая режимы ввода-вывода консоли.

    Низкоуровневые функции I/O обеспечивают прямой доступ к вводу данных консоли и экранным буферам, давая возможность приложению обращаться к событиям мыши и событиям изменения размера буфера ввода и к расширенной информации для событий клавиатуры. Низкоуровневые функции вывода данных дают возможность приложению читать или записывать в экранном буфере заданное число последовательных символьных знакомест, или читать, или записывать в прямоугольные блоки символьные знакоместа в заданном месте в экранном буфере. Режимы ввода данных консоли воздействуют на низкоуровневый ввод данных, разрешая приложению устанавливать, чьи это события в буфере вводимых данных, мыши или изменения размера буфера. Режимы вывода информации консоли не воздействуют на низкоуровневый вывод данных.

    Высокоуровневая и низкоуровневая методики ввода-вывода не являются взаимоисключающими и приложение может использовать любую комбинацию этих функций. Тем не менее, как правило, прикладная программа использует исключительно один или другой способ.

    Нижеследующие разделы описывают консольные режимы работы и высокоуровневые и низкоуровневые функции I/O.
    Режимы консоли
    Связанная с каждым консольным буфером вводимых данных установка режимов ввода, воздействует на операции ввода информации. Точно так же, каждый экранный буфер консоли имеет установку режимов вывода, который воздействует на операции вывода данных. Режимы ввода данных могут быть разделены на две группы: которые воздействуют на высокоуровневые функции ввода данных и которые воздействуют на низкоуровневые функции ввода. Режимы вывода воздействуют только на прикладные программы, которые используют высокоуровневые функции вывода данных.
    Функция GetConsoleMode сообщает о текущем режиме ввода данных буфера ввода консоли или текущего режима вывода экранного буфера. Функция SetConsoleMode устанавливает текущий режим или консольного буфера вводимых данных или экранного буфера. Если консоль имеет множество экранных буферов, режимы вывода каждого могут быть разными. Приложение может изменять режимы ввода-вывода (I/O) в любое время. Для получения дополнительной информации о консольных режимах работы, которые находятся под влиянием высокоуровневых и низкоуровневых операций ввода-вывода, смотрите статью Высокоуровневые консольные режимы работы и Низкоуровневые консольные режимы работы.

    Функция GetConsoleDisplayMode сообщает, находится ли текущая консоль в полноэкранном режиме и связывается ли она непосредственно с аппаратными средствами.
    Высокоуровневый консольный ввод-вывод
    Функции высокоуровневого ввода-вывода (I/O) обеспечивают простой способ чтения потока символов из консольного ввода данных или записи потока символов в консольном выводе информации. Высокоуровневая операция чтения получает введенные символы из буфера вводимых данных консоли и сохраняет их в заданном буфере. Высокоуровневая операция записи берет символы из заданного буфера и записывает их в экранный буфер в текущем местоположении курсора, продвигая курсор, по мере того, как записывается символ.

    Высокоуровневый ввод-вывод дает Вам выбор между функциями ReadFile и WriteFile и функциями ReadConsole и WriteConsole. Они были бы идентичны, если бы не два важных различия. Консольные функции поддерживают использование или символов Unicode или набора символов ANSI; функции файлового ввода-вывода не поддерживают Unicode. К тому же, функции файлового ввода-вывода могут быть использованы для обращения к файлам, каналам и последовательным устройствам связи; консольные функции могут быть использованы только с консольными дескрипторами. Это различие важно, если приложение опирается на стандартные дескрипторы, которые, могут быть переназначены.

    При использовании любого набора высокоуровневых функций, приложение может управлять цветом текста и фона используемыми символами дисплея, впоследствии записанными в экранном буфере. Прикладная программа может также использовать и консольные режимы работы, которые воздействуют на высокоуровневый консольный ввод-вывод (I/O), чтобы включать или отключать нижеследующие свойства:
    • Эхо-контроль ввода информации с клавиатуры в активном экранном буфере
    • Построчный ввод данных, в котором операция чтения не возвращается до тех пор, пока не нажата клавиша ENTER.
    • Автоматические процессы ввода информации с клавиатуры, которые манипулируют возвратом каретки, CTRL+C и другими частностями ввода данных
    • Автоматические действия вывода данных, которые управляют переносом строки, возвратом каретки, возвратом на один символ и другими частностями вывода информации
    Высокоуровневые консольные режимы работы
    Характер работы высокоуровневых консольных функций находится под влиянием консольного режима ввода и вывода. Когда консоль создана, для ее буфера вводимых данных разрешены все из ниже перечисленных консольных режимов ввода:
    • Режим построчного ввода данных
    • Режим обработки ввода данных
    • Режим отражения ввода данных
    Для обоих из ниже перечисленных консольных режимов вывода, когда они создаются, разрешены действия экранного буфера консоли:
    • Режим обработки вывода данных
    • Режим переноса выводимых данных в конце строки (EOL)
    Все три режима ввода данных, наряду с режимом обработки вывода, предназначены, чтобы работать вместе. Самое лучшее или включать, или отключить все эти режимы, как группу. Когда все они включены, приложение, как говорится, находится в "приготовленном" режиме, который означает то, что большинство действий являются управляемыми для приложения. Когда все отключены, прикладная программа находится в "неприготовленном" режиме, который означает, что ввод данных не фильтруется и любая его обработка оставлена приложению.

    Прикладная программа может использовать функцию GetConsoleMode, чтобы установить текущий режим буфера вводимых данных консоли или экранного буфера. Вы можете включать или отключать любой из этих режимов при помощи использования нижеследующих значений в функции SetConsoleMode.

    Обратите внимание на то, что установка режима вывода в одном из экранных буферов не воздействует на режим вывода других экранных буферов
    РежимОписание
    ENABLE_PROCESSED_INPUTДескриптор используется консольным вводом, чтобы заставить систему обрабатывать любое системное редактирование или ввод данных от управляющей клавиши, а не возвращать его как введенное данное при операции чтения буфера. Если к тому же включается построчный ввод данных, возвраты на один символ и возвраты каретки обрабатываются правильно. Возврат на один символ заставляет курсор, двигаться назад на один пробел без воздействия на символ в позиции курсора. Возврат каретки преобразуется в комбинацию кодов возврата каретки ASCII 13 и конца строки ASCII 10, представляемые как пустая строка. Если включен отраженный режим ввода данных, а вывод данных должен отразить системное редактирование, должна быть включена обработка вывода информации для активного экранного буфера. Если включается обработка ввода данных, комбинация клавиш CTRL+C пересылается на соответствующий обработчик независимо от того, включен или нет построчный ввод данных. Для получения дополнительной информации об управляющих обработчиках, см. статью Консольное управление обработчиками.
    ENABLE_LINE_INPUTИспользуется с дескриптором консольного ввода данных, чтобы заставить функции ReadFile и ReadConsole возвращать значение, когда нажата клавиша ENTER. Если режим построчного ввода данных заблокирован, функции возвращают значение тогда, когда один или несколько символов доступны в буфере вводимых данных.
    ENABLE_ECHO_INPUTИспользуется с дескриптором консольного ввода данных, чтобы заставить ввод информации с клавиатуры читать при помощи функций ReadFile или ReadConsole, которая будет отображаться на экране активным экранным буфером. Символы отображаются на экране только в том случае, если процесс, который вызывает ReadFile или ReadConsole имеет открытый дескриптор активного экранного буфера. Эхо-режим не может быть разрешен, если также не включен построчный ввод данных. Режим вывода активного экранного буфера воздействует на способ, которым отображаемый на экране ввод данных показывается на экране.
    ENABLE_PROCESSED_OUTPUTИспользуется с дескриптором экранного буфера консоли, чтобы заставить систему выполнить соответствующее действие для управляющих символов ANSI, которые пишутся в экранном буфере. Обрабатываются возврат на один символ, перемещение при помощи клавиши TAB, звонковая сигнализация, возврат каретки и символы перевода строки. Символ табуляции перемещает курсор в следующую позицию табуляции, которая установлена через каждые восемь символов. Звонковая сигнализация издает звук краткой длительности.
    ENABLE_WRAP_AT_EOL_OUTPUTИспользуется с дескриптором экранного буфера консоли, чтобы заставить текущую позицию вывода данных (позицию курсора) переместиться в первый столбец следующей строки, когда текущая строка достигла конца. Если достигается низ области окна, начало координат окна перемещается вниз на одну строку. Это перемещение имеет действие прокрутки содержания окна на одну строку. Если достигается низ экранного буфера консоли, содержание экранного буфера консоли прокручивается на одну строку, а верхняя строка экранного буфера консоли сбрасывается.
    Если этот режим заблокирован, последний символ в строке переписывается поверх любого последующего символа.
    Высокоуровневые консольные функции ввода и вывода
    Функции ReadFile и WriteFile или функции ReadConsole и WriteConsole, дают возможность приложению читать ввод данных консоли и записывать консольный вывод информации как поток символов. ReadConsole и WriteConsole ведут себя точно подобно ReadFile и WriteFile за исключением того, что они могут быть использованы или как функции расширенного 16-битного алфавита (в которой текстовые параметры должны использовать Unicode) или как функции ANSI (в которой текстовые параметры должны использовать символы из набора символов Windows). Прикладные программы, которым нужно поддерживать один набор источников, чтобы поддержать или Unicode или набор символов ANSI, должны использовать ReadConsole и WriteConsole.
    Функции ReadConsole и WriteConsole могут быть использованы только с дескрипторами консоли; функции ReadFile и WriteFile могут быть использованы с другими дескрипторами (такими как дескрипторы файлов или каналов). Функции ReadConsole и WriteConsole завершаются с ошибкой, если используются со стандартным дескриптором, который был переназначен и больше не является консольным дескриптором.
    Чтобы получать ввод информации с клавиатуры, процесс может использовать функции ReadFile или ReadConsole с дескриптором буфера вводимых данных консоли, или он может использовать ReadFile, чтобы читать ввод данных из файла или канала, если был переназначен STDIN. Эти функции возвращают только события клавиатуры, которые могут быть преобразованы в символы ANSI (или в символы Unicode в случае ReadConsole). Ввод данных, который может быть возвращен, включает в себя комбинации управляющих клавиш. Функции не возвращают события клавиатуры, включающие функциональные клавиши или клавиши со стрелкой. События ввода, созданные мышью, окном, фокусом или вводом меню не учитываются.
    Если включен режим построчного ввода данных (режим по умолчанию), функции ReadFile и ReadConsole не возвращают значения вызывающей программе до тех пор, пока не будет нажата клавиша ENTER. Если режим построчного ввода данных заблокирован, функции не возвращают значения до тех пор, пока, по меньшей мере, не будет доступен один символ. В любом режиме, все доступные символы читаются до тех пор, пока, или к набору на клавиатуре, больше нет доступа, или было прочитано заданное число символов. Непрочитанные символы буферизируются до следующей операции чтения. Функции сообщают об общем количестве фактически прочитанных символов. Если включается эхо-режим ввода данных, символы, читаемые этими функциями, записываются в текущую позицию курсора активного экранного буфера.
    Процесс может использовать функцию WriteFile или WriteConsole, чтобы записать в или активный или неактивный экранный буфер, или, если STDOUT был переназначен, он может использовать функцию WriteFile, чтобы записать в файл или канал. Обработка режима вывода и автоматического перехода в режиме вывода на новую строку в конце строчки EOL управляется путем записи символов или отображения в экранном буфере.
    Символы, написанные функцией WriteFile или WriteConsole, или повторенные на экране функцией ReadFile или ReadConsole, вставляются в экранный буфер в текущей позиции курсора. По мере того, как пишется символ, позиция курсора продвигается на следующее символьное знакоместо; однако поведение ее в конце строки зависит от режима автоматического перехода на новую строку в режиме вывода экранного буфера консоли (EOL). Приложение может использовать функцию GetConsoleScreenBufferInfo, чтобы получить текущую позицию курсора и функцию SetConsoleCursorPosition, чтобы установить позицию курсора.
    За примером, в котором используются высокоуровневые консольные функции I/O, обратитесь к статье Высокоуровневый консольный ввод-вывод.
    Низкоуровневый консольный ввод-вывод (I/O)
    Низкоуровневые консольные функции I/O расширяют контроль приложения над консольным вводом ― выводом (I/O), разрешая прямой доступ к вводу данных консоли и экранным буферам. Эти функции дают возможность прикладной программе выполнять нижеследующие задачи:
    • Принимать ввод информации о событиях мыши и изменениях размеров буфера.
    • Принимать расширенную информацию о событиях ввода с клавиатуры.
    • Фиксировать запись ввода данных в буфере ввода.
    • Читать запись вводимых данных без их удаления из буфера ввода.
    • Выяснять число ждущих обработки событий в буфере ввода.
    • Сбрасывать на диск данные буфера ввода.
    • Читать и писать строки символами Unicode или ANSI в заданном месте экранного буфера.
    • Читать и писать строчки текста и атрибуты цвета фона в заданном месте экранного буфера.
    • Читать и писать прямоугольные блоки символов и данные цвета в заданном месте экранного буфера.
    • Читать одиночные символы Unicode или ANSI, или комбинацию текста и атрибутов фона, которые определяют последовательность ячеек, начинающихся в заданном месте экранного буфера.
    Низкоуровневые консольные режимы работы
    События ввода с клавиатуры записываются в буфере вводимых данных консоли в зависимости от режима ввода данных мышью и окном консоли. Режим обработки ввода данных консоли устанавливает, как система обрабатывает комбинацию клавиш CTRL+C. Чтобы установить или получить состояние режимов ввода данных консоли, приложение может определить дескриптор буфера вводимых данных консоли при вызове функции SetConsoleMode или GetConsoleMode. Ниже перечисленные режимы используются с дескрипторами консольного ввода данных.
     
    __sheva740, Alex81524, Коцит и ещё 1-му нравится это.
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786
    РежимОписание
    ENABLE_MOUSE_INPUTОпределяет, фиксировать ли события с мышью в буфере вводимых данных. По умолчанию, ввод информации от мыши включен, а ввод данных окна заблокирован. Изменение любого из этих режимов воздействует только на ввод данных, который происходит после того, как режим установлен; ждущие обработки события мыши или окна в буфере вводимых данных не сбрасываются. Курсор мыши показывается на экране независимо от режима работы мыши.
    ENABLE_WINDOW_INPUTОпределяет, фиксировать ли события изменения размера буфера в буфере вводимых данных. По умолчанию, ввод информации от мыши включен, а ввод данных окна заблокирован. Изменение любого из этих режимов воздействует только на ввод данных, который происходит после того, как режим установлен; ждущие обработки события мыши или окна в буфере вводимых данных не сбрасываются. Курсор мыши отображается на экране независимо от режима работы мыши.
    ENABLE_PROCESSED_INPUTУправляет обработкой ввода данных для прикладных программ, используя высокоуровневые консольные функции I/O. Однако, если режим обработки ввода данных включен, комбинация клавиш CTRL+C не фиксируется в буфере вводимых данных консоли. Вместо этого, комбинация пересылается соответствующей функции, управляющей обработчиком. Для получения дополнительной информации об управлении обработчиками см. статью Консольное управление обработчиками.
    Низкоуровневые консольные функции ввода данных
    Буфер вводимых данных консоли содержит записи вводимых данных, которые могут включать в себя информацию о событиях клавиатуры, мыши, изменения размера буфера, фокуса и меню. Низкоуровневые функции обеспечивают прямой доступ к буферу вводимых данных, в отличие от высокоуровневых функций, которые фильтруют и обрабатывают информацию буфера вводимых данных, сбрасывая все, кроме ввода информации с клавиатуры.

    Имеется пять низкоуровневых функций для доступа к буферу вводимых данных консоли:
    1. ReadConsoleInput
    2. PeekConsoleInput
    3. GetNumberOfConsoleInputEvents
    4. WriteConsoleInput
    5. FlushConsoleInputBuffer
    Функции ReadConsoleInput, PeekConsoleInput и WriteConsoleInput используют структуру INPUT_RECORD, чтобы читать из или записывать в буфер вводимых данных.

    Ниже описания низкоуровневых консольных функций ввода.
    ФункцияОписание
    ReadConsoleInputЧитает и удаляет записи вводимых данных из буфера ввода. Функция не возвращает значение до тех пор, пока, по меньшей мере, не будет доступна хотя бы одна запись для чтения. Далее все доступные записи передаются в буфер вызывающего процесса до тех пор, пока или не окажется больше записей, которые доступны, или заданное число записей было прочитано. Непрочитанные записи остаются в буфере ввода для следующей операции чтения. Функция сообщает об общем количестве записей, которые были прочитаны. Пример, который использует функцию ReadConsoleInput, смотри в статье Чтение событий буфера вводимых данных.
    PeekConsoleInputЧитает без удаления ждущих обработки записей вводимых данных в буфере ввода. Все доступные записи до заданного числа копируются в буфер вызывающего процесса. Если доступных записей нет, функция немедленно возвращает значение. Функция сообщает об общем количестве записей, которые были прочитаны.
    GetNumberOfConsoleInputEventsВыясняет число непрочитанных записей вводимых данных в буфере ввода.
    WriteConsoleInputПомещает записи вводимых данных в буфер ввода позади любых ждущих обработки записей в буфере. В случае необходимости, буфер ввода растет динамически, чтобы вместить столько записей, сколько записывается. Чтобы использовать эту функцию, определяемый дескриптор буфера ввода должен иметь право доступа GENERIC_READ.
    FlushConsoleInputBufferСбрасывает все непрочитанные события в буфере ввода. Чтобы использовать эту функцию, определяемый дескриптор буфера ввода должен иметь право доступа GENERIC_READ.
    Поток процесса прикладной программы может выполнить операцию "занять", чтобы ждать ввод данных, который будет доступным в буфере ввода. Чтобы инициализировать операцию "занять", определите дескриптор буфера ввода при вызове любой из функций ожидания. Эти функции могут возвратить значение тогда, когда сообщается о состоянии одного или нескольких объектов. Состояние дескриптора консольного ввода становится сигнальным тогда, когда имеются непрочитанные записи в его буфере ввода. Состояние дескриптора сбрасывается в несигнальное тогда, когда буфер ввода становится пустым. Если не имеется доступного ввода данных, вызывающий поток входит в рациональное состояние ожидания, расходуя очень небольшое процессорное время при ожидании условия удовлетворяющего операцию "занять".
    Низкоуровневые консольные функции вывода данных
    Низкоуровневые консольные функции вывода данных обеспечивают прямой доступ к символьным знакоместам экранного буфера. Один набор функций читает из или записывает в последовательные ячейки, начинающиеся в любом месте в экранном буфере консоли. Другой набор функций читает из или записывает в прямоугольные блоки ячеек.

    Нижеследующие функции чтения из или записи в заданное число последовательных символьных знакомест в экранном буфере, начинающихся с определенной ячейки.
    ФункцияОписание
    ReadConsoleOutputCharacterКопирует строку символов Unicode или ANSI из экранного буфера.
    WriteConsoleOutputCharacterЗаписывает строку символов Unicode или ANSI в экранный буфер.
    ReadConsoleOutputAttributeКопирует строку текста и атрибуты цвета фона из экранного буфера дисплея.
    WriteConsoleOutputAttributeЗаписывает строку текста и атрибуты цвет фона в экранном буфере дисплея.
    FillConsoleOutputCharacterЗаписывает одиночный символ Unicode или ANSI в заданном числе последовательных ячеек в экранном буфере.
    FillConsoleOutputAttributeЗаписывает текст и комбинацию атрибутов цвета фона в заданном числе последовательных ячеек в экранном буфере.
    Для всех этих функций, когда подходит последняя ячейка строки, операции чтения или записи автоматически переходят на новую строку обратно в первую ячейку следующей строки. Когда подходит конец последней строки экранного буфера консоли, функции записи сбрасывают все не записанные символы или атрибуты, а функции чтения сообщают о числе символов или атрибутах, действительно записанных.
    Нижеследующие функции читают из или записывают в прямоугольные блоки символьных знакомест, в заданном месте экранного буфера.
    ФункцияОписание
    ReadConsoleOutputКопирует символ и данные о цвете от заданного блока ячеек экранного буфера в данный блок в буфере назначения.
    WriteConsoleOutputЗаписывает символ и данные о цвете в заданном блоке ячеек экранного буфера из данного блока в исходном буфере.
    Эти функции рассматривают экранные буферы и буфер источника или буферы назначения, как двухмерные массивы структур CHAR_INFO (содержащих символы и данные атрибутов цвета для каждой ячейки). Функции устанавливают ширину и высоту, в символьных знакоместах, буфера источника или буфера назначения, а указатель на буфер рассматривается как указатель на начальную ячейку с координатами (0,0) двухмерного массива. Функции используют структуру SMALL_RECT, которая определяет, какой прямоугольник доступен в экранном буфере консоли, и обуславливает координаты левой верхней ячейки в буфере источнике или буфере назначения в месте соответствующего прямоугольника в этом буфере.
    Эти функции автоматически ограничивают определяемый прямоугольник экранного буфера, чтобы вместить его в пределах границ экранного буфера консоли. Например, если прямоугольник устанавливает нижние правые координаты, которые являются (столбец 100, строка 50), а экранный буфер консоли устанавливается шириной только 80 столбцов, координаты отсекаются так, чтобы они были (столбец 79, строка 50). Точно так же этот откорректированный прямоугольник снова отсекается, чтобы вместиться в пределах границ буфера назначения или источника. Координаты экранного буфера фактического прямоугольника, в котором происходит чтение из или запись в является установленным. Пример, который использует эти функции, посмотрите в статье Чтение и запись блоков символов и атрибутов.
    Иллюстрация показывает операцию ReadConsoleOutput, где происходит отсечение по границам, когда блок читается из экранного буфера консоли, и снова, когда блок копируется в буфер назначения. Функция сообщает о фактическом прямоугольнике экранного буфера, который она скопировала.
    Image8.gif
    Кодовые страницы консоли
    Кодовая страница (code page) является отображением 256 символьных кодов для каждого отдельного символа. Разные кодовые страницы включают в себя разные специальные символы, обычно настраиваемые для языка или группы языков.
    Каждая консоль связана с двумя кодовыми страницами: одна для ввода данных и один для вывода информации. Консоль использует свою кодовую страницу ввода, чтобы преобразовать ввод информации с клавиатуры в соответствующее символьное значение. Свою кодовую страницу вывода данных она использует, чтобы преобразовать символьные значения, записанные различными функциями вывода в изображение, отображаемое в консольном окне. Приложение может использовать функции SetConsoleCP и GetConsoleCP, чтобы устанавливать и получать кодовые страницы ввода консоли, а функции SetConsoleOutputCP и GetConsoleOutputCP, чтобы устанавливать и получать свои кодовые страницы вывода данных.
    Идентификаторы кодовых страниц, доступных на локальном компьютере сохраняются в системном реестре под нижеследующим ключом.
    Код (Text):
    1. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage
    Консольное управление обработчиками
    Каждый консольный процесс имеет свой собственный перечень функций управления обработчиками, которые вызываются системой, когда процесс получает сигнал CTRL+C, CTRL+BREAK или CTRL+CLOSE. Вначале, перечень управления обработчиками для каждого процесса содержит только заданную по умолчанию функцию обработчика, которая вызывает функцию ExitProcess. Консольный процесс может добавлять или удалять дополнительные функции HandlerRoutine путем вызова функции SetConsoleCtrlHandler. Эта функция не находится под влиянием перечней управления обработчиками для других процессов. Когда консольный процесс получает какой-либо из управляющих сигналов он вызывает функции обработчика. Основа для вызова ― последняя из зарегистрированных и первая из вызываемых функций, до тех пор, пока один из обработчиков не возвратит значение 1 (TRUE). Если ни один из обработчиков не возвращает значение 1 (TRUE), вызывается заданный по умолчанию обработчик.
    Нижеследующее объявление typedef иллюстрирует формат управляющей функции обработчика.
    Код (C):
    1. typedef BOOL (*PHANDLER_ROUTINE)(DWORD dwCtrlType);
    Параметр dwCtrlType функции идентифицирует, какой управляющий сигнал был принят, а величина возвращаемого значения указывает, был ли сигнал обработан.
    Пример функции управления обработчиком, см. в статье Регистрация функции управления обработчиком.
    • Сигналы CTRL+C и CTRL+BREAK
    • Сигнал CTRL+CLOSE
    • Группы консольных процессов
    Защита буфера и права доступа в консоли
    оригинал на английском
    Модель системы безопасности Windows NT дает Вам возможность управлять доступом к консольным буферам ввода и экранным буферам консоли. Для получения дополнительной информации о системе безопасности, смотри раздел Модель контроля доступа.
    Вы можете определить дескриптор защиты для консольного ввода данных и экранных буферов консоли, когда Вы вызываете функцию CreateFile или CreateConsoleScreenBuffer. Если Вы определяете значение NULL, объект получает заданный по умолчанию дескриптор защиты. ACL, в заданном по умолчанию дескрипторе защиты для консольного буфера, исходят из первичного права или маркера заимствования прав создателя.
    Обработанные возвращенные значения функций CreateFile, CreateConsoleScreenBuffer и GetStdHandle имеют права доступа GENERIC_READ и GENERIC_WRITE.
    Правильные права доступа включают в себя GENERIC_READ и GENERIC_WRITE универсальные права доступа.
    ЗначениеПредназначение
    GENERIC_READЗапрашивает доступ для чтения в экранном буфере консоли, включая процесс, который читает данные из буфера.
    GENERIC_WRITEЗапрашивает доступ для записи в экранный буфер консоли, включая процесс, который записывает данные в буфер
    Использование консоли
    Использование высокоуровневых функций ввода и вывода данных
    Нижеследующий пример использует высокоуровневые консольные функции I/O для консольного ввода-вывода. Для получения дополнительной информации о высокоуровневых консольных функциях I/O, см. статью Высокоуровневый консольный ввод-вывод.
    В примере предполагается, что заданные по умолчанию режимы ввода-вывода (I/O) являются по существу вначале для первого вызова функций ReadFile и WriteFile. Затем для второго вызова ReadFile и WriteFile режим ввода данных изменяется, выключается режим построчного ввода данных и отраженный режим ввода данных. Функция SetConsoleTextAttribute используется для, установки цвета, которым впоследствии письменный текст будет показан на экране. Перед выходом, программа восстанавливает исходный консольный режим ввода данных и атрибуты цвета.
    Функция NewLine примера используется тогда, когда отключается режим построчного ввода данных. Она обрабатывает возвраты каретки, перемещая позицию курсора в первую ячейку следующей строки. Если курсор находится уже в последней строке экранного буфера консоли, содержание экранного буфера консоли прокручивается вверх на одну строку.
    Обратите внимание на то, что MyErrorExit ― групповой символ ― заместитель для определяемой программой функции, которая показывает на экране и обрабатывает аварийные ситуации.
    Код (C):
    1. #include <windows.h>
    2. void NewLine(void);
    3. void ScrollScreenBuffer(HANDLE, INT);
    4. HANDLE hStdout, hStdin;
    5. CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
    6. void main(void)
    7. {
    8.     LPSTR lpszPrompt1 = "Type a line and press Enter, or q to quit: ";
    9.     LPSTR lpszPrompt2 = "Type any key, or q to quit: ";
    10.     CHAR chBuffer[256];
    11.     DWORD cRead, cWritten, fdwMode, fdwOldMode;
    12.     WORD wOldColorAttrs;
    13.     // Получим дескрипторы для STDIN и STDOUT
    14.     hStdin = GetStdHandle(STD_INPUT_HANDLE);
    15.     hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    16.     if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE)
    17.     {
    18.         MessageBox(NULL, "GetStdHandle", "Console Error", MB_OK);
    19.         return;
    20.     }
    21. // Сохраним текущий цвет текста
    22.     if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
    23.     {
    24.         MessageBox(NULL, "GetConsoleScreenBufferInfo", "Console Error", MB_OK);
    25.         return;
    26.     }
    27.     wOldColorAttrs = csbiInfo.wAttributes;
    28. // Установим атрибуты текста которые пишут красный текст по черному фону.
    29.     if (! SetConsoleTextAttribute(hStdout, FOREGROUND_RED|FOREGROUND_INTENSITY))
    30.     {
    31.         MessageBox(NULL, "SetConsoleTextAttribute", "Console Error", MB_OK);
    32.         return;
    33.     }
    34. // Запишем в STDOUT и прочитаем из STDIN, используя режим по умолчанию.
    35. // При вводе данных эхо-режим осуществляется автоматически, а функция ReadFile
    36. // не возвращает значения до тех пор, пока не напечатается каретка возврата.
    37. //
    38. // Режим ввода по умолчанию -- построчный, обрабатываемый и эхо-режим.
    39. // Режим вывода по умолчанию -- обрабатываемый и с автопереносом в конце строки EOL.
    40.     while (1)
    41.     {
    42.         if (! WriteFile(
    43.             hStdout,                    // дескриптор вывода
    44.             lpszPrompt1,                // строка приглашения к вводу
    45.             lstrlen(lpszPrompt1),       // длина строки
    46.             &cWritten,                  // записано байтов
    47.             NULL) )                     // не перекрывающееся
    48.         {
    49.             MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
    50.             return;
    51.         }
    52.         if (! ReadFile(
    53.             hStdin,         // дескриптор ввода
    54.             chBuffer,       // буфер для передачи
    55.             255,            // размер буфера
    56.             &cRead,         // действительно прочитанные байты
    57.             NULL) )         // не перекрывающееся
    58.         break;
    59.         if (chBuffer[0] == 'q')
    60.         break;
    61.     }
    62.     // Выключим построчный режим ввода и эхо-режим
    63.     if (! GetConsoleMode(hStdin, &fdwOldMode))
    64.     {
    65.         MessageBox(NULL, "GetConsoleMode", "Console Error", MB_OK);
    66.         return;
    67.     }
    68.     fdwMode = fdwOldMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
    69.     if (! SetConsoleMode(hStdin, fdwMode))
    70.     {
    71.         MessageBox(NULL, "SetConsoleMode", "Console Error", MB_OK);
    72.         return;
    73.     }
    74.     // Без эхо-режима и построчного ввода, ReadFile возвращает значение,
    75.     // когда доступен какой либо ввод данных. Возврат каретки должен
    76.     // обрабатываться, а WriteFile используется в эхо-режиме для ввода данных
    77.     NewLine();
    78.     while (1)
    79.     {
    80.         if (! WriteFile(
    81.             hStdout,                      // дескриптор вывода
    82.             lpszPrompt2,                  // строка приглашения к вводу
    83.             lstrlen(lpszPrompt2),         // длина строки
    84.             &cWritten,                    // записано байтов
    85.             NULL) )                       // не перекрывающееся
    86.         {
    87.             MessageBox(NULL, "WriteFile", "Console Error", MB_OK);
    88.             return;
    89.         }
    90.         if (! ReadFile(hStdin, chBuffer, 1, &cRead, NULL))
    91.             break;
    92.         if (chBuffer[0] == '\r')
    93.             NewLine();
    94.         else if (! WriteFile(hStdout, chBuffer, cRead,
    95.             &cWritten, NULL))
    96.             break;
    97.         else
    98.             NewLine();
    99.         if (chBuffer[0] == 'q')
    100.             break;
    101.     }
    102. // Восстанавливаем исходный режим консоли
    103.     SetConsoleMode(hStdin, fdwOldMode);
    104. // Восстанавливаем исходный режим текста
    105.     SetConsoleTextAttribute(hStdout, wOldColorAttrs);
    106. }
    107. // Функция NewLine обрабатывает возврат каретки тогда, когда режим обработки
    108. // вводимых данных отключается. Она получает текущую позицию курсора
    109. // и сбрасывает ее до позиции первой ячейки следующей строки
    110. void NewLine(void)
    111. {
    112.     if (! GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
    113.     {
    114.         MessageBox(NULL, "GetConsoleScreenBufferInfo", "Console Error", MB_OK);
    115.         return;
    116.     }
    117.     csbiInfo.dwCursorPosition.X = 0;
    118. // Если это последняя строка в буфере экрана, прокручивает буфер вверх
    119.     if ((csbiInfo.dwSize.Y-1) == csbiInfo.dwCursorPosition.Y)
    120.     {
    121.         ScrollScreenBuffer(hStdout, 1);
    122.     }
    123. // Иначе, продвигает вперед курсор к следующей строке
    124.     else csbiInfo.dwCursorPosition.Y += 1;
    125.     if (! SetConsoleCursorPosition(hStdout,
    126.         csbiInfo.dwCursorPosition))
    127.     {
    128.         MessageBox(NULL, "SetConsoleCursorPosition", "Console Error", MB_OK);
    129.         return;
    130.     }
    131. }
    132. void ScrollScreenBuffer(HANDLE h, INT x)
    133. {
    134.     SMALL_RECT srctScrollRect, srctClipRect;
    135.     CHAR_INFO chiFill;
    136.     COORD coordDest;
    137.     srctScrollRect.Left = 0;
    138.     srctScrollRect.Top = 1;
    139.     srctScrollRect.Right = csbiInfo.dwSize.X - x;
    140.     srctScrollRect.Bottom = csbiInfo.dwSize.Y - x;
    141. // Назначение для прямоугольника прокрутки - одна строка вверх
    142.     coordDest.X = 0;
    143.     coordDest.Y = 0;
    144. // Прямоугольник отсечения по границам тот же самый, что и прокручивающийся прямоугольник.
    145. // Строка назначения оставлена неизменной
    146.     srctClipRect = srctScrollRect;
    147. // Установим символ - заполнитель и атрибуты
    148.     chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY;
    149.     chiFill.Char.AsciiChar = ' ';
    150.     // Прокрутим вверх на одну строку
    151.     ScrollConsoleScreenBuffer(
    152.         h,               // дескриптор экранного буфера
    153.         &srctScrollRect, // прямоугольник прокрутки
    154.         &srctClipRect,   // прямоугольник отсечения
    155.         coordDest,       // верхняя левая ячейка назначения
    156.         &chiFill);       // символ-заполнитель и цвет
    157. }
    Запись символов или цветов в последовательные ячейки
    Символы или атрибуты цвета могут быть записаны в заданные символьные знакоместа в экранном буфере. Нижеследующий пример использует функцию WriteConsoleOutputCharacter, чтобы записать строку символов, начинающихся в верхнем левом угле экранного буфера. Далее пример использует функцию WriteConsoleOutputAttribute, чтобы записать строку атрибутов цвета для первых 51 ячейки той же самой строки. Параметр coord для обеих функций устанавливает символьное знакоместо в экранном буфере консоли, в котором начинается запись. Местоположение в консольном окне, где эти символы или цвета появляются, зависит от прямоугольника текущего окна экранного буфера консоли. За дополнительной информацией о соотношениях между экранным буфером и его окнами, обратитесь к статьям Окно и размер экранного буфера и Прокрутка экранного буфера.
    Обратите внимание на то,что MyErrorExit ― групповой символ ― заместитель для определяемой программой функции, которая показывает на экране и обрабатывает аварийные ситуации.
    Код (C):
    1. HANDLE hOutput;
    2.     LPTSTR lpszString = "Character String";
    3.     DWORD cWritten;
    4.     BOOL fSuccess;
    5.     COORD coord;
    6.     WORD wColors[3], wColor;
    7.     CHAR chFillChar;
    8. // Запишем строку символов в буфер экрана
    9.     coord.X = 0;            // начало на первую ячейку
    10.     coord.Y = 0;            // первой строки
    11.     fSuccess = WriteConsoleOutputCharacter(
    12.         hOutput,              // дескриптор экранного буфера
    13.         lpszString,           // указатель на строку ― источник
    14.         lstrlen(lpszString),  // длина строки
    15.         coord,                // первая ячейка для записи
    16.         &cWritten);           // действительное число записей
    17.     if (! fSuccess)
    18.         MyErrorExit("WriteConsoleOutputCharacter");
    19. // Запишем строку цветов в экранный буфер
    20.     wColors[0] = BACKGROUND_RED;
    21.     wColors[1] = BACKGROUND_RED |     // белый фон
    22.                  BACKGROUND_GREEN |
    23.                  BACKGROUND_BLUE;
    24.     wColors[2] = BACKGROUND_BLUE;
    25.     for (;fSuccess && coord.X < 50; coord.X += 3)
    26.     {
    27.         fSuccess = WriteConsoleOutputAttribute(
    28.             hOutput,          // дескриптор экранного буфера
    29.             wColors,          // указатель на строку ― источник
    30.             3,                // длина строки
    31.             coord,            // первая ячейка для записи
    32.             &cWritten);       // действительное число записей
    33.     }
    34.     if (! fSuccess)
    35.         MyErrorExit("WriteConsoleOutputAttribute");
    Те же самые символы или атрибуты цвета можно записать в заданное число последовательных ячеек экранного буфера, начинающихся в заданном местоположении. Нижеследующий пример использует функцию FillConsoleOutputCharacter, чтобы очистить область экранного буфера 80 на 50 символов, а затем он использует функцию FillConsoleOutputAttribute, чтобы установить атрибуты цвета в тех же самых ячейках.
    Код (C):
    1. // Заполним область экранного буфера 80-на-50 символов пробелами
    2.     coord.X = 0;            // начнем с первой ячейки
    3.     coord.Y = 0;            //   первой строки
    4.     chFillChar = ' ';
    5.     fSuccess = FillConsoleOutputCharacter(
    6.         hStdout,          // дескриптор экранного буфера
    7.         chFillChar,       // заполнение пробелами
    8.         80*50,            // число ячеек для заполнения
    9.         coord,            // первая ячейка для записи
    10.         &cWritten);       // фактическое число записей
    11.     if (! fSuccess)
    12.         MyErrorExit("FillConsoleOutputCharacter");
    13. // Установим в области экранного буфера 80-на-50 символов цвета для белого текста на красном
    14.     wColor = BACKGROUND_RED |
    15.              FOREGROUND_RED |
    16.              FOREGROUND_GREEN |
    17.              FOREGROUND_BLUE;
    18.     fSuccess = FillConsoleOutputAttribute(
    19.         hStdout,          // дескриптор экранного буфера
    20.         wColor,           // цвет для заполнения
    21.         80*50,            // число заполняемых ячеек
    22.         coord,            // первая ячейка для записи
    23.         &cWritten);       // фактическое число записей
    24.     if (! fSuccess)
    25.         MyErrorExit("FillConsoleOutputAttribute");
    Чтение и запись блоков символов и атрибутов
    оригинал на английском
    Функция ReadConsoleOutput копирует прямоугольный блок символьных и цветных атрибутов данных из экранного буфера консоли в буфер назначения. Функция рассматривает буфер назначения как двухмерный массив структур CHAR_INFO. Точно так же функция WriteConsoleOutput копирует прямоугольный блок символьных и цветных атрибутов данных из исходного буфера в экранный буфер консоли. Для получения дополнительной информации о чтении или записи в прямоугольных блоках ячеек экранного буфера, смотри раздел Методы ввода и вывода данных.
    Нижеследующий пример использует функцию CreateConsoleScreenBuffer, чтобы создать новый экранный буфер. После того, как функция SetConsoleActiveScreenBuffer сделает этот экранный буфер активным, во временный буфер скопируется блок символов и атрибутов цвета верхних двух строк SDTOUT экранного буфера. Данные далее копируются из временного буфера в новый активный экранный буфер. Когда приложение завершает работу, используя новый экранный буфер, оно вызывает SetConsoleActiveScreenBuffer, чтобы восстановить исходный STDOUT экранный буфер.
    Код (C):
    1. #include <windows.h>
    2.  
    3. VOID main(void)
    4. {
    5.     HANDLE hStdout, hNewScreenBuffer;
    6.     SMALL_RECT srctReadRect;
    7.     SMALL_RECT srctWriteRect;
    8.     CHAR_INFO chiBuffer[160];       // [2][80];
    9.     COORD coordBufSize;
    10.     COORD coordBufCoord;
    11.     BOOL fSuccess;
    12.  
    13.     // Получим дескриптор STDOUT экранного буфера из которого будем копировать и создадим
    14.     // новый экранный буфер, в который будем копировать.
    15.  
    16.     hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    17.     hNewScreenBuffer = CreateConsoleScreenBuffer(
    18.        GENERIC_READ |               // доступ к чтению/записи
    19.        GENERIC_WRITE,
    20.        0,                           // совместно не используется
    21.        NULL,                        // атрибутов защиты нет
    22.        CONSOLE_TEXTMODE_BUFFER,       // должен быть TEXTMODE
    23.        NULL);                       // зарезервирован, должен быть NULL
    24.     if (hStdout == INVALID_HANDLE_VALUE ||
    25.             hNewScreenBuffer == INVALID_HANDLE_VALUE)
    26.     {
    27.         MyErrorExit("CreateConsoleScreenBuffer");
    28.     }
    29.  
    30.     // Сделаем новый экранный буфер активным экранным буфером.
    31.  
    32.     if (! SetConsoleActiveScreenBuffer(hNewScreenBuffer) )
    33.         MyErrorExit("SetConsoleActiveScreenBuffer");
    34.  
    35.     // Установим прямоугольник источника.
    36.  
    37.     srctReadRect.Top = 0;    // верхний левый: строчка 0, колонка 0
    38.     srctReadRect.Left = 0;
    39.     srctReadRect.Bottom = 1; // нижний правый: строчка 1, колонка 79
    40.     srctReadRect.Right = 79;
    41.  
    42.     // Размер временного буфера равен 2 строчки x 80 колонок.
    43.  
    44.     coordBufSize.Y = 2;
    45.     coordBufSize.X = 80;
    46.  
    47.     // Верхняя левая ячейка назначения временного буфера равна строка 0, колонка 0.
    48.  
    49.     coordBufCoord.X = 0;
    50.     coordBufCoord.Y = 0;
    51.  
    52.     // Скопируем блок из экранного буфера во временный буфер.
    53.  
    54.     fSuccess = ReadConsoleOutput(
    55.        hStdout,         // экранный буфер, из которого читаем
    56.        chiBuffer,       // буфер, в который копируем
    57.        coordBufSize,    // размер колонки/строки chiBuffer
    58.        coordBufCoord,   // верхняя левая ячейка назначения в chiBuffer
    59.        &srctReadRect);  // экранного буфер прямоугольника, из которого читаем
    60.  
    61.     if (! fSuccess)
    62.         MyErrorExit("ReadConsoleOutput");
    63.     // Установим прямоугольник назначения.
    64.     srctWriteRect.Top = 10;    // верхний левый: строка 10, колонка 0
    65.     srctWriteRect.Left = 0;
    66.     srctWriteRect.Bottom = 11; // нижний правый: строка 11, колонка 79
    67.     srctWriteRect.Right = 79;
    68.     // Копируем из временного буфера в новый экранный буфер.
    69.     fSuccess = WriteConsoleOutput(
    70.         hNewScreenBuffer,   // экранный буфер, в который будем записывать
    71.         chiBuffer,          // буфер, из которого копируем
    72.         coordBufSize,       // размер колонки/строки chiBuffer
    73.         coordBufCoord,      // верхняя левая ячейка источника в chiBuffer
    74.         &srctWriteRect);    // прямоугольник назначения экранного буфера
    75.     if (! fSuccess)
    76.         MyErrorExit("WriteConsoleOutput");
    77.     Sleep(10000);
    78.     // Восстановление исходного активного экранного буфера.
    79.     if (! SetConsoleActiveScreenBuffer(hStdout))
    80.         MyErrorExit("SetConsoleActiveScreenBuffer");
    81. }
     
    Последнее редактирование: 28 мар 2019
    __sheva740, Alex81524 и Ronin_ нравится это.
  7. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.786

    Чтение событий буфера вводимых данных
    оригинал на английском
    Функция ReadConsoleInput может быть использована для непосредственного обращения к буферу ввода консоли. Когда консоль создается, включается ввод информации от мыши, а ввод данных окна отключается. Чтобы гарантировать, что процесс получает все события ввода, этот пример использует функцию SetConsoleMode, чтобы включить ввод информации от окна и мыши. Затем он входит в цикл, который читает и обрабатывает консольные события ввода.
    Код (C):
    1. VOID MouseEventProc(MOUSE_EVENT_RECORD);
    2. VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);
    3. VOID KeyEventProc(KEY_EVENT_RECORD);
    4. VOID GetInputEvents(VOID);
    5. DWORD main(VOID)
    6. {
    7.     HANDLE hStdin;
    8.     DWORD cNumRead, fdwMode, fdwSaveOldMode, i;
    9.     INPUT_RECORD irInBuf[128];
    10.     // Получим стандартный дескриптор ввода.
    11.     hStdin = GetStdHandle(STD_INPUT_HANDLE);
    12.     if (hStdin == INVALID_HANDLE_VALUE)
    13.         MyErrorExit("GetStdHandle");
    14.     // Сохраним текущий режим ввода для будущего восстановления при
    15.     // выходе из программы.
    16.     if (! GetConsoleMode(hStdin, &fdwSaveOldMode) )
    17.         MyErrorExit("GetConsoleMode");
    18.     // Включим события ввода от мыши и окна.
    19.     fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
    20.     if (! SetConsoleMode(hStdin, fdwMode) )
    21.         MyErrorExit("SetConsoleMode");
    22.     // Цикл чтения и обработки событий ввода.
    23.     while (1)
    24.     {
    25.     // Ожидание событий.
    26.         if (! ReadConsoleInput(
    27.                 hStdin,      // дескриптор буфера ввода
    28.                 irInBuf,     // буфер, в котором читаем
    29.                 128,         // размер буфера чтения
    30.                 &cNumRead) ) // число прочитанных записей
    31.             MyErrorExit("ReadConsoleInput");
    32.    // Направляем события соответствующим обработчикам.
    33.         for (i = 0; i < cNumRead; i++)
    34.         {
    35.             switch(irInBuf[i].EventType)
    36.             {
    37.                 case KEY_EVENT: // ввод с клавиатуры
    38.                     KeyEventProc(irInBuf[i].Event.KeyEvent);
    39.                     break;
    40.                 case MOUSE_EVENT: // ввод от мыши
    41.                     MouseEventProc(irInBuf[i].Event.MouseEvent);
    42.                     break;
    43.                 case WINDOW_BUFFER_SIZE_EVENT: // изменение размера
    44.                                                // экранного буфера
    45.                     ResizeEventProc(
    46.                         irInBuf[i].Event.WindowBufferSizeEvent);
    47.                     break;
    48.                 case FOCUS_EVENT:  // игнорирование событий фокуса
    49.                 case MENU_EVENT:   // игнорирование событий меню
    50.                     break;
    51.                 default:
    52.                     MyErrorExit("unknown event type");
    53.                     break;
    54.             }
    55.         }
    56.     }
    57.     return 0;
    58. }
    Очистка экрана
    оригинал на английском
    Имеется два способа очистки экрана в консольной программе. Первый способ состоит в том, чтобы использовать системную функцию языка C во время выполнения как ниже указано:
    Код (C):
    1. #include <stdlib.h>
    2. void main()
    3. {
    4.    system("cls");
    5. }
    Системная функция вызывает команду cls, предусмотренную интерпретатором команд, чтобы очистить экран.
    Второй ― состоит в том, чтобы записать, что функция программно очищает экран, используя функции FillConsoleOutputCharacter и FillConsoleOutputAttribute . Ниже код, который демонстрирует эту методику.
    Код (C):
    1. void cls( HANDLE hConsole )
    2. {
    3. COORD coordScreen = { 0, 0 }; // исходная позиция для курсора
    4.    DWORD cCharsWritten;
    5.    CONSOLE_SCREEN_BUFFER_INFO csbi;
    6.    DWORD dwConSize;
    7. // Получим число символьных ячеек в текущем буфере.
    8.    if( !GetConsoleScreenBufferInfo( hConsole, &csbi ))
    9.       return;
    10.    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
    11. // Заполним полностью экран пробелами.
    12.    if( !FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',
    13.       dwConSize, coordScreen, &cCharsWritten ))
    14.       return;