|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: mfedit.c
3: *
4: * Main module for the Enhanced Metafile Editor
5: * contains everything
6: *
7: * Created: 28-May-1992 14:24:00
8: * Author: Petrus Wong
9: *
10: * Copyright (c) 1990 Microsoft Corporation
11: *
12: * The Enhanced Metafile Editor serves to demonstrate the enhanced metafile
13: * APIs in Windows NT.
14: *
15: * The Editor provides the following functions:
16: * 1. Playback and recording of GDI calls
17: * 2. Embedding bitmap and enhanced metafile into another enhanced
18: * metafile with transformation
19: * 3. Hit-testing against enhanced metafile records
20: * 4. Random access playback
21: * 5. Playback metafile records one-by-one
22: * 6. Selective recording of existing enhanced metafile records into
23: * a new enhanced metafile
24: * 7. drawing with pen, text, bezier, line, ellipse, rectangle and
25: * embedding bitmap and enhanced metafile tools
26: *
27: * Dependencies:
28: *
29: * metadef.h - contains definition for enhanced metafile records
30: *
31: \**************************************************************************/
32: #include <stdlib.h>
33: #include "mfedit.h"
34: #include <stdarg.h>
35: #include <string.h>
36: #include <stdio.h>
37: #include <commdlg.h>
38:
39: //
40: // Forward declarations.
41: //
42: BOOL InitializeApp (void);
43: LONG MainWndProc (HWND, UINT, DWORD, LONG);
44: LONG DrawSurfWndProc (HWND, UINT, DWORD, LONG);
45: LONG MDIWndProc (HWND, UINT, DWORD, LONG);
46: LONG About (HWND, UINT, DWORD, LONG);
47: LONG TextWndProc (HWND, UINT, DWORD, LONG);
48: LONG CtrlPanelDlgProc(HWND, UINT, DWORD, LONG);
49: BOOL bDrawStuff (HDC, INT, INT, INT, INT, BOOL, BOOL, BOOL, LPSTR);
50: HENHMETAFILE hemfLoadMetafile(HWND);
51: HDC hDCRecordMetafileAs(HWND, LPSTR);
52: BOOL APIENTRY bPlayRecord(HDC, LPHANDLETABLE, LPENHMETARECORD, UINT, LPVOID);
53: BOOL APIENTRY bDoHitTest(HDC, LPHANDLETABLE, LPENHMETARECORD, UINT, LPVOID);
54: BOOL bHitTest(HDC, INT, INT);
55: HBITMAP hBmpLoadBitmapFile(HDC, PSTR);
56: BOOL bGetBMP(HWND, BOOL);
57: BOOL bChooseNewFont(HWND, PLOGFONT, COLORREF * );
58: BOOL bChooseNewColor(HWND, LPDWORD);
59: HBRUSH hBrCreateBrush(HDC, DWORD);
60:
61: /***************************************************************************\
62: * WinMain
63: *
64: * History:
65: * 11-Feb-1992 Petrus Wong
66: \***************************************************************************/
67: int WinMain(
68: HANDLE hInstance,
69: HANDLE hPrevInstance,
70: LPSTR lpCmdLine,
71: int nShowCmd)
72: {
73: MSG msg;
74: HANDLE hAccel;
75:
76: ghModule = GetModuleHandle(NULL);
77: if (!InitializeApp()) {
78: MessageBox(ghwndMain, "MfEdit: InitializeApp failure!", "Error", MB_OK);
79: return 0;
80: }
81:
82: if (!(hAccel = LoadAccelerators (ghModule, MAKEINTRESOURCE(ACCEL_ID))))
83: MessageBox(ghwndMain, "MfEdit: Load Accel failure!", "Error", MB_OK);
84:
85:
86: while (GetMessage(&msg, NULL, 0, 0)) {
87: if (!TranslateAccelerator( ghwndMain, hAccel, &msg) ) {
88: TranslateMessage(&msg);
89: DispatchMessage(&msg);
90: }
91: }
92:
93: return 1;
94:
95: UNREFERENCED_PARAMETER(lpCmdLine);
96: UNREFERENCED_PARAMETER(nShowCmd);
97: UNREFERENCED_PARAMETER(hInstance);
98: UNREFERENCED_PARAMETER(hPrevInstance);
99: }
100:
101:
102: /***************************************************************************\
103: * InitializeApp
104: *
105: * History:
106: * 11-Feb-1992 Petrus Wong
107: * Name changes.
108: * 09-09-91 Petrus Wong Created.
109: \***************************************************************************/
110:
111: BOOL InitializeApp(void)
112: {
113: WNDCLASS wc;
114: int index;
115:
116: wc.style = CS_DBLCLKS;
117: wc.lpfnWndProc = (WNDPROC)MainWndProc;
118: wc.cbClsExtra = 0;
119: wc.cbWndExtra = sizeof(DWORD);
120: wc.hInstance = ghModule;
121: wc.hIcon = LoadIcon(ghModule, MAKEINTRESOURCE(APPICON));
122: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
123: wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
124: wc.lpszMenuName = "MainMenu";
125: wc.lpszClassName = "MetafDemoClass";
126:
127: if (!RegisterClass(&wc))
128: return FALSE;
129:
130: wc.style = CS_OWNDC | CS_SAVEBITS;
131: wc.lpfnWndProc = (WNDPROC)DrawSurfWndProc;
132: wc.hIcon = NULL;
133: wc.hCursor = NULL;
134: wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
135: wc.lpszMenuName = NULL;
136: wc.lpszClassName = "DrawSurfClass";
137:
138: if (!RegisterClass(&wc))
139: return FALSE;
140:
141: wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
142: wc.lpfnWndProc = (WNDPROC)TextWndProc;
143: wc.hIcon = NULL;
144: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
145: wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
146: wc.lpszMenuName = NULL;
147: wc.lpszClassName = "Text";
148:
149: if (!RegisterClass(&wc))
150: return FALSE;
151:
152:
153:
154: hMenu = LoadMenu(ghModule, "MainMenu");
155:
156: for (index = 0; index < OD_BTN_CNT; index++) {
157: ghBmpDn[index] = (PVOID)LoadBitmap(ghModule, (LPCSTR)MAKEINTRESOURCE(BMID_BASED+index));
158: ghBmpUp[index] = (PVOID)LoadBitmap(ghModule, (LPCSTR)MAKEINTRESOURCE(BMID_BASEU+index));
159: }
160: for (index = 0; index < OD_TOOL_CNT; index++) {
161: ghToolBmpDn[index] = (PVOID)LoadBitmap(ghModule, (LPCSTR)MAKEINTRESOURCE(BMID_TOOLBASED+index));
162: ghToolBmpUp[index] = (PVOID)LoadBitmap(ghModule, (LPCSTR)MAKEINTRESOURCE(BMID_TOOLBASEU+index));
163:
164: }
165:
166: ghwndMain = CreateWindowEx(0L, "MetafDemoClass", "Enhanced Metafile Editor",
167: WS_OVERLAPPED | WS_CAPTION | WS_BORDER |
168: WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX |
169: WS_CLIPCHILDREN | WS_VISIBLE | WS_SYSMENU,
170: 80, 70, 600, 300,
171: NULL, hMenu, ghModule, NULL);
172:
173: if (ghwndMain == NULL)
174: return FALSE;
175:
176: SetWindowLong(ghwndMain, GWL_USERDATA, 0L);
177:
178: SetFocus(ghwndMain); /* set initial focus */
179:
180: return TRUE;
181: }
182:
183:
184: /***************************************************************************\
185: * MainWndProc
186: *
187: * History:
188: * 11-Feb-1992 Petrus Wong
189: * Name changes. Added comments.
190: * 09-09-91 Petrus Wong Created.
191: \***************************************************************************/
192:
193: long MainWndProc(
194: HWND hwnd,
195: UINT message,
196: DWORD wParam,
197: LONG lParam)
198: {
199: static int iMetafCnt=0;
200: static char szFilename[256] = "c:\\metaf";
201: static BOOL bReset=FALSE;
202:
203: switch (message) {
204:
205: case WM_CREATE: {
206:
207: SetWindowLong(hwnd, 0, (LONG)NULL);
208: ghDCMem = CreateCompatibleDC(NULL);
209:
210: ghwndCtrlPanel = CreateDialog(ghModule, (LPCSTR)MAKEINTRESOURCE(DID_CTRLPANEL),
211: hwnd, (DLGPROC) CtrlPanelDlgProc);
212:
213: ghwndDrawSurf = CreateWindow("DrawSurfClass", NULL,
214: WS_BORDER | WS_CHILD | WS_VISIBLE,
215: 0, 0, 0, 0,
216: hwnd,
217: NULL,
218: ghModule,
219: NULL);
220:
221: ghTextWnd = CreateWindow("Text", NULL,
222: WS_BORDER | SS_LEFT | WS_CHILD | WS_VISIBLE,
223: 0, 0, 0, 0,
224: hwnd,
225: NULL, //(HMENU) 2,
226: ghModule,
227: NULL);
228:
229: ghbrRed = CreateSolidBrush(RGB(255, 0, 0));
230: ghbrAppBkgd = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
231: ghpnWide = CreatePen(PS_SOLID, 5, RGB(0, 0, 0));
232: return 0L;
233: }
234:
235: case WM_SIZE: {
236: RECT rc;
237: LONG lcyCtrlPanel, lcyDrawSurf;
238:
239: GetWindowRect(ghwndCtrlPanel, &rc);
240: lcyCtrlPanel = rc.bottom-rc.top;
241: lcyDrawSurf = HIWORD(lParam) - lcyCtrlPanel - glcyStatus;
242:
243: //
244: // CR!! Alternatively, this window can be created with cy
245: // equals to cy of the screen and saving this call
246: // altogether.
247: //
248: MoveWindow(ghwndCtrlPanel,
249: 0, 0, LOWORD(lParam), lcyCtrlPanel, TRUE);
250:
251: //
252: // This ordering guarantees the text window paints correctly
253: //
254: MoveWindow(ghTextWnd,
255: 0, lcyCtrlPanel + lcyDrawSurf,
256: LOWORD(lParam), // cx of hwnd
257: glcyStatus, TRUE);
258:
259: MoveWindow(ghwndDrawSurf,
260: 0, lcyCtrlPanel,
261: LOWORD(lParam), // cx of hwnd
262: lcyDrawSurf, TRUE);
263: break;
264: }
265:
266: case WM_DESTROY: {
267: DeleteDC(ghDCMem);
268: DeleteEnhMetaFile(ghMetaf);
269: DestroyWindow(ghwndCtrlPanel);
270: DeleteObject(ghbrRed);
271: DeleteObject(ghbrCur);
272: DeleteObject(ghpnCur);
273: DeleteObject(ghbrAppBkgd);
274: DeleteObject(ghpnWide);
275: PostQuitMessage(0);
276: return 0L;
277: }
278:
279: case WM_COMMAND: {
280: static int iPlus=0;
281:
282: switch (LOWORD(wParam)) {
283: case DID_ZERO:
284: case DID_ONE:
285: case DID_TWO:
286: case DID_THREE:
287: case DID_FOUR:
288: case DID_FIVE:
289: case DID_SIX:
290: case DID_SEVEN:
291: case DID_EIGHT:
292: case DID_NINE: {
293: HDC hDCDrawSurf;
294: ENHMETAHEADER EnhMetaHdr;
295: //RECT rcClientDS;
296: int iRecord;
297: PLAYINFO PlayInfo;
298:
299: if (ghMetaf == 0)
300: return 0L;
301:
302: GetEnhMetaFileHeader(ghMetaf, sizeof(EnhMetaHdr), &EnhMetaHdr);
303: iRecord = LOWORD(wParam) - DID_ZERO + iPlus;
304: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, iRecord, FALSE);
305: PlayInfo.iRecord = iRecord;
306: PlayInfo.bPlayContinuous = FALSE;
307: iPlus = 0;
308:
309: if ((EnhMetaHdr.nRecords > 1) && (iRecord > 0) &&
310: (iRecord <= (INT) EnhMetaHdr.nRecords)) {
311: //!!!GetClientRect(ghwndDrawSurf, &rcClientDS);
312: hDCDrawSurf = GetDC(ghwndDrawSurf);
313: //!!!EnumEnhMetaFile(hDCDrawSurf, ghMetaf, (PROC)bPlayRecord, (LPVOID) &PlayInfo, &rcClientDS);
314: EnumEnhMetaFile(hDCDrawSurf, ghMetaf, (PROC)bPlayRecord, (LPVOID) &PlayInfo, (LPRECT)&EnhMetaHdr.rclBounds);
315: //
316: // Enabling the user to record a metafile record selectively
317: //
318: if ((gbRecording) && (ghDCMetaf != NULL))
319: EnumEnhMetaFile(ghDCMetaf, ghMetaf, (PROC)bPlayRecord, (LPVOID) &PlayInfo, (LPRECT)&EnhMetaHdr.rclBounds);
320: ReleaseDC(ghwndDrawSurf, hDCDrawSurf);
321: }
322: return 0L;
323: }
324: case DID_TEN_PLUS: {
325: if (ghMetaf == 0)
326: return 0L;
327:
328: iPlus += 10;
329: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, iPlus, FALSE);
330: return 0L;
331: }
332: case MM_PRINT:
333: case MM_PAGESETUP:
334: case MM_PRINTSETUP:
335: case MM_CUT:
336: case MM_COPY:
337: case MM_PASTE:
338: case MM_DEL:
339: return 0L;
340: case MM_PEN: {
341: HDC hDC;
342: DWORD dwRGB;
343:
344: if (bChooseNewColor(hwnd, &dwRGB)) {
345: hDC = GetDC(ghwndDrawSurf);
346: if (ghpnCur != NULL)
347: DeleteObject(ghpnCur);
348: ghpnCur = CreatePen(PS_SOLID, 1, dwRGB);
349: SelectObject(hDC, ghpnCur);
350: if (ghDCMetaf != NULL)
351: SelectObject(ghDCMetaf, ghpnCur);
352: ReleaseDC(ghwndDrawSurf, hDC);
353: }
354: return 0L;
355: }
356: case MM_BRUSH: {
357: HDC hDC;
358: static DWORD dwRGB=RGB(255, 255, 255);
359:
360: if (bChooseNewColor(hwnd, &dwRGB)) {
361: hDC = GetDC(ghwndDrawSurf);
362: if (ghbrCur != NULL)
363: DeleteObject(ghbrCur);
364: ghbrCur = hBrCreateBrush(hDC, dwRGB);
365: SelectObject(hDC, ghbrCur);
366: if (ghDCMetaf != NULL)
367: SelectObject(ghDCMetaf, ghbrCur);
368: ReleaseDC(ghwndDrawSurf, hDC);
369: }
370: return 0L;
371: }
372: case MM_FONT: {
373: if (bChooseNewFont(ghwndMain, &glf, &gCrText)) {
374: ghCurFont = CreateFontIndirect(&glf);
375: if (ghDCMetaf != NULL)
376: SelectObject(ghDCMetaf, ghCurFont);
377: }
378: return 0L;
379: }
380:
381: case MM_HITTEST: {
382: static BOOL bHitTest=FALSE;
383: HWND hwndRecBtn;
384:
385: bHitTest = (bHitTest ? FALSE : TRUE);
386: hwndRecBtn = GetDlgItem(ghwndCtrlPanel, DID_RECORD);
387: if (bHitTest) {
388: CheckMenuItem(hMenu, MM_HITTEST, MF_CHECKED);
389: EnableMenuItem(hMenu, MM_RECORD, MF_GRAYED);
390: EnableWindow(hwndRecBtn, FALSE);
391: gbHitTest = TRUE;
392: } else {
393: CheckMenuItem(hMenu, MM_HITTEST, MF_UNCHECKED);
394: EnableMenuItem(hMenu, MM_RECORD, MF_ENABLED);
395: EnableWindow(hwndRecBtn, TRUE);
396: gbHitTest = FALSE;
397: return 0L;
398: }
399:
400: if (ghMetaf == 0) {
401: SetWindowText(ghTextWnd, "No Metafile loaded for hit-testing");
402: return 0L;
403: }
404: return 0L;
405: }
406: case MM_ABOUT:
407: if (DialogBox(ghModule, (LPCSTR)"AboutBox", ghwndMain, (DLGPROC)About) == -1)
408: MessageBox(ghwndMain, "DEMO: About Dialog Creation Error!", "Error", MB_OK);
409: return 0L;
410:
411: case MM_LOAD_MASKBMP:
412: SetWindowText(ghTextWnd, "Load Mask Bitmap");
413: bGetBMP(hwnd, TRUE);
414: return 0L;
415:
416: case MM_LOAD_BMP:
417: SetWindowText(ghTextWnd, "Load Bitmap");
418: bGetBMP(hwnd, FALSE);
419: return 0L;
420:
421: case MM_SAVE_BMP:
422: SetWindowText(ghTextWnd, "Save Drawing Surface as Bitmap");
423: return 0L;
424:
425: case MM_LOAD:
426: case DID_OPEN: {
427: ENHMETAHEADER EnhMetaHdr;
428:
429: SetWindowText(ghTextWnd, "Load Metafile");
430: DeleteEnhMetaFile(ghMetaf);
431: ghMetaf = hemfLoadMetafile(hwnd);
432: if (ghMetaf != 0) {
433: GetEnhMetaFileHeader(ghMetaf, sizeof(EnhMetaHdr), &EnhMetaHdr);
434: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, EnhMetaHdr.nRecords, FALSE);
435: } else {
436: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, 0, FALSE);
437: }
438: bReset = TRUE;
439: return 0L;
440: }
441: case MM_RECORD:
442: if (gbHitTest) {
443: SetWindowText(ghTextWnd, "Please CANCEL Hit Testing Mode First!");
444: return 0L;
445: }
446:
447: SetWindowText(ghTextWnd, "Recording...");
448: if (!gbRecording) {
449: ghDCMetaf = hDCRecordMetafileAs(hwnd, szFilename);
450: }
451:
452: if (ghDCMetaf == NULL) {
453: SetWindowText(ghTextWnd, "ERROR: Failed in creating the metafile DC!");
454: return 0L;
455: }
456: gbRecording = TRUE;
457:
458: if (ghpnCur != NULL)
459: SelectObject(ghDCMetaf, ghpnCur);
460:
461: if (ghbrCur != NULL)
462: SelectObject(ghDCMetaf, ghbrCur);
463:
464: if (ghCurFont != NULL)
465: SelectObject(ghDCMetaf, ghCurFont);
466: return 0L;
467:
468: case DID_RECORD: {
469: char tmp[256];
470: char suffix[20];
471:
472: if (gbHitTest) {
473: SetWindowText(ghTextWnd, "Please CANCEL Hit Testing Mode First!");
474: return 0L;
475: }
476:
477: SetWindowText(ghTextWnd, "Recording...");
478: if (!gbRecording) {
479: wsprintf((LPSTR) suffix, "%d.emf", iMetafCnt);
480: iMetafCnt++;
481: strcpy(tmp, szFilename);
482: strcat(tmp, suffix);
483: ghDCMetaf = CreateEnhMetaFile((HDC)NULL, tmp, (LPRECT)NULL, (LPSTR)NULL);
484: }
485:
486: if (ghDCMetaf == NULL) {
487: SetWindowText(ghTextWnd, "ERROR: Failed in creating the metafile DC!");
488: return 0L;
489: }
490: gbRecording = TRUE;
491:
492: if (ghpnCur != NULL)
493: SelectObject(ghDCMetaf, ghpnCur);
494:
495: if (ghbrCur != NULL)
496: SelectObject(ghDCMetaf, ghbrCur);
497:
498: if (ghCurFont != NULL)
499: SelectObject(ghDCMetaf, ghCurFont);
500:
501: return 0L;
502: }
503: case DID_STOP:
504: SetWindowText(ghTextWnd, "Stop");
505: if (gbRecording) {
506: ghMetaf = CloseEnhMetaFile(ghDCMetaf);
507: gbRecording = FALSE;
508: }
509: return 0L;
510: case DID_PLAY: {
511: HDC hDCDrawSurf;
512: ENHMETAHEADER EnhMetaHdr;
513: //!!!RECT rcClientDS;
514:
515: SetWindowText(ghTextWnd, "Playing Metafile");
516: if (ghMetaf != NULL) {
517: hDCDrawSurf = GetDC(ghwndDrawSurf);
518: //!!!GetClientRect(ghwndDrawSurf, &rcClientDS);
519: GetEnhMetaFileHeader(ghMetaf, sizeof(ENHMETAHEADER), &EnhMetaHdr);
520: //!!!PlayEnhMetaFile( hDCDrawSurf, ghMetaf, (LPRECT) &rcClientDS);
521: PlayEnhMetaFile( hDCDrawSurf, ghMetaf, (LPRECT) &EnhMetaHdr.rclBounds);
522:
523: //
524: // Enabling the user to embed another metafile
525: //
526: if ((gbRecording) && (ghDCMetaf != NULL))
527: PlayEnhMetaFile( ghDCMetaf, ghMetaf, (LPRECT) &EnhMetaHdr.rclBounds);
528:
529: ReleaseDC(ghwndDrawSurf, hDCDrawSurf);
530: }
531: return 0L;
532: }
533: case DID_FF: {
534: HDC hDCDrawSurf;
535: ENHMETAHEADER EnhMetaHdr;
536: //!!!RECT rcClientDS;
537: static int iRecord = 0;
538: PLAYINFO PlayInfo;
539:
540: if (ghMetaf == 0)
541: return 0L;
542:
543: PlayInfo.iRecord = ++iRecord;
544: PlayInfo.bPlayContinuous = TRUE;
545:
546: GetEnhMetaFileHeader(ghMetaf, sizeof(EnhMetaHdr), &EnhMetaHdr);
547: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, iRecord, FALSE);
548: if ((EnhMetaHdr.nRecords > 1) && (iRecord <= (INT)EnhMetaHdr.nRecords)) {
549: //!!!GetClientRect(ghwndDrawSurf, &rcClientDS);
550: hDCDrawSurf = GetDC(ghwndDrawSurf);
551: //!!!EnumEnhMetaFile(hDCDrawSurf, ghMetaf, (PROC)bPlayRecord, (LPVOID) &PlayInfo, (LPRECT) &rcClientDS);
552: EnumEnhMetaFile(hDCDrawSurf, ghMetaf, (PROC)bPlayRecord, (LPVOID) &PlayInfo, (LPRECT) &EnhMetaHdr.rclBounds);
553:
554: //
555: // Enabling the user to record a metafile records selectively
556: //
557: if ((gbRecording) && (ghDCMetaf != NULL))
558: EnumEnhMetaFile(ghDCMetaf, ghMetaf, (PROC)bPlayRecord, (LPVOID) &PlayInfo, (LPRECT)&EnhMetaHdr.rclBounds);
559:
560: ReleaseDC(ghwndDrawSurf, hDCDrawSurf);
561: }
562:
563: if ((iRecord == (INT) EnhMetaHdr.nRecords) || bReset) {
564: iRecord = 0;
565: if (bReset)
566: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, 0, FALSE);
567: bReset = FALSE;
568: }
569:
570: return 0L;
571: }
572: case DID_CLEAR: {
573: HDC hDCDrawSurf;
574: HGDIOBJ hObjOld;
575: RECT rcDrawSurf;
576:
577: SetWindowText(ghTextWnd, "Drawing Surface cleared");
578: hDCDrawSurf = GetDC(ghwndDrawSurf);
579: ghbrAppBkgd = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
580: hObjOld = SelectObject(hDCDrawSurf, ghbrAppBkgd);
581: GetClientRect(ghwndDrawSurf, &rcDrawSurf);
582: PatBlt(hDCDrawSurf, 0, 0, rcDrawSurf.right, rcDrawSurf.bottom, PATCOPY);
583: ReleaseDC(ghwndDrawSurf, hDCDrawSurf);
584: SelectObject(hDCDrawSurf, hObjOld);
585: return 0L;
586: }
587:
588: case DID_PEN:
589: SetWindowText(ghTextWnd, "Pen");
590: return 0L;
591: case DID_TEXT:
592: SetWindowText(ghTextWnd, "Text");
593: return 0L;
594: case DID_RECT:
595: SetWindowText(ghTextWnd, "Rectangle");
596: return 0L;
597: case DID_FILLRECT:
598: SetWindowText(ghTextWnd, "Filled Rectangle");
599: return 0L;
600: case DID_ELLIPSE:
601: SetWindowText(ghTextWnd, "Ellipse");
602: return 0L;
603: case DID_FILLELLIPSE:
604: SetWindowText(ghTextWnd, "Filled Ellipse");
605: return 0L;
606: case DID_LINE:
607: SetWindowText(ghTextWnd, "Line");
608: return 0L;
609: case DID_BEZIER:
610: SetWindowText(ghTextWnd,
611: "Bezier: Click with Left button for placing control points");
612: return 0L;
613: case DID_BMPOBJ:
614: SetWindowText(ghTextWnd,
615: "Bitmap: Click three points for the destination of the bitmap");
616: return 0L;
617: case DID_METAF:
618: SetWindowText(ghTextWnd,
619: "External Metafile: Click three points for the destination of the Metafile");
620: return 0L;
621: default:
622: return DefWindowProc(hwnd, message, wParam, lParam);
623: }
624: } // WM_COMMAND
625: default:
626: return DefWindowProc(hwnd, message, wParam, lParam);
627: }
628: }
629:
630: /******************************Public*Routine******************************\
631: *
632: * DrawSurfWndProc
633: * Drawing surface window procedure
634: *
635: * Effects: Trapping all mouse messages and call the DrawStuff appropriately
636: * for drawing to the drawing surface DC and metafile DC as needed.
637: *
638: * Warnings:
639: *
640: * History:
641: * 30-Apr-1992 -by- Petrus Wong
642: * Wrote it.
643: \**************************************************************************/
644:
645: long DrawSurfWndProc(
646: HWND hwnd,
647: UINT message,
648: DWORD wParam,
649: LONG lParam)
650: {
651: static BOOL bTrack = FALSE;
652: static int OrgX, OrgY;
653: static int PrevX, PrevY;
654: static HDC hDC;
655: static HCURSOR hCurArrow, hCurHT;
656:
657: switch (message) {
658: case WM_CREATE:
659: {
660: RECT rect;
661:
662: GetClientRect(GetParent(hwnd), &rect);
663:
664: SetWindowPos(hwnd, NULL,
665: 0,
666: 30,
667: rect.right-rect.left,
668: rect.bottom-rect.top-30,
669: SWP_NOZORDER | SWP_NOMOVE);
670:
671: CreateCaret(hwnd, NULL, 1, 12);
672: ghCurFont = GetStockObject(SYSTEM_FONT);
673: GetObject(ghCurFont, sizeof(LOGFONT), &glf);
674: hCurArrow = LoadCursor(NULL, IDC_ARROW);
675: hCurHT = LoadCursor(NULL, IDC_CROSS);
676: break;
677: }
678:
679: case WM_LBUTTONDOWN: {
680: int x, y;
681:
682: x = (int) LOWORD(lParam);
683: y = (int) HIWORD(lParam);
684:
685: if (gbHitTest) {
686: hDC = GetDC(hwnd);
687: bHitTest(hDC, x, y);
688: ReleaseDC(hwnd, hDC);
689: break;
690: }
691:
692: bTrack = TRUE;
693: OrgX = PrevX = x;
694: OrgY = PrevY = y;
695:
696: hDC = GetDC(hwnd);
697: SetCapture(hwnd);
698: break;
699: }
700:
701: case WM_MOUSEMOVE: {
702: RECT rectClient;
703: int NextX;
704: int NextY;
705:
706: if (gbHitTest) {
707: SetCursor(hCurHT);
708: } else {
709: SetCursor(hCurArrow);
710: }
711:
712: // Update the selection region
713: if (bTrack) {
714: NextX = (SHORT) LOWORD(lParam);
715: NextY = (SHORT) HIWORD(lParam);
716:
717: // Do not draw outside the window's client area
718:
719: GetClientRect (hwnd, &rectClient);
720: if (NextX < rectClient.left) {
721: NextX = rectClient.left;
722: } else if (NextX >= rectClient.right) {
723: NextX = rectClient.right - 1;
724: }
725: if (NextY < rectClient.top) {
726: NextY = rectClient.top;
727: } else if (NextY >= rectClient.bottom) {
728: NextY = rectClient.bottom - 1;
729: }
730: if ((NextX != PrevX) || (NextY != PrevY)) {
731: SetROP2(hDC, R2_NOT); // Erases the previous box
732: bDrawStuff(hDC, OrgX, OrgY, PrevX, PrevY, TRUE, TRUE, FALSE, NULL);
733:
734: //
735: // Optimization. Do not record in metafile DC if it is going
736: // to be erased. So only call bDrawStuff with the PEN tool.
737: //
738: if (gbRecording && (ghDCMetaf != NULL) && (gdwCurTool == DID_PEN)) {
739: bDrawStuff(ghDCMetaf, OrgX, OrgY, PrevX, PrevY, TRUE, TRUE, FALSE, NULL);
740: }
741:
742:
743: // Get the current mouse position
744: PrevX = NextX;
745: PrevY = NextY;
746:
747: //
748: // SetROP2(hDC, R2_COPYPEN);
749: // This is commented out because we don't want to erase
750: // the background as it sweeps.
751: //
752: bDrawStuff(hDC, OrgX, OrgY, PrevX, PrevY, FALSE, TRUE, FALSE, NULL);
753:
754: if (gbRecording && (ghDCMetaf != NULL) && (gdwCurTool == DID_PEN)) {
755: bDrawStuff(ghDCMetaf, OrgX, OrgY, PrevX, PrevY, FALSE, TRUE, FALSE, NULL);
756: }
757:
758: }
759: }
760: break;
761:
762: }
763:
764: case WM_LBUTTONUP: {
765: int NextX;
766: int NextY;
767:
768: if (!bTrack)
769: break;
770:
771: // End the selection
772: ReleaseCapture();
773: bTrack = FALSE;
774:
775: // Erases the box
776: //
777: // SetROP2(hDC, R2_NOT);
778: // This is assumed to be R2_NOT, thus unnecessary
779: //
780: bDrawStuff(hDC, OrgX, OrgY, PrevX, PrevY, TRUE, FALSE, FALSE, NULL);
781:
782: if (gbRecording && (ghDCMetaf != NULL) && (gdwCurTool == DID_PEN)) {
783: bDrawStuff(ghDCMetaf, OrgX, OrgY, PrevX, PrevY, TRUE, FALSE, FALSE, NULL);
784: }
785:
786: NextX = LOWORD(lParam);
787: NextY = HIWORD(lParam);
788:
789: // Draws the new box
790: SetROP2(hDC, R2_COPYPEN);
791: bDrawStuff(hDC, OrgX, OrgY, NextX, NextY, FALSE, FALSE, TRUE, NULL);
792:
793: ReleaseDC(hwnd, hDC);
794:
795: if (gbRecording && (ghDCMetaf != NULL)) {
796: bDrawStuff(ghDCMetaf, OrgX, OrgY, NextX, NextY, FALSE, FALSE, FALSE, NULL);
797: }
798:
799: break;
800: } // case WM_LBUTTONUP
801:
802: case WM_CHAR: {
803:
804: if (gdwCurTool != DID_TEXT)
805: break;
806:
807: hDC = GetDC(hwnd);
808: bDrawStuff(hDC, 0, 0, 0, 0, TRUE, FALSE, FALSE, (LPSTR)&wParam);
809: ReleaseDC(hwnd, hDC);
810:
811: if (gbRecording && (ghDCMetaf != NULL)) {
812: bDrawStuff(ghDCMetaf, 0, 0, 0, 0, TRUE, FALSE, FALSE, (LPSTR)&wParam);
813: }
814:
815: break;
816: }
817:
818: case WM_DESTROY: {
819: DestroyCaret();
820: DeleteObject(ghCurFont);
821: PostQuitMessage(0);
822: return 0L;
823: }
824:
825: default:
826: return DefWindowProc(hwnd, message, wParam, lParam);
827: }
828: }
829:
830:
831: /***************************************************************************\
832: * About
833: *
834: * About dialog proc.
835: *
836: * History:
837: * 09-09-91 Petrus Wong Rewrote.
838: * 04-13-91 ???? Created.
839: \***************************************************************************/
840:
841: long About(
842: HWND hDlg,
843: UINT message,
844: DWORD wParam,
845: LONG lParam)
846: {
847: switch (message) {
848: case WM_INITDIALOG:
849: return TRUE;
850:
851: case WM_COMMAND:
852: if (wParam == IDOK)
853: EndDialog(hDlg, wParam);
854: break;
855: }
856:
857: return FALSE;
858:
859: UNREFERENCED_PARAMETER(lParam);
860: UNREFERENCED_PARAMETER(hDlg);
861: }
862:
863: /***************************************************************************\
864: *
865: * TextWndProc
866: *
867: * Text Window procedure for displaying miscellaneous messages to user.
868: *
869: * History:
870: * 10-07-91 Petrus Wong
871: * 3D text output
872: *
873: \***************************************************************************/
874:
875: LONG TextWndProc (HWND hwnd, UINT message, DWORD wParam, LONG lParam)
876: {
877: static HFONT hFont = (HFONT) NULL;
878:
879: switch (message)
880: {
881: case WM_CREATE:
882: {
883: LOGFONT lf;
884: HDC hDC;
885: HFONT hOldFont;
886: TEXTMETRIC tm;
887: //RECT rect;
888:
889: SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (PVOID) &lf, (UINT)FALSE);
890:
891: hDC = GetDC(hwnd);
892: // this is the height for 8 point size font in pixels
893: lf.lfHeight = 8 * GetDeviceCaps(hDC, LOGPIXELSY) / 72;
894:
895: hFont = CreateFontIndirect(&lf);
896: hOldFont = SelectObject(hDC, hFont);
897: GetTextMetrics(hDC, &tm);
898:
899: // base the height of the window on size of text
900: glcyStatus = tm.tmHeight+6*GetSystemMetrics(SM_CYBORDER)+2;
901: ReleaseDC(hwnd, hDC);
902: break;
903: }
904:
905: case WM_DESTROY:
906: if (hFont)
907: DeleteObject(hFont);
908: break;
909:
910: case WM_SETTEXT:
911: DefWindowProc(hwnd, message, wParam, lParam);
912: InvalidateRect(hwnd,NULL,FALSE);
913: UpdateWindow(hwnd);
914: return 0L;
915:
916: case WM_PAINT:
917: {
918: PAINTSTRUCT ps;
919: RECT rc;
920: char ach[128];
921: int len, nxBorder, nyBorder;
922: HFONT hOldFont = NULL;
923:
924: BeginPaint(hwnd, &ps);
925:
926: GetClientRect(hwnd,&rc);
927:
928: nxBorder = GetSystemMetrics(SM_CXBORDER);
929: rc.left += 9*nxBorder;
930: rc.right -= 9*nxBorder;
931:
932: nyBorder = GetSystemMetrics(SM_CYBORDER);
933: rc.top += 3*nyBorder;
934: rc.bottom -= 3*nyBorder;
935:
936: // 3D Text
937: len = GetWindowText(hwnd, ach, sizeof(ach));
938: SetBkColor(ps.hdc, GetSysColor(COLOR_BTNFACE));
939:
940: SetBkMode(ps.hdc, TRANSPARENT);
941: SetTextColor(ps.hdc, RGB(64,96,96));
942: if (hFont)
943: hOldFont = SelectObject(ps.hdc, hFont);
944: ExtTextOut(ps.hdc, rc.left+2*nxBorder+2, rc.top+2, ETO_OPAQUE | ETO_CLIPPED,
945: &rc, ach, len, NULL);
946:
947: SetTextColor(ps.hdc, RGB(128,128,128));
948: if (hFont)
949: hOldFont = SelectObject(ps.hdc, hFont);
950: ExtTextOut(ps.hdc, rc.left+2*nxBorder+1, rc.top+1, ETO_CLIPPED,
951: &rc, ach, len, NULL);
952:
953: SetTextColor(ps.hdc, RGB(255,255,255));
954: if (hFont)
955: hOldFont = SelectObject(ps.hdc, hFont);
956: ExtTextOut(ps.hdc, rc.left+2*nxBorder, rc.top, ETO_CLIPPED,
957: &rc, ach, len, NULL);
958:
959: SetBkMode(ps.hdc, OPAQUE);
960:
961: if (hOldFont)
962: SelectObject(ps.hdc, hOldFont);
963:
964: EndPaint(hwnd, &ps);
965: return 0L;
966: }
967: }
968: return DefWindowProc(hwnd, message, wParam, lParam);
969: }
970:
971: /******************************Public*Routine******************************\
972: *
973: * CtrlPanelDlgProc
974: * The Control Panel dialog procedure
975: *
976: * Effects: Responsible for drawing the owner draw buttons. Notifying
977: * parent of user's action.
978: *
979: * Warnings:
980: *
981: * History:
982: * 27-May-1992 -by- Petrus Wong
983: * Wrote it.
984: \**************************************************************************/
985:
986: LONG CtrlPanelDlgProc(HWND hwnd, UINT msg, DWORD dwParam, LONG lParam)
987: {
988: switch (msg) {
989: case WM_INITDIALOG: {
990: int index;
991:
992: for (index = 0; index < OD_BTN_CNT; index++) {
993: grHwndCtrlBtn[index] = (PVOID)GetDlgItem(hwnd, (INT)(ID_OD_BTN_BASE+index));
994: }
995: for (index = 0; index < OD_TOOL_CNT; index++) {
996: grHwndToolBtn[index] = (PVOID)GetDlgItem(hwnd, (INT)(ID_OD_TOOL_BASE+index));
997: }
998: return TRUE;
999: }
1000:
1001: case WM_DRAWITEM: {
1002: PDRAWITEMSTRUCT pDIS = (PDRAWITEMSTRUCT) lParam;
1003: HBITMAP hBmpOld;
1004: BITMAP bm;
1005: HANDLE hCtl;
1006: HDC hDCCtl;
1007:
1008: if (pDIS->CtlID == gdwCurCtrl) {
1009: GetObject((HBITMAP) ghBmpDn[pDIS->CtlID - ID_OD_BTN_BASE], sizeof(BITMAP), (LPSTR)&bm);
1010: hBmpOld = SelectObject(ghDCMem, (HBITMAP) ghBmpDn[pDIS->CtlID - ID_OD_BTN_BASE]);
1011: }
1012:
1013: if (pDIS->CtlID == gdwCurTool) {
1014: GetObject((HBITMAP)ghToolBmpDn[pDIS->CtlID - ID_OD_TOOL_BASE], sizeof(BITMAP), (LPSTR)&bm);
1015: hBmpOld = SelectObject(ghDCMem, (HBITMAP)ghToolBmpDn[pDIS->CtlID - ID_OD_TOOL_BASE]);
1016: }
1017:
1018: if ((pDIS->CtlID < ID_OD_TOOL_BASE) && (pDIS->CtlID != gdwCurCtrl)) {
1019: GetObject((HBITMAP)ghBmpUp[pDIS->CtlID - ID_OD_BTN_BASE], sizeof(BITMAP), (LPSTR)&bm);
1020: hBmpOld = SelectObject(ghDCMem, (HBITMAP)ghBmpUp[pDIS->CtlID - ID_OD_BTN_BASE]);
1021: }
1022:
1023: if ((pDIS->CtlID >= ID_OD_TOOL_BASE) && (pDIS->CtlID != gdwCurTool)) {
1024: GetObject((HBITMAP)ghToolBmpUp[pDIS->CtlID - ID_OD_TOOL_BASE], sizeof(BITMAP), (LPSTR)&bm);
1025: hBmpOld = SelectObject(ghDCMem, (HBITMAP)ghToolBmpUp[pDIS->CtlID - ID_OD_TOOL_BASE]);
1026: }
1027:
1028: //
1029: // pDIS->hDC is clipped to the update region but unfortunately
1030: // that doesn't work well with StretchBlt. StretchBlt is used
1031: // because I don't have to make sure that the bitmap size is
1032: // exactly the same as the size of the button.
1033: //
1034: hCtl = GetDlgItem(hwnd, pDIS->CtlID);
1035: hDCCtl = GetDC(hCtl);
1036: StretchBlt(hDCCtl, //pDIS->hDC,
1037: pDIS->rcItem.left, pDIS->rcItem.top,
1038: pDIS->rcItem.right - pDIS->rcItem.left,
1039: pDIS->rcItem.bottom - pDIS->rcItem.top,
1040: ghDCMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
1041: ReleaseDC(hCtl, hDCCtl);
1042: SelectObject(ghDCMem, hBmpOld);
1043: break;
1044: }
1045:
1046: case WM_COMMAND: {
1047: DWORD dwOldCtrl = gdwCurCtrl;
1048: DWORD dwOldTool = gdwCurTool;
1049:
1050: switch (dwParam) {
1051: case DID_ONE:
1052: case DID_TWO:
1053: case DID_THREE:
1054: case DID_FOUR:
1055: case DID_FIVE:
1056: case DID_SIX:
1057: case DID_SEVEN:
1058: case DID_EIGHT:
1059: case DID_NINE:
1060: case DID_ZERO:
1061: case DID_TEN_PLUS:
1062: //SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, dwParam - DID_ZERO, FALSE);
1063: SendMessage(ghwndMain, WM_COMMAND, dwParam, lParam);
1064: break;
1065: case DID_OPEN:
1066: case DID_RECORD:
1067: case DID_STOP:
1068: case DID_PLAY:
1069: case DID_FF:
1070: SendMessage(ghwndMain, WM_COMMAND, dwParam, lParam);
1071: gdwCurCtrl = dwParam;
1072: InvalidateRect((HWND)grHwndCtrlBtn[dwOldCtrl - ID_OD_BTN_BASE], NULL, FALSE);
1073: InvalidateRect((HWND)grHwndCtrlBtn[gdwCurCtrl - ID_OD_BTN_BASE], NULL, FALSE);
1074: break;
1075: case DID_CLEAR:
1076: SendMessage(ghwndMain, WM_COMMAND, dwParam, lParam);
1077: break;
1078: case DID_TEXT:
1079: case DID_PEN:
1080: case DID_RECT:
1081: case DID_FILLRECT:
1082: case DID_ELLIPSE:
1083: case DID_FILLELLIPSE:
1084: case DID_LINE:
1085: case DID_BEZIER:
1086: case DID_BMPOBJ:
1087: case DID_METAF:
1088: SendMessage(ghwndMain, WM_COMMAND, dwParam, lParam);
1089: gdwCurTool = dwParam;
1090: InvalidateRect((HWND)grHwndToolBtn[dwOldTool - ID_OD_TOOL_BASE], NULL, FALSE);
1091: InvalidateRect((HWND)grHwndToolBtn[gdwCurTool - ID_OD_TOOL_BASE], NULL, FALSE);
1092: break;
1093: }
1094: break;
1095: }
1096:
1097:
1098: case WM_PAINT:
1099: {
1100: HDC hdc;
1101: RECT rc, rcDlg;
1102: PAINTSTRUCT ps;
1103: HPEN hpenWindowFrame, hpenDarkGray;
1104: int icyDlg;
1105: int icyBorder;
1106:
1107: icyBorder = GetSystemMetrics(SM_CYBORDER);
1108:
1109: GetWindowRect(hwnd, &rcDlg);
1110: icyDlg = rcDlg.right - rcDlg.left;
1111:
1112: /*
1113: * Draw our border lines.
1114: */
1115: GetClientRect(hwnd, &rc);
1116: hdc = BeginPaint(hwnd, &ps);
1117:
1118: SelectObject(hdc, GetStockObject(WHITE_PEN));
1119: MoveToEx(hdc, rc.left, rc.top, NULL);
1120: LineTo(hdc, rc.right, rc.top);
1121:
1122: hpenDarkGray = CreatePen(PS_SOLID, 1, DARKGRAY);
1123: SelectObject(hdc, hpenDarkGray);
1124: MoveToEx(hdc, rc.left, (rc.top + icyDlg) - icyBorder - 1, NULL);
1125: LineTo(hdc, rc.right, (rc.top + icyDlg) - icyBorder - 1);
1126:
1127: hpenWindowFrame = CreatePen(PS_SOLID, icyBorder,
1128: GetSysColor(COLOR_WINDOWFRAME));
1129: SelectObject(hdc, hpenWindowFrame);
1130: MoveToEx(hdc, rc.left, (rc.top + icyDlg) - icyBorder, NULL);
1131: LineTo(hdc, rc.right, (rc.top + icyDlg) - icyBorder);
1132:
1133: EndPaint(hwnd, &ps);
1134: DeleteObject(hpenWindowFrame);
1135: DeleteObject(hpenDarkGray);
1136: }
1137:
1138: break;
1139:
1140:
1141: //case WM_CTLCOLOR:
1142: case WM_CTLCOLORDLG:
1143: //case WM_CTLCOLORLISTBOX:
1144: //case WM_CTLCOLORSTATIC:
1145: switch (GET_WM_CTLCOLOR_TYPE(dwParam, lParam, msg)) {
1146: case CTLCOLOR_DLG:
1147: //case CTLCOLOR_LISTBOX:
1148: return (BOOL)GetStockObject(LTGRAY_BRUSH);
1149:
1150: //case CTLCOLOR_STATIC:
1151: // SetBkColor(GET_WM_CTLCOLOR_HDC(dwParam, lParam, msg),
1152: // LIGHTGRAY);
1153: // return (BOOL)GetStockObject(LTGRAY_BRUSH);
1154: }
1155: return (BOOL)NULL;
1156:
1157: default:
1158: return FALSE;
1159: }
1160:
1161: return FALSE;
1162: }
1163:
1164:
1165:
1166: /******************************Public*Routine******************************\
1167: *
1168: * bDrawStuff
1169: *
1170: * Effects: The drawing routines are localized here.
1171: * bErase is TRUE if this fcn is called for erasing previous object.
1172: * (as in tracking objects.) It is FALSE, otherwise.
1173: *
1174: * bMove is TRUE if this fcn is called inside the WM_MOUSEMOVE (as
1175: * in tracking objects.) It is FALSE, otherwise.
1176: *
1177: * bCntPt is TRUE if this fcn is to increment either the iCnt or
1178: * iCntMF counter (used only in processing metafile or bezier.)
1179: * It is FALSE, otherwise.
1180: *
1181: * lpstr contains the character to be drawn by TextOut when it is
1182: * not NULL.
1183: *
1184: * Warnings: Metafile and Bezier assume that the caller is calling this fcn
1185: * to draw in the screen DC first. Then draw it to the metafile DC.
1186: * Thus, when it is called to draw on the metafile DC, the points
1187: * would have been set already.
1188: *
1189: * History:
1190: * 10-May-1992 -by- Petrus Wong
1191: * Wrote it.
1192: \**************************************************************************/
1193:
1194: BOOL bDrawStuff(HDC hDC, INT OrgX, INT OrgY,
1195: INT NextX, INT NextY,
1196: BOOL bErase,
1197: BOOL bMove,
1198: BOOL bCntPt,
1199: LPSTR lpstr) {
1200: BOOL bSuccess;
1201: HGDIOBJ hObjOld;
1202: static POINT rgPts[MAX_POINTS], rgPtsMF[MAX_POINTS_MF], rgPtsBMP[MAX_POINTS_BMP];
1203: static int iCnt=0, iCntMF=0, iCntBMP=0;
1204: static BOOL bCaretShown=FALSE;
1205:
1206: bSuccess = TRUE;
1207: if (bCaretShown) {
1208: HideCaret(ghwndDrawSurf);
1209: bCaretShown = FALSE;
1210: }
1211:
1212: switch (gdwCurTool) {
1213: case DID_PEN:
1214: if (bErase) {
1215: MoveToEx(hDC, NextX, NextY, NULL);
1216: } else {
1217: //
1218: // Override the ROP2 st. the pen won't erase its track
1219: //
1220: SetROP2(hDC, R2_COPYPEN);
1221: LineTo(hDC, NextX, NextY);
1222: }
1223: break;
1224: case DID_TEXT: {
1225: POINT Pt;
1226:
1227: if (lpstr == NULL) {
1228: ShowCaret(ghwndDrawSurf);
1229: bCaretShown = TRUE;
1230: SetCaretPos(NextX, NextY);
1231: MoveToEx(hDC, NextX, NextY, NULL);
1232: SetFocus(ghwndDrawSurf);
1233: break;
1234: }
1235:
1236: SetTextAlign(hDC, TA_UPDATECP);
1237: hObjOld = SelectObject(hDC, ghCurFont);
1238: SetTextColor(hDC, gCrText);
1239: SetBkMode(hDC, TRANSPARENT);
1240: TextOut(hDC, 0, 0, lpstr, 1);
1241: SelectObject(hDC, hObjOld);
1242: GetCurrentPositionEx(hDC, (LPPOINT) &Pt);
1243: SetCaretPos(Pt.x, Pt.y+2);
1244: ShowCaret(ghwndDrawSurf);
1245: bCaretShown = TRUE;
1246:
1247: break;
1248: }
1249: case DID_RECT:
1250: hObjOld = SelectObject(hDC, GetStockObject(NULL_BRUSH));
1251: Rectangle(hDC, OrgX, OrgY, NextX, NextY);
1252: SelectObject(hDC, hObjOld);
1253: break;
1254: case DID_FILLRECT:
1255: Rectangle(hDC, OrgX, OrgY, NextX, NextY);
1256: break;
1257: case DID_ELLIPSE:
1258: hObjOld = SelectObject(hDC, GetStockObject(NULL_BRUSH));
1259: Ellipse(hDC, OrgX, OrgY, NextX, NextY);
1260: SelectObject(hDC, hObjOld);
1261: break;
1262: case DID_FILLELLIPSE:
1263: Ellipse(hDC, OrgX, OrgY, NextX, NextY);
1264: break;
1265: case DID_LINE:
1266: MoveToEx(hDC, OrgX, OrgY, NULL);
1267: LineTo(hDC, NextX, NextY);
1268: break;
1269: case DID_BEZIER:
1270: if (bErase || bMove)
1271: return bSuccess;
1272:
1273: if (bCntPt) {
1274: rgPts[iCnt].x = NextX;
1275: rgPts[iCnt].y = NextY;
1276: iCnt++;
1277:
1278: if (iCnt == MAX_POINTS - 1)
1279: iCnt = 0;
1280: }
1281:
1282: if ((iCnt % 3) == 1) { // (iCnt + 1) % 3 == 1
1283: //
1284: // Override the ROP2 st. the pen won't erase its track
1285: //
1286: SetROP2(hDC, R2_COPYPEN);
1287: PolyBezier(hDC, (LPPOINT)&rgPts, (DWORD) iCnt);
1288: }
1289: return bSuccess;
1290:
1291: case DID_BMPOBJ: {
1292: static BOOL bBltReady = FALSE;
1293: HDC hDCRef;
1294: HGDIOBJ hObjOld;
1295: BITMAP bm;
1296:
1297: if (bErase || bMove)
1298: return bSuccess;
1299:
1300: if (ghBmp == NULL) {
1301: SetWindowText(ghTextWnd, "ERROR: No bitmap to embed!");
1302: return bSuccess;
1303: }
1304:
1305: if (bCntPt) {
1306: bBltReady = FALSE;
1307: rgPtsBMP[iCntBMP].x = NextX;
1308: rgPtsBMP[iCntBMP].y = NextY;
1309: iCntBMP++;
1310:
1311: if (iCntBMP < MAX_POINTS_BMP) {
1312: return bSuccess;
1313: }
1314: } else {
1315: //
1316: // Caller don't want to increment counter, so must be doing
1317: // recording, so we just Blt again...
1318: //
1319: // But, if the Blt data is no good, bail out...
1320: //
1321: if (!bBltReady) {
1322: return bSuccess;
1323: }
1324: hDCRef = CreateCompatibleDC(NULL);
1325: hObjOld = SelectObject(hDCRef, ghBmp);
1326: GetObject(ghBmp, sizeof(BITMAP), (LPSTR)&bm);
1327: PlgBlt(hDC, rgPtsBMP, hDCRef, 0, 0, bm.bmWidth, bm.bmHeight,
1328: ghBmpMask, 0, 0);
1329: SelectObject(hDCRef, hObjOld);
1330: DeleteDC(hDCRef);
1331: return bSuccess;
1332: }
1333: bBltReady = TRUE;
1334: hDCRef = CreateCompatibleDC(NULL);
1335: hObjOld = SelectObject(hDCRef, ghBmp);
1336:
1337: GetObject(ghBmpMask, sizeof(BITMAP), (LPSTR)&bm);
1338: if (bm.bmBitsPixel != 1) {
1339: SetWindowText(ghTextWnd, "ERROR: Mask has to be a Monochrome bitmap!");
1340: ghBmpMask = NULL;
1341: }
1342:
1343: //
1344: // Avoiding a HT bug
1345: //
1346: //ghBmpMask = NULL;
1347: GetObject(ghBmp, sizeof(BITMAP), (LPSTR)&bm);
1348: //SetStretchBltMode(hDC, HALFTONE);
1349: PlgBlt(hDC, rgPtsBMP, hDCRef, 0, 0, bm.bmWidth, bm.bmHeight,
1350: ghBmpMask, 0, 0);
1351: SelectObject(hDCRef, hObjOld);
1352: DeleteDC(hDCRef);
1353: iCntBMP = 0; // reset
1354: return bSuccess;
1355: }
1356:
1357: case DID_METAF: {
1358: ENHMETAHEADER EnhMetaHdr;
1359: RECT rcClientDS;
1360: static XFORM xform;
1361: static BOOL bXformReady = FALSE;
1362:
1363: if (bErase || bMove)
1364: return bSuccess;
1365:
1366: if (ghMetaf == NULL) {
1367: SetWindowText(ghTextWnd, "ERROR: No metafile to embed!");
1368: return bSuccess;
1369: }
1370:
1371: if (bCntPt) {
1372: bXformReady = FALSE;
1373: rgPtsMF[iCntMF].x = NextX;
1374: rgPtsMF[iCntMF].y = NextY;
1375: iCntMF++;
1376:
1377: if (iCntMF < MAX_POINTS_MF) {
1378: return bSuccess;
1379: }
1380: } else {
1381: //
1382: // Caller don't want to increment counter, so must be doing
1383: // recording, so we just set xform and play it again...
1384: //
1385: // But, if the xform data is no good, bail out...
1386: //
1387: if (!bXformReady) {
1388: return bSuccess;
1389: }
1390:
1391: GetEnhMetaFileHeader(ghMetaf, sizeof(ENHMETAHEADER), &EnhMetaHdr);
1392: SetWorldTransform(hDC, &xform);
1393: GetClientRect(ghwndDrawSurf, &rcClientDS);
1394: //PlayEnhMetaFile(hDC, ghMetaf, (LPRECT) &rcClientDS);
1395: PlayEnhMetaFile(hDC, ghMetaf, (LPRECT) &EnhMetaHdr.rclBounds);
1396: ModifyWorldTransform(hDC, NULL, MWT_IDENTITY);
1397: return bSuccess;
1398: }
1399:
1400: GetEnhMetaFileHeader(ghMetaf, sizeof(ENHMETAHEADER), &EnhMetaHdr);
1401: //
1402: // Based on the three points, top-left, top-right and bottom-left
1403: // (in this order), of the destination, solve equations for the
1404: // elements of the transformation matrix.
1405: //
1406: xform.eDx = (float) rgPtsMF[0].x;
1407: xform.eDy = (float) rgPtsMF[0].y;
1408: xform.eM11 = (rgPtsMF[1].x - xform.eDx)/(EnhMetaHdr.rclBounds.right - EnhMetaHdr.rclBounds.left);
1409: xform.eM12 = (rgPtsMF[1].y - xform.eDy)/(EnhMetaHdr.rclBounds.right - EnhMetaHdr.rclBounds.left);
1410: xform.eM21 = (rgPtsMF[2].x - xform.eDx)/(EnhMetaHdr.rclBounds.bottom - EnhMetaHdr.rclBounds.top);
1411: xform.eM22 = (rgPtsMF[2].y - xform.eDy)/(EnhMetaHdr.rclBounds.bottom - EnhMetaHdr.rclBounds.top);
1412:
1413: bXformReady = TRUE;
1414: SetWorldTransform(hDC, &xform);
1415: GetClientRect(ghwndDrawSurf, &rcClientDS);
1416: //PlayEnhMetaFile(hDC, ghMetaf, (LPRECT) &rcClientDS);
1417: PlayEnhMetaFile(hDC, ghMetaf, (LPRECT) &EnhMetaHdr.rclBounds);
1418: ModifyWorldTransform(hDC, NULL, MWT_IDENTITY);
1419: iCntMF = 0; // reset
1420: return bSuccess;
1421: }
1422: default:
1423: break;
1424: }
1425: //
1426: // Reset counter, user has selected other tools.
1427: //
1428: iCnt = 0;
1429: iCntMF = 0;
1430: iCntBMP = 0;
1431: return bSuccess;
1432: }
1433:
1434: /******************************Public*Routine******************************\
1435: *
1436: * hemfLoadMetafile
1437: *
1438: * Effects: Brings up the Open file common dialog
1439: * Get the enhanced metafile spec'd by user
1440: * returns the handle to the enhanced metafile if successfull
1441: * otherwise, returns 0.
1442: *
1443: * Warnings:
1444: *
1445: * History:
1446: * 08-May-1992 -by- Petrus Wong
1447: * Wrote it.
1448: \**************************************************************************/
1449:
1450: HENHMETAFILE hemfLoadMetafile(HWND hwnd) {
1451: OPENFILENAME ofn;
1452: char szFile[256], szFileTitle[256];
1453: static char *szFilter;
1454:
1455: szFilter =
1456: "EnhMeta files (*.emf)\0*.emf\0\0";
1457:
1458: strcpy(szFile, "*.emf\0");
1459: ofn.lStructSize = sizeof(OPENFILENAME);
1460: ofn.hwndOwner = hwnd;
1461: ofn.lpstrFilter = szFilter;
1462: ofn.lpstrCustomFilter = (LPSTR) NULL;
1463: ofn.nMaxCustFilter = 0L;
1464: ofn.nFilterIndex = 1;
1465: ofn.lpstrFile = szFile;
1466: ofn.nMaxFile = sizeof(szFile);
1467: ofn.lpstrFileTitle = szFileTitle;
1468: ofn.nMaxFileTitle = sizeof(szFileTitle);
1469: ofn.lpstrInitialDir = NULL;
1470: ofn.lpstrTitle = "Load Metafile";
1471: ofn.Flags = 0L;
1472: ofn.nFileOffset = 0;
1473: ofn.nFileExtension = 0;
1474: ofn.lpstrDefExt = "EMF";
1475:
1476: if (!GetOpenFileName(&ofn))
1477: return 0L;
1478:
1479: return GetEnhMetaFile(szFile);
1480: }
1481:
1482: /******************************Public*Routine******************************\
1483: *
1484: * hDCRecordMetafileAs
1485: *
1486: * Effects: Brings up the SaveAs common dialog
1487: * Creates the enhanced metafile with the filename spec'd by user
1488: * Modifies the second arg to reflect the new default filename
1489: * less extension
1490: * returns the created metafile DC if successful, otherwise, 0
1491: *
1492: * Warnings:
1493: *
1494: * History:
1495: * 08-May-1992 -by- Petrus Wong
1496: * Wrote it.
1497: \**************************************************************************/
1498:
1499: HDC hDCRecordMetafileAs(HWND hwnd, LPSTR szFilename) {
1500: OPENFILENAME ofn;
1501: char szFile[256], szFileTitle[256];
1502: static char *szFilter;
1503: char *szTmp, szTmp2[256];
1504: HDC hDCMeta;
1505:
1506: szFilter = "EnhMeta files (*.emf)\0\0";
1507: strcpy(szFile, "*.emf\0");
1508: ofn.lStructSize = sizeof(OPENFILENAME);
1509: ofn.hwndOwner = hwnd;
1510: ofn.lpstrFilter = szFilter;
1511: ofn.lpstrCustomFilter = (LPSTR) NULL;
1512: ofn.nMaxCustFilter = 0L;
1513: ofn.nFilterIndex = 0L;
1514: ofn.lpstrFile = szFile;
1515: ofn.nMaxFile = sizeof(szFile);
1516: ofn.lpstrFileTitle = szFileTitle;
1517: ofn.nMaxFileTitle = sizeof(szFileTitle);
1518: ofn.lpstrInitialDir = NULL;
1519: ofn.lpstrTitle = "Save Metafile As";
1520: ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
1521: ofn.nFileOffset = 0;
1522: ofn.nFileExtension = 0;
1523: ofn.lpstrDefExt = (LPSTR)NULL;
1524:
1525: if (!GetSaveFileName(&ofn)) {
1526: return 0L;
1527: }
1528:
1529: hDCMeta = CreateEnhMetaFile((HDC)NULL, szFile, (LPRECT)NULL, (LPSTR)NULL);
1530:
1531: //
1532: // parses the new filename, removes the extension and copy it into
1533: // szFilename
1534: //
1535: strcpy(szFilename, "");
1536: szTmp = (char *)strtok(szFile, "\\");
1537: strcpy(szTmp2, szTmp);
1538: while (szTmp != NULL) {
1539: szTmp = (char *)strtok(NULL, "\\");
1540: if (szTmp != NULL) {
1541: strcat(szFilename, szTmp2);
1542: strcpy(szTmp2, szTmp);
1543: strcat(szFilename, "\\");
1544: }
1545: }
1546: szTmp = (char *)strtok(szTmp2, ".");
1547: strcat(szFilename, szTmp);
1548:
1549: return hDCMeta;
1550: }
1551:
1552:
1553: /******************************Public*Routine******************************\
1554: *
1555: * bPlayRecord
1556: *
1557: * Effects: Play metafile
1558: * if PlayInfo.bPlayContinuous is TRUE
1559: * play metafile from 1st record up to the PlayInfo.iRecord th
1560: * record
1561: * else only play the PlayInfo.iRecord th record and those preceding
1562: * records that are relevant like MoveTo, etc.
1563: * Terminates enumeration after playing up to the
1564: * PlayInfo.iRecord th record
1565: *
1566: * Warnings:
1567: *
1568: * History:
1569: * 08-May-1992 -by- Petrus Wong
1570: * Wrote it.
1571: \**************************************************************************/
1572:
1573: BOOL APIENTRY bPlayRecord(HDC hDC, LPHANDLETABLE lpHandleTable,
1574: LPENHMETARECORD lpEnhMetaRecord,
1575: UINT nHandles,
1576: LPVOID lpData) {
1577: BOOL bSuccess;
1578: static int iCnt=0;
1579: int i;
1580: char ach[128];
1581: char achTmp[128];
1582: LONG lNumDword;
1583:
1584: bSuccess = TRUE;
1585:
1586: lNumDword = (lpEnhMetaRecord->nSize-8) / 4;
1587:
1588: iCnt++;
1589: if (((PLAYINFO *) lpData)->bPlayContinuous) {
1590: bSuccess = PlayEnhMetaFileRecord(hDC, lpHandleTable,
1591: lpEnhMetaRecord, nHandles);
1592: if (iCnt == ((PLAYINFO *) lpData)->iRecord) {
1593: wsprintf((LPSTR) ach, "%s", rgMetaName[lpEnhMetaRecord->iType]);
1594: for (i=0; i < lNumDword; i++) {
1595: wsprintf((LPSTR) achTmp, "%ld ", lpEnhMetaRecord->dParm[i]);
1596: if ((strlen(ach)+strlen(achTmp))/sizeof(char) >= 128)
1597: break;
1598: strcat(ach, achTmp);
1599: }
1600: SetWindowText(ghTextWnd, ach);
1601: }
1602: } else {
1603:
1604: switch (lpEnhMetaRecord->iType) {
1605: case MR_SETWINDOWEXTEX:
1606: case MR_SETWINDOWORGEX:
1607: case MR_SETVIEWPORTEXTEX:
1608: case MR_SETVIEWPORTORGEX:
1609: case MR_SETBRUSHORGEX:
1610: case MR_SETMAPMODE:
1611: case MR_SETBKMODE:
1612: case MR_SETPOLYFILLMODE:
1613: case MR_SETROP2:
1614: case MR_SETSTRETCHBLTMODE:
1615: case MR_SETTEXTALIGN:
1616: case MR_SETTEXTCOLOR:
1617: case MR_SETBKCOLOR:
1618: case MR_OFFSETCLIPRGN:
1619: case MR_MOVETOEX:
1620: case MR_SETMETARGN:
1621: case MR_EXCLUDECLIPRECT:
1622: case MR_INTERSECTCLIPRECT:
1623: case MR_SCALEVIEWPORTEXTEX:
1624: case MR_SCALEWINDOWEXTEX:
1625: case MR_SAVEDC:
1626: case MR_RESTOREDC:
1627: case MR_SETWORLDTRANSFORM:
1628: case MR_MODIFYWORLDTRANSFORM:
1629: case MR_SELECTOBJECT:
1630: case MR_CREATEPEN:
1631: case MR_CREATEBRUSHINDIRECT:
1632: case MR_DELETEOBJECT:
1633: case MR_SELECTPALETTE:
1634: case MR_CREATEPALETTE:
1635: case MR_SETPALETTEENTRIES:
1636: case MR_RESIZEPALETTE:
1637: case MR_REALIZEPALETTE:
1638: case MR_SETARCDIRECTION:
1639: case MR_SETMITERLIMIT:
1640: case MR_BEGINPATH:
1641: case MR_ENDPATH:
1642: case MR_CLOSEFIGURE:
1643: case MR_SELECTCLIPPATH:
1644: case MR_ABORTPATH:
1645: case MR_EXTCREATEFONTINDIRECTW:
1646: case MR_CREATEMONOBRUSH:
1647: case MR_CREATEDIBPATTERNBRUSHPT:
1648: case MR_EXTCREATEPEN:
1649: goto PlayRec;
1650: default:
1651: break;
1652: } //switch
1653:
1654: if (iCnt == ((PLAYINFO *) lpData)->iRecord) {
1655: PlayRec:
1656: bSuccess = PlayEnhMetaFileRecord(hDC, lpHandleTable,
1657: lpEnhMetaRecord, nHandles);
1658: wsprintf((LPSTR) ach, "%s", rgMetaName[lpEnhMetaRecord->iType]);
1659: for (i=0; i < lNumDword; i++) {
1660: wsprintf((LPSTR) achTmp, "%ld ", lpEnhMetaRecord->dParm[i]);
1661: if ((strlen(ach)+strlen(achTmp))/sizeof(char) >= 128)
1662: break;
1663: strcat(ach, achTmp);
1664: }
1665: SetWindowText(ghTextWnd, ach);
1666: }
1667: }
1668:
1669: if (iCnt == ((PLAYINFO *) lpData)->iRecord) {
1670: iCnt = 0;
1671: return FALSE;
1672: }
1673: return bSuccess;
1674: }
1675:
1676: /******************************Public*Routine******************************\
1677: *
1678: * LoadBitmapFile
1679: *
1680: * Effects: Loads the bitmap from file and return the bitmap
1681: *
1682: * Warnings: pszFileName contains the full path
1683: *
1684: * History:
1685: * 13-May-1992 Petrus Wong return bitmap handle
1686: * 09-Jan-1992 -by- Petrus Wong
1687: * Wrote it.
1688: \**************************************************************************/
1689:
1690: HBITMAP hBmpLoadBitmapFile(HDC hDC, PSTR pszFileName)
1691: {
1692: HANDLE hFile, hMapFile;
1693: LPVOID pMapFile;
1694: LPBITMAPINFOHEADER pbmh;
1695: LPBITMAPINFO pbmi;
1696: PBYTE pjTmp;
1697: ULONG sizBMI;
1698: HBITMAP hBitmap;
1699:
1700: hBitmap = NULL;
1701:
1702: if ((hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
1703: OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL)) == (HANDLE)-1) {
1704: SetWindowText(ghTextWnd, "Fail in file open");
1705: goto ErrExit1;
1706: }
1707:
1708: //
1709: // Create a map file of the opened file
1710: //
1711: if ((hMapFile = CreateFileMapping(hFile, NULL,
1712: PAGE_READONLY, 0, 0, "MapF")) == (HANDLE)-1) {
1713: SetWindowText(ghTextWnd, "Fail in creating map file");
1714: goto ErrExit2;
1715:
1716: }
1717:
1718: //
1719: // Map a view of the whole file
1720: //
1721: if ((pMapFile = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0)) == NULL) {
1722: SetWindowText(ghTextWnd, "Fail in mapping view of the Map File object");
1723: goto ErrExit3;
1724: }
1725:
1726: //
1727: // First check that it is a bitmap file
1728: //
1729: if (*((PWORD)pMapFile) != 0x4d42) { // 'BM'
1730: MessageBox(ghwndMain, "This is not a DIB bitmap file!", "Error", MB_OK);
1731: goto ErrExit3;
1732: }
1733:
1734: pbmh = (LPBITMAPINFOHEADER)((PBYTE)pMapFile + sizeof(BITMAPFILEHEADER));
1735:
1736: //
1737: // Use the size to determine if it is a BitmapCoreHeader or
1738: // BitmapInfoHeader
1739: //
1740: if (pbmh->biSize == sizeof(BITMAPCOREHEADER))
1741: {
1742: sizBMI = sizeof(BITMAPCOREHEADER)+sizeof(RGBTRIPLE)*
1743: ((((LPBITMAPCOREHEADER)pbmh)->bcBitCount == 24) ? 0 : (1 << ((LPBITMAPCOREHEADER)pbmh)->bcBitCount));
1744: }
1745: else // BITMAPINFOHEADER
1746: {
1747: sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*
1748: ((pbmh->biBitCount == 24) ? 0 : (1 << pbmh->biBitCount));
1749: }
1750:
1751: if ((pbmi = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED,sizBMI)) == NULL) {
1752: MessageBox(ghwndMain, "Fail in Memory Allocation!", "Error", MB_OK);
1753: goto ErrExit3;
1754: }
1755:
1756: //
1757: // Make sure we pass in a DWORD aligned BitmapInfo to CreateDIBitmap
1758: // Otherwise, exception on the MIPS platform
1759: // CR!!! Equivalent to memcpy
1760: //
1761: pjTmp = (PBYTE)pbmi;
1762:
1763: while(sizBMI--)
1764: {
1765: *(((PBYTE)pjTmp)++) = *(((PBYTE)pbmh)++);
1766: }
1767:
1768: pMapFile = (PBYTE)pMapFile + ((BITMAPFILEHEADER *)pMapFile)->bfOffBits;
1769:
1770: if ((hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)pbmi,
1771: CBM_INIT, pMapFile, pbmi, DIB_RGB_COLORS)) == NULL) {
1772: SetWindowText(ghTextWnd, "Fail in creating DIB bitmap from file!");
1773: goto ErrExit4;
1774: }
1775:
1776:
1777:
1778: ErrExit4:
1779: LocalFree(pbmi);
1780: ErrExit3:
1781: CloseHandle(hMapFile);
1782: ErrExit2:
1783: CloseHandle(hFile);
1784: ErrExit1:
1785:
1786: return (hBitmap);
1787:
1788: }
1789:
1790: /******************************Public*Routine******************************\
1791: *
1792: * bGetBMP
1793: *
1794: * Effects: call common dialog and pass the filename to hBmpLoadBitmapFile
1795: * return TRUE if successful, FALSE otherwise
1796: *
1797: * Warnings:
1798: *
1799: * History:
1800: * 13-May-1992 -by- Petrus Wong
1801: * Wrote it.
1802: \**************************************************************************/
1803:
1804: BOOL bGetBMP(HWND hwnd, BOOL bMask) {
1805: OPENFILENAME ofn;
1806: char szFile[256], szFileTitle[256];
1807: static char *szFilter;
1808: BOOL bSuccess;
1809: HDC hDC;
1810:
1811: bSuccess = FALSE;
1812:
1813: szFilter =
1814: "DIB files (*.bmp)\0*.bmp\0RLE files (*.rle)\0*.rle\0\0";
1815:
1816: strcpy(szFile, "*.bmp\0");
1817: ofn.lStructSize = sizeof(OPENFILENAME);
1818: ofn.hwndOwner = hwnd;
1819: ofn.lpstrFilter = szFilter;
1820: ofn.lpstrCustomFilter = (LPSTR) NULL;
1821: ofn.nMaxCustFilter = 0L;
1822: ofn.nFilterIndex = 1;
1823: ofn.lpstrFile = szFile;
1824: ofn.nMaxFile = sizeof(szFile);
1825: ofn.lpstrFileTitle = szFileTitle;
1826: ofn.nMaxFileTitle = sizeof(szFileTitle);
1827: ofn.lpstrInitialDir = NULL;
1828: ofn.lpstrTitle = (bMask ? "Load Mask" : "Load Bitmap");
1829: ofn.Flags = 0L;
1830: ofn.nFileOffset = 0;
1831: ofn.nFileExtension = 0;
1832: ofn.lpstrDefExt = "BMP";
1833:
1834: if (!GetOpenFileName(&ofn))
1835: return 0L;
1836:
1837: hDC = GetDC(ghwndDrawSurf);
1838: if (bMask) {
1839: ghBmpMask = hBmpLoadBitmapFile(hDC, szFile);
1840: if (ghBmpMask != NULL)
1841: bSuccess = TRUE;
1842: } else {
1843: ghBmp = hBmpLoadBitmapFile(hDC, szFile);
1844: if (ghBmp != NULL)
1845: bSuccess = TRUE;
1846: }
1847: ReleaseDC(ghwndDrawSurf, hDC);
1848:
1849: return bSuccess;
1850: }
1851:
1852: /******************************Public*Routine******************************\
1853: *
1854: * bHitTest
1855: *
1856: * Effects: Enumerates metafile records
1857: * Calling bDoHitTest to process each record found.
1858: * The mouse position is passed to the bDoHitTest
1859: *
1860: * Warnings:
1861: *
1862: * History:
1863: * 20-May-1992 -by- Petrus Wong
1864: * Wrote it.
1865: \**************************************************************************/
1866:
1867: BOOL bHitTest(HDC hDC, INT x, INT y) {
1868: BOOL bSuccess;
1869: ENHMETAHEADER EnhMetaHdr;
1870: //POINT point;
1871: //!!!RECT rcClientDS;
1872: HTDATA htData;
1873:
1874: bSuccess = TRUE;
1875:
1876: if (ghMetaf == 0)
1877: return 0L;
1878:
1879: GetEnhMetaFileHeader(ghMetaf, sizeof(EnhMetaHdr), &EnhMetaHdr);
1880: //!!!GetClientRect(ghwndDrawSurf, &rcClientDS);
1881: htData.point.x = x;
1882: htData.point.y = y;
1883: htData.iRecord = EnhMetaHdr.nRecords;
1884: EnumEnhMetaFile(hDC, ghMetaf, (PROC)bDoHitTest, (LPVOID) &htData, (LPRECT)&EnhMetaHdr.rclBounds);
1885: //!!!EnumEnhMetaFile(hDC, ghMetaf, (PROC)bDoHitTest, (LPVOID) &point, (LPRECT)&rcClientDS);
1886:
1887: return bSuccess;
1888: }
1889:
1890: /******************************Public*Routine******************************\
1891: *
1892: * bDoHitTest
1893: *
1894: * Effects: Play all records related to transformation
1895: * Remember new mouse position if the record is a MoveTo
1896: * Convert rectangle, ellipse, lineto and bezier to path
1897: * Widen the path and convert it to region.
1898: * Test if the mouse position is inside the region.
1899: *
1900: * Warnings: Only handle rectangle, ellipse, line and polybezier
1901: *
1902: * History:
1903: * 20-May-1992 -by- Petrus Wong
1904: * Wrote it.
1905: \**************************************************************************/
1906:
1907: BOOL APIENTRY bDoHitTest(HDC hDC, LPHANDLETABLE lpHandleTable,
1908: LPENHMETARECORD lpEnhMetaRecord,
1909: UINT nHandles,
1910: LPVOID lpData) {
1911: BOOL bSuccess;
1912: char ach[128];
1913: char achTmp[128];
1914: POINT PtOrg;
1915: LONG lNumDword;
1916: XFORM xfSave;
1917: SIZE SizeWndEx, SizeViewEx;
1918: POINT ptWndOrgin, ptViewOrgin;
1919: int i, iMode;
1920: HRGN hRgn;
1921: PPOINT pPt, pPtTmp;
1922: static HGDIOBJ hObjOld=NULL;
1923: static LONG lCurX=0;
1924: static LONG lCurY=0;
1925: static BOOL bXform=FALSE;
1926: static int iCnt=0;
1927:
1928: iCnt++;
1929:
1930: //
1931: // select a wide pen for widen path later on
1932: //
1933: hObjOld = SelectObject(hDC, ghpnWide);
1934:
1935: //
1936: // save the mouse hit position, this was passed in as a POINT structure
1937: //
1938: PtOrg.x = (((HTDATA *)lpData)->point).x;
1939: PtOrg.y = (((HTDATA *)lpData)->point).y;
1940:
1941: //
1942: // save the number of parameters for the GDI fcn concerned in DWORD.
1943: // This is the total size of metafile record in question less the
1944: // size of the GDI function
1945: //
1946: lNumDword = (lpEnhMetaRecord->nSize-8) / 4;
1947:
1948: switch (lpEnhMetaRecord->iType) {
1949: case MR_SETWINDOWEXTEX:
1950: case MR_SETWINDOWORGEX:
1951: case MR_SETVIEWPORTEXTEX:
1952: case MR_SETVIEWPORTORGEX:
1953: case MR_SETMAPMODE:
1954: case MR_SCALEVIEWPORTEXTEX:
1955: case MR_SCALEWINDOWEXTEX:
1956: case MR_SETMETARGN:
1957: case MR_SAVEDC:
1958: case MR_RESTOREDC:
1959: case MR_SETWORLDTRANSFORM:
1960: case MR_MODIFYWORLDTRANSFORM: {
1961: //
1962: // play all records related to transformation
1963: //
1964: PlayEnhMetaFileRecord(hDC, lpHandleTable,
1965: lpEnhMetaRecord, nHandles);
1966: bXform = TRUE;
1967: return TRUE;
1968: }
1969: //
1970: // convert the following GDI calls to path for hit testing
1971: //
1972: case MR_RECTANGLE: {
1973: BeginPath(hDC);
1974: Rectangle(hDC, lpEnhMetaRecord->dParm[0], lpEnhMetaRecord->dParm[1],
1975: lpEnhMetaRecord->dParm[2], lpEnhMetaRecord->dParm[3]);
1976: EndPath(hDC);
1977: break;
1978: }
1979: case MR_ELLIPSE: {
1980: BeginPath(hDC);
1981: Ellipse(hDC, lpEnhMetaRecord->dParm[0], lpEnhMetaRecord->dParm[1],
1982: lpEnhMetaRecord->dParm[2], lpEnhMetaRecord->dParm[3]);
1983: EndPath(hDC);
1984: break;
1985: }
1986: case MR_MOVETOEX: {
1987: //
1988: // Remember our current position
1989: //
1990: lCurX = lpEnhMetaRecord->dParm[0];
1991: lCurY = lpEnhMetaRecord->dParm[1];
1992: return TRUE;
1993: }
1994: case MR_LINETO: {
1995: BeginPath(hDC);
1996: MoveToEx(hDC, lCurX, lCurY, NULL);
1997: LineTo(hDC, lpEnhMetaRecord->dParm[0], lpEnhMetaRecord->dParm[1]);
1998: EndPath(hDC);
1999: break;
2000: }
2001: case MR_POLYBEZIER16: {
2002: int i;
2003: LONG lSize;
2004: LONG lPtCnt;
2005:
2006: lPtCnt = lpEnhMetaRecord->dParm[4];
2007: lSize = lPtCnt * sizeof(POINTL);
2008:
2009: if ((pPt = (PPOINT) LocalAlloc(LMEM_FIXED, lSize)) == NULL) {
2010: SetWindowText(ghTextWnd, "ERROR: Failed in Memory Allocation: NO HIT");
2011: return TRUE;
2012: }
2013:
2014: pPtTmp = pPt;
2015:
2016: for (i=0; i < (INT) lPtCnt; i++, pPtTmp++) {
2017: pPtTmp->x = (LONG)(LOWORD(lpEnhMetaRecord->dParm[i+5]));
2018: pPtTmp->y = (LONG)(HIWORD(lpEnhMetaRecord->dParm[i+5]));
2019: }
2020:
2021: BeginPath(hDC);
2022: PolyBezier(hDC, (LPPOINT)pPt, (DWORD) lPtCnt);
2023: EndPath(hDC);
2024: LocalFree(pPt);
2025: break;
2026: }
2027: default:
2028: return TRUE;
2029: } //switch
2030:
2031: if (bXform) {
2032: //
2033: // Set World transform to identity temporarily so that pen width
2034: // is not affected by world to page transformation
2035: //
2036: GetWorldTransform(hDC, &xfSave);
2037: ModifyWorldTransform(hDC, NULL, MWT_IDENTITY);
2038:
2039: //
2040: // Set Page transform to identity temporarily so that pen width
2041: // is not affected by page to device transformation
2042: //
2043: iMode = GetMapMode(hDC);
2044:
2045: if ((iMode == MM_ISOTROPIC) || (iMode == MM_ANISOTROPIC)) {
2046: GetWindowOrgEx(hDC, &ptWndOrgin);
2047: GetWindowExtEx(hDC, &SizeWndEx);
2048: GetViewportExtEx(hDC, &SizeViewEx);
2049: GetViewportOrgEx(hDC, &ptViewOrgin);
2050: }
2051:
2052: SetMapMode(hDC, MM_TEXT);
2053: }
2054:
2055: WidenPath(hDC);
2056:
2057: hRgn = PathToRegion(hDC);
2058:
2059: if (hRgn == 0) {
2060: SetWindowText(ghTextWnd, "ERROR: Null Region: NO HIT");
2061: DeleteObject(hRgn);
2062: return TRUE;
2063: }
2064: //DPtoLP(hDC, &PtOrg, 1);
2065: //SetPixel(hDC, PtOrg.x, PtOrg.y, RGB(0, 255, 0));
2066: //
2067: // test if mouse hit position is in region
2068: //
2069: bSuccess = PtInRegion(hRgn, PtOrg.x, PtOrg.y);
2070: //Temporily comment this out to avoid a bug in 265
2071: //FillRgn(hDC, hRgn, ghbrRed);
2072: DeleteObject(hRgn);
2073: //
2074: // Set transform back.
2075: //
2076: if (bXform) {
2077: SetWorldTransform(hDC, &xfSave);
2078: SetMapMode(hDC, iMode);
2079:
2080: if ((iMode == MM_ISOTROPIC) || (iMode == MM_ANISOTROPIC)) {
2081: SetWindowOrgEx(hDC, ptWndOrgin.x, ptWndOrgin.y, NULL);
2082: SetWindowExtEx(hDC, SizeWndEx.cx, SizeWndEx.cy, NULL);
2083: SetViewportExtEx(hDC, SizeViewEx.cx, SizeViewEx.cy, NULL);
2084: SetViewportOrgEx(hDC, ptViewOrgin.x, ptViewOrgin.y, NULL);
2085: }
2086: }
2087:
2088: if (bSuccess) {
2089: Beep(440, 500);
2090: //
2091: // Reporting the metafile record number. Then reset counter.
2092: //
2093: SetDlgItemInt(ghwndCtrlPanel, DID_COUNTER, iCnt, FALSE);
2094: iCnt=0;
2095: wsprintf((LPSTR) ach, "HIT %s", rgMetaName[lpEnhMetaRecord->iType]);
2096:
2097: for (i=0; i < lNumDword; i++) {
2098: wsprintf((LPSTR) achTmp, "%ld ", lpEnhMetaRecord->dParm[i]);
2099: if ((strlen(ach)+strlen(achTmp))/sizeof(char) >= 128)
2100: break;
2101: strcat(ach, achTmp);
2102: }
2103:
2104: SetWindowText(ghTextWnd, ach);
2105: SelectObject(hDC, hObjOld);
2106: bXform = FALSE;
2107: return FALSE;
2108: }
2109: SetWindowText(ghTextWnd, "NO HIT");
2110: if (iCnt >= ((HTDATA *)lpData)->iRecord)
2111: iCnt = 0;
2112: return TRUE;
2113:
2114: UNREFERENCED_PARAMETER(lpHandleTable);
2115: UNREFERENCED_PARAMETER(nHandles);
2116:
2117: }
2118:
2119: /******************************Public*Routine******************************\
2120: *
2121: * bChooseNewFont
2122: *
2123: * Effects:
2124: *
2125: * Warnings:
2126: *
2127: * History:
2128: * 20-May-1992 -by- Petrus Wong
2129: * Wrote it.
2130: \**************************************************************************/
2131:
2132: BOOL bChooseNewFont(HWND hwnd, PLOGFONT plf, COLORREF *pClrRef) {
2133: HDC hDC;
2134: CHOOSEFONT chf;
2135:
2136: hDC = GetDC( hwnd );
2137: chf.hDC = CreateCompatibleDC( hDC );
2138: ReleaseDC( hwnd, hDC );
2139: chf.lStructSize = sizeof(CHOOSEFONT);
2140: chf.hwndOwner = hwnd;
2141: chf.lpLogFont = plf;
2142: chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
2143: chf.rgbColors = *pClrRef;
2144: chf.lCustData = 0;
2145: chf.hInstance = (HANDLE)NULL;
2146: chf.lpszStyle = (LPSTR)NULL;
2147: chf.nFontType = SCREEN_FONTTYPE;
2148: chf.nSizeMin = 0;
2149: chf.nSizeMax = 0;
2150: chf.Flags = CF_SCREENFONTS | CF_EFFECTS;
2151: chf.lpfnHook = (FARPROC)NULL;
2152: chf.lpTemplateName = (LPSTR)NULL;
2153:
2154: if (ChooseFont( &chf ) == FALSE ) {
2155: DeleteDC( hDC );
2156: return FALSE;
2157: }
2158:
2159: *pClrRef = chf.rgbColors;
2160:
2161: DeleteDC( hDC );
2162: return (TRUE);
2163: }
2164:
2165: /******************************Public*Routine******************************\
2166: *
2167: * bChooseNewColor
2168: *
2169: * Effects: Returns TRUE if successful; lpdwRGB points the color selected.
2170: * Otherwise, FALSE.
2171: *
2172: * Warnings:
2173: *
2174: * History:
2175: * 21-May-1992 -by- Petrus Wong
2176: * Wrote it.
2177: \**************************************************************************/
2178:
2179: BOOL bChooseNewColor(HWND hwnd, LPDWORD lpdwRGB) {
2180: static DWORD argbCust[16] = {
2181: RGB(255, 255, 255), RGB(255, 255, 255),
2182: RGB(255, 255, 255), RGB(255, 255, 255),
2183: RGB(255, 255, 255), RGB(255, 255, 255),
2184: RGB(255, 255, 255), RGB(255, 255, 255),
2185: RGB(255, 255, 255), RGB(255, 255, 255),
2186: RGB(255, 255, 255), RGB(255, 255, 255),
2187: RGB(255, 255, 255), RGB(255, 255, 255),
2188: RGB(255, 255, 255), RGB(255, 255, 255)
2189: };
2190: CHOOSECOLOR cc;
2191: BOOL bResult;
2192:
2193: cc.lStructSize = sizeof(CHOOSECOLOR);
2194: cc.hwndOwner = hwnd;
2195: cc.hInstance = ghModule;
2196: cc.rgbResult = *lpdwRGB;
2197: cc.lpCustColors = argbCust;
2198: cc.Flags = CC_RGBINIT | CC_SHOWHELP;
2199: cc.lCustData = 0;
2200: cc.lpfnHook = NULL;
2201: cc.lpTemplateName = NULL;
2202:
2203: bResult = ChooseColor(&cc);
2204:
2205: if (bResult) {
2206: *lpdwRGB = cc.rgbResult;
2207: return TRUE;
2208: }
2209:
2210: return FALSE;
2211: }
2212:
2213:
2214: /******************************Public*Routine******************************\
2215: *
2216: * hBrCreateBrush
2217: *
2218: * Effects: Creates a brush with the specified RGB
2219: *
2220: * Warnings:
2221: *
2222: * History:
2223: * 04-Mar-1992 -by- Petrus Wong
2224: * Wrote it.
2225: \**************************************************************************/
2226:
2227: HBRUSH hBrCreateBrush(HDC hDC, DWORD dwRGB)
2228: {
2229: HDC hdcMem;
2230: HBRUSH hbr;
2231: HBRUSH hbrOld;
2232: HBITMAP hbmPat;
2233: HBITMAP hbmOld;
2234:
2235: hbr = CreateSolidBrush(dwRGB);
2236: hdcMem = CreateCompatibleDC(hDC);
2237:
2238: //
2239: // Minimum size for a bitmap to be used in a fill pattern is 8x8
2240: //
2241: hbmPat = CreateCompatibleBitmap(hDC, 8, 8);
2242:
2243: hbmOld = SelectObject(hdcMem, hbmPat);
2244: hbrOld = SelectObject(hdcMem, hbr);
2245: PatBlt(hdcMem, 0, 0, 8, 8, PATCOPY);
2246:
2247: //
2248: // Deselect hbmPat and hbr
2249: //
2250: SelectObject(hdcMem, hbmOld);
2251: SelectObject(hdcMem, hbrOld);
2252:
2253: DeleteDC(hdcMem);
2254: DeleteObject(hbr);
2255:
2256: hbr = CreatePatternBrush(hbmPat);
2257:
2258: DeleteObject(hbmPat);
2259:
2260: return hbr;
2261: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.