![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Фрейм, PaintBox и клавиатура... [D6, Win2k]
tunguss © (2005-05-20 18:05:00)Вот есть вопрос к вам, уважаемые господа.
Описываю ситуацию.
Есть фрейм (он обязателен по умолчанию - без него никуда :) ) - разрабатывается отдельно, но тестируется на форме. Наследник фрейма, естественно.
Я положил в свое время на него PaintBox во всю ширь (это важно) чтобы рисовать по канвасу без каких-либо заморочек (об этой я еще тогда не знал :) ). Возможно именно тогда я ошибся и следовало бы создавать канвас в ран-тайме - сейчас это возможное решение, но, как вы понимаете, не желательное (не то что это трудно переделать, но существует опасность возникновения побочных проблем).
Итак. Проблема жутко тривиальная - фрейму не поймать нажатые клавиши. Все. Причем с мышью все в порядке (она как раз ловится PaintBox'ом).
Форма их принимать не может, потому что тогда проект не будет соответствовать спецификации. Все способы с хуками, переопределениями KeyDown и поимкой messag'ей - перепробованы.
Вполне логично предположить, что PaintBox берет на себя эти самые messag'ы. Но у PaintBox'а нет ивентов-обрабочиков клавиатуры!
Вот так. Прошу высказывать возможные решения проблемы. Поскольку есть вероятность, что для ее решения требуются минимальные усилия, которые либо просто не приходят в голову либо сказывается недостаток опыта :)
tunguss (2005-05-26 15:31:00) [21]Всем-всем-всем, кто сюда наткнется. Вероятно обнаружена бага в 6-7 дельфях (насчет других не знаю). Что делаем. Создаем фрейм и биндим ему OnKeyDown. В обработчике пишем что-нибудь вроде 'Key catched'. Кидаем фрейм на палитру и затем на пустую форму (необязательный шаг - можно и в рантайме его...). Запускаем. Тыркаем буквенные клавиши. Все пойманы - хорошо. Тыкаем какую-нибудь стрелку. Упс - не поймало. Тыкаем буквенные клавиши.... Упс -.... тоже не поймало! А KeyDown должен ловить все!... Вот так. У кого есть доводы против того, что это бага и пути ее решения без правки кода формы (AppEvents ни на фрейме ни на форме тоже нежелателен) - пишите пожалуйста.
tunguss (2005-05-24 14:09:00) [22]Да, все приведенные примеры /отдельно/ от программы работают. Но не работают у меня в программе :). Все еще ищу хорошо укрывшуюся багу.
tunguss (2005-05-24 14:07:00) [23]Смутило тем, что чтобы фрейм получил фокус нужно тыкнуть в него мышкой :). Это метод когда на форме много контролов - пока так и есть - но в результирующей проге их не будет. Просто смутило. Не возмутило, не разозлило, ни чего еще подобное :)).
jack128 (2005-05-24 00:26:00) [24]tunguss © (23.05.05 12:46) [2]
Немного смутило название процедуры PaintBox1Click, но ради эксперимента попробовал даже с
ней :)
Чем оно тебя смутило?? Автотматом генерируемое название обработчика события OnClick для компонента с именем PaintBox1. С высокой долей вероятности - этот компонент имеет тип TPaintBox. Короче
Unit1
dfm
object 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
pas
unit 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
dfm
object 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
pas
unit 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-23 16:43:00) [25]Попробовал. И так не прошло :(. Спасибо вам ребята за помощь но такое чувство что действительно где-то то ли в моем коде то ли в коде заказчика делается какая-то гадость (нет, в конструкторе формы я оспасных свойств не устанавливаю :)).
На всякий случай уточню, что мне нужен WM_KEYDOWN, поскольку я перехватываю нажатие стрелок - навигация и все такое.
VladimirB (2005-05-23 16:29:00) [26]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 12:46:00) [27]По поводу наследования абсолютно согласен. Действительно, не логично :). Поторопился :).
Но... Ваш метод к сожалению не работает. Я его уже пробовал раньше (уже не перечислить сколько методов я пробовал :) ), но на всякий случай попробовал еще раз. Немного смутило название процедуры PaintBox1Click, но ради эксперимента попробовал даже с
ней :) (первым дело конечно же поставил это дело в конструктор).
KeyPreview у формы установлен в False, но, собственно, и со значением True фрейм абсолютно также упрямится :). ActiveControl на форме - тот самый фрейм. Но другие компоненты, тем не менее, независимо ни от KeyPreviiew, ни от ActiveControl, реагируют на нажатия клавиш так, как если бы фрейма вообще не было.
Если вы пробовали приведенный метод и он у вас работал - пожалйста скажите - возможно различия в каком-нибудь маленьком противном свойстве - тогда я хотя бы примерно буду, что искать и где весь этот корень зла (или просто обменяемся исходниками).
В любом случае, благодарю вас за внимание к моей проблеме.
jack128 (2005-05-21 17:19:00) [28]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;