[英]How to move an R Tk window to the parent process's screen?
I'm creating an R process from a C# application and the R script that runs creates a Tk window. 我正在从C#应用程序创建R进程,运行的R脚本创建一个Tk窗口。 Right now the window is always showing up on the primary monitor, while my C# application is running on the 2nd monitor.
现在,我的C#应用程序正在第二台监视器上运行时,该窗口始终显示在主监视器上。 How do I move it to the 2nd monitor (when the parent process is there) or get it to be created there in the first place?
我如何将其移动到第二台监视器(当有父进程存在时)还是首先要在第二台监视器上创建它?
Here's how I launch the process right now: 这是我现在启动该过程的方式:
var process = new System.Diagnostics.Process
{
StartInfo = new ProcessStartInfo(rFilepath, String.Format("\"{0}\"", scriptFilepath))
};
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = process.StartInfo.RedirectStandardError = true;
process.Start();
process.EnableRaisingEvents = true;
process.Exited += (x, y) =>
{
if (process.ExitCode != 0)
Program.HandleException(new Exception(String.Format("Output:\r\n{0}\r\n\r\nError:\r\n{1}",
process.StandardOutput.ReadToEnd(),
process.StandardError.ReadToEnd())));
};
Here's the part of the R script that sets up the main window: 这是设置主窗口的R脚本的一部分:
base <- tktoplevel()
tkwm.title(base, "AppName")
// create frames and controls here and put them in with tkgrid
tcl("wm", "attributes", base, topmost=TRUE)
tcl("wm", "attributes", base, topmost=FALSE)
tkfocus(base)
I'm not a R expert, but since there's no answers for your question, I'll try one. 我不是R专家,但是由于您的问题没有答案,因此我将尝试其中的一个。
Here follows a generic code that can move the main window of a child process from C#. 以下是通用代码,该代码可以将子进程的主窗口从C#中移出。 Since it uses the WinAPI SetWindowPos function, some P/Invoke was used here.
由于它使用WinAPI SetWindowPos函数,因此此处使用了一些P / Invoke。
The imports from SetWindowPosFlags is a bit scary, but it's just a C# version of the original headers documented in Windows API. 从SetWindowPosFlags的导入有点吓人,但这只是Windows API中记录的原始标头的C#版本。
The code below, moves the window X +10 and Y +10 relative to your parent process window. 下面的代码使窗口X +10和Y +10相对于父进程窗口移动。 You can change the X and Y to reflect your actual need.
您可以更改X和Y以反映您的实际需求。
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;
using System.Threading;
namespace WindowsPosTests
{
[Flags()]
enum SetWindowPosFlags : uint
{
/// <summary>If the calling thread and the thread that owns the window are attached to different input queues,
/// the system posts the request to the thread that owns the window. This prevents the calling thread from
/// blocking its execution while other threads process the request.</summary>
/// <remarks>SWP_ASYNCWINDOWPOS</remarks>
AsynchronousWindowPosition = 0x4000,
/// <summary>Prevents generation of the WM_SYNCPAINT message.</summary>
/// <remarks>SWP_DEFERERASE</remarks>
DeferErase = 0x2000,
/// <summary>Draws a frame (defined in the window's class description) around the window.</summary>
/// <remarks>SWP_DRAWFRAME</remarks>
DrawFrame = 0x0020,
/// <summary>Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to
/// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE
/// is sent only when the window's size is being changed.</summary>
/// <remarks>SWP_FRAMECHANGED</remarks>
FrameChanged = 0x0020,
/// <summary>Hides the window.</summary>
/// <remarks>SWP_HIDEWINDOW</remarks>
HideWindow = 0x0080,
/// <summary>Does not activate the window. If this flag is not set, the window is activated and moved to the
/// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
/// parameter).</summary>
/// <remarks>SWP_NOACTIVATE</remarks>
DoNotActivate = 0x0010,
/// <summary>Discards the entire contents of the client area. If this flag is not specified, the valid
/// contents of the client area are saved and copied back into the client area after the window is sized or
/// repositioned.</summary>
/// <remarks>SWP_NOCOPYBITS</remarks>
DoNotCopyBits = 0x0100,
/// <summary>Retains the current position (ignores X and Y parameters).</summary>
/// <remarks>SWP_NOMOVE</remarks>
IgnoreMove = 0x0002,
/// <summary>Does not change the owner window's position in the Z order.</summary>
/// <remarks>SWP_NOOWNERZORDER</remarks>
DoNotChangeOwnerZOrder = 0x0200,
/// <summary>Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to
/// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent
/// window uncovered as a result of the window being moved. When this flag is set, the application must
/// explicitly invalidate or redraw any parts of the window and parent window that need redrawing.</summary>
/// <remarks>SWP_NOREDRAW</remarks>
DoNotRedraw = 0x0008,
/// <summary>Same as the SWP_NOOWNERZORDER flag.</summary>
/// <remarks>SWP_NOREPOSITION</remarks>
DoNotReposition = 0x0200,
/// <summary>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</summary>
/// <remarks>SWP_NOSENDCHANGING</remarks>
DoNotSendChangingEvent = 0x0400,
/// <summary>Retains the current size (ignores the cx and cy parameters).</summary>
/// <remarks>SWP_NOSIZE</remarks>
IgnoreResize = 0x0001,
/// <summary>Retains the current Z order (ignores the hWndInsertAfter parameter).</summary>
/// <remarks>SWP_NOZORDER</remarks>
IgnoreZOrder = 0x0004,
/// <summary>Displays the window.</summary>
/// <remarks>SWP_SHOWWINDOW</remarks>
ShowWindow = 0x0040,
}
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Process process = new Process();
process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
process.StartInfo.FileName = Application.ExecutablePath;
//Starts new process
process.Start();
//Wait for process main handle be acquired
while (process.MainWindowHandle == IntPtr.Zero)
Thread.Sleep(1);
//Move window
SetWindowPosFlags flags = SetWindowPosFlags.ShowWindow | SetWindowPosFlags.IgnoreResize | SetWindowPosFlags.IgnoreZOrder;
SetWindowPos(process.MainWindowHandle, new IntPtr(0), this.Left + 10, this.Top + 10, 0, 0, flags);
}
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.