summaryrefslogtreecommitdiff
path: root/plugins/AutoShutdown/frame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AutoShutdown/frame.cpp')
-rw-r--r--plugins/AutoShutdown/frame.cpp644
1 files changed, 644 insertions, 0 deletions
diff --git a/plugins/AutoShutdown/frame.cpp b/plugins/AutoShutdown/frame.cpp
new file mode 100644
index 0000000000..f9266b1906
--- /dev/null
+++ b/plugins/AutoShutdown/frame.cpp
@@ -0,0 +1,644 @@
+/*
+
+'AutoShutdown'-Plugin for Miranda IM
+
+Copyright 2004-2007 H. Herkenrath
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program (Shutdown-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+/* Show Frame */
+extern HINSTANCE hInst;
+static HWND hwndCountdownFrame;
+static WORD hFrame;
+/* Misc */
+static HANDLE hHookModulesLoaded;
+
+/************************* Helpers ************************************/
+
+#define FRAMEELEMENT_BAR 1
+#define FRAMEELEMENT_BKGRND 2
+#define FRAMEELEMENT_TEXT 3
+static COLORREF GetDefaultColor(BYTE id)
+{
+ switch(id) {
+ case FRAMEELEMENT_BAR:
+ return RGB(250,0,0); /* same color as used on header icon */
+ case FRAMEELEMENT_BKGRND:
+ return (COLORREF)DBGetContactSettingDword(NULL,"CLC","BkColour",CLCDEFAULT_BKCOLOUR);
+ case FRAMEELEMENT_TEXT:
+ return GetSysColor(COLOR_WINDOWTEXT);
+ }
+ return 0; /* never happens */
+}
+
+static LOGFONT* GetDefaultFont(LOGFONT *lf)
+{
+ NONCLIENTMETRICS ncm;
+ ZeroMemory(&ncm,sizeof(ncm));
+ ncm.cbSize=sizeof(ncm);
+ if(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,ncm.cbSize,&ncm,0)) {
+ *lf=ncm.lfStatusFont;
+ return lf;
+ }
+ return (LOGFONT*)NULL;
+}
+
+static HICON SetFrameTitleIcon(WORD hFrame,HICON hNewIcon)
+{
+ HICON hPrevIcon;
+ hPrevIcon=(HICON)CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_ICON,hFrame),0);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_ICON,hFrame),(LPARAM)hNewIcon);
+ if((int)hPrevIcon==-1) return (HICON)NULL;
+ return hPrevIcon;
+}
+
+static LRESULT CALLBACK ProgressBarSubclassProc(HWND hwndProgress,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_ERASEBKGND:
+ return TRUE;
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ return SendMessage(GetParent(hwndProgress),msg,wParam,lParam);
+ }
+ return CallWindowProc((WNDPROC)GetWindowLong(hwndProgress,GWL_USERDATA),hwndProgress,msg,wParam,lParam);
+}
+
+/************************* Window Class *******************************/
+
+#define COUNTDOWNFRAME_CLASS _T("AutoShutdownCountdown")
+
+/* Data */
+struct CountdownFrameWndData { /* sizeof=57, max cbClsExtra=40 on Win32 */
+ time_t countdown,settingLastTime;
+ HANDLE hHookColorsChanged,hHookFontsChanged,hHookIconsChanged;
+ HANDLE hwndIcon,hwndProgress,hwndDesc,hwndTime,hwndToolTip;
+ HBRUSH hbrBackground;
+ COLORREF clrBackground,clrText;
+ HFONT hFont;
+ WORD fTimeFlags;
+ BYTE flags;
+};
+
+/* Flags */
+#define FWPDF_PAUSED 0x01
+#define FWPDF_PAUSEDSHOWN 0x02
+#define FWPDF_COUNTDOWNINVALID 0x04
+#define FWPDF_TIMEISCLIPPED 0x08
+
+/* Menu Items */
+#define MENUITEM_STOPCOUNTDOWN 1
+#define MENUITEM_PAUSECOUNTDOWN 2
+
+/* Messages */
+#define M_REFRESH_COLORS (WM_USER+0)
+#define M_REFRESH_ICONS (WM_USER+1)
+#define M_REFRESH_FONTS (WM_USER+2)
+#define M_SET_COUNTDOWN (WM_USER+3)
+#define M_UPDATE_COUNTDOWN (WM_USER+4)
+#define M_CHECK_CLIPPED (WM_USER+5)
+#define M_CLOSE_COUNTDOWN (WM_USER+6)
+#define M_PAUSE_COUNTDOWN (WM_USER+7)
+
+static LRESULT CALLBACK FrameWndProc(HWND hwndFrame,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ struct CountdownFrameWndData *dat=(struct CountdownFrameWndData*)GetWindowLong(hwndFrame,GWL_USERDATA);
+
+ switch(msg) {
+ case WM_NCCREATE: /* init window data */
+ dat=(struct CountdownFrameWndData*)mir_calloc(sizeof(*dat));
+ SetWindowLong(hwndFrame,GWL_USERDATA,(LONG)dat);
+ if(dat==NULL) return FALSE; /* creation failed */
+ dat->fTimeFlags=*(WORD*)((CREATESTRUCT*)lParam)->lpCreateParams;
+ dat->flags=FWPDF_COUNTDOWNINVALID;
+ break;
+ case WM_CREATE: /* create childs */
+ { CREATESTRUCT *params=(CREATESTRUCT*)lParam;
+ dat->hwndIcon=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ _T("Static"),
+ NULL,
+ WS_CHILD|WS_VISIBLE|SS_ICON|SS_CENTERIMAGE|SS_NOTIFY,
+ 3, 0,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON),
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ dat->hwndProgress=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ PROGRESS_CLASS,
+ (dat->fTimeFlags&SDWTF_ST_TIME)?TranslateT("Shutdown at:"):TranslateT("Time left:"),
+ WS_CHILD|WS_VISIBLE|PBS_SMOOTH,
+ GetSystemMetrics(SM_CXICON)+5,
+ 5, 90,
+ (GetSystemMetrics(SM_CXICON)/2)-5,
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ if(dat->hwndProgress==NULL) return -1; /* creation failed, calls WM_DESTROY */
+ SendMessage(dat->hwndProgress,PBM_SETSTEP,(WPARAM)1,0);
+ SetWindowLong(dat->hwndProgress,GWL_USERDATA,SetWindowLong(dat->hwndProgress,GWL_WNDPROC,(LONG)ProgressBarSubclassProc));
+ dat->hwndDesc=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ _T("Static"),
+ (dat->fTimeFlags&SDWTF_ST_TIME)?TranslateT("Shutdown at:"):TranslateT("Time left:"),
+ WS_CHILD|WS_VISIBLE|SS_LEFTNOWORDWRAP|SS_NOTIFY,
+ GetSystemMetrics(SM_CXICON)+5,
+ (GetSystemMetrics(SM_CXICON)/2),
+ 75,
+ (GetSystemMetrics(SM_CXICON)/2),
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ dat->hwndTime=CreateWindowEx(WS_EX_NOPARENTNOTIFY,
+ _T("Static"),
+ NULL, /* hh:mm:ss */
+ WS_CHILD|WS_VISIBLE|SS_RIGHT|SS_NOTIFY|SS_ENDELLIPSIS,
+ (GetSystemMetrics(SM_CXICON)+80),
+ (GetSystemMetrics(SM_CXICON)/2),
+ 35,
+ (GetSystemMetrics(SM_CXICON)/2),
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ if(dat->hwndTime==NULL) return -1; /* creation failed, calls WM_DESTROY */
+ /* create tooltips */
+ if(IsWinVer98Plus() || IsWinVer2000Plus()) {
+ TTTOOLINFO ti;
+ dat->hwndToolTip=CreateWindowEx(WS_EX_TOPMOST,
+ TOOLTIPS_CLASS,
+ NULL,
+ WS_POPUP|TTS_ALWAYSTIP|TTS_NOPREFIX,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hwndFrame,
+ NULL,
+ params->hInstance,
+ NULL);
+ if(dat->hwndToolTip!=NULL) {
+ SetWindowPos(dat->hwndToolTip,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize=sizeof(ti);
+ ti.hwnd=hwndFrame;
+ ti.uFlags=TTF_IDISHWND|TTF_SUBCLASS|TTF_TRANSPARENT;
+ ti.lpszText=LPSTR_TEXTCALLBACK; /* commctl 4.70+ */
+ ti.uId=(UINT)dat->hwndTime; /* in-place tooltip */
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ ti.uFlags&=~TTF_TRANSPARENT;
+ ti.uId=(UINT)dat->hwndProgress;
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ if(dat->hwndDesc!=NULL) {
+ ti.uId=(UINT)dat->hwndDesc;
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ }
+ if(dat->hwndIcon!=NULL) {
+ ti.uId=(UINT)dat->hwndIcon;
+ SendMessage(dat->hwndToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);
+ }
+ }
+ }
+ /* init layout */
+ dat->hHookColorsChanged=HookEventMessage(ME_COLOUR_RELOAD,hwndFrame,M_REFRESH_COLORS);
+ dat->hHookFontsChanged=HookEventMessage(ME_FONT_RELOAD,hwndFrame,M_REFRESH_FONTS);
+ dat->hHookIconsChanged=HookEventMessage(ME_SKIN2_ICONSCHANGED,hwndFrame,M_REFRESH_ICONS);
+ SendMessage(hwndFrame,M_REFRESH_COLORS,0,0);
+ SendMessage(hwndFrame,M_REFRESH_FONTS,0,0);
+ SendMessage(hwndFrame,M_REFRESH_ICONS,0,0);
+ SendMessage(hwndFrame,M_SET_COUNTDOWN,0,0);
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ if(!SetTimer(hwndFrame,1,1000,NULL)) return -1; /* creation failed, calls WM_DESTROY */
+ return 0;
+ }
+ case WM_DESTROY:
+ { HICON hIcon;
+ if(dat==NULL) return 0;
+ UnhookEvent(dat->hHookColorsChanged);
+ UnhookEvent(dat->hHookFontsChanged);
+ UnhookEvent(dat->hHookIconsChanged);
+ /* other childs are destroyed automatically */
+ if(dat->hwndToolTip!=NULL) DestroyWindow(dat->hwndToolTip);
+ hIcon=(HICON)SendMessage(dat->hwndIcon,STM_SETIMAGE,IMAGE_ICON,(LPARAM)NULL);
+ IcoLib_ReleaseIcon(hIcon); /* does NULL check */
+ break;
+ }
+ case WM_NCDESTROY:
+ if(dat==NULL) return 0;
+ if(dat->hFont!=NULL) DeleteObject(dat->hFont);
+ if(dat->hbrBackground!=NULL) DeleteObject(dat->hbrBackground);
+ mir_free(dat);
+ SetWindowLong(hwndFrame,GWL_USERDATA,(LONG)NULL);
+ break;
+ case WM_SIZE:
+ { RECT rc;
+ LONG width,height;
+ HDWP hdwp;
+ UINT defflg=SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOACTIVATE;
+ SetRect(&rc,0,0,LOWORD(lParam),HIWORD(lParam)); /* width,height */
+ /* workaround: reduce flickering of frame in clist */
+ InvalidateRect(hwndFrame,&rc,FALSE);
+ hdwp=BeginDeferWindowPos(3);
+ /* progress */
+ width=rc.right-GetSystemMetrics(SM_CXICON)-10;
+ height=rc.bottom-(GetSystemMetrics(SM_CYICON)/2)-5;
+ hdwp=DeferWindowPos(hdwp,dat->hwndProgress,NULL,0,0,width,height,SWP_NOMOVE|defflg);
+ /* desc */
+ if(dat->hwndDesc!=NULL) hdwp=DeferWindowPos(hdwp,dat->hwndDesc,NULL,GetSystemMetrics(SM_CXICON)+5,5+height,0,0,SWP_NOSIZE|defflg);
+ /* time */
+ hdwp=DeferWindowPos(hdwp,dat->hwndTime,NULL,GetSystemMetrics(SM_CXICON)+85,5+height,width-80,(GetSystemMetrics(SM_CXICON)/2),defflg);
+ EndDeferWindowPos(hdwp);
+ PostMessage(hwndFrame,M_CHECK_CLIPPED,0,0);
+ return 0;
+ }
+ case M_REFRESH_COLORS:
+ { COLORREF clrBar;
+ if(FontService_GetColor(TranslateT("Automatic Shutdown"),TranslateT("Progress Bar"),&clrBar))
+ clrBar=GetDefaultColor(FRAMEELEMENT_BAR);
+ if(FontService_GetColor(TranslateT("Automatic Shutdown"),TranslateT("Background"),&dat->clrBackground))
+ dat->clrBackground=GetDefaultColor(FRAMEELEMENT_BKGRND);
+ if(dat->hbrBackground!=NULL) DeleteObject(dat->hbrBackground);
+ dat->hbrBackground=CreateSolidBrush(dat->clrBackground);
+ SendMessage(dat->hwndProgress,PBM_SETBARCOLOR,0,(LPARAM)clrBar);
+ SendMessage(dat->hwndProgress,PBM_SETBKCOLOR,0,(LPARAM)dat->clrBackground);
+ InvalidateRect(hwndFrame,NULL,TRUE);
+ return 0;
+ }
+ case M_REFRESH_ICONS:
+ if(dat->hwndIcon!=NULL)
+ IcoLib_ReleaseIcon((HICON)SendMessage(dat->hwndIcon,STM_SETIMAGE,IMAGE_ICON,(LPARAM)IcoLib_GetIcon("AutoShutdown_Header")));
+ if(hFrame) /* refresh frame title icon */
+ IcoLib_ReleaseIcon(SetFrameTitleIcon(hFrame,IcoLib_GetIcon("AutoShutdown_Active")));
+ return 0;
+ case M_REFRESH_FONTS:
+ { LOGFONT lf;
+ if(!FontService_GetFont(TranslateT("Automatic Shutdown"),TranslateT("Countdown on Frame"),&dat->clrText,&lf)) {
+ if(dat->hFont!=NULL) DeleteObject(dat->hFont);
+ dat->hFont=CreateFontIndirect(&lf);
+ }
+ else {
+ dat->clrText=GetDefaultColor(FRAMEELEMENT_TEXT);
+ if(GetDefaultFont(&lf)!=NULL) {
+ if(dat->hFont!=NULL) DeleteObject(dat->hFont);
+ dat->hFont=CreateFontIndirect(&lf);
+ }
+ }
+ if(dat->hwndDesc!=NULL)
+ SendMessage(dat->hwndDesc,WM_SETFONT,(WPARAM)dat->hFont,FALSE);
+ SendMessage(dat->hwndTime,WM_SETFONT,(WPARAM)dat->hFont,FALSE);
+ InvalidateRect(hwndFrame,NULL,FALSE);
+ return 0;
+ }
+ case WM_SYSCOLORCHANGE:
+ SendMessage(hwndFrame,M_REFRESH_COLORS,0,0);
+ break;
+ case WM_SETTINGCHANGE: /* colors depend on windows settings */
+ SendMessage(hwndFrame,M_REFRESH_COLORS,0,0);
+ SendMessage(hwndFrame,M_REFRESH_FONTS,0,0);
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ RedrawWindow(hwndFrame,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_ERASE);
+ break;
+ case WM_TIMECHANGE: /* windows system clock changed */
+ SendMessage(hwndFrame,M_SET_COUNTDOWN,0,0);
+ PostMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ break;
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORSTATIC:
+ SetTextColor((HDC)wParam,dat->clrText);
+ SetBkColor((HDC)wParam,dat->clrBackground);
+ return (BOOL)dat->hbrBackground;
+ case WM_ERASEBKGND:
+ { RECT rc;
+ if(dat->hbrBackground!=NULL && GetClientRect(hwndFrame,&rc)) {
+ FillRect((HDC)wParam,&rc,dat->hbrBackground);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ case M_SET_COUNTDOWN:
+ if(dat->fTimeFlags&SDWTF_ST_TIME) {
+ dat->settingLastTime=(time_t)DBGetContactSettingDword(NULL,"AutoShutdown","TimeStamp",SETTING_TIMESTAMP_DEFAULT);
+ dat->countdown=time(NULL);
+ if(dat->settingLastTime>dat->countdown) dat->countdown=dat->settingLastTime-dat->countdown;
+ else dat->countdown=0;
+ }
+ else if(dat->flags&FWPDF_COUNTDOWNINVALID) {
+ dat->countdown=(time_t)DBGetContactSettingDword(NULL,"AutoShutdown","Countdown",SETTING_COUNTDOWN_DEFAULT);
+ dat->countdown*=(time_t)DBGetContactSettingDword(NULL,"AutoShutdown","CountdownUnit",SETTING_COUNTDOWNUNIT_DEFAULT);
+ }
+ dat->flags&=~FWPDF_COUNTDOWNINVALID;
+ /* commctl 4.70+, Win95: 1-100 will work fine (wrap around) */
+ SendMessage(dat->hwndProgress,PBM_SETRANGE32,(WPARAM)0,(LPARAM)dat->countdown);
+ return 0;
+ case WM_TIMER:
+ if(dat==NULL) return 0;
+ if(dat->countdown!=0 && !(dat->flags&FWPDF_COUNTDOWNINVALID) && !(dat->flags&FWPDF_PAUSED)) {
+ dat->countdown--;
+ PostMessage(dat->hwndProgress,PBM_STEPIT,0,0);
+ }
+ if(IsWindowVisible(hwndFrame)) PostMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ if(dat->countdown==0) {
+ SendMessage(hwndFrame,M_CLOSE_COUNTDOWN,0,0);
+ ServiceShutdown(0,TRUE);
+ ServiceStopWatcher(0,0);
+ }
+ return 0;
+ case WM_SHOWWINDOW:
+ /* the text is kept unchanged while hidden */
+ if((BOOL)wParam) SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ break;
+ case M_UPDATE_COUNTDOWN:
+ if(dat->flags&FWPDF_PAUSED && !(dat->flags&FWPDF_PAUSEDSHOWN)) {
+ SetWindowText(dat->hwndTime,TranslateT("Paused"));
+ dat->flags|=FWPDF_PAUSEDSHOWN;
+ }
+ else {
+ TCHAR szOutput[256];
+ if(dat->fTimeFlags&SDWTF_ST_TIME)
+ GetFormatedDateTime(szOutput,SIZEOF(szOutput),dat->settingLastTime,TRUE);
+ else GetFormatedCountdown(szOutput,SIZEOF(szOutput),dat->countdown);
+ SetWindowText(dat->hwndTime,szOutput);
+ PostMessage(hwndFrame,M_CHECK_CLIPPED,0,0);
+ /* update tooltip text (if shown) */
+ if(dat->hwndToolTip!=NULL && !(dat->flags&FWPDF_PAUSED)) {
+ TTTOOLINFO ti;
+ ti.cbSize=sizeof(ti);
+ if(SendMessage(dat->hwndToolTip,TTM_GETCURRENTTOOL,0,(LPARAM)&ti) && (HWND)ti.uId!=dat->hwndIcon)
+ SendMessage(dat->hwndToolTip,TTM_UPDATE,0,0);
+ } else dat->flags&=~FWPDF_PAUSEDSHOWN;
+ }
+ return 0;
+ case M_CLOSE_COUNTDOWN:
+ KillTimer(hwndFrame,1);
+ dat->countdown=0;
+ dat->flags&=~FWPDF_PAUSED;
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ dat->flags|=FWPDF_COUNTDOWNINVALID;
+ /* step up to upper range */
+ SendMessage(dat->hwndProgress,PBM_SETPOS,SendMessage(dat->hwndProgress,PBM_GETRANGE,FALSE,0),0);
+ SetWindowLong(dat->hwndProgress,GWL_STYLE,GetWindowLong(dat->hwndProgress,GWL_STYLE)|PBM_SETMARQUEE);
+ SendMessage(dat->hwndProgress,PBM_SETMARQUEE,TRUE,10); /* marquee for rest of time */
+ return 0;
+ case M_PAUSE_COUNTDOWN:
+ if(dat->flags&FWPDF_PAUSED) {
+ /* unpause */
+ dat->flags&=~(FWPDF_PAUSED|FWPDF_PAUSEDSHOWN);
+ SendMessage(hwndFrame,M_SET_COUNTDOWN,0,0);
+ SendMessage(dat->hwndProgress,PBM_SETSTATE,PBST_NORMAL,0); /* WinVista+ */
+ }
+ else {
+ /* pause */
+ dat->flags|=FWPDF_PAUSED;
+ SendMessage(dat->hwndProgress,PBM_SETSTATE,PBST_PAUSED,0); /* WinVista+ */
+ }
+ SendMessage(hwndFrame,M_UPDATE_COUNTDOWN,0,0);
+ return 0;
+ case WM_CONTEXTMENU:
+ { HMENU hContextMenu;
+ POINT pt;
+ if(dat->flags&FWPDF_COUNTDOWNINVALID) return 0;
+ POINTSTOPOINT(pt,MAKEPOINTS(lParam));
+ if(pt.x==-1 && pt.y==-1) { /* invoked by keyboard */
+ RECT rc;
+ /* position in middle above rect */
+ if(!GetWindowRect(hwndFrame, &rc)) return 0;
+ pt.x=rc.left+((int)(rc.right-rc.left)/2);
+ pt.y=rc.top+((int)(rc.bottom-rc.top)/2);
+ }
+ hContextMenu=CreatePopupMenu();
+ if(hContextMenu!=NULL) {
+ AppendMenu(hContextMenu,MF_STRING,MENUITEM_PAUSECOUNTDOWN,(dat->flags&FWPDF_PAUSED)?TranslateT("&Unpause Countdown"):TranslateT("&Pause Countdown"));
+ SetMenuDefaultItem(hContextMenu,MENUITEM_PAUSECOUNTDOWN,FALSE);
+ AppendMenu(hContextMenu,MF_STRING,MENUITEM_STOPCOUNTDOWN,TranslateT("&Cancel Countdown"));
+ TrackPopupMenuEx(hContextMenu,TPM_LEFTALIGN|TPM_TOPALIGN|TPM_HORPOSANIMATION|TPM_VERPOSANIMATION|TPM_RIGHTBUTTON,pt.x,pt.y,hwndFrame,NULL);
+ DestroyMenu(hContextMenu);
+ }
+ return 0;
+ }
+ case WM_LBUTTONDBLCLK:
+ if(!(dat->flags&FWPDF_COUNTDOWNINVALID))
+ SendMessage(hwndFrame,M_PAUSE_COUNTDOWN,0,0);
+ return 0;
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case MENUITEM_STOPCOUNTDOWN:
+ /* close only countdown window when other watcher types running */
+ if(dat->fTimeFlags&~(SDWTF_SPECIFICTIME|SDWTF_ST_MASK))
+ CloseCountdownFrame(); /* something else is running */
+ else ServiceStopWatcher(0,0); /* calls CloseCountdownFrame() */
+ return 0;
+ case MENUITEM_PAUSECOUNTDOWN:
+ SendMessage(hwndFrame,M_PAUSE_COUNTDOWN,0,0);
+ return 0;
+ }
+ break;
+ case M_CHECK_CLIPPED: /* for in-place tooltip on dat->hwndTime */
+ { RECT rc;
+ HDC hdc;
+ SIZE size;
+ HFONT hFontPrev=NULL;
+ TCHAR szOutput[256];
+ dat->flags&=~FWPDF_TIMEISCLIPPED;
+ if(GetWindowText(dat->hwndTime,szOutput,SIZEOF(szOutput)-1))
+ if(GetClientRect(dat->hwndTime,&rc)) {
+ hdc=GetDC(dat->hwndTime);
+ if(hdc!=NULL) {
+ if(dat->hFont!=NULL)
+ hFontPrev=SelectObject(hdc,dat->hFont);
+ if(GetTextExtentPoint32(hdc,szOutput,lstrlen(szOutput),&size))
+ if(size.cx>=(rc.right-rc.left))
+ dat->flags&=FWPDF_TIMEISCLIPPED;
+ if(dat->hFont!=NULL)
+ SelectObject(hdc,hFontPrev);
+ ReleaseDC(dat->hwndTime,hdc);
+ }
+ }
+ return 0;
+ }
+ case WM_NOTIFY:
+ if(((NMHDR*)lParam)->hwndFrom==dat->hwndToolTip)
+ switch(((NMHDR*)lParam)->code) {
+ case TTN_SHOW: /* 'in-place' tooltip on dat->hwndTime */
+ if(dat->flags&FWPDF_TIMEISCLIPPED && (HWND)wParam==dat->hwndTime && IsWinVer2000Plus()) {
+ RECT rc;
+ if(GetWindowRect(dat->hwndTime,&rc)) {
+ SetWindowLong(dat->hwndToolTip,GWL_STYLE,GetWindowLong(dat->hwndToolTip,GWL_STYLE)|TTS_NOANIMATE);
+ SetWindowLong(dat->hwndToolTip,GWL_EXSTYLE,GetWindowLong(dat->hwndToolTip,GWL_EXSTYLE)|WS_EX_TRANSPARENT);
+ SendMessage(dat->hwndToolTip,TTM_ADJUSTRECT,TRUE,(LPARAM)&rc);
+ SetWindowPos(dat->hwndToolTip,NULL,rc.left,rc.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+ return TRUE; /* self-defined position */
+ }
+ }
+ SetWindowLong(dat->hwndToolTip,GWL_STYLE,GetWindowLong(dat->hwndToolTip,GWL_STYLE)&(~TTS_NOANIMATE));
+ SetWindowLong(dat->hwndToolTip,GWL_EXSTYLE,GetWindowLong(dat->hwndToolTip,GWL_EXSTYLE)&(~WS_EX_TRANSPARENT));
+ return 0;
+ case TTN_POP:
+ /* workaround #5: frame does not get redrawn after
+ * in-place tooltip hidden on dat->hwndTime */
+ RedrawWindow(hwndCountdownFrame,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_ERASE);
+ return 0;
+ case TTN_NEEDTEXT:
+ { NMTTDISPINFO *ttdi=(NMTTDISPINFO*)lParam;
+ if(dat->flags&FWPDF_TIMEISCLIPPED && (HWND)wParam==dat->hwndTime) {
+ if(GetWindowText(dat->hwndTime,ttdi->szText,SIZEOF(ttdi->szText)-1))
+ ttdi->lpszText=ttdi->szText;
+ }
+ else if((HWND)wParam==dat->hwndIcon)
+ ttdi->lpszText=TranslateT("Automatic Shutdown");
+ else {
+ TCHAR szTime[SIZEOF(ttdi->szText)];
+ if(dat->fTimeFlags&SDWTF_ST_TIME)
+ GetFormatedDateTime(szTime,SIZEOF(szTime),dat->settingLastTime,FALSE);
+ else GetFormatedCountdown(szTime,SIZEOF(szTime),dat->countdown);
+ mir_sntprintf(ttdi->szText,SIZEOF(ttdi->szText),_T("%s %s"),(dat->fTimeFlags&SDWTF_ST_TIME)?TranslateT("Shutdown at:"):TranslateT("Time left:"),szTime);
+ ttdi->lpszText=ttdi->szText;
+ }
+ return 0;
+ }
+ }
+ break;
+ }
+ return DefWindowProc(hwndFrame,msg,wParam,lParam);
+}
+
+/************************* Show Frame *********************************/
+
+void ShowCountdownFrame(WORD fTimeFlags)
+{
+ hwndCountdownFrame=CreateWindowEx(WS_EX_CONTROLPARENT|WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT,
+ COUNTDOWNFRAME_CLASS,
+ NULL,
+ WS_CHILD|WS_TABSTOP,
+ 0, 0,
+ GetSystemMetrics(SM_CXICON)+103,
+ GetSystemMetrics(SM_CYICON)+2,
+ (HWND)CallService(MS_CLUI_GETHWND,0,0),
+ NULL,
+ hInst,
+ &fTimeFlags);
+ if(hwndCountdownFrame==NULL) return;
+
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ CLISTFrame clf;
+ ZeroMemory(&clf,sizeof(clf));
+ clf.cbSize=sizeof(clf);
+ clf.hIcon=IcoLib_GetIcon("AutoShutdown_Active"); /* CListFrames does not make a copy */
+ clf.align=alBottom;
+ clf.height=GetSystemMetrics(SM_CYICON);
+ clf.Flags=F_VISIBLE|F_SHOWTBTIP|F_NOBORDER|F_SKINNED;
+ clf.name=Translate("AutoShutdown");
+ clf.TBname=Translate("Automatic Shutdown");
+ clf.hWnd=hwndCountdownFrame;
+ hFrame=(WORD)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&clf,0);
+ if(hFrame) {
+ ShowWindow(hwndCountdownFrame,SW_SHOW);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,hFrame),(LPARAM)clf.name);
+ /* HACKS TO FIX CLUI FRAMES:
+ * *** why is CLUIFrames is horribly buggy??! *** date: sept 2005, nothing changed until sept 2006
+ * workaround #1: MS_CLIST_FRAMES_REMOVEFRAME does not finish with destroy cycle (clist_modern, clist_nicer crashes) */
+ SendMessage((HWND)CallService(MS_CLUI_GETHWND,0,0),WM_SIZE,0,0);
+ /* workaround #2: drawing glitch after adding a frame (frame positioned wrongly when hidden) */
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,hFrame,FU_FMPOS|FU_FMREDRAW);
+ /* workaround #3: MS_CLIST_FRAMES_SETFRAMEOPTIONS does cause redrawing problems */
+ if(!(CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,hFrame),0)&F_VISIBLE))
+ CallService(MS_CLIST_FRAMES_SHFRAME,hFrame,0);
+ /* workaround #4: MS_CLIST_FRAMES_SHFRAME does cause redrawing problems when frame was hidden */
+ RedrawWindow(hwndCountdownFrame,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_ERASE);
+ /* workaround #5: for in-place tooltip TTN_POP
+ * workaround #6 and #7: see CloseCountdownFrame() */
+ }
+ }
+}
+
+void CloseCountdownFrame(void)
+{
+ if(hwndCountdownFrame!=NULL) {
+ SendMessage(hwndCountdownFrame,M_CLOSE_COUNTDOWN,0,0);
+ if(hFrame) {
+ IcoLib_ReleaseIcon(SetFrameTitleIcon(hFrame,NULL));
+ /* HACKS TO FIX CLUIFrames:
+ * workaround #6: MS_CLIST_FRAMES_REMOVEFRAME does not finish with
+ * destroy cycle (clist_modern, clist_nicer crashes) */
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,hFrame),(LPARAM)CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,hFrame),0)&(~F_VISIBLE));
+ #if !defined(_DEBUG)
+ /* workaround #7: MS_CLIST_FRAMES_REMOVEFRAME crashes after two calls
+ * clist_nicer crashes after some calls (bug in it) */
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME,hFrame,0);
+ #endif
+ }
+ else DestroyWindow(hwndCountdownFrame);
+ hwndCountdownFrame=NULL;
+ hFrame=0;
+ }
+
+}
+
+/************************* Misc ***************************************/
+
+static int FrameModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ LOGFONT lf;
+ COLORREF clr;
+ HMODULE hUxThemeDLL;
+ BOOL (WINAPI *pfnIsThemeActive)(VOID);
+ /* built-in font module is not available before this hook */
+ clr=GetDefaultColor(FRAMEELEMENT_TEXT);
+ FontService_RegisterFont("AutoShutdown","CountdownFont",TranslateT("Automatic Shutdown"),TranslateT("Countdown on Frame"),0,FALSE,GetDefaultFont(&lf),clr);
+ clr=GetDefaultColor(FRAMEELEMENT_BKGRND);
+ FontService_RegisterColor("AutoShutdown","BkgColor",TranslateT("Automatic Shutdown"),TranslateT("Background"),clr);
+ /* progressbar color can only be changed in windows classic theme */
+ /* FIXME: should be registered/unregistered on WM_THEMECHANGED/ME_OPT_INITIALISE msg,
+ * currently not possible as no such font service exists */
+ hUxThemeDLL=LoadLibraryA("UXTHEME"); /* all ascii */
+ *(PROC*)&pfnIsThemeActive=(hUxThemeDLL!=NULL)?GetProcAddress(hUxThemeDLL,"IsThemeActive"):NULL;
+ if(pfnIsThemeActive==NULL || !pfnIsThemeActive()) {
+ /* progressbar color can only be changed with classic theme */
+ clr=GetDefaultColor(FRAMEELEMENT_BAR);
+ FontService_RegisterColor("AutoShutdown","ProgressColor",TranslateT("Automatic Shutdown"),TranslateT("Progress Bar"),clr);
+ }
+ if(hUxThemeDLL!=NULL) FreeLibrary(hUxThemeDLL);
+ }
+ return 0;
+}
+
+int InitFrame(void)
+{
+ WNDCLASSEX wcx;
+ ZeroMemory(&wcx,sizeof(wcx));
+ wcx.cbSize =sizeof(wcx);
+ wcx.style =CS_DBLCLKS|CS_PARENTDC;
+ wcx.lpfnWndProc =FrameWndProc;
+ wcx.hInstance =hInst;
+ wcx.hCursor =(HCURSOR)LoadImage(NULL,IDC_ARROW,IMAGE_CURSOR,0,0,LR_SHARED);
+ wcx.lpszClassName =COUNTDOWNFRAME_CLASS;
+ if(!RegisterClassEx(&wcx)) return 1;
+
+ hwndCountdownFrame=NULL;
+ hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,FrameModulesLoaded);
+ return 0;
+}
+
+void UninitFrame(void)
+{
+ /* frame closed by UninitWatcher() */
+ UnregisterClass(COUNTDOWNFRAME_CLASS,hInst); /* fails if window still exists */
+ UnhookEvent(hHookModulesLoaded);
+}