2010-07-28 1 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

+0

일단 Window가 있으면 핸들에서'SetWindowPos'를 호출 할 수 있다고 가정합니다 – Sebastian