home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2002 December (Special) / DOSV2002_12.iso / utility / tcl230ja95.lzh / source.lzh / dll / tclock.c < prev    next >
C/C++ Source or Header  |  2001-02-18  |  26KB  |  1,028 lines

  1. /*-----------------------------------------------------
  2.   tclock.c
  3.   customize the tray clock
  4.   KAZUBON 1997-2001
  5. -------------------------------------------------------*/
  6.  
  7. #include "tcdll.h"
  8.  
  9. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  10. void InitClock(HWND hwnd);
  11. void EndClock(void);
  12. BOOL IsIE4(HWND hwnd);
  13. void CreateTip(HWND hwnd);
  14. void CreateClockDC(HWND hwnd);
  15. void ReadData(HWND hwnd);
  16. void InitSysInfo(HWND hwnd);
  17. void OnTimer(HWND hwnd);
  18. void DrawClockSub(HWND hwnd, HDC hdc, SYSTEMTIME* pt, int beat100);
  19. LRESULT OnCalcRect(HWND hwnd);
  20. void OnTooltipNeedText(UINT code, LPARAM lParam);
  21. void OnCopy(HWND hwnd, LPARAM lParam);
  22. void UpdateSysRes(HWND hwnd, BOOL bsysres, BOOL bbattery, BOOL bmem);
  23. void InitDaylightTimeTransition(void);
  24. BOOL CheckDaylightTimeTransition(SYSTEMTIME *lt);
  25.  
  26. /*------------------------------------------------
  27.   shared data among processes
  28. --------------------------------------------------*/
  29. #pragma data_seg(".MYDATA")
  30. HHOOK hhook = 0;
  31. HWND hwndTClockMain = NULL;
  32. HWND hwndClock = NULL;
  33. char szShareBuf[81] = { 0 };
  34. #pragma data_seg()
  35.  
  36. /*------------------------------------------------
  37.   globals
  38. --------------------------------------------------*/
  39. HANDLE hmod = 0;
  40. WNDPROC oldWndProc = NULL;
  41. BOOL bTimer = FALSE;
  42. BOOL bTimerTesting = FALSE;
  43. HDC hdcClock = NULL;
  44. HBITMAP hbmpClock = NULL;
  45. HFONT hFon = NULL;
  46. HWND hwndTip = NULL;
  47. COLORREF colback, colback2, colfore;
  48. char format[1024];
  49. BOOL bHour12, bHourZero;
  50. SYSTEMTIME LastTime;
  51. int beatLast = -1;
  52. int bDispSecond = FALSE;
  53. int nDispBeat = 0;
  54. BOOL bNoClock = FALSE;
  55. int nBlink = 0;
  56. BOOL bIE4 = FALSE, bWin95 = FALSE, bWin98 = FALSE,
  57.     bWinNT = FALSE, bWin2000 = FALSE;
  58. int dwidth = 0, dheight = 0, dvpos = 0, dlineheight = 0;
  59. int iClockWidth = -1;
  60. BOOL bPlaying = FALSE;
  61. BOOL bDispSysInfo = FALSE, bTimerSysInfo = FALSE;
  62. BOOL bGetSysRes = FALSE, bGetBattery = FALSE;
  63. BOOL bGetMem = 0;
  64. int iFreeRes[3] = {0,0,0}, iCPUUsage = 0, iBatteryLife = 0;
  65. char sAvailPhysK[11], sAvailPhysM[11];
  66.  
  67. extern HWND hwndStart;
  68. extern HWND hwndStartMenu;
  69.  
  70. extern BOOL bStartMenuClock; // startbtn.c
  71.  
  72. extern BOOL bFillTray;
  73.  
  74. extern int codepage;
  75.  
  76. // XButton Messages
  77. #define WM_XBUTTONDOWN                  0x020B
  78. #define WM_XBUTTONUP                    0x020C
  79.  
  80. /*------------------------------------------------
  81.   initialize the clock
  82. --------------------------------------------------*/
  83. void InitClock(HWND hwnd)
  84. {
  85.     BOOL b;
  86.     DWORD dw;
  87.     
  88.     hwndClock = hwnd;
  89.     
  90.     dw = GetVersion();
  91.     bWin95 = (dw & 0x80000000);
  92.     bWin98 = ((dw & 0x80000000) && 
  93.         LOBYTE(LOWORD(dw)) >= 4 && HIBYTE(LOWORD(dw)) >= 10);
  94.     bWinNT = !(dw & 0x80000000);
  95.     bWin2000 = (!(dw & 0x80000000) && LOBYTE(LOWORD(dw)) >= 5);
  96.     if(bWin2000) bWin98 = TRUE;
  97.     
  98.     if(bWin95)
  99.       GetRegLong(HKEY_DYN_DATA, "PerfStats\\StartStat", "KERNEL\\CPUUsage", 0);
  100.     
  101.     PostMessage(hwndTClockMain, WM_USER, 0, (LPARAM)hwnd);
  102.     
  103.     //レジストリ読み込み
  104.     ReadData(hwndClock);
  105.     InitDaylightTimeTransition();
  106.     //サブクラス化
  107.     oldWndProc = (WNDPROC)GetWindowLong(hwndClock, GWL_WNDPROC);
  108.     SetWindowLong(hwndClock, GWL_WNDPROC, (LONG)WndProc);
  109.     //ダブルクリック受け付けない
  110.     SetClassLong(hwndClock, GCL_STYLE,
  111.       GetClassLong(hwndClock, GCL_STYLE) & ~CS_DBLCLKS);
  112.     
  113.     //スタートボタンの初期化
  114.     SetStartButton(hwndClock);
  115.     //スタートメニューの初期化
  116.     SetStartMenu(hwndClock);
  117.     
  118.     //ツールチップ作成
  119.     CreateTip(hwndClock);
  120.     
  121.     b = GetMyRegLong(NULL, "DropFiles", FALSE);
  122.     DragAcceptFiles(hwnd, b);
  123.     
  124.     bIE4 = IsIE4(hwndClock);
  125.     if(bIE4)
  126.     {
  127.         InitStartMenuIE4();
  128.         InitTaskSwitch(hwndClock);
  129.     }
  130.     
  131.     InitTrayNotify(hwndClock);
  132.     
  133.     if(bWin2000) SetLayeredTaskbar(hwndClock);
  134.     
  135.     //タスクバーの更新
  136.     PostMessage(GetParent(GetParent(hwndClock)), WM_SIZE,
  137.         SIZE_RESTORED, 0);
  138.     InvalidateRect(GetParent(GetParent(hwndClock)), NULL, TRUE);
  139. }
  140.  
  141. /*------------------------------------------------
  142.   ending process
  143. --------------------------------------------------*/
  144. void DeleteClockRes(void)
  145. {
  146.     if(hFon) DeleteObject(hFon); hFon = NULL;
  147.     if(hdcClock) DeleteDC(hdcClock); hdcClock = NULL;
  148.     if(hbmpClock) DeleteObject(hbmpClock); hbmpClock = NULL;
  149. }
  150. void EndClock(void)
  151. {
  152.     DragAcceptFiles(hwndClock, FALSE);
  153.     if(hwndTip) DestroyWindow(hwndTip); hwndTip = NULL;
  154.     EndTrayNotify();
  155.     EndTaskSwitch();
  156.     EndStartButton();
  157.     EndStartMenu();
  158.     ClearStartMenuIE4();
  159.     
  160.     DeleteClockRes();
  161.     
  162.     EndNewAPI(hwndClock);
  163.     EndSysres();
  164.     FreeBatteryLife();
  165.     if(bWin95)
  166.       GetRegLong(HKEY_DYN_DATA, "PerfStats\\StopStat", "KERNEL\\CPUUsage", 0);
  167.     
  168.     if(hwndClock && IsWindow(hwndClock))
  169.     {
  170.         if(bTimer) KillTimer(hwndClock, 1); bTimer = FALSE;
  171.         if(bTimerSysInfo) KillTimer(hwndClock, 2);
  172.         SetWindowLong(hwndClock, GWL_WNDPROC, (LONG)oldWndProc);
  173.         oldWndProc = NULL;
  174.     }
  175.     //TClockウィンドウを終了させる
  176.     if(IsWindow(hwndTClockMain))
  177.         PostMessage(hwndTClockMain, WM_USER+2, 0, 0);
  178. }
  179.  
  180. /*------------------------------------------------
  181.   IE 4 or later is installed ?
  182. --------------------------------------------------*/
  183. BOOL IsIE4(HWND hwnd)
  184. {
  185.     char classname[80];
  186.     DWORD dw;
  187.     
  188.     dw = GetRegLong(HKEY_CURRENT_USER,
  189.         "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
  190.         "ClassicShell", 0);
  191.     if(dw) return TRUE;
  192.     
  193.     hwnd = GetParent(GetParent(hwnd));
  194.     if(hwnd == NULL) return FALSE;
  195.     hwnd = GetWindow(hwnd, GW_CHILD);
  196.     while(hwnd)
  197.     {
  198.         GetClassName(hwnd, classname, 80);
  199.         if(lstrcmpi(classname, "ReBarWindow32") == 0)
  200.             return TRUE;
  201.         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  202.     }
  203.     return FALSE;
  204. }
  205.  
  206. /*------------------------------------------------
  207.   subclass procedure of the clock
  208. --------------------------------------------------*/
  209. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  210. {
  211.     switch(message) // ツールチップ対応
  212.     {
  213.         case WM_LBUTTONDOWN:
  214.         case WM_RBUTTONDOWN:
  215.         case WM_MBUTTONDOWN:
  216.         case WM_LBUTTONUP:
  217.         case WM_RBUTTONUP:
  218.         case WM_MBUTTONUP:
  219.         case WM_MOUSEMOVE:
  220.         {
  221.             MSG msg;
  222.             msg.hwnd = hwnd;
  223.             msg.message = message;
  224.             msg.wParam = wParam;
  225.             msg.lParam = lParam;
  226.             msg.time = GetMessageTime();
  227.             msg.pt.x = LOWORD(GetMessagePos());
  228.             msg.pt.y = HIWORD(GetMessagePos());
  229.             if(hwndTip)
  230.                 SendMessage(hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
  231.         }
  232.     }
  233.     
  234.     switch(message)
  235.     {
  236.         case WM_DESTROY:
  237.             DeleteClockRes();
  238.             break;
  239.         // 親ウィンドウから送られ、サイズを返すメッセージ
  240.         case (WM_USER+100):
  241.             if(bNoClock) break;
  242.             return OnCalcRect(hwnd);
  243.         // システムの設定を反映する
  244.         case WM_SYSCOLORCHANGE:
  245.             CreateClockDC(hwnd); //hdcClock作り直し
  246.         case WM_WININICHANGE:
  247.         case WM_TIMECHANGE:
  248.         // 親ウィンドウから送られる
  249.         case (WM_USER+101):
  250.         {
  251.             HDC hdc;
  252.             if(bNoClock) break;
  253.             hdc = GetDC(hwnd);
  254.             DrawClock(hwnd, hdc);
  255.             ReleaseDC(hwnd, hdc);
  256.             return 0;
  257.         }
  258.         case WM_SIZE:
  259.             CreateClockDC(hwnd); //hdcClock作り直し
  260.             break;
  261.         case WM_ERASEBKGND:
  262.             break;
  263.         case WM_PAINT:
  264.         {
  265.             PAINTSTRUCT ps;
  266.             HDC hdc;
  267.             if(bNoClock) break;
  268.             hdc = BeginPaint(hwnd, &ps);
  269.             DrawClock(hwnd, hdc);
  270.             EndPaint(hwnd, &ps);
  271.             return 0;
  272.         }
  273.         case WM_TIMER:
  274.             if(wParam == 1) OnTimer(hwnd);
  275.             else if(wParam == 2)
  276.                 UpdateSysRes(hwnd, bGetSysRes, bGetBattery, bGetMem);
  277.             else
  278.             {
  279.                 if(bNoClock) break;
  280.             }
  281.             return 0;
  282.         // マウスダウン
  283.         case WM_LBUTTONDOWN:
  284.         case WM_RBUTTONDOWN:
  285.         case WM_MBUTTONDOWN:
  286.         case WM_XBUTTONDOWN:
  287.             if(nBlink)
  288.             {
  289.                 nBlink = 0; InvalidateRect(hwnd, NULL, TRUE);
  290.             }
  291.             if(message == WM_LBUTTONDOWN && bStartMenuClock &&
  292.                 hwndStart && IsWindow(hwndStart))
  293.             {
  294.                 SetWindowPos(hwndStart, NULL, 0, 0, 0, 0,
  295.                     SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  296.                 // スタートメニュー
  297.                 PostMessage(hwndStart, WM_LBUTTONDOWN, 0, 0);
  298.                 return 0;
  299.             }
  300.             PostMessage(hwndTClockMain, message, wParam, lParam);
  301.             return 0;
  302.         // マウスアップ
  303.         case WM_LBUTTONUP:
  304.         case WM_RBUTTONUP:
  305.         case WM_MBUTTONUP:
  306.         case WM_XBUTTONUP:
  307.             PostMessage(hwndTClockMain, message, wParam, lParam);
  308.             if(message == WM_RBUTTONUP) break;
  309.             return 0;
  310.         case WM_MOUSEMOVE:
  311.             return 0;
  312.         case WM_CONTEXTMENU:   // 右クリックメニュー
  313.             PostMessage(hwndTClockMain, message, wParam, lParam);
  314.             return 0;
  315.         case WM_NCHITTEST: // oldWndProcに処理させない
  316.             return DefWindowProc(hwnd, message, wParam, lParam);
  317.         case WM_MOUSEACTIVATE:
  318.             return MA_ACTIVATE;
  319.         // ファイルのドロップ
  320.         case WM_DROPFILES:
  321.             PostMessage(hwndTClockMain, WM_DROPFILES, wParam, lParam);
  322.             return 0;
  323.         case WM_NOTIFY: //ツールチップのテキスト表示
  324.         {
  325.             UINT code;
  326.             code = ((LPNMHDR)lParam)->code;
  327.             if(code == TTN_NEEDTEXT || code == TTN_NEEDTEXTW)
  328.             {
  329.                 OnTooltipNeedText(code, lParam);
  330.                 return 0;
  331.             }
  332.             break;
  333.         }
  334.         case WM_COMMAND:
  335.             if(LOWORD(wParam) == 102) EndClock();
  336.             return 0;
  337.         case CLOCKM_REFRESHCLOCK: // refresh the clock
  338.         {
  339.             BOOL b;
  340.             ReadData(hwnd);
  341.             CreateClockDC(hwnd);
  342.             b = GetMyRegLong(NULL, "DropFiles", FALSE);
  343.             DragAcceptFiles(hwnd, b);
  344.             InvalidateRect(hwnd, NULL, FALSE);
  345.             InvalidateRect(GetParent(hwndClock), NULL, TRUE);
  346.             return 0;
  347.         }
  348.         case CLOCKM_REFRESHTASKBAR: // refresh other elements than clock
  349.             SetStartButton(hwnd);
  350.             SetStartMenu(hwnd);
  351.             InitTaskSwitch(hwnd);
  352.             InitTrayNotify(hwnd);
  353.             CreateClockDC(hwnd);
  354.             if(bWin2000) SetLayeredTaskbar(hwndClock);
  355.             PostMessage(GetParent(GetParent(hwnd)), WM_SIZE,
  356.                 SIZE_RESTORED, 0);
  357.             InvalidateRect(GetParent(GetParent(hwndClock)), NULL, TRUE);
  358.             return 0;
  359.         case CLOCKM_BLINK: // blink the clock
  360.             if(wParam) { if(nBlink == 0) nBlink = 4; }
  361.             else nBlink = 2;
  362.             return 0;
  363.         case CLOCKM_COPY: // copy format to clipboard
  364.             OnCopy(hwnd, lParam);
  365.             return 0;
  366.         case WM_WINDOWPOSCHANGING:  // サイズ調整
  367.         {
  368.             LPWINDOWPOS pwp;
  369.             if(bNoClock) break;
  370.             pwp = (LPWINDOWPOS)lParam;
  371.             if(IsWindowVisible(hwnd) && !(pwp->flags & SWP_NOSIZE))
  372.             {
  373.                 int h;
  374.                 h = (int)HIWORD(OnCalcRect(hwnd));
  375.                 if(pwp->cy > h) pwp->cy = h;
  376.             }
  377.             break;
  378.         }
  379.     }
  380.     /*
  381.     {
  382.         char s[80];
  383.         wsprintf(s, "%X", message);
  384.         WriteDebug(s);
  385.     }
  386.     */
  387.     return CallWindowProc(oldWndProc, hwnd, message, wParam, lParam);
  388. }
  389.  
  390. /*------------------------------------------------
  391.  設定の読み込みとデータの初期化
  392. --------------------------------------------------*/
  393. void ReadData(HWND hwnd)
  394. {
  395.     char fontname[80];
  396.     int fontsize;
  397.     LONG weight, italic;
  398.     SYSTEMTIME lt;
  399.     
  400.     colfore = GetMyRegLong(NULL, "ForeColor", 
  401.         0x80000000 | COLOR_BTNTEXT);
  402.     colback = GetMyRegLong(NULL, "BackColor",
  403.         0x80000000 | COLOR_3DFACE);
  404.     if(GetMyRegLong(NULL, "UseBackColor2", TRUE))
  405.         colback2 = GetMyRegLong(NULL, "BackColor2", colback);
  406.     else colback2 = colback;
  407.     
  408.     GetMyRegStr(NULL, "Font", fontname, 80, "");
  409.     
  410.     fontsize = GetMyRegLong(NULL, "FontSize", 9);
  411.     weight = GetMyRegLong(NULL, "Bold", 0);
  412.     if(weight) weight = FW_BOLD;
  413.     else weight = 0;
  414.     italic = GetMyRegLong(NULL, "Italic", 0);
  415.     
  416.     if(hFon) DeleteObject(hFon);
  417.     hFon = CreateMyFont(fontname, fontsize, weight, italic);
  418.     
  419.     dheight = (int)(short)GetMyRegLong(NULL, "ClockHeight", 0);
  420.     dwidth = (int)(short)GetMyRegLong(NULL, "ClockWidth", 0);
  421.     dvpos = (int)(short)GetMyRegLong(NULL, "VertPos", 0);
  422.     dlineheight = (int)(short)GetMyRegLong(NULL, "LineHeight", 0);
  423.     
  424.     bNoClock = GetMyRegLong(NULL, "NoClock", FALSE);
  425.     
  426.     if(!GetMyRegStr(NULL, "Format", format, 1024, "") || !format[0])
  427.     {
  428.         bNoClock = TRUE;
  429.     }
  430.     
  431.     bDispSecond = IsDispSecond(format);
  432.     if(!bTimer) SetTimer(hwndClock, 1, 1000, NULL);
  433.     bTimer = TRUE;
  434.     nDispBeat = IsDispBeat(format);
  435.     
  436.     bHour12 = GetMyRegLong(NULL, "Hour12", 0);
  437.     bHourZero = GetMyRegLong(NULL, "HourZero", 0);
  438.     
  439.     GetLocalTime(<);
  440.     LastTime.wDay = lt.wDay;
  441.     
  442.     InitFormat(<);      // format.c
  443.     
  444.     iClockWidth = -1;
  445.     
  446.     InitSysInfo(hwnd);
  447. }
  448.  
  449. void InitSysInfo(HWND hwnd)
  450. {
  451.     char tip[1024];
  452.     GetMyRegStr("Tooltip", "Tooltip", tip, 1024, "");
  453.     
  454.     if(bTimerSysInfo) KillTimer(hwndClock, 2);
  455.     
  456.     bDispSysInfo = bTimerSysInfo = FALSE;
  457.     bGetSysRes = FALSE;
  458.     bGetBattery = FALSE;
  459.     bGetMem = 0;
  460.     sAvailPhysK[0] = sAvailPhysM[0] = 0;
  461.     
  462.     if(bWin95)
  463.     {
  464.         if(IsDispSysInfo(format))
  465.         {
  466.             bGetSysRes = TRUE; bDispSysInfo = TRUE;
  467.         }
  468.         if(!bGetSysRes) bGetSysRes = IsDispSysInfo(tip);
  469.         if(bGetSysRes) bTimerSysInfo = TRUE;
  470.     }
  471.     if(bWin95 || bWin2000)
  472.     {
  473.         if(FindFormatStr(format, "BL"))
  474.         {
  475.             bGetBattery = TRUE; bDispSysInfo = TRUE;
  476.         }
  477.         if(!bGetBattery) bGetBattery = FindFormatStr(tip, "BL");
  478.         if(bGetBattery) bTimerSysInfo = TRUE;
  479.     }
  480.     if(FindFormatStr(format, "MK") || FindFormatStr(format, "MM"))
  481.         bGetMem = TRUE;
  482.     if(bGetMem) bDispSysInfo = TRUE;
  483.     if(!bGetMem)
  484.         bGetMem = (FindFormatStr(tip, "MK") || FindFormatStr(tip, "MM"));
  485.     if(bGetMem) bTimerSysInfo = TRUE;
  486.     
  487.     if(bTimerSysInfo)
  488.     {
  489.         int interval;
  490.         UpdateSysRes(hwnd, bGetSysRes, bGetBattery, bGetMem);
  491.         interval = (int)GetMyRegLong(NULL, "IntervalSysInfo", 5);
  492.         if(interval <= 0 || 60 < interval) interval = 5;
  493.         SetTimer(hwndClock, 2, interval * 1000, NULL);
  494.     }
  495. }
  496.  
  497. /*------------------------------------------------
  498.  ツールチップウィンドウの作成
  499. --------------------------------------------------*/
  500. void CreateTip(HWND hwnd)
  501. {
  502.     TOOLINFO ti;
  503.     
  504.     hwndTip = CreateWindow(TOOLTIPS_CLASS, (LPSTR)NULL,
  505.         TTS_ALWAYSTIP,
  506.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  507.         NULL, NULL, hmod, NULL); 
  508.     if(!hwndTip) return;
  509.  
  510.     ti.cbSize = sizeof(TOOLINFO); 
  511.     ti.uFlags = 0;
  512.     ti.hwnd = hwnd;
  513.     ti.hinst = NULL;
  514.     ti.uId = 1;
  515.     ti.lpszText = LPSTR_TEXTCALLBACK;
  516.     ti.rect.left = 0;
  517.     ti.rect.top = 0;
  518.     ti.rect.right = 480; 
  519.     ti.rect.bottom = 480;
  520.     
  521.     SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO)&ti);
  522.     SendMessage(hwndTip, TTM_ACTIVATE, TRUE, 0);
  523. }
  524.  
  525. /*------------------------------------------------
  526.  描画用メモリDCの作成
  527. --------------------------------------------------*/
  528. void CreateClockDC(HWND hwnd)
  529. {
  530.     RECT rc;
  531.     COLORREF col;
  532.     HDC hdc;
  533.     
  534.     if(hdcClock) DeleteDC(hdcClock); hdcClock = NULL;
  535.     if(hbmpClock) DeleteObject(hbmpClock); hbmpClock = NULL;
  536.     
  537.     if(bNoClock) return;
  538.     
  539.     if(bFillTray) hwnd = GetParent(hwnd);
  540.     GetClientRect(hwnd, &rc);
  541.     
  542.     hdc = GetDC(NULL);
  543.     
  544.     hdcClock = CreateCompatibleDC(hdc);
  545.     if(!hdcClock)
  546.     {
  547.         ReleaseDC(NULL, hdc);
  548.         return;
  549.     }
  550.     hbmpClock = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
  551.     if(!hbmpClock)
  552.     {
  553.         DeleteDC(hdcClock); hdcClock = NULL;
  554.         ReleaseDC(NULL, hdc);
  555.         return;
  556.     }
  557.     SelectObject(hdcClock, hbmpClock);
  558.     
  559.     SelectObject(hdcClock, hFon);
  560.     SetBkMode(hdcClock, TRANSPARENT);
  561.     SetTextAlign(hdcClock, TA_CENTER|TA_TOP);
  562.     col = colfore;
  563.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  564.     SetTextColor(hdcClock, col);
  565.     
  566.     FillClock(hwnd, hdcClock, &rc, 0);
  567.     
  568.     ReleaseDC(NULL, hdc);
  569. }
  570.  
  571. /*------------------------------------------------
  572.    get date/time and beat to display
  573. --------------------------------------------------*/
  574. void GetDisplayTime(SYSTEMTIME* pt, int* beat100)
  575. {
  576.     FILETIME ft, lft;
  577.     SYSTEMTIME lt;
  578.     
  579.     GetSystemTimeAsFileTime(&ft);
  580.     
  581.     if(beat100)
  582.     {
  583.         DWORDLONG dl;
  584.         SYSTEMTIME st;
  585.         int sec;
  586.         
  587.         dl = *(DWORDLONG*)&ft + 36000000000;
  588.         FileTimeToSystemTime((FILETIME*)&dl, &st);
  589.         
  590.         sec = st.wHour * 3600 + st.wMinute * 60 + st.wSecond;
  591.         *beat100 = (sec * 1000) / 864;
  592.     }
  593.     
  594.     FileTimeToLocalFileTime(&ft, &lft);
  595.     FileTimeToSystemTime(&lft, <);
  596.     memcpy(pt, <, sizeof(lt));
  597. }
  598.  
  599. /*------------------------------------------------
  600.  WM_TIMER の処理
  601. --------------------------------------------------*/
  602. void OnTimer(HWND hwnd)
  603. {
  604.     SYSTEMTIME t;
  605.     int beat100;
  606.     HDC hdc;
  607.     BOOL bRedraw;
  608.     
  609.     GetDisplayTime(&t, nDispBeat?(&beat100):NULL);
  610.     
  611.     if(t.wMilliseconds > 200 || (bWinNT && t.wMilliseconds > 50))
  612.     {
  613.         KillTimer(hwnd, 1);
  614.         bTimerTesting = TRUE;
  615.         SetTimer(hwnd, 1, 1001 - t.wMilliseconds, NULL);
  616.     }
  617.     else if(bTimerTesting)
  618.     {
  619.         KillTimer(hwnd, 1);
  620.         bTimerTesting = FALSE;
  621.         SetTimer(hwnd, 1, 1000, NULL);
  622.     }
  623.     
  624.     if(CheckDaylightTimeTransition(&t))
  625.     {
  626.         CallWindowProc(oldWndProc, hwnd, WM_TIMER, 0, 0);
  627.         GetDisplayTime(&t, nDispBeat?(&beat100):NULL);
  628.     }
  629.     
  630.     bRedraw = FALSE;
  631.     if(nBlink > 0) bRedraw = TRUE;
  632.     else if(bDispSecond) bRedraw = TRUE;
  633.     else if(nDispBeat == 1 && beatLast != (beat100/100)) bRedraw = TRUE;
  634.     else if(nDispBeat == 2 && beatLast != beat100) bRedraw = TRUE;
  635.     else if(bDispSysInfo) bRedraw = TRUE;
  636.     else if(LastTime.wHour != (int)t.wHour 
  637.         || LastTime.wMinute != (int)t.wMinute) bRedraw = TRUE;
  638.     
  639.     if(bNoClock) bRedraw = FALSE;
  640.     
  641.     if(LastTime.wDay != t.wDay || LastTime.wMonth != t.wMonth ||
  642.         LastTime.wYear != t.wYear)
  643.     {
  644.         InitFormat(&t); // format.c
  645.         InitDaylightTimeTransition();
  646.     }
  647.     
  648.     hdc = NULL;
  649.     if(bRedraw) hdc = GetDC(hwnd);
  650.     
  651.     memcpy(&LastTime, &t, sizeof(t));
  652.     
  653.     if(nDispBeat == 1) beatLast = beat100/100;
  654.     else if(nDispBeat > 1) beatLast = beat100;
  655.     
  656.     if(nBlink >= 3 && t.wMinute == 1) nBlink = 0;
  657.     
  658.     if(hdc)
  659.     {
  660.         DrawClockSub(hwnd, hdc, &t, beat100); //描画
  661.         ReleaseDC(hwnd, hdc);
  662.     }
  663.     
  664.     if(nBlink)
  665.     {
  666.         if(nBlink % 2) nBlink++;
  667.         else nBlink--;
  668.     }
  669.     
  670.     CheckCursorOnStartButton();
  671. }
  672.  
  673. /*------------------------------------------------
  674.  時計の描画
  675. --------------------------------------------------*/
  676. void DrawClock(HWND hwnd, HDC hdc)
  677. {
  678.     SYSTEMTIME t;
  679.     int beat100;
  680.     
  681.     GetDisplayTime(&t, nDispBeat?(&beat100):NULL);
  682.     DrawClockSub(hwnd, hdc, &t, beat100);
  683. }
  684.  
  685. /*------------------------------------------------
  686.   draw the clock
  687. --------------------------------------------------*/
  688. void DrawClockSub(HWND hwnd, HDC hdc, SYSTEMTIME* pt, int beat100)
  689. {
  690.     BITMAP bmp;
  691.     RECT rcFill,  rcClock;
  692.     TEXTMETRIC tm;
  693.     int hf, y, w;
  694.     char s[1024], *p, *sp;
  695.     SIZE sz;
  696.     int xclock, yclock, wclock, hclock, xsrc, ysrc, wsrc, hsrc;
  697.     int xcenter;
  698.     HRGN hRgn, hOldRgn;
  699.     
  700.     if(!hdcClock) CreateClockDC(hwnd);
  701.     
  702.     if(!hdcClock || !hbmpClock) return;
  703.     
  704.     GetObject(hbmpClock, sizeof(BITMAP), (LPVOID)&bmp);
  705.     rcFill.left = rcFill.top = 0;
  706.     rcFill.right = bmp.bmWidth; rcFill.bottom = bmp.bmHeight;
  707.     
  708.     FillClock(hwnd, hdcClock, &rcFill, nBlink);
  709.     
  710.     MakeFormat(s, pt, beat100, format);
  711.     
  712.     GetClientRect(hwndClock, &rcClock);
  713.     if(bFillTray)
  714.     {
  715.         POINT ptTray, ptClock;
  716.         ptTray.x = ptTray.y = 0;
  717.         ClientToScreen(GetParent(hwndClock), &ptTray);
  718.         ptClock.x = ptClock.y = 0;
  719.         ClientToScreen(hwndClock, &ptClock);
  720.         xclock = ptClock.x - ptTray.x;
  721.         yclock = ptClock.y - ptTray.y;
  722.     }
  723.     else
  724.     {
  725.         xclock = 0; yclock = 0;
  726.     }
  727.     wclock = rcClock.right;  hclock = rcClock.bottom;
  728.     
  729.     GetTextMetrics(hdcClock, &tm);
  730.     
  731.     if(bFillTray)
  732.     {
  733.         hRgn = CreateRectRgn(xclock,  yclock,
  734.             xclock + wclock, yclock + hclock);
  735.         hOldRgn = SelectObject(hdcClock, hRgn);
  736.     }
  737.     
  738.     hf = tm.tmHeight - tm.tmInternalLeading;
  739.     p = s;
  740.     y = hf / 4 - tm.tmInternalLeading / 2;
  741.     if(bFillTray) y += yclock;
  742.     xcenter = wclock / 2;
  743.     if(bFillTray) xcenter += xclock;
  744.     w = 0;
  745.     while(*p)
  746.     {
  747.         sp = p;
  748.         while(*p && *p != 0x0d) p++;
  749.         if(*p == 0x0d) { *p = 0; p += 2; }
  750.         if(*p == 0 && sp == s)
  751.         {
  752.             y = (hclock - tm.tmHeight) / 2  - tm.tmInternalLeading / 4;
  753.             if(bFillTray) y += yclock;
  754.         }
  755.         TextOut(hdcClock, xcenter, y + dvpos, sp, strlen(sp));
  756.         
  757.         if(GetTextExtentPoint32(hdcClock, sp, strlen(sp), &sz) == 0)
  758.             sz.cx = strlen(sp) * tm.tmAveCharWidth;
  759.         if(w < sz.cx) w = sz.cx;
  760.         
  761.         y += hf; if(*p) y += 2 + dlineheight;
  762.     }
  763.     
  764.     xsrc = 0; ysrc = 0; wsrc = rcFill.right; hsrc = rcFill.bottom;
  765.     if(bFillTray)
  766.     {
  767.         xsrc = xclock; ysrc = yclock;
  768.         wsrc = wclock; hsrc = hclock;
  769.     }
  770.     BitBlt(hdc, 0, 0, wsrc, hsrc, hdcClock, xsrc, ysrc, SRCCOPY);
  771.     
  772.     if(bFillTray)
  773.     {
  774.         SelectObject(hdcClock, hOldRgn);
  775.         DeleteObject(hRgn);
  776.     }
  777.     
  778.     w += tm.tmAveCharWidth * 2;
  779.     w += dwidth;
  780.     if(w > iClockWidth)
  781.     {
  782.         iClockWidth = w;
  783.         PostMessage(GetParent(GetParent(hwndClock)), WM_SIZE,
  784.             SIZE_RESTORED, 0);
  785.     }
  786. }
  787.  
  788. /*------------------------------------------------
  789.   paint background of clock
  790. --------------------------------------------------*/
  791. void FillClock(HWND hwnd, HDC hdc, RECT *prc, int nblink)
  792. {
  793.     HBRUSH hbr;
  794.     COLORREF col;
  795.     
  796.     if(nblink == 0 || (nblink % 2)) col = colfore;
  797.     else col = colback;
  798.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  799.     SetTextColor(hdc, col);
  800.     
  801.     if(nblink || colback == colback2 || !bWin98)
  802.     {
  803.         if(nblink == 0 || (nblink % 2)) col = colback;
  804.         else col = colfore;
  805.         if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  806.         hbr = CreateSolidBrush(col);
  807.         FillRect(hdc, prc, hbr);
  808.         DeleteObject(hbr);
  809.     }
  810.     else
  811.     {
  812.         COLORREF col2;
  813.         
  814.         col = colback;
  815.         if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  816.         col2 = colback2;
  817.         if(col2 & 0x80000000) col2 = GetSysColor(col2 & 0x00ffffff);
  818.         
  819.         GradientFillClock(hdc, prc, col, col2);
  820.     }
  821.  
  822. }
  823.  
  824. /*------------------------------------------------
  825.  時計に必要なサイズを返す
  826.  戻り値:上位WORD 高さ 下位WORD 幅
  827. --------------------------------------------------*/
  828. LRESULT OnCalcRect(HWND hwnd)
  829. {
  830.     SYSTEMTIME t;
  831.     int beat100;
  832.     LRESULT w, h;
  833.     HDC hdc;
  834.     TEXTMETRIC tm;
  835.     char s[1024], *p, *sp;
  836.     SIZE sz;
  837.     int hf;
  838.     
  839.     if(!(GetWindowLong(hwnd, GWL_STYLE)&WS_VISIBLE)) return 0;
  840.     
  841.     hdc = GetDC(hwnd);
  842.     
  843.     if(hFon) SelectObject(hdc, hFon);
  844.     GetTextMetrics(hdc, &tm);
  845.     
  846.     GetDisplayTime(&t, nDispBeat?(&beat100):NULL);
  847.     MakeFormat(s, &t, beat100, format);
  848.     
  849.     p = s; w = 0; h = 0;
  850.     hf = tm.tmHeight - tm.tmInternalLeading;
  851.     while(*p)
  852.     {
  853.         sp = p;
  854.         while(*p && *p != 0x0d) p++;
  855.         if(*p == 0x0d) { *p = 0; p += 2; }
  856.         if(GetTextExtentPoint32(hdc, sp, strlen(sp), &sz) == 0)
  857.             sz.cx = strlen(sp) * tm.tmAveCharWidth;
  858.         if(w < sz.cx) w = sz.cx;
  859.         h += hf; if(*p) h += 2 + dlineheight;
  860.     }
  861.     w += tm.tmAveCharWidth * 2;
  862.     if(iClockWidth < 0) iClockWidth = w;
  863.     else w = iClockWidth;
  864.     w += dwidth;
  865.     
  866.     h += hf / 2 + dheight;
  867.     if(h < 4) h = 4;
  868.     
  869.     ReleaseDC(hwnd, hdc);
  870.     
  871.     return (h << 16) + w;
  872. }
  873.  
  874. /*------------------------------------------------
  875.  ツールチップの表示
  876. --------------------------------------------------*/
  877. void OnTooltipNeedText(UINT code, LPARAM lParam)
  878. {
  879.     SYSTEMTIME t;
  880.     int beat100;
  881.     char fmt[1024], s[1024];
  882.     
  883.     GetMyRegStr("Tooltip", "Tooltip", fmt, 1024, "");
  884.     if(fmt[0] == 0) strcpy(fmt, "\"TClock\" LDATE");
  885.     GetDisplayTime(&t, &beat100);
  886.     MakeFormat(s, &t, beat100, fmt);
  887.     
  888.     if(code == TTN_NEEDTEXT)
  889.         strcpy(((LPTOOLTIPTEXT)lParam)->szText, s);
  890.     else
  891.         MultiByteToWideChar(CP_ACP, 0, s, -1,
  892.             ((LPTOOLTIPTEXTW)lParam)->szText, 80);
  893.     SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
  894.         SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
  895. }
  896.  
  897.  
  898. /*------------------------------------------------
  899.   copy date/time text to clipboard
  900. --------------------------------------------------*/
  901. void OnCopy(HWND hwnd, LPARAM lParam)
  902. {
  903.     SYSTEMTIME t;
  904.     int beat100;
  905.     char entry[20], fmt[256], s[1024], *pbuf;
  906.     HGLOBAL hg;
  907.     BOOL br, bb, bm;
  908.     
  909.     GetDisplayTime(&t, &beat100);
  910.     wsprintf(entry, "%d%dClip",
  911.         (int)LOWORD(lParam), (int)HIWORD(lParam));
  912.     GetMyRegStr("Mouse", entry, fmt, 256, "");
  913.     if(fmt[0] == 0) strcpy(fmt, format);
  914.     
  915.     br = IsDispSysInfo(fmt);
  916.     bb = FindFormatStr(fmt, "BL");
  917.     bm = (FindFormatStr(fmt, "MK") || FindFormatStr(fmt, "MM"));
  918.     if(br || bb || bm)
  919.         UpdateSysRes(hwnd, br, bb, bm);
  920.     
  921.     MakeFormat(s, &t, beat100, fmt);
  922.     
  923.     if(!OpenClipboard(hwnd)) return;
  924.     EmptyClipboard();
  925.     hg = GlobalAlloc(GMEM_DDESHARE, strlen(s) + 1);
  926.     pbuf = (char*)GlobalLock(hg);
  927.     strcpy(pbuf, s);
  928.     GlobalUnlock(hg);
  929.     SetClipboardData(CF_TEXT, hg);
  930.     CloseClipboard(); 
  931. }
  932.  
  933. void UpdateSysRes(HWND hwnd, BOOL bsysres, BOOL bbattery, BOOL bmem)
  934. {
  935.     int i;
  936.     
  937.     if(bWin95 && bsysres)
  938.     {
  939. //        char s[10];
  940.         for(i = 0; i < 3; i++)
  941.             iFreeRes[i] = GetFreeSystemResources((WORD)i);
  942.         
  943.         iCPUUsage = GetRegLong(HKEY_DYN_DATA, "PerfStats\\StatData",
  944.             "KERNEL\\CPUUsage", 0);
  945. //        wsprintf(s, "%d", iCPUUsage);
  946. //        WriteDebug(s);
  947.     }
  948.     if((bWin95 || bWin2000) && bbattery)
  949.     {
  950.         iBatteryLife = GetBatteryLifePercent();
  951.     }
  952.     if(bmem)
  953.     {
  954.         MEMORYSTATUS ms;
  955.         ms.dwLength = sizeof(ms);
  956.         GlobalMemoryStatus(&ms);
  957.         wsprintf(sAvailPhysK, "%d", ms.dwAvailPhys / 1024);
  958.         wsprintf(sAvailPhysM, "%d", ms.dwAvailPhys / (1024 * 1024));
  959.     }
  960. }
  961.  
  962. int iHourTransition = -1, iMinuteTransition = -1;
  963.  
  964. /*------------------------------------------------
  965.   initialize time-zone information
  966. --------------------------------------------------*/
  967. void InitDaylightTimeTransition(void)
  968. {
  969.     SYSTEMTIME lt, *plt;
  970.     TIME_ZONE_INFORMATION tzi;
  971.     DWORD dw;
  972.     BOOL b;
  973.     
  974.     iHourTransition = iMinuteTransition = -1;
  975.     
  976.     GetLocalTime(<);
  977.     
  978.     b = FALSE;
  979.     memset(&tzi, 0, sizeof(tzi));
  980.     dw = GetTimeZoneInformation(&tzi);
  981.     if(dw == TIME_ZONE_ID_STANDARD
  982.       && tzi.DaylightDate.wMonth == lt.wMonth
  983.       && tzi.DaylightDate.wDayOfWeek == lt.wDayOfWeek)
  984.     {
  985.         b = TRUE; plt = &(tzi.DaylightDate);
  986.     }
  987.     if(dw == TIME_ZONE_ID_DAYLIGHT
  988.       && tzi.StandardDate.wMonth == lt.wMonth
  989.       && tzi.StandardDate.wDayOfWeek == lt.wDayOfWeek)
  990.     {
  991.         b = TRUE; plt = &(tzi.StandardDate);
  992.     }
  993.     
  994.     if(b && plt->wDay < 5)
  995.     {
  996.         if(((lt.wDay - 1) / 7 + 1) == plt->wDay)
  997.         {
  998.             iHourTransition = plt->wHour;
  999.             iMinuteTransition = plt->wMinute;
  1000.         }
  1001.     }
  1002.     else if(b && plt->wDay == 5)
  1003.     {
  1004.         FILETIME ft;
  1005.         SystemTimeToFileTime(<, &ft);
  1006.         *(DWORDLONG*)&ft += 6048000000000i64;
  1007.         FileTimeToSystemTime(&ft, <);
  1008.         if(lt.wDay < 8)
  1009.         {
  1010.             iHourTransition = plt->wHour;
  1011.             iMinuteTransition = plt->wMinute;
  1012.         }
  1013.     }
  1014. }
  1015.  
  1016. BOOL CheckDaylightTimeTransition(SYSTEMTIME *plt)
  1017. {
  1018.     if((int)plt->wHour == iHourTransition &&
  1019.        (int)plt->wMinute >= iMinuteTransition)
  1020.     {
  1021.         iHourTransition = iMinuteTransition = -1;
  1022.         return TRUE;
  1023.     }
  1024.     else return FALSE;
  1025. }
  1026.  
  1027.  
  1028.