|
|
1.1 root 1: /***************************************************************************
2: * *
3: * MODULE : ICClip.C *
4: * *
5: * DESCRIPTION : Clipboard functions for ImagEdit *
6: * *
7: * FUNCTIONS : CopyImageClip () - Copies selected portion of image to *
8: * the clipboard. *
9: * *
10: * PasteImageClip () - Pastes the clipboard image to *
11: * selected portion of edit image. *
12: * *
13: * *
14: * HISTORY : 6/21/89 - created by LR *
15: * *
16: ***************************************************************************/
17:
18: #include "imagedit.h"
19: #include "dialogs.h"
20: #include "iehelp.h"
21:
22:
23:
24: /*==========================================================================
25: |ImagEdit's clipboard data is in two formats: |
26: | a) a standard CF_BITMAP format and |
27: | b) a private ImagEdit format described below. |
28: | |
29: |The private ImagEdit format data consists of: |
30: | 1. a DWORD describing screen color when image was sent to clipboard |
31: | followed by... |
32: | 2. the DIB bits of the monochrome AND image (in ghdcANDMask). |
33: | |
34: |The CF_BITMAP format consists of the image bitmap (the combined XOR and |
35: |AND images in ghdcImage for icons and cursors). |
36: | |
37: |This information is sufficient to re-create the image correctly during |
38: |paste even if the screen viewing color is subsequently changed. |
39: | |
40: |Both formats are created if the image being edited is an icon or a cursor.|
41: |Only the CF_BITMAP format is created if a bitmap is being edited. |
42: ==========================================================================*/
43:
44: /****************************************************************************
45: * *
46: * FUNCTION : BOOL PASCAL CopyImageClip(fBitmap) *
47: * *
48: * PURPOSE : Copies the information from the selected area of image to *
49: * the clipboard. *
50: * *
51: * SIDE EFFECTS: may change contents of the clipboard. The "pick" or clip *
52: * rectangle is reset to cover the entire image. *
53: * *
54: ****************************************************************************/
55:
56: BOOL CopyImageClip(VOID)
57: {
58: HCURSOR hcurOld;
59: HBITMAP hStdBitmap;
60: HBITMAP hPrivBitmap;
61: HDC hStdDC;
62: HDC hPrivDC;
63: HANDLE hOldSObj;
64: HANDLE hOldPObj;
65: HANDLE hPriv;
66: LPSTR lpPriv;
67:
68: hcurOld = SetCursor(hcurWait);
69:
70: /* create a temp. bitmap and DC for the standard clipboard format
71: * along the same lines as the image bitmap
72: */
73: hStdDC = CreateCompatibleDC(ghdcImage);
74: hStdBitmap = MyCreateBitmap(ghdcImage, gcxPick, gcyPick, 16);
75: hOldSObj = SelectObject(hStdDC, hStdBitmap);
76:
77: /* blt the image bits into standard format DC */
78: BitBlt(hStdDC, 0, 0, gcxPick, gcyPick, ghdcImage,
79: grcPick.left, grcPick.top, SRCCOPY);
80: SelectObject(hStdDC, hOldSObj);
81:
82: if (giType != FT_BITMAP) {
83: /* for icons and cursors, create a temp. DC and bitmap for the AND
84: * mask and blt the mask bits into it.
85: */
86: hPrivDC = CreateCompatibleDC(ghdcANDMask);
87: hPrivBitmap = CreateCompatibleBitmap(ghdcANDMask, gcxPick, gcyPick);
88: hOldPObj = SelectObject(hPrivDC, hPrivBitmap);
89: BitBlt(hPrivDC, 0, 0, gcxPick, gcyPick, ghdcANDMask,
90: grcPick.left, grcPick.top, SRCCOPY);
91:
92: /* Allocate a buffer for the private ImagEdit format */
93: hPriv = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
94: (DWORD)((gcxPick + 31) >> 3) * gcyPick + sizeof(DWORD));
95: if (!hPriv) {
96: DeleteDC(hStdDC);
97: DeleteObject(hStdBitmap);
98: DeleteDC(hPrivDC);
99: DeleteObject(hPrivBitmap);
100: return FALSE;
101: }
102:
103: lpPriv = (LPSTR)GlobalLock(hPriv);
104:
105: /* Fill in the first DWORD with the screen color information */
106: *((DWORD FAR *)lpPriv) = grgbScreen;
107:
108: /* Get the mask bits into the buffer */
109: GetBitmapBits(hPrivBitmap, (DWORD)((gcxPick + 31) >> 3) * gcyPick,
110: (LPSTR)lpPriv + sizeof(DWORD));
111:
112: SelectObject(hPrivDC, hOldPObj);
113: DeleteObject(hPrivBitmap);
114: DeleteDC(hPrivDC);
115: }
116:
117: /* Open clipboard and clear it of it's contents */
118: if (!OpenClipboard(ghwndMain)) {
119: DeleteDC(hStdDC);
120: return(FALSE);
121: }
122: EmptyClipboard();
123:
124: if (giType != FT_BITMAP) {
125: /* set the private ImagEdit format data into the clipboard */
126: if (!SetClipboardData(ClipboardFormat, hPriv)) {
127: DeleteDC(hStdDC);
128: GlobalUnlock(hPriv);
129: GlobalFree(hPriv);
130: CloseClipboard();
131: return(FALSE);
132: }
133: GlobalUnlock(hPriv);
134: }
135: /* set the standard CF_BITMAP format data in the clipboard */
136: if (!SetClipboardData(CF_BITMAP, hStdBitmap)) {
137: DeleteDC(hStdDC);
138: GlobalFree(hPriv); // hPriv may not have been initialized (if giType == BITMAP).
139: CloseClipboard();
140: return(FALSE);
141: }
142:
143: CloseClipboard();
144: DeleteDC(hStdDC);
145:
146: /*
147: * Reset pick rectangle to cover entire image.
148: */
149: PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
150:
151: /*
152: * Erase the drag rectangle.
153: */
154: WorkUpdate();
155:
156: SetCursor(hcurOld);
157:
158: return TRUE;
159: }
160:
161:
162:
163: /************************************************************************
164: * PasteImageClip
165: *
166: * Pastes an image from the clipboard to the current image.
167: *
168: * It is assumed that this routine will not be called unless an
169: * image is currently being edited.
170: *
171: * The pick rectangle is reset to cover the entire image if the
172: * paste is successful.
173: *
174: * Basic outline of how Paste is done in ImagEdit.
175: *
176: * Find out what format is available in the clipboard:
177: * a. CF_BITMAP only
178: * --------------
179: * case 1: Pasting to an icon or cursor
180: * * We don't have any screen color information.
181: * Make the mask bits opaque and blt. the bitmap to
182: * ghdcImage.
183: *
184: * case 2: Pasting to a bitmap
185: * * Blt the bitmap to the image DC.
186: *
187: * b. both ImagEdit and CF_BITMAP
188: * ---------------------------
189: * case 1: Pasting to an icon or cursor
190: * * Recover the image from the AND and screen color
191: * data (in ImagEdit) and the combined image bitmap
192: * (in CF_BITMAP). Use the information to make the
193: * neccessary changes if the screen viewing color was
194: * changed between Copy and Paste.
195: *
196: * case 2: Pasting to a bitmap
197: * * Blt the CF_BITMAP data to the image DC.
198: *
199: * If the destination image differs in dimensions from
200: * source image, the source image is stretched or clipped to that of
201: * destination, depending on preference
202: *
203: * History:
204: *
205: ************************************************************************/
206:
207: BOOL PasteImageClip(VOID)
208: {
209: HCURSOR hcurOld;
210: INT cxClip;
211: INT cyClip;
212: INT cxTarget;
213: INT cyTarget;
214: INT cxSource;
215: INT cySource;
216: DWORD rgbClipScreen;
217: BOOL fIEFormatFound;
218: HANDLE hClipData;
219: LPSTR lpClipData;
220: BITMAP bmClip;
221: HDC hdcClip;
222: HBITMAP hbmClip;
223: HBITMAP hbmClipOld;
224: HDC hdcClipAND;
225: HBITMAP hbmClipAND;
226: HBITMAP hbmClipANDOld;
227: HDC hdcClipAND16;
228: HBITMAP hbmClipAND16;
229: HBITMAP hbmClipAND16Old;
230: HDC hdcTarget;
231: HBITMAP hbmTarget;
232: HBITMAP hbmTargetOld;
233: HDC hdcTargetAND16;
234: HBITMAP hbmTargetAND16;
235: HBITMAP hbmTargetAND16Old;
236: HDC hdcTargetAND;
237: HBITMAP hbmTargetAND;
238: HBITMAP hbmTargetANDOld;
239:
240: hcurOld = SetCursor(hcurWait);
241:
242: if (!OpenClipboard(ghwndMain)) {
243: Message(MSG_NOCLIPBOARD);
244: goto Error1;
245: }
246:
247: if (!(hbmClip = GetClipboardData(CF_BITMAP))) {
248: Message(MSG_NOCLIPBOARDFORMAT);
249: goto Error2;
250: }
251:
252: GetObject(hbmClip, sizeof(BITMAP), (LPSTR)&bmClip);
253: cxClip = (INT)bmClip.bmWidth;
254: cyClip = (INT)bmClip.bmHeight;
255:
256: /*
257: * If the dimensions of the current pick rectangle don't match
258: * the bitmap being pasted, ask the user if they want to stretch
259: * or clip the pasted image.
260: */
261: cxTarget = gcxPick;
262: cyTarget = gcyPick;
263: cxSource = cxClip;
264: cySource = cyClip;
265: if (gcxPick != cxClip || gcyPick != cyClip) {
266: if (DlgBox(DID_PASTEOPTIONS, (WNDPROC)PasteOptionsDlgProc) == IDCANCEL) {
267: goto Error2;
268: }
269:
270: /*
271: * If clipping and the clipboard dimensions differ from the
272: * selected pick rectangle, then either the target dimensions
273: * or the source dimensions need to be sized down.
274: */
275: if (!fStretchClipboardData) {
276: if (cxClip < gcxPick)
277: cxTarget = cxClip;
278: else
279: cxSource = gcxPick;
280:
281: if (cyClip < gcyPick)
282: cyTarget = cyClip;
283: else
284: cySource = gcyPick;
285: }
286: }
287:
288: /*
289: * Update the undo buffer now that we are committed to the paste.
290: */
291: ImageUpdateUndo();
292:
293: /*
294: * Determine if the private ImagEdit clipboard format is available.
295: */
296: fIEFormatFound = IsClipboardFormatAvailable(ClipboardFormat);
297:
298: if (giType != FT_BITMAP && fIEFormatFound) {
299: /*
300: * Get the AND mask bitmap and the old screen color out of
301: * the private format.
302: */
303: hClipData = GetClipboardData(ClipboardFormat);
304: lpClipData = (LPSTR)GlobalLock(hClipData);
305: rgbClipScreen = *((DWORD FAR *)lpClipData);
306: hdcClipAND = CreateCompatibleDC(ghdcImage);
307: hbmClipAND = CreateBitmap(cxClip, cyClip, (BYTE)1, (BYTE)1,
308: (LPSTR)lpClipData + sizeof(DWORD));
309: hbmClipANDOld = SelectObject(hdcClipAND, hbmClipAND);
310:
311: /*
312: * Create a color bitmap for temporary use.
313: */
314: hdcClipAND16 = CreateCompatibleDC(ghdcImage);
315: hbmClipAND16 = MyCreateBitmap(ghdcImage, cxSource, cySource, 16);
316: hbmClipAND16Old = SelectObject(hdcClipAND16, hbmClipAND16);
317:
318: /*
319: * Blt the AND mask onto the color bitmap.
320: */
321: BitBlt(hdcClipAND16, 0, 0, cxSource, cySource, hdcClipAND,
322: 0, 0, SRCCOPY);
323:
324: /*
325: * Create the color target AND mask bitmap.
326: */
327: hdcTargetAND16 = CreateCompatibleDC(ghdcImage);
328: hbmTargetAND16 = MyCreateBitmap(ghdcImage, cxTarget, cyTarget, 16);
329: hbmTargetAND16Old = SelectObject(hdcTargetAND16, hbmTargetAND16);
330:
331: /*
332: * StretchBlt from the color AND mask bitmap to the color target
333: * AND mask bitmap. The blt must be done from a color bitmap to
334: * a color bitmap, and the stretch blt mode must be set to
335: * COLORONCOLOR. All this is necessary so that the AND mask
336: * stays exactly in sync with the stretch blt of the color
337: * (XOR) mask. If these steps are not done correctly, shrinking
338: * an image with screen colored pixels in it can cause problems,
339: * because the stretch blt will use a slightly different
340: * algorithm to compress the monochrome AND mask and the color
341: * XOR mask.
342: */
343: SetStretchBltMode(hdcTargetAND16, COLORONCOLOR);
344: SetStretchBltMode(hdcClipAND16, COLORONCOLOR); //
345: StretchBlt(hdcTargetAND16, 0, 0, cxTarget, cyTarget, hdcClipAND16,
346: 0, 0, cxSource, cySource, SRCCOPY);
347:
348: /*
349: * Create the monochrome target AND mask bitmap.
350: */
351: hdcTargetAND = CreateCompatibleDC(ghdcImage);
352: hbmTargetAND = MyCreateBitmap(ghdcImage, cxTarget, cyTarget, 2);
353: hbmTargetANDOld = SelectObject(hdcTargetAND, hbmTargetAND);
354:
355: /*
356: * Blt the color AND mask onto the monochrome AND mask.
357: * The monochrome AND mask is the one that we will use
358: * later. It must be monochrome or the ImageDCSeparate
359: * and ImageDCCombine functions will not work properly.
360: */
361: BitBlt(hdcTargetAND, 0, 0, cxTarget, cyTarget, hdcTargetAND16,
362: 0, 0, SRCCOPY);
363:
364: /*
365: * Cleanup.
366: */
367: SelectObject(hdcTargetAND16, hbmTargetAND16Old);
368: DeleteObject(hbmTargetAND16);
369: DeleteDC(hdcTargetAND16);
370: SelectObject(hdcClipAND16, hbmClipAND16Old);
371: DeleteObject(hbmClipAND16);
372: DeleteDC(hdcClipAND16);
373: SelectObject(hdcClipAND, hbmClipANDOld);
374: DeleteObject(hbmClipAND);
375: DeleteDC(hdcClipAND);
376: GlobalUnlock(hClipData);
377: }
378:
379: /*
380: * Get the clipboard bitmap into a DC.
381: */
382: hdcClip = CreateCompatibleDC(ghdcImage);
383: hbmClipOld = SelectObject(hdcClip, hbmClip);
384:
385: /*
386: * Create the target bitmap.
387: */
388: hdcTarget = CreateCompatibleDC(ghdcImage);
389: hbmTarget = MyCreateBitmap(ghdcImage, cxTarget, cyTarget, 16);
390: hbmTargetOld = SelectObject(hdcTarget, hbmTarget);
391:
392: /*
393: * StretchBlt the bitmap onto the target.
394: */
395: SetStretchBltMode(hdcTarget, COLORONCOLOR);
396: SetStretchBltMode(hdcClip, COLORONCOLOR); //
397: StretchBlt(hdcTarget, 0, 0, cxTarget, cyTarget, hdcClip, 0, 0,
398: cxSource, cySource, SRCCOPY);
399:
400: /*
401: * Handle some special cases.
402: */
403: if (giType == FT_BITMAP || !fIEFormatFound) {
404: /*
405: * The image we are pasting into is either a bitmap, or
406: * there does not exist an AND mask in the clipboard.
407: */
408: if (gnColors == 2) {
409: /*
410: * We are pasting to a mono image. We must convert the
411: * colors in the clipboard bitmap into monochrome.
412: */
413: ImageDCMonoBlt(hdcTarget, cxTarget, cyTarget);
414: }
415: }
416: else {
417: /*
418: * We are pasting into an icon or cursor image and we have
419: * available an AND mask. Is the current image monochrome?
420: */
421: if (gnColors == 2) {
422: /*
423: * Remove the old screen/inverse colors from the image,
424: * convert it to monochrome, then put back in the
425: * current screen/inverse colors.
426: */
427: ImageDCSeparate(hdcTarget, cxTarget, cyTarget, hdcTargetAND,
428: rgbClipScreen);
429: ImageDCMonoBlt(hdcTarget, cxTarget, cyTarget);
430: ImageDCCombine(hdcTarget, cxTarget, cyTarget, hdcTargetAND);
431: }
432: /*
433: * Does the screen color specified in the clipboard
434: * differ from the current screen color?
435: */
436: else if (rgbClipScreen != grgbScreen) {
437: /*
438: * Remove the old screen/inverse colors, then put back
439: * in the current ones.
440: */
441: ImageDCSeparate(hdcTarget, cxTarget, cyTarget, hdcTargetAND,
442: rgbClipScreen);
443: ImageDCCombine(hdcTarget, cxTarget, cyTarget, hdcTargetAND);
444: }
445: }
446:
447: /*
448: * Blt the clipboard image to the proper rectangle in the current image.
449: */
450: BitBlt(ghdcImage, grcPick.left, grcPick.top,
451: cxTarget, cyTarget, hdcTarget, 0, 0, SRCCOPY);
452:
453: /*
454: * If the current image is an icon or cursor, we must take care
455: * of the AND mask also.
456: */
457: if (giType != FT_BITMAP) {
458: /*
459: * Is there an AND mask in the clipboard to use?
460: */
461: if (fIEFormatFound) {
462: /*
463: * Blt it into the current image's AND mask.
464: */
465: BitBlt(ghdcANDMask, grcPick.left, grcPick.top,
466: cxTarget, cyTarget, hdcTargetAND, 0, 0, SRCCOPY);
467: }
468: else {
469: /*
470: * Make the AND mask opaque, because there is no
471: * screen color information.
472: */
473: PatBlt(ghdcANDMask, grcPick.left, grcPick.top,
474: cxTarget, cyTarget, BLACKNESS);
475: }
476: }
477:
478: /*
479: * Cleanup.
480: */
481: SelectObject(hdcTarget, hbmTargetOld);
482: DeleteObject(hbmTarget);
483: DeleteDC(hdcTarget);
484:
485: if (giType != FT_BITMAP && fIEFormatFound) {
486: SelectObject(hdcTargetAND, hbmTargetANDOld);
487: DeleteObject(hbmTargetAND);
488: DeleteDC(hdcTargetAND);
489: }
490:
491: SelectObject(hdcClip, hbmClipOld);
492: DeleteDC(hdcClip);
493:
494: CloseClipboard();
495:
496: /*
497: * Update the View and workspace windows.
498: */
499: ViewUpdate();
500:
501: /*
502: * Reset pick rectangle to cover entire image.
503: */
504: PickSetRect(0, 0, gcxImage - 1, gcyImage - 1);
505:
506: fImageDirty = TRUE;
507:
508: SetCursor(hcurOld);
509:
510: return TRUE;
511:
512: Error2:
513: CloseClipboard();
514:
515: Error1:
516: SetCursor(hcurOld);
517:
518: return FALSE;
519: }
520:
521:
522:
523: /************************************************************************
524: * PasteOptionsDlgProc
525: *
526: * Proc for the dialog that asks the user whether they want to clip
527: * or stretch the bitmap being pasted in.
528: *
529: * Upon return with an IDOK value, the fStretchClipboardData global
530: * will be TRUE if they want to stretch, or FALSE if they want to clip.
531: *
532: * History:
533: *
534: ************************************************************************/
535:
536: DIALOGPROC PasteOptionsDlgProc(
537: HWND hwnd,
538: UINT msg,
539: WPARAM wParam,
540: LPARAM lParam)
541: {
542: switch (msg) {
543: case WM_INITDIALOG:
544: CheckRadioButton(hwnd, DID_PASTEOPTIONSSTRETCH,
545: DID_PASTEOPTIONSCLIP,
546: fStretchClipboardData ?
547: DID_PASTEOPTIONSSTRETCH : DID_PASTEOPTIONSCLIP);
548:
549: CenterWindow(hwnd);
550:
551: break;
552:
553: case WM_COMMAND:
554: switch (LOWORD(wParam)) {
555: case IDOK :
556: if (IsDlgButtonChecked(hwnd, DID_PASTEOPTIONSSTRETCH))
557: fStretchClipboardData = TRUE;
558: else
559: fStretchClipboardData = FALSE;
560:
561: EndDialog(hwnd, IDOK);
562: break;
563:
564: case IDCANCEL:
565: EndDialog(hwnd, IDCANCEL);
566: break;
567:
568: case IDHELP:
569: WinHelp(ghwndMain, gszHelpFile, HELP_CONTEXT,
570: HELPID_PASTEOPTIONS);
571: break;
572: }
573:
574: break;
575:
576: default:
577: return FALSE;
578: }
579:
580: return TRUE;
581: }
582:
583:
584:
585: /************************************************************************
586: * PickSetRect
587: *
588: * Sets the globals for the picking rectangle size. This affects
589: * what is copied into the clipboard.
590: *
591: * Arguments:
592: *
593: * History:
594: *
595: ************************************************************************/
596:
597: VOID PickSetRect(
598: INT xLeft,
599: INT yTop,
600: INT xRight,
601: INT yBottom)
602: {
603: SetRect(&grcPick, xLeft, yTop, xRight, yBottom);
604: gcxPick = (grcPick.right - grcPick.left) + 1;
605: gcyPick = (grcPick.bottom - grcPick.top) + 1;
606: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.