PreTranslateMessage in C# for hosted MFC window - c#

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?

Related

Can I use WPF in win32 application?

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.

Receive messages of other window

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.

Getting events of another application

In my c# application I need to detect when a user clicks one of two buttons in a different, third party application.
I am able to get the Handle of the application but the MainWindowHandle returns 0.
I tried WndProc but for some reason the event will not fire in my application.
How can I get/intercept the button click event from that application into mine?
Global system hooks allow an application to intercept Windows messages intended for other applications. This has always been difficult to implement in C#. This project on Codeplex attempts to implement global system hooks by creating a DLL wrapper in C++ that posts messages to the hooking application's message queue. Put simply, this lets you implement any type of global Windows hook from managed code: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx

Read a non C# Apps textbox using windows API from a C# Windows forms App

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

How can I embed an unmanaged C++ form into a .NET application?

I have been able to successfully wrap my unmanaged Borland C++ dll, and launch it's forms from a C# .NET 4.0 application. Is it possible to embed a form from the dll directly into a .NET application?
To clarify, the original form is being used as an embedded control in a Borland C++ project already. It essentially looks like a custom control, sitting on a panel within the application.
When I say 'embed' I mean place INTO a form in the same way you drop buttons, panels, etc on to a form. I'm not looking to just make a child form.
If this is not possible, then perhaps a better question would be how do I embed an unmanged custom control into a .Net application?
Yes, you just need to use some low-level win32 functions from user32.dll : SetParent, GetWindowLog, SetWindowLong , MoveWindow . You can create an empty .NET container control, set the parent of the native window to the .NET control, then (optionally) modify the window style (i.e. to remove borders of native window), and pay attention to resize it together with the .NET control. Note that, at a managed level, the .NET control will be unaware it has any children.
In the .NET control do something like
public void AddNativeChildWindow(IntPtr hWndChild){
//adjust window style of child in case it is a top-level window
int iStyle = GetWindowLong(hWndChild, GWL_STYLE);
iStyle = iStyle & (int)(~(WS_OVERLAPPEDWINDOW | WS_POPUP));
iStyle = iStyle | WS_CHILD;
SetWindowLong(hWndChild, GWL_STYLE, iStyle);
//let the .NET control be the parent of the native window
SetParent((IntPtr)hWndChild, this.Handle);
this._childHandle=hWndChild;
// just for fun, send an appropriate message to the .NET control
SendMessage(this.Handle, WM_PARENTNOTIFY, (IntPtr)1, (IntPtr)hWndChild);
}
Then override the WndProc of the .NET control to make it resize the native form appropriately -- for example to fill the client area.
protected override unsafe void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_PARENTNOTIFY:
//... maybe change the border styles , etc
break;
case WM_SIZE:
iWid =(int)( (int)m.LParam & 0xFFFF);
iHei= (int) (m.LParam) >> 16;
if (_childHandle != (IntPtr)0)
{
MoveWindow(_childHandle, 0, 0, iWid, iHei, true);
}
break;
}
}
Note I wrote this response assuming that the OP wanted to literally embed the native DLL containing the form in the .NET app, not just modify the way in which it's displayed.
In short, no. You'll need to package the C++ DLL with your distribution and import/wrap its functions the same way that you're doing now.
I seem to recall from my Delphi (which uses the same compiler back-end as Borland C++) days that the form designer generates C++ code which creates a winproc/message loop, etc for each of the assets in the form via with Win32 API.
Since all of that code is unmanaged, it can't be compiled into a managed assembly. You could port it to managed C++, but that would kill most of the benefit of having it in C++ to start with, and you're stuck with a crappy exception model and all of the other wonderful parts of C++. In that case, you'd probably be better off just rewriting it in C#.
But, since this is software, and almost anything is possible, here's a really lame solution: embed the DLL as a binary resource in your .NET app and, at run time, pull its contents into a binary stream, save it to disk and then load it (I'm not sure if there is a way to execute an unmanaged DLL from memory, other than cheating by putting it on a RAM disk).
The only thing this gets you is the ability to hide the DLL, but I really don't see the point.
Edit
Do you mean embed as in show as a child window, or embed as in place the code within the .NET project?

Categories