Windows Form as child window of an unmanaged app - c#

I am looking for a way to embed Windows Forms applications written in C# in a C++ windows application. The native application main window is subdivided into several panes. The C# app is supposed to appear within one of those panes, i.e. the root window of the C# component (the outermost form) must be a child window of the main application.
Can this be done? If so, how?
Some additional context: To my knowledge, there are two ways to go about this. First, host the CLR in the native app by using the .net hosting APIs (ICLRRuntimeHost, etc.). Second, host the CLR by putting the windows form in an ActiveX control.
Regarding the first approach, I have managed to get the CLR started up and to load a C# assembly (thanks largely to Mattias Högström). Where I am hitting a road block is that I see no way how to tell the component I am running in the CLR that it needs to be a child of a window passed in from the C++ side.
I have also experimented with the second method (using ActiveX and thanks to Daniel Yanovsky). It almost, but only almost, works for my purposes. I can let arbitrary Windows Forms components run in a child pane of the native app. BUT they always run on the main thread of the main app. This means they use the windows message loop of the main app. MSDN says this will not work reliably since the standard Windows message loops don't meet the requirements of Windows Forms (I wanted to post the link to MSDN here but have already used up my new-user-two-link-allotment).
The exceptions to the message loop issue are, according to MSDN, Internet Explorer and MFC apps. The native app I am using as a host is definitely not Internet Explorer. Also, it uses the windows API as wrapped by wxWidgets so MFC is not (or at least not a welcome) option.
The solutions Microsoft proposes involve letting the C# components run in their own message loops on their own threads. This, at least as far as I can tell, necessarily leads back to the first approach mentioned above. So I am back to the question of getting a Windows Form to work under a passed-in parent window.
Again, I am interested in any input that clarifies the child window issue, independent of the approaches I have mentioned here. But in light of the context I could reduce the general question to two specific questions (and I would need an answer to only one of them):
Given a Windows Form hosted in an ActiveX control, how can I allow the form to run in its own message loop on its own thread?
or
Given a Windows Form running in a CLR hosted by a native app, how can I make the form be a child window of a window in the native app?

yes, it can be done. We did the same thing years ago. This is our approach: .NET control also has native window handle, we get these handles through C++/CLI and pass them to Win32, and add these handles as the children of native windows. So the .NET controls run on the main thread of the main app, the problematic part is the message loop, as you have mentioned in your question. We need route the message between the nation and .NET windows if needed. As I remembered, we fixed a lot of bugs related to this, and still there were some mysterious problem we didn't figure out.
There's anothe way: using WPF interop. http://msdn.microsoft.com/en-us/library/ms742522.aspx . According to MS, this should fix the message problems, but we didn't try this approach. You can just use Win32 to host WPF, then use WPF to host Winform.
So for your last 2 questions:
You can't. Only one message loop.
Use handle. This article talks about the handle of Windows Forms: http://blogs.msdn.com/b/jfoscoding/archive/2004/11/24/269416.aspx

Related

How to obtain handle to notification window in Windows 10

I would like to obtain handle to notification window (balloon) using WinAPI. How can I do it, correctly?
Currently I found the solution by enumerating all windows using FindWindowEx function and then obtaining all windows that belongs to ShellExperienceHost.exe process. The operation is executed using GetWindowThreadProcessId API call.
After that we are limited to five windows and one of that window is notification window. But, the only parameter I can base on is window name. In this certain case it is "New notification". However, for my native language it is "Nowe powiadomienie". The application I am currently working on, needs to support multiple language. So, creating set with the names is not good options. Because, the code will be difficult to maintenance and can be depend on further changes in Windows.
I will be grateful for any help in this area.

Implementing separate application instances in taskbar like Skype

I noticed for a few updates of Skype now that if you start 2 or 3 instances of Skype, in the windows taskbar they appear as separate windows and you can drag them individually as opposed to other applications when they are "glued" together and you can drag them all at once.
My question is how can I implement the individual appearance in my application and is it possible from C# or through winapi?
The shell groups windows in the taskbar using each window's Application User Model ID (AppUserModelID).
By default, every window generated by a given EXE (even in different processes) shares a system-generated AppUserModelID.
You can give each process its own AppUserModelID by calling SetCurrentProcessExplicitAppUserModelID. From your description this is probably what Skype is doing, though I haven't checked.
You can give each window its own AppUserModelID by setting a different PKEY_AppUserModel_ID property on the windows.
Note that these IDs are required to have a particular format:
CompanyName.ProductName.SubProduct.VersionInformation
Raymond Chen wrote an article about this, and it's also worth reading the documentation I linked to.
I'm not aware of WinForms having explicit support for this, but you could certainly use interop to call the Win32 API directly.

Issue with the window focus in WinRT

I've got an issue with the focus management in WinRT. The issue is specific for the application startup. Let me share the example of it:
If during the startup I change the focus (for instance I can start selecting some text in a browser), the runtime will decide that it doesn't need to show the application. The application is being started in a 'hidden mode'. It means that I do not see the UI, but I still can find it in process explorer.
So what I need here is to make the application be active in all possible cases. I tried to use several native functions such as ShowWindow, SetActiveWindow, SetForegroundWindow, but without any success.
I also noticed that any WinRT app is being started under WWAHOST.exe and mainwindowhandle is 0. The app shows up if I use 'Switch to' option in Process Explorer context menu.
WinRT applications are sandboxed and have very little control on the way the OS handles them, and almost no way to affect the behavior of other applications running on the same host. What I would suggest then is for you to design your application in such a way that it shows some UI as early as possible, then asynchronously you can load any other resources that your application may need.

C# PInvoke and QWidget

I have an application that I am trying to automate on Windows. I need to find the location of a window that is running inside the application, and then automate a couple of mouse events on the application.
In a previous incarnation of the software that I am automating, I was able to search for child windows of the process which were named using the GetWindowText WinAPI function from C# (in combination with GetWindowTextLength).
The software manufacturers have now updated the software and updated the way that the child windows are drawn. Now each window lacks a caption, and has a class name of QWidget. I can no longer use my old strategy to find the child window location. I presume the use of QWidget means the windowing system uses the Qt framework.
Is there any way of pulling any data from the QWidget using PInvoke that I might be able to identify my windows with?
There's a couple problems here. One is that you can't get "unshared" data from another process. You can get at window data by pinvoking methods like GetWindowLong; but unless you know specific data about what QWidget does in that data (the other problem), there's not much you can do with the data.
Another problem is if you want to use most QT objects in a managed application (you can do this with C++/CLI and IJW) you need to initialize A QT Application object in your application... I'm not sure how this would impact what you want to do.

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

Categories