Пропустить событие KeyPress InputComboBox как параметр функции

Моя ОС - Windows 10 64bit, и я использую Delphi 10.0 Seattle Update 1.

У меня есть функция , которая вызывает в InputBox , что, вместо того , правку, она содержит функцию funInputComboBox ( константный ГТРК _ Метка : Строка ; аут STRV _ Результат : Строка ; Const STRC _ Items : Строка = '' ; Const STRC _ LocateItem : String = '' ): Boolean ; функция GetCharSize ( Canvas : TCanvas ): TPoint ; var I : целое ; Буфер : массив [ 0..51 ] из Чар ; begin for I : = 0 to 25 do Buffer [ I ] : = Chr ( I + Ord ( 'A' )); для I : от 0 до 25 выполняются Буфер [ I + 26 ] : = Chr ( I + Ord ( 'a' )); GetTextExtentPoint ( Canvas . Handle , Buffer , 52 , TSize ( Результат )); Результат . X : = Результат . X div 52 ; конец ; var Форма : TForm ; Подсказка : TLabel ; Комбо : TComboBox ; DialogUnits : TPoint ; ButtonTop , ButtonWidth , ButtonHeight : Integer ; begin Результат : = False ; STRV _ Результат : = '' ; Форма : = TForm . Создать ( приложение ); с формой сделайте попытку холста . Шрифт : = Шрифт ; DialogUnits : = GetCharSize ( Canvas ); BorderStyle : = bsDialog ; Надпись : = Приложение . Название ; ClientWidth : = MulDiv ( 180 , DialogUnits . X , 4 ); Позиция : = poScreenCenter ; Подсказка : = TLabel . Создать ( Форма ); with Prompt do begin Parent : = Form ; Надпись : = метка STRC _ ; Слева : = MulDiv ( 8 , DialogUnits . X , 4 ); Вверх : = MulDiv ( 8 , DialogUnits . У , 8 ); Ограничения . MaxWidth : = MulDiv ( 164 , DialogUnits . X , 4 ); WordWrap : = True ; конец ; Комбо : = TComboBox . Создать ( Форма ); с Combo do begin Parent : = Form ; Стиль : = csDropDown ; Элементы . Текст : = STRC _ Элементы ; ItemIndex : = Элементы . IndexOf ( STRC _ LocateItem ); Слева : = Подсказка . Слева ; Вверх : = Приглашение . Верх + подсказка . Высота + 5 ; Ширина : = MulDiv ( 164 , DialogUnits . X , 4 ); CharCase : = ecUpperCase ; - OnKeyPress : = ????? конец ; ButtonTop : = Combo . Top + Combo . Высота + 15 ; ButtonWidth : = MulDiv ( 50 , DialogUnits . X , 4 ); ButtonHeight : = MulDiv ( 14 , DialogUnits . У , 8 ); с TButton . Create ( Form ) do begin Parent : = Form ; Надпись : = 'OK' ; ModalResult : = mrOk ; По умолчанию : = True ; SetBounds ( MulDiv ( 38 , DialogUnits . X , 4 ), ButtonTop , ButtonWidth , ButtonHeight ); конец ; с TButton . Create ( Form ) do begin Parent : = Form ; Надпись : = «Отменить» ; ModalResult : = mrCancel ; Отмена : = Истина ; SetBounds ( MulDiv ( 92 , DialogUnits . X , 4 ), Combo . Top + Combo . Высота + 15 , ButtonWidth , ButtonHeight ); Форма . ClientHeight : = Верх + Высота + 13 ; конец ; Результат : = ( ShowModal = mrOk ); если Result then STRV _ Result : = Combo . Текст ; наконец, форму . Бесплатно ; конец ; конец ; Box. Смотри ниже:

OnKeyPress

Он отлично работает и выполняет свою работу, но я хочу добавить что-то еще. Иногда эта функция будет использоваться в местах, где требуется маскировать текст, например, автомобильные таблички выглядят следующим образом: AAA-0000 (3 числа и 4 буквы), поэтому, когда я это называю, я хочу пройти процедура / функция, которая будет вызываться при срабатывании.procedure proValidaMascaraPlaca(Sender: TObject; var Key: Char);

Моя процедура проверки маски имеет этот заголовок:

utils

Он не принадлежит ни к одному классу, он помещен в ваш ежедневный блок.procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin proValidaMascaraPlaca(Sender, Key); end;

Когда нам нужно его использовать, нам это нравится:

with Combo do
begin
  OnKeyPress := proValidaMascaraPlaca
end;

Итак, я хочу, чтобы мой объект Inpuprocedure (Sender: TObject; var Key: Char) объекта имел эту функцию, где он мог иметь любую процедуру проверки, которую мы передаем в качестве параметра:

function MakeMethod(Data, Code: Pointer): TMethod;
begin
  Result.Data := Data;
  Result.Code := Code;
end;

Очевидно, это не сработало, поэтому я попробовал другой метод, который я видел здесь. Он состоял из функции, которая имитировала бы ее, как если бы она была :TKeyPressEvent = procedure(Sender: TObject; var Key: Char) of object; with Combo do begin OnKeyPress := TKeyPressEvent(MakeMethod(@Combo, @proValidaMascaraPlaca)); end;

nil

Моя функция по-прежнему не имеет параметра процедуры, поэтому я исправляю ее в этом примере:

@Combo

Я попробовал proValidaMascaraPlaca()вместо этого Char, но оба потерпели неудачу. Они выполняли компиляцию, но когда она Senderбыла вызвана, она получила некоторую странную ценность OnKeyPressи of object, что привело к нарушению доступа.

Я надеюсь, что кто-то поймет, что я пытаюсь сделать, или уже сделал / видел это, и знаю, что я должен сделать, чтобы он работал. Это то, что я пытался сделать в течение некоторого времени, что я упал, как будто это заставит меня просматривать параметры по-новому.

delphi,events,parameters,parameter-passing,delphi-10-seattle,

1

Ответов: 1


1 принят

Проблема в том, что тип, используемый для Selfсобытия (как и для всех других событий VCL / FMX), объявляется как proValidaMascaraPlaca(), поэтому он требует, чтобы назначенный обработчик имел MakeMethod()параметр. При использовании метода класса этот параметр подразумевается, управляемый компилятором для вас. Но при использовании вашей автономной TMethod.Dataпроцедуры с Selfлюбым значением, которое вы назначаете proValidaMascaraPlaca()полю, передается в Selfпараметре, но не Senderимеет никакого Keyпараметра! Вот почему вы получаете мусор в своих Selfи proValidaMascaraPlaca()параметрах, потому что стек вызовов поврежден.

Чтобы сделать эту работу, вам нужно добавить явный параметр в качестве первого параметра , например:procedure proValidaMascaraPlaca(Self: Pointer; Sender: TObject; var Key: Char);Self

Data

MakeMethod()затем получит любое значение, указанное вами в @Comboпараметре Sender( Keyв вашем примере), Comboи proValidaMascaraPlaca()будет получать любые значения, Comboотправляемые им, как и ожидалось.

Если вы не хотите редактировать MakeMethod()itproValidaMascaraPlaca () (потому что он находится в библиотеке утилиты), вам нужно будет создать отдельную функцию-оболочку для передачи Self, а затем эта оболочка может вызвать игнорирование , например:procedure MyComboKeyPress(Self: Pointer; Sender: TObject; var Key: Char); begin proValidaMascaraPlaca(Sender, Key); end; ... with Combo do begin ... Combo.OnKeyPress := TKeyPressEvent(MakeMethod(nil, @MyComboKeyPress)); end;Self

TComboBox

Гораздо проще (и, в конечном счете, более безопасном) решении было бы получить новый класс TComboBoxвместо этого и переопределить виртуальный KeyPress()метод, например:

type
  TMyValidatingComboBox = class(TComboBox)
  protected
    procedure KeyPress(var Key: Char); override;
  end;

procedure TMyValidatingComboBox.KeyPress(var Key: Char);
begin
  inherited;
  proValidaMascaraPlaca(Self, Key);
end;

...

Combo := TMyValidatingComboBox.Create(Form);
Дельфы, событие, параметры, параметр-прохождение, Дельфы-10-Сиэттл,
Похожие вопросы