|
|
1.1 root 1: /****************************************************************************/
2: /* */
3: /* Microsoft Confidential */
4: /* */
5: /* Copyright (c) Microsoft Corp. 1987-1993 */
6: /* All Rights Reserved */
7: /* */
8: /****************************************************************************/
9: /****************************** Module Header *******************************
10: * Module Name: zoomin.c
11: *
12: * Microsoft ZoomIn utility. This tool magnifies a portion of the screen,
13: * allowing you to see things at a pixel level.
14: *
15: * History:
16: * 01/01/88 Created.
17: * 01/01/92 Ported to NT.
18: * 03/06/92 Cleanup.
19: *
20: ****************************************************************************/
21:
22: #include "zoomin.h"
23:
24:
25: CHAR szAppName[] = "ZoomIn"; // Aplication name.
26: HINSTANCE ghInst; // Instance handle.
27: HWND ghwndApp; // Main window handle.
28: HANDLE ghaccelTable; // Main accelerator table.
29: INT gnZoom = 4; // Zoom (magnification) factor.
30: HPALETTE ghpalPhysical; // Handle to the physical palette.
31: INT gcxScreenMax; // Width of the screen (less 1).
32: INT gcyScreenMax; // Height of the screen (less 1).
33: INT gcxZoomed; // Client width in zoomed pixels.
34: INT gcyZoomed; // Client height in zoomed pixels.
35: BOOL gfRefEnable = FALSE; // TRUE if refresh is enabled.
36: INT gnRefInterval = 20; // Refresh interval in 10ths of seconds.
37: BOOL gfTracking = FALSE; // TRUE if tracking is in progress.
38: POINT gptZoom = {100, 100}; // The center of the zoomed area.
39:
40:
41:
42: /************************************************************************
43: * WinMain
44: *
45: * Main entry point for the application.
46: *
47: * Arguments:
48: *
49: * History:
50: *
51: ************************************************************************/
52:
53: INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, INT nCmdShow)
54: {
55: MSG msg;
56:
57: if (!InitInstance(hInst, nCmdShow))
58: return FALSE;
59:
60: /* * Polling messages from event queue
61: */
62:
63: while (GetMessage(&msg, NULL, 0, 0)) {
64: if (!TranslateAccelerator(ghwndApp, ghaccelTable, &msg)) {
65: TranslateMessage(&msg);
66: DispatchMessage(&msg);
67: }
68: }
69:
70: return msg.wParam;
71: }
72:
73:
74:
75: /************************************************************************
76: * InitInstance
77: *
78: * Instance initialization for the app.
79: *
80: * Arguments:
81: *
82: * History:
83: *
84: ************************************************************************/
85:
86: BOOL InitInstance(
87: HINSTANCE hInst,
88: INT cmdShow)
89: {
90: WNDCLASS wc;
91: INT dx;
92: INT dy;
93: DWORD flStyle;
94: RECT rc;
95:
96: ghInst = hInst;
97:
98: /*
99: * Register a class for the main application window.
100: */
101: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
102: wc.hIcon = LoadIcon(hInst, "zoomin");
103: wc.lpszMenuName = MAKEINTRESOURCE(IDMENU_ZOOMIN);
104: wc.lpszClassName = szAppName;
105: wc.hbrBackground = GetStockObject(BLACK_BRUSH);
106: wc.hInstance = hInst;
107: wc.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW;
108: wc.lpfnWndProc = (WNDPROC)AppWndProc;
109: wc.cbWndExtra = 0;
110: wc.cbClsExtra = 0;
111:
112: if (!RegisterClass(&wc))
113: return FALSE;
114:
115: if (!(ghaccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDACCEL_ZOOMIN))))
116: return FALSE;
117:
118: if (!(ghpalPhysical = CreatePhysicalPalette()))
119: return FALSE;
120:
121: gcxScreenMax = GetSystemMetrics(SM_CXSCREEN) - 1; gcyScreenMax = GetSystemMetrics(SM_CYSCREEN) - 1;
122:
123: flStyle = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME |
124: WS_MINIMIZEBOX | WS_VSCROLL;
125: dx = 44 * gnZoom;
126: dy = 36 * gnZoom;
127:
128: SetRect(&rc, 0, 0, dx, dy);
129: AdjustWindowRect(&rc, flStyle, TRUE);
130:
131: ghwndApp = CreateWindow(szAppName, szAppName, flStyle,
132: CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top,
133: NULL, NULL, hInst, NULL);
134:
135: if (!ghwndApp)
136: return FALSE;
137: ShowWindow(ghwndApp, cmdShow);
138:
139: return TRUE;
140: }
141:
142:
143:
144: /************************************************************************
145: * CreatePhysicalPalette
146: *
147: * Creates a palette for the app to use. The palette references the
148: * physical palette, so that it can properly display images grabbed
149: * from palette managed apps.
150: *
151: * History:
152: *
153: ************************************************************************/
154:
155: HPALETTE CreatePhysicalPalette(VOID)
156: {
157: PLOGPALETTE ppal;
158: HPALETTE hpal = NULL;
159: INT i;
160:
161: ppal = (PLOGPALETTE)LocalAlloc(LPTR,
162: sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * NPAL);
163: if (ppal) {
164: ppal->palVersion = 0x300;
165: ppal->palNumEntries = NPAL;
166:
167: for (i = 0; i < NPAL; i++) {
168: ppal->palPalEntry[i].peFlags = (BYTE)PC_EXPLICIT;
169: ppal->palPalEntry[i].peRed = (BYTE)i;
170: ppal->palPalEntry[i].peGreen = (BYTE)0;
171: ppal->palPalEntry[i].peBlue = (BYTE)0;
172: }
173:
174: hpal = CreatePalette(ppal);
175: LocalFree(ppal);
176: }
177:
178: return hpal;
179: }
180:
181:
182:
183: /************************************************************************
184: * AppWndProc
185: *
186: * Main window proc for the zoomin utility.
187: *
188: * Arguments:
189: * Standard window proc args.
190: *
191: * History:
192: *
193: ************************************************************************/
194:
195: LONG APIENTRY AppWndProc(
196: HWND hwnd,
197: UINT msg,
198: WPARAM wParam,
199: LPARAM lParam)
200: {
201: PAINTSTRUCT ps;
202: HCURSOR hcurOld;
203:
204: switch (msg) {
205: case WM_CREATE:
206: SetScrollRange(hwnd, SB_VERT, MIN_ZOOM, MAX_ZOOM, FALSE);
207: SetScrollPos(hwnd, SB_VERT, gnZoom, FALSE);
208: break;
209:
210: case WM_TIMER:
211: /*
212: * Update on every timer message. The cursor will be
213: * flashed to the hourglash for some visual feedback
214: * of when a snapshot is being taken.
215: */
216: hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
217: DoTheZoomIn(NULL);
218: SetCursor(hcurOld);
219: break;
220:
221: case WM_PAINT:
222: BeginPaint(hwnd, &ps);
223: DoTheZoomIn(ps.hdc);
224: EndPaint(hwnd, &ps);
225: return 0L;
226:
227: case WM_SIZE:
228: CalcZoomedSize();
229: break;
230:
231: case WM_LBUTTONDOWN:
232: ((gptZoom).x = (SHORT)LOWORD(lParam), (gptZoom).y = (SHORT)HIWORD(lParam));
233: ClientToScreen(hwnd, &gptZoom);
234: DrawZoomRect();
235: DoTheZoomIn(NULL);
236:
237: SetCapture(hwnd);
238: gfTracking = TRUE;
239:
240: break;
241:
242: case WM_MOUSEMOVE:
243: if (gfTracking) {
244: DrawZoomRect();
245: ((gptZoom).x = (SHORT)LOWORD(lParam), (gptZoom).y = (SHORT)HIWORD(lParam));
246: ClientToScreen(hwnd, &gptZoom);
247: DrawZoomRect();
248: DoTheZoomIn(NULL);
249: }
250:
251: break;
252:
253: case WM_LBUTTONUP:
254: if (gfTracking) {
255: DrawZoomRect();
256: ReleaseCapture();
257: gfTracking = FALSE;
258: }
259:
260: break;
261:
262: case WM_VSCROLL:
263: switch (LOWORD(wParam)) {
264: case SB_LINEDOWN:
265: gnZoom++;
266: break;
267:
268: case SB_LINEUP:
269: gnZoom--;
270: break;
271:
272: case SB_PAGEUP:
273: gnZoom -= 2;
274: break;
275:
276: case SB_PAGEDOWN:
277: gnZoom += 2;
278: break;
279:
280: case SB_THUMBPOSITION:
281: case SB_THUMBTRACK:
282: gnZoom = HIWORD(wParam);
283: break;
284: }
285:
286: gnZoom = BOUND(gnZoom, MIN_ZOOM, MAX_ZOOM);
287: SetScrollPos(hwnd, SB_VERT, gnZoom, TRUE);
288: CalcZoomedSize();
289: DoTheZoomIn(NULL);
290: break;
291:
292: case WM_KEYDOWN:
293: switch (wParam) {
294: case VK_UP:
295: case VK_DOWN:
296: case VK_LEFT:
297: case VK_RIGHT:
298: MoveView((INT)wParam, GetKeyState(VK_SHIFT) & 0x8000,
299: GetKeyState(VK_CONTROL) & 0x8000);
300: break;
301: }
302:
303: break;
304:
305: case WM_COMMAND:
306: switch (LOWORD(wParam)) {
307: case MENU_EDIT_COPY:
308: CopyToClipboard();
309: break;
310:
311: case MENU_EDIT_REFRESH:
312: DoTheZoomIn(NULL);
313: break;
314:
315: case MENU_OPTIONS_REFRESHRATE:
316: DialogBox(ghInst, (LPSTR)MAKEINTRESOURCE(DID_REFRESHRATE),
317: hwnd, (WNDPROC)RefreshRateDlgProc);
318:
319: break;
320:
321: case MENU_HELP_ABOUT:
322: DialogBox(ghInst, (LPSTR)MAKEINTRESOURCE(DID_ABOUT),
323: hwnd, (WNDPROC)AboutDlgProc);
324:
325: break;
326:
327: default:
328: break;
329: }
330:
331: break;
332:
333: case WM_CLOSE:
334: if (ghpalPhysical)
335: DeleteObject(ghpalPhysical);
336:
337: DestroyWindow(hwnd);
338:
339: break;
340:
341: case WM_DESTROY:
342: PostQuitMessage(0);
343: break;
344:
345: default:
346: return DefWindowProc(hwnd, msg, wParam, lParam);
347: }
348:
349: return 0L;
350: }
351:
352:
353:
354: /************************************************************************
355: * CalcZoomedSize
356: *
357: * Calculates some globals. This routine needs to be called any
358: * time that the size of the app or the zoom factor changes.
359: *
360: * History:
361: *
362: ************************************************************************/
363:
364: VOID CalcZoomedSize(VOID)
365: {
366: RECT rc;
367:
368: GetClientRect(ghwndApp, &rc);
369:
370: gcxZoomed = (rc.right / gnZoom) + 1;
371: gcyZoomed = (rc.bottom / gnZoom) + 1;
372: }
373:
374:
375:
376: /************************************************************************
377: * DoTheZoomIn
378: *
379: * Does the actual paint of the zoomed image.
380: *
381: * Arguments:
382: * HDC hdc - If not NULL, this hdc will be used to paint with.
383: * If NULL, a dc for the apps window will be obtained.
384: *
385: * History:
386: *
387: ************************************************************************/
388:
389: VOID DoTheZoomIn(
390: HDC hdc)
391: {
392: BOOL fRelease;
393: HPALETTE hpalOld = NULL;
394: HDC hdcScreen;
395: INT x;
396: INT y;
397:
398: if (!hdc) {
399: hdc = GetDC(ghwndApp);
400: fRelease = TRUE;
401: }
402: else {
403: fRelease = FALSE;
404: }
405:
406: if (ghpalPhysical) {
407: hpalOld = SelectPalette(hdc, ghpalPhysical, FALSE);
408: RealizePalette(hdc);
409: }
410:
411: /*
412: * The point must not include areas outside the screen dimensions.
413: */
414: x = BOUND(gptZoom.x, gcxZoomed / 2, gcxScreenMax - (gcxZoomed / 2));
415: y = BOUND(gptZoom.y, gcyZoomed / 2, gcyScreenMax - (gcyZoomed / 2));
416:
417: hdcScreen = GetDC(NULL);
418: SetStretchBltMode(hdc, COLORONCOLOR);
419: StretchBlt(hdc, 0, 0, gnZoom * gcxZoomed, gnZoom * gcyZoomed,
420: hdcScreen, x - gcxZoomed / 2,
421: y - gcyZoomed / 2, gcxZoomed, gcyZoomed, SRCCOPY);
422: ReleaseDC(NULL, hdcScreen);
423:
424: if (hpalOld)
425: SelectPalette(hdc, hpalOld, FALSE);
426:
427: if (fRelease)
428: ReleaseDC(ghwndApp, hdc);
429: }
430:
431:
432:
433: /************************************************************************
434: * MoveView
435: *
436: * This function moves the current view around.
437: *
438: * Arguments:
439: * INT nDirectionCode - Direction to move. Must be VK_UP, VK_DOWN,
440: * VK_LEFT or VK_RIGHT.
441: * BOOL fFast - TRUE if the move should jump a larger increment.
442: * If FALSE, the move is just one pixel.
443: * BOOL fPeg - If TRUE, the view will be pegged to the screen
444: * boundary in the specified direction. This overides
445: * the fFast parameter.
446: *
447: * History:
448: *
449: ************************************************************************/
450:
451: VOID MoveView(
452: INT nDirectionCode,
453: BOOL fFast,
454: BOOL fPeg)
455: {
456: INT delta;
457:
458: if (fFast)
459: delta = FASTDELTA;
460: else
461: delta = 1;
462:
463: switch (nDirectionCode) {
464: case VK_UP:
465: if (fPeg)
466: gptZoom.y = gcyZoomed / 2;
467: else
468: gptZoom.y -= delta;
469:
470: gptZoom.y = BOUND(gptZoom.y, 0, gcyScreenMax);
471:
472: break;
473:
474: case VK_DOWN:
475: if (fPeg)
476: gptZoom.y = gcyScreenMax - (gcyZoomed / 2);
477: else
478: gptZoom.y += delta;
479:
480: gptZoom.y = BOUND(gptZoom.y, 0, gcyScreenMax);
481:
482: break;
483:
484: case VK_LEFT:
485: if (fPeg)
486: gptZoom.x = gcxZoomed / 2;
487: else
488: gptZoom.x -= delta;
489:
490: gptZoom.x = BOUND(gptZoom.x, 0, gcxScreenMax);
491:
492: break;
493:
494: case VK_RIGHT:
495: if (fPeg)
496: gptZoom.x = gcxScreenMax - (gcxZoomed / 2);
497: else
498: gptZoom.x += delta;
499:
500: gptZoom.x = BOUND(gptZoom.x, 0, gcxScreenMax);
501:
502: break;
503: }
504:
505: DoTheZoomIn(NULL);
506: }
507:
508:
509:
510: /************************************************************************
511: * DrawZoomRect
512: *
513: * This function draws the tracking rectangle. The size and shape of
514: * the rectangle will be proportional to the size and shape of the
515: * app's client, and will be affected by the zoom factor as well.
516: *
517: * History:
518: *
519: ************************************************************************/
520:
521: VOID DrawZoomRect(VOID)
522: {
523: HDC hdc;
524: RECT rc;
525: INT x;
526: INT y;
527:
528: x = BOUND(gptZoom.x, gcxZoomed / 2, gcxScreenMax - (gcxZoomed / 2));
529: y = BOUND(gptZoom.y, gcyZoomed / 2, gcyScreenMax - (gcyZoomed / 2));
530:
531: rc.left = x - gcxZoomed / 2;
532: rc.top = y - gcyZoomed / 2;
533: rc.right = rc.left + gcxZoomed;
534: rc.bottom = rc.top + gcyZoomed;
535:
536: InflateRect(&rc, 1, 1);
537:
538: hdc = GetDC(NULL);
539:
540: PatBlt(hdc, rc.left, rc.top, rc.right-rc.left, 1, DSTINVERT);
541: PatBlt(hdc, rc.left, rc.bottom, 1, -(rc.bottom-rc.top), DSTINVERT);
542: PatBlt(hdc, rc.right-1, rc.top, 1, rc.bottom-rc.top, DSTINVERT);
543: PatBlt(hdc, rc.right, rc.bottom-1, -(rc.right-rc.left), 1, DSTINVERT);
544:
545: ReleaseDC(NULL, hdc);
546: }
547:
548:
549:
550: /************************************************************************
551: * EnableRefresh
552: *
553: * This function turns on or off the auto-refresh feature.
554: *
555: * Arguments:
556: * BOOL fEnable - TRUE to turn the refresh feature on, FALSE to
557: * turn it off.
558: *
559: * History:
560: *
561: ************************************************************************/
562:
563: VOID EnableRefresh(
564: BOOL fEnable)
565: {
566: if (fEnable) {
567: /*
568: * Already enabled. Do nothing.
569: */
570: if (gfRefEnable)
571: return;
572:
573: if (SetTimer(ghwndApp, IDTIMER_ZOOMIN, gnRefInterval * 100, NULL))
574: gfRefEnable = TRUE;
575: }
576: else {
577: /*
578: * Not enabled yet. Do nothing.
579: */
580: if (!gfRefEnable)
581: return;
582:
583: KillTimer(ghwndApp, IDTIMER_ZOOMIN);
584: gfRefEnable = FALSE;
585: }
586: }
587:
588:
589:
590: /************************************************************************
591: * CopyToClipboard
592: *
593: * This function copies the client area image of the app into the
594: * clipboard.
595: *
596: * History:
597: *
598: ************************************************************************/
599:
600: VOID CopyToClipboard(VOID)
601: {
602: HDC hdcSrc;
603: HDC hdcDst;
604: RECT rc;
605: HBITMAP hbm;
606:
607: if (OpenClipboard(ghwndApp)) {
608: EmptyClipboard();
609:
610: if (hdcSrc = GetDC(ghwndApp)) {
611: GetClientRect(ghwndApp, &rc);
612: if (hbm = CreateCompatibleBitmap(hdcSrc,
613: rc.right - rc.left, rc.bottom - rc.top)) {
614: if (hdcDst = CreateCompatibleDC(hdcSrc)) {
615: /*
616: * Calculate the dimensions of the bitmap and
617: * convert them to tenths of a millimeter for
618: * setting the size with the SetBitmapDimensionEx
619: * call. This allows programs like WinWord to
620: * retrieve the bitmap and know what size to
621: * display it as.
622: */
623:
624:
625:
626:
627:
628:
629: SetBitmapDimensionEx(hbm, (DWORD)((INT)(((DWORD)(rc.right - rc.left) * MM10PERINCH) / (DWORD)GetDeviceCaps(hdcSrc, LOGPIXELSX))), (DWORD)((INT)(((DWORD)(rc.bottom - rc.top) * MM10PERINCH) / (DWORD)GetDeviceCaps(hdcSrc, LOGPIXELSY))), NULL);
630:
631: SelectObject(hdcDst, hbm);
632: BitBlt(hdcDst, 0, 0,
633: rc.right - rc.left, rc.bottom - rc.top,
634: hdcSrc, rc.left, rc.top, SRCCOPY);
635: DeleteDC(hdcDst);
636: SetClipboardData(CF_BITMAP, hbm);
637: }
638: else {
639: DeleteObject(hbm);
640: }
641: }
642:
643: ReleaseDC(ghwndApp, hdcSrc);
644: }
645:
646: CloseClipboard();
647: }
648: else {
649: MessageBeep(0);
650: }
651: }
652:
653:
654:
655: /************************************************************************
656: * AboutDlgProc
657: *
658: * This is the About Box dialog procedure.
659: *
660: * History:
661: *
662: ************************************************************************/
663:
664: BOOL APIENTRY AboutDlgProc(
665: HWND hwnd,
666: UINT msg,
667: WPARAM wParam,
668: LPARAM lParam)
669: {
670: switch (msg) {
671: case WM_INITDIALOG:
672: return TRUE;
673:
674: case WM_COMMAND:
675: EndDialog(hwnd, IDOK);
676: return TRUE;
677:
678: default:
679: return FALSE;
680: }
681: }
682:
683:
684:
685: /************************************************************************
686: * RefreshRateDlgProc
687: *
688: * This is the Refresh Rate dialog procedure.
689: *
690: * History:
691: *
692: ************************************************************************/
693:
694: BOOL APIENTRY RefreshRateDlgProc(
695: HWND hwnd,
696: UINT msg,
697: WPARAM wParam,
698: LPARAM lParam)
699: {
700: BOOL fTranslated;
701:
702: switch (msg) {
703: case WM_INITDIALOG:
704: SendDlgItemMessage(hwnd, DID_REFRESHRATEINTERVAL, EM_LIMITTEXT,
705: 3, 0L);
706: SetDlgItemInt(hwnd, DID_REFRESHRATEINTERVAL, gnRefInterval, FALSE);
707: CheckDlgButton(hwnd, DID_REFRESHRATEENABLE, gfRefEnable ? 1 : 0);
708: return TRUE;
709:
710: case WM_COMMAND:
711: switch (LOWORD(wParam)) {
712: case IDOK:
713: gnRefInterval = GetDlgItemInt(hwnd, DID_REFRESHRATEINTERVAL,
714: &fTranslated, FALSE);
715:
716: /*
717: * Stop any existing timers then start one with the
718: * new interval if requested to.
719: */
720: EnableRefresh(FALSE);
721: EnableRefresh(
722: IsDlgButtonChecked(hwnd, DID_REFRESHRATEENABLE));
723:
724: EndDialog(hwnd, IDOK);
725: break;
726:
727: case IDCANCEL:
728: EndDialog(hwnd, IDCANCEL);
729: break;
730: }
731:
732: break;
733: }
734:
735: return FALSE;
736: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.