statusbar.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. #include "main.h"
  2. #include "./statusbar.h"
  3. #include "./graphics.h"
  4. #include "./browserHost.h"
  5. #include "../winamp/wa_dlg.h"
  6. #include "../Plugins/General/gen_ml/ml_ipc_0313.h"
  7. #include "./ifc_skinhelper.h"
  8. #include "./ifc_wasabihelper.h"
  9. #include <windows.h>
  10. #include <shlwapi.h>
  11. #include <strsafe.h>
  12. #define TEXTMARGIN_LEFT 3
  13. #define TEXTMARGIN_TOP 1
  14. #define TEXTMARGIN_RIGHT 3
  15. #define TEXTMARGIN_BOTTOM 1
  16. #define SBT_INFLATE_ID 31
  17. #define SBT_INFLATE_DELAY 50
  18. #define SBT_INFLATE_INTERVAL 20
  19. #define SBT_MOUSEROLL_ID 32
  20. #define SBT_MOUSEROLL_DELAY 50
  21. #define SBT_MOUSEROLL_INTERVAL 20
  22. #define SBF_MOUSEROLL 0x00000001
  23. #define SBF_CACHEDFONT 0x00000002
  24. typedef struct __STATUSBAR
  25. {
  26. UINT flags;
  27. RECT parentRect;
  28. SIZE textSize;
  29. LPWSTR pszText;
  30. INT cchText;
  31. INT cchTextMax;
  32. HFONT textFont;
  33. COLORREF rgbBk;
  34. COLORREF rgbText;
  35. HBRUSH brushBk;
  36. LONG desiredCX;
  37. LONG mouseY;
  38. LONG desiredY;
  39. HRGN windowRegion;
  40. HWND hBrowser;
  41. DWORD inflateTime;
  42. } STATUSBAR;
  43. typedef struct __STATUSBARMOUSEHOOK
  44. {
  45. HHOOK hHook;
  46. HWND hwnd;
  47. } STATUSBARMOUSEHOOK;
  48. static size_t tlsIndex = -1;
  49. #define GetStatusbar(__hwnd) ((STATUSBAR*)(LONG_PTR)(LONGX86)GetWindowLongPtr((__hwnd), 0))
  50. static LRESULT CALLBACK Statusbar_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  51. static void CALLBACK Statusbar_InflateTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId);
  52. static void CALLBACK Statusbar_MouseRollTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId);
  53. static LRESULT CALLBACK Statusbar_MouseHook(INT code, WPARAM wParam, LPARAM lParam);
  54. BOOL Statusbar_RegisterClass(HINSTANCE hInstance)
  55. {
  56. WNDCLASS wc;
  57. ATOM klassAtom;
  58. ifc_wasabihelper *wasabi;
  59. if (GetClassInfo(hInstance, NWC_ONLINEMEDIASTATUSBAR, &wc))
  60. return TRUE;
  61. ZeroMemory(&wc, sizeof(WNDCLASS));
  62. wc.hInstance = hInstance;
  63. wc.lpszClassName = NWC_ONLINEMEDIASTATUSBAR;
  64. wc.lpfnWndProc = Statusbar_WindowProc;
  65. wc.style = CS_PARENTDC | CS_SAVEBITS;
  66. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  67. wc.hbrBackground = NULL;
  68. wc.cbWndExtra = sizeof(STATUSBAR*);
  69. klassAtom = RegisterClassW(&wc);
  70. if (0 == klassAtom)
  71. return FALSE;
  72. if (SUCCEEDED(Plugin_GetWasabiHelper(&wasabi)))
  73. {
  74. api_application *application;
  75. if (SUCCEEDED(wasabi->GetApplicationApi(&application)))
  76. {
  77. application->DirectMouseWheel_RegisterSkipClass(klassAtom);
  78. application->Release();
  79. }
  80. wasabi->Release();
  81. }
  82. return TRUE;
  83. }
  84. static BOOL Statusbar_GetTextSize(HWND hwnd, HFONT textFont, LPCWSTR pszText, INT cchText, SIZE *textSize)
  85. {
  86. HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
  87. if (NULL == hdc) return FALSE;
  88. HFONT originalFont = (HFONT)SelectObject(hdc, textFont);
  89. BOOL result;
  90. if (0 == cchText)
  91. {
  92. TEXTMETRIC tm;
  93. result = GetTextMetrics(hdc, &tm);
  94. if (FALSE != result)
  95. {
  96. textSize->cx = 0;
  97. textSize->cy = tm.tmHeight;
  98. }
  99. }
  100. else
  101. {
  102. result = GetTextExtentPoint32(hdc, pszText, cchText, textSize);
  103. }
  104. SelectObject(hdc, originalFont);
  105. ReleaseDC(hwnd, hdc);
  106. return result;
  107. }
  108. static BOOL Statusbar_SetWindowPos(HWND hwnd, HWND hwndInsertAfter, INT x, INT y, INT cx, INT cy, UINT flags)
  109. {
  110. STATUSBAR *statusbar = GetStatusbar(hwnd);
  111. if (NULL != statusbar)
  112. {
  113. INT k = cy/4;
  114. if (k > cx) k = 0;
  115. POINT szPoint[5] = {0};
  116. //szPoint[0].x = 0;
  117. //szPoint[0].y = 0;
  118. szPoint[1].x = cx - k;
  119. //szPoint[1].y = 0;
  120. szPoint[2].x = cx;
  121. szPoint[2].y = k;
  122. szPoint[3].x = cx;
  123. szPoint[3].y = cy;
  124. //szPoint[4].x = 0;
  125. szPoint[4].y = cy;
  126. HRGN rgn = CreatePolygonRgn(szPoint, ARRAYSIZE(szPoint), WINDING);
  127. if (0 != SetWindowRgn(hwnd, rgn, TRUE))
  128. {
  129. if (NULL != statusbar->windowRegion)
  130. DeleteObject(statusbar->windowRegion);
  131. statusbar->windowRegion = rgn;
  132. }
  133. else
  134. {
  135. if (NULL != rgn)
  136. DeleteObject(rgn);
  137. }
  138. }
  139. if (0 == SetWindowPos(hwnd, hwndInsertAfter, x, y, cx, cy, flags))
  140. return FALSE;
  141. return TRUE;
  142. }
  143. static void Statusbar_Inflate(HWND hwnd)
  144. {
  145. STATUSBAR *statusbar = GetStatusbar(hwnd);
  146. if (NULL == statusbar) return;
  147. DWORD currentTime = GetTickCount();
  148. DWORD kMult = (currentTime - statusbar->inflateTime) / SBT_INFLATE_INTERVAL;
  149. if (kMult < 4) kMult = 1;
  150. statusbar->inflateTime = currentTime;
  151. RECT windowRect;
  152. if (!GetWindowRect(hwnd, &windowRect))
  153. return;
  154. DWORD windowStyle = GetWindowStyle(hwnd);
  155. LONG currentWidth = windowRect.right - windowRect.left;
  156. LONG targetCX = statusbar->desiredCX;
  157. if (0 == (SBS_ACTIVE & windowStyle) || targetCX < 16)
  158. targetCX = 0;
  159. if (currentWidth == targetCX)
  160. return;
  161. LONG width = currentWidth;
  162. LONG height = windowRect.bottom - windowRect.top;
  163. LONG step;
  164. while(kMult-- && width != targetCX)
  165. {
  166. if (width > targetCX)
  167. {
  168. step = (width - targetCX) / 3;
  169. if (step < 6) step = 6;
  170. width -= step;
  171. if (width < targetCX) width = targetCX;
  172. }
  173. else
  174. {
  175. step = (targetCX - width)*2 / 3;
  176. if (step < 48) step = 48;
  177. width += step;
  178. if (width > targetCX) width = targetCX;
  179. }
  180. }
  181. Statusbar_SetWindowPos(hwnd, HWND_TOP, 0, 0, width, height,
  182. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE);
  183. if (width < (windowRect.right - windowRect.left))
  184. {
  185. if (NULL != statusbar->hBrowser)
  186. {
  187. RECT invalidRect;
  188. SetRect(&invalidRect, windowRect.left + width - 4, windowRect.top, windowRect.right, windowRect.bottom);
  189. MapWindowPoints(HWND_DESKTOP, statusbar->hBrowser, (POINT*)&invalidRect, 2);
  190. RedrawWindow(statusbar->hBrowser, &invalidRect, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  191. }
  192. }
  193. else
  194. {
  195. RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME);
  196. }
  197. if (0 == width && 0 == (SBS_ACTIVE & windowStyle))
  198. {
  199. ShowWindow(hwnd, SW_HIDE);
  200. }
  201. else
  202. {
  203. if (width != targetCX)
  204. {
  205. SetTimer(hwnd, SBT_INFLATE_ID, SBT_INFLATE_INTERVAL, Statusbar_InflateTimer);
  206. }
  207. }
  208. }
  209. static void Statusbar_UpdateLayout(HWND hwnd, BOOL fForce)
  210. {
  211. DWORD windowStyle = GetWindowStyle(hwnd);
  212. if (0 == (WS_VISIBLE & windowStyle) && FALSE == fForce)
  213. {
  214. if (0 == (SBS_UPDATELAYOUT & windowStyle))
  215. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle | SBS_UPDATELAYOUT);
  216. return;
  217. }
  218. if (0 != (SBS_UPDATELAYOUT & windowStyle))
  219. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~SBS_UPDATELAYOUT);
  220. STATUSBAR *statusbar = GetStatusbar(hwnd);
  221. if (NULL == statusbar) return;
  222. if (!Statusbar_GetTextSize(hwnd, statusbar->textFont, statusbar->pszText, statusbar->cchText, &statusbar->textSize))
  223. ZeroMemory(&statusbar->textSize, sizeof(SIZE));
  224. RECT windowRect;
  225. SetRect(&windowRect,
  226. statusbar->parentRect.left,
  227. statusbar->parentRect.bottom - statusbar->textSize.cy + statusbar->mouseY,
  228. statusbar->parentRect.left + statusbar->textSize.cx,
  229. statusbar->parentRect.bottom + statusbar->mouseY);
  230. if (0 != statusbar->textSize.cy)
  231. windowRect.top -= (TEXTMARGIN_TOP + TEXTMARGIN_BOTTOM);
  232. if (0 != statusbar->textSize.cx)
  233. windowRect.right += (TEXTMARGIN_LEFT + TEXTMARGIN_RIGHT);
  234. if (windowRect.right > statusbar->parentRect.right - 2)
  235. windowRect.right = statusbar->parentRect.right - 2;
  236. if ((windowRect.right - windowRect.left) < 20)
  237. windowRect.right = windowRect.left;
  238. if (windowRect.top < statusbar->parentRect.top + 20)
  239. windowRect.top = statusbar->parentRect.bottom;
  240. RECT previousRect;
  241. if (!GetWindowRect(hwnd, &previousRect))
  242. SetRectEmpty(&previousRect);
  243. if (FALSE == EqualRect(&previousRect, &windowRect))
  244. {
  245. LONG width = windowRect.right - windowRect.left;
  246. LONG height = windowRect.bottom - windowRect.top;
  247. LONG prevWidth = previousRect.right - previousRect.left;
  248. LONG prevHeight = previousRect.bottom - previousRect.top;
  249. LONG widthAdjust = 0;
  250. if (statusbar->desiredCX != prevWidth)
  251. {
  252. widthAdjust = width - prevWidth;
  253. }
  254. KillTimer(hwnd, SBT_INFLATE_ID);
  255. statusbar->desiredCX = width;
  256. statusbar->inflateTime = GetTickCount();
  257. HWND hParent = GetParent(hwnd);
  258. MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&previousRect, 2);
  259. if (windowRect.left != previousRect.left || windowRect.top != previousRect.top || height != prevHeight || 0 != widthAdjust)
  260. {
  261. Statusbar_SetWindowPos(hwnd, HWND_TOP, windowRect.left, windowRect.top, prevWidth + widthAdjust, height,
  262. SWP_NOACTIVATE | SWP_NOOWNERZORDER);
  263. if (widthAdjust < 0 && NULL != statusbar->hBrowser)
  264. {
  265. RECT invalidRect;
  266. SetRect(&invalidRect, previousRect.left + prevWidth + widthAdjust - 4, previousRect.top, previousRect.left + prevWidth, previousRect.bottom);
  267. MapWindowPoints(HWND_DESKTOP, statusbar->hBrowser, (POINT*)&invalidRect, 2);
  268. RedrawWindow(statusbar->hBrowser, &invalidRect, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  269. }
  270. else if (0 != widthAdjust)
  271. {
  272. RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_FRAME);
  273. }
  274. }
  275. if (width > prevWidth)
  276. {
  277. Statusbar_Inflate(hwnd);
  278. }
  279. else
  280. {
  281. SetTimer(hwnd, SBT_INFLATE_ID, SBT_INFLATE_DELAY, Statusbar_InflateTimer);
  282. //Statusbar_Inflate(hwnd);
  283. }
  284. }
  285. else
  286. {
  287. InvalidateRect(hwnd, NULL, FALSE);
  288. }
  289. }
  290. static BOOL Statusbar_InstallMouseHook(HWND hwnd)
  291. {
  292. if (TLS_OUT_OF_INDEXES == tlsIndex)
  293. {
  294. tlsIndex = Plugin_TlsAlloc();
  295. if (TLS_OUT_OF_INDEXES == tlsIndex)
  296. return FALSE;
  297. }
  298. STATUSBARMOUSEHOOK *hook = (STATUSBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex);
  299. if (NULL != hook) return FALSE;
  300. hook = (STATUSBARMOUSEHOOK*)calloc(1, sizeof(STATUSBARMOUSEHOOK));
  301. if (NULL == hook) return FALSE;
  302. hook->hwnd = hwnd;
  303. hook->hHook = SetWindowsHookEx(WH_MOUSE, Statusbar_MouseHook, NULL, GetCurrentThreadId());
  304. if (NULL == hook->hHook)
  305. {
  306. free(hook);
  307. return FALSE;
  308. }
  309. Plugin_TlsSetValue(tlsIndex, hook);
  310. return TRUE;
  311. }
  312. static void Statusbar_RemoveMouseHook()
  313. {
  314. if (TLS_OUT_OF_INDEXES == tlsIndex) return;
  315. STATUSBARMOUSEHOOK *hook = (STATUSBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex);
  316. if (NULL == hook) return;
  317. Plugin_TlsSetValue(tlsIndex, NULL);
  318. if (NULL != hook->hHook)
  319. UnhookWindowsHookEx(hook->hHook);
  320. free(hook);
  321. }
  322. static void CALLBACK Statusbar_InstallMouseHookApc(ULONG_PTR param)
  323. {
  324. Statusbar_InstallMouseHook((HWND)param);
  325. }
  326. static void CALLBACK Statusbar_RemoveMouseHookApc(ULONG_PTR param)
  327. {
  328. Statusbar_RemoveMouseHook();
  329. }
  330. static void Statusbar_MouseRoll(HWND hwnd)
  331. {
  332. STATUSBAR *psb = GetStatusbar(hwnd);
  333. if (NULL == psb || 0 == (SBF_MOUSEROLL & psb->flags)) return;
  334. if (psb->desiredY == psb->mouseY)
  335. {
  336. psb->flags &= ~SBF_MOUSEROLL;
  337. return;
  338. }
  339. RECT windowRect;
  340. if (!GetWindowRect(hwnd, &windowRect))
  341. return;
  342. windowRect.top -= psb->mouseY;
  343. if (psb->mouseY > psb->desiredY)
  344. {
  345. psb->mouseY -= 4;
  346. if (psb->mouseY < psb->desiredY) psb->mouseY = psb->desiredY;
  347. }
  348. else
  349. {
  350. psb->mouseY += 4;
  351. if (psb->mouseY > psb->desiredY) psb->mouseY = psb->desiredY;
  352. }
  353. windowRect.top += psb->mouseY;
  354. HWND hParent = GetParent(hwnd);
  355. if (NULL != hParent)
  356. {
  357. MapWindowPoints(HWND_DESKTOP, hParent, (POINT*)&windowRect, 1);
  358. SetWindowPos(hwnd, HWND_TOP, windowRect.left, windowRect.top, 0, 0,
  359. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_ASYNCWINDOWPOS);
  360. }
  361. if (psb->desiredY == psb->mouseY ||
  362. 0 == SetTimer(hwnd, SBT_MOUSEROLL_ID, SBT_MOUSEROLL_INTERVAL, Statusbar_MouseRollTimer))
  363. {
  364. psb->flags &= ~SBF_MOUSEROLL;
  365. }
  366. }
  367. static void Statusbar_MouseCheck(HWND hwnd, POINT pt)
  368. {
  369. STATUSBAR *psb = GetStatusbar(hwnd);
  370. if (NULL == psb) return;
  371. DWORD windowStyle = GetWindowStyle(hwnd);
  372. if (0 != (WS_DISABLED & windowStyle))
  373. {
  374. if (0 != psb->desiredY)
  375. {
  376. psb->desiredY = 0;
  377. if (0 == (SBF_MOUSEROLL & psb->flags) &&
  378. 0 != SetTimer(hwnd, SBT_MOUSEROLL_ID, 0, Statusbar_MouseRollTimer))
  379. {
  380. psb->flags |= SBF_MOUSEROLL;
  381. }
  382. }
  383. return;
  384. }
  385. RECT windowRect;
  386. if (!GetWindowRect(hwnd, &windowRect))
  387. return;
  388. windowRect.right = windowRect.left + psb->desiredCX;
  389. windowRect.top -= psb->mouseY;
  390. windowRect.bottom -= psb->mouseY;
  391. LONG mouseY = psb->desiredY;
  392. if (pt.y < windowRect.bottom)
  393. {
  394. if (pt.y < (windowRect.bottom - 12))
  395. {
  396. pt.y += 12;
  397. }
  398. else
  399. {
  400. pt.y = windowRect.bottom - 1;
  401. }
  402. }
  403. if (PtInRect(&windowRect, pt))
  404. {
  405. psb->desiredY = pt.y - windowRect.top + 1;
  406. }
  407. else
  408. {
  409. psb->desiredY = 0;
  410. }
  411. if (psb->desiredY != mouseY)
  412. {
  413. if (0 == (SBF_MOUSEROLL & psb->flags) &&
  414. 0 != SetTimer(hwnd, SBT_MOUSEROLL_ID, 0, Statusbar_MouseRollTimer))
  415. {
  416. psb->flags |= SBF_MOUSEROLL;
  417. }
  418. }
  419. }
  420. static void Statusbar_Paint(HWND hwnd, HDC hdc, const RECT *prcPaint, BOOL fErase)
  421. {
  422. DWORD windowStyle = GetWindowStyle(hwnd);
  423. if (0 != (SBS_UPDATELAYOUT & windowStyle))
  424. Statusbar_UpdateLayout(hwnd, TRUE);
  425. STATUSBAR *statusbar = GetStatusbar(hwnd);
  426. if (NULL == statusbar) return;
  427. RECT clientRect, textRect;
  428. GetClientRect(hwnd, &clientRect);
  429. CopyRect(&textRect, &clientRect);
  430. SetBkColor(hdc, statusbar->rgbBk);
  431. SetTextColor(hdc, statusbar->rgbText);
  432. HRGN rgnBack = CreateRectRgnIndirect((NULL != prcPaint) ? prcPaint : &clientRect);
  433. HRGN rgn = NULL;
  434. if (0 != statusbar->cchText)
  435. {
  436. textRect.top += TEXTMARGIN_TOP;
  437. textRect.right -= TEXTMARGIN_RIGHT;
  438. SetBkMode(hdc, TRANSPARENT);
  439. SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
  440. HFONT origFont = (HFONT)SelectObject(hdc, statusbar->textFont);
  441. rgn = CreateRectRgnIndirect(&textRect);
  442. DWORD options = (FALSE != fErase) ? ETO_OPAQUE : 0;
  443. if (0 != ExtTextOut(hdc, textRect.left + TEXTMARGIN_LEFT, textRect.bottom - TEXTMARGIN_BOTTOM,
  444. options, &textRect, statusbar->pszText, statusbar->cchText, NULL))
  445. {
  446. CombineRgn(rgnBack, rgnBack, rgn, RGN_DIFF);
  447. }
  448. SelectObject(hdc, origFont);
  449. }
  450. if (0 != fErase)
  451. {
  452. FillRgn(hdc, rgnBack, statusbar->brushBk);
  453. }
  454. if (NULL != rgn) DeleteObject(rgn);
  455. if (NULL != rgnBack) DeleteObject(rgnBack);
  456. }
  457. static LRESULT Statusbar_OnCreate(HWND hwnd, CREATESTRUCT *pcs)
  458. {
  459. STATUSBAR *statusbar = (STATUSBAR*)calloc(1, sizeof(STATUSBAR));
  460. if (NULL != statusbar)
  461. {
  462. SetLastError(ERROR_SUCCESS);
  463. if (!SetWindowLongPtr(hwnd, 0, (LONGX86)(LONG_PTR)statusbar) && ERROR_SUCCESS != GetLastError())
  464. {
  465. free(statusbar);
  466. statusbar = NULL;
  467. }
  468. }
  469. if (NULL == statusbar)
  470. {
  471. DestroyWindow(hwnd);
  472. return -1;
  473. }
  474. return 0;
  475. }
  476. static void Statusbar_OnDestroy(HWND hwnd)
  477. {
  478. STATUSBAR *statusbar = GetStatusbar(hwnd);
  479. SetWindowLongPtr(hwnd, 0, 0L);
  480. if (NULL == statusbar) return;
  481. if (NULL != statusbar->textFont && 0 == (SBF_CACHEDFONT & statusbar->flags))
  482. DeleteObject(statusbar->textFont);
  483. if (NULL != statusbar->windowRegion)
  484. DeleteObject(statusbar->windowRegion);
  485. if (NULL != statusbar->brushBk)
  486. DeleteObject(statusbar->brushBk);
  487. Statusbar_RemoveMouseHook();
  488. if (NULL != statusbar->hBrowser)
  489. PostMessage(statusbar->hBrowser, NBHM_QUEUEAPC, (WPARAM)hwnd, (LPARAM)Statusbar_RemoveMouseHookApc);
  490. free(statusbar);
  491. }
  492. static void Statusbar_OnPaint(HWND hwnd)
  493. {
  494. PAINTSTRUCT ps;
  495. if (BeginPaint(hwnd, &ps))
  496. {
  497. if (ps.rcPaint.left != ps.rcPaint.right)
  498. Statusbar_Paint(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
  499. EndPaint(hwnd, &ps);
  500. }
  501. }
  502. static void Statusbar_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
  503. {
  504. RECT clientRect;
  505. if (GetClientRect(hwnd, &clientRect))
  506. Statusbar_Paint(hwnd, hdc, &clientRect, 0 != (PRF_ERASEBKGND & options));
  507. }
  508. static BOOL Statusbar_SetText(HWND hwnd, LPCWSTR pszText)
  509. {
  510. STATUSBAR *statusbar = GetStatusbar(hwnd);
  511. if (NULL == statusbar) return FALSE;
  512. INT cchText;
  513. cchText = (NULL != pszText && FALSE == IS_INTRESOURCE(pszText)) ? lstrlen(pszText) : 0;
  514. if (cchText >= statusbar->cchTextMax)
  515. {
  516. statusbar->cchText = 0;
  517. statusbar->cchTextMax = 0;
  518. if (NULL != statusbar->pszText)
  519. Plugin_FreeString(statusbar->pszText);
  520. INT cchMalloc = ((cchText / 1024) + 1) * 1024;
  521. statusbar->pszText = Plugin_MallocString(cchMalloc);
  522. if (NULL == statusbar->pszText)
  523. return FALSE;
  524. statusbar->cchTextMax = cchMalloc;
  525. }
  526. statusbar->cchText = cchText;
  527. if (0 == cchText)
  528. {
  529. statusbar->pszText[0] = L'\0';
  530. }
  531. else
  532. {
  533. if (FAILED(StringCchCopy(statusbar->pszText, statusbar->cchTextMax, pszText)))
  534. {
  535. statusbar->pszText[0] = L'\0';
  536. statusbar->cchText = 0;
  537. return FALSE;
  538. }
  539. }
  540. return TRUE;
  541. }
  542. static BOOL Statusbar_OnSetText(HWND hwnd, LPCWSTR pszText)
  543. {
  544. if (FALSE == Statusbar_SetText(hwnd, pszText))
  545. return FALSE;
  546. Statusbar_UpdateLayout(hwnd, FALSE);
  547. return TRUE;
  548. }
  549. static INT Statusbar_OnGetText(HWND hwnd, LPWSTR pszBuffer, INT cchBufferMax)
  550. {
  551. if (NULL == pszBuffer || cchBufferMax)
  552. return 0;
  553. pszBuffer[0] = L'\0';
  554. STATUSBAR *statusbar = GetStatusbar(hwnd);
  555. if (NULL == statusbar) return 0;
  556. INT cchCopy = (statusbar ? statusbar->cchText : 0);
  557. if (NULL != statusbar && 0 != cchCopy)
  558. {
  559. if (cchCopy >= cchBufferMax)
  560. cchCopy = (cchBufferMax - 1);
  561. StringCchCopyN(pszBuffer, cchBufferMax, statusbar->pszText, cchCopy);
  562. }
  563. return cchCopy;
  564. }
  565. static INT Statusbar_OnGetTextLength(HWND hwnd)
  566. {
  567. STATUSBAR *statusbar = GetStatusbar(hwnd);
  568. return (NULL != statusbar) ? statusbar->cchText : 0;
  569. }
  570. static LRESULT Statusbar_OnShowWindow(HWND hwnd, BOOL fShow, UINT nState)
  571. {
  572. STATUSBAR *psb = GetStatusbar(hwnd);
  573. if (NULL != psb)
  574. {
  575. if (FALSE != fShow)
  576. {
  577. Statusbar_InstallMouseHook(hwnd);
  578. if (NULL != psb->hBrowser)
  579. PostMessage(psb->hBrowser, NBHM_QUEUEAPC, (WPARAM)hwnd, (LPARAM)Statusbar_InstallMouseHookApc);
  580. }
  581. else
  582. {
  583. Statusbar_RemoveMouseHook();
  584. if (NULL != psb->hBrowser)
  585. PostMessage(psb->hBrowser, NBHM_QUEUEAPC, (WPARAM)hwnd, (LPARAM)Statusbar_RemoveMouseHookApc);
  586. }
  587. }
  588. return DefWindowProcW(hwnd, WM_SHOWWINDOW, (WPARAM)fShow, (LPARAM)nState);
  589. }
  590. static void Statusbar_OnUpdateSkin(HWND hwnd, BOOL fRedraw)
  591. {
  592. STATUSBAR *statusbar = GetStatusbar(hwnd);
  593. if (NULL == statusbar) return;
  594. ifc_skinhelper *skin;
  595. if (FAILED(Plugin_GetSkinHelper(&skin)))
  596. skin = NULL;
  597. if (NULL == skin || FAILED(skin->GetColor(WADLG_WNDBG, &statusbar->rgbBk)))
  598. statusbar->rgbBk = GetSysColor(COLOR_WINDOW);
  599. if (NULL == skin || FAILED(skin->GetColor(WADLG_WNDFG, &statusbar->rgbText)))
  600. statusbar->rgbText = GetSysColor(COLOR_WINDOWTEXT);
  601. statusbar->rgbText = BlendColors(statusbar->rgbText, statusbar->rgbBk, 127);
  602. if (NULL != statusbar->textFont)
  603. {
  604. if (0 == (SBF_CACHEDFONT & statusbar->flags))
  605. DeleteObject(statusbar->textFont);
  606. statusbar->textFont = NULL;
  607. }
  608. if (NULL != skin)
  609. statusbar->textFont = skin->GetFont();
  610. if (NULL != statusbar->textFont)
  611. statusbar->flags |= SBF_CACHEDFONT;
  612. else
  613. {
  614. statusbar->flags &= ~SBF_CACHEDFONT;
  615. LOGFONT lf;
  616. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0);
  617. StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Tahoma");
  618. statusbar->textFont = CreateFontIndirect(&lf);
  619. }
  620. if (NULL != skin)
  621. skin->Release();
  622. if (NULL != statusbar->brushBk)
  623. DeleteObject(statusbar->brushBk);
  624. statusbar->brushBk = CreateSolidBrush(statusbar->rgbBk);
  625. Statusbar_UpdateLayout(hwnd, FALSE);
  626. }
  627. static void Statusbar_OnSetParentRect(HWND hwnd, const RECT *parentRect)
  628. {
  629. STATUSBAR *statusbar = GetStatusbar(hwnd);
  630. if (NULL == statusbar || NULL == parentRect) return;
  631. CopyRect(&statusbar->parentRect, parentRect);
  632. Statusbar_UpdateLayout(hwnd, FALSE);
  633. }
  634. static BOOL Statusbar_OnSetActive(HWND hwnd, BOOL fActive)
  635. {
  636. DWORD windowStyle = GetWindowStyle(hwnd);
  637. if (0 == (SBS_ACTIVE & windowStyle) == (FALSE == fActive))
  638. return TRUE;
  639. if (FALSE == fActive)
  640. windowStyle &= ~SBS_ACTIVE;
  641. else
  642. windowStyle |= SBS_ACTIVE;
  643. SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);
  644. if (0 != (SBS_ACTIVE & windowStyle))
  645. {
  646. if (0 == (WS_VISIBLE & windowStyle))
  647. {
  648. Statusbar_UpdateLayout(hwnd, TRUE);
  649. ShowWindow(hwnd, SW_SHOWNA);
  650. }
  651. }
  652. else
  653. {
  654. if (0 != (WS_VISIBLE & windowStyle))
  655. {
  656. STATUSBAR *statusbar = GetStatusbar(hwnd);
  657. if (NULL != statusbar)
  658. {
  659. KillTimer(hwnd, SBT_INFLATE_ID);
  660. statusbar->desiredCX = 0;
  661. statusbar->inflateTime = GetTickCount();
  662. SetTimer(hwnd, SBT_INFLATE_ID, SBT_INFLATE_DELAY, Statusbar_InflateTimer);
  663. }
  664. }
  665. }
  666. return TRUE;
  667. }
  668. static BOOL Statusbar_OnUpdate(HWND hwnd, LPCWSTR pszText)
  669. {
  670. STATUSBAR *psb = GetStatusbar(hwnd);
  671. if (NULL == psb) return FALSE;
  672. if (NULL == pszText || L'\0' == *pszText)
  673. return TRUE;
  674. if (NULL == pszText)
  675. {
  676. if (NULL == psb->pszText)
  677. {
  678. return TRUE;
  679. }
  680. pszText = L"";
  681. }
  682. if (NULL != psb->pszText &&
  683. CSTR_EQUAL == CompareString(CSTR_INVARIANT, 0, psb->pszText, -1, pszText, -1))
  684. {
  685. return TRUE;
  686. }
  687. Statusbar_SetText(hwnd, pszText);
  688. DWORD windowStyle = GetWindowStyle(hwnd);
  689. if (0 != (WS_VISIBLE & windowStyle))
  690. {
  691. Statusbar_UpdateLayout(hwnd, FALSE);
  692. InvalidateRect(hwnd, NULL, TRUE);
  693. }
  694. return TRUE;
  695. }
  696. static BOOL Statusbar_OnSetBrowserHost(HWND hwnd, HWND hBrowser)
  697. {
  698. STATUSBAR *psb = GetStatusbar(hwnd);
  699. if (NULL == psb) return FALSE;
  700. psb->hBrowser = hBrowser;
  701. return TRUE;
  702. }
  703. static LRESULT Statusbar_OnEnable(HWND hwnd, BOOL fEnable)
  704. {
  705. UINT windowStyle = GetWindowStyle(hwnd);
  706. UINT newStyle = windowStyle;
  707. if (FALSE == fEnable)
  708. newStyle |= WS_DISABLED;
  709. else
  710. newStyle &= ~WS_DISABLED;
  711. if(newStyle == windowStyle)
  712. return fEnable;
  713. SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);
  714. return !fEnable;
  715. }
  716. static LRESULT CALLBACK Statusbar_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  717. {
  718. switch (uMsg)
  719. {
  720. case WM_CREATE: return Statusbar_OnCreate(hwnd, (CREATESTRUCT*)lParam);
  721. case WM_DESTROY: Statusbar_OnDestroy(hwnd); break;
  722. case WM_PAINT: Statusbar_OnPaint(hwnd); return 0;
  723. case WM_PRINTCLIENT: Statusbar_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0;
  724. case WM_ERASEBKGND: return 0;
  725. case WM_SETTEXT: return Statusbar_OnSetText(hwnd, (LPCWSTR)lParam);
  726. case WM_GETTEXT: return Statusbar_OnGetText(hwnd, (LPWSTR)lParam, (INT)wParam);
  727. case WM_GETTEXTLENGTH: return Statusbar_OnGetTextLength(hwnd);
  728. case WM_SHOWWINDOW: return Statusbar_OnShowWindow(hwnd, (BOOL)wParam, (UINT)lParam);
  729. case SBM_UPDATESKIN: Statusbar_OnUpdateSkin(hwnd, (BOOL)lParam); return 0;
  730. case SBM_SETPARENTRECT: Statusbar_OnSetParentRect(hwnd, (const RECT*)lParam); return 0;
  731. case SBM_SETACTIVE: return Statusbar_OnSetActive(hwnd, (BOOL)wParam);
  732. case SBM_UPDATE: return Statusbar_OnUpdate(hwnd, (LPCWSTR)lParam);
  733. case SBM_SETBROWSERHOST: return Statusbar_OnSetBrowserHost(hwnd, (HWND)lParam);
  734. case SBM_ENABLE: return Statusbar_OnEnable(hwnd, (BOOL)lParam);
  735. }
  736. return DefWindowProcW(hwnd, uMsg, wParam, lParam);
  737. }
  738. static void CALLBACK Statusbar_InflateTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId)
  739. {
  740. KillTimer(hwnd, eventId);
  741. Statusbar_Inflate(hwnd);
  742. }
  743. static void CALLBACK Statusbar_MouseRollTimer(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD timerId)
  744. {
  745. KillTimer(hwnd, eventId);
  746. Statusbar_MouseRoll(hwnd);
  747. }
  748. static LRESULT CALLBACK Statusbar_MouseHook(INT code, WPARAM wParam, LPARAM lParam)
  749. {
  750. STATUSBARMOUSEHOOK *hook = (STATUSBARMOUSEHOOK*)Plugin_TlsGetValue(tlsIndex);
  751. if (NULL == hook || NULL == hook->hHook) return FALSE;
  752. if (code >= 0)
  753. {
  754. MOUSEHOOKSTRUCT *mouseHook = (MOUSEHOOKSTRUCT*)lParam;
  755. if (NULL != hook->hwnd)
  756. {
  757. Statusbar_MouseCheck(hook->hwnd, mouseHook->pt);
  758. }
  759. }
  760. return CallNextHookEx(hook->hHook, code, wParam, lParam);
  761. }