How to give MessageBox.Show() focus?

I

inhahe

I have the following code

---
using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class cl {
static public void Main() {
byte[] byteReadStream = null;
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 213);
TcpListener tcpl = new TcpListener(ipe);
while(true) {
tcpl.Start();
TcpClient tcpc = tcpl.AcceptTcpClient();
byteReadStream = new byte[tcpc.Available];
tcpc.GetStream().Read(byteReadStream, 0, tcpc.Available);
MessageBox.Show (Encoding.Default.GetString(byteReadStream)); } } }
---

you send it a line on port 213 and it pops up a window showing the
message.
the problem is the message comes up behind other windows. since
MessagBox.Show() is a static method and i don't know how to get an
object for it i can't do .Focus() on it.
i thought of doing .Focus() on the whole app too but i dunno how do to
do that either.
 
P

Peter Duniho

inhahe said:
[...]
you send it a line on port 213 and it pops up a window showing the
message.
the problem is the message comes up behind other windows. since
MessagBox.Show() is a static method and i don't know how to get an
object for it i can't do .Focus() on it.
i thought of doing .Focus() on the whole app too but i dunno how do to
do that either.

If the application is not currently the active application (and if it
has no window visible, it very likely isn't), it cannot force itself to
the foreground. This is by design, specifically to prevent one process
from stealing focus from the current foreground application.

You can look into using the notification tray for this sort of thing, or
you can live with the behavior.

Pete
 
K

kndg

inhahe said:
I have the following code

---
using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class cl {
static public void Main() {
byte[] byteReadStream = null;
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 213);
TcpListener tcpl = new TcpListener(ipe);
while(true) {
tcpl.Start();
TcpClient tcpc = tcpl.AcceptTcpClient();
byteReadStream = new byte[tcpc.Available];
tcpc.GetStream().Read(byteReadStream, 0, tcpc.Available);
MessageBox.Show (Encoding.Default.GetString(byteReadStream)); } } }
---

you send it a line on port 213 and it pops up a window showing the
message.
the problem is the message comes up behind other windows. since
MessagBox.Show() is a static method and i don't know how to get an
object for it i can't do .Focus() on it.
i thought of doing .Focus() on the whole app too but i dunno how do to
do that either.

Hi,

My solution is to create a custom form instead. See if below code works
for you.

public class MainForm : Form
{
private static MainForm thisForm = new MainForm();
private Label label;

public string Message
{
get { return label.Text; }
set { label.Text = value; }
}

private MainForm()
{
label = new Label();
label.Dock = DockStyle.Fill;

Controls.Add(label);
}

public static void ShowMessage(string message)
{
thisForm.TopMost = true;
thisForm.Message = message;
thisForm.ShowDialog();
}
}

Then, change MessageBox.Show() to MainForm.ShowMessage().

Regards.
 
I

inhahe

inhahe said:
I have the following code
---
using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class cl {
static public void Main() {
byte[] byteReadStream = null;
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 213);
TcpListener tcpl = new TcpListener(ipe);
while(true) {
tcpl.Start();
TcpClient tcpc = tcpl.AcceptTcpClient();
byteReadStream = new byte[tcpc.Available];
tcpc.GetStream().Read(byteReadStream, 0, tcpc.Available);
MessageBox.Show (Encoding.Default.GetString(byteReadStream)); } } }
---
you send it a line on port 213 and it pops up a window showing the
message.
the problem is the message comes up behind other windows. since
MessagBox.Show() is a static method and i don't know how to get an
object for it i can't do .Focus() on it.
i thought of doing .Focus() on the whole app too but i dunno how do to
do that either.

Hi,

My solution is to create a custom form instead. See if below code works
for you.

public class MainForm : Form
{
   private static MainForm thisForm = new MainForm();
   private Label label;

   public string Message
   {
     get { return label.Text; }
     set { label.Text = value; }
   }

   private MainForm()
   {
     label = new Label();
     label.Dock = DockStyle.Fill;

     Controls.Add(label);
   }

   public static void ShowMessage(string message)
   {
     thisForm.TopMost = true;
     thisForm.Message = message;
     thisForm.ShowDialog();
   }

}

Then, change MessageBox.Show() to MainForm.ShowMessage().

Regards.

It still pops up behind other apps.
I changed the class to:

public class MainForm : Form
{
private static MainForm thisForm = new MainForm();
private Label label;
public string Message
{
get { return label.Text; }
set { label.Text = value; }
}
private MainForm()
{
label = new Label();
label.Dock = DockStyle.Fill;
Controls.Add(label);
}
public static void ShowMessage(string message, string title)
{
thisForm.Text = title;
thisForm.TopMost = true;
thisForm.Message = message;
thisForm.ShowDialog();
thisForm.BringToFront();
}
}

(mainly I just added .BringToFront())

and it still doesn't fix the problem

this is windows 7, btw.
 
P

Peter Duniho

inhahe said:
[...]
It still pops up behind other apps.

Like I said, you can't force your window to the front if your
application isn't already the foreground application.
 
I

inhahe

inhahe said:
[...]
It still pops up behind other apps.

Like I said, you can't force your window to the front if your
application isn't already the foreground application.

oh, i completely missed your message, sorry

when someone IMs you in AIM, a new window pops up into the foreground,
even if aim isn't active and even if it's minimized to the system tray
(and i like it that way). so i know it's possible... does that just
mean .net is crippled and i have to use MFC or something?
 
P

Peter Duniho

inhahe said:
[...]
when someone IMs you in AIM, a new window pops up into the foreground,
even if aim isn't active and even if it's minimized to the system tray
(and i like it that way). so i know it's possible... does that just
mean .net is crippled and i have to use MFC or something?

No, .NET isn't crippled. It mean those applications are using a
different mechanism to display their notification. I.e. the
notification area.

I don't recall if .NET has support specifically for the notification
area, other than the System.Windows.Forms.NotifyIcon class. It's not
something I use myself, so my knowledge on the specifics is limited.
You'll have to do some research on your own to see.

If not, then for sure you can use the unmanaged notification area API in
Windows to do what you want.

The important thing to keep in mind that is that Windows has very
specific rules about what windows can be displayed where, and a
fundamental rule is that without going through "the proper channels"
(i.e. the notification area), your process is not to force itself to the
foreground (note that even in the notification area example, the window
displayed does _not_ have focus...in may be on top, but it doesn't
change what the foreground application or window is).

Pete
 
K

kndg

inhahe said:
[...]
It still pops up behind other apps.
I changed the class to:
[...]
(mainly I just added .BringToFront())

and it still doesn't fix the problem

this is windows 7, btw.

Hi,

I did a test and observed this behaviour. It didn't show up at the front
only for the first message (2nd message onwards will pop up at the
front). So, I did a quick hack -- show a dummy message and immediately
close it. Here is a complete solution. Please try if it works for you.

Server.cs --------------------------------------------------------------

using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class Server
{
static public void Main()
{
byte[] byteReadStream = null;
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 213);
TcpListener tcpl = new TcpListener(ipe);

MainForm.Init(); // <-- add a hack

while (true)
{
tcpl.Start();
TcpClient tcpc = tcpl.AcceptTcpClient();
byteReadStream = new byte[tcpc.Available];
tcpc.GetStream().Read(byteReadStream, 0, tcpc.Available);
//MessageBox.Show(Encoding.Default.GetString(byteReadStream));
MainForm.ShowMessage(Encoding.Default.GetString(byteReadStream));
}
}
}

public class MainForm : Form
{
private static MainForm thisForm = new MainForm();
private Label label;

public string Message
{
get { return label.Text; }
set { label.Text = value; }
}

private MainForm()
{
label = new Label();
label.Dock = DockStyle.Fill;

Controls.Add(label);
}

public static void Init()
{
thisForm.TopMost = true;
thisForm.Message = "Server Initializing...";
thisForm.Show();
thisForm.Hide();
}

public static void ShowMessage(string message)
{
thisForm.TopMost = true;
thisForm.Message = message;
thisForm.ShowDialog();
}
}

Client.cs --------------------------------------------------------------

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class Client
{
public static void Main(string[] args)
{
Console.Write("Message: ");
string message = Console.ReadLine();
SendMessage(message);
}

public static void SendMessage(string message)
{
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 213);
TcpClient client = new TcpClient();
client.Connect(ipe);

byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);

stream.Close();
client.Close();
}
}

It works on my system XP-SP3 + .NET3.5-SP1
Regards.
 
K

kndg

Alternatively, you can use P/Invoke to get the foreground window and
feed it to one of the MessageBox.Show() overloads.

server2.cs -------------------------------------------------------------

using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;

public class Server
{
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

public static void Main()
{
byte[] byteReadStream = null;
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 213);
TcpListener tcpl = new TcpListener(ipe);

while (true)
{
tcpl.Start();
TcpClient tcpc = tcpl.AcceptTcpClient();
byteReadStream = new byte[tcpc.Available];
tcpc.GetStream().Read(byteReadStream, 0, tcpc.Available);
IntPtr handle = GetForegroundWindow();
MessageBox.Show(new WindowWrapper(handle),
Encoding.Default.GetString(byteReadStream));
}
}
}

public class WindowWrapper : IWin32Window
{
private IntPtr handle;

public WindowWrapper(IntPtr handle)
{
this.handle = handle;
}

public IntPtr Handle
{
get { return handle; }
}
}

I don't know if this is a correct approach or not. I myself prefer a
custom form approach as I can customize how the message will be displayed.

Regards.
 
J

Jeff Johnson

The important thing to keep in mind that is that Windows has very specific
rules about what windows can be displayed where, and a fundamental rule is
that without going through "the proper channels" (i.e. the notification
area), your process is not to force itself to the foreground (note that
even in the notification area example, the window displayed does _not_
have focus...in may be on top, but it doesn't change what the foreground
application or window is).

There are evil ways to get around this, but they involve Windows API (i.e.,
P/Invoke) and are not directly supported by .NET. So no, inhahe, .NET does
not PROVIDE this to you (easily), but that does not mean it is "crippled."
Most of us welcome it. If Outlook Express were written in .NET, for example,
then the progress window wouldn't pop up at random while I'm doing other
things....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top