With Windows 8, WinRT, C++/Cx I think the time to write an elegant C# / XAML app using some DirectX rendering in C++ has finally come! Thanks WinRT! :-)

Here I just plan to describe my attempt at learning DirectX and C++ and integrate it nicely in a C# XAML app.

My first exercise was to attempt to create a simple DirectX “Context” as WinRT C++/Cx component that can target multiple DirectX hosts: SwapPanel, CoreWindow, ImageSource and render an independent scene and initialize and use it from C#.

Note this is a metro app. It requires VS2012 and Windows 8.

First the appetizers, here is my simple scene:

And it is created with the code below, mostly one giant C# (5, async inside!) object initializer:

There is much to say about this sample but I won’t go into the detail of DirectX too much (this is a very basic sample as far as DirectX is concerned and the source code is available, at the bottom), instead I will mostly speak about C++/Cx – C# communication.

1. The main DirectX C++/Cx components

1.1. DXContext

First there is the DirectX context, here is an extract of its important methods and properties

DXContext is a ‘public ref class’ meaning it’s a shared component (Can be used by C#), it must be sealed (unfortunately… Except those inheriting from DependencyObject, all C++ public ref class must be sealed, as explained here, inheritance section)

All the public members are accessible from C#, the most important are the overloaded “SetTarget()” methods that will set the DirectX Rendering target. Can be changed anytime (although it seems to be an expensive operation, I think rendering on a Texture should probably be done an other way, when I will know better).

Finally it hold all DirectX device information as internal variables. These can’t be public or protected as they are not WinRT component. But, being internal, they can be accessed by other component in the library, it’s how the scene can render. I tried to trim the fat to the minimum number of DirectX variable that such an object should contains.

Note plain C++ doesn’t have the ‘internal’ visibility, this is a C++/Cx extension and it means the same thing as in C#, i.e. members are accessible by all code in the same library.

ComPtr<T> is a shared COM Pointer. Take care of all reference counting for you.

DXContext implements INotifyPropertyChanged and can be observed by XAML component or data binding! I also created a macro for the INotifyPropertyChanged implementation as it is repetitive and I had to write a long winded implementation due to some mysterious bug in the pure C++ sample.

It has a Snapshot() method to take a screen capture! And BasicTexture have a method to save to file.

1.2 Scene

My first attempt at using this DXContext was to create a Scene object which contains ISceneData object.

An ISceneData can be ripped of, more or less, verbatim from various DirectX sample around the web. And the Scene object will take care of initializing it and rendering it when the time is right. I have 2 ISceneData implementations: CubeRenderer, HelloDWrite.

1.3 BasicScene, BasicShape, BasicTexture

Unfortunately all the sample on the web often have a lot variables, all mixed up and trying to sort out what does what takes some thinking.

So I created a BasicScene which takes a list of shapes with texture and location (transform) and renders it

It also has some Background and a Camera, all WinRT component that can be controlled by C++.

The BasicShape contains point and index buffer for triangles and has various create method that will populate the buffers.

The BasicTexture can load a file or be created directly in memory (and rendered to by using Context.SetTarget(texture)), and contains the texture and textureView used by the rendering process.

Each of these class has very few DirectX specific variables making it relatively easy to understand what’s going on.

2. C++/Cx to C# mapping

When C++/Cx components are called from C#, the .NET runtime does some type mapping for you. There is the obvious, the basic types (int, float, etc..) and value types (struct) are used as is. But there is more, mapping for exception and important interfaces (such as IEnumerable).

It’s worth having a look at this MSDN page which details the various mapping happening.

Also, to refresh my C++ skill I found this interesting web site where most Google query lead to anytime I had a C++ syntax or STL issue!

3. Exception across ABI

You can’t pass custom exception or exception’s message across ABI (C++ / C# / JavaScript boundary). All that can pass is an HRESULT, basically a number. Some special number will pass some special exception as explained on this MSDN page.

If you want to pass some specific exception you have to use some unreserved HRESULT (as described here) and have some helper class to turn the HRESULT in a meaningful number.

Note you can’t expose Platform::Exception publicly either (well maybe you can, but it was troublesome). But you can expose an HRESULT. The runtime will automatically turn it into a System.Exception when called from C#.

4. Reference counting and weak pointer

C++/Cx is pure C++. There is no garbage collection happening when writing pure C++ app, even if one use the C++/Cx extension. The hat (^) pointer is a ref counted pointer that can automatically be turned into a C# reference.

That can lead to a problem when 2 C++/Cx components reference each other as in the following (simplified) scenario

5. debugging / logging

Sometimes logging is helpful for debugging. For example I log creation and deletion of some items to be sure I don’t have any memory leak. However, printf, cout<<, System::Console::WriteLine won’t work in a metro app.

One has to use OutputDebugString, output will appears in Visual Studio output window.

6. IEnumerable, IList

If you use C# you must love IEnumerable, IEnumerator, IList and LINQ. When writing a C++ component you should make sure it plays nice with all that.

The .NET runtime does some automatic mapping when calling in C++/Cx component, as explained here.

6.1 IEnumerable

In C++ one shall expose Windows::Foundation::Collection::IIterable<T> to be consumed in C# a System.Collections.Generic.IEnumerable<T>.

IIterable has a single method First() that return and IIterator. That will be mapped to an IEnumerator.

However there is a a little gotcha. Unlike C# IEnumerator which starts before the first element (one has to call bool MoveNext()) IIterator starts on the first element.

6.2 IList

One can return an Windows::Foundation::Collections::IVector<T> to be mapped to an IList<T>. There is already a class implementing it:

Platform::Collections::Vector<T>.

Or one can use vector->GetView() to return a Windows::Foundation::Collections::IVectorView<T> that will be mapped to an IReadonlyList<T>.

7. Function pointers and lambda

C++ 0x (or whatever is called the latest C++ standard) introduced lambda expression to create inline function, much like in C#.

It’s all quite intuitive except for the capture part. You have to specify which value you want to capture (this, local variable) and you can specify by value or reference (using the ‘&’ prefix), or all local variables and this with equal as in: ‘[=]’

In some instance I had problem assigning lambda to a function pointer, for example the code below didn’t compile for me (maybe I missed something?)

Remark tasks are value type and start executing immediately once created (in another thread).

When chaining tasks with ‘then’ you can capture exception from previous task by taking a task<T> argument instead of T. And put a try/catch around task.get(). If you do not catch exception it will eventually brings the program down.

9. Conclusion

It proved pleasantly surprisingly easy to have the C++ and C# works together with WinRT. Smooth and painless. C++ 11 was easier to use that my memory of C++ was telling me. And in the end I mixed and matched them all with great fun. To boot my C# app starts real quick (like a plain C++ app)! It’s way better than C++ CLI!

But none behave like an ordinary HeaderedItemsControl and all did impose some constraint which make using databinding, templating or MVVM more awkward than it should be. So here is my take on this control.

There is a Transparent Grid background grid for hit testing, a border at lowest Z order for highlight, the content presenter for the header and an ItemsPresenter in a Popup for children.

Now the most basic implementation of an ItemsControl just setup children. I also copy the style in PrepareContainerForItemOverride, as MenuItem’s children item are whole new MenuItem with the default style. This code make sure all children and children’s children and so on looks the same as the top level MenuItem, in case it has been styled.

Mouse Handling

Now all is needed is to overrides OnMouseEnter, OnMouseLeave, OnMouseLeftButtonDown, OnMouseLeftButtonUp.

Most of them do little and delegate the thinking to the class MenuPopupManager. This class maintains a list of all open popup, position the Popup appropriately, hide those Popup that need be hidden and close all MenuItem after a timeout.

Ideally it should close all menu when the user click outside the MenuItem but I could not get it to work reliably.

Obviously MenuItem implement Click and triggering an ICommand and hiding itself after that. If no Click event handler or Command is defined it will do nothing (including not closing the menu), making it easy to embed advanced control in popup menu.

Styling

And lastly I added a bit of Styling. I downloaded the Silverlight toolkit and took the SystemBrushes class from the SystemColor theme’s source code. Used various SystemBrushes’s Brush for styling the Menu and MenuItem.

The nice silverish background brush of the Menu is SystemBrushes.ButtonGradient

For the mouse hover effect where an highlight color (quickly but progressively) appears I finally took the time to use animation and view state. It proved to be real easy!

First I setup 2 states. One which progressively increased the opacity of the background control (PART_HighlightBg). The second state does nothing, in effect reverting the opacity change instantly. I could have used an animation too but I liked the shorter template and result is good too.

One of the pet project I am working on now is an installer application (in D!). One of the problem I need to solve is automatic archival of my files.

Well it turn out that MSBuild (the underlying build tool used by Visual Studio) is quite extensible. While I haven’t read anything which made me a MSBuild master yet, I found this library (msbuildtask) with plenty of MSBuild goodies (including a zip task).

And also a post on Bell Hall’s blog which explain how to take advantage of this task to zip your project output automatically.

Automated builds are one of the core fundamental musts for software development. However, your build doesn't just have to build the solution and execute your unit tests. For IronEditor, my build also creates two zip files. One zip is the output from the build for archiving purposes, the second is my deployment zip - the zip which actually gets pushed up to CodePlex containing only the files required by the application. In this post, I will cover how you can get MSBuild to zip your build output.

To use zipping functionality within your build scripts, you need to use the MSBuild Community Tasks which is a great collection of MSBuild extensions and a must if you are using MSBuild.

In order to zip your files, you need to specify which files you want to zip. In the script below, I create an ItemGroup called ZipFiles, this includes all the subdirectories (**) and files (*.*) from my Release directory which is my build output folder. I also specify that this group should not include any other zip files. I then create a Builds directory if it doesn't already exist. Finally, I use the Zip task, passing in my ZipFiles ItemGroup which the task uses to know which files to include.

The most important property is the WorkingDirectory, this is the root directory where all the files you want to exist live. If you don't have this set correctly, you will have the additional directories in your zip file which are navigated in order to get to your actual files and just looks rubbish.

My deployment zip also looks very similar and is executed after the above target. The only different is that I individually specify which files and directories to include. For some directories, such as Config, I still include all sub-directories and files it contains as they will all be relevant and required.

One thing which tripped me up was that while my ItemGroup was created within a target, it actually has global scope. As such, you need to call the two groups within the two different targets something different.

Once my script has executed, I have two zip files created - one containing everything, the other ready to be released on CodePlex.

Documentation

Well you also need to read about D language syntax! A web exhaustive description can be found there. I should say for such task I like to have a book. I bought this one (there are not that many! ^_^).

I bought the kindle version, then I though better of it (Kindle book are not good at being read back and forth and jumping chapter like crazy, as is needed in a learning process!) and then the paper back version! I left a bad comment because it didn’t answer the question how to compile the damn thing! (which, if you have read my D post so far, we figured out by now!) but I like it, sorry about the comment.

Ho, almost missed that, when you “installed” D (unzipped it!) you also installed the offline documentation! Check out (on your disk)

Statement of the day

Thanks to the paper version of the D language I was able to browse through all 350 pages of it in an hour (it’s just a book about syntax hey!). I discover a really interesting and innovative statement, a “using” on steroid, scope()

If there are multiple ScopeGuardStatements in a scope, they are executed in the reverse lexical order in which they appear. If any scope instances are to be destructed upon the close of the scope, they also are interleaved with the ScopeGuardStatements in the reverse lexical order in which they appear.

Unzip the latest version of DMD somewhere, you are done! Now that was easy.

And if you heard about DM / DMC, don’t worry about it. It was for D1, just ignore it.

2. IDE

Well, arguably you can go with the command line. The compiler flags and linker flags are simple enough. Yet I’m too spoiled by VS, I need my IDE! In fact, on the D2 page, following the Editor link on the left (in Tools), I found 3 which were attractive: D-IDE, Entice and Visual D.

D-IDE is cool because it’s C# but that’s about it (it’s still basic and buggy, sadly).

Entice is a GUI designer. It was exciting at first, but I deleted it in the end because it is used for DFL or DWT which both requires to overwrite the base runtime library (aka Phobos). Which I don’t quite feel like doing yet.

You can create a new module with Visual D (new D project), press F5, and voila, hello D world!

Now I wanted to create a GUI Hello world!

I had a look at DFL and DWT. DFL looks lighter / smaller and good enough for my need. Yet they both required Tango, which seem to be a popular D BCL (aka Phobos) replacement. Well that ended it for me. Tango might be popular but I’m not going to replace my BCL when I can’t even compile a(n advanced) program yet (you’ll see my library trouble next).

Finally I found DGui. Looking like WinForm. Depending just on Phobos (the BCL).

I downloaded, unzipped, copied a sample (in the sample directory) into my “hello.d” file and tried to compile.

Now the problems started…

First error would be:

Error 1 Error: module all is in file 'dgui\all.d' which cannot be read C:\Dev\DTest\DTest1\hello.d 3

This is due to the import statement at the top:

import dgui.all;

3.a. file and hierarchy structure

D has 2 ‘code unit’ if I may call it that way. Module and package. It’s a bit like classes and packages in Java. A module is everything in one file. I’m not yet sure if the module should be named after the file it’s in, but that, at least, seems to be the convention.

The package is a folder of source code.

When I wrote “import dgui.all” the compiler looked for the module “all” (i.e. the file “all.d”) in the package (i.e. directory) “dgui”.

I need to specify the search path for those modules / packages for this to work. Go to project properties => Configuration => DMD and add the path to the source of the library.

Press F5, now we get an other error! (i.e. we progressed!…)

3.b. declaration file

So, what’s going on? And why does it look for a ‘.d’ file (a source file! I want to use the library not recompile it!)

Here is what happen, the compiler needs some declaration to describe the function that are going to be called. They could be defined inline in the program (if calling into Win32 from D for example, much like DllImport in C#), but more generally you it will look at declaration file defined by the library. There are 2 options there:

Unlike C, where the developer should maintain and synchronise a definition (header / .h) and an implementation (.c /.cpp) file, D can use a single implementation file for both purpose. Hence it will look in the original D source file.

If there is a need to protect some intellectual property, the developer can an generate an ‘interface file’ when compiling (ordinary D file with the ‘.di’ extension and only declaration inside) and deploy these instead of the source code.

3.c. linking

Much like C, C++ and other native environment, compiling D is a 2 stage program. First compiling the source files into object files (.o) and then linking all those files into various target (library (.lib or .dll), executable (.exe)).

But it’s all done on the key stroke of F5, hence a catch all usage meaning of compile for both compiling (making object files) and linking (creating the final output).

'Symbol alien_looking_name’ generally mean a linker problem. It just happened that Visual D create a “buildlog.html” as well as a “$(project).build.cmd” file in the output folder. So you can see what command it ran to compile and the link the program.

Now I guess I need to include dgui.lib in my project. So go to project properties => linker and set the libraries and search path.

Now it still doesn’t compile and give me this warning:

Warning 1 Warning 2: File Not Found dgui.lib C:\Dev\DTest\DTest1\

I can see in the cmd file or build log that it build with the following command

Now I can see in D Linker’s documentation that DMD_LIB is not used, it is LIB that is used. I guess it’s a little bug with Visual D (maybe it was made for D1?) at any rate, I solved it by setting the whole path to the DGui library!

F5… build succeeded!

4. Bonus, compile DGui

Well, one could add all the file of DGui in Visual D I guess. But DGui comes with a “dgui_build_rel.bat”, I should use it, don’t you think?

Well all I had to do was to add the path to dmd.exe (i.e. C:\D\dmd2\windows\bin\) to the PATH environment variable.

As found in System Property => Advance System Settings => Advanced => Environment Variables…

Now I can just click on the bat file and… DGui build successfully, that was easy!

5. Done

That’s it, I show how to install D, install a library and compile a program using it!

Recently I had Visual Studio freezing every time I opened some project. A coworker had it crash. After some digging I thought of disabling VS start-up Add-In.

There are so many of them, as you can see in the registry at: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Packages

Anyway, there is no easy way to enable / disable them on an individual basis, but you could just disable them all.

Go to the Tools menu then Options:

Then go to Environment / Add-In and uncheck "Allow Add-in components to load"

To be honest I have no clue what are all the add-in so disabled, but I haven't noticed any missing feature. On the other hand I did notice big improvements, such as much faster VS startup and no slow or crashing start-up.

Later I discover another “trick” to reset Visual Studio to an almost pristine state. It’s not uninstall/reinstall which not only tool a lot of time but leave all the plugin/add-ons/etc… in place.

It’s resetting VS settings. Just in case you better save your settings before resetting them as well!