debugging visual C++ properties(hovering over variables does not show value) - visual-c++

I am working on code written in Visual C++17. But a MS specific feature is used namely properties.
Please note that I am not talking about .NET, but the behavior is similar. Most of my collegues including myself have a lot of experience in C# and hence at first glance these properties seem a handy feature.
This is not managed C++, to emphasize and avoid confusion!
The definition in Visual C++ is as follows :
virtual long GetDatumLening() = 0;
virtual void SetDatumLening(long l) = 0;
__declspec(property(get = GetDatumLening, put = SetDatumLening)) long DatumLening;
And using it in the code is like this :
if (hoofdLening->NietHypothecaireLening && hoofdLening->DatumLening < lControleDatum)
Both NietHypothecaireLening and DatumLening are properties defined in the explained manner.
Now my problem is that when I am debugging the application if I hover over those properties the values are not shown whereas properties in C# are shown even if there is some code behind it which is quite nice.
Is there a setting of some kind that I am missing in my Visual Studio environment or is this something I will have to live with ?
The fact that both the getter and setter are virtual should not make a difference, there is of course a non abstract class that implements these methods.
Thanks in advance.

Related

How do you load data into an attributed database class generated by the MFC application wizard?

Using the MFCApplication wizard in Visual C++ 2012, if "Generate attributed database class" is checked, a header with some special syntax (attributed C++ classes) are generated, which look like this:
// MFCApplication2Set.h: interface of the CMFCApplication2Set class
//
#pragma once
// code generated on March-05-13, 9:26 AM
[
db_source(L"Provider=SQLNCLI11.1;..."),
db_table(L"dbo.tblEmployee")
]
class CMFCApplication2Set
{
public:
... big list of stuff that corresponds to the fields in your db table omitted ...
}
The above header corresponds to a mostly empty implementation file:
// MFCApplication2Set.cpp : implementation of the CMFCApplication2Set class
//
#include "stdafx.h"
#include "MFCApplication2.h"
#include "MFCApplication2Set.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCApplication2Set implementation
That was the WHOLE implementation class. Notice that:
A. No parent class name is specified anywhere.
B. There's some "Visual C++ magic" going on here, that is, as a novice to modern C++, I'm lost.
db_source is documented here but the documentation is pretty thin or at least opaque to me.
Questions:
I was mystified by this syntax when I first saw it, but I figured out it's probably a variant of this Attributes feature in Visual C++. It is that, right?
How am I meant to I use these generated "attributed database class" objects? I found this documentation but if you look carefully at that documentation, that code sample is showing people the Old Way and the New Way, and is not telling me what I want to know which is how to use this new object that the IDE can not give me any documentation or code completion features for. Also since the generated code for the CMFCApplication2Set class generated by the wizard does not reference any types or class names, I'm lost. If I could even use some IDE feature to know what methods and stuff have been Magically Injected into this Magical mystery Object, I'd be better off. The only think I can think to do is to learn the old way and learn all the things you can call from the old two-separate-ATL-types world, and then somehow learn to combine them.
In a nutshell, I'm looking for the minimum syntax I need to know to actually use one of these Attributed Database Class instances, variables, as they are generated in a new MFC app by the wizard. The instance shown below is a member of an MFC document class and CMFCApplication2Set m_MFCApplication2Set is declared as a field inside the MFC document class.
What I have tried is to use this "untyped object". This object appears to have lots of data fields (m_X) and has only one method that shows up in IDE code completion, called GetRowSetProperties. Thanks to whatever magic or injection is going on, this generated Attributed Database Class (which does not visibly inherit anything) is a complete mystery to me at edit time and compile time.
Here's me just trying to inspect this thing to see if it even initialized itself when its constructor ran:
BOOL CMFCApplication2Doc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE;
TRACE( m_MFCApplication2Set.m_AStringFieldName); // outputs NOISE.
return TRUE; }
At compile time and edit time, the IDE gives me NO help about the types involved in this "anonymous" class that inherits from nothing, but which gets lots of secret powers due to some kind of Injection via those attributes I'm guessing. At debug time, I can see that there is more than just a bunch of data fields in this C++ class, but this still doesn't help me know how to use it. A minimal code sample of using one of these to go get a recordset from the database, would be great.
Update: Calling OpenDataSource is fun, because it compiles but the IDE doesn't think it should be valid. Nevertheless, it runs, and returns 0 as the result, but that doesn't actually initialize this CThingyThatVisualStudioGaveYouThatYouDontKnowWhatItIs:
This is a deprecated feature of attributed C++ code. Pre-processor expands code and replaces attributes with actual base classes. If you enable generation of these intermediate files, things are going to be more clear to you:
You will have XXX.mrg.cpp and XXX.mrg.h files generated, which you can review and see the real C++ code forwarded to compiler.
The attributes will be replaced with substituted bases classes, maps like BEGIN_COLUMN_MAP etc. The attributed source code is compact, but the feature is deprecated and looking into expanded code it should be easy (if necessary) to strip the attributes and copy expanded code right into source. It's easy with DB attributes, and more difficult with COM attributes since the internal dependencies are most sophisticated.

Converting C-style series of casts on AfxGetMainWnd from VC6/MFC6 to operate in modern MFC version (VC++2008 and later)

An application I'm porting from Visual C++ 6.0 to the MFC version in VC++2008, does a lot of get-AfxGetMainWnd()-and-do-C-Style-casts on it like this:
CUserInterfaceDoc *m_pDoc = (CUserInterfaceDoc*)((CFrameWnd *)AfxGetMainWnd())
->GetActiveDocument();
When I try the steps above, simply converting to dynamic_cast<>, I find that the Main Window is no longer accessible via casting-to-a-CUserInterfaceDoc in my program. I think that perhaps MFC had abused casts in VC++ 6, or that the compiler did some magic.
Rewriting the above to use dynamic casts would go like this, and it ends up with a nil pointer, which trips the assert() conditions I wrote here, as I want it to:
CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd);
assert(m_pDoc);
I'm assuming that everybody who has done this before will be able to say "Yeah, of course, they changed that casting behaviour...." but I can't find the documentation for it.
Where possible I'm changing my C++ classes to have a member variable (field) where I store
links to things that it was formerly finding by walking down from the "more or less global" AfxMainWnd().
It would help me to know what changed though, so I can understand what's going on above.
CUserInterfaceDoc is my application's MFC C++ Document class, it is a COleServerDoc which used to be "findable" at runtime with the gross C-style cast at the top.
The above cast still compiles in modern C++ but it's broken, probably due to the fact that the old VC++ 6 compiler did some kind of internal 'magic' with C-style casts that was against the ISO C++ standards. (That's purely a guess on my part).
My question is in two parts:
What's the usual way to get at the CurrentDocument (CFrameWnd::CurrentDocument) from another class that currently has no reference to the main CFrameWnd and had been using the hack I show at the top of this question?
What changed between the non-ISO-compliant VC++ 6 and the more-or-less ISO-compliant later C++ versions that would change the behaviour of the cast expressions above, or did the breakage occur due to MFC internal architecture changes?
My code change:
CUserInterfaceDoc * CMyBrowser::GetUserInterfaceDoc()
{
CUserInterfaceDoc *m_pDoc;
// formerly did this, which works in VC++6 and doesn't work anymore:
//m_pDoc = (CUserInterfaceDoc*)((CFrameWnd *)AfxGetMainWnd())->GetActiveDocument();
assert(m_pMainFrm);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> ( m_pMainFrm->GetActiveDocument() );
assert(m_pDoc);
}
If you are using MFC, you might as well just bite the bullet and use DYNAMIC_DOWNCAST which is an MFC defined macro for casting that's basically equivalent to dynamic_cast.
CFrameWnd* pFrm = DYNAMIC_DOWNCAST(CFrameWnd, AfxGetApp()->m_pMainWnd);
m_pDoc = DYNAMIC_CAST(CUserInterfaceDoc, m_pMainFrm->GetActiveDocument());
In your first rewrite:
CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd);
assert(m_pDoc);
... you simply missed the GetActiveDocument() call which was there in the C-Style cast. So it should work like this:
CUserInterfaceDoc *m_pDoc;
CWnd * mainWnd = AfxGetMainWnd();
assert(mainWnd);
CFrameWnd *frmWnd = dynamic_cast<CFrameWnd *> (mainWnd);
assert(frmWnd);
m_pDoc = dynamic_cast<CUserInterfaceDoc *> (frmWnd->GetActiveDocument());
assert(m_pDoc);
DYNAMIC_DOWNCAST is soo oldschool and actually no longer required if you enable RTTI (which is on by default).
See also: MFC DYNAMIC_DOWNCAST vs. dynamic_cast

ObjectQuery extensions from managed C++/CLI

I'm trying to move a project over to using Entity Framework, but to make it more fun, the project is in C++/CLR.
I've got a query
ObjectQuery<myData::Facility^>^ facQ = myContext->FacilitySet;
and I want to do this
int n = facQ.Count()
But I can't because c++ doesn't recognise extension methods using C# syntax. facQ->Count() doesn't work.
Using C# extension methods from managed C++/CLI shows the answer for user-defined extensions; but in this case, the extension is part of the .NET framework http://msdn.microsoft.com/en-us/library/bb349034%28v=vs.90%29.aspx.
Any ideas?
(I'm using visual studio 2008, and .NET 3.5).
System::Data::Objects::ObjectQuery implements IEnumerable<T>. The Count() method you see in C# is from the System::Linq::Enumerable class.
using namespace System::Linq;
int n = Enumerable::Count(facQ);
Also see this answer, which shows a couple examples of calling other extension methods in that class.

C# for-loop loop-expression syntax

I have a nice question about the loop-expression of a for-loop in C#.
I always like to learn and extend my knowledge so I often use my reflector to look and learn from other. Lately I was looking around in an assembly which I assume is a C# assembly.
I came across this:
public virtual void DoRows(Parse rows)
{
for (; rows != null; {
Parse more;
rows = more;
}
)
{
more = rows.More;
this.DoRow(rows);
}
}
I never knew I could use a code-block in my loop-expression. So I fired up MSDN and went looking in the language reference of C# but found nothing.
The C++ reference shows some interesting things tho (http://msdn.microsoft.com/en-us/library/b80153d8.aspx), but I am not a C++ developper and I have a strong feeling the assmbly was not written in C++.
dotPeek says the assembly is a v4.0.30319 / msil assembly.
Now here are the questions:
- Is this a C++ or a C# code-construct?!
- Can we do things like this in C#?
I am not able to reproduce code that looks like that and compiles in VS2010.
#edit: changed the word assembly in code-construct.
#edit II: Thanks for all your answers. I think this is either a bug in the dotPeek reflector or we found some for-loop-expression easter eggs. This is what Red Gate says about the same method:
public virtual void DoRows(Parse rows)
{
while (rows != null)
{
Parse more = rows.More;
this.DoRow(rows);
rows = more;
}
}
There is no such thing as a C++ or C# assembly. Once the code is compiled, it is ILCode. The reflector takes this ILCode and decompiles it to the language you selected.
This can result in code that is valid in ILCode, but not valid in the target language.
Compilation to IL is a many-to-one operation and decompilers have rules regarding which of the many choices they choose when decompiling. Often, different languages produce IL that is not possible to reproduce directly in another language.
In this instance either the decompiler has chosen poorly and the produced C# is invalid (a bug in the decompiler), or it cannot decompile the code into equivalent C#.

XNA - Keyboard Input

I just started using XNA Framework 4.0 today, and I was wondering what the easiest way was to get input from the keyboard. I recognize a lot of C++ in C# but the whole Java side of it is alien to me. This coupled with XNA is a little confusing so, please be specific and give examples. Thanks.
If you're comfortable mucking around with the Object Browser in VS, I'd advise looking at Microsoft.Xna.Framework.Input.Keyboard/Keyboardstate. These entries will show you what you have available to you in terms of ready-made functions. Alternatively, you could look on MSDN or follow a tutorial on Creator's Club. I'll post a quick snippet that checks for a specific keystroke.
currentState = Keyboard.GetState();
if(currentState.IsKeyDown(theKey) && previousState.IsKeyUp(theKey))
{
//Do something here
}
previousState = currentState;
theKey is a parameter that is defined outside of the scope of this snippet. You could set theKey to a specific value that you would want to trigger some specific program behavior on pressing (at the commented location in the fragment above). theKey is defined as:
Keys theKey
previousState and currentState are defined as:
private static KeyboardState currentState;
private static KeyboardState previousState;
While perhaps not the prettiest way of doing that, it works and is a fairly straightforward example to build from. Hope that helps.

Resources