【问题标题】:Setting process window size and location before process.start()在 process.start() 之前设置进程窗口大小和位置
【发布时间】:2015-05-27 15:23:44
【问题描述】:

我正在使用一个表单来启动新的 Flash 进程,使用 Process.start() 和 MoveWindow() 来调整进程窗口的大小和位置。问题是在调用 MoveWindow() 之前,您可以在一瞬间看到默认大小和位置的窗口。我想知道是否有办法在实际进程开始之前设置窗口的位置和大小。

Process flash = new Process();
flash.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
flash.StartInfo.FileName = "C:\\RED\\bin\\android.swf";
flash.Start();
Thread.Sleep(300);
mainForm.MoveWindow(flash.MainWindowHandle, posX, 0, 1920, 1080, true);

【问题讨论】:

  • 可以从某个地方获取初始窗口大小。否则,唯一的选择就是像你一样做。提示:尝试显示最小化窗口并一起恢复/移动。
  • 您的提示部分有效,我正在使用 2 个屏幕并希望在每个屏幕上播放一个 Flash。使用最小化窗口并恢复它会导致窗口始终出现在主屏幕中。

标签: c# process


【解决方案1】:

使用CreateProcess。我同样需要为该职位创建另一个流程。

我已经定义了如下的 PInvoke。

public class Kernel32
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct STARTUPINFO
    {
        public uint cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct STARTUPINFOEX
    {
        public STARTUPINFO StartupInfo;
        public IntPtr lpAttributeList;
    }

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool CreateProcess(
       string lpApplicationName,
       string lpCommandLine,
       ref SECURITY_ATTRIBUTES lpProcessAttributes,
       ref SECURITY_ATTRIBUTES lpThreadAttributes,
       bool bInheritHandles,
       uint dwCreationFlags,
       IntPtr lpEnvironment,
       string lpCurrentDirectory,
       [In] ref STARTUPINFO lpStartupInfo,
       out PROCESS_INFORMATION lpProcessInformation);
}

并像下面这样使用它。

const uint NORMAL_PRIORITY_CLASS = 0x0020;
const uint CREATE_UNICODE_ENVIRONMENT = 0x0400;
const uint STARTF_USESHOWWINDOW = 0x0001;
var pInfo = new Kernel32.PROCESS_INFORMATION();
var sInfo = new Kernel32.STARTUPINFO();
sInfo.dwX = (uint)hostingApp.X; // X Position 
sInfo.dwY = (uint)hostingApp.Y; // Y Position 
sInfo.dwXSize = (uint)hostingApp.Width; // Width
sInfo.dwYSize = (uint)hostingApp.Height; // Height
sInfo.dwFlags = STARTF_USESHOWWINDOW;
var pSec = new Kernel32.SECURITY_ATTRIBUTES();
var tSec = new Kernel32.SECURITY_ATTRIBUTES();
pSec.nLength = System.Runtime.InteropServices.Marshal.SizeOf(pSec);
tSec.nLength = System.Runtime.InteropServices.Marshal.SizeOf(tSec);

    var create_result = Kernel32.CreateProcess(
        fileName,                   // lpApplicationName
        " " + arguments,            // lpCommandLine
        ref pSec,                   // lpProcessAttributes
        ref tSec,                   // lpThreadAttributes
        false,                      // bInheritHandles
        NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,      // dwCreationFlags
        IntPtr.Zero,                // lpEnvironment
        null,                       // lpCurrentDirectory
        ref sInfo,                  // lpStartupInfo
        out pInfo);                 // lpProcessInformation


    var process = Process.GetProcessById(pInfo.dwProcessId);

希望这会有所帮助。

【讨论】:

  • 我尝试使用此示例的变体,但启动的应用程序(记事本)没有监听 STARTUPINFO 结构中设置的 XY 尺寸。如果我没有设置 dwFlags 值,记事本会正常出现。如果我确实将 dwFlags 值设置为 STARTF_USESHOWWINDOW,记事本根本不会出现并且不在任务栏中(尽管我能够打印它的进程 ID)。 MSDN 文档说尺寸将在应用程序第一次调用 CreateWindow 时使用,但记事本忽略了我的尺寸设置。
【解决方案2】:

查看ProcessStartInfo.WindowStyle。您应该能够将其设置为以 Hidden 开头,直到您移动并调整其大小,然后将其恢复正常。

here:

隐藏的窗口样式。窗口可以是可见的,也可以是隐藏的。系统通过不绘制它来显示一个隐藏的窗口。如果一个窗口被隐藏,它实际上是被禁用的。隐藏窗口可以处理来自系统或其他窗口的消息,但它不能处理来自用户的输入或显示输出。通常,应用程序可能会在自定义窗口外观时隐藏新窗口,然后将窗口样式设置为 Normal。要使用 ProcessWindowStyle.Hidden,ProcessStartInfo.UseShellExecute 属性必须为 false。

流程开始后如何更改样式,请看这个问题:

Toggle Process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden at runtime

【讨论】:

  • 我尝试使用 ProcessWindowStyle.Hidden,但问题是隐藏的窗口没有句柄(也没有实际的窗口),所以我无法调整它的大小。
猜你喜欢
  • 2021-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多