2010-07-28 48 views
2

當在Windows 7(也許是Vista)上任務欄中單擊時鐘時,會彈出一個彈出窗口,顯示日曆和時鐘(因此不是日期和時間調整窗口)。我如何自己打開此窗口(首選使用C#)?Windows 7左鍵單擊時鐘彈出

我希望timedate.cpl會打電話給這個,但是這會打開日期和時間調整窗口。

回答

4

要顯示時鐘,您需要將相應的窗口消息發送到托盤窗口。這可以通過使用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); 
    } 
} 
+0

日Thnx答覆,但我想類似的東西也和它有兩個問題: 1)時鐘必須是可見的(在系統打開時鐘關閉圖標不會顯示彈出窗口)。 2)我想在其他地方顯示彈出窗口(第二個屏幕)。 – jerone 2010-07-28 20:16:59

+0

我想一旦窗口在那裏,你可以在句柄上調用SetWindowPos – Sebastian 2013-11-29 23:10:17