Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

есть ли разница между onKeyUp и onKeyPress? [D7, WinXP]


Страницы:   1 2

Creative ©   (2006-11-27 17:06:00) 

Пытаюсь описать собственный класс окна. Все работает, но удивляет одна вещь. У меня обрабабывается событие onKeyPress, пишу аналогичную обработку событие onKeyUp. Результат - тот же самый. Все событие, которе должны происходить, происходят, пока клавише нажата. Разве они не должны происходить только при ее отпускании? Почему так происходит?


type TWndCore = class
    private
     ......//все нужные поля

    OnKeyPress     : procedure;
    OnKeyUp        : procedure;
    constructor CreateWnd(Width, Height : integer; FullScreen, VSync : boolean; ColorDepth, Freq : integer);
    destructor Destroy(); override;
    function  MessageOperations(hInstance : HINST; hPrevInstance : HINST; lpCmdLine : PChar; nCmdShow : Integer) : Integer; stdcall;

===============

function TWndCore.MessageOperations(hInstance, hPrevInstance: HINST;
 lpCmdLine: PChar; nCmdShow: Integer): Integer;
var Msg : TMsg;
begin
.........

if @OnKeyPress <> nil then OnKeyPress;
if @OnKeyUp <> nil then OnKeyUp;
end;


Основной код



procedure KeyUp;
begin
if Keys[VK_UP] then DoSmth1;
end;

procedure KeyPress;
begin
if Keys[VK_UP] then DoSmth2;
end;

begin
Wnd := TWndCore.CreateWnd(640, 480, false, true, 32, 60);
Wnd.OnKeyPress := KeyPress;
Wnd.OnKeyUp := KeyUp;

Wnd.MessageOperations(hinstance, hprevinst, cmdline, cmdshow)
end.


Creative   (2006-11-28 11:08:00) [21]


> Этот код подходит для того, чтобы в программе путем опроса
> определять, нажата ли в текущий момент определенная клавиша.
>  Но никакой реакции на момент нажатия (или отпускания) клавиши
> этот код не подразумевает.
> Может быть, попробовать стандартный способ ?


Да, но в действие то происходит момент нажатия клавиши. Как же так?

Стандартный способ - вы имеете в виду нечто, аналогичное тому как обрабатываются событие в VCL? Потому что я сейчас как раз думаю рассмотреть как это сделано там, и переписать для себя. Если это не очень глупо.


Игорь Шевченко   (2006-11-28 10:22:00) [22]

Creative   (27.11.06 17:58) [13]


> Задачка в том, что мне нужно, чтобы по нажатию клавиши последовательно
> перерисовывались картинки. Но если я использую это событие
> onKeyPress - они перерисовываются слишком быстро, не успеваешь
> клавишу оторвать, уже несколько мелькнуло. Мне посоветовали
> повесить обработчик на onKeyUp.


Для этой задачки этот код вроде не подходит. Этот код подходит для того, чтобы в программе путем опроса определять, нажата ли в текущий момент определенная клавиша. Но никакой реакции на момент нажатия (или отпускания) клавиши этот код не подразумевает.
Может быть, попробовать стандартный способ ?


Creative   (2006-11-27 17:58:00) [23]


> Игорь Шевченко ©   (27.11.06 17:53) [11]
> В чем задача-то ?


Задачка в том, что мне нужно, чтобы по нажатию клавиши последовательно перерисовывались картинки. Но если я использую это событие onKeyPress - они перерисовываются слишком быстро, не успеваешь клавишу оторвать, уже несколько мелькнуло. Мне посоветовали повесить обработчик на onKeyUp.
А конкретно этот код понравился мне (в отличие от стандартного Winmin`а) тем, что в отновном проекте не болтается бешеное количество служебных процедур.


Creative   (2006-11-27 17:55:00) [24]

Соственно основной код. Код исходный, без моих искажений.

program Start;

uses Windows, Core, OpenGL;

var Wnd : TWndCore;
   C: TCube;

{$R *.res}

procedure DrawCube;
begin
C.Render;
end;

procedure KeyPress;
begin
if Keys[VK_LEFT] then C.RotateY(-3);
if Keys[VK_RIGHT] then C.RotateY(3);
if Keys[VK_DOWN] then C.Move(-0.1);
end;

begin
Wnd := TWndCore.CreateWnd(640, 480, false, true, 32, 60);
C:= TCube.Create;
Wnd.OnRender := DrawCube;
Wnd.OnKeyPress := KeyPress;
Wnd.MessageOperations(hinstance, hprevinst, cmdline, cmdshow)
end.


Creative   (2006-11-27 17:53:00) [25]

Пропущены стандартные условия создания окна (if FullScreenб ChangeDisplayMode и всякое такое) и подготовка контекста устройства (окно пишется для последующей работы с OpenGL)


function TWndCore.MessageOperations(hInstance, hPrevInstance: HINST;
 lpCmdLine: PChar; nCmdShow: Integer): Integer;
var Msg : TMsg;
begin
FActive := true;
while FActive do begin
 if (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) then begin
 if (msg.message = WM_QUIT) or (msg.message = WM_CLOSE) then
 FActive := false
   else begin
   TranslateMessage(msg);
   DispatchMessage(msg);
   end;
 end;

RefreshRenderPort;
if @OnRender <> nil then OnRender;
if @OnKeyPress <> nil then OnKeyPress;

SwapBuffers;
end;

Destroy();
Result := Msg.wParam;
end;


Игорь Шевченко   (2006-11-27 17:53:00) [26]

И зачем тебе требуется OnKeyPress при такой обработке ? Насколько я вижу, этот код позволяет узнать нажата ли в данный момент кнопка, а не вызвать пользовательский обработчик по нажатию/отпусканию кнопки.

В чем задача-то ?


Creative   (2006-11-27 17:50:00) [27]


var ScrWidth,
   ScrHeight,
   ScrBPP,
   ScrFreq : integer;
   glext : string;
   wglGetSwapIntervalEXT : function : GLint; stdcall;
   wglSwapIntervalEXT : function(interval : GLint) : Boolean; stdcall;

implementation

{ TWndCore }

constructor TWndCore.CreateWnd(Width, Height: integer; FullScreen, VSync: boolean; ColorDepth, Freq: integer);
var dwstyle : DWORD;
   dwexstyle : DWORD;
   h_Inst : HINST;

function MainAction(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;
begin
Result := 0;
 case (Msg) of
   WM_CREATE:
     begin
       //
     end;
   WM_CLOSE:
     begin
       PostQuitMessage(0);
       Result := 0
     end;
   WM_KEYDOWN:
     begin
       keys[wParam] := True;
       Result := 0;
     end;
   WM_KEYUP:
     begin
       keys[wParam] := False;
       Result := 0;
     end;
   WM_SIZE:
     begin
       ResizePort(LOWORD(LPARAM), HIWORD(LPARAM));
       Result := 0;
     end;
   WM_LBUTTONDOWN:
     begin
       //
     end;
   WM_LBUTTONUP:
     begin
       //
     end;
   WM_MOUSEMOVE:
     begin
       //
     end;
   WM_TIMER :
     begin
       Result := 0;
       end;
   else
     Result := DefWindowProc(hWnd, Msg, wParam, lParam);
 end;
end;


Creative   (2006-11-27 17:49:00) [28]

Спасибо, убедительно. С учетом того, что я не очень понимаю, какие именно куски кода не относятся к проблеме, я пожалуй его весь выложу.


unit Core;

interface

uses Windows, Messages, OpenGL;

const ApplicationName = 'RenderPort';

var keys : Array[0..255] of Boolean;

type TWndCore = class
    private
    FHandle  : HWND;
    FHDC     : HDC;
    FGLRC    : HGLRC;
    FWidth   : integer;
    FHeight  : integer;
    FRenderPort       : TWndClass;
    FoldScreenWidth   : integer;
    FoldScreenHeight  : integer;
    FScrMode          : TDeviceMode;
    FMainAction : Pointer;
    FFullScreen       : boolean;
    FBPP             : integer;
    FFreq            : integer;
    FVertSync        : boolean;
    WGL_EXT_swap_control : boolean;
    FActive : boolean;
    protected
    procedure GraphicInit;
    procedure GraphicFree;
    procedure RefreshRenderPort;
    function  ChangeDisplayMode(Width, Height, BPP, Freq : integer) : boolean;
    public
    OnBeforeRender : procedure;
    OnRender       : procedure;
    OnAfterRender  : procedure;
    OnKeyPress     : procedure;
    constructor CreateWnd(Width, Height : integer; FullScreen, VSync : boolean; ColorDepth, Freq : integer);
    destructor Destroy(); override;
    procedure PreparePort(FullScreen : boolean; ColorDepth : integer);
    procedure SwapBuffers;
    procedure ResizePort(Width, Height : integer);
    function  MessageOperations(hInstance : HINST; hPrevInstance : HINST; lpCmdLine : PChar; nCmdShow : Integer) : Integer; stdcall;
end;


Игорь Шевченко   (2006-11-27 17:47:00) [29]

Creative   (27.11.06 17:40) [6]

Во-первых, можно кусками. До 7168 байт в сообщение можно вставить. Не относящиеся к проблеме части кода можно убрать. Во-вторых, выкладывая код в форум ты привлекаешь всех посетителей. В третьих, посылая что-то по почте, ты просишь техподдержку, вынуждая конкретного адресата заниматься твоей пролемой.


Creative   (2006-11-27 17:40:00) [30]

Да я-то с удовольствием, но он велик слишком. Не лучше будет по почте?


Игорь Шевченко   (2006-11-27 17:37:00) [31]

Creative   (27.11.06 17:35) [4]


> Проблема в том, что конкетно обработку событий я стянула
> из чужого кода


Два варинта - либо криво стянула, либо чужой код крив. Я не увидел в приведенном фрагменте ничего, что бы относилось к обработке этих событий, а с телепатией у меня в понедельник плохо. Что знал - рассказал, будет больше кода, будет больше рассказов


Creative   (2006-11-27 17:35:00) [32]

Проблема в том, что конкетно обработку событий я стянула из чужого кода и в том-то и дело что в нем НЕ БЫЛО никакой своей обработки. Я привела в первом посте все, что касалось событий. Поэтому я и думала, что описанные приемы - это что-то принятое и понятное системе и достаточно только написать то, что мне нужно, аналогичным образом - и все будет работать.


Игорь Шевченко   (2006-11-27 17:27:00) [33]

Creative   (27.11.06 17:25) [2]

Нет, файл здесь нельзя прикрепить, можно только код в сообщение вставить.
Но судя по всему, у тебя какая-то своя обработка, которой в приведенном коде не видно. Событие OnKeyUp срабатывает в ответ на сообщение WM_KEYUP, а OnKeyPress на сообщение WM_CHAR. Как видишь, разница есть.


Creative   (2006-11-27 17:25:00) [34]


> > Почему так происходит?
> Потому что кривой класс окна ?


а здесь можно как-то прикрепить файл? можно было бы предъявить исходник.


Игорь Шевченко   (2006-11-27 17:15:00) [35]


> есть ли разница между onKeyUp и onKeyPress?


Есть.


> Пытаюсь описать собственный класс окна
> ...


> Почему так происходит?


Потому что кривой класс окна ?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо