|
|
#include "ctlspriv.h"
static struct { WPARAM vk1; WPARAM vk2; int dx; int dy; } arrNumMaps[] = { { VK_NUMPAD1, VK_END, -RM_SCROLLUNIT, RM_SCROLLUNIT,}, { VK_NUMPAD2, VK_DOWN, 0, RM_SCROLLUNIT}, { VK_NUMPAD3, VK_NEXT, RM_SCROLLUNIT, RM_SCROLLUNIT}, { VK_NUMPAD4, VK_LEFT, -RM_SCROLLUNIT, 0}, { VK_NUMPAD5, VK_CLEAR, 0, 0}, { VK_NUMPAD6, VK_RIGHT, RM_SCROLLUNIT, 0}, { VK_NUMPAD7, VK_HOME, -RM_SCROLLUNIT, -RM_SCROLLUNIT}, { VK_NUMPAD8, VK_UP, 0, -RM_SCROLLUNIT}, { VK_NUMPAD9, VK_PRIOR, RM_SCROLLUNIT, -RM_SCROLLUNIT}, };
// do some keyboard handling...
// this works like USER's arrow keys for resizing
void RM_HandleKeyDown(LPRECT prcHot, WPARAM wParam, LPARAM lParam) { int i; POINT pt; GetCursorPos(&pt); for (i = ARRAYSIZE(arrNumMaps) - 1 ; i >= 0; i--) { if (wParam == arrNumMaps[i].vk1 || wParam == arrNumMaps[i].vk2) { break; } } if (i == -1) { ReleaseCapture(); return; }
// this deals with if the cursor is within the bounds of the rect
if (pt.x < prcHot->right && pt.x >= prcHot->left && arrNumMaps[i].dx) { if (arrNumMaps[i].dx > 0) pt.x = prcHot->right - 2; else pt.x = prcHot->left + 1; } if (pt.y < prcHot->bottom && pt.y >= prcHot->top && arrNumMaps[i].dy) { if (arrNumMaps[i].dy > 0) pt.y = prcHot->bottom - 2; else pt.y = prcHot->top + 1; } pt.x += arrNumMaps[i].dx; pt.y += arrNumMaps[i].dy;
if (!arrNumMaps[i].dx && !arrNumMaps[i].dy) { // special case this for centering
pt.x = (prcHot->right + prcHot->left) / 2; pt.y = (prcHot->top + prcHot->bottom) / 2; }
// all we do is move the cursor.. the RM_CheckScroll will do the actual
// scrolling for us.
SetCursorPos(pt.x, pt.y); }
void RM_GetScrollXY(PREADERMODEINFO prmi, LPRECT prcHot, LPINT pdx, LPINT pdy) {
POINT pt; GetCursorPos(&pt); *pdx = 0; *pdy = 0; if (pt.x <= prcHot->left) { *pdx = ((pt.x - prcHot->left) / RM_SCROLLUNIT) - 1; } else if (pt.x >= prcHot->right) { *pdx = ((pt.x - prcHot->right) / RM_SCROLLUNIT) + 1; } if (pt.y <= prcHot->top) { *pdy = ((pt.y - prcHot->top) / RM_SCROLLUNIT) - 1; } else if (pt.y >= prcHot->bottom) { *pdy = ((pt.y - prcHot->bottom) / RM_SCROLLUNIT) + 1; }
if (prmi->fFlags & RMF_VERTICALONLY) *pdx = 0;
if (prmi->fFlags & RMF_HORIZONTALONLY) *pdy = 0; }
void RM_CheckScroll(PREADERMODEINFO prmi, LPRECT prcHot) { int dx; int dy;
RM_GetScrollXY(prmi, prcHot, &dx, &dy); prmi->pfnScroll(prmi, dx, dy); }
void RM_SetCursor(PREADERMODEINFO prmi, LPRECT prcHot) { int dx; int dy; LPCTSTR pRes; RM_GetScrollXY(prmi, prcHot, &dx, &dy);
// default is center
if (prmi->fFlags & RMF_VERTICALONLY) pRes = IDC_VERTICALONLY; else if (prmi->fFlags & RMF_HORIZONTALONLY) pRes = IDC_HORIZONTALONLY; else pRes = IDC_MOVE2D;
// multiply to figure out if either is zero and also the sign parity
if (dy * dx) { // diagonal case
if (dy > 0) { if (dx > 0) pRes = IDC_SOUTHEAST; else pRes = IDC_SOUTHWEST; } else { if (dx > 0) pRes = IDC_NORTHEAST; else pRes = IDC_NORTHWEST; } } else { // simple horizontal or vertical case
if (dy > 0) pRes = IDC_SOUTH; else if (dy < 0) pRes = IDC_NORTH; else if (dx < 0) pRes = IDC_WEST; else if (dx > 0) pRes = IDC_EAST; } SetCursor(LoadCursor(HINST_THISDLL, pRes)); }
void DoReaderMode(PREADERMODEINFO prmi) { RECT rcHot; if (!prmi->hwnd || prmi->cbSize != sizeof(*prmi)) return; SetCapture(prmi->hwnd); // if they didn't pass in a rect, then use the window
if (!prmi->prc) { GetWindowRect(prmi->hwnd, &rcHot ); } else { rcHot = *prmi->prc; MapWindowPoints(prmi->hwnd, HWND_DESKTOP, (LPPOINT)&rcHot, 2); } // set the cursor to the center of the hot rect if they ask us to
if (prmi->fFlags & RMF_ZEROCURSOR) { SetCursorPos((rcHot.left + rcHot.right)/2, (rcHot.top + rcHot.bottom)/2); } while (GetCapture() == prmi->hwnd) { BOOL fMessage; MSG32 msg32; RM_CheckScroll(prmi, &rcHot);
// Try to peek keyboard message first, then mouse message,
// and finally, other message. This is for raid 44392.
// During scrolling, Trident might generate too many WM_PAINT
// messages that push keyboard/mouse message (that DoReaderMode()
// uses to stop auto-scroll mode) down in message pump, and we can
// not get those messages until we peek and process all these
// WM_PAINT messages. This is way cuto-scroll mode can be stopped
// only by moving cursor back to origin circle (Trident does not
// scroll, so no need to paint). Trident's scroll performance
// issue will be worked on after RTM (raid 33232).
//
fMessage = PeekMessage32(&msg32, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE, TRUE); if (!fMessage) { fMessage = PeekMessage32(&msg32, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE, TRUE); if (!fMessage) { fMessage = PeekMessage32(&msg32, NULL, 0, 0, PM_REMOVE, TRUE); } }
if (fMessage) { if (!prmi->pfnTranslateDispatch || !prmi->pfnTranslateDispatch((LPMSG)&msg32)) {
if (msg32.message == g_msgMSWheel) goto BailOut;
switch(msg32.message) { case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_SYSKEYDOWN: BailOut: ReleaseCapture(); break;
case WM_KEYDOWN: // if it's an arrow key, move the mouse cursor
RM_HandleKeyDown(&rcHot, msg32.wParam, msg32.lParam); break;
case WM_MOUSEMOVE: case WM_SETCURSOR: RM_SetCursor(prmi, &rcHot); break;
default: TranslateMessage32(&msg32, TRUE); DispatchMessage32(&msg32, TRUE); } } } else WaitMessage(); } }
|