5

What I'm trying to do is simple: make my WinForm on top of another, but not topmost. Like, when I click on a window, my winform will be on top of it, but when I click on something else, like a browser, my form will not be on top of it.

Like a TopMost WinForm, but only for a specific process. (Im making a overlay for a game, so I need it to be topmost ONLY on the game.)

Pictures to help (Everything inside the RED border is my form):enter image description here

And then when I change to another window (In this case, Explorer) I want my form to be in the background, just like the League of Legends cliententer image description here

Thiago Souza
  • 171
  • 3
  • 12
  • Just to be sure: I Want my WinForms application to be 'Docked' to another process (League of Legends) to create a custom interface. So that way, when I minimize or the game window is in background, my form would be on top of the game, but not the TopMost. – Thiago Souza Aug 27 '17 at 05:01

2 Answers2

8

Owned forms are always displayed on top of their owner form. To make a form owned by an owner, you can assign a reference of the owner form to Onwer property of the owned form, for example:

var f = new Form();
f.Owner = this;
f.Show();

Set a Window of another Process as Owner

To do so, you should first find the handle of window of the other process, then using SetWindowLong API function, you can set it as owner of your form, for example:

//using System.Runtime.InteropServices;
//using System.Diagnostics;

[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
private void button1_Click(object sender, EventArgs e)
{
    var notepad = Process.GetProcessesByName("notepad").FirstOrDefault();
    if(notepad!=null)
    {
        var owner = notepad.MainWindowHandle;
        var owned = this.Handle;
        var i = SetWindowLong(owned, -8 /*GWL_HWNDPARENT*/, owner);
    }
}

In above example, your form will be always on top of the notepad window.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • That should work with 2 forms, but its not my case. My program is a form, and I want it to be attached to a program which is not a WinForm. – Thiago Souza Aug 27 '17 at 04:55
  • Be advised, you are leavign safe code here, wich is the natural way to execute anything in .NET. It is quite possible to use unsafe code, but you run into all the hassles of the pre .NET world and the added problems at working across that important .NET Border. If this is a core feature, you might be better of using something more native (native C++) or any of the tricks to seperate the unsafe code out of your primary application (https://social.msdn.microsoft.com/Forums/vstudio/en-US/644c2f9c-f06a-496a-b497-6420a7919fdb/64-bit-app-calling-32-bit-dll?forum=csharpgeneral). – Christopher Aug 27 '17 at 05:19
  • @Christopher It's the way that setting `Owner` property works internally. Take a look at its [source code](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Form.cs,6c3819871d1e9085,references). – Reza Aghaei Aug 27 '17 at 05:22
  • @Reza Aghaei: I am talking about the 2nd part, where you use DLLImport to get unsafe, custom code to run. Their own implementation of owner proper they can mark as safe despite using the DLL, exactly *because* they do not allow this kind of thing. – Christopher Aug 27 '17 at 05:25
0

If it is a Form then you can open it as a modal dialogue with the following code:

    var modalForm = new Form();
    modalForm .ShowDialog();

ShowDialogue() will always open the form as a top Form from which it is created. But one problem is that you cannot perform any action to the parent form until you close the modal dialogue form.

Tanjeer
  • 89
  • 4
  • ShowDialog, blocks the window which is behind. Also OP is looking for a solution that can be used for window of another process as well. – Reza Aghaei Aug 27 '17 at 05:53