123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391 |
- // some code taken from (freeware) Cool ScrollBar library by J Brown
- #include "main.h"
- #include <windowsx.h>
- #include <tchar.h>
- #include "scrollwnd.h"
- #include "../winamp/wa_dlg.h"
- #ifndef WM_MOUSEWHEEL
- #define WM_MOUSEWHEEL 0x020A
- #endif
- extern HRESULT(WINAPI *SetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); //xp theme shit
- extern HRESULT(WINAPI *IsAppThemed)(void);
- static TCHAR szPropStr[] = _T("CoolSBSubclassPtr");
- //
- // Special thumb-tracking variables
- //
- //
- static UINT uCurrentScrollbar = COOLSB_NONE; //SB_HORZ / SB_VERT
- static UINT uCurrentScrollPortion = HTSCROLL_NONE;
- static UINT uCurrentButton = 0;
- static RECT rcThumbBounds; //area that the scroll thumb can travel in
- static int nThumbSize; //(pixels)
- static int nThumbPos; //(pixels)
- static int nThumbMouseOffset; //(pixels)
- static int nLastPos = -1; //(scrollbar units)
- static int nThumbPos0; //(pixels) initial thumb position
- //
- // Temporary state used to auto-generate timer messages
- //
- static UINT uMouseOverId = 0;
- static UINT uMouseOverScrollbar = COOLSB_NONE;
- static UINT uHitTestPortion = HTSCROLL_NONE;
- static UINT uLastHitTestPortion = HTSCROLL_NONE;
- static RECT MouseOverRect;
- static UINT uScrollTimerMsg = 0;
- static UINT uScrollTimerPortion = HTSCROLL_NONE;
- static UINT_PTR uScrollTimerId = 0;
- static HWND hwndCurCoolSB = 0;
- ScrollWnd *GetScrollWndFromHwnd(HWND hwnd)
- {
- return (ScrollWnd *)GetProp(hwnd, szPropStr);
- }
- //
- // swap the rectangle's x coords with its y coords
- //
- static void __stdcall RotateRect(RECT *rect)
- {
- int temp;
- temp = rect->left;
- rect->left = rect->top;
- rect->top = temp;
- temp = rect->right;
- rect->right = rect->bottom;
- rect->bottom = temp;
- }
- //
- // swap the coords if the scrollbar is a SB_VERT
- //
- static void __stdcall RotateRect0(SCROLLBAR *sb, RECT *rect)
- {
- if (sb->nBarType == SB_VERT)
- RotateRect(rect);
- }
- //
- // Calculate if the SCROLLINFO members produce
- // an enabled or disabled scrollbar
- //
- static BOOL IsScrollInfoActive(SCROLLINFO *si)
- {
- if ((si->nPage > (UINT)si->nMax
- || si->nMax <= si->nMin || si->nMax == 0))
- return FALSE;
- else
- return TRUE;
- }
- //
- // Return if the specified scrollbar is enabled or not
- //
- static BOOL IsScrollbarActive(SCROLLBAR *sb)
- {
- SCROLLINFO *si = &sb->scrollInfo;
- if (((sb->fScrollFlags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ||
- !(sb->fScrollFlags & CSBS_THUMBALWAYS) && !IsScrollInfoActive(si))
- return FALSE;
- else
- return TRUE;
- }
- BOOL drawFrameControl(HDC hdc, LPRECT lprc, UINT uType, UINT state)
- {
- HDC hdcbmp;
- HBITMAP hbmpOld, hbmp;
- int startx, starty;
- hbmp = WADlg_getBitmap();
- if (!hbmp) return FALSE;
- hdcbmp = CreateCompatibleDC(hdc);
- if (!hdcbmp) return FALSE;
- hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp);
-
- startx = 0;
- starty = 31;
- switch (state&3)
- {
- case DFCS_SCROLLRIGHT: startx = 14; starty = 45; break;
- case DFCS_SCROLLLEFT: startx = 0; starty = 45; break;
- case DFCS_SCROLLDOWN: startx = 14; starty = 31; break;
- }
- if (state&DFCS_PUSHED) startx += 28;
- StretchBlt(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, hdcbmp, startx, starty, 14, 14, SRCCOPY);
-
- SelectObject(hdcbmp, hbmpOld);
- DeleteDC(hdcbmp);
- return 1;
- }
- //
- // Draw a standard scrollbar arrow
- //
- static int DrawScrollArrow(SCROLLBAR *sbar, HDC hdc, RECT *rect, UINT arrow, BOOL fMouseDown, BOOL fMouseOver)
- {
- UINT ret;
- UINT flags = arrow;
- //HACKY bit so this routine can be called by vertical and horizontal code
- if (sbar->nBarType == SB_VERT)
- {
- if (flags & DFCS_SCROLLLEFT) flags = flags & ~DFCS_SCROLLLEFT | DFCS_SCROLLUP;
- if (flags & DFCS_SCROLLRIGHT) flags = flags & ~DFCS_SCROLLRIGHT | DFCS_SCROLLDOWN;
- }
- if (fMouseDown) flags |= (DFCS_FLAT | DFCS_PUSHED);
- ret = drawFrameControl(hdc, rect, DFC_SCROLL, flags);
- return ret;
- }
- //
- // Return the size in pixels for the specified scrollbar metric,
- // for the specified scrollbar
- //
- static int GetScrollMetric(SCROLLBAR *sbar, int metric)
- {
- if (sbar->nBarType == SB_HORZ)
- {
- if (metric == SM_CXHORZSB)
- {
- if (sbar->nArrowLength < 0)
- return -sbar->nArrowLength * 14; //GetSystemMetrics(SM_CXHSCROLL);
- else
- return sbar->nArrowLength;
- }
- else
- {
- if (sbar->nArrowWidth < 0)
- return -sbar->nArrowWidth * 14; //GetSystemMetrics(SM_CYHSCROLL);
- else
- return sbar->nArrowWidth;
- }
- }
- else if (sbar->nBarType == SB_VERT)
- {
- if (metric == SM_CYVERTSB)
- {
- if (sbar->nArrowLength < 0)
- return -sbar->nArrowLength * 14;//GetSystemMetrics(SM_CYVSCROLL);
- else
- return sbar->nArrowLength;
- }
- else
- {
- if (sbar->nArrowWidth < 0)
- return -sbar->nArrowWidth * 14;//GetSystemMetrics(SM_CXVSCROLL);
- else
- return sbar->nArrowWidth;
- }
- }
- return 0;
- }
- //
- //
- //
- static COLORREF GetSBForeColor(void)
- {
- return WADlg_getColor(WADLG_SCROLLBAR_FGCOLOR);
- }
- static COLORREF GetSBBackColor(void)
- {
- return WADlg_getColor(WADLG_SCROLLBAR_BGCOLOR);
- }
- //
- // Paint a checkered rectangle, with each alternate
- // pixel being assigned a different colour
- //
- static void DrawCheckedRect(HDC hdc, RECT *rect, COLORREF fg, COLORREF bg)
- {
- static WORD wCheckPat[8] =
- {
- 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555
- };
- HBITMAP hbmp;
- HBRUSH hbr, hbrold;
- COLORREF fgold, bgold;
- hbmp = CreateBitmap(8, 8, 1, 1, wCheckPat);
- hbr = CreatePatternBrush(hbmp);
- UnrealizeObject(hbr);
- SetBrushOrgEx(hdc, rect->left, rect->top, 0);
- hbrold = (HBRUSH)SelectObject(hdc, hbr);
- fgold = SetTextColor(hdc, fg);
- bgold = SetBkColor(hdc, bg);
- PatBlt(hdc, rect->left, rect->top,
- rect->right - rect->left,
- rect->bottom - rect->top,
- PATCOPY);
- SetBkColor(hdc, bgold);
- SetTextColor(hdc, fgold);
- SelectObject(hdc, hbrold);
- DeleteObject(hbr);
- DeleteObject(hbmp);
- }
- //
- // Fill the specifed rectangle using a solid colour
- //
- static void PaintRect(HDC hdc, RECT *rect, COLORREF color)
- {
- COLORREF oldcol = SetBkColor(hdc, color);
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, _T(""), 0, 0);
- SetBkColor(hdc, oldcol);
- }
- //
- // Draw a simple blank scrollbar push-button. Can be used
- // to draw a push button, or the scrollbar thumb
- // drawflag - could set to BF_FLAT to make flat scrollbars
- //
- void DrawBlankButton(HDC hdc, const RECT *rect, UINT drawflag, int pushed, int vertical)
- {
- HBITMAP hbmp, hbmpOld;
- hbmp = WADlg_getBitmap();
- if (!hbmp) return;
- HDC hdcbmp = CreateCompatibleDC(hdc);
- if (!hdcbmp) return;
- hbmpOld = (HBITMAP)SelectObject(hdcbmp, hbmp);
- #define PART1SIZE 4 //copied top
- #define PART2SIZE 5 //stretched top
- #define PART3SIZE 10 //copied middle
- #define PART4SIZE 5 //stretched bottom
- #define PART5SIZE 4 //copied bottom
- if (vertical)
- {
- int middle = (rect->bottom - rect->top) / 2;
- int startx = pushed ? 70 : 56;
- //top
- StretchBlt(hdc, rect->left, rect->top, rect->right - rect->left, PART1SIZE, hdcbmp, startx, 31, 14, PART1SIZE, SRCCOPY);
- int p = PART1SIZE;
- //stretched top
- int l = middle - PART1SIZE - (PART3SIZE / 2);
- if (l > 0)
- {
- StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE, 14, PART2SIZE, SRCCOPY);
- p += middle - PART1SIZE - (PART3SIZE / 2);
- }
- //copied middle
- int m = (rect->bottom - rect->top) - PART1SIZE - PART5SIZE; //space that's available for middle
- m = min(m, PART3SIZE);
- if (m > 0)
- {
- StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, m, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE, 14, m, SRCCOPY);
- p += m;
- }
- //stretched bottom
- l = rect->bottom - rect->top - p - PART5SIZE;
- if (l > 0) StretchBlt(hdc, rect->left, rect->top + p, rect->right - rect->left, l, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE, 14, PART4SIZE, SRCCOPY);
- //bottom
- StretchBlt(hdc, rect->left, rect->bottom - PART5SIZE, rect->right - rect->left, PART5SIZE, hdcbmp, startx, 31 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, 14, PART5SIZE, SRCCOPY);
- }
- else
- {
- int middle = (rect->right - rect->left) / 2;
- int starty = pushed ? 45 : 31;
- //top
- StretchBlt(hdc, rect->left, rect->top, PART1SIZE, rect->bottom - rect->top, hdcbmp, 84, starty, PART1SIZE, 14, SRCCOPY);
- int p = PART1SIZE;
- //stretched top
- int l = middle - PART1SIZE - (PART3SIZE / 2);
- if (l > 0)
- {
- StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE, starty, PART2SIZE, 14, SRCCOPY);
- p += middle - PART1SIZE - (PART3SIZE / 2);
- }
- //copied middle
- int m = (rect->right - rect->left) - PART1SIZE - PART5SIZE; //space that's available for middle
- m = min(m, PART3SIZE);
- if (m > 0)
- {
- StretchBlt(hdc, rect->left + p, rect->top, m, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE, starty, m, 14, SRCCOPY);
- p += m;
- }
- //stretched bottom
- l = rect->right - rect->left - p - PART5SIZE;
- if (l > 0) StretchBlt(hdc, rect->left + p, rect->top, l, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE, starty, PART4SIZE, 14, SRCCOPY);
- //bottom
- StretchBlt(hdc, rect->right - PART5SIZE, rect->top, PART5SIZE, rect->bottom - rect->top, hdcbmp, 84 + PART1SIZE + PART2SIZE + PART3SIZE + PART4SIZE, starty, PART5SIZE, 14, SRCCOPY);
- }
- SelectObject(hdcbmp, hbmpOld);
- DeleteDC(hdcbmp);
- }
- //
- // Send a WM_VSCROLL or WM_HSCROLL message
- //
- static void SendScrollMessage(HWND hwnd, UINT scrMsg, UINT scrId, UINT pos)
- {
- SendMessage(hwnd, scrMsg, MAKEWPARAM(scrId, pos), 0);
- }
- //
- // Calculate the screen coordinates of the area taken by
- // the horizontal scrollbar. Take into account the size
- // of the window borders
- //
- static BOOL GetHScrollRect(ScrollWnd *sw, HWND hwnd, RECT *rect)
- {
- GetWindowRect(hwnd, rect);
- if (sw->fLeftScrollbar)
- {
- rect->left += sw->cxLeftEdge + (sw->sbarVert.fScrollVisible ?
- GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
- rect->right -= sw->cxRightEdge;
- }
- else
- {
- rect->left += sw->cxLeftEdge; //left window edge
- rect->right -= sw->cxRightEdge + //right window edge
- (sw->sbarVert.fScrollVisible ?
- GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
- }
- rect->bottom -= sw->cyBottomEdge; //bottom window edge
- rect->top = rect->bottom -
- (sw->sbarHorz.fScrollVisible ?
- GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0);
- return TRUE;
- }
- //
- // Calculate the screen coordinates of the area taken by the
- // vertical scrollbar
- //
- static BOOL GetVScrollRect(ScrollWnd *sw, HWND hwnd, RECT *rect)
- {
- GetWindowRect(hwnd, rect);
- rect->top += sw->cyTopEdge; //top window edge
- rect->bottom -= sw->cyBottomEdge +
- (sw->sbarHorz.fScrollVisible ? //bottom window edge
- GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB) : 0);
- if (sw->fLeftScrollbar)
- {
- rect->left += sw->cxLeftEdge;
- rect->right = rect->left + (sw->sbarVert.fScrollVisible ?
- GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
- }
- else
- {
- rect->right -= sw->cxRightEdge;
- rect->left = rect->right - (sw->sbarVert.fScrollVisible ?
- GetScrollMetric(&sw->sbarVert, SM_CXVERTSB) : 0);
- }
- return TRUE;
- }
- // Depending on what type of scrollbar nBar refers to, call the
- // appropriate Get?ScrollRect function
- //
- BOOL GetScrollRect(ScrollWnd *sw, UINT nBar, HWND hwnd, RECT *rect)
- {
- if (nBar == SB_HORZ)
- return GetHScrollRect(sw, hwnd, rect);
- else if (nBar == SB_VERT)
- return GetVScrollRect(sw, hwnd, rect);
- else
- return FALSE;
- }
- //
- // Work out the scrollbar width/height for either type of scrollbar (SB_HORZ/SB_VERT)
- // rect - coords of the scrollbar.
- // store results into *thumbsize and *thumbpos
- //
- static int CalcThumbSize(SCROLLBAR *sbar, const RECT *rect, int *pthumbsize, int *pthumbpos)
- {
- SCROLLINFO *si;
- int scrollsize; //total size of the scrollbar including arrow buttons
- int workingsize; //working area (where the thumb can slide)
- int siMaxMin;
- int butsize;
- int startcoord;
- int thumbpos = 0, thumbsize = 0;
- //work out the width (for a horizontal) or the height (for a vertical)
- //of a standard scrollbar button
- butsize = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
- if (1) //sbar->nBarType == SB_HORZ)
- {
- scrollsize = rect->right - rect->left;
- startcoord = rect->left;
- }
- /*else if(sbar->nBarType == SB_VERT)
- {
- scrollsize = rect->bottom - rect->top;
- startcoord = rect->top;
- }
- else
- {
- return 0;
- }*/
- si = &sbar->scrollInfo;
- siMaxMin = si->nMax - si->nMin + 1;
- workingsize = scrollsize - butsize * 2;
- //
- // Work out the scrollbar thumb SIZE
- //
- if (si->nPage == 0)
- {
- thumbsize = butsize;
- }
- else if (siMaxMin > 0)
- {
- thumbsize = MulDiv(si->nPage, workingsize, siMaxMin);
- if (thumbsize < sbar->nMinThumbSize)
- thumbsize = sbar->nMinThumbSize;
- }
- //
- // Work out the scrollbar thumb position
- //
- if (siMaxMin > 0)
- {
- int pagesize = max(1, si->nPage);
- thumbpos = MulDiv(si->nPos - si->nMin, workingsize - thumbsize, siMaxMin - pagesize);
- if (thumbpos < 0)
- thumbpos = 0;
- if (thumbpos >= workingsize - thumbsize)
- thumbpos = workingsize - thumbsize;
- }
- thumbpos += startcoord + butsize;
- *pthumbpos = thumbpos;
- *pthumbsize = thumbsize;
- return 1;
- }
- //
- // return a hit-test value for whatever part of the scrollbar x,y is located in
- // rect, x, y: SCREEN coordinates
- // the rectangle must not include space for any inserted buttons
- // (i.e, JUST the scrollbar area)
- //
- static UINT GetHorzScrollPortion(SCROLLBAR *sbar, HWND hwnd, const RECT *rect, int x, int y)
- {
- int thumbwidth, thumbpos;
- int butwidth = GetScrollMetric(sbar, SM_SCROLL_LENGTH);
- int scrollwidth = rect->right - rect->left;
- int workingwidth = scrollwidth - butwidth * 2;
- if (y < rect->top || y >= rect->bottom)
- return HTSCROLL_NONE;
- CalcThumbSize(sbar, rect, &thumbwidth, &thumbpos);
- //if we have had to scale the buttons to fit in the rect,
- //then adjust the button width accordingly
- if (scrollwidth <= butwidth * 2)
- {
- butwidth = scrollwidth / 2;
- }
- //check for left button click
- if (x >= rect->left && x < rect->left + butwidth)
- {
- return HTSCROLL_LEFT;
- }
- //check for right button click
- else if (x >= rect->right - butwidth && x < rect->right)
- {
- return HTSCROLL_RIGHT;
- }
- //if the thumb is too big to fit (i.e. it isn't visible)
- //then return a NULL scrollbar area
- if (thumbwidth >= workingwidth)
- return HTSCROLL_NONE;
- //check for point in the thumbbar
- if (x >= thumbpos && x < thumbpos + thumbwidth)
- {
- return HTSCROLL_THUMB;
- }
- //check for left margin
- else if (x >= rect->left + butwidth && x < thumbpos)
- {
- return HTSCROLL_PAGELEFT;
- }
- else if (x >= thumbpos + thumbwidth && x < rect->right - butwidth)
- {
- return HTSCROLL_PAGERIGHT;
- }
- return HTSCROLL_NONE;
- }
- //
- // For vertical scrollbars, rotate all coordinates by -90 degrees
- // so that we can use the horizontal version of this function
- //
- static UINT GetVertScrollPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
- {
- UINT r;
- RotateRect(rect);
- r = GetHorzScrollPortion(sb, hwnd, rect, y, x);
- RotateRect(rect);
- return r;
- }
- //
- // CUSTOM DRAW support
- //
- static LRESULT PostCustomPrePostPaint0(HWND hwnd, HDC hdc, SCROLLBAR *sb, UINT dwStage)
- {
- return 0;
- }
- static LRESULT PostCustomDrawNotify0(HWND hwnd, HDC hdc, UINT nBar, RECT *prect, UINT nItem, BOOL fMouseDown, BOOL fMouseOver, BOOL fInactive)
- {
- return 0;
- }
- // Depending on if we are supporting custom draw, either define
- // a macro to the function name, or to nothing at all. If custom draw
- // is turned off, then we can save ALOT of code space by binning all
- // calls to the custom draw support.
- //
- #define PostCustomDrawNotify 1 ? (void)0 : PostCustomDrawNotify0
- #define PostCustomPrePostPaint 1 ? (void)0 : PostCustomPrePostPaint0
- static LRESULT PostMouseNotify0(HWND hwnd, UINT msg, UINT nBar, RECT *prect, UINT nCmdId, POINT pt)
- {
- return 0;
- }
- #ifdef NOTIFY_MOUSE
- #define PostMouseNotify PostMouseNotify0
- #else
- #define PostMouseNotify 1 ? (void)0 : PostMouseNotify0
- #endif
- //
- // Draw a complete HORIZONTAL scrollbar in the given rectangle
- // Don't draw any inserted buttons in this procedure
- //
- // uDrawFlags - hittest code, to say if to draw the
- // specified portion in an active state or not.
- //
- //
- static LRESULT NCDrawHScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
- {
- SCROLLINFO *si;
- RECT ctrl, thumb;
- RECT sbm;
- int butwidth = GetScrollMetric(sb, SM_SCROLL_LENGTH);
- int scrollwidth = rect->right - rect->left;
- int workingwidth = scrollwidth - butwidth * 2;
- int thumbwidth = 0, thumbpos = 0;
- BOOL fCustomDraw = 0;
- BOOL fMouseDownL = 0, fMouseOverL = 0;
- BOOL fMouseDownR = 0, fMouseOverR = 0;
- COLORREF crCheck1 = GetSBForeColor();
- COLORREF crCheck2 = GetSBBackColor();
- COLORREF crInverse1 = WADlg_getColor(WADLG_SCROLLBAR_INV_FGCOLOR);
- COLORREF crInverse2 = WADlg_getColor(WADLG_SCROLLBAR_INV_BGCOLOR);
- UINT uDEFlat = sb->fFlatScrollbar ? BF_FLAT : 0;
- //drawing flags to modify the appearance of the scrollbar buttons
- UINT uLeftButFlags = DFCS_SCROLLLEFT;
- UINT uRightButFlags = DFCS_SCROLLRIGHT;
- if (scrollwidth <= 0)
- return 0;
- si = &sb->scrollInfo;
- if (hwnd != hwndCurCoolSB)
- uDrawFlags = HTSCROLL_NONE;
- //
- // work out the thumb size and position
- //
- CalcThumbSize(sb, rect, &thumbwidth, &thumbpos);
- if (sb->fScrollFlags & ESB_DISABLE_LEFT) uLeftButFlags |= DFCS_INACTIVE;
- if (sb->fScrollFlags & ESB_DISABLE_RIGHT) uRightButFlags |= DFCS_INACTIVE;
- //if we need to grey the arrows because there is no data to scroll
- if (!IsScrollInfoActive(si) && !(sb->fScrollFlags & CSBS_THUMBALWAYS))
- {
- uLeftButFlags |= DFCS_INACTIVE;
- uRightButFlags |= DFCS_INACTIVE;
- }
- if (hwnd == hwndCurCoolSB)
- {
- fMouseDownL = (uDrawFlags == HTSCROLL_LEFT);
- fMouseDownR = (uDrawFlags == HTSCROLL_RIGHT);
- }
- //
- // Draw the scrollbar now
- //
- if (scrollwidth > butwidth*2)
- {
- //LEFT ARROW
- SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
- else
- DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
- RotateRect0(sb, &ctrl);
- //MIDDLE PORTION
- //if we can fit the thumbbar in, then draw it
- if (thumbwidth > 0 && thumbwidth <= workingwidth
- && IsScrollInfoActive(si) && ((sb->fScrollFlags & ESB_DISABLE_BOTH) != ESB_DISABLE_BOTH))
- {
- //Draw the scrollbar margin above the thumb
- SetRect(&sbm, rect->left + butwidth, rect->top, thumbpos, rect->bottom);
- RotateRect0(sb, &sbm);
- if (fCustomDraw)
- {
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGELEFT, uDrawFlags == HTSCROLL_PAGELEFT, FALSE, FALSE);
- }
- else
- {
- if (uDrawFlags == HTSCROLL_PAGELEFT)
- DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
- else
- DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
- }
- RotateRect0(sb, &sbm);
- //Draw the margin below the thumb
- sbm.left = thumbpos + thumbwidth;
- sbm.right = rect->right - butwidth;
- RotateRect0(sb, &sbm);
- if (fCustomDraw)
- {
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &sbm, SB_PAGERIGHT, uDrawFlags == HTSCROLL_PAGERIGHT, 0, 0);
- }
- else
- {
- if (uDrawFlags == HTSCROLL_PAGERIGHT)
- DrawCheckedRect(hdc, &sbm, crInverse1, crInverse2);
- else
- DrawCheckedRect(hdc, &sbm, crCheck1, crCheck2);
- }
- RotateRect0(sb, &sbm);
- //Draw the THUMB finally
- SetRect(&thumb, thumbpos, rect->top, thumbpos + thumbwidth, rect->bottom);
- RotateRect0(sb, &thumb);
- if (fCustomDraw)
- {
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &thumb, SB_THUMBTRACK, uDrawFlags == HTSCROLL_THUMB, uHitTestPortion == HTSCROLL_THUMB, FALSE);
- }
- else
- {
- int track = 0;
- if (uCurrentScrollbar == (UINT)sb->nBarType) track = GetScrollWndFromHwnd(hwnd)->fThumbTracking;
- DrawBlankButton(hdc, &thumb, uDEFlat, track, sb->nBarType == SB_VERT);
- }
- RotateRect0(sb, &thumb);
- }
- //otherwise, just leave that whole area blank
- else
- {
- OffsetRect(&ctrl, butwidth, 0);
- ctrl.right = rect->right - butwidth;
- //if we always show the thumb covering the whole scrollbar,
- //then draw it that way
- if (!IsScrollInfoActive(si) && (sb->fScrollFlags & CSBS_THUMBALWAYS)
- && ctrl.right - ctrl.left > sb->nMinThumbSize)
- {
- //leave a 1-pixel gap between the thumb + right button
- ctrl.right --;
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_THUMBTRACK, fMouseDownL, FALSE, FALSE);
- else
- {
- DrawBlankButton(hdc, &ctrl, uDEFlat, 0, sb->nBarType == SB_VERT);
- }
- RotateRect0(sb, &ctrl);
- //draw the single-line gap
- ctrl.left = ctrl.right;
- ctrl.right += 1;
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
- else
- PaintRect(hdc, &ctrl, GetSysColor(COLOR_SCROLLBAR));
- RotateRect0(sb, &ctrl);
- }
- //otherwise, paint a blank if the thumb doesn't fit in
- else
- {
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
- else
- DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
- RotateRect0(sb, &ctrl);
- }
- }
- //RIGHT ARROW
- SetRect(&ctrl, rect->right - butwidth, rect->top, rect->right, rect->bottom);
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE);
- else
- DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR);
- RotateRect0(sb, &ctrl);
- }
- //not enough room for the scrollbar, so just draw the buttons (scaled in size to fit)
- else
- {
- butwidth = scrollwidth / 2;
- //LEFT ARROW
- SetRect(&ctrl, rect->left, rect->top, rect->left + butwidth, rect->bottom);
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINELEFT, fMouseDownL, fMouseOverL, uLeftButFlags & DFCS_INACTIVE);
- else
- DrawScrollArrow(sb, hdc, &ctrl, uLeftButFlags, fMouseDownL, fMouseOverL);
- RotateRect0(sb, &ctrl);
- //RIGHT ARROW
- OffsetRect(&ctrl, scrollwidth - butwidth, 0);
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_LINERIGHT, fMouseDownR, fMouseOverR, uRightButFlags & DFCS_INACTIVE);
- else
- DrawScrollArrow(sb, hdc, &ctrl, uRightButFlags, fMouseDownR, fMouseOverR);
- RotateRect0(sb, &ctrl);
- //if there is a gap between the buttons, fill it with a solid color
- //if(butwidth & 0x0001)
- if (ctrl.left != rect->left + butwidth)
- {
- ctrl.left --;
- ctrl.right -= butwidth;
- RotateRect0(sb, &ctrl);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sb->nBarType, &ctrl, SB_PAGERIGHT, 0, 0, 0);
- else
- DrawCheckedRect(hdc, &ctrl, crCheck1, crCheck2);
- RotateRect0(sb, &ctrl);
- }
- }
- return fCustomDraw;
- }
- //
- // Draw a vertical scrollbar using the horizontal draw routine, but
- // with the coordinates adjusted accordingly
- //
- static LRESULT NCDrawVScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
- {
- LRESULT ret;
- RECT rc;
- rc = *rect;
- RotateRect(&rc);
- ret = NCDrawHScrollbar(sb, hwnd, hdc, &rc, uDrawFlags);
- RotateRect(&rc);
- return ret;
- }
- //
- // Generic wrapper function for the scrollbar drawing
- //
- static LRESULT NCDrawScrollbar(SCROLLBAR *sb, HWND hwnd, HDC hdc, const RECT *rect, UINT uDrawFlags)
- {
- if (sb->nBarType == SB_HORZ)
- return NCDrawHScrollbar(sb, hwnd, hdc, rect, uDrawFlags);
- else
- return NCDrawVScrollbar(sb, hwnd, hdc, rect, uDrawFlags);
- }
- //
- // Define these two for proper processing of NCPAINT
- // NOT needed if we don't bother to mask the scrollbars we draw
- // to prevent the old window procedure from accidently drawing over them
- //
- HDC CoolSB_GetDC(HWND hwnd, WPARAM wParam)
- {
- // I just can't figure out GetDCEx, so I'll just use this:
- return GetWindowDC(hwnd);
- }
- static LRESULT NCPaint(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- SCROLLBAR *sb;
- HDC hdc;
- HRGN hrgn;
- RECT winrect, rect;
- HRGN clip;
- BOOL fUpdateAll = ((LONG)wParam == 1);
- BOOL fCustomDraw = FALSE;
- LRESULT ret;
- DWORD dwStyle;
- GetWindowRect(hwnd, &winrect);
- //if entire region needs painting, then make a region to cover the entire window
- hrgn = (HRGN)wParam;
- //hdc = GetWindowDC(hwnd);
- hdc = CoolSB_GetDC(hwnd, wParam);
- //
- // Only draw the horizontal scrollbar if the window is tall enough
- //
- sb = &sw->sbarHorz;
- if (sb->fScrollVisible)
- {
- //get the screen coordinates of the whole horizontal scrollbar area
- GetHScrollRect(sw, hwnd, &rect);
- //make the coordinates relative to the window for drawing
- OffsetRect(&rect, -winrect.left, -winrect.top);
- if (uCurrentScrollbar == SB_HORZ)
- fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
- else
- fCustomDraw |= NCDrawHScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
- }
- //
- // Only draw the vertical scrollbar if the window is wide enough to accomodate it
- //
- sb = &sw->sbarVert;
- if (sb->fScrollVisible)
- {
- //get the screen cooridinates of the whole horizontal scrollbar area
- GetVScrollRect(sw, hwnd, &rect);
- //make the coordinates relative to the window for drawing
- OffsetRect(&rect, -winrect.left, -winrect.top);
- if (uCurrentScrollbar == SB_VERT)
- fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
- else
- fCustomDraw |= NCDrawVScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NONE);
- }
- //Call the default window procedure for WM_NCPAINT, with the
- //new window region. ** region must be in SCREEN coordinates **
- dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
- // If the window has WS_(H-V)SCROLL bits set, we should reset them
- // to avoid windows taking the scrollbars into account.
- // We temporarily set a flag preventing the subsecuent
- // WM_STYLECHANGING/WM_STYLECHANGED to be forwarded to
- // the original window procedure
- if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
- {
- sw->bPreventStyleChange = TRUE;
- SetWindowLongPtr(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL));
- }
- ret = (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_NCPAINT, (WPARAM)hrgn, lParam);
- if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
- {
- SetWindowLong(hwnd, GWL_STYLE, dwStyle);
- sw->bPreventStyleChange = FALSE;
- }
- // DRAW THE DEAD AREA
- // only do this if the horizontal and vertical bars are visible
- if (sw->sbarHorz.fScrollVisible && sw->sbarVert.fScrollVisible)
- {
- GetWindowRect(hwnd, &rect);
- OffsetRect(&rect, -winrect.left, -winrect.top);
- rect.bottom -= sw->cyBottomEdge;
- rect.top = rect.bottom - GetScrollMetric(&sw->sbarHorz, SM_CYHORZSB);
- if (sw->fLeftScrollbar)
- {
- rect.left += sw->cxLeftEdge;
- rect.right = rect.left + GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
- }
- else
- {
- rect.right -= sw->cxRightEdge;
- rect.left = rect.right - GetScrollMetric(&sw->sbarVert, SM_CXVERTSB);
- }
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, SB_BOTH, &rect, 32, 0, 0, 0);
- else
- {
- //calculate the position of THIS window's dead area
- //with the position of the PARENT window's client rectangle.
- //if THIS window has been positioned such that its bottom-right
- //corner sits in the parent's bottom-right corner, then we should
- //show the sizing-grip.
- //Otherwise, assume this window is not in the right place, and
- //just draw a blank rectangle
- RECT parent;
- RECT rect2;
- HWND hwndParent = GetParent(hwnd);
- GetClientRect(hwndParent, &parent);
- MapWindowPoints(hwndParent, 0, (POINT *)&parent, 2);
- CopyRect(&rect2, &rect);
- OffsetRect(&rect2, winrect.left, winrect.top);
- if (!sw->fLeftScrollbar && parent.right == rect2.right + sw->cxRightEdge && parent.bottom == rect2.bottom + sw->cyBottomEdge
- || sw->fLeftScrollbar && parent.left == rect2.left - sw->cxLeftEdge && parent.bottom == rect2.bottom + sw->cyBottomEdge)
- drawFrameControl(hdc, &rect, DFC_SCROLL, sw->fLeftScrollbar ? DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP);
- else
- PaintRect(hdc, &rect, WADlg_getColor(WADLG_SCROLLBAR_DEADAREA_COLOR));
- }
- }
- UNREFERENCED_PARAMETER(clip);
- ReleaseDC(hwnd, hdc);
- return ret;
- }
- //
- // Need to detect if we have clicked in the scrollbar region or not
- //
- static LRESULT NCHitTest(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- RECT hrect;
- RECT vrect;
- POINT pt;
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- //work out exactly where the Horizontal and Vertical scrollbars are
- GetHScrollRect(sw, hwnd, &hrect);
- GetVScrollRect(sw, hwnd, &vrect);
- //Clicked in the horizontal scrollbar area
- if (sw->sbarHorz.fScrollVisible && PtInRect(&hrect, pt))
- {
- return HTHSCROLL;
- }
- //Clicked in the vertical scrollbar area
- else if (sw->sbarVert.fScrollVisible && PtInRect(&vrect, pt))
- {
- return HTVSCROLL;
- }
- //clicked somewhere else
- else
- {
- return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_NCHITTEST, wParam, lParam);
- }
- }
- //
- // Return a HT* value indicating what part of the scrollbar was clicked
- // Rectangle is not adjusted
- //
- static UINT GetHorzPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
- {
- RECT rc = *rect;
- if (y < rc.top || y >= rc.bottom) return HTSCROLL_NONE;
- //Now we have the rectangle for the scrollbar itself, so work out
- //what part we clicked on.
- return GetHorzScrollPortion(sb, hwnd, &rc, x, y);
- }
- //
- // Just call the horizontal version, with adjusted coordinates
- //
- static UINT GetVertPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
- {
- UINT ret;
- RotateRect(rect);
- ret = GetHorzPortion(sb, hwnd, rect, y, x);
- RotateRect(rect);
- return ret;
- }
- //
- // Wrapper function for GetHorzPortion and GetVertPortion
- //
- static UINT GetPortion(SCROLLBAR *sb, HWND hwnd, RECT *rect, int x, int y)
- {
- if (sb->nBarType == SB_HORZ)
- return GetHorzPortion(sb, hwnd, rect, x, y);
- else if (sb->nBarType == SB_VERT)
- return GetVertPortion(sb, hwnd, rect, x, y);
- else
- return HTSCROLL_NONE;
- }
- //
- // Input: rectangle of the total scrollbar area
- // Output: adjusted to take the inserted buttons into account
- //
- static void GetRealHorzScrollRect(SCROLLBAR *sb, RECT *rect)
- {
- if (sb->fButVisibleBefore) rect->left += sb->nButSizeBefore;
- if (sb->fButVisibleAfter) rect->right -= sb->nButSizeAfter;
- }
- //
- // Input: rectangle of the total scrollbar area
- // Output: adjusted to take the inserted buttons into account
- //
- static void GetRealVertScrollRect(SCROLLBAR *sb, RECT *rect)
- {
- if (sb->fButVisibleBefore) rect->top += sb->nButSizeBefore;
- if (sb->fButVisibleAfter) rect->bottom -= sb->nButSizeAfter;
- }
- //
- // Decide which type of scrollbar we have before calling
- // the real function to do the job
- //
- static void GetRealScrollRect(SCROLLBAR *sb, RECT *rect)
- {
- if (sb->nBarType == SB_HORZ)
- {
- GetRealHorzScrollRect(sb, rect);
- }
- else if (sb->nBarType == SB_VERT)
- {
- GetRealVertScrollRect(sb, rect);
- }
- }
- //
- // Left button click in the non-client area
- //
- static LRESULT NCLButtonDown(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- RECT rect, winrect;
- HDC hdc;
- SCROLLBAR *sb;
- POINT pt;
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- hwndCurCoolSB = hwnd;
- //
- // HORIZONTAL SCROLLBAR PROCESSING
- //
- if (wParam == HTHSCROLL)
- {
- uScrollTimerMsg = WM_HSCROLL;
- uCurrentScrollbar = SB_HORZ;
- sb = &sw->sbarHorz;
- //get the total area of the normal Horz scrollbar area
- GetHScrollRect(sw, hwnd, &rect);
- uCurrentScrollPortion = GetHorzPortion(sb, hwnd, &rect, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- }
- //
- // VERTICAL SCROLLBAR PROCESSING
- //
- else if (wParam == HTVSCROLL)
- {
- uScrollTimerMsg = WM_VSCROLL;
- uCurrentScrollbar = SB_VERT;
- sb = &sw->sbarVert;
- //get the total area of the normal Horz scrollbar area
- GetVScrollRect(sw, hwnd, &rect);
- uCurrentScrollPortion = GetVertPortion(sb, hwnd, &rect, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
- }
- //
- // NORMAL PROCESSING
- //
- else
- {
- uCurrentScrollPortion = HTSCROLL_NONE;
- return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
- }
- //
- // we can now share the same code for vertical
- // and horizontal scrollbars
- //
- switch (uCurrentScrollPortion)
- {
- //inserted buttons to the left/right
- case HTSCROLL_THUMB:
- //if the scrollbar is disabled, then do no further processing
- if (!IsScrollbarActive(sb))
- return 0;
- GetRealScrollRect(sb, &rect);
- RotateRect0(sb, &rect);
- CalcThumbSize(sb, &rect, &nThumbSize, &nThumbPos);
- RotateRect0(sb, &rect);
- //remember the bounding rectangle of the scrollbar work area
- rcThumbBounds = rect;
- sw->fThumbTracking = TRUE;
- sb->scrollInfo.nTrackPos = sb->scrollInfo.nPos;
- if (wParam == HTVSCROLL)
- nThumbMouseOffset = pt.y - nThumbPos;
- else
- nThumbMouseOffset = pt.x - nThumbPos;
- nLastPos = -sb->scrollInfo.nPos;
- nThumbPos0 = nThumbPos;
- //if(sb->fFlatScrollbar)
- //{
- GetWindowRect(hwnd, &winrect);
- OffsetRect(&rect, -winrect.left, -winrect.top);
- hdc = GetWindowDC(hwnd);
- NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_THUMB);
- ReleaseDC(hwnd, hdc);
- //}
- break;
- //Any part of the scrollbar
- case HTSCROLL_LEFT:
- if (sb->fScrollFlags & ESB_DISABLE_LEFT) return 0;
- else goto target1;
- case HTSCROLL_RIGHT:
- if (sb->fScrollFlags & ESB_DISABLE_RIGHT) return 0;
- else goto target1;
- goto target1;
- case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
- target1:
- //if the scrollbar is disabled, then do no further processing
- if (!IsScrollbarActive(sb))
- break;
- //ajust the horizontal rectangle to NOT include
- //any inserted buttons
- GetRealScrollRect(sb, &rect);
- SendScrollMessage(hwnd, uScrollTimerMsg, uCurrentScrollPortion, 0);
- // Check what area the mouse is now over :
- // If the scroll thumb has moved under the mouse in response to
- // a call to SetScrollPos etc, then we don't hilight the scrollbar margin
- if (uCurrentScrollbar == SB_HORZ)
- uScrollTimerPortion = GetHorzScrollPortion(sb, hwnd, &rect, pt.x, pt.y);
- else
- uScrollTimerPortion = GetVertScrollPortion(sb, hwnd, &rect, pt.x, pt.y);
- GetWindowRect(hwnd, &winrect);
- OffsetRect(&rect, -winrect.left, -winrect.top);
- hdc = GetWindowDC(hwnd);
- //if we aren't hot-tracking, then don't highlight
- //the scrollbar thumb unless we click on it
- if (uScrollTimerPortion == HTSCROLL_THUMB)
- uScrollTimerPortion = HTSCROLL_NONE;
- NCDrawScrollbar(sb, hwnd, hdc, &rect, uScrollTimerPortion);
- ReleaseDC(hwnd, hdc);
- //Post the scroll message!!!!
- uScrollTimerPortion = uCurrentScrollPortion;
- //set a timer going on the first click.
- //if this one expires, then we can start off a more regular timer
- //to generate the auto-scroll behaviour
- uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID1, COOLSB_TIMERINTERVAL1, 0);
- sw->update();
- break;
- default:
- return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_NCLBUTTONDOWN, wParam, lParam);
- //return 0;
- }
- SetCapture(hwnd);
- return 0;
- }
- //
- // Left button released
- //
- static LRESULT LButtonUp(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- RECT rect;
- POINT pt;
- RECT winrect;
- //current scrollportion is the button that we clicked down on
- if (uCurrentScrollPortion != HTSCROLL_NONE)
- {
- SCROLLBAR *sb = &sw->sbarHorz;
- lParam = GetMessagePos();
- ReleaseCapture();
- GetWindowRect(hwnd, &winrect);
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- //emulate the mouse input on a scrollbar here...
- if (uCurrentScrollbar == SB_HORZ)
- {
- //get the total area of the normal Horz scrollbar area
- sb = &sw->sbarHorz;
- GetHScrollRect(sw, hwnd, &rect);
- }
- else if (uCurrentScrollbar == SB_VERT)
- {
- //get the total area of the normal Horz scrollbar area
- sb = &sw->sbarVert;
- GetVScrollRect(sw, hwnd, &rect);
- }
- //we need to do different things depending on if the
- //user is activating the scrollbar itself, or one of
- //the inserted buttons
- switch (uCurrentScrollPortion)
- {
- //The scrollbar is active
- case HTSCROLL_LEFT: case HTSCROLL_RIGHT:
- case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
- case HTSCROLL_NONE:
- KillTimer(hwnd, uScrollTimerId);
- case HTSCROLL_THUMB:
- sw->update();
- //In case we were thumb tracking, make sure we stop NOW
- if (sw->fThumbTracking == TRUE)
- {
- SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBPOSITION, nLastPos);
- sw->fThumbTracking = FALSE;
- }
- //send the SB_ENDSCROLL message now that scrolling has finished
- SendScrollMessage(hwnd, uScrollTimerMsg, SB_ENDSCROLL, 0);
- //adjust the total scroll area to become where the scrollbar
- //really is (take into account the inserted buttons)
- GetRealScrollRect(sb, &rect);
- OffsetRect(&rect, -winrect.left, -winrect.top);
- HDC hdc = GetWindowDC(hwnd);
- //draw whichever scrollbar sb is
- NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL);
- ReleaseDC(hwnd, hdc);
- break;
- }
- //reset our state to default
- uCurrentScrollPortion = HTSCROLL_NONE;
- uScrollTimerPortion = HTSCROLL_NONE;
- uScrollTimerId = 0;
- uScrollTimerMsg = 0;
- uCurrentScrollbar = COOLSB_NONE;
- return 0;
- }
- else
- {
- /*
- // Can't remember why I did this!
- if(GetCapture() == hwnd)
- {
- ReleaseCapture();
- }*/
- }
- //sw->update();
- return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_LBUTTONUP, wParam, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_LBUTTONUP, wParam, lParam);
- }
- //
- // This function is called whenever the mouse is moved and
- // we are dragging the scrollbar thumb about.
- //
- static LRESULT ThumbTrackHorz(SCROLLBAR *sbar, HWND hwnd, int x, int y)
- {
- POINT pt;
- RECT rc, winrect, rc2;
- COLORREF crCheck1 = GetSBForeColor();
- COLORREF crCheck2 = GetSBBackColor();
- HDC hdc;
- int thumbpos = nThumbPos;
- int pos;
- int siMaxMin = 0;
- UINT flatflag = sbar->fFlatScrollbar ? BF_FLAT : 0;
- BOOL fCustomDraw = FALSE;
- SCROLLINFO *si;
- si = &sbar->scrollInfo;
- pt.x = x;
- pt.y = y;
- //draw the thumb at whatever position
- rc = rcThumbBounds;
- SetRect(&rc2, rc.left - THUMBTRACK_SNAPDIST*2, rc.top - THUMBTRACK_SNAPDIST,
- rc.right + THUMBTRACK_SNAPDIST*2, rc.bottom + THUMBTRACK_SNAPDIST);
- rc.left += GetScrollMetric(sbar, SM_CXHORZSB);
- rc.right -= GetScrollMetric(sbar, SM_CXHORZSB);
- //if the mouse is not in a suitable distance of the scrollbar,
- //then "snap" the thumb back to its initial position
- #ifdef SNAP_THUMB_BACK
- if (!PtInRect(&rc2, pt))
- {
- thumbpos = nThumbPos0;
- }
- //otherwise, move the thumb to where the mouse is
- else
- #endif //SNAP_THUMB_BACK
- {
- //keep the thumb within the scrollbar limits
- thumbpos = pt.x - nThumbMouseOffset;
- if (thumbpos < rc.left) thumbpos = rc.left;
- if (thumbpos > rc.right - nThumbSize) thumbpos = rc.right - nThumbSize;
- }
- GetWindowRect(hwnd, &winrect);
- if (sbar->nBarType == SB_VERT)
- RotateRect(&winrect);
- hdc = GetWindowDC(hwnd);
- OffsetRect(&rc, -winrect.left, -winrect.top);
- thumbpos -= winrect.left;
- //draw the margin before the thumb
- SetRect(&rc2, rc.left, rc.top, thumbpos, rc.bottom);
- RotateRect0(sbar, &rc2);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGELEFT, 0, 0, 0);
- else
- DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2);
- RotateRect0(sbar, &rc2);
- //draw the margin after the thumb
- SetRect(&rc2, thumbpos + nThumbSize, rc.top, rc.right, rc.bottom);
- RotateRect0(sbar, &rc2);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_PAGERIGHT, 0, 0, 0);
- else
- DrawCheckedRect(hdc, &rc2, crCheck1, crCheck2);
- RotateRect0(sbar, &rc2);
- //finally draw the thumb itelf. This is how it looks on win2000, anyway
- SetRect(&rc2, thumbpos, rc.top, thumbpos + nThumbSize, rc.bottom);
- RotateRect0(sbar, &rc2);
- if (fCustomDraw)
- PostCustomDrawNotify(hwnd, hdc, sbar->nBarType, &rc2, SB_THUMBTRACK, TRUE, TRUE, FALSE);
- else
- {
- DrawBlankButton(hdc, &rc2, flatflag, 1, sbar->nBarType == SB_VERT);
- }
- RotateRect0(sbar, &rc2);
- ReleaseDC(hwnd, hdc);
- //post a SB_TRACKPOS message!!!
- siMaxMin = si->nMax - si->nMin;
- if (siMaxMin > 0)
- pos = MulDiv(thumbpos - rc.left, siMaxMin - si->nPage + 1, rc.right - rc.left - nThumbSize);
- else
- pos = thumbpos - rc.left;
- if (pos != nLastPos)
- {
- if (sbar->flags & SCROLLBAR_LISTVIEW)
- {
- // only for listviews
- if (sbar->nBarType == SB_HORZ)
- {
- SCROLLINFO info;
- info.cbSize = sizeof(SCROLLINFO);
- info.fMask = SIF_TRACKPOS;
- if (GetScrollInfo(hwnd, SB_HORZ, &info))
- {
- int nPos = info.nTrackPos;
- SendMessage(hwnd, LVM_SCROLL, pos - nPos, 0);
- SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
- }
- }
- else if (sbar->nBarType == SB_VERT)
- {
- SCROLLINFO info;
- info.cbSize = sizeof(SCROLLINFO);
- info.fMask = SIF_TRACKPOS;
- if (GetScrollInfo(hwnd, SB_VERT, &info))
- {
- int nPos = info.nTrackPos;
- SendMessage(hwnd, LVM_SCROLL, 0, (pos - nPos)*14); //BIG FUCKO: get the text height size
- SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
- }
- }
- }
- else
- {
- si->nTrackPos = pos;
- SCROLLINFO info;
- info.cbSize = sizeof(SCROLLINFO);
- info.fMask = SIF_TRACKPOS;
- info.nTrackPos = pos;
-
- SetScrollInfo(hwnd, sbar->nBarType, &info, FALSE);
- SendScrollMessage(hwnd, uScrollTimerMsg, SB_THUMBTRACK, pos);
- }
- }
- nLastPos = pos;
- return 0;
- }
- //
- // remember to rotate the thumb bounds rectangle!!
- //
- static LRESULT ThumbTrackVert(SCROLLBAR *sb, HWND hwnd, int x, int y)
- {
- //sw->swapcoords = TRUE;
- RotateRect(&rcThumbBounds);
- ThumbTrackHorz(sb, hwnd, y, x);
- RotateRect(&rcThumbBounds);
- //sw->swapcoords = FALSE;
- return 0;
- }
- //
- // Called when we have set the capture from the NCLButtonDown(...)
- //
- static LRESULT MouseMove(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- RECT rect;
- POINT pt;
- RECT winrect;
- if (sw->fThumbTracking == TRUE)
- {
- int x, y;
- lParam = GetMessagePos();
- x = GET_X_LPARAM(lParam);
- y = GET_Y_LPARAM(lParam);
- if (uCurrentScrollbar == SB_HORZ)
- return ThumbTrackHorz(&sw->sbarHorz, hwnd, x, y);
- else if (uCurrentScrollbar == SB_VERT)
- return ThumbTrackVert(&sw->sbarVert, hwnd, x, y);
- }
- if (uCurrentScrollPortion == HTSCROLL_NONE)
- {
- return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
- }
- else
- {
- LPARAM nlParam;
- SCROLLBAR *sb = &sw->sbarHorz;
- nlParam = GetMessagePos();
- GetWindowRect(hwnd, &winrect);
- pt.x = GET_X_LPARAM(nlParam);
- pt.y = GET_Y_LPARAM(nlParam);
- //emulate the mouse input on a scrollbar here...
- if (uCurrentScrollbar == SB_HORZ)
- {
- sb = &sw->sbarHorz;
- }
- else if (uCurrentScrollbar == SB_VERT)
- {
- sb = &sw->sbarVert;
- }
- //get the total area of the normal scrollbar area
- GetScrollRect(sw, sb->nBarType, hwnd, &rect);
- //see if we clicked in the inserted buttons / normal scrollbar
- //thisportion = GetPortion(sb, hwnd, &rect, LOWORD(lParam), HIWORD(lParam));
- UINT thisportion = GetPortion(sb, hwnd, &rect, pt.x, pt.y);
- //we need to do different things depending on if the
- //user is activating the scrollbar itself, or one of
- //the inserted buttons
- static UINT lastportion = 0;
- switch (uCurrentScrollPortion)
- {
- //The scrollbar is active
- case HTSCROLL_LEFT: case HTSCROLL_RIGHT: case HTSCROLL_THUMB:
- case HTSCROLL_PAGELEFT: case HTSCROLL_PAGERIGHT:
- case HTSCROLL_NONE:
- //adjust the total scroll area to become where the scrollbar
- //really is (take into account the inserted buttons)
- GetRealScrollRect(sb, &rect);
- OffsetRect(&rect, -winrect.left, -winrect.top);
- HDC hdc = GetWindowDC(hwnd);
- if (thisportion != uCurrentScrollPortion)
- {
- uScrollTimerPortion = HTSCROLL_NONE;
- if (lastportion != thisportion)
- NCDrawScrollbar(sb, hwnd, hdc, &rect, HTSCROLL_NORMAL);
- }
- //otherwise, draw the button in its depressed / clicked state
- else
- {
- uScrollTimerPortion = uCurrentScrollPortion;
- if (lastportion != thisportion)
- NCDrawScrollbar(sb, hwnd, hdc, &rect, thisportion);
- }
- ReleaseDC(hwnd, hdc);
- break;
- }
- lastportion = thisportion;
- //must return zero here, because we might get cursor anomilies
- //CallWindowProc(sw->oldproc, hwnd, WM_MOUSEMOVE, wParam, lParam);
- return 0;
- }
- }
- //
- // We must allocate from in the non-client area for our scrollbars
- // Call the default window procedure first, to get the borders (if any)
- // allocated some space, then allocate the space for the scrollbars
- // if they fit
- //
- static LRESULT NCCalcSize(ScrollWnd *sw, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- NCCALCSIZE_PARAMS *nccsp;
- RECT *rect;
- RECT oldrect;
- //BOOL fCalcValidRects = (wParam == TRUE);
- SCROLLBAR *sb;
- LRESULT ret;
- DWORD dwStyle;
- //Regardless of the value of fCalcValidRects, the first rectangle
- //in the array specified by the rgrc structure member of the
- //NCCALCSIZE_PARAMS structure contains the coordinates of the window,
- //so we can use the exact same code to modify this rectangle, when
- //wParam is TRUE and when it is FALSE.
- nccsp = (NCCALCSIZE_PARAMS *)lParam;
- rect = &nccsp->rgrc[0];
- oldrect = *rect;
- dwStyle = GetWindowLong(hwnd, GWL_STYLE);
- // TURN OFF SCROLL-STYLES.
- if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
- {
- sw->bPreventStyleChange = TRUE;
- SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL));
- }
- //call the default procedure to get the borders allocated
- ret = (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCCALCSIZE, wParam, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_NCCALCSIZE, wParam, lParam);
- // RESTORE PREVIOUS STYLES (if present at all)
- if (dwStyle & (WS_VSCROLL | WS_HSCROLL))
- {
- SetWindowLong(hwnd, GWL_STYLE, dwStyle);
- sw->bPreventStyleChange = FALSE;
- }
- // calculate what the size of each window border is,
- sw->cxLeftEdge = rect->left - oldrect.left;
- sw->cxRightEdge = oldrect.right - rect->right;
- sw->cyTopEdge = rect->top - oldrect.top;
- sw->cyBottomEdge = oldrect.bottom - rect->bottom;
- sb = &sw->sbarHorz;
- //if there is room, allocate some space for the horizontal scrollbar
- //NOTE: Change the ">" to a ">=" to make the horz bar totally fill the
- //window before disappearing
- if ((sb->fScrollFlags & CSBS_VISIBLE) &&
- #ifdef COOLSB_FILLWINDOW
- rect->bottom - rect->top >= GetScrollMetric(sb, SM_CYHORZSB))
- #else
- rect->bottom - rect->top > GetScrollMetric(sb, SM_CYHORZSB))
- #endif
- {
- rect->bottom -= GetScrollMetric(sb, SM_CYHORZSB);
- sb->fScrollVisible = TRUE;
- }
- else
- sb->fScrollVisible = FALSE;
- sb = &sw->sbarVert;
- //if there is room, allocate some space for the vertical scrollbar
- if ((sb->fScrollFlags & CSBS_VISIBLE) &&
- rect->right - rect->left >= GetScrollMetric(sb, SM_CXVERTSB))
- {
- if (sw->fLeftScrollbar)
- rect->left += GetScrollMetric(sb, SM_CXVERTSB);
- else
- rect->right -= GetScrollMetric(sb, SM_CXVERTSB);
- sb->fScrollVisible = TRUE;
- }
- else
- sb->fScrollVisible = FALSE;
- //don't return a value unless we actually modify the other rectangles
- //in the NCCALCSIZE_PARAMS structure. In this case, we return 0
- //no matter what the value of fCalcValidRects is
- return ret;//FALSE;
- }
- //
- // used for hot-tracking over the scroll buttons
- //
- static LRESULT NCMouseMove(ScrollWnd *sw, HWND hwnd, WPARAM wHitTest, LPARAM lParam)
- {
- //install a timer for the mouse-over events, if the mouse moves
- //over one of the scrollbars
- return (sw->fWndUnicode) ? CallWindowProcW(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam) :
- CallWindowProcA(sw->oldproc, hwnd, WM_NCMOUSEMOVE, wHitTest, lParam);
- }
- //
- // Timer routine to generate scrollbar messages
- //
- static LRESULT CoolSB_Timer(ScrollWnd *swnd, HWND hwnd, WPARAM wTimerId, LPARAM lParam)
- {
- //let all timer messages go past if we don't have a timer installed ourselves
- if (uScrollTimerId == 0 && uMouseOverId == 0)
- {
- return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam);
- }
- //if the first timer goes off, then we can start a more
- //regular timer interval to auto-generate scroll messages
- //this gives a slight pause between first pressing the scroll arrow, and the
- //actual scroll starting
- if (wTimerId == COOLSB_TIMERID1)
- {
- KillTimer(hwnd, uScrollTimerId);
- uScrollTimerId = SetTimer(hwnd, COOLSB_TIMERID2, COOLSB_TIMERINTERVAL2, 0);
- return 0;
- }
- //send the scrollbar message repeatedly
- else if (wTimerId == COOLSB_TIMERID2)
- {
- //need to process a spoof WM_MOUSEMOVE, so that
- //we know where the mouse is each time the scroll timer goes off.
- //This is so we can stop sending scroll messages if the thumb moves
- //under the mouse.
- POINT pt;
- GetCursorPos(&pt);
- ScreenToClient(hwnd, &pt);
- MouseMove(swnd, hwnd, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
- if (uScrollTimerPortion != HTSCROLL_NONE)
- SendScrollMessage(hwnd, uScrollTimerMsg, uScrollTimerPortion, 0);
- swnd->update();
- return 0;
- }
- else
- {
- return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, WM_TIMER, wTimerId, lParam);
- }
- }
- //
- // We must intercept any calls to SetWindowLong, to check if
- // left-scrollbars are taking effect or not
- //
- static LRESULT CoolSB_StyleChange(ScrollWnd *swnd, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- STYLESTRUCT *ss = (STYLESTRUCT *)lParam;
- if (wParam == GWL_EXSTYLE)
- {
- if (ss->styleNew & WS_EX_LEFTSCROLLBAR)
- swnd->fLeftScrollbar = TRUE;
- else
- swnd->fLeftScrollbar = FALSE;
- }
- return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, msg, wParam, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, msg, wParam, lParam);
- }
- static UINT curTool = -1;
- static LRESULT CoolSB_Notify(ScrollWnd *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_NOTIFY, wParam, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, WM_NOTIFY, wParam, lParam);
- }
- static LRESULT SendToolTipMessage0(HWND hwndTT, UINT message, WPARAM wParam, LPARAM lParam)
- {
- return SendMessage(hwndTT, message, wParam, lParam);
- }
- #ifdef COOLSB_TOOLTIPS
- #define SendToolTipMessage SendToolTipMessage0
- #else
- #define SendToolTipMessage 1 ? (void)0 : SendToolTipMessage0
- #endif
- //
- // We must intercept any calls to SetWindowLong, to make sure that
- // the user does not set the WS_VSCROLL or WS_HSCROLL styles
- //
- static LRESULT CoolSB_SetCursor(ScrollWnd *swnd, HWND hwnd, WPARAM wParam, LPARAM lParam)
- {
- return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, WM_SETCURSOR, wParam, lParam);
- }
- //
- // CoolScrollbar subclass procedure.
- // Handle all messages needed to mimick normal windows scrollbars
- //
- LRESULT CALLBACK CoolSBWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- WNDPROC oldproc;
- ScrollWnd *swnd = GetScrollWndFromHwnd(hwnd);
- if (!swnd || !swnd->oldproc)
- {
- return (IsWindowUnicode(hwnd)) ? DefWindowProcW(hwnd, message, wParam, lParam) :
- DefWindowProcA(hwnd, message, wParam, lParam);
- }
- switch (message)
- {
- case WM_NCDESTROY:
- //this should NEVER be called, because the user
- //should have called Uninitialize() themselves.
- //However, if the user tries to call Uninitialize()..
- //after this window is destroyed, this window's entry in the lookup
- //table will not be there, and the call will fail
- oldproc = swnd->oldproc;
- delete(swnd);
- //we must call the original window procedure, otherwise it
- //will never get the WM_NCDESTROY message, and it wouldn't
- //be able to clean up etc.
- return (IsWindowUnicode(hwnd)) ? CallWindowProcW(oldproc, hwnd, message, wParam, lParam) : CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
- case WM_NCCALCSIZE:
- return NCCalcSize(swnd, hwnd, wParam, lParam);
- case WM_NCPAINT:
- return NCPaint(swnd, hwnd, wParam, lParam);
- case WM_NCHITTEST:
- return NCHitTest(swnd, hwnd, wParam, lParam);
- case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP:
- case WM_NCMBUTTONDOWN: case WM_NCMBUTTONUP:
- if (wParam == HTHSCROLL || wParam == HTVSCROLL)
- return 0;
- else
- break;
- case WM_NCLBUTTONDBLCLK:
- //TRACE("WM_NCLBUTTONDBLCLK %d\n", count++);
- if (wParam == HTHSCROLL || wParam == HTVSCROLL)
- return NCLButtonDown(swnd, hwnd, wParam, lParam);
- else
- break;
- case WM_NCLBUTTONDOWN:
- //TRACE("WM_NCLBUTTONDOWN%d\n", count++);
- return NCLButtonDown(swnd, hwnd, wParam, lParam);
- case WM_LBUTTONUP:
- //TRACE("WM_LBUTTONUP %d\n", count++);
- return LButtonUp(swnd, hwnd, wParam, lParam);
- case WM_NOTIFY:
- return CoolSB_Notify(swnd, hwnd, wParam, lParam);
- //Mouse moves are received when we set the mouse capture,
- //even when the mouse moves over the non-client area
- case WM_MOUSEMOVE:
- //TRACE("WM_MOUSEMOVE %d\n", count++);
- return MouseMove(swnd, hwnd, wParam, lParam);
- case WM_TIMER:
- return CoolSB_Timer(swnd, hwnd, wParam, lParam);
- //case WM_STYLECHANGING:
- // return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGING, wParam, lParam);
- case WM_STYLECHANGED:
- if (swnd->bPreventStyleChange)
- {
- // the NCPAINT handler has told us to eat this message!
- return 0;
- }
- else
- {
- if (message == WM_STYLECHANGED)
- return CoolSB_StyleChange(swnd, hwnd, WM_STYLECHANGED, wParam, lParam);
- }
- break;
- case WM_NCMOUSEMOVE:
- {
- static LPARAM lastpos = -1;
- //TRACE("WM_NCMOUSEMOVE %d\n", count++);
- //The problem with NCMOUSEMOVE is that it is sent continuously
- //even when the mouse is stationary (under win2000 / win98)
- //
- //Tooltips don't like being sent a continous stream of mouse-moves
- //if the cursor isn't moving, because they will think that the mouse
- //is moving position, and the internal timer will never expire
- //
- if (lastpos != lParam)
- {
- lastpos = lParam;
- }
- }
- return NCMouseMove(swnd, hwnd, wParam, lParam);
- case WM_SETCURSOR:
- return CoolSB_SetCursor(swnd, hwnd, wParam, lParam);
- case WM_CAPTURECHANGED:
- break;
- case WM_ERASEBKGND:
- if (swnd && !swnd->fThumbTracking && uCurrentScrollPortion == HTSCROLL_NONE)
- {
- //disable windows scrollbar painting (fixes gfx repainting weirdness)
- int style = GetWindowLong(hwnd, GWL_STYLE);
- if (style&(WS_HSCROLL | WS_VSCROLL))
- {
- SetWindowLong(hwnd, GWL_STYLE, style&~(WS_HSCROLL | WS_VSCROLL));
- }
- LRESULT ret = (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, message, wParam, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, message, wParam, lParam);
- swnd->update();
- return ret;
- }
- break;
- //needed if we want mousewheel to work properly because we disable the styles in WM_ERASEBKGND...
- case WM_MOUSEWHEEL:
- {
- int style = GetWindowLong(hwnd, GWL_STYLE);
- swnd->bPreventStyleChange = TRUE;
- SetWindowLong(hwnd, GWL_STYLE, style | (swnd->sbarHorz.fScrollVisible ? WS_HSCROLL : 0) | (swnd->sbarVert.fScrollVisible ? WS_VSCROLL : 0));
- LRESULT ret = (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, message, wParam, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, message, wParam, lParam);
- SetWindowLongPtr(hwnd, GWL_STYLE, style);
- swnd->bPreventStyleChange = FALSE;
- return ret;
- }
- case WM_USER + 0x3443: //manually sent by other windows (like columns header for ex.)
- if (swnd) swnd->update();
- break;
- default:
- break;
- }
- return (swnd->fWndUnicode) ? CallWindowProcW(swnd->oldproc, hwnd, message, wParam, lParam) :
- CallWindowProcA(swnd->oldproc, hwnd, message, wParam, lParam);
- }
- SCROLLBAR *GetScrollBarFromHwnd(HWND hwnd, UINT nBar)
- {
- ScrollWnd *sw = GetScrollWndFromHwnd(hwnd);
- if (!sw) return 0;
- if (nBar == SB_HORZ)
- return &sw->sbarHorz;
- else if (nBar == SB_VERT)
- return &sw->sbarVert;
- else
- return 0;
- }
- //
- // return the default minimum size of a scrollbar thumb
- //
- int WINAPI CoolSB_GetDefaultMinThumbSize(void)
- {
- DWORD dwVersion = GetVersion();
- // set the minimum thumb size for a scrollbar. This
- // differs between NT4 and 2000, so need to check to see
- // which platform we are running under
- if (dwVersion < 0x80000000) // Windows NT/2000
- {
- if (LOBYTE(LOWORD(dwVersion)) >= 5)
- return MINTHUMBSIZE_2000;
- else
- return MINTHUMBSIZE_NT4;
- }
- else
- {
- return MINTHUMBSIZE_NT4;
- }
- }
- //
- // Set the minimum size, in pixels, that the thumb box will shrink to.
- //
- BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size)
- {
- SCROLLBAR *sbar;
- if (!GetScrollWndFromHwnd(hwnd))
- return FALSE;
- if (size == -1)
- size = CoolSB_GetDefaultMinThumbSize();
- if ((wBar == SB_HORZ || wBar == SB_BOTH) &&
- (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
- {
- sbar->nMinThumbSize = size;
- }
- if ((wBar == SB_VERT || wBar == SB_BOTH) &&
- (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
- {
- sbar->nMinThumbSize = size;
- }
- return TRUE;
- }
- static void RedrawNonClient(HWND hwnd, BOOL fFrameChanged)
- {
- if (fFrameChanged == FALSE)
- {
- SendMessage(hwnd, WM_NCPAINT, (WPARAM)1, 0);
- }
- else
- {
- SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE
- | SWP_FRAMECHANGED | SWP_DRAWFRAME);
- }
- }
- ScrollWnd::ScrollWnd(HWND hwnd, int flags)
- {
- SCROLLINFO *si;
- RECT rect;
- DWORD dwCurStyle;
- bars = 0;
- oldproc = NULL;
- memset(&sbarHorz, 0, sizeof(sbarHorz));
- memset(&sbarVert, 0, sizeof(sbarVert));
- sbarHorz.flags = flags;
- sbarVert.flags = flags;
- fThumbTracking = 0;
- fLeftScrollbar = 0;
- cxLeftEdge = cxRightEdge = cyTopEdge = cyBottomEdge = 0;
- bPreventStyleChange = 0;
- m_disable_hscroll = 0;
- m_xp_theme_disabled = 0;
- m_hwnd = hwnd;
- GetClientRect(hwnd, &rect);
- si = &sbarHorz.scrollInfo;
- si->cbSize = sizeof(SCROLLINFO);
- si->fMask = SIF_ALL;
- GetScrollInfo(hwnd, SB_HORZ, si);
- si = &sbarVert.scrollInfo;
- si->cbSize = sizeof(SCROLLINFO);
- si->fMask = SIF_ALL;
- GetScrollInfo(hwnd, SB_VERT, si);
- //check to see if the window has left-aligned scrollbars
- if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR)
- fLeftScrollbar = TRUE;
- else
- fLeftScrollbar = FALSE;
- dwCurStyle = GetWindowLong(hwnd, GWL_STYLE);
- SetProp(hwnd, szPropStr, (HANDLE)this);
- //scrollbars will automatically get enabled, even if
- //they aren't to start with....sorry, but there isn't an
- //easy alternative.
- if (dwCurStyle & WS_HSCROLL)
- sbarHorz.fScrollFlags = CSBS_VISIBLE;
- if (dwCurStyle & WS_VSCROLL)
- sbarVert.fScrollFlags = CSBS_VISIBLE;
- //need to be able to distinguish between horizontal and vertical
- //scrollbars in some instances
- sbarHorz.nBarType = SB_HORZ;
- sbarVert.nBarType = SB_VERT;
- sbarHorz.fFlatScrollbar = CSBS_NORMAL;
- sbarVert.fFlatScrollbar = CSBS_NORMAL;
- //set the default arrow sizes for the scrollbars
- sbarHorz.nArrowLength = SYSTEM_METRIC;
- sbarHorz.nArrowWidth = SYSTEM_METRIC;
- sbarVert.nArrowLength = SYSTEM_METRIC;
- sbarVert.nArrowWidth = SYSTEM_METRIC;
- bPreventStyleChange = FALSE;
- fWndUnicode = IsWindowUnicode(hwnd);
- oldproc = (WNDPROC)(LONG_PTR) ((fWndUnicode) ? SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)CoolSBWndProc) :
- SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)CoolSBWndProc));
-
- CoolSB_SetMinThumbSize(hwnd, SB_BOTH, CoolSB_GetDefaultMinThumbSize());
- //send the window a frame changed message to update the scrollbars
- RedrawNonClient(hwnd, TRUE);
- //disable XP styles
- if (SetWindowTheme && !m_xp_theme_disabled)
- {
- SetWindowTheme(m_hwnd, L" ", L" ");
- m_xp_theme_disabled = 1;
- }
- }
- BOOL WINAPI CoolSB_ShowScrollBar(HWND hwnd, int wBar, BOOL fShow)
- {
- SCROLLBAR *sbar;
- BOOL bFailed = FALSE;
- DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE);
- if ((wBar == SB_HORZ || wBar == SB_BOTH) &&
- (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ)))
- {
- sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE;
- sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
- //bFailed = TRUE;
- if (fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL);
- else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL);
- }
- if ((wBar == SB_VERT || wBar == SB_BOTH) &&
- (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT)))
- {
- sbar->fScrollFlags = sbar->fScrollFlags & ~CSBS_VISIBLE;
- sbar->fScrollFlags |= (fShow == TRUE ? CSBS_VISIBLE : 0);
- //bFailed = TRUE;
- if (fShow) SetWindowLong(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL);
- else SetWindowLong(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL);
- }
- if (bFailed)
- {
- return FALSE;
- }
- else
- {
- SetWindowPos(hwnd, 0, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
- SWP_NOACTIVATE | SWP_FRAMECHANGED);
- return TRUE;
- }
- }
- ScrollWnd::~ScrollWnd()
- {
- if (oldproc)
- {
- ((fWndUnicode) ? SetWindowLongPtrW(m_hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)oldproc) :
- SetWindowLongPtrA(m_hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)oldproc));
- }
- RemoveProp(m_hwnd, szPropStr);
- RedrawNonClient(m_hwnd, TRUE);
- }
- void ScrollWnd::update()
- {
- int dohorz = 0, dovert = 0;
- SCROLLINFO tsi = {sizeof(SCROLLINFO), SIF_ALL, };
- if (!m_disable_hscroll)
- {
- GetScrollInfo(m_hwnd, SB_HORZ, &tsi);
- if (memcmp(&tsi, &sbarHorz.scrollInfo, sizeof(SCROLLINFO)))
- {
- memcpy(&sbarHorz.scrollInfo, &tsi, sizeof(SCROLLINFO));
- dohorz = 1;
- }
- }
- GetScrollInfo(m_hwnd, SB_VERT, &tsi);
- if (memcmp(&tsi, &sbarVert.scrollInfo, sizeof(SCROLLINFO)))
- {
- memcpy(&sbarVert.scrollInfo, &tsi, sizeof(SCROLLINFO));
- dovert = 1;
- }
- BOOL fRecalcFrame = FALSE;
- if (dohorz) updatesb(SB_HORZ, &fRecalcFrame);
- if (dovert) updatesb(SB_VERT, &fRecalcFrame);
- if (dohorz || dovert) RedrawNonClient(m_hwnd, fRecalcFrame);
- }
- void ScrollWnd::updatesb(int fnBar, BOOL *fRecalcFrame)
- {
- SCROLLBAR *sbar = (fnBar == SB_HORZ ? &sbarHorz : &sbarVert);
- SCROLLINFO *mysi = &sbar->scrollInfo;
- if (mysi->nPage > (UINT)mysi->nMax
- || (mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0)
- || mysi->nMax <= mysi->nMin)
- {
- if (sbar->fScrollVisible)
- {
- CoolSB_ShowScrollBar(m_hwnd, fnBar, FALSE);
- *fRecalcFrame = TRUE;
- }
- }
- else
- {
- if (!sbar->fScrollVisible && mysi->nPage > 0)
- {
- CoolSB_ShowScrollBar(m_hwnd, fnBar, TRUE);
- *fRecalcFrame = TRUE;
- }
- else if (sbar->fScrollVisible && mysi->nPage == 0)
- {
- CoolSB_ShowScrollBar(m_hwnd, fnBar, FALSE);
- *fRecalcFrame = TRUE;
- }
- }
- }
- void ScrollWnd::disableHorzScroll()
- {
- m_disable_hscroll = 1;
- sbarHorz.fScrollFlags = 0;
- }
- #if 0 // unused
- int ScrollWnd::setScrollInfo(int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw)
- {
- SCROLLINFO *mysi;
- SCROLLBAR *sbar;
- BOOL fRecalcFrame = FALSE;
- if (!lpsi)
- return FALSE;
- if (fnBar == SB_HORZ) mysi = &sbarHorz.scrollInfo;
- else mysi = &sbarVert.scrollInfo;
- if (lpsi->fMask & SIF_RANGE)
- {
- mysi->nMin = lpsi->nMin;
- mysi->nMax = lpsi->nMax;
- }
- //The nPage member must specify a value from 0 to nMax - nMin +1.
- if (lpsi->fMask & SIF_PAGE)
- {
- UINT t = (UINT)(mysi->nMax - mysi->nMin + 1);
- mysi->nPage = min(max(0, lpsi->nPage), t);
- }
- //The nPos member must specify a value between nMin and nMax - max(nPage - 1, 0).
- if (lpsi->fMask & SIF_POS)
- {
- mysi->nPos = max(lpsi->nPos, mysi->nMin);
- mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0));
- }
- sbar = GetScrollBarFromHwnd(m_hwnd, fnBar);
- if ((lpsi->fMask & SIF_DISABLENOSCROLL) || (sbar->fScrollFlags & CSBS_THUMBALWAYS))
- {
- if (!sbar->fScrollVisible)
- {
- CoolSB_ShowScrollBar(m_hwnd, fnBar, TRUE);
- fRecalcFrame = TRUE;
- }
- }
- else
- {
- if (mysi->nPage > (UINT)mysi->nMax
- || mysi->nPage == (UINT)mysi->nMax && mysi->nMax == 0
- || mysi->nMax <= mysi->nMin)
- {
- if (sbar->fScrollVisible)
- {
- CoolSB_ShowScrollBar(m_hwnd, fnBar, FALSE);
- fRecalcFrame = TRUE;
- }
- }
- else
- {
- if (!sbar->fScrollVisible)
- {
- CoolSB_ShowScrollBar(m_hwnd, fnBar, TRUE);
- fRecalcFrame = TRUE;
- }
- }
- }
- if (fRedraw && !fThumbTracking)
- RedrawNonClient(m_hwnd, fRecalcFrame);
- return mysi->nPos;
- }
- #endif
|