I would like to check the left button is the pressed one.
I red on Msdna:
if(e->Button == MouseButtons.Left) {...}
//or
if(e->Button == ::MouseButtons.Left) {...}
But no one of them compiles.
This is an annoyance of the C++ language, inherited by C++/CLI. It puts the names of types and the names of class members in the same symbol table. This is something you'll battle often when you write Winforms code in C++/CLI instead of C# or VB.NET, languages that keep type identifiers separate.
There's an ambiguity between the MouseButtons enum type and the Form class' MouseButtons property, they are both in scope here. IntelliSense stops helping you to get the syntax right which is probably how you ended up with . instead of :: Leaving no odds anymore to get a decent compiler error message. You resolve the ambiguity by writing the enum type name in full:
if (e->Button == System::Windows::Forms::MouseButtons::Left) {
// etc...
}
Problems like these are probably one reason that C++/CLI never got very popular. Then again, C# is rather a class act. Recommended.
You need to hook the event on control you want:
this->control->MouseDown += new System::Windows::Forms::MouseEventHandler(this, &Form1::control_MouseDown);
and handle it like this:
void control_MouseDown(Object* sender, System::Windows::Forms::MouseEventArgs* e) {
if(e->Button == MouseButtons::Left) {
//code here
}
}
Related
I've been starting to use VS2017 Community. This bugs me:
Below is normal getter setter from previous VS:
public string Name
{
get{ return _name;}
set{ _name = value;}
}
This is the new getter setter:
public string Name { get => _name; set => _name = value; }
Anyone can explain to me why the syntax is changed?
I wouldn't say they changed it, I would say they gave us some new syntax options. You can still use the "old" way of declaring getters and setters, but there is now also a more functional programming style of doing it as well. In C#6 Microsoft already introduced using expressions for getter only properties doing:
public int SomeProp => someMethod();
C#7 enhanced this support allowing it to be used for getters AND setters. One nice feature of this is with the new "throw expressions" feature which allows us to make some concise syntax. For example, before you had to do.
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (value == null)
throw new ArgumentNullException(nameof(Name));
_name = value;
}
}
We can now simplify this to:
private string _name;
public string Name {
get => _name;
set => _name = value ?? throw new ArgumentNullException(nameof(Name));
}
Granted, you could do the throw expression even without making the setter a lambda, but as you can see, for simple things, it makes the syntax very concise.
As with anything, use the syntax that makes the most sense to you and is most readable for the people who will be coding your application. Microsoft has been making a push to add more and more functional programming style features to C# and this is just another example of that. If you find it ugly/confusing/not needed, you can absolutely accomplish everything you need with the existing method. As another example, why do we have while and do while loops? I can honestly say I've used a do while loop maybe 5 times in my career. A while loop can do everything a do while can just with different syntax. However, there are sometimes where you realize that using a do while will make your code more readable, so why not use it if it makes things easier to follow?
The syntax hasn't changed: it has been improved. C# has been always backwards-compatible with syntax and grammar from previous versions.
Why property getters/setters can be implemented with lambda syntax (expression-bodied accessors)? Probably there's no scientific reason to do so, but there's a consensus about introducing useful functional programming constructs in C# as it turns the language into a more productive tool.
Just foillow up C#'s evolution since C# 2.0:
From delegates provided as regular methods to anonymous delegates.
LINQ, lambda-style delegates/expression trees.
Expression-bodied methods.
...and expression-bodied accessors! And probably future C# versions will introduce even more functional programming-style syntax and grammar.
You'll notice they removed the 'return' syntax, this was done (from what I've read) to make it more clear that they aren't functions (and when reflected can't be treated as functions and can't be made into delegates) but rather this kind of 'pseudo-function' (if you get what I'm trying to well get at).
So basically its to make it more clear that the getter is linking this this variable and the repeating for the setter. It also is because in newer versions you can do something like
public int MyInt => x ? y:z;
Which represents
public int MyInt
{
get
{
return x ? y:z;
}
}
Also both syntax should work, its just a new syntax that they added to bring it in line with the above example.
I know I am adding this details after a year, but just understood that my VS 2017 generated new syntax on my web user control, and that does not reflect on the aspx file when I wanted to set a value for it.
like
private bool _ShowBankDetailPanel = false; //To Show Bank details section in registration
public bool ShowBankDetailPanel { get => _ShowBankDetailPanel; set => _ShowBankDetailPanel = value; }
and on ASPX side you will NOT have property like
it is only recognize
old style getter setter....(I experience this,,, but I am be wrong)
I have unmanaged object of WtfClass.
class WtfClass { };
And I also have managed class which uses pointer to this object.
ref class MyClass //works fine if you remove "ref"
{
public:
void MyMethod();
void WtfMethod(void * pVoid);
WtfClass *pWtfStruct;
};
void MyClass::MyMethod()
{
/*WtfClass* pWtfStruct; //if you uncomment this it will compile even with ref*/
WtfMethod((int*)(&pWtfStruct)); //(!!!invalid type conversion here)
}
void MyClass::WtfMethod(void *pVoid)
{}
I can't cast WtfClass* pointer from field, but can easily cast the same pointer defined within MyMethod(). If make MyClass unmanaged it works in any case.
It's better to look at screenshots:
https://ibin.co/2iOcN1ooaC7A.png [using ref-bad.png]
https://ibin.co/2iOcYtP84H0e.png [using ref-good.png]
ibin.co/2iOcjCCc2gQe.png [without ref.png] (sorry not enough reputation to paste more than 2 links)
Of course I can have workaround like this, but I'd like to understand why this happening:
void MyClass::MyMethod()
{
WtfClass* pWorkAround = pWtfStruct; //not required in this case
WtfMethod((void*)(&pWorkAround));
}
OK, so to summarize, without the duplicate field & local variable names:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
}
};
Side question: &fieldWtfPtr is of type WtfClass**, a double pointer. Did you mean to cast that to a int**, also a double pointer? Or perhaps did you want to take fieldWtfPtr as a WtfClass* single pointer and cast that to a int* single pointer?
Here's why you're getting the error: MyClass is a managed object. The garbage compiler is allowed to move it around at any point, without telling you. So, it's location in memory can change at any point. So when you try to take the address of a class field, it's not valid because the address of that field can change at any point!
Why the other things make it work:
Local variables are stored on the stack, and the stack doesn't get moved around by the garbage collector, so it is valid to take the address of a local variable.
If you remove the ref, then MyClass is no longer a managed object, so the garbage collector won't move it around, so now the addresses of its fields won't change willy-nilly.
For this case, the easiest fix would be to make use of a local temporary variable.
void foo()
{
WtfClass* localCopyWtfPtr = this->fieldWtfPtr;
WtfMethod((int*)(&localCopyWtfPtr)); // Works
// If WtfMethod changed the data, write it back.
this->fieldWtfPtr = localCopyWtfPtr;
}
When I tried to recreate this, the compiler generated the following error:
error C2440: 'type cast' : cannot convert from 'cli::interior_ptr<CWtfClass*>' to 'LPVOID *'
I think what is going on here is some magic that allows managed classes to have unmanaged members. The MSDN documentation for cli::interior_ptr describes what's going on - basically this is used to allow for the managed object to change its memory address in the managed heap, which would cause problems when native pointers come in to play.
The reason that assigning the member to a variable first works is most likely because it has an implicit conversion to the template parameter, but since it is a managed type the compiler won't allow you to get the address of the variable (since the garbage collector can move it around in memory as needed).
The workaround in your question is probably the best way to fix this compiler error.
David answered why this happens and suggested a workaround for your case.
I'll just post a different solution here: You can pin your managed object to tell the GC not to move it around. The most lightweight way to do that is through pin_ptr (the GC won't even know you pinned something unless it stumbles upon your code in the middle of a collection). As long as it stays in scope, the managed object will be pinned and won't move. It's best if you avoid pinning for too long, but this lets you get a pointer to a chunk of managed memory which is guaranteed not to move - it's helpful when you want to avoid copying things around.
Here's how to do it:
pin_ptr<WtfClass*> pin(&pWtfStruct);
WtfMethod(pin);
pin acts just like a WtfClass**.
Regarding side question of David Yaw.
I faced with this problem while used some WINAPI functions.
IAudioEndpointVolume* pWtfVolume = NULL;
pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pWtfVolume);
pWtfVolume->SetMute(BST_CHECKED, pGuidMyContext);
And it's working only if I pass &pWtfVolume. Ironically you can pass argument without "&", just pFieldVolume and compiler will say OKAY, but interface IAudioEndpointVolume will not work.
Look at this:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
WtfMethod((int*)(fieldWtfPtr)); // Compiles!!!
}
};
In visual studio, when programming with C# (or other .NET languages), one can apply an attribute to a method which causes the debugger to ignore it. [DebuggerHidden] or [DebuggerStepThrough] both allow this in C#.
Is there an equivalent when working with Objective-C code using Xcode 5?
Example to illustrate the behaviour
void Main() {
Print("GetNumber returns: ", GetNumber());
}
[DebuggerHidden]
int GetNumber() {
return 42;
}
void Print(string s, int n) {
Console.WriteLine(s + n.ToString());
}
Without the [DebuggerHidden] attribute, when stepping through the code using "Step Into...", control flow goes like this:
Main
GetNumber
Print
With the attribute, the debugger skips GetNumber, and goes straight from Main to Print.
This is very useful for ignoring trivial method calls such as property getters, etc.
I have some various such trivial methods that I'd like to make the debugger skip past in Xcode if possible.
I am writing a managed wrapper in C++/CLI (VS2010) for a third-party unmanaged library. In the code, I have a method that looks like this:
if(oldState != _state && UnitStateChanged != nullptr)
UnitStateChanged(this, gcnew UnitStateChangedEventArgs(oldState, _state));
The "nullptr" generates the following error:
error C2446: '!=' : no conversion from 'int' to 'UnitStateChangedEventHandler ^'
The compiler seems to treat any use of "nullptr" as an "int", even on something as simple as this:
Object^ temp = nullptr;
Everything i've read indicates that the compiler will figure it out on it's own, but that doesn't seem to be the case. Is there a setting that I'm missing (other than /clr or #pragma managed)?
Someone without a C++11 compiler wrote
#define nullptr (0)
somewhere in a header file?
(The usual macro is #define NULL (0))
This is, of course, forbidden.
It looks like you're trying to fire an event.
In C#, there's a standard idiom for firing an event while protecting against null reference exceptions and multithreading modification:
// C#
EventHandler handler = this.MyEvent;
if(handler != null)
handler(this, new EventArgs(foo));
It looks like you're trying to re-create that in C++/CLI, but it's unnecessary. In C++/CLI, an event will emit three 'inner methods' (is that the proper name for them?) called add, remove, and raise. In C#, it creates add and remove only, no explicit raise, which is why we have to write that block of code over and over.
Here's an event defined in C++/CLI, and what .NET Reflector sees when it decompiles it:
// C++/CLI:
public ref class Test
{
public:
event EventHandler^ MyEvent;
};
// Decompiled to C#:
public class Test
{
// Fields
private EventHandler <backing_store>MyEvent;
// Events
public event EventHandler MyEvent
{
[MethodImpl(MethodImplOptions.Synchronized)] add
{
this.<backing_store>MyEvent = (EventHandler) Delegate.Combine(this.<backing_store>MyEvent, value);
}
[MethodImpl(MethodImplOptions.Synchronized)] remove
{
this.<backing_store>MyEvent = (EventHandler) Delegate.Remove(this.<backing_store>MyEvent, value);
}
raise
{
EventHandler <tmp> = null;
<tmp> = this.<backing_store>MyEvent;
if (<tmp> != null)
{
<tmp>(value0, value1);
}
}
}
}
The raise inner method is doing the null check for you, so you can skip doing it, and just fire the event without checking.
if(oldState != _state)
this->UnitStateChanged(this, gcnew UnitStateChangedEventArgs(oldState, _state));
This apparently is a Google-proof term since I can't get any search engines to not throw away the "extra" characters. I did also look on MSDN in the C++ reference but I can't seem to find the C++/CLI reference because there is nothing in the declarations section on it.
It means "pass by reference":
void bar::foo(Object^% arg) {
arg = gcnew Object; // Callers argument gets updated
}
Same thing in C++:
void foo(Object** arg) {
*arg = new Object;
}
or C#:
void foo(out object arg) {
arg = new Object();
}
C++/CLI doesn't distinguish between ref and out, it does not have the definite assignment checking feature that the C# language has so no need to distinguish between the two. Same in VB.NET, ByRef vs ByVal.
% is a tracking reference.
It is similar to a native reference (Object&), but a tracking reference can reference a CLR object while a native reference cannot. The distinction is necessary because the garbage collector can move CLR objects around, so a CLR-object's memory address may change.
The ^ is a handle. This simply means it is managed. See MSDN and also this SO post.
Essentially, it's the "managed" version of Object*&, and equivalent to ref or out on a reference type in C#.
This is a managed pointer by reference. So if you had something like:
void DoSomething(System::String^% stringObject)
in C# it would look like:
void DoSomething(ref System.String stringObject)
This is a C++/CLI Tracking Reference. This is kind of like a C++ reference, but to a managed object.