Как мне вызвать реализацию базового класса TextBox :: OnKeyDown () в моем переопределении? - PullRequest
1 голос
/ 28 февраля 2012

Я создал подкласс класса TextBox , чтобы можно было захватывать все события клавиатуры в методе OnKeyDown () ( Событие KeyDown не будет срабатывать для всехсобытия клавиатуры, включая, но не ограничиваясь, backspace и клавиши со стрелками, но OnKeyDown будет) .

Проблема в том, что он эффективно отключает TextBox, так как полностью обходит обработку внутренней клавиатуры элемента управления,Очевидное решение - вызвать OnKeyDown в суперклассе.

Как мне это сделать в среде выполнения Windows? Простой вызов TextBox :: OnKeyDown (...) не сработает, поскольку он фактически приведет меня к моему переопределению .

Метод OnKeyDown () является частью интерфейса IControlOverrides,и кажется, что я не могу получить указатель на этот интерфейс для экземпляра объекта TextBox, но только для моего производного экземпляра объекта.

1 Ответ

1 голос
/ 28 февраля 2012

Наследование в C ++ / CX не такое же, как наследование в C ++. Это связано с тем, что классы C ++ / CX ref на самом деле являются COM-объектами, которые реализуют наследование посредством различных агрегаций.

Пример, с которым я работал, был

public ref class MyTextBox : public TextBox {
  MyTextBox() {};
  ~MyTextBox() {};
  virtual void OnKeyDown(KeyEventArgs^ e) override {
    TextBox::OnKeyDown(e);
  };
};

, который не будет работать, потому что TextBox :: OnKeyDown () будет эффективно вызывать MyTextBox :: OnKeyDown (). Это связано с тем, как виртуальные методы реализованы в C ++ / CX и COM, подробный обзор можно прочитать здесь .

Visual Studio 11 Developer Preview Solution

Короткая версия заключается в том, что метод OnKeyDown () является частью интерфейса IControlOverrides, реализованного как MyTextBox, так и TextBox, благодаря некоторым хитрым трюкам компилятора. Чтобы получить указатель на интерфейс для реализации TextBox, мы сначала должны запросить его у TextBox - если мы спросим MyTextBox, мы окажемся там, где начали. И поскольку это наследование в COM, а не в C ++, мы делаем это через указатель на объект baseclass вместо this :

  virtual void OnKeyDown(KeyEventArgs^ e) override {
    struct IControlOverrides^ ico;
    HRESULT hr = __cli_baseclass->__cli_QueryInterface(const_cast<class Platform::Guid%>(reinterpret_cast<const class Platform::Guid%>(__uuidof(struct IControlOverrides^))),reinterpret_cast<void**>(&ico));
    if (!hr) {
        hr = ico->__cli_OnKeyDown(e);
    };
  };

Visual Studio 11 Beta Solution

Как и во многих других вещах, это было улучшено в бета-версии VS 11. Хотя «__super ::» по-прежнему не будет работать, теперь он работает нормально, просто для явного вызова интерфейса, в котором он определен:

  virtual void OnKeyDown(KeyEventArgs^ e) override {
    IControlOverrides::OnKeyDown(e);
  };

Обозреватель объектов в VS покажет вам, какой интерфейс определен методом OnKeyDown () в (IControlOverrides).

Проблема решена!

...