Difference between revisions of "Creating pattern editor view using WPF and managed C++"

From Jeskola Buzz Wiki
Jump to: navigation, search
(Gui.h)
(Reminded people that there some requirements needed by the user: (XP+ and .NET 3.0))
 
Line 9: Line 9:
 
* Use WPF to create rich user interfaces
 
* Use WPF to create rich user interfaces
 
* You can use Visual C++ Express Edition to create a Buzz machine
 
* You can use Visual C++ Express Edition to create a Buzz machine
 +
 +
Please be aware that the users must have:
 +
* Windows XP or later
 +
* .NET 3.0 or later
  
 
== Source and resource files ==
 
== Source and resource files ==

Latest revision as of 14:15, 15 August 2009

Introduction

This is a very simple example how to create a machine with pattern editor view using WPF and managed C++. Thanks to Antonio who created an example project file.

Some benefits using managed C++ to create UI

  • Managed and unmanaged code can be mixed together
  • Communicate with .NET framework and components
  • Use WPF to create rich user interfaces
  • You can use Visual C++ Express Edition to create a Buzz machine

Please be aware that the users must have:

  • Windows XP or later
  • .NET 3.0 or later

Source and resource files

PianoRoll.xaml

 <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
     <Grid Margin="0,0,0,0">
 
         <Canvas x:Name="PianoKeysCanvas" Width="300" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,0,0,21">            
         </Canvas>
         
         <Canvas Margin="300,1,0,24" Name="noteCanvas" HorizontalAlignment="Stretch" Width="Auto">
             <Border BorderBrush="Black" BorderThickness="1">
             </Border>
         </Canvas>
         <ScrollBar Height="19" HorizontalAlignment="Left" Name="scrollBar2" VerticalAlignment="Bottom" Orientation="Horizontal" Margin="0,0,0,0"/>
         <ScrollBar HorizontalAlignment="right" Name="scrollBar1" Width="17" Margin="0,0,0,21" />
     </Grid>
 </UserControl>

Gui.h

 #pragma once
 
 #include <windows.h>
 #include <vcclr.h>
 #include <math.h>
 
 using namespace System;
 using namespace System::Windows::Controls;
 using namespace System::Windows::Threading;
 using namespace System::Windows::Interop;
 
 using namespace System::Windows::Media;
 using namespace System::Windows::Shapes;
 
 ref class ManagedGUI
 {
 public:
 	HwndSource ^HS;
 	UserControl ^Control;
 	int pianoKeyHeight;
 	double xScale, yScale;
 
 	ManagedGUI(UserControl ^uc)
 	{
 		Control = uc;
 		pianoKeyHeight = 30;
 		xScale = 1;
 		yScale = 1;
 
 		CreatePianoKeys();
 		CreatePianoGrid();
 	}
 
 	void CreatePianoKeys();
 
 	void CreatePianoGrid();
 
 	// RUNS IN AUDIO THREAD
 	// Don't modify the manged gui directly from audio thread. Send a notification etc.
 	void BuzzTick()
 	{
 	}  
 };
 
 
 class GUI
 {
 public:
 	gcroot<ManagedGUI ^> MGUI;
 	HWND Window;
 };
 
 extern void CreateGUI(GUI &gui, HWND parent);

Gui.cpp

Creates the piano keys dynamically manipulating WPF GUI.

 #include <windows.h>
 #include "gui.h"
 
 using namespace System;
 using namespace System::IO;
 using namespace System::Windows;
 using namespace System::Windows::Controls;
 using namespace System::Windows::Interop;
 using namespace System::Windows::Media;
 using namespace System::Windows::Markup;
 using namespace System::Windows::Threading;
 using namespace System::Runtime;
 using namespace System::Runtime::InteropServices;
 using namespace System::Reflection;
 using namespace System::Collections::Generic;
 using namespace System::Windows::Shapes;
 
 HINSTANCE g_hInstance;
 
 #pragma unmanaged
 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 {
 	g_hInstance = hModule;
     return TRUE;
 }
 #pragma managed
 
 
 LRESULT WINAPI WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
 	switch(message)
 	{
 	case WM_CREATE:
 		{
 			CREATESTRUCT *cs = (CREATESTRUCT *)lParam;
 			GUI *pgui = (GUI *)cs->lpCreateParams;
 			::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pgui);
 
 			System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters("sp");
 			sourceParams->ParentWindow = System::IntPtr(hwnd);
 			sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;
 		    System::Windows::Interop::HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
 			source->RootVisual = pgui->MGUI->Control;
 
 			pgui->MGUI->HS = source;			
 
 		}
 		break;
 
 	case WM_SIZE:
 		{
 			GUI *pgui = (GUI *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
 			pgui->MGUI->Control->Width = LOWORD(lParam);
 			pgui->MGUI->Control->Height = HIWORD(lParam);
 			return TRUE;
 		}
 		break;
 
 	case WM_DESTROY:
 		{
 			GUI *pgui = (GUI *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);			
 		}
 		break;
 
 	default:
 		return DefWindowProc (hwnd, message, wParam, lParam);
 		break;
 
 	}	
 	return 0;
 }
      
 void CreateGUI(GUI &gui, HWND parent)
 {
 	char mfn[_MAX_PATH];
 	GetModuleFileName(g_hInstance, mfn, _MAX_PATH);
 	char *pext = strstr(mfn, ".dll");
 	if (pext == NULL)
 		return;
  
 	strcpy_s(pext, 6, ".xaml");
 
 	String ^gfn;
 	gfn = Marshal::PtrToStringAnsi(System::IntPtr(mfn));
 
 	try
 	{
 		UserControl ^uc = (UserControl ^)XamlReader::Load(File::Open(gfn, FileMode::Open));
 		gui.MGUI = gcnew ManagedGUI(uc);
 	}
 	catch (Exception ^e)
 	{
 		System::Windows::MessageBox::Show(e->Message, gfn);
 		return;
 	}
 
 	static int count = 0;
 
 	if (!count++)
 	{
 		WNDCLASS windowClass;
 		windowClass.style = 0;
 		windowClass.lpfnWndProc = WindowProc;
 		windowClass.cbClsExtra = 0;
 		windowClass.cbWndExtra = 0;
 		windowClass.hInstance = (HINSTANCE)g_hInstance;
 		windowClass.hIcon = 0;
 		windowClass.hCursor = 0;
 		windowClass.hbrBackground = 0;
 		windowClass.lpszMenuName = 0;
 		windowClass.lpszClassName = "limiterwndcls";
 		RegisterClass (&windowClass);
 	}
 
 	try
 	{
 		gui.Window = CreateWindowEx (0, "limiterwndcls", "limiterwnd", WS_CHILD | WS_VISIBLE,0, 0, 1, (int)gui.MGUI->Control->Height, parent, NULL, (HINSTANCE)g_hInstance, &gui);
 
 	}
 	catch (System::Exception^ e)
 	{
 		System::Windows::MessageBox::Show(e->Message);
 	}
 
 }
 
 void ManagedGUI::CreatePianoKeys()
 {
 	System::Windows::Controls::Canvas ^pianoKeysCanvas = dynamic_cast<System::Windows::Controls::Canvas ^>(Control->FindName("PianoKeysCanvas"));
 	
 	int key8count = 0;
 
 	for (int i = 0; i < 127; i++)
 	{
 		int key8 = i % 12;
 		bool iskey8 = (key8 == 0) | (key8 == 2) | (key8 == 4) | (key8 == 6) | (key8 == 7) | (key8 == 9) | (key8 == 11);
 
 		if (iskey8)
 		{
 			System::Windows::Shapes::Rectangle ^keyRect;
 			keyRect = gcnew System::Windows::Shapes::Rectangle();
 			keyRect->Height = pianoKeyHeight;
 			keyRect->Width = 300;
 
 			keyRect->Stroke = gcnew SolidColorBrush(Colors::Black);
 			keyRect->Fill = gcnew SolidColorBrush(Colors::White);
 			
 			keyRect->SetValue(Canvas::TopProperty, (double)(key8count * pianoKeyHeight - 1) * yScale);
 			keyRect->SetValue(Canvas::LeftProperty, (double)0 * xScale);
 			keyRect->VerticalAlignment = VerticalAlignment::Top;
 			keyRect->HorizontalAlignment = HorizontalAlignment::Left;
 
 			pianoKeysCanvas->Children->Add(keyRect);
 			key8count++;
 		}
 	}
 
 	key8count = 0;
 
 	for (int i = 0; i < 127; i++)
 	{
 		int key8 = i % 12;
 		bool iskey8 = (key8 == 0) | (key8 == 2) | (key8 == 4) | (key8 == 6) | (key8 == 7) | (key8 == 9) | (key8 == 11);
 
 		if (!iskey8)
 		{
 			int blackHeight = pianoKeyHeight * 0.7;
 			System::Windows::Shapes::Rectangle ^keyRect;
 			keyRect = gcnew System::Windows::Shapes::Rectangle();
 			keyRect->Height = blackHeight;
 			keyRect->Width = 200;
 			keyRect->RadiusX = 4;
 			keyRect->RadiusY = 4;
 
 			keyRect->Stroke = gcnew SolidColorBrush(Colors::Black);
 			keyRect->Fill = gcnew SolidColorBrush(Colors::Black);
 			
 			keyRect->SetValue(Canvas::TopProperty, (double)((key8count * pianoKeyHeight - 1) - blackHeight/2) * yScale);
 			keyRect->SetValue(Canvas::LeftProperty, (double)-20 * xScale);
 			keyRect->VerticalAlignment = VerticalAlignment::Top;
 			keyRect->HorizontalAlignment = HorizontalAlignment::Left;
 
 			pianoKeysCanvas->Children->Add(keyRect);	
 		}
 		else
 		{
 			key8count++;
 		}
 	}
 }
 
 void ManagedGUI::CreatePianoGrid()
 {
 	System::Windows::Controls::Canvas ^pianoKeysCanvas = dynamic_cast<System::Windows::Controls::Canvas ^>(Control->FindName("noteCanvas"));
 	
 	int key8count = 0;
 
 	for (int i = 0; i < 127; i++)
 	{
 		int key8 = i % 12;
 		bool iskey8 = (key8 == 0) | (key8 == 2) | (key8 == 4) | (key8 == 6) | (key8 == 7) | (key8 == 9) | (key8 == 11);
 
 		if (iskey8)
 		{
 			System::Windows::Shapes::Rectangle ^keyRect;
 			keyRect = gcnew System::Windows::Shapes::Rectangle();
 			keyRect->Height = pianoKeyHeight/2;	
 			keyRect->Width = 1600;
 			keyRect->Margin.Bottom = 0;
 			keyRect->Margin.Top = 0;
 			keyRect->Margin.Left = 0;
 			keyRect->Margin.Right = 0;
 
 			keyRect->Stroke = gcnew SolidColorBrush(Colors::LightBlue);
 			keyRect->Fill = gcnew SolidColorBrush(Colors::White);
 			
 			keyRect->SetValue(Canvas::TopProperty, (double)(key8count * pianoKeyHeight - 1) * yScale);
 			keyRect->SetValue(Canvas::LeftProperty, (double)0 * xScale);
 			keyRect->VerticalAlignment = VerticalAlignment::Top;
 			keyRect->HorizontalAlignment = HorizontalAlignment::Left;
 
 			pianoKeysCanvas->Children->Add(keyRect);
 			key8count++;
 		}
 		else
 		{
 			System::Windows::Shapes::Rectangle ^keyRect;
 			keyRect = gcnew System::Windows::Shapes::Rectangle();
 			keyRect->Height = pianoKeyHeight/2;	
 			keyRect->Width = 1600;
 			keyRect->Margin.Bottom = 0;
 			keyRect->Margin.Top = 0;
 			keyRect->Margin.Left = 0;
 			keyRect->Margin.Right = 0;
 
 			keyRect->Stroke = gcnew SolidColorBrush(Colors::LightBlue);
 			keyRect->Fill = gcnew SolidColorBrush(Colors::LightGray);
 			
 			keyRect->SetValue(Canvas::TopProperty, (double)(key8count * pianoKeyHeight - 1 - pianoKeyHeight/2) * yScale);
 			keyRect->SetValue(Canvas::LeftProperty, (double)0 * xScale);
 			keyRect->VerticalAlignment = VerticalAlignment::Top;
 			keyRect->HorizontalAlignment = HorizontalAlignment::Left;
 
 			pianoKeysCanvas->Children->Add(keyRect);			
 		}
 	}
 
 	for (int i = 0; i < 100; i++)
 	{
 		int beat = i % 4;
 
 		if (beat == 0)
 		{
 			System::Windows::Shapes::Line ^keyLine;
 			keyLine = gcnew System::Windows::Shapes::Line();
 
 			keyLine->Stroke = gcnew SolidColorBrush(Colors::Brown);
 
 			keyLine->X1 = i * 30;
 			keyLine->Y1 = 0;
 			keyLine->X2 = i * 30;
 			keyLine->Y2 = 1000;
 						
 			pianoKeysCanvas->Children->Add(keyLine);
 		}
 		else
 		{
 			System::Windows::Shapes::Line ^keyLine;
 			keyLine = gcnew System::Windows::Shapes::Line();
 
 			keyLine->Stroke = gcnew SolidColorBrush(Colors::LightGray);
 
 			keyLine->X1 = i * 30;
 			keyLine->Y1 = 0;
 			keyLine->X2 = i * 30;
 			keyLine->Y2 = 1000;
 						
 			pianoKeysCanvas->Children->Add(keyLine);
 		}
 	}
 }

PianoRoll.cpp

Very light Buzz machine implementation. Does nothing.

 #define _USE_MATH_DEFINES
 
 #include <string.h>
 #include <stdlib.h>
 #include <assert.h>
 #include <math.h>
 #include "MachineInterface.h"
 #include "GUI.h"
 
 CMachineParameter const paraThreshold = { pt_byte, "Threshold", "Threshold", 0,	127, 255, MPF_STATE, 90 };
 
 CMachineParameter const *pParameters[] = { &paraThreshold };
 
 #pragma pack(1)		
 class gvals
 {
 public:
 	byte threshold;
 };
 #pragma pack()
 
 CMachineInfo const MacInfo = 
 {
 	MT_GENERATOR,								// type
 	MI_VERSION,	
 	MIF_PATTERN_EDITOR | MIF_PE_NO_CLIENT_EDGE | MIF_NO_OUTPUT | MIF_CONTROL_MACHINE,						// flags
 	0,										// min tracks
 	0,										// max tracks
 	1,										// numGlobalParameters
 	0,										// numTrackParameters
 	pParameters,
 	0,
 	NULL,
 #ifdef _DEBUG
 	"WDE PianoRoll (Debug build)",		// name
 #else
 	"WDE PianoRoll",					// name
 #endif
 	"PianoRoll",									// short name
 	"WDE",						// author
 	NULL
 };
 
 class mi;
 
 class miex : public CMachineInterfaceEx
 {
 public:
 	virtual void *CreatePatternEditor(void *parenthwnd);
 
 	mi *pmi;
 };
 
 class mi : public CMachineInterface
 {
 public:
 	mi();
 	virtual ~mi();
 	virtual void Init(CMachineDataInput * const pi);
 	virtual void Tick();
 
 	miex ex;
 	GUI gui;
 	gvals gval;
 };
 
 void *miex::CreatePatternEditor(void *parenthwnd)
 {
 	pmi->gui.Window = 0;
 	CreateGUI(pmi->gui, (HWND)parenthwnd);
 	return pmi->gui.Window;
 }
 
 DLL_EXPORTS
 
 mi::mi()
 {
 	ex.pmi = this;
 	GlobalVals = &gval;
 	AttrVals = NULL;
 }
 
 mi::~mi()
 {
 }
 
 void mi::Init(CMachineDataInput * const pi)
 {
 	pCB->SetMachineInterfaceEx(&ex);
 
 	pCB->WriteLine("INIT");
 
 
 }
 
 void mi::Tick()
 {
 	// Example how to call a method from managed gui
 	gui.MGUI->BuzzTick();
 }

PianoRoll.vcproj

 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
 	Version="9,00"
 	Name="PianoRoll"
 	ProjectGUID="{B615CA66-0381-4E69-AF27-D8DE020E54A0}"
 	RootNamespace="Limiter"
 	Keyword="Win32Proj"
 	TargetFrameworkVersion="196613"
 	>
 	<Platforms>
 		<Platform
 			Name="Win32"
 		/>
 	</Platforms>
 	<ToolFiles>
 	</ToolFiles>
 	<Configurations>
 		<Configuration
 			Name="Debug|Win32"
 			OutputDirectory="C:\Program Files\Jeskola\Buzz\Gear\Effects"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
 			CharacterSet="0"
 			ManagedExtensions="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
 				CommandLine=""
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
 			/>
 			<Tool
 				Name="VCWebServiceProxyGeneratorTool"
 			/>
 			<Tool
 				Name="VCMIDLTool"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIMITER_EXPORTS"
 				MinimalRebuild="false"
 				BasicRuntimeChecks="0"
 				RuntimeLibrary="3"
 				StructMemberAlignment="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
 				DebugInformationFormat="3"
 				CallingConvention="0"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 			/>
 			<Tool
 				Name="VCResourceCompilerTool"
 			/>
 			<Tool
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
 				Name="VCLinkerTool"
 				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				AssemblyDebug="1"
 				SubSystem="2"
 				TargetMachine="1"
 			/>
 			<Tool
 				Name="VCALinkTool"
 			/>
 			<Tool
 				Name="VCManifestTool"
 			/>
 			<Tool
 				Name="VCXDCMakeTool"
 			/>
 			<Tool
 				Name="VCBscMakeTool"
 			/>
 			<Tool
 				Name="VCFxCopTool"
 			/>
 			<Tool
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
 				CommandLine="copy PianoRoll.xaml "C:\Program Files\Jeskola\Buzz\Gear\Effects\""
 			/>
 		</Configuration>
 		<Configuration
 			Name="Release|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
 			CharacterSet="0"
 			ManagedExtensions="1"
 			WholeProgramOptimization="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
 			/>
 			<Tool
 				Name="VCCustomBuildTool"
 			/>
 			<Tool
 				Name="VCXMLDataGeneratorTool"
 			/>
 			<Tool
 				Name="VCWebServiceProxyGeneratorTool"
 			/>
 			<Tool
 				Name="VCMIDLTool"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="2"
 				EnableIntrinsicFunctions="true"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIMITER_EXPORTS"
 				RuntimeLibrary="2"
 				BufferSecurityCheck="false"
 				EnableFunctionLevelLinking="true"
 				FloatingPointModel="2"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
 				DebugInformationFormat="3"
 				CallingConvention="0"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 			/>
 			<Tool
 				Name="VCResourceCompilerTool"
 			/>
 			<Tool
 				Name="VCPreLinkEventTool"
 			/>
 			<Tool
 				Name="VCLinkerTool"
 				OutputFile="h:\projects\buzz\rel\1.1\gear\effects\Jeskola Limiter.dll"
 				LinkIncremental="1"
 				GenerateDebugInformation="true"
 				SubSystem="2"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
 				TargetMachine="1"
 			/>
 			<Tool
 				Name="VCALinkTool"
 			/>
 			<Tool
 				Name="VCManifestTool"
 			/>
 			<Tool
 				Name="VCXDCMakeTool"
 			/>
 			<Tool
 				Name="VCBscMakeTool"
 			/>
 			<Tool
 				Name="VCFxCopTool"
 			/>
 			<Tool
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 	</Configurations>
 	<References>
 		<AssemblyReference
 			RelativePath="PresentationCore.dll"
 			AssemblyName="PresentationCore, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35, processorArchitecture=IA64"
 			MinFrameworkVersion="196608"
 		/>
 		<AssemblyReference
 			RelativePath="PresentationFramework.dll"
 			AssemblyName="PresentationFramework, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
 			MinFrameworkVersion="196608"
 		/>
 		<AssemblyReference
 			RelativePath="UIAutomationProvider.dll"
 			AssemblyName="UIAutomationProvider, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
 			MinFrameworkVersion="196608"
 		/>
 		<AssemblyReference
 			RelativePath="UIAutomationTypes.dll"
 			AssemblyName="UIAutomationTypes, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
 			MinFrameworkVersion="196608"
 		/>
 		<AssemblyReference
 			RelativePath="System.dll"
 			AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
 			MinFrameworkVersion="131072"
 		/>
 		<AssemblyReference
 			RelativePath="WindowsBase.dll"
 			AssemblyName="WindowsBase, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
 			MinFrameworkVersion="196608"
 		/>
 		<AssemblyReference
 			RelativePath="System.Data.dll"
 			AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
 			MinFrameworkVersion="131072"
 		/>
 		<AssemblyReference
 			RelativePath="System.Drawing.dll"
 			AssemblyName="System.Drawing, Version=2.0.0.0, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
 			MinFrameworkVersion="131072"
 		/>
 		<AssemblyReference
 			RelativePath="System.Windows.Forms.dll"
 			AssemblyName="System.Windows.Forms, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
 			MinFrameworkVersion="131072"
 		/>
 		<AssemblyReference
 			RelativePath="System.XML.dll"
 			AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
 			MinFrameworkVersion="131072"
 		/>
 	</References>
 	<Files>
 		<Filter
 			Name="Source Files"
 			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
 			<File
 				RelativePath=".\GUI.cpp"
 				>
 			</File>
 			<File
 				RelativePath=".\PianoRoll.cpp"
 				>
 			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
 			Filter="h;hpp;hxx;hm;inl;inc;xsd"
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
 			<File
 				RelativePath=".\GUI.h"
 				>
 			</File>
 		</Filter>
 		<Filter
 			Name="Resource Files"
 			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
 			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
 			>
 		</Filter>
 		<File
 			RelativePath=".\PianoRoll.xaml"
 			>
 		</File>
 		<File
 			RelativePath=".\ReadMe.txt"
 			>
 		</File>
 	</Files>
 	<Globals>
 	</Globals>
 </VisualStudioProject>


Final words

Thats it. Remember to copy the xaml file to the same folder where the machine dll is. Now go and explore WPF and .NET possibilities!