256 lines
6.9 KiB
C
256 lines
6.9 KiB
C
|
|
||
|
#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();
|
||
|
}
|
||
|
}
|