#include "main.h" #include "./statusbar.h" #include "./graphics.h" #include "./browserHost.h" #include "../winamp/wa_dlg.h" #include "../Plugins/General/gen_ml/ml_ipc_0313.h" #include "./ifc_skinhelper.h" #include "./ifc_wasabihelper.h" #include #include #include #define TEXTMARGIN_LEFT 3 #define TEXTMARGIN_TOP 1 #define TEXTMARGIN_RIGHT 3 #define TEXTMARGIN_BOTTOM 1 #define SBT_INFLATE_ID 31 #define SBT_INFLATE_DELAY 50 #define SBT_INFLATE_INTERVAL 20 #define SBT_MOUSEROLL_ID 32 #define SBT_MOUSEROLL_DELAY 50 #define SBT_MOUSEROLL_INTERVAL 20 #define SBF_MOUSEROLL 0x00000001 #define SBF_CACHEDFONT 0x00000002 typedef struct __STATUSBAR { UINT flags; RECT parentRect; SIZE textSize; LPWSTR pszText; INT cchText; INT cchTextMax; HFONT textFont; COLORREF rgbBk; COLORREF rgbText; HBRUSH brushBk; LONG desiredCX; LONG mouseY; LONG desiredY; HRGN windowRegion; HWND hBrowser; DWORD inflateTime; } STATUSBAR; typedef struct __STATUSBARMOUSEHOOK { HHOOK hHook; HWND hwnd; } STATUSBARMOUSEHOOK; static size_t tlsIndex = -1; #define GetStatusbar(__hwnd) ((STATUSBAR*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0)) static LRESULT CALLBACK Statusbar_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static void CALLBACK Statusbar_InflateTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId); static void CALLBACK Statusbar_MouseRollTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId); static LRESULT CALLBACK Statusbar_MouseHook(INT code, WPARAM wParam, LPARAM lParam); BOOL Statusbar_RegisterClass(HINSTANCE hInstance) { WNDCLASS wc; ATOM klassAtom; ifc_wasabihelper *wasabi; if (GetClassInfo(hInstance, NWC_ONLINEMEDIASTATUSBAR, &wc)) return TRUE; ZeroMemory(&wc, sizeof(WNDCLASS)); wc.hInstance = hInstance; wc.lpszClassName = NWC_ONLINEMEDIASTATUSBAR; wc.lpfnWndProc = Statusbar_WindowProc; wc.style = CS_PARENTDC | CS_SAVEBITS; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.cbWndExtra = sizeof(STATUSBAR*); klassAtom = RegisterClassW(&wc); if (0 == klassAtom) return FALSE; if (SUCCEEDED(Plugin_GetWasabiHelper(&wasabi))) { api_application *application; if (SUCCEEDED(wasabi->GetApplicationApi(&application))) { application->DirectMouseWheel_RegisterSkipClass(klassAtom); application->Release(); } wasabi->Release(); } return TRUE; } static BOOL Statusbar_GetTextSize(HWND hwnd, HFONT textFont, LPCWSTR pszText, INT cchText, SIZE *textSize) { HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); if (NULL == hdc) return FALSE; HFONT originalFont = (HFONT)SelectObject(hdc, textFont); BOOL result; if (0 == cchText) { TEXTMETRIC tm; result = GetTextMetrics(hdc, &tm); if (FALSE != result) { textSize->cx = 0; textSize->cy = tm.tmHeight; } } else { result = GetTextExtentPoint32(hdc, pszText, cchText, textSize); } SelectObject(hdc, originalFont); ReleaseDC(hwnd, hdc); return result; } static BOOL Statusbar_SetWindowPos(HWND hwnd, HWND hwndInsertAfter, INT x, INT y, INT cx, INT cy, UINT flags) { STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL != statusbar) { INT k = cy/4; if (k > cx) k = 0; POINT szPoint[5] = {0}; //szPoint[0].x = 0; //szPoint[0].y = 0; szPoint[1].x = cx - k; //szPoint[1].y = 0; szPoint[2].x = cx; szPoint[2].y = k; szPoint[3].x = cx; szPoint[3].y = cy; //szPoint[4].x = 0; szPoint[4].y = cy; HRGN rgn = CreatePolygonRgn(szPoint, ARRAYSIZE(szPoint), WINDING); if (0 != SetWindowRgn(hwnd, rgn, TRUE)) { if (NULL != statusbar->windowRegion) DeleteObject(statusbar->windowRegion); statusbar->windowRegion = rgn; } else { if (NULL != rgn) DeleteObject(rgn); } } if (0 == SetWindowPos(hwnd, hwndInsertAfter, x, y, cx, cy, flags)) return FALSE; return TRUE; } static void Statusbar_Inflate(HWND hwnd) { STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar) return; DWORD currentTime = GetTickCount(); DWORD kMult = (currentTime - statusbar->inflateTime) / SBT_INFLATE_INTERVAL; if (kMult < 4) kMult = 1; statusbar->inflateTime = currentTime; RECT windowRect; if (!GetWindowRect(hwnd, &windowRect)) return; DWORD windowStyle = GetWindowStyle(hwnd); LONG currentWidth = windowRect.right - windowRect.left; LONG targetCX = statusbar->desiredCX; if (0 == (SBS_ACTIVE & windowStyle) || targetCX < 16) targetCX = 0; if (currentWidth == targetCX) return; LONG width = currentWidth; LONG height = windowRect.bottom - windowRect.top; LONG step; while(kMult-- && width != targetCX) { if (width > targetCX) { step = (width - targetCX) / 3; if (step < 6) step = 6; width -= step; if (width < targetCX) width = targetCX; } else { step = (targetCX - width)*2 / 3; if (step < 48) step = 48; width += step; if (width > targetCX) width = targetCX; } } Statusbar_SetWindowPos(hwnd, HWND_TOP, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE); if (width < (windowRect.right - windowRect.left)) { if (NULL != statusbar->hBrowser) { RECT invalidRect; SetRect(&invalidRect, windowRect.left + width - 4, windowRect.top, windowRect.right, windowRect.bottom); MapWindowPoints(HWND_DESKTOP, statusbar->hBrowser, (POINT*)&invalidRect, 2); RedrawWindow(statusbar->hBrowser, &invalidRect, NULL, RDW_INVALIDATE | RDW_UPDATENOW); } } else { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME); } if (0 == width && 0 == (SBS_ACTIVE & windowStyle)) { ShowWindow(hwnd, SW_HIDE); } else { if (width != targetCX) { SetTimer(hwnd, SBT_INFLATE_ID, SBT_INFLATE_INTERVAL, Statusbar_InflateTimer); } } } static void Statusbar_UpdateLayout(HWND hwnd, BOOL fForce) { DWORD windowStyle = GetWindowStyle(hwnd); if (0 == (WS_VISIBLE & windowStyle) && FALSE == fForce) { if (0 == (SBS_UPDATELAYOUT & windowStyle)) SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | SBS_UPDATELAYOUT); return; } if (0 != (SBS_UPDATELAYOUT & windowStyle)) SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~SBS_UPDATELAYOUT); STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar) return; if (!Statusbar_GetTextSize(hwnd, statusbar->textFont, statusbar->pszText, statusbar->cchText, &statusbar->textSize)) ZeroMemory(&statusbar->textSize, sizeof(SIZE)); RECT windowRect; SetRect(&windowRect, statusbar->parentRect.left, statusbar->parentRect.bottom - statusbar->textSize.cy + statusbar->mouseY, statusbar->parentRect.left + statusbar->textSize.cx, statusbar->parentRect.bottom + statusbar->mouseY); if (0 != statusbar->textSize.cy) windowRect.top -= (TEXTMARGIN_TOP + TEXTMARGIN_BOTTOM); if (0 != statusbar->textSize.cx) windowRect.right += (TEXTMARGIN_LEFT + TEXTMARGIN_RIGHT); if (windowRect.right > statusbar->parentRect.right - 2) windowRect.right = statusbar->parentRect.right - 2; if ((windowRect.right - windowRect.left) < 20) windowRect.right = windowRect.left; if (windowRect.top < statusbar->parentRect.top + 20) windowRect.top = statusbar->parentRect.bottom; RECT previousRect; if (!GetWindowRect(hwnd, &previousRect)) SetRectEmpty(&previousRect); if (FALSE == EqualRect(&previousRect, &windowRect)) { LONG width = windowRect.right - windowRect.left; LONG height = windowRect.bottom - windowRect.top; LONG prevWidth = previousRect.right - previousRect.left; LONG prevHeight = previousRect.bottom - previousRect.top; LONG widthAdjust = 0; if (statusbar->desiredCX != prevWidth) { widthAdjust = width - prevWidth; } KillTimer(hwnd, SBT_INFLATE_ID); statusbar->desiredCX = width; statusbar->inflateTime = GetTickCount(); HWND hParent = GetParent(hwnd); MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&previousRect, 2); if (windowRect.left != previousRect.left || windowRect.top != previousRect.top || height != prevHeight || 0 != widthAdjust) { Statusbar_SetWindowPos(hwnd, HWND_TOP, windowRect.left, windowRect.top, prevWidth + widthAdjust, height, SWP_NOACTIVATE | SWP_NOOWNERZORDER); if (widthAdjust < 0 && NULL != statusbar->hBrowser) { RECT invalidRect; SetRect(&invalidRect, previousRect.left + prevWidth + widthAdjust - 4, previousRect.top, previousRect.left + prevWidth, previousRect.bottom); MapWindowPoints(HWND_DESKTOP, statusbar->hBrowser, (POINT*)&invalidRect, 2); RedrawWindow(statusbar->hBrowser, &invalidRect, NULL, RDW_INVALIDATE | RDW_UPDATENOW); } else if (0 != widthAdjust) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME); } } if (width > prevWidth) { Statusbar_Inflate(hwnd); } else { SetTimer(hwnd, SBT_INFLATE_ID, SBT_INFLATE_DELAY, Statusbar_InflateTimer); //Statusbar_Inflate(hwnd); } } else { InvalidateRect(hwnd, NULL, FALSE); } } static BOOL Statusbar_InstallMouseHook(HWND hwnd) { if (TLS_OUT_OF_INDEXES == tlsIndex) { tlsIndex = Plugin_TlsAlloc(); if (TLS_OUT_OF_INDEXES == tlsIndex) return FALSE; } STATUSBARMOUSEHOOK *hook = (STATUSBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex); if (NULL != hook) return FALSE; hook = (STATUSBARMOUSEHOOK*)calloc(1, sizeof(STATUSBARMOUSEHOOK)); if (NULL == hook) return FALSE; hook->hwnd = hwnd; hook->hHook = SetWindowsHookEx(WH_MOUSE, Statusbar_MouseHook, NULL, GetCurrentThreadId()); if (NULL == hook->hHook) { free(hook); return FALSE; } Plugin_TlsSetValue(tlsIndex, hook); return TRUE; } static void Statusbar_RemoveMouseHook() { if (TLS_OUT_OF_INDEXES == tlsIndex) return; STATUSBARMOUSEHOOK *hook = (STATUSBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex); if (NULL == hook) return; Plugin_TlsSetValue(tlsIndex, NULL); if (NULL != hook->hHook) UnhookWindowsHookEx(hook->hHook); free(hook); } static void CALLBACK Statusbar_InstallMouseHookApc(ULONG_PTR param) { Statusbar_InstallMouseHook((HWND)param); } static void CALLBACK Statusbar_RemoveMouseHookApc(ULONG_PTR param) { Statusbar_RemoveMouseHook(); } static void Statusbar_MouseRoll(HWND hwnd) { STATUSBAR *psb = GetStatusbar(hwnd); if (NULL == psb || 0 == (SBF_MOUSEROLL & psb->flags)) return; if (psb->desiredY == psb->mouseY) { psb->flags &= ~SBF_MOUSEROLL; return; } RECT windowRect; if (!GetWindowRect(hwnd, &windowRect)) return; windowRect.top -= psb->mouseY; if (psb->mouseY > psb->desiredY) { psb->mouseY -= 4; if (psb->mouseY < psb->desiredY) psb->mouseY = psb->desiredY; } else { psb->mouseY += 4; if (psb->mouseY > psb->desiredY) psb->mouseY = psb->desiredY; } windowRect.top += psb->mouseY; HWND hParent = GetParent(hwnd); if (NULL != hParent) { MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&windowRect, 1); SetWindowPos(hwnd, HWND_TOP, windowRect.left, windowRect.top, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_ASYNCWINDOWPOS); } if (psb->desiredY == psb->mouseY || 0 == SetTimer(hwnd, SBT_MOUSEROLL_ID, SBT_MOUSEROLL_INTERVAL, Statusbar_MouseRollTimer)) { psb->flags &= ~SBF_MOUSEROLL; } } static void Statusbar_MouseCheck(HWND hwnd, POINT pt) { STATUSBAR *psb = GetStatusbar(hwnd); if (NULL == psb) return; DWORD windowStyle = GetWindowStyle(hwnd); if (0 != (WS_DISABLED & windowStyle)) { if (0 != psb->desiredY) { psb->desiredY = 0; if (0 == (SBF_MOUSEROLL & psb->flags) && 0 != SetTimer(hwnd, SBT_MOUSEROLL_ID, 0, Statusbar_MouseRollTimer)) { psb->flags |= SBF_MOUSEROLL; } } return; } RECT windowRect; if (!GetWindowRect(hwnd, &windowRect)) return; windowRect.right = windowRect.left + psb->desiredCX; windowRect.top -= psb->mouseY; windowRect.bottom -= psb->mouseY; LONG mouseY = psb->desiredY; if (pt.y < windowRect.bottom) { if (pt.y < (windowRect.bottom - 12)) { pt.y += 12; } else { pt.y = windowRect.bottom - 1; } } if (PtInRect(&windowRect, pt)) { psb->desiredY = pt.y - windowRect.top + 1; } else { psb->desiredY = 0; } if (psb->desiredY != mouseY) { if (0 == (SBF_MOUSEROLL & psb->flags) && 0 != SetTimer(hwnd, SBT_MOUSEROLL_ID, 0, Statusbar_MouseRollTimer)) { psb->flags |= SBF_MOUSEROLL; } } } static void Statusbar_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase) { DWORD windowStyle = GetWindowStyle(hwnd); if (0 != (SBS_UPDATELAYOUT & windowStyle)) Statusbar_UpdateLayout(hwnd, TRUE); STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar) return; RECT clientRect, textRect; GetClientRect(hwnd, &clientRect); CopyRect(&textRect, &clientRect); SetBkColor(hdc, statusbar->rgbBk); SetTextColor(hdc, statusbar->rgbText); HRGN rgnBack = CreateRectRgnIndirect((NULL != prcPaint) ? prcPaint : &clientRect); HRGN rgn = NULL; if (0 != statusbar->cchText) { textRect.top += TEXTMARGIN_TOP; textRect.right -= TEXTMARGIN_RIGHT; SetBkMode(hdc, TRANSPARENT); SetTextAlign(hdc, TA_LEFT | TA_BOTTOM); HFONT origFont = (HFONT)SelectObject(hdc, statusbar->textFont); rgn = CreateRectRgnIndirect(&textRect); DWORD options = (FALSE != fErase) ? ETO_OPAQUE : 0; if (0 != ExtTextOut(hdc, textRect.left + TEXTMARGIN_LEFT, textRect.bottom - TEXTMARGIN_BOTTOM, options, &textRect, statusbar->pszText, statusbar->cchText, NULL)) { CombineRgn(rgnBack, rgnBack, rgn, RGN_DIFF); } SelectObject(hdc, origFont); } if (0 != fErase) { FillRgn(hdc, rgnBack, statusbar->brushBk); } if (NULL != rgn) DeleteObject(rgn); if (NULL != rgnBack) DeleteObject(rgnBack); } static LRESULT Statusbar_OnCreate(HWND hwnd, CREATESTRUCT *pcs) { STATUSBAR *statusbar = (STATUSBAR*)calloc(1, sizeof(STATUSBAR)); if (NULL != statusbar) { SetLastError(ERROR_SUCCESS); if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)statusbar) && ERROR_SUCCESS != GetLastError()) { free(statusbar); statusbar = NULL; } } if (NULL == statusbar) { DestroyWindow(hwnd); return -1; } return 0; } static void Statusbar_OnDestroy(HWND hwnd) { STATUSBAR *statusbar = GetStatusbar(hwnd); SetWindowLongPtr(hwnd, 0, 0L); if (NULL == statusbar) return; if (NULL != statusbar->textFont && 0 == (SBF_CACHEDFONT & statusbar->flags)) DeleteObject(statusbar->textFont); if (NULL != statusbar->windowRegion) DeleteObject(statusbar->windowRegion); if (NULL != statusbar->brushBk) DeleteObject(statusbar->brushBk); Statusbar_RemoveMouseHook(); if (NULL != statusbar->hBrowser) PostMessage(statusbar->hBrowser, NBHM_QUEUEAPC, (WPARAM)hwnd, (LPARAM)Statusbar_RemoveMouseHookApc); free(statusbar); } static void Statusbar_OnPaint(HWND hwnd) { PAINTSTRUCT ps; if (BeginPaint(hwnd, &ps)) { if (ps.rcPaint.left != ps.rcPaint.right) Statusbar_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase); EndPaint(hwnd, &ps); } } static void Statusbar_OnPrintClient(HWND hwnd, HDC hdc, UINT options) { RECT clientRect; if (GetClientRect(hwnd, &clientRect)) Statusbar_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options)); } static BOOL Statusbar_SetText(HWND hwnd, LPCWSTR pszText) { STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar) return FALSE; INT cchText; cchText = (NULL != pszText && FALSE == IS_INTRESOURCE(pszText)) ? lstrlen(pszText) : 0; if (cchText >= statusbar->cchTextMax) { statusbar->cchText = 0; statusbar->cchTextMax = 0; if (NULL != statusbar->pszText) Plugin_FreeString(statusbar->pszText); INT cchMalloc = ((cchText / 1024) + 1) * 1024; statusbar->pszText = Plugin_MallocString(cchMalloc); if (NULL == statusbar->pszText) return FALSE; statusbar->cchTextMax = cchMalloc; } statusbar->cchText = cchText; if (0 == cchText) { statusbar->pszText[0] = L'\0'; } else { if (FAILED(StringCchCopy(statusbar->pszText, statusbar->cchTextMax, pszText))) { statusbar->pszText[0] = L'\0'; statusbar->cchText = 0; return FALSE; } } return TRUE; } static BOOL Statusbar_OnSetText(HWND hwnd, LPCWSTR pszText) { if (FALSE == Statusbar_SetText(hwnd, pszText)) return FALSE; Statusbar_UpdateLayout(hwnd, FALSE); return TRUE; } static INT Statusbar_OnGetText(HWND hwnd, LPWSTR pszBuffer, INT cchBufferMax) { if (NULL == pszBuffer || cchBufferMax) return 0; pszBuffer[0] = L'\0'; STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar) return 0; INT cchCopy = (statusbar ? statusbar->cchText : 0); if (NULL != statusbar && 0 != cchCopy) { if (cchCopy >= cchBufferMax) cchCopy = (cchBufferMax - 1); StringCchCopyN(pszBuffer, cchBufferMax, statusbar->pszText, cchCopy); } return cchCopy; } static INT Statusbar_OnGetTextLength(HWND hwnd) { STATUSBAR *statusbar = GetStatusbar(hwnd); return (NULL != statusbar) ? statusbar->cchText : 0; } static LRESULT Statusbar_OnShowWindow(HWND hwnd, BOOL fShow, UINT nState) { STATUSBAR *psb = GetStatusbar(hwnd); if (NULL != psb) { if (FALSE != fShow) { Statusbar_InstallMouseHook(hwnd); if (NULL != psb->hBrowser) PostMessage(psb->hBrowser, NBHM_QUEUEAPC, (WPARAM)hwnd, (LPARAM)Statusbar_InstallMouseHookApc); } else { Statusbar_RemoveMouseHook(); if (NULL != psb->hBrowser) PostMessage(psb->hBrowser, NBHM_QUEUEAPC, (WPARAM)hwnd, (LPARAM)Statusbar_RemoveMouseHookApc); } } return DefWindowProcW(hwnd, WM_SHOWWINDOW, (WPARAM)fShow, (LPARAM)nState); } static void Statusbar_OnUpdateSkin(HWND hwnd, BOOL fRedraw) { STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar) return; ifc_skinhelper *skin; if (FAILED(Plugin_GetSkinHelper(&skin))) skin = NULL; if (NULL == skin || FAILED(skin->GetColor(WADLG_WNDBG, &statusbar->rgbBk))) statusbar->rgbBk = GetSysColor(COLOR_WINDOW); if (NULL == skin || FAILED(skin->GetColor(WADLG_WNDFG, &statusbar->rgbText))) statusbar->rgbText = GetSysColor(COLOR_WINDOWTEXT); statusbar->rgbText = BlendColors(statusbar->rgbText, statusbar->rgbBk, 127); if (NULL != statusbar->textFont) { if (0 == (SBF_CACHEDFONT & statusbar->flags)) DeleteObject(statusbar->textFont); statusbar->textFont = NULL; } if (NULL != skin) statusbar->textFont = skin->GetFont(); if (NULL != statusbar->textFont) statusbar->flags |= SBF_CACHEDFONT; else { statusbar->flags &= ~SBF_CACHEDFONT; LOGFONT lf; SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0); StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Tahoma"); statusbar->textFont = CreateFontIndirect(&lf); } if (NULL != skin) skin->Release(); if (NULL != statusbar->brushBk) DeleteObject(statusbar->brushBk); statusbar->brushBk = CreateSolidBrush(statusbar->rgbBk); Statusbar_UpdateLayout(hwnd, FALSE); } static void Statusbar_OnSetParentRect(HWND hwnd, const RECT *parentRect) { STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL == statusbar || NULL == parentRect) return; CopyRect(&statusbar->parentRect, parentRect); Statusbar_UpdateLayout(hwnd, FALSE); } static BOOL Statusbar_OnSetActive(HWND hwnd, BOOL fActive) { DWORD windowStyle = GetWindowStyle(hwnd); if (0 == (SBS_ACTIVE & windowStyle) == (FALSE == fActive)) return TRUE; if (FALSE == fActive) windowStyle &= ~SBS_ACTIVE; else windowStyle |= SBS_ACTIVE; SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle); if (0 != (SBS_ACTIVE & windowStyle)) { if (0 == (WS_VISIBLE & windowStyle)) { Statusbar_UpdateLayout(hwnd, TRUE); ShowWindow(hwnd, SW_SHOWNA); } } else { if (0 != (WS_VISIBLE & windowStyle)) { STATUSBAR *statusbar = GetStatusbar(hwnd); if (NULL != statusbar) { KillTimer(hwnd, SBT_INFLATE_ID); statusbar->desiredCX = 0; statusbar->inflateTime = GetTickCount(); SetTimer(hwnd, SBT_INFLATE_ID, SBT_INFLATE_DELAY, Statusbar_InflateTimer); } } } return TRUE; } static BOOL Statusbar_OnUpdate(HWND hwnd, LPCWSTR pszText) { STATUSBAR *psb = GetStatusbar(hwnd); if (NULL == psb) return FALSE; if (NULL == pszText || L'\0' == *pszText) return TRUE; if (NULL == pszText) { if (NULL == psb->pszText) { return TRUE; } pszText = L""; } if (NULL != psb->pszText && CSTR_EQUAL == CompareString(CSTR_INVARIANT, 0, psb->pszText, -1, pszText, -1)) { return TRUE; } Statusbar_SetText(hwnd, pszText); DWORD windowStyle = GetWindowStyle(hwnd); if (0 != (WS_VISIBLE & windowStyle)) { Statusbar_UpdateLayout(hwnd, FALSE); InvalidateRect(hwnd, NULL, TRUE); } return TRUE; } static BOOL Statusbar_OnSetBrowserHost(HWND hwnd, HWND hBrowser) { STATUSBAR *psb = GetStatusbar(hwnd); if (NULL == psb) return FALSE; psb->hBrowser = hBrowser; return TRUE; } static LRESULT Statusbar_OnEnable(HWND hwnd, BOOL fEnable) { UINT windowStyle = GetWindowStyle(hwnd); UINT newStyle = windowStyle; if (FALSE == fEnable) newStyle |= WS_DISABLED; else newStyle &= ~WS_DISABLED; if(newStyle == windowStyle) return fEnable; SetWindowLongPtr(hwnd, GWL_STYLE, newStyle); return !fEnable; } static LRESULT CALLBACK Statusbar_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: return Statusbar_OnCreate(hwnd, (CREATESTRUCT*)lParam); case WM_DESTROY: Statusbar_OnDestroy(hwnd); break; case WM_PAINT: Statusbar_OnPaint(hwnd); return 0; case WM_PRINTCLIENT: Statusbar_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0; case WM_ERASEBKGND: return 0; case WM_SETTEXT: return Statusbar_OnSetText(hwnd, (LPCWSTR)lParam); case WM_GETTEXT: return Statusbar_OnGetText(hwnd, (LPWSTR)lParam, (INT)wParam); case WM_GETTEXTLENGTH: return Statusbar_OnGetTextLength(hwnd); case WM_SHOWWINDOW: return Statusbar_OnShowWindow(hwnd, (BOOL)wParam, (UINT)lParam); case SBM_UPDATESKIN: Statusbar_OnUpdateSkin(hwnd, (BOOL)lParam); return 0; case SBM_SETPARENTRECT: Statusbar_OnSetParentRect(hwnd, (const RECT*)lParam); return 0; case SBM_SETACTIVE: return Statusbar_OnSetActive(hwnd, (BOOL)wParam); case SBM_UPDATE: return Statusbar_OnUpdate(hwnd, (LPCWSTR)lParam); case SBM_SETBROWSERHOST: return Statusbar_OnSetBrowserHost(hwnd, (HWND)lParam); case SBM_ENABLE: return Statusbar_OnEnable(hwnd, (BOOL)lParam); } return DefWindowProcW(hwnd, uMsg, wParam, lParam); } static void CALLBACK Statusbar_InflateTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId) { KillTimer(hwnd, eventId); Statusbar_Inflate(hwnd); } static void CALLBACK Statusbar_MouseRollTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId) { KillTimer(hwnd, eventId); Statusbar_MouseRoll(hwnd); } static LRESULT CALLBACK Statusbar_MouseHook(INT code, WPARAM wParam, LPARAM lParam) { STATUSBARMOUSEHOOK *hook = (STATUSBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex); if (NULL == hook || NULL == hook->hHook) return FALSE; if (code >= 0) { MOUSEHOOKSTRUCT *mouseHook = (MOUSEHOOKSTRUCT*)lParam; if (NULL != hook->hwnd) { Statusbar_MouseCheck(hook->hwnd, mouseHook->pt); } } return CallNextHookEx(hook->hHook, code, wParam, lParam); }