How to use other class enum properties in Qml - qml

Given is a class ClassA which contains an enum:
class ClassA : public QObject
{
Q_OBJECT
QML_ELEMENT
public:
enum EnumClassA {
};
Q_ENUM(EnumClassA)
};
A second class has a property of ClassA::EnumClassA:
#include <ClassA.h>
class ClassB : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(ClassA::EnumClassA value READ ...)
public:
};
This works in Qml (meaning the property value can be used in Qml), but when using qmlint/qmlsc compiler the following message is shown:
error: Could not compile binding for value: Cannot generate efficient code for content pointer of non-QVariant wrapper type double of ClassB::value with type ClassA::EnumClassA
A dirty fix could be this:
// replace "Q_PROPERTY(ClassA::EnumClassA value READ ...)" with:
Q_PROPERTY(int value READ ...)
but it would be much nicer to keep the type in the property.
Is it possible to modify the enum so that it can be compiled?
Regards,

Related

Property same name as type - can i get rid of the explicit namespace?

This does not compile without explicit namespaces.
namespace A
{
public enum class Foo {};
public interface class Bar
{
public:
property A::Foo Foo
{
virtual A::Foo get();
};
};
} // namespace A
I used the common .NET/C# style to name the type and property identical here. The explicit namespaces are annoying, especially if they are nested/verbose in a real example.
Can i get rid of the explicit namespaces somehow?
Any way to "beautify" this? I tried using/typedef of the enum in the implementation of the property in the .cpp file to get the enum in the surrounding scope. No success.

custom attached property not found

I want to implement a new property (named "MenuForeground") for the pivot element, in order change the color of the PivotItem header through a defined ControlTemplate.
Therefore I created a new class for the custom property, added the #include in the needed code-behind xaml.h file and defined a new namespace ("xamlns:cap") according to the namespace of the custom property.
PivotProperties.h
#pragma once
using namespace Windows::UI::Xaml;
namespace CustomAttachedProperties
{
public ref class PivotProperties sealed : Windows::UI::Xaml::DependencyObject
{
public:
static Windows::UI::Color GetMenuForeground(UIElement^ obj);
static void SetMenuForeground(UIElement^ obj, Windows::UI::Color value);
static property DependencyProperty^ MenuForegroundProperty
{
DependencyProperty^ get() { return _menuForegroundProperty; }
}
private:
static DependencyProperty^ _menuForegroundProperty;
};
}
PivotProperties.cpp
#include "pch.h"
#include "PivotProperties.h"
using namespace CustomAttachedProperties;
DependencyProperty^ PivotProperties::_menuForegroundProperty = DependencyProperty::RegisterAttached(
"MenuForeground",
Windows::UI::Color::typeid,
Windows::UI::Xaml::Controls::Pivot::typeid,
ref new PropertyMetadata(false));
Windows::UI::Color PivotProperties::GetMenuForeground(UIElement^ obj)
{
return (Windows::UI::Color)obj->GetValue(_menuForegroundProperty);
}
void PivotProperties::SetMenuForeground(UIElement^ obj, Windows::UI::Color value)
{
obj->SetValue(_menuForegroundProperty, value);
}
In order to use the new property for a pivot element I declared a new xml namespace in the root element like the following
<Page
// ...
xmlns:cap="clr-namespace:CustomAttachedProperties">
But if I try to use the new property ...
<Pivot x:Name="pivot" cap:PivotProperties.MenuForeground="Red">...</Pivot>
... an error pops up, saying: "The attachable property 'MenuForeground' was not found in type 'PivotProperties'.
How to fix that?
The third parameter ownerType of the RegisterAttached method must be
The owner type that is registering the dependency property
not the type of the object where you want to set the property.
So your declaration should look like this:
DependencyProperty^ PivotProperties::_menuForegroundProperty =
DependencyProperty::RegisterAttached(
"MenuForeground",
Windows::UI::Color::typeid,
PivotProperties::typeid, // here
ref new PropertyMetadata(false));
Please note also that it is not necessary that your PivotProperties class derives from DependencyObject, as long as it only declares attached properties.
You may also consider using Windows.UI.Xaml.Media.Brush as property type to make it conforming with other properties like Background and Foreground.

Different function definition after compilation

I have my Keyboard class:
namespace BSGameFramework
{
namespace Input
{
static public ref class Keyboard
{
public:
static KeyboardState GetState();
};
}
}
Where KeyboardState is a ref struct.
After compilation as dll from my C# application I see the function from metadata as follow:
namespace BSGameFramework.Input
{
public class Keyboard
{
public Keyboard();
public static void GetState(ref KeyboardState value);
}
}
Keyboard class has lost its static state and the function GetState is now returning void and taking a KeyboardState as referenced parameter!
Somebody know why? Thanks in advance :D
The reason is because of the return type, ref struct KeyboardState.
In C++/CLI, the "ref" vs. "value" is the thing that determines whether a type is a reference type or a value type, not "class" vs. "struct". ref class and ref struct are both the same thing as C#'s class. value class and value struct are both the same thing as C#'s struct.
Therefore, you have a C++/CLI method declared as returning a reference type, but without the ^. This data type does exist in C++/CLI, but not in C#. The method signature you see is a workaround.
There are two possible solutions to this issue:
Change KeyboardState to a value struct. From what you said, it sounds like you intended for this to be a value type from the beginning, so this is probably the best solution.
Change the return type of the method to KeyboardState^. This will let the method show up in C# the same as it does in C++/CLI. However, if you do this, you'll want to switch all uses of KeyboardState to KeyboardState^. It's a reference type, it should be used with a ^.

c++ native code using an abstract class into a wrapper

I need to implement a c# GUI for my unmanaged code. So i have designed a wrapper to deal with my native code, but this does not work porperly.
I have a method which requires to make an instance to an abstract class and i'm not sure how to deal with it.
First for my C++ classes i used an abstract class:
class Interface abstract
{
public: Interface (void);
public: ~Interface (void);
public: virtual double Get() = 0;
};
And i used a ClassSpecific1 and a ClassSpecific2 depending on my current application, and i inherited the functions from the abstract class for each one.
class ClassSpecific1 : public Interface
{
public: ClassSpecific1 (void);
public: ~ClassSpecific1 (void);
private: double Get();//based on the abstract class
};
class ClassSpecific2 : public Interface
{
public: ClassSpecific2 (void);
public: ~ClassSpecific2 (void);
private: double Get();//based on the abstract class
};
Later i used another class, it works as a general class and uses the ClassSpecific1 or the ClassSpecific2 with an instance of the abstract class.
class ClassAPI
{
public: ClassLaserAPI(void);
public: ~ClassLaserAPI(void);
public: double Get(Interface *objToInterface);//This Get() calls the Get() in ClassSpecific1 or ClassSpecific2
};
Until here everything seems all right. I have tested everything and works as expected. My big problem is that i don't know how to make my method Get(Interface *objToInterface) from ClassAPI into my wrapper. Do i need to make a wrapper for my abstract class first in order to be able to create the instance**(Interface *objToInterface)** on the wrapper?
This is what i have so far, i hope someone can give me some help, i'm getting lost in how to proceed.
namespace API
{
public __gc class APIManaged
{
public: APIManaged(void);
public: ~APIManaged(void);
/** Unmanaged pointer to ClassAPI
*
*/
private: ClassAPI __nogc* cAPI;
public: double Get(Interface __nogc* objInterface);
};
I'm also having the same problem and got it resolved using this topic:
C++/CLI Inheriting from a native C++ class with abstract methods and exposing it to C#
I too am using an unmanaged abstract class and got things working by following the tips outlined in the link. I ended up with a few errors to fix and fixed them by changing my linker options in my unmanaged projects to not compile with /clr and only the wrapper project compiles using /clr.
Posting your output errors may help clarify some of the troubles you are having...

How to make my class implement from IMyInterface<T>?

I want to port the following code from c# to c++/cli:
class MyClass : IEnumerable<int> { ... }
I've tried
class ref class MyClass : IEnumerable<int>
but it doesn't seem to be working.
C++ has multiple types of inheritance. Don't forget to specify it, e.g.:
ref class MyClass : public IEnumerable<int>
{ };
In C++/CLI, I frequently find myself spelling out the full namespace in interface implementations. E.g.:
ref class MyClass :
public MyCompany::MyProject::MyComponent::IMyInterface
{ };
If your class doesn't actually implement the provided interface, you'll also (of course) get an error. And you'll want to remove the ^ from the class declaration. You're inheriting from an interface, not from a GC Handle to an instance of that interface.
Assuming your code is exactly what you're trying to compile, you have an extra class there. It should be just ref class, and not class ref class. Also, don't forget to translate any C# using statements to C++ using namespace, i.e.: using namespace System::Collections::Generic.