1

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

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

如何在 Windows 运行时执行此操作?仅仅调用 TextBox::OnKeyDown(...) 是行不通的,因为它会有效地将我带到我的 override

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

4

1 回答 1

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 中实现的,可以在此处阅读深入的概述。

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 测试版解决方案

与许多其他事情一样,这在 VS 11 Beta 中得到了改进。虽然 "__super::" 仍然不起作用,但它现在可以正常工作,只是为了显式调用定义它的接口:

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

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

问题解决了!

于 2012-02-28T12:40:43.610 回答