Невозможность чтения состояния клавиатуры в видеореж

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Невозможность чтения состояния клавиатуры в видеореж

Сообщение Сквозняк » 13.07.2006 20:18:34

Использовал библиотеку SDL4 FreePascal в линуксе, создал такой как мне нужен видеорежим - 720х400. Но возникла непреодолимая проблема: никак не прочесть средствами паскаля состояние клавиатуры. Модули CRT и Keyboard не дают нужного эффекта. Или клава не читается или читается в текстовом окне, хотя активно графическое. И в полноэкранном и в графическом окне эффект одинаков. Только в полноэкранном не дейсвуют никакие горячие клавиши системы. Возникла идея использовать внешнюю библиотеку типа DLL, но есть сомнения что под линуксом компилятор с этим согласится. Мне сказали, на С хорошо действует Getkeystate. Может кто-то может написать на С совместимую с FPC под линуксом библиотеку передающую на паскаль данные аналогичные получаемым с помощью keypressed и readkey? Желательно сразу возвращать переменные типа Word.
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Romtek » 17.07.2006 11:59:17

Мне кажется, что есть другие пути для приложений в Линукс.
Как там вообще происходит обработка сообщений?
Аватара пользователя
Romtek
постоялец
 
Сообщения: 190
Зарегистрирован: 22.05.2005 12:29:35
Откуда: Рамат Ган

Сообщение Сквозняк » 17.07.2006 14:02:01

Это надо сишников спрашивать, на нём пингвин писан :( На стандартные средства паскаля мало надежды - разработчики похоже забили на этот вопрос. Если бы я в своё время изучил асму, можно было скомпилировать сишный код покороче и вырезать из него ассемблерную вставку. Есть и третий путь - разобраться с клавиатурным модулем библиотеки SDL4Freepascal-1.2.0.0 Теоретически, его можно заставить работать и под виндовсом, но практически для этого нужно править исходники чтобы избавиться от ошибок компилятора. Размер кода в них небольшой, если кто-то поможет с ним разобраться, буду очень благодарен http://sdl4fp.sourceforge.net
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение @lex » 20.07.2006 14:28:28

А может попробовать использовать что-то вроде DirectInput? В OpenGL наверное что-то подобное должно быть...
@lex
постоялец
 
Сообщения: 180
Зарегистрирован: 19.06.2006 13:16:29
Откуда: Невинномысск

Сообщение Сквозняк » 29.09.2006 18:41:21

Максимум чего удалось добиться - чтения портов, но файл port можно открыть только под рутом. Очень криво. Если и в новом компиляторе те же недоделки, тогда пользоваться ФПЦ нереал. Чтобы использовать DirectInput нужно добавлять в прогу исходники OpenGL?
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Cheb » 02.10.2006 12:53:11

Хммм... :? А сообщения окну от X сервера на что?.. Я, в своё время, реализовал окошко, которое отлично клавиатуру ловило - спасибо туториалу на http://freepascal.ru/article//book/xwin/
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Сообщение Mirage » 03.10.2006 20:17:53

Неужели в Линуксе нет аналога GetKeyboardState()?
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Сообщение Сквозняк » 15.10.2006 15:07:01

В СИ может и есть, а в ФПЦ...
Юзил я тот учебник, на соурцах нашёл, через поисковик. Проблема в том что рассматривает он лишь частный способ использования клавиатуры. Для получения к ней доступа, окно нужно создавать определённым образом и никак иначе. Часть параметров используемых для видеорежима в OpenGL для однопользовательского графического приложения вообще не нужны. Следовательно нужные функции из примера к своей программе не приклеишь - просто отсутствуют параметры окна, которые нужно вставить в функцию.
Код: Выделить всё
Program kvadrat;

Uses SDL, SDL_Video, crt, keyboard;

Const
   width = 720;
   height =400;
   colordepth = 32 ;
Type
   Pixel = LONGWORD; { Must have colordepth bits }

Type
    TpixelBuf = Array [0..height-1, 0..width-1] of Pixel ;

Var
   screen: PSDL_Surface ;
   Q3, W3, E3: BYTE;
   Q8, W8: WORD;

BEGIN

ClrScr;
   SDL_Init (SDL_INIT_VIDEO) ;
     screen := SDL_SetVideoMode (width, height, colordepth, ( SDL_FULLSCREEN + SDL_ANYFORMAT  + SDL_SWSURFACE)) ;

   if screen = nil then
   Begin
       Writeln ('Couldn''t initialize video mode at ', width, 'x',
                height, 'x', colordepth, 'bpp') ;
       Halt(1)
   End ;

randomize;

FOR E3:=0 TO 255 DO BEGIN
FOR W3:=0 TO 21 DO
FOR Q3:=0 TO 255 DO BEGIN
Tpixelbuf(screen^.pixels^)[RANDOM(height),RANDOM(width)] :=
SDL_MapRGB(screen^.format,RANDOM(256),RANDOM(256),RANDOM(256));
                    END;

SDL_UpdateRect (screen, 0, 0, 0, 0) ;
DELAY(80);

FOR Q8:=0 TO HEIGHT-1 DO FOR W8:=0 TO WIDTH-1 DO
Tpixelbuf(screen^.pixels^)[Q8,W8]:=0;

                   END;
delay(3000);

{InitKeyboard;
GetKeyEvent;
DoneKeyboard;}

SDL_FreeSurface (screen);
SDL_Quit;

END.

SDL импортирует функции из стандартных модулей, графика как раз та что надо, работает просто. Клавиатурные модули тоже есть, только ничего с них выжать не удаётся. Теоретически, если принудительно перенести фокус ввода на нужное окно, можно обойтись и средствами модуля CRT, только вот как это сделать.
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Alexander » 15.10.2006 16:25:30

А нет ли небольшого работающего примера для сдл на С ?
Ведь главное принцип. Может это вообще задача самого сдл (через
его функции) ? Или ещё как нибудь. Вряд ли Паскаль менее функционален
чем Си. Только понять что делать.

И правильно ли я понял, что сдл может
работать и без иксов (с фреймбуфером что ли) ?
Тогда уже скорее всего клавиатура средствами сдл, а не языка.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 793
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Сообщение Сквозняк » 15.10.2006 20:46:31

Если исходники скомпилируются на СИ, тогда есть ) Пытался скомпилить на паскале под вин, не пошло. Каким способом сдл строит видеорежим, я не понял, но там необходим минимум параметров, массив переменных для хранения пикселей, и окно нельзя ни увеличить ни закрыть мышкой. В исходниках нет ассемблерных вставок. Всё импортируется из паскаля, добавлено несколько типов и так, по мелочи. Почти весь текст - комментарии на английском. К сожалению, моего знания языка, даже усиленного промтом ) не хватило для полного понимания модулей sdl_events.pp и sdl_keyboard.pp Исходники лежат на http://sdl4fp.sourceforge.net/ весят 44 кило.
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк » 29.10.2006 04:30:03

Вот что обнаружилось в кэше гугля под сишную версию. С оператором switch не совсем ясно, как выполняемые им действия записать на паскале?
Код: Выделить всё
Linux Game Programming for PC & Embedded Systems using SDL
Presented by
Fore June
Author of Windows Fan, Linux Fan
Games and SDL
SDL Installation
SDL API
SDL Events       SDL Graphics


SDL Events


Programs that operate in a GUI environment are event-driven. An event is an action that takes place within a program when something happens. Part of writing a GUI application is to create event listeners. An event listener is an object or a loop that triggers certain action when a specific event occurs. In the SDL programming environment, an event is produced whenever you move or click the mouse, press a key, or resize the SDL video window. Event handling allows your application to receive input from the user. SDL stores unprocessed events in an internal event queue which allows SDL to collect as many events as possible each time it updates an event. Using functions like SDL_PollEvent, SDL_PeepEvents and SDL_WaitEvent you can observe and handle waiting input events.

There are four main categories of events: keyboard, mouse, window, and system-dependent events. Window events handle gaining and losing focus, as well as exit requests. System-dependent events process raw messages from the windowing system that SDL otherwise would ignore. Information of an event is stored in the structure type SDL_Event. The event queue itself is composed of a series of SDL_Event unions, one for each waiting event. SDL_Event unions are read from the queue with the SDL_PollEvent function and it is then up to the application to process the information stored with them.
Synopsis          SDL_Event -- General event structure, which is a union of all possible event types for receiving events from SDL.
Definition          typedef union{
  Uint8 type;
  SDL_ActiveEvent active;
  SDL_KeyboardEvent key;
  SDL_MouseMotionEvent motion;
  SDL_MouseButtonEvent button;
  SDL_JoyAxisEvent jaxis;
  SDL_JoyBallEvent jball;
  SDL_JoyHatEvent jhat;
  SDL_JoyButtonEvent jbutton;
  SDL_ResizeEvent resize;
  SDL_ExposeEvent expose;
  SDL_QuitEvent quit;
  SDL_UserEvent user;
  SDL_SysWMEvent syswm;
} SDL_Event;
   
Description          For reading and placing events on the event queue.
 


The SDL event subsystem is intertwined with the video subsystem. We basically cannot separate the use of them. Therefore, they are both initialized with SDL_INIT_VIDEO parameter to SDL_Init().

Event Processing To process an event, you need to read the SDL_Event unions from the event queue using the SDL_PollEvent() or SDL_WaitEvent() function. You can also add events onto the event queue using SDL_PushEvent(), which returns 0 on success or -1 on failure. The following are some typical techniques that people use to handle events.
Waiting for events

You can wait for events to occur using the SDL_WaitEvent() function, which waits indefinitely and returns only if an event or an error has occurred.
Synopsis          #include "SDL.h"
int SDL_WaitEvent(SDL_Event *event);
Description          Waits indefinitely for the next available event.
 
Returns          0 if there was an error while waiting for events, 1 otherwise. Information of the event detected will be stored in the structure pointed by event and the event is removed from the event queue.
 
   
     Tip:
SDL has international keyboard support, translating key events and placing the UNICODE equivalents into event.key.keysym.unicode. Since this has some processing overhead involved, it must be enabled using SDL_EnableUNICODE().

Example:
/*
waitevent.cpp

compile by: g++ -o waitevent waitevent.cpp -I/usr/include -L/usr/local/lib -lSDL
executed by: ./waitevent
*/

#include <SDL/SDL.h>
#include <stdlib.h>

bool wait_for_events ()
{
  SDL_Event event;
  int status;
  char *key;
  bool quit = false;

  printf("waiting for events, press 'q' or 'ESC' to quit\n");
  while ( !quit ) {            
    status = SDL_WaitEvent(&event);   //wait indefinitely for an event to occur
               //event will be removed from event queue
    if ( !status ) {         //Error has occurred while waiting
   printf("SDL_WaitEvent error: %s\n", SDL_GetError());
   return false;
    }
    switch (event.type) {      //check the event type
      case SDL_KEYDOWN:         //if a key has been pressed
   key = SDL_GetKeyName(event.key.keysym.sym);
       printf("The %s key was pressed!\n", key );
   if ( event.key.keysym.sym == SDLK_ESCAPE )   //quit if 'ESC' pressed
     quit = true;
       else if ( key[0] == 'q'  )   //quit if 'q'  pressed
     quit = true;         //same as "if ( event.key.keysym.sym == SDLK_q )"
       break;
       case SDL_MOUSEMOTION:             //mouse moved
        printf("Mouse motion x:%d, y:%d\n", event.motion.x, event.motion.y );
        break;
      case SDL_MOUSEBUTTONUP:           //mouse button pressed
        printf("Mouse pressed x:%d, y:%d\n", event.button.x, event.button.y );
        break;
     case SDL_QUIT:         //'x' of Window clicked
     exit ( 1 );
       break;
    }
  } //while
  return true;
}

int main()
{   
  SDL_Surface *screen;

  //initialize the event subsystem along with video system
  if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
        fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
        exit(1);
  }
  //ensure SDL_Quit is called when the program exits
  atexit(SDL_Quit);
   
  //set video mode of 640 x 480 with 16-bit pixels
  screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
  if ( screen == NULL ) {
        fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
        exit(1);
  }
 
  wait_for_events();
 
  return 0;
}


Keyboard and Mouse Events

In the above example, it prints out the key you have pressed and exits if you have pressed 'ESC' or 'q'. The function SDL_GetKeyName() is used to get the name of the key being pressed. SDL assigns a virtual keysym to each key on the keyboard. A preprocessor symbol is used to map to each virtual keysym. For example, Escape key corresponds to the symbol SDLK_ESCAPE; key 'q' corresponds to SDLK_q. Virtual keysyms are of type SDLKey. Virtual keysyms treat the special keys like Ctrl, Alt, and Shift as ordinary keys. You can find their keysyms in the header file SDL_keysym.h. However, those keys are also considered as modifier keys which are represented by ORed bit flags. For example, the flag for a combination of right Ctrl and Alt keys would be ( KMOD_RCTRL | KMOD_RALT ).

A mouse event is generated when you move the move or click on one of its buttons. A mouse reports changes in its position with respect to a fixed unit of measure, called a mickey. For example, a movement 1 inch right and two inches down may correspond to 200 horizontal mouse units and -400 vertical mouse units.

The following are some often used events generated by a mouse or a keyboard. SDL_QUIT - user clicked little x button in the corner of a window mode.
SDL_KEYDOWN - key pressed, stored in the key member of SDL_Event
SDL_KEYUP - key released, stored in the key member of SDL_Event
SDL_MOUSEDOWN - mouse button pressed, stored in button member of SDL_Event
SDL_MOUSEUP - mouse button released, stored in button member of SDL_Event
SDL_MOUSEMOTION - mouse moved, stored in motion member of SDL_Event


For keyboard events, the data are stored in the key event of SDL_Event. A few of the more useful SDLKey's include SDLK_RETURN
SDLK_ESCAPE
SDLK_SPACE
SDLK_0
SDLK_1
...
SDLK_9
SDLK_a
SDLK_b
SDLK_c
...
SDLK_z


The button structure for Mouse up and down is a SDL_MouseButtonEvent structure and has 5 members. The x and y members store the coordinates for the cursor, with ( 0, 0 ) at the upper left corner and the screen is positive. The button member can be SDL_BUTTON_LEFT, SDL_BUTTON_MIDDLE, or SDL_BUTTON_RIGHT. The type member stores SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP and state stores SDL_PRESSED and SDL_RELEASED.

The motion member is an SDL_MouseMotionEvent structure. This has the x and y coordinates of the mouse, and xrel and yrel as relative motion in the x and y direction. along with type (always SDL_MOUSEMOTION) Synopsis          SDL_MouseButtonEvent -- Mouse button event structure
Definition          typedef struct{
  Uint8 type;      //SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP
  Uint8 button;      //Mouse button index (SDL_BUTTON_LEFT, SDL_BUTTON_MIDDLE,
         //SDL_BUTTON_RIGHT, SDL_BUTTON_WHEELUP, SDL_BUTTON_WHEELDOWN)
  Uint8 state;      //SDL_PRESSED or SDL_RELEASED
  Uint16 x, y;      //The X/Y coordinates of the mouse at press/release time
} SDL_MouseButtonEvent;
Description          A member of the SDL_Event union and is used when an event of type SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP is reported.


The following are some useful related functions. SDL_WarpMouse(Uint26 x, Uint16 y)    warp the mouse to the given location and generate a SDL_MOUSEMOTION event.
Uint8 *SDL_GetKeyState(int *numkeys)    if numkeys is NULL, then all the keys will be returned, otherwise just the first numkeys. The return value is a pointer to an array of keystates, where the SDLKey values are the indexes (SDLK_RETURN, SDLK_p, ...)
For example,
Uint8 *keystate = SDL_GetKeyState(NULL);
if (keystate[SDLK_RETURN]) { printf("Return Key Pressed"); }
SDLMod SDL_GetModState()    returns the current state of modifier keys (shift, alt, etc.) where SDLMod is an enum, some values including, KMOD_NONE, KMOD_LSHIFT, KMOD_RSHIFT, KMOD_LALT, KMOD_RALT, KMOD_CAPS. A complete list can be found from SDL_GetModState man page.
char *SDL_GetKeyName ( SDLKey key )    returns a char pointer to the key.
int SDL_EnableKeyRepeat ( int delay, int interval )    sets the key repeat rate. If idelay is 0, repeating is disabled. Two good values for this function are SDL_DEFAULT_REPEAT_DELAY and SDL_DEFAULT_REPEAT_INTERVAL. This returns 0 on success and -1 on failure.


As we mentioned in an earlier chapter, SDL does not support USB devices. If you need to a USB keyboard or mouse for your embedded system, minor modifications of the SDL library are needed; we shall discuss the required modifications in a later chapter.
Polling for events

You can poll for events using the SDL_PollEvent() function.        Tip:
You can peek at events in the event queue without removing them by passing the SDL_PEEKEVENT action to SDL_PeepEvents().

Example:
{
  SDL_Event event;

  while ( SDL_PollEvent(&event) ) {
    switch (event.type) {
      case SDL_MOUSEMOTION:
   printf("Mouse moved by %d,%d to (%d,%d)\n",
          event.motion.xrel, event.motion.yrel,
          event.motion.x, event.motion.y);
   break;
      case SDL_MOUSEBUTTONDOWN:
   printf("Mouse button %d pressed at (%d,%d)\n",
          event.button.button, event.button.x, event.button.y);
   break;
      case SDL_QUIT:
   exit(0);
    }
  }
}

Polling event state

In addition to handling events directly, each type of event has a function which allows you to check the application event state. If you use this exclusively, you should ignore all events with the SDL_EventState() function, and call SDL_PumpEvents() periodically to update the application event state.       
   Tip:
You can hide or show the system mouse cursor using SDL_ShowCursor().


Example:
{
  SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
}

void CheckMouseHover(void)
{
  int mouse_x, mouse_y;

  SDL_PumpEvents();

  SDL_GetMouseState(&mouse_x, &mouse_y);
  if ( (mouse_x < 32) && (mouse_y < 32) ) {
    printf("Mouse in upper left hand corner!\n");
  }
}
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк » 29.10.2006 04:34:23

А вот перспективный исходник на пасе, выводит на экран БМП. В оконном режиме окно можно закрыть кликнув по крестику в правом верхнем углу окна. В "квадрате" этого не было.
Код: Выделить всё
Here's a demo I wrote that does something rather similar. It was a test base for my game I'm developing. The ol classic space invaders. (Just starting game development, never done much before, except in asm).

--Begin Code---
program demo;

uses
SDL, SDL_Video, SDL_Events;

const
width = 640;
height = 480;
colordepth = 16;

var
screen: PSDL_Surface;
image: PSDL_Surface;
event: PSDL_Event;
done: Boolean;
filename: String;
begin
SDL_Init(SDL_INIT_VIDEO);
event := new(PSDL_Event);
screen := SDL_SetVideoMode(width, height, colordepth, SDL_SWSURFACE);
if screen = nil then
begin
writeLn ('Couldn''t initialize video mode at ', width, 'x', height, 'x', colordepth, 'bpp');
halt(1);
end;
filename := 'splash.bmp';
image := SDL_loadBMP(@filename[1]);
if (image = nil) then
begin
writeLn('Couldn''t load ' + filename);
halt(1);
end;
if (SDL_BlitSurface(image, nil, screen, nil) < 0) then
begin
writeLn('BlitSurface error:' {+ SDL_GetError()});
end;
SDL_updateRect(screen, 0, 0, image^.w, image^.h);
SDL_freeSurface(image);
done := FALSE;
while (done = FALSE) do
begin
if (SDL_PollEvent(event) > 0) then
begin
if (event^.eventtype = SDL_EventQuit) then
begin
done := TRUE;
end;
end;
end;
SDL_freeSurface(screen);
SDL_Quit ;
end.

--End Code--

cheers
James
-- James Mills, Декабрь 31, 2002 08:07
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32

Сообщение Сквозняк » 29.10.2006 14:11:19

Заработало
Код: Выделить всё

program demo;

uses
SDL, SDL_Video, SDL_Events;

const
width = 720;
height = 400;
colordepth = 32;

var
screen: PSDL_Surface;
image: PSDL_Surface;
event: PSDL_Event;
done: Boolean;
filename: String;

label 1;


begin

SDL_Init(SDL_INIT_VIDEO);
event := new(PSDL_Event);
screen := SDL_SetVideoMode(width, height, colordepth, (SDL_FULLSCREEN + SDL_SWSURFACE));
if screen = nil then
begin
writeLn ('Couldn''t initialize video mode at ', width, 'x', height, 'x', colordepth, 'bpp');
halt(1);
end;
filename := '0.bmp';
image := SDL_loadBMP(@filename[1]);
if (image = nil) then
begin
writeLn('Couldn''t load ' + filename);
halt(1);
end;
if (SDL_BlitSurface(image, nil, screen, nil) < 0) then
begin
writeLn('BlitSurface error:' {+ SDL_GetError()});
end;
SDL_updateRect(screen, 0, 0, image^.w, image^.h);
SDL_freeSurface(image);
done := FALSE;
while (done = FALSE) do
begin
if (SDL_PollEvent(event) > 0) then
begin
CASE event^.eventtype OF
SDL_KEYDOWN, SDL_MOUSEBUTTONDOWN :done := TRUE;
end;
end;
end;


SDL_freeSurface(screen);
SDL_Quit ;
end.
Сквозняк
энтузиаст
 
Сообщения: 1124
Зарегистрирован: 29.06.2006 22:08:32


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

Рейтинг@Mail.ru