Как мне вызвать реализацию базового класса TextBox :: OnKeyDown () в моем переопределении?

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

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

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

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


person Ludvig A. Norin    schedule 28.02.2012    source источник
comment
Разве в c ++ / cx нет ключевого слова __super?   -  person user1227804    schedule 28.02.2012
comment
__super привязан к базовому классу, что означает то же самое, что и TextBox :: OnKeyDown (...) в этом примере.   -  person Ludvig A. Norin    schedule 28.02.2012


Ответы (1)


Наследование в C ++ / CX не то же самое, что наследование в C ++. Это связано с тем, что классы ссылок C ++ / CX на самом деле являются 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

Краткая версия заключается в том, что метод 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

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

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

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

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

person Ludvig A. Norin    schedule 28.02.2012
comment
Обновление через несколько лет: я пробовал использовать TextBox::OnKeyDown(e) с компилятором VS 12, и он делает все правильно. В этой гимнастике больше нет необходимости. - person sethobrien; 18.03.2015