|
|
1.1 root 1: /***************************************************************************
2: * *
3: * MODULE : track.c *
4: * *
5: * PURPOSE : Generic tracking code. *
6: * *
7: ***************************************************************************/
8: #include <windows.h>
9: #include <windowsx.h>
10: #include "track.h"
11:
12: RECT rcTrack;
13: RECT rcDelta;
14: POINT ptOrg;
15: POINT ptPrev;
16: DWORD fsTrack;
17: RECT rcBoundary;
18: INT cxMinTrack;
19: INT cyMinTrack;
20:
21: VOID DrawTrackRect(HWND hwnd, LPRECT prcOld, LPRECT prcNew);
22: VOID HorzUpdate(HDC hdc, INT yOld, INT yNew, INT x1Old, INT x1New, INT x2Old,
23: INT x2New);
24: VOID VertUpdate(HDC hdc, INT xOld, INT xNew, INT y1Old, INT y1New, INT y2Old,
25: INT y2New);
26: LONG APIENTRY TrackingWndProc(HWND hwnd, DWORD msg, WPARAM wParam, LPARAM lParam);
27:
28: typedef POINTS MPOINT ;
29: #define MAKEMPOINT(l) (*((MPOINT *)&(l)))
30: #define MPOINT2POINT(mpt,pt) ((pt).x = (mpt).x, (pt).y = (mpt).y)
31:
32:
33: /****************************************************************************
34: * *
35: * FUNCTION : TrackRect() *
36: * *
37: * PURPOSE : Implements functionality similiar to the PM WinTrackRect() *
38: * *
39: * RETURNS : TRUE on success, FALSE if tracking was canceled. *
40: * prcResult contains the resulting rectangle. *
41: * *
42: ****************************************************************************/
43: BOOL TrackRect(
44: HANDLE hInst,
45: HWND hwnd, // bounding window
46: INT left, // rectangle to track in bounding window coords.
47: INT top,
48: INT right,
49: INT bottom,
50: INT cxMin,
51: INT cyMin,
52: DWORD fs,
53: LPRECT prcResult) // result rect in bounding window coords.
54: {
55: static BOOL fTracking = 0;
56: FARPROC lpOrgWndProc, lpTrackWndProc;
57: HWND hwndOldCapture, hwndOldFocus;
58: MSG msg;
59:
60: if (fTracking)
61: return FALSE;
62:
63: fTracking = TRUE;
64:
65: lpOrgWndProc = (FARPROC)GetWindowLong(hwnd, GWL_WNDPROC);
66: lpTrackWndProc = MakeProcInstance((FARPROC)TrackingWndProc, hInst);
67: SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)lpTrackWndProc);
68:
69: hwndOldCapture = GetCapture();
70: SetCapture(hwnd);
71:
72: hwndOldFocus = SetFocus(hwnd);
73: UpdateWindow(hwnd);
74:
75: GetCursorPos(&ptOrg);
76: ScreenToClient(hwnd, &ptOrg);
77:
78: if (fs & TF_SETPOINTERPOS) {
79:
80: if (fs & TF_LEFT && fs & TF_RIGHT)
81: ptOrg.x = (left + right) / 2;
82: else if (fs & TF_LEFT)
83: ptOrg.x = left;
84: else if (fs & TF_RIGHT)
85: ptOrg.x = right;
86:
87: if (fs & TF_TOP && fs & TF_BOTTOM)
88: ptOrg.y = (top + bottom) / 2;
89: else if (fs & TF_TOP)
90: ptOrg.y = top;
91: else if (fs & TF_BOTTOM)
92: ptOrg.y = bottom;
93:
94: ClientToScreen(hwnd, &ptOrg);
95: SetCursorPos(ptOrg.x, ptOrg.y);
96: ScreenToClient(hwnd, &ptOrg);
97: }
98:
99: ptPrev = ptOrg;
100: cxMinTrack = cxMin;
101: cyMinTrack = cyMin;
102: GetClientRect(hwnd, &rcBoundary);
103: fsTrack = fs;
104: SetRect(&rcTrack, left, top, right, bottom);
105: SetRect(&rcDelta, left - ptOrg.x, top - ptOrg.y, right - ptOrg.x,
106: bottom - ptOrg.y);
107: DrawTrackRect(hwnd, &rcTrack, NULL);
108:
109: while (GetMessage(&msg, NULL, NULL, NULL))
110: DispatchMessage(&msg);
111:
112: DrawTrackRect(hwnd, &rcTrack, NULL);
113:
114: SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)lpOrgWndProc);
115: FreeProcInstance(lpTrackWndProc);
116:
117: SetFocus(hwndOldFocus);
118: SetCapture(hwndOldCapture);
119: CopyRect(prcResult, &rcTrack);
120:
121: fTracking = FALSE;
122: }
123:
124:
125:
126:
127:
128: /****************************************************************************
129: * *
130: * FUNCTION : DrawTrackRect() *
131: * *
132: * PURPOSE : XOR draws whats needed to move a selection from prcOld to *
133: * prcNew. If prcNew == NULL this is considered a *
134: * first-time draw or last time erase. *
135: * *
136: ****************************************************************************/
137: VOID DrawTrackRect(
138: HWND hwnd,
139: LPRECT prcOld,
140: LPRECT prcNew)
141: {
142: HDC hdc;
143:
144: hdc = GetDC(hwnd);
145: SetROP2(hdc, R2_NOT);
146: // erase/draw the whole thing
147: MoveToEx(hdc, prcOld->left, prcOld->top, NULL);
148: LineTo(hdc, prcOld->right, prcOld->top);
149: LineTo(hdc, prcOld->right, prcOld->bottom);
150: LineTo(hdc, prcOld->left, prcOld->bottom);
151: LineTo(hdc, prcOld->left, prcOld->top);
152: if (prcNew) {
153: MoveToEx(hdc, prcNew->left, prcNew->top, NULL);
154: LineTo(hdc, prcNew->right, prcNew->top);
155: LineTo(hdc, prcNew->right, prcNew->bottom);
156: LineTo(hdc, prcNew->left, prcNew->bottom);
157: LineTo(hdc, prcNew->left, prcNew->top);
158: }
159: ReleaseDC(hwnd, hdc);
160: }
161:
162:
163:
164: /****************************************************************************
165: * *
166: * FUNCTION : TrackingWndProc() *
167: * *
168: * PURPOSE : Window procedure that subclasses the given parent window. *
169: * This handles the mouse tracking and rectangle updates. *
170: * *
171: ****************************************************************************/
172: LONG APIENTRY TrackingWndProc(
173: HWND hwnd,
174: DWORD msg,
175: WPARAM wParam,
176: LPARAM lParam)
177: {
178: switch (msg) {
179: case WM_MOUSEMOVE:
180: {
181: RECT rcNow, rcTest;
182:
183: if (ptPrev.x == (short)LOWORD(lParam) && ptPrev.y == (short)HIWORD(lParam))
184: return 0;
185: CopyRect(&rcNow, &rcTrack);
186: if (fsTrack & TF_LEFT)
187: rcNow.left = (short)LOWORD(lParam) + rcDelta.left;
188: if (fsTrack & TF_RIGHT)
189: rcNow.right = (short)LOWORD(lParam) + rcDelta.right;
190: if (fsTrack & TF_TOP)
191: rcNow.top = (short)HIWORD(lParam) + rcDelta.top;
192: if (fsTrack & TF_BOTTOM)
193: rcNow.bottom = (short)HIWORD(lParam) + rcDelta.bottom;
194:
195: if (rcNow.left > rcNow.right - cxMinTrack)
196: if (fsTrack & TF_LEFT)
197: rcNow.left = rcNow.right - cxMinTrack;
198: else
199: rcNow.right = rcNow.left + cxMinTrack;
200:
201: if (rcNow.top > rcNow.bottom - cyMinTrack)
202: if (fsTrack & TF_TOP)
203: rcNow.top = rcNow.bottom - cyMinTrack;
204: else
205: rcNow.bottom = rcNow.top + cyMinTrack;
206:
207: if (fsTrack & TF_ALLINBOUNDARY) {
208: if ((fsTrack & TF_MOVE) == TF_MOVE) {
209: IntersectRect(&rcTest, &rcNow, &rcBoundary);
210: if (!EqualRect(&rcTest, &rcNow)) {
211: if (rcNow.left < rcBoundary.left)
212: OffsetRect(&rcNow, rcBoundary.left - rcNow.left, 0);
213: if (rcNow.right > rcBoundary.right)
214: OffsetRect(&rcNow, rcBoundary.right - rcNow.right, 0);
215: if (rcNow.top < rcBoundary.top)
216: OffsetRect(&rcNow, 0, rcBoundary.top - rcNow.top);
217: if (rcNow.bottom > rcBoundary.bottom)
218: OffsetRect(&rcNow, 0, rcBoundary.bottom - rcNow.bottom);
219: }
220: } else
221: IntersectRect(&rcNow, &rcNow, &rcBoundary);
222: }
223:
224: if (EqualRect(&rcNow, &rcTrack))
225: return 0;
226:
227: DrawTrackRect(hwnd, &rcTrack, &rcNow);
228:
229: CopyRect(&rcTrack, &rcNow);
230: MPOINT2POINT(MAKEMPOINT(lParam), ptPrev);
231: }
232: break;
233:
234: case WM_LBUTTONUP:
235: SendMessage(hwnd, WM_MOUSEMOVE, wParam, lParam);
236: PostMessage(hwnd, WM_QUIT, 0, 0); // pop out of modal loop
237: return 0;
238: break;
239:
240: default:
241: return(DefWindowProc(hwnd, msg, wParam, lParam));
242: break;
243: }
244: return 0;
245: }
246:
247:
248:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.