coolsblib.c
上传用户:xhri001
上传日期:2022-07-04
资源大小:99k
文件大小:24k
源码类别:

界面编程

开发平台:

Visual C++

  1. /*
  2. Cool Scrollbar Library Version 1.2
  3. Module: coolsblib.c
  4. Copyright (c) J Brown 2001
  5. This code is freeware, however, you may not publish
  6. this code elsewhere or charge any money for it. This code
  7. is supplied as-is. I make no guarantees about the suitability
  8. of this code - use at your own risk.
  9. It would be nice if you credited me, in the event
  10. that you use this code in a product.
  11. VERSION HISTORY:
  12.  V1.2: TreeView problem fixed by Diego Tartara
  13.    Small problem in thumbsize calculation also fixed (thanks Diego!)
  14.  V1.1: Added support for Right-left windows
  15.        Changed calling convention of APIs to WINAPI (__stdcall)
  16.    Completely standalone (no need for c-runtime)
  17.  V1.0: Apr 2001: Initial Version
  18. */
  19. #define STRICT
  20. #include <windows.h>
  21. #include <commctrl.h>
  22. #include <tchar.h>
  23. #include "coolscroll.h"
  24. #include "userdefs.h"
  25. #include "coolsb_internal.h"
  26. static TCHAR szPropStr[] = _T("CoolSBSubclassPtr");
  27. LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  28. SCROLLWND *GetScrollWndFromHwnd(HWND hwnd)
  29. {
  30. return (SCROLLWND *)GetProp(hwnd, szPropStr);
  31. }
  32. SCROLLBAR *GetScrollBarFromHwnd(HWND hwnd, UINT nBar)
  33. {
  34. SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
  35. if(!sw) return 0;
  36. if(nBar == SB_HORZ)
  37. return &sw->sbarHorz;
  38. else if(nBar == SB_VERT)
  39. return &sw->sbarVert;
  40. else
  41. return 0;
  42. }
  43. BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd)
  44. {
  45. if(GetScrollWndFromHwnd(hwnd))
  46. return TRUE;
  47. else
  48. return FALSE;
  49. }
  50. BOOL GetScrollRect(SCROLLWND *sw, UINT nBar, HWND hwnd, RECT *rect);
  51. //
  52. // Special support for USER32.DLL patching (using Detours library)
  53. // The only place we call a real scrollbar API is in InitializeCoolSB,
  54. // where we call EnableScrollbar.
  55. //
  56. // We HAVE to call the origial EnableScrollbar function, 
  57. // so we need to be able to set a pointer to this func when using
  58. // using Detours (or any other LIB??)
  59. //
  60. static BOOL (WINAPI * pEnableScrollBar) (HWND, UINT, UINT) = 0;
  61. void WINAPI CoolSB_SetESBProc(void *proc)
  62. {
  63. pEnableScrollBar = proc;
  64. }
  65. //
  66. //
  67. static void RedrawNonClient(HWND hwnd, BOOL fFrameChanged)
  68. {
  69. if(fFrameChanged == FALSE)
  70. {
  71. /*
  72. RECT rect;
  73. HRGN hrgn1, hrgn2;
  74. SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
  75. GetScrollRect(sw, SB_HORZ, hwnd, &rect);
  76. hrgn1 = CreateRectRgnIndirect(&rect);
  77. GetScrollRect(sw, SB_VERT, hwnd, &rect);
  78. hrgn2 = CreateRectRgnIndirect(&rect);
  79. CombineRgn(hrgn1, hrgn2, hrgn1, RGN_OR);
  80. SendMessage(hwnd, WM_NCPAINT, (WPARAM)hrgn1, 0);
  81. DeleteObject(hrgn1);
  82. DeleteObject(hrgn2);*/
  83. SendMessage(hwnd, WM_NCPAINT, (WPARAM)1, 0);
  84. }
  85. else
  86. {
  87. SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE
  88. | SWP_FRAMECHANGED | SWP_DRAWFRAME);
  89. }
  90. }
  91. //
  92. // return the default minimum size of a scrollbar thumb
  93. //
  94. int WINAPI CoolSB_GetDefaultMinThumbSize(void)
  95. {
  96. DWORD dwVersion = GetVersion();
  97. // set the minimum thumb size for a scrollbar. This
  98. // differs between NT4 and 2000, so need to check to see
  99. // which platform we are running under
  100. if(dwVersion < 0x80000000)              // Windows NT/2000
  101. {
  102. if(LOBYTE(LOWORD(dwVersion)) >= 5)
  103. return MINTHUMBSIZE_2000;
  104. else
  105. return MINTHUMBSIZE_NT4;
  106. }
  107. else
  108. {
  109. return MINTHUMBSIZE_NT4;
  110. }
  111. }
  112. static SCROLLINFO *GetScrollInfoFromHwnd(HWND hwnd, int fnBar)
  113. {
  114. SCROLLBAR *sb = GetScrollBarFromHwnd(hwnd, fnBar);
  115. if(sb == 0)
  116. return FALSE;
  117. if(fnBar == SB_HORZ)
  118. {
  119. return &sb->scrollInfo;
  120. }
  121. else if(fnBar == SB_VERT)
  122. {
  123. return &sb->scrollInfo;
  124. }
  125. else
  126. return NULL;
  127. }
  128. //
  129. // Initialize the cool scrollbars for a window by subclassing it
  130. // and using the coolsb window procedure instead
  131. //
  132. BOOL WINAPI InitializeCoolSB(HWND hwnd)
  133. {
  134. SCROLLWND *sw;
  135. SCROLLINFO *si;
  136. INITCOMMONCONTROLSEX ice;
  137. TOOLINFO ti;
  138. RECT rect;
  139. DWORD dwCurStyle;
  140. //BOOL fDisabled;
  141. if(pEnableScrollBar == 0)
  142. pEnableScrollBar = EnableScrollBar;
  143. GetClientRect(hwnd, &rect);
  144. //if we have already initialized Cool Scrollbars for this window,
  145. //then stop the user from doing it again
  146. if(GetScrollWndFromHwnd(hwnd) != 0)
  147. {
  148. return FALSE;
  149. }
  150. //allocate a private scrollbar structure which we 
  151. //will use to keep track of the scrollbar data
  152. sw = (SCROLLWND *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCROLLWND));
  153. si = &sw->sbarHorz.scrollInfo;
  154. si->cbSize = sizeof(SCROLLINFO);
  155. si->fMask  = SIF_ALL;
  156. GetScrollInfo(hwnd, SB_HORZ, si);
  157. si = &sw->sbarVert.scrollInfo;
  158. si->cbSize = sizeof(SCROLLINFO);
  159. si->fMask  = SIF_ALL;
  160. GetScrollInfo(hwnd, SB_VERT, si);
  161. //check to see if the window has left-aligned scrollbars
  162. if(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)
  163. sw->fLeftScrollbar = TRUE;
  164. else
  165. sw->fLeftScrollbar = FALSE;
  166. dwCurStyle = GetWindowLong(hwnd, GWL_STYLE);
  167. SetProp(hwnd, szPropStr, (HANDLE)sw);
  168. //try to enable the scrollbar arrows - if the return value is
  169. //non-zero, then the scrollbars were previously disabled
  170. //fDisabled = pEnableScrollBar(hwnd, SB_HORZ, ESB_ENABLE_BOTH);
  171. //scrollbars will automatically get enabled, even if
  172. //they aren't to start with....sorry, but there isn't an
  173. //easy alternative.
  174. if(dwCurStyle & WS_HSCROLL)
  175. sw->sbarHorz.fScrollFlags = CSBS_VISIBLE;
  176. if(dwCurStyle & WS_VSCROLL)
  177. sw->sbarVert.fScrollFlags = CSBS_VISIBLE;
  178. //need to be able to distinguish between horizontal and vertical
  179. //scrollbars in some instances
  180. sw->sbarHorz.nBarType      = SB_HORZ;
  181. sw->sbarVert.nBarType      = SB_VERT;
  182. sw->sbarHorz.fFlatScrollbar  = CSBS_NORMAL;
  183. sw->sbarVert.fFlatScrollbar  = CSBS_NORMAL;
  184. //set the default arrow sizes for the scrollbars
  185. sw->sbarHorz.nArrowLength  = SYSTEM_METRIC;
  186. sw->sbarHorz.nArrowWidth  = SYSTEM_METRIC;
  187. sw->sbarVert.nArrowLength  = SYSTEM_METRIC;
  188. sw->sbarVert.nArrowWidth  = SYSTEM_METRIC;
  189. sw->bPreventStyleChange  = FALSE;
  190. sw->oldproc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)CoolSBWndProc);
  191. CoolSB_SetMinThumbSize(hwnd, SB_BOTH, CoolSB_GetDefaultMinThumbSize());
  192. #ifdef COOLSB_TOOLTIPS
  193. ice.dwSize = sizeof(ice);
  194. ice.dwICC  = ICC_BAR_CLASSES;
  195. InitCommonControlsEx(&ice);
  196. sw->hwndToolTip = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, TOOLTIPS_CLASS, _T(""),
  197.                             WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
  198.                             CW_USEDEFAULT, CW_USEDEFAULT,
  199.                             CW_USEDEFAULT, CW_USEDEFAULT,
  200.                             hwnd, NULL, GetModuleHandle(0),
  201.                             NULL);
  202. ti.cbSize = sizeof(TOOLINFO);
  203. ti.uFlags = TTF_IDISHWND;
  204. ti.hwnd   = hwnd;
  205. ti.uId    = (UINT)hwnd;
  206. ti.lpszText = LPSTR_TEXTCALLBACK;
  207. ti.hinst   = GetModuleHandle(0);
  208. SendMessage(sw->hwndToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
  209. #else
  210. UNREFERENCED_PARAMETER(ice);
  211. UNREFERENCED_PARAMETER(ti);
  212. sw->hwndToolTip = 0;
  213. #endif
  214. //send the window a frame changed message to update the scrollbars
  215. RedrawNonClient(hwnd, TRUE);
  216. return TRUE;
  217. }
  218. BOOL WINAPI CoolSB_EnableScrollBar (HWND hwnd, int wSBflags, UINT wArrows)
  219. {
  220. SCROLLBAR *sbar;
  221. UINT oldstate;
  222. BOOL bFailed = FALSE;
  223. if(!CoolSB_IsCoolScrollEnabled(hwnd))
  224. return EnableScrollBar(hwnd, wSBflags, wArrows);
  225. if((wSBflags == SB_HORZ || wSBflags == SB_BOTH) && 
  226. (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  227. {
  228. oldstate = sbar->fScrollFlags;
  229. //clear any existing state, and OR in the disabled flags
  230. sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows;
  231. if(oldstate == sbar->fScrollFlags)
  232. bFailed = TRUE;
  233. }
  234. if((wSBflags == SB_VERT || wSBflags == SB_BOTH) && 
  235. (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  236. {
  237. oldstate = sbar->fScrollFlags;
  238. //clear any existing state, and OR in the disabled flags
  239. sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows;
  240. if(oldstate == sbar->fScrollFlags)
  241. bFailed = TRUE;
  242. }
  243. return !bFailed;
  244. }
  245. BOOL WINAPI CoolSB_GetScrollBarInfo(HWND hwnd)
  246. {
  247. // SCROLLBARINFO sbi; not defined in winuser.h
  248. return FALSE;
  249. }
  250. BOOL WINAPI CoolSB_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
  251. {
  252. SCROLLINFO *mysi;
  253. BOOL copied = FALSE;
  254. if(!lpsi)
  255. return FALSE;
  256. if(!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar)))
  257. {
  258. return GetScrollInfo(hwnd, fnBar, lpsi);
  259. }
  260. if(lpsi->fMask & SIF_PAGE)
  261. {
  262. lpsi->nPage = mysi->nPage;
  263. copied = TRUE;
  264. }
  265. if(lpsi->fMask & SIF_POS)
  266. {
  267. lpsi->nPos = mysi->nPos;
  268. copied = TRUE;
  269. }
  270. if(lpsi->fMask & SIF_TRACKPOS)
  271. {
  272. lpsi->nTrackPos = mysi->nTrackPos;
  273. copied = TRUE;
  274. }
  275. if(lpsi->fMask & SIF_RANGE)
  276. {
  277. lpsi->nMin = mysi->nMin;
  278. lpsi->nMax = mysi->nMax;
  279. copied = TRUE;
  280. }
  281. return copied;
  282. }
  283. int WINAPI CoolSB_GetScrollPos (HWND hwnd, int nBar)
  284. {
  285. SCROLLINFO *mysi;
  286. if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
  287. return GetScrollPos(hwnd, nBar);
  288. return mysi->nPos;
  289. }
  290. BOOL WINAPI CoolSB_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos)
  291. {
  292. SCROLLINFO *mysi;
  293. if(!lpMinPos || !lpMaxPos)
  294. return FALSE;
  295. if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
  296. return GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos);
  297. *lpMinPos = mysi->nMin;
  298. *lpMaxPos = mysi->nMax;
  299. return TRUE;
  300. }
  301. int WINAPI CoolSB_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw)
  302. {
  303. SCROLLINFO *mysi;
  304. SCROLLBAR *sbar;
  305. BOOL       fRecalcFrame = FALSE;
  306. if(!lpsi)
  307. return FALSE;
  308. if(!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar)))
  309. return SetScrollInfo(hwnd, fnBar, lpsi, fRedraw);
  310. //if(CoolSB_IsThumbTracking(hwnd))
  311. // return mysi->nPos;
  312. if(lpsi->fMask & SIF_RANGE)
  313. {
  314. mysi->nMin = lpsi->nMin;
  315. mysi->nMax = lpsi->nMax;
  316. }
  317. //The nPage member must specify a value from 0 to nMax - nMin +1. 
  318. if(lpsi->fMask & SIF_PAGE)
  319. {
  320. UINT t = (UINT)(mysi->nMax - mysi->nMin + 1);
  321. mysi->nPage = min(max(0, lpsi->nPage), t);
  322. }
  323. //The nPos member must specify a value between nMin and nMax - max(nPage - 1, 0).
  324. if(lpsi->fMask & SIF_POS)
  325. {
  326. mysi->nPos = max(lpsi->nPos, mysi->nMin);
  327. mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0));
  328. }
  329. sbar = GetScrollBarFromHwnd(hwnd, fnBar);
  330. if((lpsi->fMask & SIF_DISABLENOSCROLL) || (sbar->fScrollFlags & CSBS_THUMBALWAYS))
  331. {
  332. if(!sbar->fScrollVisible)
  333. {
  334. CoolSB_ShowScrollBar(hwnd, fnBar, TRUE);
  335. fRecalcFrame = TRUE;
  336. }
  337. }
  338. else
  339. {
  340. if(    mysi->nPage >  (UINT)mysi->nMax 
  341. || mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0
  342. || mysi->nMax  <= mysi->nMin)
  343. {
  344. if(sbar->fScrollVisible)
  345. {
  346. CoolSB_ShowScrollBar(hwnd, fnBar, FALSE);
  347. fRecalcFrame = TRUE;
  348. }
  349. }
  350. else
  351. {
  352. if(!sbar->fScrollVisible)
  353. {
  354. CoolSB_ShowScrollBar(hwnd, fnBar, TRUE);
  355. fRecalcFrame = TRUE;
  356. }
  357. }
  358. }
  359. if(fRedraw && !CoolSB_IsThumbTracking(hwnd))
  360. RedrawNonClient(hwnd, fRecalcFrame);
  361. return mysi->nPos;
  362. }
  363. int WINAPI CoolSB_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw)
  364. {
  365. SCROLLINFO *mysi;
  366. int oldpos;
  367. if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
  368. {
  369. return SetScrollPos(hwnd, nBar, nPos, fRedraw);
  370. }
  371. //this is what should happen, but real scrollbars don't work like this..
  372. //if(CoolSB_IsThumbTracking(hwnd))
  373. // return mysi->nPos;
  374. //validate and set the scollbar position
  375. oldpos = mysi->nPos;
  376. mysi->nPos = max(nPos, mysi->nMin);
  377. mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0));
  378. if(fRedraw && !CoolSB_IsThumbTracking(hwnd))
  379. RedrawNonClient(hwnd, FALSE);
  380. return oldpos;
  381. }
  382. int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw)
  383. {
  384. SCROLLINFO *mysi;
  385. if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar)))
  386. return SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, fRedraw);
  387. if(CoolSB_IsThumbTracking(hwnd))
  388. return mysi->nPos;
  389. //hide the scrollbar if nMin == nMax
  390. //nMax-nMin must not be greater than MAXLONG
  391. mysi->nMin = nMinPos;
  392. mysi->nMax = nMaxPos;
  393. if(fRedraw)
  394. RedrawNonClient(hwnd, FALSE);
  395. return TRUE;
  396. }
  397. //
  398. // Show or hide the specified scrollbars
  399. //
  400. BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow)
  401. {
  402. SCROLLBAR *sbar;
  403. BOOL bFailed = FALSE;
  404. DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  405. if(!CoolSB_IsCoolScrollEnabled(hwnd))
  406. return ShowScrollBar(hwnd, wBar, fShow);
  407. if((wBar == SB_HORZ || wBar == SB_BOTH) && 
  408.    (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  409. {
  410. sbar->fScrollFlags  =  sbar->fScrollFlags & ~CSBS_VISIBLE;
  411. sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
  412. //bFailed = TRUE;
  413. if(fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL);
  414. else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL);
  415. }
  416. if((wBar == SB_VERT || wBar == SB_BOTH) && 
  417.    (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  418. {
  419. sbar->fScrollFlags  =  sbar->fScrollFlags & ~CSBS_VISIBLE;
  420. sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
  421. //bFailed = TRUE;
  422. if(fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL);
  423. else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL);
  424. }
  425. if(bFailed)
  426. {
  427. return FALSE;
  428. }
  429. else
  430. {
  431. //DWORD style = GetWindowLong(hwnd, GWL_STYLE);
  432. //style |= WS_VSCROLL;
  433. //if(s
  434. //SetWindowLong(hwnd, GWL_STYLE, style);
  435. SetWindowPos(hwnd, 0, 0, 0, 0, 0, 
  436. SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 
  437. SWP_NOACTIVATE | SWP_FRAMECHANGED);
  438. return TRUE;
  439. }
  440. }
  441. //
  442. // Remove cool scrollbars from the specified window.
  443. //
  444. HRESULT WINAPI UninitializeCoolSB(HWND hwnd)
  445. {
  446. int i = 0;
  447. SCROLLWND *sw = GetScrollWndFromHwnd(hwnd);
  448. if(!sw) return E_FAIL;
  449. //restore the window procedure with the original one
  450. SetWindowLong(hwnd, GWL_WNDPROC, (LONG)sw->oldproc);
  451. RemoveProp(hwnd, szPropStr);
  452. //SetWindowLong(hwnd, GWL_USERDATA, 0);
  453. //finally, release the memory needed for the cool scrollbars
  454. HeapFree(GetProcessHeap(), 0, sw);
  455.     //Force WM_NCCALCSIZE and WM_NCPAINT so the original scrollbars can kick in
  456.     RedrawNonClient(hwnd, TRUE);
  457. return S_OK;
  458. }
  459. #ifdef INCLUDE_BUTTONS
  460. //
  461. // Cool scrollbar specific interface (BUTTON support)
  462. //
  463. //
  464. // Insert a button into the scrollbar area
  465. //
  466. // wSBflags - SB_HORZ / SB_VERT only
  467. // uPos     - position into which to insert.
  468. // can be 0 to insert at the start, or -1 to insert
  469. // at the end of previously inserted buttons
  470. //
  471. BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb)
  472. {
  473. SCROLLBAR *sbar;
  474. SCROLLBUT *sbut;
  475. UINT i;
  476. if(!psb) return FALSE;
  477. if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
  478. return FALSE;
  479. //check that we havn't reached the maximum allowed buttons yet
  480. if(sbar->nButtons == MAX_COOLSB_BUTS)
  481. return FALSE;
  482. //insert at end
  483. if(nPos == -1)
  484. {
  485. sbut = &sbar->sbButtons[sbar->nButtons];
  486. }
  487. //otherwise, need to make room
  488. else if((int)nPos < 0 || (int)nPos > (UINT)sbar->nButtons)
  489. {
  490. return FALSE;
  491. }
  492. else
  493. {
  494. //insert space for the button at the specified position
  495. for(i = sbar->nButtons; i > nPos; i--)
  496. {
  497. sbar->sbButtons[i] = sbar->sbButtons[i-1];
  498. }
  499. sbut = &sbar->sbButtons[nPos];
  500. }
  501. //only set the button's properties if they are
  502. //specified by the SCROLLBUT->fMask. 
  503. //Otherwise, use a default property value
  504. if(psb->fMask & SBBF_TYPE)
  505. sbut->uButType   = psb->uButType;
  506. else
  507. sbut->uButType  = SBBT_PUSHBUTTON;
  508. if(psb->fMask & SBBF_STATE)
  509. sbut->uState  = psb->uState;
  510. else
  511. sbut->uState  = 0;
  512. if(psb->fMask & SBBF_ID)
  513. sbut->uCmdId     = psb->uCmdId;
  514. else
  515. sbut->uCmdId  = 0;
  516. if(psb->fMask & SBBF_SIZE)
  517. sbut->nSize  = psb->nSize;
  518. else
  519. sbut->nSize  = -1;
  520. if(psb->fMask & SBBF_PLACEMENT)
  521. sbut->uPlacement = psb->uPlacement;
  522. else
  523. sbut->uPlacement = SBBP_LEFT;
  524. if(psb->fMask & SBBF_BITMAP)
  525. sbut->hBmp  = psb->hBmp;
  526. else
  527. sbut->hBmp  = 0;
  528. if(psb->fMask & SBBF_ENHMETAFILE)
  529. sbut->hEmf  = psb->hEmf;
  530. else
  531. sbut->hEmf  = 0;
  532. if(psb->fMask & SBBF_CURSOR)
  533. sbut->hCurs = psb->hCurs;
  534. else
  535. sbut->hCurs = 0;
  536. /*
  537. We don't use the callback function anymore. The uButType
  538. member must now specify SBBT_OWNERDRAW, and a WM_NOTIFY will
  539. be sent when a button must be drawn
  540. if((psb->fMask & SBBF_OWNERDRAW) && ((psb->uButType & SBBT_MASK) == SBBT_OWNERDRAW))
  541. pDrawProc  = psb->pDrawProc;
  542. else
  543. pDrawProc  = 0;*/
  544. sbar->nButtons++;
  545. sbut->nSizeReserved = sbut->nSize;
  546. //MAKE SURE that any resizable buttons are only to the left / above
  547. //a scrollbar. We don't support resize operations to the right of a scrollbar
  548. if((sbut->uButType & SBBM_RESIZABLE) && sbut->uPlacement == SBBP_RIGHT)
  549. sbut->uButType &= ~SBBM_RESIZABLE;
  550. if(psb->fMask & SBBF_BUTMINMAX)
  551. {
  552. sbut->nMinSize = psb->nMinSize;
  553. sbut->nMaxSize = psb->nMaxSize;
  554. }
  555. else
  556. {
  557. sbut->nMinSize = 0;
  558. sbut->nMaxSize = -1;
  559. }
  560. return TRUE;
  561. }
  562. static SCROLLBUT *GetButtonFromId(SCROLLBAR *sbar, UINT uCmdId)
  563. {
  564. int i;
  565. for(i = 0; i < sbar->nButtons; i++)
  566. {
  567. if(sbar->sbButtons[i].uCmdId == uCmdId)
  568. return &sbar->sbButtons[i];
  569. }
  570. return 0;
  571. }
  572. //
  573. // Modify the properties of the specified scrollbar button.
  574. // wSBflags - SB_HORZ / SB_VERT only
  575. // uItem    - the command identifier specified when the button was created,
  576. //    or a non-negative position of the button, depending on if
  577. //    fByCmd is FALSE or TRUE, respectively
  578. //
  579. BOOL WINAPI CoolSB_ModifyButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb)
  580. {
  581. SCROLLBAR *sbar;
  582. SCROLLBUT *sbut;
  583. if(!psb) return FALSE;
  584. //find if this window is CoolScroll enabled
  585. if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
  586. return FALSE;
  587. //find the button to modify, depending on if we
  588. //are modifying by position or command id
  589. if(fByCmd == FALSE)
  590. {
  591. //button from position
  592. if((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons)
  593. return FALSE;
  594. else
  595. sbut = &sbar->sbButtons[uItem];
  596. }
  597. else if(fByCmd == TRUE)
  598. {
  599. //button from command identifier
  600. if(!(sbut = GetButtonFromId(sbar, uItem)))
  601. return FALSE;
  602. }
  603. if(psb->fMask & SBBF_TYPE) sbut->uButType   = psb->uButType;
  604. if(psb->fMask & SBBF_STATE) sbut->uState  = psb->uState;
  605. if(psb->fMask & SBBF_ID) sbut->uCmdId     = psb->uCmdId;
  606. if(psb->fMask & SBBF_SIZE) sbut->nSize  = psb->nSize;
  607. if(psb->fMask & SBBF_PLACEMENT) sbut->uPlacement = psb->uPlacement;
  608. if(psb->fMask & SBBF_BITMAP) sbut->hBmp  = psb->hBmp;
  609. if(psb->fMask & SBBF_ENHMETAFILE) sbut->hEmf  = psb->hEmf;
  610. if(psb->fMask & SBBF_CURSOR) sbut->hCurs  = psb->hCurs;
  611. if(psb->fMask & SBBF_BUTMINMAX)
  612. {
  613. sbut->nMinSize = psb->nMinSize;
  614. sbut->nMaxSize = psb->nMaxSize;
  615. }
  616. return TRUE;
  617. }
  618. BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd)
  619. {
  620. int i;
  621. SCROLLBAR *sbar;
  622. //find if this window is CoolScroll enabled
  623. if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
  624. return FALSE;
  625. //find the button to modify, depending on if we
  626. //are modifying by position or command id
  627. if(fByCmd == FALSE && ((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons))
  628. {
  629. return FALSE;
  630. }
  631. else if(fByCmd == TRUE)
  632. {
  633. //find the button with the specified command id
  634. for(i = 0; i < sbar->nButtons; i++)
  635. {
  636. if(sbar->sbButtons[i].uCmdId == uItem)
  637. {
  638. //change the id to an index
  639. uItem = i;
  640. break;
  641. }
  642. }
  643. //if we failed to find the button...
  644. if(i == sbar->nButtons) return FALSE;
  645. }
  646. //remove the button!
  647. for(i = uItem; i < sbar->nButtons - 1; i++)
  648. {
  649. sbar->sbButtons[i] = sbar->sbButtons[i+1];
  650. }
  651. sbar->nButtons--;
  652. RedrawNonClient(hwnd, TRUE);
  653. return TRUE;
  654. }
  655. //
  656. // fill in the supplied SCROLLBUT structure
  657. //
  658. BOOL WINAPI CoolSB_GetButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb)
  659. {
  660. SCROLLBAR *sbar;
  661. SCROLLBUT *sbut;
  662. if(!psb) return FALSE;
  663. //find if this window is CoolScroll enabled
  664. if(!(sbar = GetScrollBarFromHwnd(hwnd, wSBflags)))
  665. return FALSE;
  666. //find the button to modify, depending on if we
  667. //are modifying by position or command id
  668. if(fByCmd == FALSE)
  669. {
  670. //button from position
  671. if((int)uItem < 0 || (int)uItem >= (UINT)sbar->nButtons)
  672. return FALSE;
  673. else
  674. sbut = &sbar->sbButtons[uItem];
  675. }
  676. else if(fByCmd == TRUE)
  677. {
  678. //button from command identifier
  679. if(!(sbut = GetButtonFromId(sbar, uItem)))
  680. return FALSE;
  681. }
  682. //copy them across
  683. *psb = *sbut;
  684. return FALSE; 
  685. }
  686. #else
  687. BOOL WINAPI CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos,  SCROLLBUT *psb) { return FALSE; }
  688. BOOL WINAPI CoolSB_ModifyButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) { return FALSE; }
  689. BOOL WINAPI CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd) { return FALSE; }
  690. BOOL WINAPI CoolSB_GetButton   (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb) { return FALSE; }
  691. #endif //INCLUDE_BUTTONS
  692. //
  693. // Set the size of the scrollbars
  694. //
  695. BOOL WINAPI CoolSB_SetSize (HWND hwnd, int wBar, int nLength, int nWidth)
  696. {
  697. SCROLLBAR *sbar;
  698. if(nLength == 0 || nWidth == 0)
  699. return FALSE;
  700. if(nLength < -8 || nWidth < -8)
  701. return FALSE;
  702. if(nLength > 256 || nWidth > 256)
  703. return FALSE;
  704. if(!GetScrollWndFromHwnd(hwnd))
  705. return FALSE;
  706. if((wBar == SB_HORZ || wBar == SB_BOTH) && 
  707.    (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  708. {
  709. sbar->nArrowLength = nLength;
  710. sbar->nArrowWidth  = nWidth;
  711. }
  712. if((wBar == SB_VERT || wBar == SB_BOTH) && 
  713.    (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  714. {
  715. sbar->nArrowLength = nLength;
  716. sbar->nArrowWidth  = nWidth;
  717. }
  718. RedrawNonClient(hwnd, TRUE);
  719. return TRUE;
  720. }
  721. //
  722. // Alter the display mode of the scrollbars
  723. // wBar   - SB_HORZ / SB_VERT / SB_BOTH
  724. // nStyle - CSBF_NORMAL / CSBF_FLAT / CSBF_HOTTRACKED
  725. //
  726. BOOL WINAPI CoolSB_SetStyle(HWND hwnd, int wBar, UINT nStyle)
  727. {
  728. SCROLLBAR *sbar;
  729. if(!GetScrollWndFromHwnd(hwnd))
  730. return FALSE;
  731. if((wBar == SB_HORZ || wBar == SB_BOTH) && 
  732.    (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  733. {
  734. sbar->fFlatScrollbar = nStyle;
  735. }
  736. if((wBar == SB_VERT || wBar == SB_BOTH) && 
  737.    (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  738. {
  739. sbar->fFlatScrollbar = nStyle;
  740. }
  741. RedrawNonClient(hwnd, FALSE);
  742. return TRUE;
  743. }
  744. //
  745. // Set if the thumb is always visible, even if there is no data to
  746. //  scroll. Setting this keeps the scrollbar enabled, but the thumb
  747. //  covers the whole area
  748. //
  749. BOOL WINAPI CoolSB_SetThumbAlways(HWND hwnd, int wBar, BOOL fThumbAlways)
  750. {
  751. SCROLLBAR *sbar;
  752. if(!GetScrollWndFromHwnd(hwnd))
  753. return FALSE;
  754. if((wBar == SB_HORZ || wBar == SB_BOTH) && 
  755.    (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  756. {
  757. if(fThumbAlways)
  758. sbar->fScrollFlags |=  CSBS_THUMBALWAYS;
  759. else
  760. sbar->fScrollFlags &= ~CSBS_THUMBALWAYS;
  761. }
  762. if((wBar == SB_VERT || wBar == SB_BOTH) && 
  763.    (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  764. {
  765. if(fThumbAlways)
  766. sbar->fScrollFlags |=  CSBS_THUMBALWAYS;
  767. else
  768. sbar->fScrollFlags &= ~CSBS_THUMBALWAYS;
  769. }
  770. RedrawNonClient(hwnd, FALSE);
  771. return TRUE;
  772. }
  773. //
  774. // Set the minimum size, in pixels, that the thumb box will shrink to.
  775. //
  776. BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size)
  777. {
  778. SCROLLBAR *sbar;
  779. if(!GetScrollWndFromHwnd(hwnd))
  780. return FALSE;
  781. if(size == -1)
  782. size = CoolSB_GetDefaultMinThumbSize();
  783. if((wBar == SB_HORZ || wBar == SB_BOTH) && 
  784.    (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
  785. {
  786. sbar->nMinThumbSize = size;
  787. }
  788. if((wBar == SB_VERT || wBar == SB_BOTH) && 
  789.    (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
  790. {
  791. sbar->nMinThumbSize = size;
  792. }
  793. return TRUE;
  794. }