I need to integrate legacy MFC code into my C# .Net application.
To simulate my MFC code for the purpose of simplifying integration, I created a sample MFC Dialog application, with one button and one edit box. It writes Hello World into the edit box, when I click the button.
My goal is to make this callable from my .Net application. I will be happy if my .Net application can pop up the Dialog box, and have it print HelloWorld when I click the button. I have heard that C++/CLI is a good way to do this. If dynamic linking complicates the matter, I am ok with static linking too.
Firstly, I would like to know if this is even possible? I do not understand the process needed to accomplish this.
So far: I enabled the CLR support from Project properties, and created a C# WinForms application. I was able to add the MFC Dialog application as a reference to the C# WInforms application. But I am stuck at finding out how to export the dialog across the interface. Since, I am doing static linkage, do I still have to write dllexports for the dialog class? How do I export all of the dialog class, how will C# find the resource file that describes how the GUI is laid out for the Dialog?
The code for the dialog box is App Wizard generated, I just added an edit box and a button, and added a handler for the button that writes HelloWorld into the edit box.
To get a start, I tried creating another MFC application to see if I could at least call my MFC Dialog from another MFC application. In the consumer application, I added my Hello World Dialog app as a reference, and included the path to the Dialog header file. But it gave me error saying that IDD_DLG, which is the ID for my dialog was unidentified. So, I need to figure out how to supply with the resource file, where all the IDs are defined.
MFC Methods cannot directly be P/Invoked (see this SO Answer), what I have done to invoke a dialog box from another program is to create a DLL containing the dialog box, export a function which can invoke the dialog box and call the DLL function from an external application (e.g.: C#):
#include "stdafx.h"
#include "afxdialogex.h"
#include "MyDlg.h"
extern "C" __declspec (dllexport) BOOL ShowDlg()
{ AFX_MANAGE_STATE(AfxGetStaticModuleState());
CMyDlg dlg;
INT_PTR nResponse = dlg.DoModal();
return (nResponse == IDOK);
}
You could also add parameters to pass to/from the dialog box as required...
The keyword here is COM interoperability: Build a COM server (i.e. an ActiveX control) to call unmanaged code from managed code. This is the best way, in my opinion.
Related
Our company has a software in Alaska Xbase++. I want to modernize the GUI with WPF, without rewriting the software in C#. In this Alaska Xbase++ language, I have the ability to call C/C++ functions. I beleive, it is possible to create hybrid DLL, which has managed code, yet callable from unmanaged language, so doing a stdcall.
So my plan is that I write a wrapper DLL which manages all the things to create a WPF window and controls (and eventloop, everything). In this Alaska Xbase++ language I would call this wrapper DLL to create WPF window and controls in my Application.
For example:
-WpfWrapper.DLL In C# DLL (or application which listens data from Xbase++ app):
Function CreateWpfWindow(title) {..}
Function CreateWpfButton(caption, x, y, parent) {..}
C# DLL doing the "WPF things".
-In Alaska Xbase++ language I have a main window. But I want to modernize the GUI, I want to create some WPF window in that old Win32 app, so I call the DLL:
nHandle=CreateWpfWindow("My WPF window in Alaska Xbase++!")
CreateWpfButton("My button", 100, 100, nHandle)
This is just my thoughts.. Maybe there is other way. But I wonder is it possible to integrate IN ANY WAY WPF window and controls to an old Win32 Application? I beleive it does, either via some wrapper DLL or via some wrapper application.
Please give me some guidance how this could work. The created WPF window in my old app must be in focus, and above other windows. I have the HWND of my main window, I beleive it is neccesary.
I don't know what "Alaska Xbase++" is but my guess is the question you are asking is the reverse of what you should try. You shouldn't try to build a GUI application by calling into C# from some obscure programming environment. You should try to wrap your business logic, implemented in an obscure programming environment, in a DLL and call into that from C#.
Does Xbase++ expose a C interface?
If so make a custom DLL that calls your Xbase++ code and DllImport that DLL into a WPF application.
What I'm trying to do: receive messages of other process window (Spy++).
For example: I opened new notepad window: http://i.stack.imgur.com/vNg6h.png
And then I moved the mouse over the notepad window, the windows will send this message to the notepad window (or to the main window child window/s):
WM_MOUSEMOVE xPos=100,yPos=200
I want to receive this message exactly when then mouse event is happening (by event or while loop) (probably while loop with Application.doEvents() and Threading.Thread.Sleep(1)).
What I have tried:
create messages listener by the ManagedSpyLib (if you will import this library you can't compile your project... and if you will succeed to import this library it's not built for this mission)
I also searched about it and this is the most relevant result: http://www.codeproject.com/Articles/3923/InterSpy-An-integrated-Windows-message-trace-and-f
but this is a c++ project and I'm trying to do it in C# or VB.NET.
Good example is better than explanation for me. :)
The hooks that you need for this are WH_CALLWNDPROC and WH_GETMESSAGE. And these require DLL injection. You cannot inject managed code and so you will need to use unmanaged code for the hooking. You can then get your unmanaged injected DLL to communicate back to your C# application, but you will have to concede defeat on your attempts to write the hooking code in C#.
You need to look at the HOOK. That's how SPY++ works.
However, .Net is not very suitable for this, because you have to use a lot of WIN32 API functions.
We developped an MFC application where the main window was implemented in a DLL. In an attempt to revamp it, we are thinking of changing this to a WPF-application where the "old" native window gets rehosted in a Wpf-Window. So far so good.
However, our old MFC application trapped some messages at the application level (ex: preventing mouse-clicks or keyboard inputs). To rehost the MFC-window inside the WPF-application, we need a way to catch these from the WPF-application and ask the old MFC-window to pre-translate them...
Is this possible at all?
I was thinking of rehosting the MFC window in a HwndHost, then add a message hook. The code in my bridging CLR-DLL looks like this (and doesn't achieve what I want):
MyHwndHost ^handle = gcnew MyHwndHost(pContentWnd);
handle->MessageHook += gcnew HwndSourceHook(&CVSimCoreNat::ControlMsgFilter);
Can anyone help?
We have an old Windows 32 bit app written in C++ which does some stuff and displays the results in what resembles a textbox.
I have been ask to write an application in C# that reads the data out of the old app and then further process the data.
The issue is how do I read the textbox in the old application?
Someone told me I can get the “handle “of the application using windows API and step through the controls and then read each ones data! Is this true and if so how would I do it from C#?
This is to be a .Net 4 Windows forms Application.
Many thanks
You're probably going to have to use some Interop calls to accomplish this, specifically using a combination of FindWindow / FindWindowEx and SendMessage & WM_GETTEXT / WM_GETTEXTLENGTH.
Here is an article on the subject (in c++, however the same concepts will just need to be ported to use P/Invoke), it's a bit dated but I believe is should be very relevant to your situation.
You can use Spy++ application (comes with VisualStudio) to inspect your native application and find class name of control you are looking for.
Having that, you can get your native application's main window handle, which is easy if you are responsible for launching that application from your c# app:
...
var proc = Process.Start();
var mainWndHandle = proc.MainWindowHandle;
Otherwise, you will have to find other means of finding that window, fe. you can use function that I've described below to look for that window on your desktop (see msdn page for more info)
If you have all that, you can then get handle to the textbox control, using FindWindowEx function (as well as you can use it to find main window, by passing NULL as a hwndParent).
And when you have handle to this textbox, you can read it contents, by sending message of WM_GETTEXT.
If you haven't been PInvoke'ing much, you can check http://pinvoke.net/ for reference on how to call WINAPI function from your c# program.
Do you really need the UI of the C++ application? Because it will be very unconfortable to have 2 separate UIs with different message pumps. You'll need to syncronize this mess on the update of the value.
Why don't you properly strip the logic code from the C++ application and expose it in a Interop CLR project (C++/CLI)? If you don't need to add more features to the C++ app, it seems very straightforward to me
I am working with C# winforms Application i am dll in my project when call that function from that dll i get unwanted MessageBox from that .Is it possible to block that MessageBox?
If push comes to shove, you can fire up a thread that kills off any open windows by title using WinAPI or libraries.
I'd resort to less harsh mechanisms like changing the dll first or putting a change req to the right people.
There is no nice option to get rid of the message box if this is a third-party dll.
However, as C# is compiled to IL you can view the byte code and remove the call to MessageBox.Show or replace it with a call to Trace.WriteLine. You can do this e.g. using the ildasm.exe/ilasm.exe tools coming with the SDK.
You can study that dll with hex-editor, debugger or some resource viewer to find out how dialog box is created and then subscribe to that Windows event (Like OnCreate - surf WinAPI docs for info on Windows creation functions). In your event handler try to suppress dialog box and see if dll function is happy about the fact that dialog wasn't shown
If your dll is managed code you can decompile it and remove MessageBox call like 0xA3 suggested. If your dll is native you can use API hooking. Example of WinAPI hooking you can find here. It's in C++, but can be easily translated to C#.