![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
есть ли разница между onKeyUp и onKeyPress? [D7, WinXP]
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?
Есть.
> Пытаюсь описать собственный класс окна
> ...
> Почему так происходит?
Потому что кривой класс окна ?