mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
9.8 KiB
294 lines
9.8 KiB
/***************************************************************************
|
|
* *
|
|
* MODULE : track.c *
|
|
* *
|
|
* PURPOSE : Generic tracking code. *
|
|
* *
|
|
***************************************************************************/
|
|
#define NOGDICAPMASKS
|
|
// #define NOVIRTUALKEYCODES
|
|
#define NOWINSTYLES
|
|
#define NOSYSMETRICS
|
|
#define NOMENUS
|
|
#define NOICONS
|
|
#define NOKEYSTATES
|
|
#define NOSYSCOMMANDS
|
|
#define NOSHOWWINDOW
|
|
#define NOATOM
|
|
#define NOCLIPBOARD
|
|
#define NOCOLOR
|
|
#define NOCTLMGR
|
|
#define NODRAWTEXT
|
|
#define NOMB
|
|
#define NOLOGERROR
|
|
#define NOMEMMGR
|
|
#define NOMETAFILE
|
|
#define NOMINMAX
|
|
#define NOOEMRESOURCE
|
|
#define NOOPENFILE
|
|
#define NOSCROLL
|
|
#define NOSOUND
|
|
#define NOTEXTMETRIC
|
|
#define NOWH
|
|
#define NOHELP
|
|
#define NOPROFILER
|
|
#define NODEFERWINDOWPOS
|
|
#define NODRIVERS
|
|
#define NOCOMM
|
|
#define NODBCS
|
|
#define NOSYSTEMPARAMSINFO
|
|
#define NOSCALABLEFONT
|
|
#include <windows.h>
|
|
#include <port1632.h>
|
|
#include "track.h"
|
|
|
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
#define max(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
TRACKINFO ti;
|
|
RECT rcDelta;
|
|
RECT rcOrg;
|
|
POINT ptPrev;
|
|
|
|
VOID DrawTrackRect(HWND hwnd, LPRECT prcOld, LPRECT prcNew);
|
|
VOID HorzUpdate(HDC hdc, INT yOld, INT yNew, INT x1Old, INT x1New, INT x2Old,
|
|
INT x2New);
|
|
VOID VertUpdate(HDC hdc, INT xOld, INT xNew, INT y1Old, INT y1New, INT y2Old,
|
|
INT y2New);
|
|
LONG APIENTRY TrackingWndProc(HWND hwnd, WORD msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* FUNCTION : TrackRect() *
|
|
* *
|
|
* PURPOSE : Implements functionality similiar to the PM WinTrackRect() *
|
|
* *
|
|
* RETURNS : TRUE on success, FALSE if tracking was canceled. *
|
|
* prcResult contains the resulting rectangle. *
|
|
* *
|
|
****************************************************************************/
|
|
BOOL TrackRect(
|
|
HANDLE hInst,
|
|
HWND hwnd, // bounding window
|
|
LPTRACKINFO lpti)
|
|
{
|
|
static BOOL fTracking = 0;
|
|
FARPROC lpOrgWndProc, lpTrackWndProc;
|
|
HWND hwndOldCapture, hwndOldFocus;
|
|
MSG msg;
|
|
|
|
if (fTracking)
|
|
return FALSE;
|
|
|
|
ti = *lpti;
|
|
|
|
fTracking = TRUE;
|
|
|
|
lpOrgWndProc = (FARPROC)GetWindowLong(hwnd, GWL_WNDPROC);
|
|
lpTrackWndProc = MakeProcInstance((FARPROC)TrackingWndProc, hInst);
|
|
SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)lpTrackWndProc);
|
|
|
|
hwndOldCapture = GetCapture();
|
|
SetCapture(hwnd);
|
|
|
|
hwndOldFocus = SetFocus(hwnd);
|
|
UpdateWindow(hwnd);
|
|
|
|
rcOrg = ti.rcTrack;
|
|
|
|
if (ti.fs & TF_SETPOINTERPOS) {
|
|
|
|
if (ti.fs & TF_LEFT && ti.fs & TF_RIGHT)
|
|
ti.ptOrg.x = (ti.rcTrack.left + ti.rcTrack.right) / 2;
|
|
else if (ti.fs & TF_LEFT)
|
|
ti.ptOrg.x = ti.rcTrack.left;
|
|
else if (ti.fs & TF_RIGHT)
|
|
ti.ptOrg.x = ti.rcTrack.right;
|
|
|
|
if (ti.fs & TF_TOP && ti.fs & TF_BOTTOM)
|
|
ti.ptOrg.y = (ti.rcTrack.top + ti.rcTrack.bottom) / 2;
|
|
else if (ti.fs & TF_TOP)
|
|
ti.ptOrg.y = ti.rcTrack.top;
|
|
else if (ti.fs & TF_BOTTOM)
|
|
ti.ptOrg.y = ti.rcTrack.bottom;
|
|
|
|
ClientToScreen(hwnd, &ti.ptOrg);
|
|
SetCursorPos(ti.ptOrg.x, ti.ptOrg.y);
|
|
ScreenToClient(hwnd, &ti.ptOrg);
|
|
}
|
|
|
|
ptPrev = ti.ptOrg;
|
|
SetRect(&rcDelta, ti.rcTrack.left - ti.ptOrg.x, ti.rcTrack.top - ti.ptOrg.y,
|
|
ti.rcTrack.right - ti.ptOrg.x, ti.rcTrack.bottom - ti.ptOrg.y);
|
|
DrawTrackRect(hwnd, &ti.rcTrack, NULL);
|
|
|
|
while (GetMessage(&msg, hwnd, 0, 0)) {
|
|
if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {
|
|
DrawTrackRect(hwnd, &ti.rcTrack, NULL);
|
|
ti.rcTrack = rcOrg;
|
|
DrawTrackRect(hwnd, &ti.rcTrack, NULL);
|
|
break;
|
|
} else {
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
DrawTrackRect(hwnd, &ti.rcTrack, NULL);
|
|
|
|
SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)lpOrgWndProc);
|
|
FreeProcInstance(lpTrackWndProc);
|
|
|
|
SetFocus(hwndOldFocus);
|
|
SetCapture(hwndOldCapture);
|
|
|
|
fTracking = FALSE;
|
|
|
|
*lpti = ti;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* FUNCTION : DrawTrackRect() *
|
|
* *
|
|
* PURPOSE : XOR draws whats needed to move a selection from prcOld to *
|
|
* prcNew. If prcNew == NULL this is considered a *
|
|
* first-time draw or last time erase. *
|
|
* *
|
|
****************************************************************************/
|
|
VOID DrawTrackRect(
|
|
HWND hwnd,
|
|
LPRECT prcOld,
|
|
LPRECT prcNew)
|
|
{
|
|
HDC hdc;
|
|
|
|
hdc = GetDC(hwnd);
|
|
SetROP2(hdc, R2_NOT);
|
|
// erase/draw the whole thing
|
|
MMoveTo(hdc, prcOld->left, prcOld->top);
|
|
LineTo(hdc, prcOld->right, prcOld->top);
|
|
LineTo(hdc, prcOld->right, prcOld->bottom);
|
|
LineTo(hdc, prcOld->left, prcOld->bottom);
|
|
LineTo(hdc, prcOld->left, prcOld->top);
|
|
if (prcNew) {
|
|
MMoveTo(hdc, prcNew->left, prcNew->top);
|
|
LineTo(hdc, prcNew->right, prcNew->top);
|
|
LineTo(hdc, prcNew->right, prcNew->bottom);
|
|
LineTo(hdc, prcNew->left, prcNew->bottom);
|
|
LineTo(hdc, prcNew->left, prcNew->top);
|
|
}
|
|
ReleaseDC(hwnd, hdc);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
* *
|
|
* FUNCTION : TrackingWndProc() *
|
|
* *
|
|
* PURPOSE : Window procedure that subclasses the given parent window. *
|
|
* This handles the mouse tracking and rectangle updates. *
|
|
* *
|
|
****************************************************************************/
|
|
LONG APIENTRY TrackingWndProc(
|
|
HWND hwnd,
|
|
WORD msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (msg) {
|
|
case WM_MOUSEMOVE:
|
|
{
|
|
RECT rcNow, rcTest;
|
|
INT x, y;
|
|
|
|
x = (int)(short)LOWORD(lParam);
|
|
y = (int)(short)HIWORD(lParam);
|
|
if (ptPrev.x == x && ptPrev.y == y)
|
|
return(0);
|
|
|
|
if (ti.fs & TF_RUBBERBAND) {
|
|
rcNow.left = min(x, rcOrg.left);
|
|
rcNow.right = max(x, rcOrg.right);
|
|
rcNow.top = min(y, rcOrg.top);
|
|
rcNow.bottom = max(y, rcOrg.bottom);
|
|
} else {
|
|
|
|
CopyRect(&rcNow, &ti.rcTrack);
|
|
|
|
if (ti.fs & TF_LEFT)
|
|
rcNow.left = x + rcDelta.left;
|
|
if (ti.fs & TF_RIGHT)
|
|
rcNow.right = x + rcDelta.right;
|
|
if (ti.fs & TF_TOP)
|
|
rcNow.top = y + rcDelta.top;
|
|
if (ti.fs & TF_BOTTOM)
|
|
rcNow.bottom = y + rcDelta.bottom;
|
|
|
|
if (rcNow.left > rcNow.right - ti.ptMinTrackSize.x)
|
|
if (ti.fs & TF_LEFT)
|
|
rcNow.left = rcNow.right - ti.ptMinTrackSize.x;
|
|
else
|
|
rcNow.right = rcNow.left + ti.ptMinTrackSize.x;
|
|
|
|
if (rcNow.top > rcNow.bottom - ti.ptMinTrackSize.y)
|
|
if (ti.fs & TF_TOP)
|
|
rcNow.top = rcNow.bottom - ti.ptMinTrackSize.y;
|
|
else
|
|
rcNow.bottom = rcNow.top + ti.ptMinTrackSize.y;
|
|
|
|
if (ti.cxGrid > 1 || ti.cyGrid > 1) {
|
|
OffsetRect(&rcNow,
|
|
-((rcNow.left - rcOrg.left) % ti.cxGrid),
|
|
-((rcNow.top - rcOrg.top ) % ti.cyGrid));
|
|
}
|
|
|
|
}
|
|
|
|
if (ti.fs & TF_ALLINBOUNDARY) {
|
|
if ((ti.fs & TF_MOVE) == TF_MOVE) {
|
|
IntersectRect(&rcTest, &rcNow, &ti.rcBoundary);
|
|
if (!EqualRect(&rcTest, &rcNow)) {
|
|
if (rcNow.left < ti.rcBoundary.left)
|
|
OffsetRect(&rcNow, ti.rcBoundary.left - rcNow.left, 0);
|
|
if (rcNow.right > ti.rcBoundary.right)
|
|
OffsetRect(&rcNow, ti.rcBoundary.right - rcNow.right, 0);
|
|
if (rcNow.top < ti.rcBoundary.top)
|
|
OffsetRect(&rcNow, 0, ti.rcBoundary.top - rcNow.top);
|
|
if (rcNow.bottom > ti.rcBoundary.bottom)
|
|
OffsetRect(&rcNow, 0, ti.rcBoundary.bottom - rcNow.bottom);
|
|
}
|
|
} else
|
|
IntersectRect(&rcNow, &rcNow, &ti.rcBoundary);
|
|
}
|
|
|
|
if (EqualRect(&rcNow, &ti.rcTrack))
|
|
return 0;
|
|
|
|
DrawTrackRect(hwnd, &ti.rcTrack, &rcNow);
|
|
|
|
CopyRect(&ti.rcTrack, &rcNow);
|
|
LONG2POINT(lParam, ptPrev);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
SendMessage(hwnd, WM_MOUSEMOVE, wParam, lParam);
|
|
PostMessage(hwnd, WM_QUIT, 0, 0); // pop out of modal loop
|
|
return 0;
|
|
break;
|
|
|
|
default:
|
|
return(DefWindowProc(hwnd, msg, wParam, lParam));
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|