#include "../commonheaders.h" extern HINSTANCE g_hInst; HANDLE hStatusBarShowToolTipEvent,hStatusBarHideToolTipEvent; boolean canloadstatusbar = FALSE; HWND helperhwnd = 0; HANDLE hFrameHelperStatusBar; void CluiProtocolStatusChanged(int parStatus, const char* szProto); INT_PTR GetConnectingIconService (WPARAM wParam,LPARAM lParam); int RecreateStatusBar(HWND); int UseOwnerDrawStatusBar; #define TM_STATUSBAR 23435234 #define TM_STATUSBARHIDE 23435235 boolean tooltipshoing; WNDPROC OldWindowProc = NULL; POINT lastpnt; RECT OldRc = {0}; static HBITMAP hBmpBackground; static int backgroundBmpUse; static COLORREF bkColour; extern BYTE showOpts; int extraspace; int OnStatusBarBackgroundChange() { { DBVARIANT dbv; showOpts = DBGetContactSettingByte(NULL,"CLUI","SBarShow",1); bkColour = DBGetContactSettingDword(NULL,"StatusBar","BkColour",CLCDEFAULT_BKCOLOUR); if (hBmpBackground) {DeleteObject(hBmpBackground); hBmpBackground = NULL;} if (DBGetContactSettingByte(NULL,"StatusBar","UseBitmap",CLCDEFAULT_USEBITMAP)) { if (!DBGetContactSettingString(NULL,"StatusBar","BkBitmap",&dbv)) { hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal); mir_free(dbv.pszVal); } } backgroundBmpUse = DBGetContactSettingWord(NULL,"StatusBar","BkBmpUse",CLCDEFAULT_BKBMPUSE); extraspace = DBGetContactSettingDword(NULL,"StatusBar","BkExtraSpace",0); } RecreateStatusBar(pcli->hwndContactList); if (pcli->hwndStatus) InvalidateRect(pcli->hwndStatus,NULL,TRUE); return 0; } void DrawDataForStatusBar(LPDRAWITEMSTRUCT dis) { //LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam; ProtocolData *PD = (ProtocolData *)dis->itemData; char *szProto = (char*)dis->itemData; int status,x; SIZE textSize; boolean NeedDestroy = FALSE; HICON hIcon; HRGN hrgn; if (PD == NULL){return;} if (dis->hDC == NULL) {return;} //clip it hrgn = CreateRectRgn(dis->rcItem.left, dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom); SelectClipRgn(dis->hDC, hrgn); szProto = PD->RealName; #ifdef _DEBUG { //char buf[512]; //sprintf(buf,"proto: %s draw at pos: %d\r\n",szProto,dis->rcItem.left); //OutputDebugStringA(buf); } #endif status = CallProtoService(szProto,PS_GETSTATUS,0,0); SetBkMode(dis->hDC,TRANSPARENT); x = dis->rcItem.left+extraspace; if (showOpts&1) { if ((DBGetContactSettingByte(NULL,"CLUI","UseConnectingIcon",1) == 1) && status < ID_STATUS_OFFLINE) { hIcon = (HICON)GetConnectingIconService((WPARAM)szProto,0); if (hIcon) { NeedDestroy = TRUE; }else { hIcon = LoadSkinnedProtoIcon(szProto,status); } }else { hIcon = LoadSkinnedProtoIcon(szProto,status); } DrawIconEx(dis->hDC,x,(dis->rcItem.top+dis->rcItem.bottom-GetSystemMetrics(SM_CYSMICON))>>1,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL); if (NeedDestroy) DestroyIcon(hIcon); x += GetSystemMetrics(SM_CXSMICON)+2; } else x += 2; if (showOpts&2) { TCHAR szName[64]; PROTOACCOUNT* pa = ProtoGetAccount(szProto); mir_sntprintf(szName, SIZEOF(szName), _T("%s%s"), pa->tszAccountName, showOpts&4 ? _T(" ") : _T("")); GetTextExtentPoint32(dis->hDC, szName, (int)_tcslen(szName), &textSize); TextOut(dis->hDC,x,(dis->rcItem.top+dis->rcItem.bottom-textSize.cy)>>1,szName,lstrlen(szName)); x += textSize.cx; } if (showOpts&4) { TCHAR *szStatus = pcli->pfnGetStatusModeDescription(status, 0); if (!szStatus) szStatus = _T(""); GetTextExtentPoint32(dis->hDC,szStatus,lstrlen(szStatus),&textSize); TextOut(dis->hDC,x,(dis->rcItem.top+dis->rcItem.bottom-textSize.cy)>>1,szStatus,lstrlen(szStatus)); } SelectClipRgn(dis->hDC, NULL); DeleteObject(hrgn); } void DrawBackGround(HWND hwnd,HDC mhdc) { HDC hdcMem,hdc; RECT clRect,*rcPaint; int yScroll = 0; int y; PAINTSTRUCT paintst = {0}; HBITMAP hBmpOsb,holdbmp; DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE); int grey = 0; HFONT oFont; HBRUSH hBrushAlternateGrey = NULL; HFONT hFont; //InvalidateRect(hwnd,0,FALSE); hFont = (HFONT)SendMessage(hwnd,WM_GETFONT,0,0); if (mhdc) { hdc = mhdc; rcPaint = NULL; }else { hdc = BeginPaint(hwnd,&paintst); rcPaint = &(paintst.rcPaint); } GetClientRect(hwnd,&clRect); if (rcPaint == NULL) rcPaint = &clRect; if (rcPaint->right-rcPaint->left == 0||rcPaint->top-rcPaint->bottom == 0) rcPaint = &clRect; y = -yScroll; hdcMem = CreateCompatibleDC(hdc); hBmpOsb = CreateBitmap(clRect.right,clRect.bottom,1,GetDeviceCaps(hdc,BITSPIXEL),NULL); holdbmp = (HBITMAP)SelectObject(hdcMem,hBmpOsb); oFont = (HFONT)SelectObject(hdcMem,hFont); SetBkMode(hdcMem,TRANSPARENT); { HBRUSH hBrush,hoBrush; hBrush = CreateSolidBrush(bkColour); hoBrush = (HBRUSH)SelectObject(hdcMem,hBrush); FillRect(hdcMem,rcPaint,hBrush); SelectObject(hdcMem,hoBrush); DeleteObject(hBrush); if (hBmpBackground) { BITMAP bmp; int x,y; int maxx,maxy; int destw,desth; GetObject(hBmpBackground,sizeof(bmp),&bmp); HDC hdcBmp = CreateCompatibleDC(hdcMem); HDC holdbackbmp = (HDC)SelectObject(hdcBmp,hBmpBackground); y = backgroundBmpUse&CLBF_SCROLL?-yScroll:0; maxx = backgroundBmpUse&CLBF_TILEH?clRect.right:1; maxy = backgroundBmpUse&CLBF_TILEV?maxy = rcPaint->bottom:y+1; switch(backgroundBmpUse&CLBM_TYPE) { case CLB_STRETCH: if (backgroundBmpUse&CLBF_PROPORTIONAL) { if (clRect.right*bmp.bmHeighttop-desth) continue; for (x = 0;xhwndStatus,SB_GETTEXT,(WPARAM)nPanel,(LPARAM)0); if (PD == NULL){ continue; } SendMessage(hwnd,SB_GETRECT,(WPARAM)nPanel,(LPARAM)&rc); //rc.left += startoffset; //if (rc.left>=rc.right) rc.left = rc.right-1; rc.top = 0; rc.left = nPanel*sectwidth+startoffset; rc.right = rc.left+sectwidth-1; ds.rcItem = rc; ds.itemData = (ULONG_PTR)PD; ds.itemID = nPanel; DrawDataForStatusBar(&ds); } } BitBlt(hdc,rcPaint->left,rcPaint->top,rcPaint->right-rcPaint->left,rcPaint->bottom-rcPaint->top,hdcMem,rcPaint->left,rcPaint->top,SRCCOPY); SelectObject(hdcMem,holdbmp); SelectObject(hdcMem,oFont); DeleteObject(hBmpOsb); DeleteDC(hdcMem); paintst.fErase = FALSE; //DeleteObject(hFont); if (!mhdc) EndPaint(hwnd,&paintst); } LRESULT CALLBACK StatusBarOwnerDrawProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { if (UseOwnerDrawStatusBar) { switch(uMsg) { case WM_ERASEBKGND: { //DrawBackGround(hwnd); return 0; } case WM_PRINT: { DrawBackGround(hwnd,(HDC)wParam); return 0; } case WM_PAINT: { DrawBackGround(hwnd,0); return 0; } } } return (CallWindowProc(OldWindowProc,hwnd,uMsg,wParam,lParam) ); } LRESULT CALLBACK StatusHelperProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: { { tooltipshoing = FALSE; //HWND label; //label = CreateWindow("static","Top window",WS_VISIBLE|WS_CHILD ,2,2,120,60,hwnd,NULL,g_hInst,0); //SendMessage(label,WM_SETFONT,(WPARAM)TitleBarFont,0); } return(FALSE); } case WM_GETMINMAXINFO:{ RECT rct; if (pcli->hwndStatus == 0){break;} GetWindowRect(pcli->hwndStatus,&rct); memset((LPMINMAXINFO)lParam,0,sizeof(MINMAXINFO)); ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 5; ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rct.bottom-rct.top; ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = 1600; ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = rct.bottom-rct.top; return 0; } case WM_NCHITTEST: { } case WM_SHOWWINDOW: { { int res; if (hFrameHelperStatusBar) { res = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS,hFrameHelperStatusBar),0); DBWriteContactSettingByte(0,"CLUI","ShowSBar",(BYTE)((res&F_VISIBLE)?1:0)); } } if (tooltipshoing){ NotifyEventHooks(hStatusBarHideToolTipEvent,0,0); tooltipshoing = FALSE; } return 0; // } case WM_TIMER: { if (wParam == TM_STATUSBARHIDE) { KillTimer(hwnd,TM_STATUSBARHIDE); if (tooltipshoing){ NotifyEventHooks(hStatusBarHideToolTipEvent,0,0); tooltipshoing = FALSE; } } if (wParam == TM_STATUSBAR) { POINT pt; KillTimer(hwnd,TM_STATUSBAR); GetCursorPos(&pt); if (pt.x == lastpnt.x&&pt.y == lastpnt.y) { { int i,nParts; ProtocolData *PD; RECT rc; ScreenToClient(pcli->hwndStatus,&pt); nParts = SendMessage(pcli->hwndStatus,SB_GETPARTS,0,0); for (i = 0;ihwndStatus,SB_GETRECT,i,(LPARAM)&rc); if (PtInRect(&rc,pt)) { PD = (ProtocolData *)SendMessage(pcli->hwndStatus,SB_GETTEXT,i,(LPARAM)0); if (PD == NULL){return 0;} NotifyEventHooks(hStatusBarShowToolTipEvent,(WPARAM)PD->RealName,0); SetTimer(hwnd,TM_STATUSBARHIDE,DBGetContactSettingWord(NULL,"CLUIFrames","HideToolTipTime",5000),0); tooltipshoing = TRUE; break; } } } } } return 0; } case WM_SETCURSOR: { { POINT pt; GetCursorPos(&pt); if (pt.x == lastpnt.x&&pt.y == lastpnt.y) { return 0; } lastpnt = pt; if (tooltipshoing){ KillTimer(hwnd,TM_STATUSBARHIDE); NotifyEventHooks(hStatusBarHideToolTipEvent,0,0); tooltipshoing = FALSE; } KillTimer(hwnd,TM_STATUSBAR); SetTimer(hwnd,TM_STATUSBAR,DBGetContactSettingWord(NULL,"CLC","InfoTipHoverTime",750),0); return 0; } } case WM_NOTIFY: { if (lParam == 0){return 0;} if (((LPNMHDR)lParam)->hwndFrom == pcli->hwndStatus) { if (((LPNMHDR)lParam)->code == WM_NCHITTEST) { LPNMMOUSE lpnmmouse = (LPNMMOUSE) lParam; } ; } } case WM_CONTEXTMENU: KillTimer(hwnd,TM_STATUSBARHIDE); if (tooltipshoing) NotifyEventHooks(hStatusBarHideToolTipEvent,0,0); tooltipshoing = FALSE; case WM_MEASUREITEM: case WM_DRAWITEM: //parent do all work for us return(SendMessage(pcli->hwndContactList,msg,wParam,lParam)); case WM_MOVE: PostMessage(pcli->hwndStatus,WM_MOVE,wParam,lParam); case WM_SIZE: { RECT rc; int b; if (pcli->hwndStatus != 0) { GetClientRect(hwnd,&rc); b = LOWORD(lParam); if (b != 0&&(rc.right-rc.left) != (OldRc.right-OldRc.left)) { OldRc = rc; if (canloadstatusbar) if (DBGetContactSettingByte(NULL,"CLUI","UseOwnerDrawStatusBar",0)||DBGetContactSettingByte(NULL,"CLUI","EqualSections",1)) CluiProtocolStatusChanged(0,0); } if (msg == WM_SIZE) PostMessage(pcli->hwndStatus,WM_SIZE,wParam,lParam); if (pcli->hwndStatus != 0) InvalidateRect(pcli->hwndStatus,NULL,TRUE); return 0; } } default: return DefWindowProc(hwnd, msg, wParam, lParam); } return DefWindowProc(hwnd, msg, wParam, lParam); } HWND CreateStatusHelper(HWND parent) { WNDCLASS wndclass = {0}; TCHAR pluginname[] = _T("Statushelper"); if (GetClassInfo(g_hInst,pluginname,&wndclass) == 0 ) { wndclass.style = 0; wndclass.lpfnWndProc = StatusHelperProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = g_hInst; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = pluginname; RegisterClass(&wndclass); } return(CreateWindow(pluginname,pluginname, /*WS_THICKFRAME|*/WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, 0,0,0,0,parent,NULL,g_hInst,NULL)); } HANDLE CreateStatusBarFrame() { CLISTFrame Frame; int h; RECT rc; memset(&Frame,0,sizeof(Frame)); Frame.cbSize = sizeof(CLISTFrame); Frame.hWnd = helperhwnd; Frame.align = alBottom; Frame.hIcon = LoadSkinnedIcon (SKINICON_OTHER_MIRANDA); Frame.Flags = (DBGetContactSettingByte(NULL,"CLUI","ShowSBar",1)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_TCHAR; GetWindowRect(helperhwnd,&rc); h = rc.bottom-rc.top; Frame.height = (h == 0)?20:h; Frame.tname = _T("Status"); Frame.TBtname = TranslateT("Status Bar"); hFrameHelperStatusBar = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0); return hFrameHelperStatusBar; } int RecreateStatusBar(HWND parent) { if (pcli->hwndStatus) { FreeProtocolData(); DestroyWindow(pcli->hwndStatus); } pcli->hwndStatus = 0; if (hFrameHelperStatusBar) CallService(MS_CLIST_FRAMES_REMOVEFRAME,(WPARAM)hFrameHelperStatusBar,0); helperhwnd = CreateStatusHelper(parent); UseOwnerDrawStatusBar = DBGetContactSettingByte(NULL,"CLUI","UseOwnerDrawStatusBar",0); //create the status wnd pcli->hwndStatus = CreateStatusWindow( ( DBGetContactSettingByte(0,"CLUI","SBarUseSizeGrip",TRUE) && (!UseOwnerDrawStatusBar)?SBARS_SIZEGRIP:0)| WS_CHILD | (DBGetContactSettingByte(NULL,"CLUI","ShowSBar",1)?WS_VISIBLE:0), _T(""), helperhwnd, 0); OldWindowProc = (WNDPROC)GetWindowLongPtr(pcli->hwndStatus,GWLP_WNDPROC); SetWindowLongPtr(pcli->hwndStatus,GWLP_WNDPROC,(LONG_PTR)&StatusBarOwnerDrawProc); CreateStatusBarFrame(); { SetWindowPos(helperhwnd,NULL,1,1,1,1,SWP_NOZORDER); CluiProtocolStatusChanged(0,0); CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0); } return 0; } HWND CreateStatusBarhWnd(HWND parent) { RecreateStatusBar(parent); OnStatusBarBackgroundChange(); hStatusBarShowToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_SHOW_TOOLTIP); hStatusBarHideToolTipEvent = CreateHookableEvent(ME_CLIST_FRAMES_SB_HIDE_TOOLTIP); return pcli->hwndStatus; }