سؤال

I have created a subclass of the TextBox class so that I can capture all keyboard events in the OnKeyDown() method (the KeyDown event will not trigger for all keyboard events, including but not limited to, backspace and arrow-keys, but OnKeyDown will).

The problem with this is that it effectively disables the TextBox, as it bypasses the control's internal keyboard handling entirely. The obvious solution is to call OnKeyDown in the superclass.

How do I do that in Windows Runtime? Just calling TextBox::OnKeyDown(...) won't work, as it will effectively take me to my override.

The OnKeyDown() method is part of the IControlOverrides interface, and it seems I can't get an interface pointer to that interface for the TextBox object instance, but only for my derived object instance.

هل كانت مفيدة؟

المحلول

Inheritance in C++/CX is not the same as inheritance in C++. This is because C++/CX ref classes are in fact COM objects, which implements inheritance through a variety of aggregation.

The example I was working with was

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

which won't work, because TextBox::OnKeyDown() will effectively call MyTextBox::OnKeyDown(). This is because of how virtual methods are implemented in C++/CX and COM, an in-depth overview can be read here.

Visual Studio 11 Developer Preview Solution

The short version is that the OnKeyDown() method is part of the IControlOverrides interface, implemented by both MyTextBox and TextBox, thanks to some clever compiler tricks. To get hold of the interface pointer for the TextBox implementation, we first need to ask the TextBox for it - if we ask MyTextBox we end up where we started. And because this is inheritance in COM, not C++, we do that through a pointer to the baseclass object instead of 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

As with so many other things, this has been improved in the VS 11 Beta. While "__super::" still won't work, it now works fine just to make the call explicitly to the interface in which it is defined:

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

The Object Browser in VS will show you which interface the OnKeyDown() method is defined in (IControlOverrides).

Problem solved!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top