如何在重写中调用基类实现TextBox::OnKeyDown()



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

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

如何在Windows运行时中做到这一点仅仅调用TextBox::OnKeyDown(…)是行不通的,因为它会有效地将我带到覆盖

OnKeyDown()方法是IControlOverrides接口的一部分,我似乎无法为TextBox对象实例获取指向该接口的接口指针,而只能为我的派生对象实例获取。

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++,我们通过指向基类对象的指针来实现,而不是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测试版中得到了改进。虽然"__super::"仍然不起作用,但它现在可以很好地对定义它的接口进行显式调用:

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

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

问题解决了!

最新更新