Create & use a WPF page with C++/CLR - wpf

I want to use C++/CLR to create a UI for my app. I need C++/CLR because I deal with a lot of native win32 C++ code. So I tried to make my app with the following steps, but they don't work:
Make an empty project
Unicode charset and enable /clr
Add refrences to PresentationCore, PresentationFramework, System, and WindowsBase
Add the App.xaml, App.xaml.h, MainWindow.xaml, MainWindow.xaml.h
Add the InitalizeComponent code to MainWindow.xaml.h (that
s where i'm having trouble.)
This is my mainwindow.xaml.h code
#pragma once
using namespace System::Windows;
using namespace System;
namespace Project2
{
public ref class MainWindow : Window
{
public:
MainWindow()
{
System::Uri ^resourceLocater = gcnew System::Uri("component\MainWindow.xaml", System::UriKind::Relative);
#line 1 "..\..\MainWindow.xaml"
System::Windows::Application::LoadComponent(this, resourceLocater);
}
};
}
My entry point code:
#include <Windows.h>
#include "App.xaml.h"
#include "MainWindow.xaml.h"
using namespace System;
using namespace System::Windows;
[STAThreadAttribute]
int WINAPI WinMain(HINSTANCE a, HINSTANCE b, LPSTR c, int d)
{
auto win = gcnew Project2::MainWindow();
auto app = gcnew Project2::App();
app->Run(win);
return 0;
}
And here's my app.xaml.h code:
#pragma once
using namespace System::Windows;
namespace Project2
{
public ref class App : Application
{
public:
};
}
The MainWindow.xaml and App.xaml all contain valid markup.
I tried chaning the values for the System::Uri resoucelocator but nothings chaning. I just get System.IO.IOException: The mainwindow.xaml was not found
Any ideas?

Related

Accessing WinForms member properties via delegates

I was somewhat surprised that can't easily access the properties of the WinForms class with functions you add as bublic, years ago with Borland VCL this wasn't an issue. Apparently 'delegates' is said to be the right keyword ... and I've been struggling with this for days now and can't get it to work. Is my approach beyond or is it just that the plug is not plugged in? Via the event handler, the forms property is successfully changed. Now i'm asking for a hint to transfer this capability down to sub1()?
#include "form1.h"
#include <Windows.h>
using namespace System;
using namespace System::Windows::Forms;
void sub1(void);
public delegate void Deleg(String^ st);
[STAThread]
void Main() // array<System::String^> ^args)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
App1::Form1 form;
Deleg^ Deleg1;
Application::Run(% form);
// Deleg1 += gcnew Deleg(form,&App1::Form1::newTxt); //?
}
void App1::Form1::button1_Click(System::Object^ s, System::EventArgs^ e)
{
String^ st = "ABC";
App1::Form1::newTxt(st);
Refresh();
sub1();
}
void sub1(void)
{
String^ s = "DEF";
// Deleg1(s);
}
I tried to copy some examples I found on the net, but apparently I don't hit the core.

A non-static member reference must be relative to a specific object

I'm trying to get the text in my textbox tb_key to write to my std::string Key Variable by doing this:
std::string Key = TRIPRECOILWARE::LoginForm::tb_key->Text;
I get an error saying :
A non-static member reference must be relative to a specific
object
I tried to search but I couldn't find anything really that fixed it for me.
Minimal Reproducible Example:
LoginForm.h
namespace TRIPRECOILWARE {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
private: System::Void tb_key_TextChanged(System::Object^ sender, System::EventArgs^ e)
{
}
}
LoginForm.cpp
std::string Key = TRIPRECOILWARE::LoginForm::tb_key->Text;
I'm trying to use this in LoginForm.h
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
if (Authenticate(StringToChar(Key), (StringToChar(hwid)))) // Authenticates key & hwid
{
this->Hide();
Software^ soft = gcnew Software();
soft->Show();
}
Basically, I want to get Key from Textbox called tb_key and write
it to my Key variable defined above. Then use that key to
authenticate and perform code
Your real problem is a duplicate of How to turn System::String^ into std::string?
Corrected code:
#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>
using namespace System;
using namespace msclr::interop;
void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
std::string Key = marshal_as<std::string>(tb_key->Text);
if (Authenticate(Key.c_str(), hwid.c_str())) // Authenticates key & hwid
{
Hide();
Software^ soft = gcnew Software();
soft->Show();
}
}

Fatal error c1001 when trying to make a GUI program in C++ CLR using .NET core in MSVS Enterprise 2019 16.4.6

I tried to make a C++ GUI program, i started with an empty project, and then add source file which is UI->windows form, and made a main function to call it. But when i tried to run it, it always shows this error
C1001 An internal error has occurred in the compiler
I also set the linker->system->subsystem into windows(/subsystem:windows)
and set entry point to my main function.
this is my main cpp file.
#include "MyForm.h"
using namespace Project1;
using namespace System::Windows::Forms;
using namespace System::Windows;
int main()
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Project1::MyForm form;
Application::Run(% form);
}
this is my header file(automaticaly created by VS)
#pragma once
namespace Project1 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for MyForm
/// </summary>
public ref class MyForm : public System::Windows::Forms::Form
{
public:
MyForm(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~MyForm()
{
if (components)
{
delete components;
}
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// MyForm
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(1089, 508);
this->Name = L"MyForm";
this->Text = L"MyForm";
this->ResumeLayout(false);
}
#pragma endregion
};
}
it has over 2k warning, i can't possibly put it all here

How to open MFC dialog from WPF application?

I have created dialog in .dll project. Now I want to open that dialog from WPF application by clicking on button. Following is the code for dialog:
TestDialog.h:
class CTestDialog : public CDialogEx
{
DECLARE_DYNAMIC(CTestDialog)
public:
CTestDialog(CWnd* pParent = NULL); // standard constructor
virtual ~CTestDialog();
// Dialog Data
enum { IDD = 1000 };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
};
TestDialog.cpp:
#include "stdafx.h"
#include "MFCDll.h"
#include "TestDialog.h"
#include "afxdialogex.h"
IMPLEMENT_DYNAMIC(CTestDialog, CDialogEx)
CTestDialog::CTestDialog(CWnd* pParent /*=NULL*/)
: CDialogEx(CTestDialog::IDD, pParent)
{
}
CTestDialog::~CTestDialog()
{
}
void CTestDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CTestDialog, CDialogEx)
END_MESSAGE_MAP()
I have created export function which create object of dialog and open that dialog by calling the DoModel() function.
extern "C" void PASCAL EXPORT ShowDialogFromDLL()
{
CTestDialog dlg;
theApp.m_pMainWnd = &dlg;
dlg.DoModal();
}
After that I am calling this export function from WPF form following is the code for WPF Form.
MainWindow.xaml.vb:
namespace MainApp
{
public partial class MainWindow : Window
{
[DllImport("MFCDll.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern void ShowDialogFromDLL();
public MainWindow()
{
InitializeComponent();
}
private void btnShow_Click(object sender, RoutedEventArgs e)
{
ShowDialogFromDLL();
}
}
}
But now when I call ShowDialogFromDLL(); after clicking button.It will throw me exception as
Microsoft Visual C++ Debug Library
Debug Assertion Failed!
Program: E:\EDR1\Test\MainApp\bin\Debug\MainApp.vshost.exe
File: f:\dd\vctools\vc7libs\ship\atlmfc\include\afxwin1.inl
Line: 24
For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
Above error is coming when I call dlg.DoModal(); method.
This should work -
extern "C" __declspec(dllexport) void __stdcall ShowDialogFromDLL()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
CTestDialog dlg;
dlg.DoModal();
}
When building a regular DLL that dynamically links to MFC, you need to use the macro AFX_MANAGE_STATE to switch the MFC module state correctly.

using DirectShow in Winforms

i could run the How To Play a File code sample in c++ win32 console application, but when i try to implement it by winforms i get these Link errors:
Error 2 error LNK2020: unresolved token (0A000016) IID_IMediaEvent
Error 3 error LNK2020: unresolved token (0A000017) IID_IMediaControl
and some more link errors .....
here is the code of the form:
#include <dshow.h>
#pragma comment(lib, "Strmiids.lib")
namespace Form1 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->SuspendLayout();
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(284, 262);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
this->ResumeLayout(false);
}
#pragma endregion
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
};
}
How can i setup the build environment in winforms to do the DirectShow programming?
im using windows SDK v7.1 And vc++ 2010
You are not getting a great diagnostic. The problem is that DirectShow is native code. But you are letting the compiler think it is okay to compile it in managed mode. Which works surprisingly well, until the linker takes a nosedive. You need to make it look like this:
#pragma once
#pragma managed(push, off)
#include <dshow.h>
#pragma managed(pop)
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "ole32.lib")
// etc..
This probably generates a flurry of errors. Right-click the project in the Solution Explorer window, Properties, Configuration Properties, General. Change Common Language Runtime support from /clr:pure to /clr. This played a sample .avi file properly when I tried it. In a DirectShow window, not the form. The sample code was designed only to work in a console application. You should also remove the calls to CoInitialize and CoUninitialize, .NET already initializes COM. Improving the error handling is advisable. Consider embedding Windows Media Player instead.

Resources