Hello all,

I have a winforms application that opens other applications such as firefox and adobe reader. The application will reside on a system with 4 monitors. I know how to open forms to other monitors, but am struggling with how to control where Process.Start() opens new applications. I've looked into ProcessStartInfo and command line arguments but can't seem to get anything to work.

Any ideas?

Thanks!
ntabb

Recommended Answers

All 5 Replies

The application dictates where the form is drawn. When the window handle is created the app can change the boundaries/location. You could find the window handle(s) from the process you started and send a message forcing the window to be repositioned:

using System.Runtime.InteropServices;
...
[DllImport("user32.dll")]
        public static extern int FindWindow(string lpClassName, string lpWindowName);
 

[DllImport("user32.dll")]
        public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
 

[DllImport("User32.dll", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);

...

      public const int WM_COMMAND = 0x0112;
      public const int WM_CLOSE = 0xF060;

...

private void Form1_Load(object sender, EventArgs e)
        {
            this.button1.Text = "Get Window";
            
            this.Text = "DevAsp Application Controller";
 

            this.button1.Text = "Move";
 

            this.textBox1.Text = "Notepad";
 

            this.textBox2.Text = "Untitled - Notepad";
 

            label1.Text = "Class Name";
            label2.Text = "Window Text";
            label3.Text = "Move along X-axis";
            label4.Text = "Move along Y-axis";
        }

private void button1_Click(object sender, EventArgs e)
        {
            handle = FindWindow(textBox1.Text, textBox2.Text);
        }
Now write code on track bar scroll event
 

private void trackBar1_Scroll(object sender, EventArgs e)
        {
            MoveWindow((IntPtr)handle, (trackBar1.Value*80), 20 , (trackBar1.Value*80)-800, 120, true);
            
        }
 

        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            MoveWindow((IntPtr)handle, 40, (trackBar2.Value * 100), 240, (trackBar2.Value * 100)+200, true);        }
        }

Borrowed from:
http://www.devasp.net/net/articles/display/689.html

sksnake,

Thanks for the help! I could not get the findWindow() method to work, but I was able to use the GetForegroundWindow() to grab the newly opened window and move it.

However, when the window is moved, the content is redrawn perfectly but the actual window is incorrectly shaded, minimize and maximize buttons don't work, and you can't resize the application with the mouse. I thought this may be a Visual Studio issue, but I compiled, packaged, and installed but the problem remains. I also tried UpdateWindow(IntPtr hWnd) but to no avail.

Have you seen this before?

Thanks!
ntabb

No I haven't seen this before, but I haven't read about or tried this before either. Can you post the code you're using?

No I haven't seen this before, but I haven't read about or tried this before either. Can you post the code you're using?

Here's what I've got:

[DllImport("user32.dll")]
        public static extern int FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll")]
        public static extern int GetTopWindow();
        [DllImport("user32.dll")]
        public static extern bool UpdateWindow(IntPtr hWnd);
        [DllImport("user32.dll")]
        public static extern int GetForegroundWindow();
        [DllImport("user32.dll")]
        public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
        [DllImport("User32.dll", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);

        public const int WM_COMMAND = 0x0112;
        public const int WM_CLOSE = 0xF060;
int screenIndex = 1;
                Screen[] screens = Screen.AllScreens;
                Process MCProcess = new Process();

                MCProcess.StartInfo.FileName = lblFolderPath.Text + "\\" + listView3.Items[0].Text;

                MCProcess.Start();

                System.Threading.Thread.Sleep(500);

                handle = GetForegroundWindow();

                MoveWindow(
                    (IntPtr)handle,
                    screens[screenIndex].Bounds.Left + 10,
                    screens[screenIndex].Bounds.Top + 10,
                    1260,
                    1004,
                    true
                    );

I've also posted screenshots of the abnormal window appearance and behavior.

Normal window
Abnormal window after move and resize

Thanks!
ntabb

See if something like this works:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace daniweb
{
  public partial class frmMoveWindow : Form
  {
    public frmMoveWindow()
    {
      InitializeComponent();
    }

    [DllImport("user32.dll")]
    public static extern int FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll")]
    public static extern int GetTopWindow();
    [DllImport("user32.dll")]
    public static extern bool UpdateWindow(IntPtr hWnd);
    [DllImport("user32.dll")]
    public static extern int GetForegroundWindow();
    [DllImport("user32.dll")]
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
    [DllImport("User32.dll", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
    
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool IsWindowVisible(IntPtr hWnd);

    public const int WM_COMMAND = 0x0112;
    public const int WM_CLOSE = 0xF060;

    private void button1_Click(object sender, EventArgs e)
    {
      const string fName = @"C:\dotnetwin\daniweb.vb\bin\Debug\daniweb.vb.exe";
      new Action<string>(Start).BeginInvoke(fName, new AsyncCallback(StartCallback), null);
    }

    private static void Start(string fName)
    {
      const int MAX_WAIT = 200;
      int counter = 0;
      using (Process p = Process.Start(fName))
      {
        while ((p.MainWindowHandle == IntPtr.Zero) || !IsWindowVisible(p.MainWindowHandle))
        {
          System.Threading.Thread.Sleep(10);
          p.Refresh();
          counter++;
          if (counter > MAX_WAIT)
            return;
        }
        p.WaitForInputIdle(10000);
        MoveWindow(p.MainWindowHandle, 0, 0, 400, 400, true);
      }
    }
    private static void StartCallback(IAsyncResult ar)
    {
      System.Runtime.Remoting.Messaging.AsyncResult result = (System.Runtime.Remoting.Messaging.AsyncResult)ar;
      Action<string> del = (Action<string>)result.AsyncDelegate;
      try
      {
        del.EndInvoke(ar);
      }
      catch { }
    }

  }
}

This uses the main window handle from the process that you started which should be a little more accurate. Sometimes when you start up browsers you have a delay but I don't really know how you want to handle that. This should allow the window to show and start pumping messages before you move it, but that in turn causes a screen flicker.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.