当左键单击 Windows 7(也可能是 Vista)任务栏中的时钟时,会打开一个弹出窗口,显示日历和时钟(因此不是日期和时间调整窗口)。我如何自己打开这个窗口(在 C# 中首选)?
我希望timedate.cpl
会调用它,但这会打开日期和时间调整窗口。
要显示时钟,您需要将适当的窗口消息发送到托盘窗口。这可以使用 Windows API 函数来完成SendMessage
:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
class ShowCalendar
{
private delegate bool EnumChildCallback(IntPtr hwnd,
ref IntPtr lParam);
[DllImport("User32.dll")]
private static extern bool EnumChildWindows(IntPtr hWndParent,
EnumChildCallback lpEnumFunc,
ref IntPtr lParam);
[DllImport("User32.dll")]
private static extern int GetClassName(IntPtr hWnd,
StringBuilder lpClassName,
int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd,
UInt32 Msg,
IntPtr wParam,
IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd,
out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private static readonly string TrayWndClassName = "Shell_TrayWnd";
private static readonly string TrayNotifyWndClassName = "TrayNotifyWnd";
private static readonly string ClockWndClassName = "TrayClockWClass";
private static readonly uint WM_NCLBUTTONDOWN = 0x00A1;
private static readonly uint HTCAPTION = 2;
private static bool EnumChildProc(IntPtr hwndChild, ref IntPtr lParam)
{
StringBuilder className = new StringBuilder(128);
GetClassName(hwndChild, className, 128);
if (className.ToString() == ClockWndClassName)
{
lParam = hwndChild;
return false;
}
return true;
}
static void Main(string[] args)
{
IntPtr hWndTray = FindWindow(TrayWndClassName, string.Empty);
if (hWndTray == IntPtr.Zero)
{
throw new Win32Exception();
}
IntPtr hWndTrayNotify = FindWindowEx(hWndTray,
IntPtr.Zero,
TrayNotifyWndClassName,
string.Empty);
if (hWndTrayNotify == IntPtr.Zero)
{
throw new Win32Exception();
}
// search clock window
EnumChildCallback cb = new EnumChildCallback(EnumChildProc);
IntPtr hWndClock = IntPtr.Zero;
EnumChildWindows(hWndTray, cb, ref hWndClock);
if (hWndClock == IntPtr.Zero)
{
throw new Win32Exception();
}
// get clock window position
RECT rect;
if (!GetWindowRect(hWndClock, out rect))
{
throw new Win32Exception();
}
// send click, lParam contains window position
IntPtr wParam = new IntPtr(HTCAPTION);
IntPtr lParam = new IntPtr(rect.Top << 16 | rect.Left);
SendMessage(hWndTray, WM_NCLBUTTONDOWN, wParam, lParam);
}
}