Форум: "Компоненты";
Текущий архив: 2005.12.18;
Скачать: [xml.tar.bz2];
ВнизФрейм, PaintBox и клавиатура... Найти похожие ветки
← →
tunguss © (2005-05-20 18:05) [0]Вот есть вопрос к вам, уважаемые господа.
Описываю ситуацию.
Есть фрейм (он обязателен по умолчанию - без него никуда :) ) - разрабатывается отдельно, но тестируется на форме. Наследник фрейма, естественно.
Я положил в свое время на него PaintBox во всю ширь (это важно) чтобы рисовать по канвасу без каких-либо заморочек (об этой я еще тогда не знал :) ). Возможно именно тогда я ошибся и следовало бы создавать канвас в ран-тайме - сейчас это возможное решение, но, как вы понимаете, не желательное (не то что это трудно переделать, но существует опасность возникновения побочных проблем).
Итак. Проблема жутко тривиальная - фрейму не поймать нажатые клавиши. Все. Причем с мышью все в порядке (она как раз ловится PaintBox"ом).
Форма их принимать не может, потому что тогда проект не будет соответствовать спецификации. Все способы с хуками, переопределениями KeyDown и поимкой messag"ей - перепробованы.
Вполне логично предположить, что PaintBox берет на себя эти самые messag"ы. Но у PaintBox"а нет ивентов-обрабочиков клавиатуры!
Вот так. Прошу высказывать возможные решения проблемы. Поскольку есть вероятность, что для ее решения требуются минимальные усилия, которые либо просто не приходят в голову либо сказывается недостаток опыта :)
← →
jack128 © (2005-05-21 17:19) [1]tunguss © (20.05.05 18:05)
Вполне логично предположить, что PaintBox берет на себя эти самые messag"ы.
нет, не логично. PaintBox - наследник GraphicControl"а и сообщения от клавы не принемает. А фрейм не принимает на себя обработку начатия клавиш, так как он не имеет фокуса ввода. В отличии от всяких Edit"ов, Memo и тд фрейм при клике по нему не получает фокуса, так что это нужно делать самостоятельно.
type
TFrame2 = class(TFrame)
PaintBox1: TPaintBox;
procedure PaintBox1Click(Sender: TObject);
private
procedure FrameKeyPress(Sender: TObject; var Key: Char);
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
procedure TFrame2.FrameKeyPress(Sender: TObject; var Key: Char);
begin
ShowMessage("Yra");
end;
procedure TFrame2.PaintBox1Click(Sender: TObject);
begin
OnKeyPress := FrameKeyPress;
if CanFocus then
SetFocus;
end;
← →
tunguss © (2005-05-23 12:46) [2]По поводу наследования абсолютно согласен. Действительно, не логично :). Поторопился :).
Но... Ваш метод к сожалению не работает. Я его уже пробовал раньше (уже не перечислить сколько методов я пробовал :) ), но на всякий случай попробовал еще раз. Немного смутило название процедуры PaintBox1Click, но ради эксперимента попробовал даже с
ней :) (первым дело конечно же поставил это дело в конструктор).
KeyPreview у формы установлен в False, но, собственно, и со значением True фрейм абсолютно также упрямится :). ActiveControl на форме - тот самый фрейм. Но другие компоненты, тем не менее, независимо ни от KeyPreviiew, ни от ActiveControl, реагируют на нажатия клавиш так, как если бы фрейма вообще не было.
Если вы пробовали приведенный метод и он у вас работал - пожалйста скажите - возможно различия в каком-нибудь маленьком противном свойстве - тогда я хотя бы примерно буду, что искать и где весь этот корень зла (или просто обменяемся исходниками).
В любом случае, благодарю вас за внимание к моей проблеме.
← →
VladimirB © (2005-05-23 16:29) [3]TFrame2 = class(TFrame)
PaintBox1: TPaintBox;
procedure PaintBox1Click(Sender: TObject);
private
{ Private declarations }
procedure WMCharQ(var Message: TWMChar); message WM_CHAR;
public
{ Public declarations }
end;
implementation
{$R *.dfm}
procedure TFrame2.WMCharQ(var Message: TWMChar);
begin
ShowMessage("sdfsd");
end;
procedure TFrame2.PaintBox1Click(Sender: TObject);
begin
SetFocus;
end;
А это форма использующая фрейм.
type
TForm1 = class(TForm)
Frame21: TFrame2;
Memo1: TMemo;
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
begin
Frame21.SetFocus;
end;
← →
tunguss © (2005-05-23 16:43) [4]Попробовал. И так не прошло :(. Спасибо вам ребята за помощь но такое чувство что действительно где-то то ли в моем коде то ли в коде заказчика делается какая-то гадость (нет, в конструкторе формы я оспасных свойств не устанавливаю :)).
На всякий случай уточню, что мне нужен WM_KEYDOWN, поскольку я перехватываю нажатие стрелок - навигация и все такое.
← →
jack128 © (2005-05-24 00:26) [5]tunguss © (23.05.05 12:46) [2]
Немного смутило название процедуры PaintBox1Click, но ради эксперимента попробовал даже с
ней :)
Чем оно тебя смутило?? Автотматом генерируемое название обработчика события OnClick для компонента с именем PaintBox1. С высокой долей вероятности - этот компонент имеет тип TPaintBox. Короче
Unit1
dfmobject Form1: TForm1
Left = 192
Top = 107
Width = 696
Height = 480
Caption = "Form1"
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = "MS Sans Serif"
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
inline Frame21: TFrame2
Left = 112
Top = 80
Width = 320
Height = 240
TabOrder = 0
end
end
pasunit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit2;
type
TForm1 = class(TForm)
Frame21: TFrame2;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
Unit2
dfmobject Frame2: TFrame2
Left = 0
Top = 0
Width = 320
Height = 240
TabOrder = 0
object PaintBox1: TPaintBox
Left = 0
Top = 0
Width = 320
Height = 240
Align = alClient
OnClick = PaintBox1Click
end
end
pasunit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
TFrame2 = class(TFrame)
PaintBox1: TPaintBox;
procedure PaintBox1Click(Sender: TObject);
private
procedure FrameKeyPress(Sender: TObject; var Key: Char);
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
procedure TFrame2.FrameKeyPress(Sender: TObject; var Key: Char);
begin
ShowMessage("Yra");
end;
procedure TFrame2.PaintBox1Click(Sender: TObject);
begin
OnKeyPress := FrameKeyPress;
if CanFocus then
SetFocus;
end;
end.
← →
tunguss © (2005-05-24 14:07) [6]Смутило тем, что чтобы фрейм получил фокус нужно тыкнуть в него мышкой :). Это метод когда на форме много контролов - пока так и есть - но в результирующей проге их не будет. Просто смутило. Не возмутило, не разозлило, ни чего еще подобное :)).
← →
tunguss © (2005-05-24 14:09) [7]Да, все приведенные примеры /отдельно/ от программы работают. Но не работают у меня в программе :). Все еще ищу хорошо укрывшуюся багу.
← →
tunguss © (2005-05-26 15:31) [8]Всем-всем-всем, кто сюда наткнется. Вероятно обнаружена бага в 6-7 дельфях (насчет других не знаю). Что делаем. Создаем фрейм и биндим ему OnKeyDown. В обработчике пишем что-нибудь вроде "Key catched". Кидаем фрейм на палитру и затем на пустую форму (необязательный шаг - можно и в рантайме его...). Запускаем. Тыркаем буквенные клавиши. Все пойманы - хорошо. Тыкаем какую-нибудь стрелку. Упс - не поймало. Тыкаем буквенные клавиши.... Упс -.... тоже не поймало! А KeyDown должен ловить все!... Вот так. У кого есть доводы против того, что это бага и пути ее решения без правки кода формы (AppEvents ни на фрейме ни на форме тоже нежелателен) - пишите пожалуйста.
← →
jack128 © (2005-05-26 17:17) [9]проверять лениво, но скорее всего просто при нажатии стрелки фокус сместился с фрейма на какой то другой контрол...
← →
rOOse © (2005-05-26 17:35) [10]Дело в том что когда ты нажимаешь левуй(правую,вниз,вверх) фокус теряется т.е он переходит с фрейма на другой компонент или на саму форму
ты попробуй вместо стрелок поставить Enter or Escape (попробуй кинь на форму две кнопки одна над другой и keydown одной из них попробуй поймать стрелку вниз хрен получится)
← →
tunguss © (2005-05-26 17:49) [11]> to jack128:
а если на форме нет контролов? :) (см. to rOOse)
> to rOOse:
не должен фокус переходить на форму. Запусти допустим Settings > Control Panel > Mouse (чтобы был достойный пример задавших такие правила) и пожамкай на Tab. Перешел хоть раз фокус на форму? :) Теперь потыркай стрелочки. В разных разделах. Перешел фокус? :) И даже если так - перед потерей фокуса должна пойматься хотя бы последняя клавиша.
← →
tunguss © (2005-05-26 17:51) [12]безысходность это всегда баг. А тут нет выхода :). Поймать стрелочки. По крайней мере я его не вижу, а смотрел растопырив все глаза.
← →
rOOse © (2005-05-26 18:05) [13]ну не на форму но фокус теряется это точно
← →
tunguss © (2005-05-26 18:10) [14]абсолютно согласен - но КУДА :)))) ?????? И как его поймать-то :)))... KeyPreview к стрелочкам не относится. SetFocus, как видишь, не пашет. Можно было бы ловить стрелочку и принудительно возвращать фокус контролу - но ее не поймать, да и это некрасиво как-то. В багах ничего плохого - просто лучше чтобы о них где-то было объявлено чтобы проггеры могли сказать заказчику "извините, вот зайдите на borland.com и посмотрите - это баг, так что уж просим не винить нас, что мы извращаемся по-всякому чтобы его обойти"...
← →
rOOse © (2005-05-26 18:16) [15]кто помнит скан коды или ASCII клавиш?
← →
tunguss © (2005-05-26 18:22) [16]это к чему? :)
← →
rOOse © (2005-05-26 18:23) [17]а ты заметил что ctrl shift f1-f12 etc тоже не работают
← →
tunguss © (2005-05-26 19:13) [18]не заметил. ну ведь значит точно баг :). читаем хелп:
The OnKeyDown handler can respond to all keyboard keys, including function keys and keys combined with the Shift, Alt, and Ctrl keys, and pressed mouse buttons.
Круто, да? :)
← →
rOOse © (2005-05-26 19:24) [19]надо поробовать создать свой компонент на основе TFrame и попробовать там
← →
tunguss © (2005-05-26 19:27) [20]может в чат пойдем :)) ?. а то все мои идеи уже теряются куда-то :)). я там :)
← →
tunguss © (2005-05-26 19:27) [21]может в чат пойдем :)) ?. а то все мои идеи уже теряются куда-то :)). я там :)
← →
Юрий Зотов © (2005-05-27 10:48) [22]> tunguss
На всякий случай загляните сюда, вдруг поможет:
http://delphimaster.net/view/5-1109751986/
← →
tunguss © (2005-05-30 12:00) [23]тема насчет бага все еще открыта. вышеочначенный флуд не считается - к решению мы не пришли :(.
← →
tunguss © (2005-05-30 12:05) [24][22] к флуду естественно не относится, спасибо Юрий. Но к сожалению в данном случае предложенный там выход нам не позволен заказчиком :).
← →
tunguss © (2005-05-30 12:31) [25]вот эти две темы также относятся к означенной проблеме:
http://delphimaster.net/view/5-1109751986/
http://delphimaster.net/view/5-1109751986/
← →
tunguss © (2005-05-30 14:21) [26]УРА. Все. Тема закрыта. Делаем так:
protected
...
procedure WMGetDlgCode (var msg: TMessage); message WM_GETDLGCODE;
...
implementation
procedure TMyCustomControl.WMGetDlgCode(var msg: TMessage);
begin
inherited;
msg.Result := msg.Result + DLGC_WANTARROWS
end;
Покорнейше благодарю Юрия Зотова и Просто Джо.
P.S. Тема-то закрыта, но мы-то все равно знаем, что это баг /:))))
← →
tunguss © (2005-05-30 14:23) [27]P.P.S. и не пугайтесь слова Custom в этом примере, как сделал это я - это делается для наследников TWinControl, Custom-компоненты, как мы помним, делают это сами ::).
← →
tunguss © (2005-05-30 15:49) [28]И еще благодарю rOOSe, VladimirB - за проявление интереса к сему вопросу....
...прям как фильм снял :).
Страницы: 1 вся ветка
Форум: "Компоненты";
Текущий архив: 2005.12.18;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.013 c