|
|
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.