【问题标题】:positioning the windows system date time clock window [duplicate]定位Windows系统日期时间时钟窗口[重复]
【发布时间】:2019-04-05 14:49:21
【问题描述】:

下面的事件方法调出windows系统日期时间时钟窗口。我的标签位于表单的右下方,系统日期时间时钟窗口出现在表单的左上方。单击此事件处理程序时,有没有办法将此日期时间时钟窗口定位在表单的右下方?

    private void LabelDateTime_Click(object sender, System.EventArgs e)
    {
        // bring up the date & time dialog
        System.Diagnostics.Process.Start("timedate.cpl");
    }

【问题讨论】:

  • 查找SetWindowPos
  • @namg_engr 您将很难以这种方式获得该窗口。您应该通过 Rundll32.exe 运行该 CP 小程序,否则您的进程将立即关闭。
  • @DangerZone 有点不同。启动 Win32 可执行文件与启动控制面板小程序不同,后者由另一个进程执行,然后关闭。

标签: c# winforms


【解决方案1】:

以这种方式使用System.Diagnostics.Process.Start()启动进程是无效的,因为生成的进程会在窗口创建后立即退出。 .cpl 小程序不是标准可执行文件,需要操作系统外壳和启动器才能启动。

但是,可以使用Rundll32.exe 创建一个稳定的进程,这将生成一些线程来承载小程序控件和 GDI+ 支持。
但是,到达小程序窗口需要一些 P/Invoke(ing),因为 rundll 是无窗口的,并且它不引用它帮助创建的那个,所以 Process.MainWindowHandle = 0

文档参考。 MSDN EnumThreadWndProc() CallbackEnumThreadWindows()GetWindowRect()GetWindowText()SetWindowPos()

using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

ProcessStartInfo psInfo = new ProcessStartInfo() {
    UseShellExecute = true,
    FileName = "rundll32.exe",
    Arguments = "shell32.dll, Control_RunDLL timedate.cpl,,0", //<- 0 = First Tab
    WindowStyle = ProcessWindowStyle.Normal
};

Process sysClockProcess = new Process() {
    SynchronizingObject = this,
    EnableRaisingEvents = true,
    StartInfo = psInfo
};

sysClockProcess.Start();
sysClockProcess.WaitForInputIdle();

//Insert the Window title. It's case SENSITIVE
//Window Title in HKEY_CURRENT_USER\Software\Classes\Local Settings\MuiCache\[COD]\[LANG]\
string windowTitle = "Date and Time";
int maxLenght = 256;
SetWindowPosFlags flags = SetWindowPosFlags.NoSize |
                          SetWindowPosFlags.AsyncWindowPos |
                          SetWindowPosFlags.ShowWindow;

//The first thread is the Main thread. All Dialog windows' handles are attached here.
//The second thread is for GDI+ Hook Window. Ignore it.
EnumThreadWindows((uint)sysClockProcess.Threads[0].Id, (hWnd, lParam) =>
{
    StringBuilder lpString = new StringBuilder(maxLenght);
    if (GetWindowText(hWnd, lpString, maxLenght) > 0)
        if (lpString.ToString() == windowTitle)
        {
            GetWindowRect(hWnd, out RECT lpRect);
            Size size = new Size(lpRect.Right - lpRect.Left, lpRect.Bottom - lpRect.Top);
            //Caculate the position of the Clock Windows relative to the ref. Form Size
            SetWindowPos(hWnd, (IntPtr)0, ((this.Width + this.Left) - size.Width),
                                          ((this.Height + this.Top) - size.Height), 0, 0, flags);
            return false;
        }
    //Window not found: return true to continue the enumeration
    return true;
}, ref windowTitle);

sysClockProcess.Exited += (s, ev) => {
    Console.WriteLine($"The process has exited. Code: " +
        $"{sysClockProcess.ExitCode} Time: {sysClockProcess.ExitTime}");
    sysClockProcess.Dispose();
};

Win32 声明:

// SetWindowPos() flags
[Flags]
public enum SetWindowPosFlags : uint
{
   NoSize =         0x0001,
   NoActivate =     0x0010,
   ShowWindow =     0x0040,
   DeferErase =     0x2000,
   AsyncWindowPos = 0x4000
}

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
   public int Left;
   public int Top;
   public int Right;
   public int Bottom;
}

//Callback for `EnumThreadWindows()`.
public delegate bool EnumThreadWndProc([In] IntPtr hWnd, [In] IntPtr lParam);

[DllImport("user32.dll")]
static extern bool EnumThreadWindows([In] uint dwThreadId, [In] EnumThreadWndProc lpfn, [In] ref string lParam);

[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, [In] int nMaxCount);

[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

[DllImport("user32.dll", SetLastError=true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 2010-12-16
    • 1970-01-01
    相关资源
    最近更新 更多