#include "stdafx.h" #include "SBdetours.h" #include "detours.h" #include #include "windows.h" #pragma warning(disable:4100) // Trampolines don't use formal parameters. static TCHAR szPropStr[] = _T("SkinScrollBarPtr"); SCROLLWND *GetScrollWndFromHwnd(HWND hwnd) { return (SCROLLWND *)GetProp(hwnd, szPropStr); } 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; } BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd) { if(GetScrollWndFromHwnd(hwnd)) return TRUE; else return FALSE; } SCROLLINFO *GetScrollInfoFromHwnd(HWND hwnd, int fnBar) { SCROLLBAR *sb = GetScrollBarFromHwnd(hwnd, fnBar); if(sb == 0) return FALSE; if(fnBar == SB_HORZ) { return &sb->scrollInfo; } else if(fnBar == SB_VERT) { return &sb->scrollInfo; } else return NULL; } BOOL WINAPI CoolSB_EnableScrollBar (HWND hwnd, int wSBflags, UINT wArrows) { SCROLLBAR *sbar; UINT oldstate; BOOL bFailed = FALSE; if(!CoolSB_IsCoolScrollEnabled(hwnd)) return EnableScrollBar(hwnd, wSBflags, wArrows); if((wSBflags == SB_HORZ || wSBflags == SB_BOTH) && (sbar = GetScrollBarFromHwnd(hwnd, SB_HORZ))) { oldstate = sbar->fScrollFlags; //clear any existing state, and OR in the disabled flags sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows; if(oldstate == sbar->fScrollFlags) bFailed = TRUE; } if((wSBflags == SB_VERT || wSBflags == SB_BOTH) && (sbar = GetScrollBarFromHwnd(hwnd, SB_VERT))) { oldstate = sbar->fScrollFlags; //clear any existing state, and OR in the disabled flags sbar->fScrollFlags = (sbar->fScrollFlags & ~ESB_DISABLE_BOTH) | wArrows; if(oldstate == sbar->fScrollFlags) bFailed = TRUE; } return !bFailed; } BOOL WINAPI CoolSB_GetScrollBarInfo(HWND hwnd) { // SCROLLBARINFO sbi; not defined in winuser.h return FALSE; } BOOL WINAPI CoolSB_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi) { SCROLLINFO *mysi; BOOL copied = FALSE; if(!lpsi) return FALSE; if(!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar))) { return GetScrollInfo(hwnd, fnBar, lpsi); } if(lpsi->fMask & SIF_PAGE) { lpsi->nPage = mysi->nPage; copied = TRUE; } if(lpsi->fMask & SIF_POS) { lpsi->nPos = mysi->nPos; copied = TRUE; } if(lpsi->fMask & SIF_TRACKPOS) { lpsi->nTrackPos = mysi->nTrackPos; copied = TRUE; } if(lpsi->fMask & SIF_RANGE) { lpsi->nMin = mysi->nMin; lpsi->nMax = mysi->nMax; copied = TRUE; } return copied; } int WINAPI CoolSB_GetScrollPos (HWND hwnd, int nBar) { SCROLLINFO *mysi; if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) return GetScrollPos(hwnd, nBar); return mysi->nPos; } BOOL WINAPI CoolSB_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) { SCROLLINFO *mysi; if(!lpMinPos || !lpMaxPos) return FALSE; if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) return GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos); *lpMinPos = mysi->nMin; *lpMaxPos = mysi->nMax; return TRUE; } int WINAPI CoolSB_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw) { SCROLLINFO *mysi; SCROLLBAR *sbar; BOOL fRecalcFrame = FALSE; if(!lpsi) return FALSE; if(!(mysi = GetScrollInfoFromHwnd(hwnd, fnBar))) return SetScrollInfo(hwnd, fnBar, lpsi, fRedraw); //if(CoolSB_IsThumbTracking(hwnd)) // return mysi->nPos; 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(hwnd, fnBar); if((lpsi->fMask & SIF_DISABLENOSCROLL) )//|| (sbar->fScrollFlags & CSBS_THUMBALWAYS)) { if(!sbar->fScrollVisible) { // CoolSB_ShowScrollBar(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(hwnd, fnBar, FALSE); fRecalcFrame = TRUE; } } else { if(!sbar->fScrollVisible) { // CoolSB_ShowScrollBar(hwnd, fnBar, TRUE); fRecalcFrame = TRUE; } } } // if(fRedraw && !CoolSB_IsThumbTracking(hwnd)) // RedrawNonClient(hwnd, fRecalcFrame); if(fRedraw) SendMessage(hwnd,WM_NCPAINT,0,0); return mysi->nPos; } int WINAPI CoolSB_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw) { SCROLLINFO *mysi; int oldpos; if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) { return SetScrollPos(hwnd, nBar, nPos, fRedraw); } //this is what should happen, but real scrollbars don't work like this.. //if(CoolSB_IsThumbTracking(hwnd)) // return mysi->nPos; //validate and set the scollbar position oldpos = mysi->nPos; mysi->nPos = max(nPos, mysi->nMin); mysi->nPos = min((UINT)mysi->nPos, mysi->nMax - max(mysi->nPage - 1, 0)); // if(fRedraw && !CoolSB_IsThumbTracking(hwnd)) // RedrawNonClient(hwnd, FALSE); if(fRedraw) SendMessage(hwnd,WM_NCPAINT,0,0); return oldpos; } int WINAPI CoolSB_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw) { SCROLLINFO *mysi; if(!(mysi = GetScrollInfoFromHwnd(hwnd, nBar))) return SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, fRedraw); // if(CoolSB_IsThumbTracking(hwnd)) // return mysi->nPos; //hide the scrollbar if nMin == nMax //nMax-nMin must not be greater than MAXLONG mysi->nMin = nMinPos; mysi->nMax = nMaxPos; if(fRedraw) SendMessage(hwnd,WM_NCPAINT,0,0); return TRUE; } // // Show or hide the specified scrollbars // BOOL WINAPI CoolSB_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow) { SCROLLBAR *sbar; BOOL bFailed = FALSE; DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE); if(!CoolSB_IsCoolScrollEnabled(hwnd)) return ShowScrollBar(hwnd, wBar, fShow); 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 { //DWORD style = GetWindowLong(hwnd, GWL_STYLE); //style |= WS_VSCROLL; //if(s //SetWindowLong(hwnd, GWL_STYLE, style); SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); return TRUE; } } #pragma warning(disable:4100) // Trampolines don't use formal parameters. DETOUR_TRAMPOLINE(BOOL WINAPI Detour_EnableScrollBar(HWND hwnd, int wSBflags, UINT wArrows), EnableScrollBar); DETOUR_TRAMPOLINE(BOOL WINAPI Detour_GetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi), GetScrollInfo); DETOUR_TRAMPOLINE(int WINAPI Detour_GetScrollPos (HWND hwnd, int nBar), GetScrollPos); DETOUR_TRAMPOLINE(BOOL WINAPI Detour_GetScrollRange (HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos), GetScrollRange); DETOUR_TRAMPOLINE(int WINAPI Detour_SetScrollInfo (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw), SetScrollInfo); DETOUR_TRAMPOLINE(int WINAPI Detour_SetScrollPos (HWND hwnd, int nBar, int nPos, BOOL fRedraw), SetScrollPos); DETOUR_TRAMPOLINE(int WINAPI Detour_SetScrollRange (HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw), SetScrollRange); DETOUR_TRAMPOLINE(BOOL WINAPI Detour_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow), ShowScrollBar); static BOOL WINAPI Tramp_EnableScrollBar(HWND hwnd, int wSBflags, UINT wArrows) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_EnableScrollBar(hwnd, wSBflags, wArrows); else return Detour_EnableScrollBar(hwnd, wSBflags, wArrows); } static BOOL WINAPI Tramp_GetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_GetScrollInfo(hwnd, fnBar, lpsi); else return Detour_GetScrollInfo(hwnd, fnBar, lpsi); } static int WINAPI Tramp_GetScrollPos(HWND hwnd, int nBar) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_GetScrollPos(hwnd, nBar); else return Detour_GetScrollPos(hwnd, nBar); } static BOOL WINAPI Tramp_GetScrollRange(HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos); else return Detour_GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos); } static int WINAPI Tramp_SetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_SetScrollInfo(hwnd, fnBar, lpsi, fRedraw); else return Detour_SetScrollInfo(hwnd, fnBar, lpsi, fRedraw); } static int WINAPI Tramp_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_SetScrollPos(hwnd, nBar, nPos, fRedraw); else return Detour_SetScrollPos(hwnd, nBar, nPos, fRedraw); } static int WINAPI Tramp_SetScrollRange(HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, fRedraw); else return Detour_SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, fRedraw); } static BOOL WINAPI Tramp_ShowScrollBar (HWND hwnd, int wBar, BOOL fShow) { if(CoolSB_IsCoolScrollEnabled(hwnd)) return CoolSB_ShowScrollBar(hwnd, wBar, fShow); else return Detour_ShowScrollBar(hwnd, wBar, fShow); } BOOL WINAPI CoolSB_InitializeApp(void) { DWORD dwVersion = GetVersion(); // Only available under Windows NT, 2000 and XP if(dwVersion < 0x80000000) { DetourFunctionWithTrampoline((PBYTE)Detour_EnableScrollBar, (PBYTE)Tramp_EnableScrollBar); DetourFunctionWithTrampoline((PBYTE)Detour_GetScrollInfo, (PBYTE)Tramp_GetScrollInfo); DetourFunctionWithTrampoline((PBYTE)Detour_GetScrollPos, (PBYTE)Tramp_GetScrollPos); DetourFunctionWithTrampoline((PBYTE)Detour_GetScrollRange, (PBYTE)Tramp_GetScrollRange); DetourFunctionWithTrampoline((PBYTE)Detour_SetScrollInfo, (PBYTE)Tramp_SetScrollInfo); DetourFunctionWithTrampoline((PBYTE)Detour_SetScrollPos, (PBYTE)Tramp_SetScrollPos); DetourFunctionWithTrampoline((PBYTE)Detour_SetScrollRange, (PBYTE)Tramp_SetScrollRange); DetourFunctionWithTrampoline((PBYTE)Detour_ShowScrollBar, (PBYTE)Tramp_ShowScrollBar); // don't actually use this feature within coolsb yet, but we might need it CoolSB_SetESBProc(Detour_EnableScrollBar); return TRUE; } else { return FALSE; } } BOOL WINAPI CoolSB_UninitializeApp(void) { DWORD dwVersion = GetVersion(); // Only available under Windows NT, 2000 and XP if(dwVersion < 0x80000000) { DetourRemove((PBYTE)Detour_EnableScrollBar, (PBYTE)Tramp_EnableScrollBar); DetourRemove((PBYTE)Detour_GetScrollInfo, (PBYTE)Tramp_GetScrollInfo); DetourRemove((PBYTE)Detour_GetScrollPos, (PBYTE)Tramp_GetScrollPos); DetourRemove((PBYTE)Detour_GetScrollRange, (PBYTE)Tramp_GetScrollRange); DetourRemove((PBYTE)Detour_SetScrollInfo, (PBYTE)Tramp_SetScrollInfo); DetourRemove((PBYTE)Detour_SetScrollPos, (PBYTE)Tramp_SetScrollPos); DetourRemove((PBYTE)Detour_SetScrollRange, (PBYTE)Tramp_SetScrollRange); DetourRemove((PBYTE)Detour_ShowScrollBar, (PBYTE)Tramp_ShowScrollBar); // don't actually use this feature within coolsb yet, but we might need it CoolSB_SetESBProc(EnableScrollBar); return TRUE; } else { return FALSE; } }