15

I have an app here I made for a client, but sometimes he doesn't know if an order has arrived because he plays World Of Warcraft with the volume max'd out. But he said he wants my little notification window to appear on top of his game if a new order arrives.

So, I was thinking I could just use BringToFront(); which seems to work when full-screen apps are Maximized. But, I have noticed that while playing V8 Supercars in full screen, BringToFront(); doesn't bring the notification window on top of the game, so I figure that some games have another way of making sure they remain on top of everything else.

How can I make sure that whenever I need my form to be seen, it will always show up on top of anything else?

R.J. Dunnill
  • 2,049
  • 3
  • 10
  • 21
bendr
  • 2,415
  • 6
  • 19
  • 24
  • 25
    seriously, his WoW affects him performing his business duties? I think I see the problem.... I'm not sure it is code-related... – Marc Gravell Jun 10 '11 at 07:22
  • 1
    @Paul in all seriousness, winforms is going to act in a different UI stack than the game. Maybe a second monitor would work... who knows. – Marc Gravell Jun 10 '11 at 07:28
  • I'm not sure if I shold post this as an answer, because I don't know if it works in every situation, however apparently this is used to keep Task Manager ontop of everything: *form1.TopMost = true;* - This is working with V8 Supercars. I'm not sure about WoW though. – bendr Jun 10 '11 at 07:29
  • @Marc, thanks. I wouldn't dare suggest he buy a new monitor. But, maybe if I tell him it would improve productivity while he plays WoW, and will increase his gaming experience (by having a full screen dedicated to his game) just maybe he might... – bendr Jun 10 '11 at 07:30
  • 1
    @Paul - the problem there is that then you need to know it works ;p i.e. will it continue showing winforms on the other monitor (changes between games, unfortunately). Plus there may be other hardware requirements. I don't think there is an easy answer here. – Marc Gravell Jun 10 '11 at 07:32
  • Yep. I get yah. Maybe I could kill the WoW process when a new order arrives – bendr Jun 10 '11 at 07:38
  • 4
    @Paul maybe code a WoW 'bot to come and tell him ;p Now I *bet* he'd pay for that! – Marc Gravell Jun 10 '11 at 07:39
  • "Make the window a "Top-Most" window. This is the way the Task-Manager can remain on top of other windows. This is a property of a Form and you make the form top-most (floating above other windows) by setting the value to true." - http://stackoverflow.com/questions/278237/keep-window-on-top-and-steal-focus-in-winforms - This seems to be the easiest [solution?] – bendr Jun 10 '11 at 07:41
  • 2
    Use FlashWindowEx and tell him to play in windowed (not fullscreen) mode. http://pietschsoft.com/post/2009/01/26/CSharp-Flash-Window-in-Taskbar-via-Win32-FlashWindowEx.aspx ... I wouldn't recommend that any program steal keyboard focus, it's just too easy to hit enter or space and fire off a default button handler. – overslacked Jun 10 '11 at 07:42
  • @Marc - That's an excellent idea. I'm excited! I think I will do that. – bendr Jun 10 '11 at 07:42
  • 1
    @Paul. Try it, however i'm not sure that'd work with full-screen DirectX games. – George Duckett Jun 10 '11 at 07:42
  • 2
    @Overslacked, agreed. Would be **far** simpler if it was a windowed game. – George Duckett Jun 10 '11 at 07:43
  • 1
    This isn't going to work, games get exclusive access to the video adapter when they run full-screen. If this is a real problem, hard to believe, then play a sound instead. – Hans Passant Jun 10 '11 at 07:43
  • @Hans Passant - tried that. He said that he never hears the sound while he's playing WoW. (Yes, this is a very real *problem*) - :-) Thanks for the suggestion. – bendr Jun 10 '11 at 07:46

7 Answers7

7
form.TopMost = true;
form.ShowDialog();
form.BringToFront();

Should work with all applications, full-screen exclusive games included (tested on all my games, so far, it works).

user703016
  • 37,307
  • 8
  • 87
  • 112
6

You could try setting the notification form's TopMost property to true...or make it modal by calling .ShowDialog instead of .Show.

alexD
  • 2,368
  • 2
  • 32
  • 43
  • Thank you @alexD - TopMost is working with my demo version of WoW. Now I must go and see if I can create that Order Notification Bot for WoW. Thanks for that @Marc. Geniusness! – bendr Jun 10 '11 at 07:56
4

I struggled with the same topic, especially when a "link" to a custom protocol was clicked in Outlook. (The App catched it, but always in the background...)

Even though a lot of solutions worked while debugging, for the "Live-Deployment" only the following chain of calls seems to achieve what was desired:

(Invoked, cause handling of links happens from a thread)

this.Invoke(new Action(() => {
  this.Activate();
  //...do stuff
  this.TopMost = true;
  this.BringToFront();
  this.TopMost = false;                              
}));

Works about every time.

dognose
  • 20,360
  • 9
  • 61
  • 107
  • 1
    This solution seems necessary if you don't want modal but require form.show() to actually result in the form being seen on top... seems like some framework bug related to these calls. – DAG Jul 03 '18 at 14:40
  • @DAG I'm not sure, if this is a bug. To me it seems pretty solid, that an application which is currently in the background shouldn't come to the front automatically, when a `form.Show()` is called. However since there are legit usecases for this, it would be nice if there was a native Support for this. for now, I have created an extension Method `ShowFront()` with above code and use it, whenever I want to ensure that shown windows come up from the background if the app has not the current focus. – dognose Jan 04 '22 at 10:08
2

Here's VB code that calls windows API functions, should be relatively easy to translate (note, this is untested, found on forums, also, you may have issues with the cursor appearing).

Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal _ hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _ ByVal cy As Long, ByVal wFlags As Long) As Long
Const HWND_TOPMOST = -1 
Const SWP_NOMOVE = &H2 
Const SWP_NOSIZE = &H1 
Private Sub Form_Load() 
    Call SetWindowPos(Form1.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE) 
End Sub

Create a timer with interval 1, with the following code:

Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long 
Private Declare Function GetForegroundWindow Lib "user32" () As Long 
Private Sub Timer1_Timer() 
    Dim mhwnd As Long 
    mhwnd = GetForegroundWindow SetParent Form1.hwnd, mhwnd 
End Sub

Code translated below (via automated tool):

const long HWND_TOPMOST = -1;
const long SWP_NOMOVE = 2;
const long SWP_NOSIZE = 1;

[DllImport("user32.dll")]
private static extern long SetWindowPos(long hwnd, long hWndInsertAfter, long X, long Y, long cx, long cy, long wFlags);

private void Form_Load() {
    SetWindowPos(Form1.hwnd, HWND_TOPMOST, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
}

[DllImport("user32.dll")]
private static extern long SetParent(long hWndChild, long hWndNewParent);

[DllImport("user32.dll")]
private static extern long GetForegroundWindow();

private void Timer1_Timer() {
    long mhwnd;
    mhwnd = GetForegroundWindow;
    SetParent;
    Form1.hwnd;
    mhwnd;
}
George Duckett
  • 31,770
  • 9
  • 95
  • 162
1

By default it will appear on top of screen but it is not model .

You can use Window.Show() method insted of closing the window change its visibility to False when it is not required. You might need to play with Parent Property of the child windows set it to main window

Dumb Code
  • 438
  • 3
  • 12
  • I'm not sure how this relates to the question (of getting rendered over WoW) – Marc Gravell Jun 10 '11 at 07:29
  • Thanks, @DumbCode, these are things that I am already using (should've put it in my question, sorry). But none of them (other than BringToFront();) bring the form to the front. Window.Show(); simply shows the window, I haven't seen it show it ontop of WoW yet. – bendr Jun 10 '11 at 07:34
  • 1
    If i can unterstand you might be looking for something like a model dialog which you want to appear on top of all windows regardress of whatever it is. [WPF Modal Dialog](http://www.codeproject.com/KB/WPF/wpfmodaldialog.aspx) correct me if i am wrong ? – Dumb Code Jun 10 '11 at 07:40
  • Um, that's what I want - however me and WPF don't seem to get along very well. It's not that we haven't tried, it's just... We're so busy all the time doing our own thing, and I just haven't had the time to invest in getting to know him. But thank you, I will keep that bookmarked for future reference for when I start using WPF. – bendr Jun 10 '11 at 07:52
0

You could try setting TopLevel = true, this brings the control forward. TopMost = true prevents any other contol getting focus, which is not always what you want.

Skyfish
  • 119
  • 2
  • 4
0

Using .NET 7 it works using only

this.Activate()