From 49566229022ee6e96eac0888f9c0501fcd92033b Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Tue, 3 Jul 2012 17:21:34 +0000 Subject: AutoShutdown: renamed to .cpp git-svn-id: http://svn.miranda-ng.org/main/trunk@736 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/AutoShutdown/frame.cpp | 644 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+) create mode 100644 plugins/AutoShutdown/frame.cpp (limited to 'plugins/AutoShutdown/frame.cpp') 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); +} -- cgit v1.2.3