reactos/base/applications/clipbrd/scrollutils.c

315 lines
6.6 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Clipboard Viewer
* FILE: base/applications/clipbrd/scrollutils.c
* PURPOSE: Scrolling related helper functions.
* PROGRAMMERS: Ricardo Hanke
*/
#include "precomp.h"
static int InternalSetScrollInfo(HWND hWnd, int nMin, int nMax, UINT nPage, int nPos, int fnBar)
{
SCROLLINFO si;
ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
si.nMin = nMin;
si.nMax = nMax;
si.nPage = nPage;
si.nPos = nPos;
return SetScrollInfo(hWnd, fnBar, &si, TRUE);
}
void HandleKeyboardScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case VK_UP:
{
SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_LINEUP, 0), 0);
break;
}
case VK_DOWN:
{
SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
break;
}
case VK_LEFT:
{
SendMessage(hWnd, WM_HSCROLL, MAKELONG(SB_LINEUP, 0), 0);
break;
}
case VK_RIGHT:
{
SendMessage(hWnd, WM_HSCROLL, MAKELONG(SB_LINEDOWN, 0), 0);
break;
}
case VK_PRIOR:
{
SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_PAGEUP, 0), 0);
break;
}
case VK_NEXT:
{
SendMessage(hWnd, WM_VSCROLL, MAKELONG(SB_PAGEDOWN, 0), 0);
break;
}
default:
{
break;
}
}
}
void HandleMouseScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state)
{
SCROLLINFO si;
int Delta;
int NewPos;
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE;
GetScrollInfo(hWnd, SB_VERT, &si);
if (Globals.uLinesToScroll == WHEEL_PAGESCROLL)
{
NewPos = si.nPage;
}
else
{
NewPos = Globals.uLinesToScroll * 5;
}
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
{
NewPos = state->CurrentY - NewPos;
}
else
{
NewPos = state->CurrentY + NewPos;
}
NewPos = min(state->MaxY, max(0, NewPos));
if (NewPos == state->CurrentY)
{
return;
}
Delta = NewPos - state->CurrentY;
state->CurrentY = NewPos;
ScrollWindowEx(hWnd, 0, -Delta, NULL, NULL, NULL, NULL, SW_INVALIDATE);
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = state->CurrentY;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
}
void HandleHorizontalScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state)
{
SCROLLINFO si;
int Delta;
int NewPos;
ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_TRACKPOS;
GetScrollInfo(hWnd, SB_HORZ, &si);
switch (LOWORD(wParam))
{
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
NewPos = si.nTrackPos;
break;
}
case SB_LINELEFT:
{
NewPos = state->CurrentX - 5;
break;
}
case SB_LINERIGHT:
{
NewPos = state->CurrentX + 5;
break;
}
case SB_PAGELEFT:
{
NewPos = state->CurrentX - si.nPage;
break;
}
case SB_PAGERIGHT:
{
NewPos = state->CurrentX + si.nPage;
break;
}
default:
{
NewPos = state->CurrentX;
break;
}
}
NewPos = min(state->MaxX, max(0, NewPos));
if (NewPos == state->CurrentX)
{
return;
}
Delta = NewPos - state->CurrentX;
state->CurrentX = NewPos;
ScrollWindowEx(hWnd, -Delta, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE);
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = state->CurrentX;
SetScrollInfo(hWnd, SB_HORZ, &si, TRUE);
}
void HandleVerticalScrollEvents(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LPSCROLLSTATE state)
{
SCROLLINFO si;
int Delta;
int NewPos;
ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_TRACKPOS;
GetScrollInfo(hWnd, SB_VERT, &si);
switch (LOWORD(wParam))
{
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
NewPos = si.nTrackPos;
break;
}
case SB_LINEUP:
{
NewPos = state->CurrentY - 5;
break;
}
case SB_LINEDOWN:
{
NewPos = state->CurrentY + 5;
break;
}
case SB_PAGEUP:
{
NewPos = state->CurrentY - si.nPage;
break;
}
case SB_PAGEDOWN:
{
NewPos = state->CurrentY + si.nPage;
break;
}
default:
{
NewPos = state->CurrentY;
break;
}
}
NewPos = min(state->MaxY, max(0, NewPos));
if (NewPos == state->CurrentY)
{
return;
}
Delta = NewPos - state->CurrentY;
state->CurrentY = NewPos;
ScrollWindowEx(hWnd, 0, -Delta, NULL, NULL, NULL, NULL, SW_INVALIDATE);
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = state->CurrentY;
SetScrollInfo(hWnd, SB_VERT, &si, TRUE);
}
void UpdateWindowScrollState(HWND hWnd, HBITMAP hBitmap, LPSCROLLSTATE lpState)
{
BITMAP bmp;
RECT rc;
if (!GetObject(hBitmap, sizeof(BITMAP), &bmp))
{
bmp.bmWidth = 0;
bmp.bmHeight = 0;
}
if (!GetClientRect(hWnd, &rc))
{
SetRectEmpty(&rc);
}
lpState->MaxX = max(bmp.bmWidth - rc.right, 0);
lpState->CurrentX = min(lpState->CurrentX, lpState->MaxX);
InternalSetScrollInfo(hWnd, 0, bmp.bmWidth, rc.right, lpState->CurrentX, SB_HORZ);
lpState->MaxY = max(bmp.bmHeight - rc.bottom, 0);
lpState->CurrentY = min(lpState->CurrentY, lpState->MaxY);
InternalSetScrollInfo(hWnd, 0, bmp.bmHeight, rc.bottom, lpState->CurrentY, SB_VERT);
}
BOOL ScrollBlt(PAINTSTRUCT ps, HBITMAP hBmp, SCROLLSTATE state)
{
RECT rect;
BOOL ret;
HDC hdc;
int xpos;
int ypos;
rect.left = ps.rcPaint.left;
rect.top = ps.rcPaint.top;
rect.right = (ps.rcPaint.right - ps.rcPaint.left);
rect.bottom = (ps.rcPaint.bottom - ps.rcPaint.top);
xpos = ps.rcPaint.left + state.CurrentX;
ypos = ps.rcPaint.top + state.CurrentY;
ret = FALSE;
hdc = CreateCompatibleDC(ps.hdc);
if (hdc)
{
if (SelectObject(hdc, hBmp))
{
ret = BitBlt(ps.hdc, rect.left, rect.top, rect.right, rect.bottom, hdc, xpos, ypos, SRCCOPY);
}
DeleteDC(hdc);
}
return ret;
}