如何在我的覆盖中调用基类实现TextBox :: OnKeyDown()?

时间:2012-02-28 11:12:53

标签: microsoft-metro windows-runtime c++-cx

我已经创建了 TextBox 类的子类,以便我可以在 OnKeyDown()方法中捕获所有键盘事件( KeyDown事件不会触发对于所有键盘事件,包括但不限于退格键和箭头键,但OnKeyDown将<)>

这个问题是它有效地禁用了TextBox,因为它完全绕过了控件的内部键盘处理。显而易见的解决方案是在超类中调用OnKeyDown。

如何在Windows运行时执行此操作? 只调用TextBox :: OnKeyDown(...)将无法正常工作,因为它实际上会将我带到我的覆盖

OnKeyDown()方法是IControlOverrides接口的一部分,似乎我无法获得TextBox对象实例的接口的接口指针,但仅适用于我的派生对象实例。

1 个答案:

答案 0 :(得分:1)

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中实现虚拟方法的方式,可以阅读深入概述here

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 Beta解决方案

与其他许多事情一样,VS 11 Beta也有所改进。虽然“__super ::”仍然不起作用,但它现在可以正常工作,只是为了明确地调用它所定义的接口:

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

VS中的对象浏览器将显示在(IControlOverrides)中定义OnKeyDown()方法的接口。

问题解决了!