#define STRICT #include #include #include #include "RgnDem.h" static L_BOOL Child_OnCreate (HWND hWnd, CREATESTRUCT FAR * lpCreateStruct); static L_VOID Child_OnCommand (HWND hWnd, L_INT id, HWND hwndCtl, L_UINT codeNotify); static L_VOID Child_OnSize (HWND hWnd, L_UINT nState, L_INT nCx, L_INT nCy); static L_VOID Child_OnPaint (HWND hWnd); static L_VOID Child_OnMDIActivate (HWND hWnd, L_BOOL fActive, HWND hWndActivate, HWND hWndDeactivate); static L_VOID Child_OnClose (HWND hWnd); static L_VOID Child_OnDestroy (HWND hWnd); static L_VOID Child_OnHScroll (HWND hWnd, HWND hWndCtl, L_UINT nCode, L_INT nPos); static L_VOID Child_OnVScroll (HWND hWnd, HWND hWndCtl, L_UINT nCode, L_INT nPos); static L_BOOL Child_OnEraseBkgnd (HWND hWnd, HDC hDC); static L_VOID Child_OnPaletteChanged (HWND hWnd, HWND hWndPaletteChange); static L_BOOL Child_OnQueryNewPalette (HWND hWnd); static L_VOID Child_OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized); static L_VOID Child_OnPaletteChanging(HWND hWnd, HWND hWndPaletteChange); static L_VOID Child_SysColorChange(HWND hwnd); static L_VOID Child_OnTimer (HWND hWnd, L_UINT id); static L_VOID Child_OnLButtonDown (HWND hWnd, L_BOOL bDoubleClick, L_INT x, L_INT y, L_UINT keyFlags); static L_VOID Child_OnMouseMove (HWND hWnd, L_INT x, L_INT y, L_UINT keyFlags); static L_VOID Child_OnLButtonUp (HWND hWnd, L_INT x, L_INT y, L_UINT keyFlags); static L_VOID Child_OnSetFocus (HWND hWnd, HWND hWndOldFocus); static L_VOID Child_OnKillFocus (HWND hWnd, HWND hWndNewFocus); L_INT PasteBitmapRgn (HWND hWnd); L_INT SaveBitmapFile (HWND hWnd); L_VOID ClientToBitmap (pCHILDDATA pData, PPOINT pPoint); L_INT CreateRegionBitmaps (HWND hWnd); L_VOID DrawShape (HWND hWnd); L_VOID DrawPoly (HWND hWnd); L_VOID MoveFloater (HWND hWnd); L_INT SafeCopyBitmapRect (pBITMAPHANDLE pBitmapDst, pBITMAPHANDLE pBitmapSrc, L_INT L_FAR * pXSrc, L_INT L_FAR * pYSrc, L_INT L_FAR * pWidth, L_INT L_FAR * pHeight); HCURSOR hOldCursor; L_BOOL bInScroll=FALSE; LRESULT CALLBACK ChildWndProc (HWND hwnd, L_UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { HANDLE_MSG (hwnd, WM_CREATE, Child_OnCreate); HANDLE_MSG (hwnd, WM_COMMAND, Child_OnCommand); HANDLE_MSG (hwnd, WM_SIZE, Child_OnSize); HANDLE_MSG (hwnd, WM_PAINT, Child_OnPaint); HANDLE_MSG (hwnd, WM_MDIACTIVATE, Child_OnMDIActivate); HANDLE_MSG (hwnd, WM_CLOSE, Child_OnClose); HANDLE_MSG (hwnd, WM_DESTROY, Child_OnDestroy); HANDLE_MSG (hwnd, WM_HSCROLL, Child_OnHScroll); HANDLE_MSG (hwnd, WM_VSCROLL, Child_OnVScroll); HANDLE_MSG (hwnd, WM_ERASEBKGND, Child_OnEraseBkgnd); HANDLE_MSG (hwnd, WM_PALETTECHANGED, Child_OnPaletteChanged); HANDLE_MSG (hwnd, WM_QUERYNEWPALETTE, Child_OnQueryNewPalette); HANDLE_MSG (hwnd, WM_PALETTEISCHANGING, Child_OnPaletteChanging); HANDLE_MSG (hwnd, WM_SYSCOLORCHANGE, Child_SysColorChange); HANDLE_MSG (hwnd, WM_ACTIVATE, Child_OnActivate); HANDLE_MSG (hwnd, WM_TIMER, Child_OnTimer); HANDLE_MSG (hwnd, WM_LBUTTONDOWN, Child_OnLButtonDown); HANDLE_MSG (hwnd, WM_MOUSEMOVE, Child_OnMouseMove); HANDLE_MSG (hwnd, WM_LBUTTONUP, Child_OnLButtonUp); HANDLE_MSG (hwnd, WM_SETFOCUS, Child_OnSetFocus); HANDLE_MSG (hwnd, WM_KILLFOCUS, Child_OnKillFocus); } return DefMDIChildProc(hwnd, message, wParam, lParam); } static L_BOOL Child_OnCreate (HWND hWnd, CREATESTRUCT FAR * lpCreateStruct) { HDC hdcCompatibile; pCHILDDATA pData; LPCREATEDATA pCreateData; //Allocate memory for window private data pCreateData = (LPCREATEDATA) CHILDCREATELPARAM(lpCreateStruct); if(!pCreateData) return FALSE; pData = (pCHILDDATA) GlobalAllocPtr(GHND, sizeof(CHILDDATA)); if(!pData) return FALSE; SetRect(&pData->rcFrame, 0, 0, 0, 0); SetRect(&pData->rcRgn, 0, 0, 0, 0); pData->nVScrollPos = 0; pData->nVScrollMax = 0; pData->nVScrollStep = 0; pData->nHScrollPos = 0; pData->nHScrollMax = 0; pData->nHScrollStep = 0; pData->cxClient = 0; pData->cyClient = 0; pData->bMovingFloater = FALSE; pData->bDrawShape = FALSE; pData->bDrawFrame = FALSE; pData->nPtCount = 0; pData->pPolyPt = NULL; pData->uTimerID = 0; pData->bCapWnd = FALSE; pData->pszTitle = GlobalAllocPtr(GHND, (lstrlen(pCreateData->pszTitle) + 1) * sizeof(L_TCHAR)); if(pData->pszTitle) lstrcpy(pData->pszTitle, pCreateData->pszTitle); L_CopyBitmap(&pData->LeadBitmap, pCreateData->pBitmap,sizeof(BITMAPHANDLE)); pData->nBitmapFormat = pCreateData->nBitmapFormat; L_InitBitmap(&pData->bmFloater,sizeof(BITMAPHANDLE), 0, 0, 0); L_InitBitmap(&pData->bmSave,sizeof(BITMAPHANDLE), 0, 0, 0); hdcCompatibile = GetDC(hWnd); pData->hPalette = L_CreatePaintPalette(hdcCompatibile, &pData->LeadBitmap); ReleaseDC(hWnd, hdcCompatibile); SetRect(&pData->rcView, 0, 0, BITMAPWIDTH(&pData->LeadBitmap), BITMAPHEIGHT(&pData->LeadBitmap)); SetWindowLong(hWnd, GWL_USERDATA, (long) pData); if(L_BitmapHasRgn(&pData->LeadBitmap)) L_GetBitmapRgnHandle(&pData->LeadBitmap, NULL, &pData->hrgnRegion); // Save some window handles hWndClient = GetParent(hWnd); hWndFrame = GetParent(hWndClient); pData->hbmSave = (HBITMAP)NULL; pData->hbmFloater = (HBITMAP)NULL; Child_OnQueryNewPalette(hWnd); return TRUE; } /*---[Child_OnActivate]----------------------------------------------------- Syntax: VOID Child_OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized) Parameters: hWnd Window handle. state WA_ACTIVE | WA_CLICKACTIVE | WA_INACTIVE hwndActDeact the winodw habdle that deactivate fMinimized Window is minimized Prototype: Color.h Notes: This procedure is responsible for handling WM_ONCOMMAND. --------------------------------------------------------------------------*/ static L_VOID Child_OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized) { if(state!=WA_INACTIVE) Child_OnQueryNewPalette (hwnd); } static L_VOID Child_OnPaletteChanged (HWND hWnd, HWND hWndPaletteChange) { HDC hDC; HPALETTE hOldPal; pCHILDDATA pData; if(hWnd == hWndPaletteChange) return; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(pData->hPalette) { DeleteObject(pData->hPalette); pData->hPalette = NULL; } hDC = GetDC(hWnd); pData->hPalette = L_CreatePaintPalette(hDC, &pData->LeadBitmap); hOldPal = SelectPalette(hDC, pData->hPalette, TRUE); RealizePalette(hDC); InvalidateRect(hWnd, NULL, FALSE); SelectPalette(hDC, hOldPal, TRUE); ReleaseDC(hWnd, hDC); } /*====(Child_OnPaletteChanging)========================================== Description: Enumerates all child windows and asks them to realize their logical palettes beside the physical palette. Syntax : VOID Child_OnPaletteChanging(HWND hwnd, HWND hWndPaletteChange) Parameters : hwnd Handle to a window. hWndPaletteChange Handle to a window that has the palette realized. Return Value: None. ==========================================================================*/ static L_VOID Child_OnPaletteChanging(HWND hWnd, HWND hWndPaletteChange) { Child_OnPaletteChanged (hWnd, hWndPaletteChange); } /*====(Child_SysColorChange)========================================== Syntax: VOID Child_SysColorChange( HWND hWnd ) Parameters: hWnd Handle to a window. Prototype: Loadsave.h Notes: This procedure is responsible for handling WM_SYSCOLORCHANGE. --------------------------------------------------------------------------*/ static L_VOID Child_SysColorChange(HWND hwnd) { Child_OnQueryNewPalette (hwnd); } static L_VOID Child_OnVScroll (HWND hWnd, HWND hWndCtl, L_UINT nCode, L_INT nPos) { L_INT nScrollInc; pCHILDDATA pData; UNREFERENCED_PARAMETER(hWndCtl); pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); bInScroll = TRUE; switch (nCode) { case SB_BOTTOM: nScrollInc = pData->nVScrollMax - pData->nVScrollPos; break; case SB_TOP: nScrollInc = -pData->nVScrollPos; break; case SB_LINEDOWN: nScrollInc = pData->nVScrollStep; break; case SB_LINEUP: nScrollInc = -pData->nVScrollStep; break; case SB_PAGEDOWN: nScrollInc = max (pData->nVScrollStep, (pData->cyClient - pData->nVScrollStep)); break; case SB_PAGEUP: nScrollInc = -max (pData->nVScrollStep, (pData->cyClient - pData->nVScrollStep)); break; case SB_THUMBTRACK: case SB_THUMBPOSITION: nScrollInc = nPos - pData->nVScrollPos; break; default: nScrollInc = 0; break; } nScrollInc = max(-pData->nVScrollPos, min(nScrollInc, (pData->nVScrollMax - pData->nVScrollPos))); if(nScrollInc) { pData->nVScrollPos += nScrollInc; OffsetRect(&pData->rcView, 0, -nScrollInc); ScrollWindow(hWnd, 0, -nScrollInc, NULL, NULL); SetScrollPos(hWnd, SB_VERT, pData->nVScrollPos, TRUE); UpdateWindow(hWnd); } bInScroll = FALSE; } static L_VOID Child_OnHScroll (HWND hWnd, HWND hWndCtl, L_UINT nCode, L_INT nPos) { L_INT nHScrollInc; pCHILDDATA pData; UNREFERENCED_PARAMETER(hWndCtl); pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; bInScroll = TRUE; switch (nCode) { case SB_LEFT: nHScrollInc = -pData->nHScrollPos; break; case SB_RIGHT: nHScrollInc = pData->nHScrollMax - pData->nHScrollPos; break; case SB_LINELEFT: nHScrollInc = -pData->nHScrollStep; break; case SB_LINERIGHT: nHScrollInc = pData->nHScrollStep; break; case SB_PAGELEFT: nHScrollInc = -max(pData->nHScrollStep, (pData->cxClient - pData->nHScrollStep)); break; case SB_PAGERIGHT: nHScrollInc = max(pData->nHScrollStep, (pData->cxClient - pData->nHScrollStep)); break; case SB_THUMBPOSITION: nHScrollInc = nPos - pData->nHScrollPos; break; default: nHScrollInc = 0; break; } nHScrollInc = max (-pData->nHScrollPos, min (nHScrollInc, (pData->nHScrollMax - pData->nHScrollPos))); if (nHScrollInc) { pData->nHScrollPos += nHScrollInc; OffsetRect(&pData->rcView, -nHScrollInc, 0); ScrollWindow(hWnd, -nHScrollInc, 0, NULL, NULL); SetScrollPos(hWnd, SB_HORZ, pData->nHScrollPos, TRUE); UpdateWindow(hWnd); } bInScroll = FALSE; } static L_BOOL Child_OnEraseBkgnd (HWND hWnd, HDC hDC) { HRGN hClientRgn, hFillRgn; RECT rcView, rcClient; HGDIOBJ hBrush; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(IsIconic(GetParent(hWnd))) hBrush = GetStockObject(BLACK_BRUSH); else hBrush = GETHBRBACKGROUND(hWnd); GetClientRect(hWnd, &rcClient); GetUpdateRect(hWnd, &rcView, 0); if(bInScroll || pData->LeadBitmap.Flags.Allocated) { IntersectRect(&rcView, &pData->rcView, &rcClient); hClientRgn = CreateRectRgnIndirect(&rcClient); hFillRgn = CreateRectRgnIndirect(&rcView); CombineRgn(hFillRgn, hClientRgn, hFillRgn, RGN_DIFF); FillRgn(hDC, hFillRgn, hBrush); DeleteObject(hFillRgn); DeleteObject(hClientRgn); } else FillRect(hDC, &rcClient, hBrush); return TRUE; } static L_VOID Child_OnSize (HWND hWnd, L_UINT nState, L_INT nCx, L_INT nCy) { static L_BOOL fSizeInUse = FALSE; L_INT nWidth; L_INT nHeight; L_INT nVScroll; L_INT nHScroll; DWORD dwStyle; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; if (!fSizeInUse) { fSizeInUse = TRUE; if (!IsIconic(hWnd))// if window is normal { if (!pData->LeadBitmap.Flags.Allocated) { /* if bitmap is not allocated then set width and height to ZERO */ nWidth = 0; nHeight = 0; } else // if bitmap is allocated, then set the width and height to bitmap width and height { nWidth = BITMAPWIDTH(&pData->LeadBitmap); nHeight= BITMAPHEIGHT(&pData->LeadBitmap); } // Set client dimensions to current width and height pData->cxClient = nCx; pData->cyClient = nCy; dwStyle = GetWindowLong (hWnd, GWL_STYLE); nVScroll = GetSystemMetrics (SM_CXVSCROLL); // Get Vertical scroll arrow width nHScroll = GetSystemMetrics (SM_CXHSCROLL); // Get Horizontal scroll arrow width if (WS_VSCROLL & dwStyle) // if Vertical scroll pData->cxClient += nVScroll; if (WS_HSCROLL & dwStyle) // if Horizontal scroll pData->cyClient += nHScroll; if (pData->cxClient < nWidth) // if client width < current width { pData->cyClient -= nHScroll; if (pData->cyClient < nHeight) pData->cxClient -= nVScroll; } else if (pData->cyClient < nHeight) // if client height < current height { pData->cxClient -= nVScroll; if (pData->cxClient < nWidth) pData->cyClient -= nHScroll; } pData->nVScrollStep = max (1, pData->cyClient / SCROLL_RATIO); pData->nHScrollStep = max (1, pData->cxClient / SCROLL_RATIO); pData->nVScrollMax = max (0, (nHeight - pData->cyClient - 1)); pData->nHScrollMax = max (0, (nWidth - pData->cxClient - 1)); pData->nVScrollPos = max (0, min (pData->nVScrollPos, pData->nVScrollMax)); pData->nHScrollPos = max (0, min (pData->nHScrollPos, pData->nHScrollMax)); if (pData->LeadBitmap.Flags.Allocated) { SetRect (&pData->rcView, 0, 0, nWidth, nHeight); OffsetRect (&pData->rcView, -pData->nHScrollPos, -pData->nVScrollPos); } SetScrollRange (hWnd, SB_HORZ, 0, pData->nHScrollMax, TRUE); SetScrollRange (hWnd, SB_VERT, 0, pData->nVScrollMax, TRUE); SetScrollPos (hWnd, SB_HORZ, pData->nHScrollPos, TRUE); SetScrollPos (hWnd, SB_VERT, pData->nVScrollPos, TRUE); } else // if window is iconized { // Retain the x-client and y-client area pData->cxClient = nCx; pData->cyClient = nCy; // set client area SetRect (&pData->rcView, 0, 0, pData->cxClient, pData->cyClient); } fSizeInUse = FALSE; } FORWARD_WM_SIZE(hWnd,nState, nCx, nCy, DefMDIChildProc); } static L_BOOL Child_OnQueryNewPalette (HWND hWnd) { HDC hDC; L_INT nNoColors = 0; HPALETTE hOldPal; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(pData->hPalette) { DeleteObject(pData->hPalette); pData->hPalette = NULL; } if(pData->LeadBitmap.Flags.Allocated) { hDC = GetDC(hWnd); pData->hPalette = L_CreatePaintPalette(hDC, &pData->LeadBitmap); if(pData->hPalette) { hOldPal = SelectPalette(hDC, pData->hPalette, FALSE); nNoColors = RealizePalette(hDC); if(nNoColors) InvalidateRect(hWnd, NULL, FALSE); SelectPalette(hDC, hOldPal, TRUE); } ReleaseDC(hWnd, hDC); } return nNoColors; } static L_VOID Child_OnCommand (HWND hWnd, L_INT id, HWND hwndCtl, L_UINT codeNotify) { HCURSOR hOldCur; L_UINT32 uOrder = 0; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); hOldCur = SetCursor(LoadCursor(NULL, IDC_WAIT)); switch(id) { case IDM_FILE_SAVE: SaveBitmapFile (hWnd); break; case IDM_EDIT_COPY: L_CopyToClipboard(hWnd, &pData->LeadBitmap,COPY2CB_EMPTY|COPY2CB_DIB); break; case IDM_EDIT_PASTE: if(pData->rcSetRegion.left == pData->rcSetRegion.right || pData->rcSetRegion.top == pData->rcSetRegion.bottom) PasteBitmap(hWnd); else PasteBitmapRgn(hWnd); break; case IDM_TOOL_SETREGION_NONE: pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; nRgnType = 0; if (L_BitmapHasRgn(&pData->LeadBitmap)) L_FreeBitmapRgn(&pData->LeadBitmap); InvalidateRect(hWnd, NULL,FALSE); break; case IDM_TOOL_SETREGION_RECTANGLE: nRgnType = 1; break; case IDM_TOOL_SETREGION_ROUNDEDRECTANGLE: nRgnType = 2; break; case IDM_TOOL_SETREGION_ELLIPSE: nRgnType = 3; break; case IDM_TOOL_SETREGION_FREEHAND: nRgnType = 4; break; case IDM_TOOL_CANCLEREGION: nRgn =0; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; if (L_BitmapHasRgn(&pData->LeadBitmap)) L_FreeBitmapRgn(&(pData->LeadBitmap)); InvalidateRect(hWnd, NULL, FALSE); break; case IDM_SHOWSTATUS_STATUS: nStat =6; if(!hStatusDlg ) DoStatusDlg(IDD_STATUS, hWnd, (DLGPROC) StatusDlgProc); break; } SetCursor(hOldCur); return; } L_INT PasteBitmapRgn (HWND hWnd) { pCHILDDATA pData; HRGN hTempRgn; RECT rcRgnBox; BITMAPHANDLE BitmapRgn; L_UINT nRet; L_UINT uOrder; if (!L_ClipboardReady ()) return 0; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return 0; L_InitBitmap(&BitmapRgn,sizeof(BITMAPHANDLE), 0, 0, 0); nRet = L_CopyFromClipboard(hWnd, &BitmapRgn,sizeof(BITMAPHANDLE)); if(nRet == SUCCESS) { if(L_BitmapHasRgn(&BitmapRgn)) { L_ChangeBitmapViewPerspective(NULL, &BitmapRgn,sizeof(BITMAPHANDLE), TOP_LEFT); switch(pData->LeadBitmap.Order) { case ORDER_BGR: uOrder = CRF_BYTEORDERBGR; break; case ORDER_RGB: uOrder = CRF_BYTEORDERRGB; break; case ORDER_GRAY: uOrder = CRF_BYTEORDERGRAY; break; } L_ColorResBitmap(&BitmapRgn, &BitmapRgn,sizeof(BITMAPHANDLE),pData->LeadBitmap.BitsPerPixel, CRF_USERHPALETTE | CRF_FLOYDSTEINDITHERING | uOrder, NULL, pData->hPalette, 0, NULL, NULL); if(pData->bmFloater.Flags.Allocated) L_FreeBitmap(&pData->bmFloater); L_GetBitmapRgnBounds(&BitmapRgn, NULL, &rcRgnBox); L_CopyBitmapRect(&pData->bmFloater, &BitmapRgn,sizeof(BITMAPHANDLE), rcRgnBox.left, rcRgnBox.top, rcRgnBox.right - rcRgnBox.left, rcRgnBox.bottom - rcRgnBox.top); L_GetBitmapRgnHandle(&BitmapRgn, NULL, &hTempRgn); GetRgnBox(hTempRgn, &rcRgnBox); OffsetRgn(hTempRgn, -rcRgnBox.left, -rcRgnBox.top); L_SetBitmapRgnHandle(&pData->LeadBitmap, NULL, hTempRgn, L_RGN_SET); L_GetBitmapRgnBounds(&pData->LeadBitmap, NULL, &rcRgnBox); L_CopyBitmapRect(&pData->bmSave, &pData->LeadBitmap,sizeof(BITMAPHANDLE), rcRgnBox.left, rcRgnBox.top, RECTWIDTH(&rcRgnBox), RECTHEIGHT(&rcRgnBox)); L_GetBitmapRgnBounds(&pData->LeadBitmap, NULL, &rcRgnBox); L_CombineBitmap(&pData->LeadBitmap, 0, 0, BITMAPWIDTH(&pData->bmFloater), BITMAPHEIGHT(&pData->bmFloater), &pData->bmFloater, 0, 0, L_SRCCOPY); fValidDraw = FALSE ; InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); L_FreeBitmap(&BitmapRgn); } else PasteBitmap(hWnd); } return nRet; } static L_VOID Child_OnPaint (HWND hWnd) { HDC hdc; HPALETTE hSavedPalette = NULL; pCHILDDATA pData; PAINTSTRUCT ps; pData = (pCHILDDATA)GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return; if (!pData->LeadBitmap.Flags.Allocated) return; hdc = BeginPaint(hWnd,&ps); if (pData->hPalette) { hSavedPalette = SelectPalette (hdc, pData->hPalette, TRUE); RealizePalette (hdc); } L_PaintDC(hdc,&pData->LeadBitmap,NULL,NULL, &pData->rcView, &ps.rcPaint, SRCCOPY); if (hSavedPalette) SelectPalette (hdc, hSavedPalette, TRUE); EndPaint(hWnd,&ps); } L_INT SaveBitmapFile (HWND hWnd) { OPENFILENAME SaveFileName; SAVEDLGPARAMS FSParm; SAVEFILEOPTION SaveFileOption; L_UINT uFlags=0; L_TCHAR buf[80]; HCURSOR hCursor; L_INT nRet; FILESAVEFORMAT Formats[2]; pCHILDDATA pData; FILESAVEFORMATBPP CmpSub[1] = {sizeof(FILESAVEFORMATBPP),24,DLG_FF_SAVE_SUB_CMP_NONPROGRESSIVE|DLG_FF_SAVE_SUB_CMP_PROGRESSIVE}; FILESAVEFORMATBPP tifSub[1] = {sizeof(FILESAVEFORMATBPP),24, DLG_FF_SAVE_SUB_TIFF1_CCITT | DLG_FF_SAVE_SUB_TIFF1_CCITT_G3_1D | DLG_FF_SAVE_SUB_TIFF1_CCITT_G3_2D | DLG_FF_SAVE_SUB_TIFF1_CCITT_G4 | DLG_FF_SAVE_SUB_TIFF1_UNCOMPRESSEDRGB | DLG_FF_SAVE_SUB_TIFF1_RLERGB | DLG_FF_SAVE_SUB_TIFF1_LZWRGB |DLG_FF_SAVE_SUB_TIFF1_JBIG }; Formats[0].uStructSize = sizeof(FILESAVEFORMAT); Formats[0].nFormat = DLG_FF_SAVE_LEAD; Formats[0].nBppCount = 1; Formats[0].pFileSaveFormatBpp = CmpSub; Formats[1].uStructSize = sizeof(FILESAVEFORMAT); Formats[1].nFormat = DLG_FF_SAVE_TIFF; Formats[1].nBppCount = 1; Formats[1].pFileSaveFormatBpp = tifSub; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return 0; _fmemset(&SaveFileName, 0, sizeof(OPENFILENAME)); _fmemset(&FSParm, 0, sizeof(SAVEDLGPARAMS)); FSParm.uStructSize = sizeof(SAVEDLGPARAMS); FSParm.nQFactor = 2; SaveFileName.lStructSize = sizeof(OPENFILENAME); SaveFileName.lpstrInitialDir = NULL; SaveFileName.lpstrTitle = TEXT("Save As"); SaveFileName.nFileOffset = 0; SaveFileName.Flags = 0; /* add some formats */ FSParm.pFileFormats = Formats; FSParm.uFileFormatsCount = 2; nRet = L_DlgSave(hWnd,&SaveFileName,&FSParm); if(nRet == SUCCESS_DLG_OK) { L_GetDefaultSaveFileOption(&SaveFileOption, sizeof(SAVEFILEOPTION)); SaveFileOption.Flags &= ~(ESO_REPLACEPAGE|ESO_INSERTPAGE); switch(FSParm.uSaveMulti) { case MULTIPAGE_OPERATION_OVERWRITE: SaveFileOption.PageNumber = 1; break; case MULTIPAGE_OPERATION_APPEND: SaveFileOption.PageNumber = 2; break; case MULTIPAGE_OPERATION_REPLACE: SaveFileOption.PageNumber = FSParm.nPageNumber; SaveFileOption.Flags |= ESO_REPLACEPAGE; break; case MULTIPAGE_OPERATION_INSERT: SaveFileOption.PageNumber = FSParm.nPageNumber; SaveFileOption.Flags |= ESO_INSERTPAGE; break; } hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); if (FSParm.nBitsPerPixel <= 4 && (&pData->LeadBitmap)->BitsPerPixel != FSParm.nBitsPerPixel) uFlags = SAVEFILE_FIXEDPALETTE; else uFlags = SAVEFILE_OPTIMIZEDPALETTE; nRet = L_SaveFile( FSParm.szFileName, &pData->LeadBitmap, FSParm.nFormat, FSParm.nBitsPerPixel, FSParm.nQFactor, uFlags, NULL, NULL, &SaveFileOption ); SetCursor (hCursor); if (nRet != SUCCESS) { wsprintf (buf, TEXT("ERROR %d saving the file %s."), nRet, (LPTSTR) FSParm.szFileName); MessageBox (hWnd, buf, TEXT("ERROR"), MB_OK); } else return (TRUE); } return (2); } static L_VOID Child_OnClose (HWND hWnd) { FORWARD_WM_CLOSE(hWnd, DefMDIChildProc); } static L_VOID Child_OnDestroy (HWND hWnd) { pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(pData) { if(L_BitmapHasRgn(&pData->LeadBitmap)) KillTimer(hWnd, 1); if(pData->LeadBitmap.Flags.Allocated) { L_FreeBitmap(&pData->LeadBitmap); L_InitBitmap(&pData->LeadBitmap, sizeof(BITMAPHANDLE),0, 0, 0); } if(pData->bmFloater.Flags.Allocated) { L_FreeBitmap(&pData->bmFloater); L_InitBitmap(&pData->bmFloater, sizeof(BITMAPHANDLE),0, 0, 0); } if(pData->bmSave.Flags.Allocated) { L_FreeBitmap(&pData->bmSave); L_InitBitmap(&pData->bmSave,sizeof(BITMAPHANDLE), 0, 0, 0); } if(pData->pszTitle) { GlobalFreePtr(pData->pszTitle); pData->pszTitle = NULL; } if(pData->hPalette) DeletePalette(pData->hPalette); if(pData->hrgnRegion) { DeleteRgn(pData->hrgnRegion); pData->hrgnRegion = NULL; } if(pData->hrgnFloater) { DeleteRgn(pData->hrgnFloater); pData->hrgnFloater = NULL; } } } static L_VOID Child_OnMDIActivate (HWND hWnd, L_BOOL fActive, HWND hWndActivate, HWND hWndDeactivate) { pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(hWnd == GetCapture()) ReleaseCapture(); if(fActive) { Child_OnQueryNewPalette(hWnd); SendMessage(hWndClient, WM_MDISETMENU, (WPARAM) hMenuChild, (LPARAM) hMenuChildWindow); } else SendMessage(hWndClient, WM_MDISETMENU, (WPARAM) hMenuInit, (LPARAM) hMenuInitWindow); DrawMenuBar(hWndFrame); } L_VOID ClientToBitmap(pCHILDDATA pData, PPOINT pPoint) { if (!pPoint || !pData) return; pPoint->x = ((L_INT32)(pPoint->x - pData->rcView.left)*BITMAPWIDTH(&pData->LeadBitmap) / RECTWIDTH(&pData->rcView)); pPoint->y = ((L_INT32)(pPoint->y - pData->rcView.top)*BITMAPHEIGHT(&pData->LeadBitmap) / RECTHEIGHT(&pData->rcView)); L_PointToBitmap(&pData->LeadBitmap, TOP_LEFT, &pPoint->x, &pPoint->y); nRgn =5; } static L_VOID Child_OnLButtonDown (HWND hWnd, L_BOOL bDoubleClick, L_INT x, L_INT y, L_UINT keyFlags) { POINT ptMousePos= {0,0}; RECT rcClient; L_INT nId = 0; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; if(!GetCapture()) { SetCapture(hWnd); GetClientRect(hWnd, &rcClient); IntersectRect(&rcClient, &rcClient,&pData->rcView); if(nRgnType) { if(pData->uTimerID) KillTimer(hWnd, 1); ptMousePos.x = x; ptMousePos.y = y; if(PtInRect(&rcClient, ptMousePos)) { ClientToBitmap(pData, &ptMousePos); if(L_BitmapHasRgn(&pData->LeadBitmap) && L_IsPtInBitmapRgn(&pData->LeadBitmap, ptMousePos.y, ptMousePos.x)) { hOldCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); CreateRegionBitmaps(hWnd); pData->deltaX = pData->deltaY = 0; pData->xAnchor = x; pData->yAnchor = y; pData->bMovingFloater = TRUE; nId = 2; } else { if(L_BitmapHasRgn(&(pData->LeadBitmap))) L_FreeBitmapRgn(&pData->LeadBitmap); InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); hOldCursor = SetCursor (LoadCursor (NULL, IDC_CROSS)); pData->ptBeg.x = pData->ptEnd.x = x; pData->ptBeg.y = pData->ptEnd.y = y; pData->rcSetRegion.left = x; pData->rcSetRegion.top = y; if(nRgnType==4) { if(pData->pPolyPt) GlobalFreePtr(pData->pPolyPt); pData->pPolyPt = (POINT *) GlobalAllocPtr(GHND, sizeof(POINT)); pData->pPolyPt[pData->nPtCount++] = pData->ptBeg; } else DrawShape (hWnd); pData->bDrawShape = TRUE; nId = 3; } } } else if(PtInRect(&rcClient, ptMousePos)) nId = 1; ShowStatus(nId,x,y); } return; } static L_VOID Child_OnMouseMove (HWND hWnd, L_INT x, L_INT y, L_UINT keyFlags) { pCHILDDATA pData; L_INT nId = 0; L_INT nBmpWidth, nBmpHeight; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; if(GetCapture() == hWnd ) { if(pData->bMovingFloater) { pData->ptEnd.x = x; pData->ptEnd.y = y; MoveFloater(hWnd); nId = 4; } else if(pData->bDrawShape) { if(nRgnType==4 && pData->pPolyPt) { pData->pPolyPt = (POINT *) GlobalReAllocPtr(pData->pPolyPt, (pData->nPtCount+1) * sizeof(POINT), GHND); pData->ptEnd.x = x; pData->ptEnd.y = y; pData->pPolyPt[pData->nPtCount++]=pData->ptEnd; DrawPoly(hWnd); } else { DrawShape (hWnd); nBmpWidth = BITMAPWIDTH(&pData->LeadBitmap); nBmpHeight = BITMAPHEIGHT(&pData->LeadBitmap); pData->ptEnd.x = (x > nBmpWidth) ? nBmpWidth : ((x < 0) ? 0 : x); pData->ptEnd.y = (y > nBmpHeight) ? nBmpHeight : ((y < 0) ? 0 : y); DrawShape (hWnd); } nId = 5; } else if(keyFlags & MK_LBUTTON) nId = 6; ShowStatus(nId,x,y); return; } } static L_VOID Child_OnLButtonUp (HWND hWnd, L_INT x, L_INT y, L_UINT keyFlags) { pCHILDDATA pData; L_INT nWidthEllipse; L_INT nHightEllipse; L_INT nId = 0; L_INT nRet; L_INT nOrigX; L_INT nOrigY; L_INT nOrigWidth; L_INT nOrigHeight; L_INT32 dwValue; RGNXFORM XForm; RECT rcRgnBox; RECT rcOutofBitmap; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if(!pData) return; if(GetCapture() == hWnd ) { if(pData->bDrawShape) { DrawShape (hWnd); pData->rcSetRegion.right = max(x, pData->rcSetRegion.left); pData->rcSetRegion.bottom = max(y, pData->rcSetRegion.top); pData->rcSetRegion.left = min(x, pData->rcSetRegion.left); pData->rcSetRegion.top = min(y, pData->rcSetRegion.top); XForm.uViewPerspective = TOP_LEFT; XForm.nXScalarNum = 1; XForm.nYScalarNum = 1; XForm.nXScalarDen = 1; XForm.nYScalarDen = 1; XForm.nXOffset = GetScrollPos(hWnd, SB_HORZ); XForm.nYOffset = GetScrollPos(hWnd, SB_VERT); L_RectFromBitmap(&(pData->LeadBitmap), TOP_LEFT, &pData->rcSetRegion); pData->bDrawFrame = TRUE; pData->bDrawShape = FALSE; switch(nRgnType) { case 1: nRgn =0; nRet = L_SetBitmapRgnRect(&(pData->LeadBitmap), &XForm, &pData->rcSetRegion, L_RGN_SET); break; case 2: nRgn =0; nWidthEllipse = abs(pData->rcSetRegion.right - pData->rcSetRegion.left) / 4; nHightEllipse = abs(pData->rcSetRegion.bottom - pData->rcSetRegion.top) / 4; nRet = L_SetBitmapRgnRoundRect(&(pData->LeadBitmap), &XForm, &pData->rcSetRegion, nWidthEllipse , nHightEllipse ,L_RGN_SET); break; case 3: nRgn =0; nRet = L_SetBitmapRgnEllipse(&(pData->LeadBitmap), &XForm, &pData->rcSetRegion, L_RGN_SET); break ; case 4: nRgn =0; if(pData->pPolyPt) { nRet = L_SetBitmapRgnPolygon(&(pData->LeadBitmap), &XForm, pData->pPolyPt, pData->nPtCount, L_POLY_WINDING, L_RGN_SET); GlobalFreePtr(pData->pPolyPt); pData->nPtCount = 0; } break ; } if(nRet == SUCCESS) { L_GetBitmapRgnBounds(&pData->LeadBitmap,NULL,&rcRgnBox); L_CopyBitmapRect(&pData->bmSave, &pData->LeadBitmap, sizeof(BITMAPHANDLE),rcRgnBox.left, rcRgnBox.top, RECTWIDTH(&rcRgnBox), RECTHEIGHT(&rcRgnBox)); nId = 7; pData->uTimerID = SetTimer(hWnd, 1, 100, NULL); } if(pData->rcSetRegion.left != pData->rcSetRegion.right || pData->rcSetRegion.top != pData->rcSetRegion.bottom) nRgn =5; InvalidateRect(hWnd,NULL,TRUE); SetCursor(hOldCursor); } else if(pData->bMovingFloater) { pData->bMovingFloater = FALSE; pData->bDrawFrame = FALSE; // get the original rectangle in bitmap coordinates SetRect(&rcRgnBox, pData->xMoveSrc, pData->yMoveSrc, pData->xMoveSrc + pData->nMoveWidth - 1, pData->yMoveSrc + pData->nMoveHeight - 1); // change it to display coordinates L_RectFromBitmap(&pData->LeadBitmap, TOP_LEFT, &rcRgnBox); // calculate the position in the bitmap based on the original position and by // the distance moved. This helps reduce the approximation errors // Favor the left and up move. // Consider a 7:1 zoomin factor. If you move to the right by 6 pixels // on the screen, you don't move in the original bitmap. But if you // move 1 pixel to the left, you move 1 pixel to the left in original bitmap dwValue = (L_INT32)pData->deltaX * BITMAPWIDTH(&pData->LeadBitmap); if( pData->deltaX < 0 ) // favor the moving to the left dwValue -= RECTWIDTH(&pData->rcView) - 1; OffsetRect(&rcRgnBox, (L_INT)(dwValue/RECTWIDTH(&pData->rcView)), 0); dwValue = (L_INT32)pData->deltaY * BITMAPHEIGHT(&pData->LeadBitmap); if( pData->deltaY < 0 ) // favor the moving to the top dwValue -= RECTHEIGHT(&pData->rcView) - 1; OffsetRect(&rcRgnBox, 0, (L_INT)(dwValue / RECTHEIGHT(&pData->rcView))); // now rc contains the coordinates in TOP_LEFT ViewPerspective. // Change them in bitmap's ViewPerspective L_RectToBitmap(&pData->LeadBitmap, TOP_LEFT, &rcRgnBox); // now I can update pData->xMoveSrc and pData->yMoveSrc nOrigX = pData->xMoveSrc = rcRgnBox.left; // save these coordinates for the combine later on nOrigY = pData->yMoveSrc = rcRgnBox.top; // SafeCopyBitmapRect might change them nOrigWidth = pData->nMoveWidth; nOrigHeight = pData->nMoveHeight; nRet = IntersectRect(&rcOutofBitmap, &rcRgnBox , &pData->rcView); if(!nRet) { L_FreeBitmapRgn(&pData->LeadBitmap); ReleaseCapture(); SetCursor(hOldCursor); return; } // save the background SafeCopyBitmapRect(&pData->bmSave, &pData->LeadBitmap, &pData->xMoveSrc, &pData->yMoveSrc, &pData->nMoveWidth, &pData->nMoveHeight); // set up the transform structure. XForm.uViewPerspective = pData->LeadBitmap.ViewPerspective; XForm.nXScalarNum = XForm.nXScalarDen = 1; XForm.nYScalarNum = XForm.nYScalarDen = 1; XForm.nXOffset = nOrigX; XForm.nYOffset = nOrigY; // set the region in the original bitmap L_SetBitmapRgnHandle( &pData->LeadBitmap, &XForm, pData->hrgnRegion, L_RGN_SET ); SetRect(&rcRgnBox, nOrigX, nOrigY, nOrigX + nOrigWidth, nOrigY + nOrigHeight); L_RectFromBitmap(&pData->LeadBitmap, TOP_LEFT, &rcRgnBox); // copy the floater bitmap to the new position L_CombineBitmap(&pData->LeadBitmap, rcRgnBox.left, rcRgnBox.top, RECTWIDTH(&rcRgnBox), RECTHEIGHT(&rcRgnBox), &pData->bmFloater, 0, 0, L_SRCCOPY); if(pData->hrgnRegion) { DeleteRgn(pData->hrgnRegion); pData->hrgnRegion = NULL; } if(pData->hrgnFloater) { DeleteRgn(pData->hrgnFloater); pData->hrgnFloater = NULL; } // and we can still move InvalidateRect (hWnd, NULL, FALSE); UpdateWindow (hWnd); pData->uTimerID = SetTimer(hWnd, 1, 100, NULL); SetCursor(hOldCursor); nId = 9; } else nId = 8; ReleaseCapture(); ShowStatus(nId,x,y); } return; } static L_VOID Child_OnTimer(HWND hWnd, UINT id) { RGNXFORM XForm; pCHILDDATA pData; HDC hDC; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (pData->uTimerID != id) return; if(L_BitmapHasRgn(&pData->LeadBitmap)) { hDC = GetDC(hWnd); if (!hDC) return; XForm.uViewPerspective = TOP_LEFT; XForm.nXScalarNum = 1; XForm.nXScalarDen = 1; XForm.nYScalarNum = 1; XForm.nYScalarDen = 1; XForm.nXOffset = -GetScrollPos(hWnd, SB_HORZ); XForm.nYOffset = -GetScrollPos(hWnd, SB_VERT); pData->uFrameType = (pData->uFrameType + 2) % 8; L_FrameBitmapRgn(hDC, &pData->LeadBitmap, &XForm, pData->uFrameType ); ReleaseDC(hWnd, hDC); } } static VOID Child_OnSetFocus(HWND hWnd, HWND hWndOldFocus) { pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return; if(L_BitmapHasRgn(&pData->LeadBitmap)) pData->uTimerID = SetTimer(hWnd, 1, 100, NULL); } static VOID Child_OnKillFocus(HWND hWnd, HWND hWndNewFocus) { pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return; if(L_BitmapHasRgn(&pData->LeadBitmap)) KillTimer(hWnd, 1); } L_VOID MoveFloater(HWND hWnd) { HDC hdc; HDC hdcUnion; HDC hdcRegion; HBITMAP hbmUnion = 0, holdUnion, holdRegion; RECT rcSave; RECT rcUnion; RECT rcRegion; pCHILDDATA pData; L_INT nUnionWidth = 0; L_INT nUnionHeight = 0; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return; hdc = GetDC (hWnd); /* All the x values are relative to the client window; viewport of the DC matches that already */ IntersectClipRect (hdc, 0, 0, RECTWIDTH(&pData->rcView), RECTHEIGHT(&pData->rcView)); SetRect (&rcSave, 0, 0, pData->nFloaterWidth, pData->nFloaterHeight); rcRegion = rcSave; OffsetRect (&rcSave, pData->xFloaterDest, pData->yFloaterDest); pData->deltaX += pData->ptEnd.x - pData->xAnchor; pData->deltaY += pData->ptEnd.y - pData->yAnchor; pData->xFloaterDest = pData->xFloaterDest + pData->ptEnd.x - pData->xAnchor; pData->yFloaterDest = pData->yFloaterDest + pData->ptEnd.y - pData->yAnchor; pData->xAnchor = pData->ptEnd.x; pData->yAnchor = pData->ptEnd.y; OffsetRect (&rcRegion, pData->xFloaterDest, pData->yFloaterDest); if (IntersectRect (&rcUnion, &rcSave, &rcRegion)) { UnionRect (&rcUnion, &rcSave, &rcRegion); /* create a DDB from the origial bitmap the size of the union */ nUnionWidth = rcUnion.right - rcUnion.left; nUnionHeight = rcUnion.bottom - rcUnion.top; hbmUnion = CreateCompatibleBitmap(hdc, nUnionWidth, nUnionHeight ); OffsetRect (&rcRegion, -rcUnion.left, -rcUnion.top); OffsetRect (&rcSave, -rcUnion.left, -rcUnion.top); hdcUnion = CreateCompatibleDC (hdc); holdUnion = SelectObject (hdcUnion, hbmUnion); hdcRegion = CreateCompatibleDC (hdc); holdRegion = SelectObject (hdcRegion, pData->hbmSave); /* copy to the union DDB what's on the screen */ BitBlt(hdcUnion, 0, 0, nUnionWidth, nUnionHeight, hdc, rcUnion.left, rcUnion.top, SRCCOPY); /* restore the background into the union. Now the union bitmap should contain what should on the screen without the floating bitmap */ BitBlt(hdcUnion, rcSave.left, rcSave.top, pData->nFloaterWidth, pData->nFloaterHeight, hdcRegion, 0, 0, SRCCOPY); /* get the new background into hbmSave */ BitBlt(hdcRegion, 0, 0, pData->nFloaterWidth, pData->nFloaterHeight, hdcUnion, rcRegion.left, rcRegion.top, SRCCOPY); /* Paint only what's is inside the region using Windows's ability to do clipping. Select the region into the union DC */ SelectObject( hdcUnion, pData->hrgnFloater ); OffsetClipRgn( hdcUnion, rcRegion.left, rcRegion.top); /* select the floater DDB */ SelectObject( hdcRegion, pData->hbmFloater); /* Now the union DDB is what should be on the screen */ BitBlt(hdcUnion, rcRegion.left, rcRegion.top, pData->nFloaterWidth, pData->nFloaterHeight, hdcRegion, 0, 0, SRCCOPY); /* blast the whole thing to the screen */ BitBlt(hdc, rcUnion.left, rcUnion.top, nUnionWidth, nUnionHeight, hdcUnion, 0, 0, SRCCOPY); SelectObject(hdcUnion, holdUnion); DeleteDC(hdcUnion); SelectObject(hdcRegion, holdRegion); DeleteDC(hdcRegion); DeleteObject(hbmUnion); } else { hdcRegion = CreateCompatibleDC (hdc); holdRegion = SelectObject (hdcRegion, pData->hbmSave); /* restore the background */ BitBlt(hdc, rcSave.left, rcSave.top, pData->nFloaterWidth, pData->nFloaterHeight, hdcRegion, 0, 0, SRCCOPY); /* save the background */ BitBlt (hdcRegion, 0, 0, pData->nFloaterWidth, pData->nFloaterHeight, hdc, pData->xFloaterDest, pData->yFloaterDest, SRCCOPY); /* Paint only what's is inside the region using Windows's ability to do clipping. Select the floater into the union DC */ SelectObject(hdc, pData->hrgnFloater); OffsetClipRgn(hdc, pData->xFloaterDest, pData->yFloaterDest); IntersectClipRect(hdc, 0, 0, RECTWIDTH(&pData->rcView), RECTHEIGHT(&pData->rcView)); /* paint only what's INSIDE the region */ SelectObject(hdcRegion, pData->hbmFloater); BitBlt(hdc, pData->xFloaterDest, pData->yFloaterDest, pData->nFloaterWidth, pData->nFloaterHeight, hdcRegion, 0, 0, SRCCOPY); SelectObject(hdcRegion, holdRegion); DeleteDC(hdcRegion); } ReleaseDC (hWnd, hdc); } L_INT SafeCopyBitmapRect(pBITMAPHANDLE pBitmapDst, pBITMAPHANDLE pBitmapSrc, L_INT L_FAR * pXSrc, L_INT L_FAR * pYSrc, L_INT L_FAR * pWidth, L_INT L_FAR * pHeight) { RECT rc; /* check the input parameters */ if( *pXSrc < 0 ) { *pWidth += *pXSrc; *pXSrc = 0; } if(*pYSrc < 0) { *pHeight += *pYSrc; *pYSrc = 0; } if(*pXSrc + *pWidth > pBitmapSrc->Width) *pWidth = pBitmapSrc->Width - *pXSrc; if(*pYSrc + *pHeight > pBitmapSrc->Height) *pHeight = pBitmapSrc->Height - *pYSrc; if(pBitmapDst->Flags.Allocated) L_FreeBitmap( pBitmapDst ); L_InitBitmap(pBitmapDst, sizeof(BITMAPHANDLE),*pWidth, *pHeight, pBitmapSrc->BitsPerPixel); pBitmapDst->ViewPerspective = pBitmapSrc->ViewPerspective; pBitmapDst->Order = pBitmapSrc->Order; if(L_AllocateBitmap(pBitmapDst, TYPE_CONV) != SUCCESS) return FAILURE; if(pBitmapSrc->BitsPerPixel <= 8) L_CopyBitmapPalette(pBitmapDst, pBitmapSrc); SetRect(&rc, *pXSrc, *pYSrc, *pXSrc + *pWidth, *pYSrc + *pHeight); L_RectFromBitmap(pBitmapSrc, TOP_LEFT, &rc); L_CombineBitmap(pBitmapDst, 0, 0, RECTWIDTH(&rc), RECTHEIGHT(&rc), pBitmapSrc, rc.left, rc.top, L_SRCCOPY); return SUCCESS; } HBITMAP ResizeToDDB(pCHILDDATA pData, HDC hDisplay, pBITMAPHANDLE pBitmap, L_INT xSrcLeft, L_INT ySrcTop, L_INT nNewWidth, L_INT nNewHeight, L_INT nClientWidth, L_INT nClientHeight) { HDC hDisplayMem; HDC hdcDevice; HBITMAP hBitmap; HBITMAP hbmSave; L_UINT32 ulFlags; RECT rcDest, rcDestClip; HPALETTE hpalSave = NULL; hdcDevice = (hDisplay) ? hDisplay : GetDC (NULL); hDisplayMem = CreateCompatibleDC (hdcDevice); if ((hBitmap = CreateCompatibleBitmap (hdcDevice, nNewWidth, nNewHeight)) == 0) { if (!hDisplay) ReleaseDC (NULL, hdcDevice); return (NULL); } hbmSave = SelectObject(hDisplayMem, hBitmap); if (pData->hPalette) { hpalSave = SelectPalette (hDisplayMem, pData->hPalette, TRUE); RealizePalette(hDisplayMem); } ulFlags = L_GetDisplayMode (); L_SetDisplayMode (DISPLAYMODE_INDEXEDPAINT, 0); SetRect(&rcDestClip, 0, 0, nNewWidth, nNewHeight); SetRect(&rcDest, - xSrcLeft, - ySrcTop, nClientWidth - xSrcLeft, nClientHeight - ySrcTop); L_PaintDC (hDisplayMem, pBitmap, NULL, NULL, &rcDest, &rcDestClip, SRCCOPY); L_SetDisplayMode (DISPLAYMODE_RESETPOSITIONS, ulFlags); if (hpalSave) SelectPalette (hDisplayMem, hpalSave, TRUE); SelectObject(hDisplayMem, hbmSave); DeleteDC(hDisplayMem); if (!hDisplay) ReleaseDC (NULL, hdcDevice); return (hBitmap); } L_INT CreateRegionBitmaps(HWND hWnd) { HDC hdc; RGNXFORM XForm; RECT rcRegion; RECT rcFloater; pCHILDDATA pData; RECT rc; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return FAILURE; hdc = GetDC(hWnd); nRgn =5; /* get the position of the region in bitmap coordinates */ XForm.uViewPerspective = pData->LeadBitmap.ViewPerspective; XForm.nXScalarNum = XForm.nXScalarDen = 1; XForm.nYScalarNum = XForm.nYScalarDen = 1; XForm.nXOffset = XForm.nYOffset = 0; L_GetBitmapRgnBounds(&pData->LeadBitmap,&XForm,&rcRegion); pData->xMoveSrc = rcRegion.left; pData->yMoveSrc = rcRegion.top; pData->nMoveWidth = RECTWIDTH(&rcRegion); pData->nMoveHeight = RECTHEIGHT(&rcRegion); /* delete the previous region */ if( pData->hrgnRegion ) DeleteObject(pData->hrgnRegion); /* get the Windows region handle from original bitmap. Current offset is xMoveSrc,yMoveSrc and I want it at 0,0 */ XForm.nXOffset = - pData->xMoveSrc; XForm.nYOffset = - pData->yMoveSrc; L_GetBitmapRgnHandle( &pData->LeadBitmap, &XForm, &pData->hrgnRegion ); /* get the position of the region in client coordinates. This is how we find out the size of the floater. We have to to it here in case the zoom factor has changed since the creation of the region. I want these coordinates to be TOP_LEFT, like the screen! */ XForm.uViewPerspective = TOP_LEFT; XForm.nXScalarNum = 1; XForm.nYScalarNum = 1; XForm.nXScalarDen = 1; XForm.nYScalarDen = 1; XForm.nXOffset = pData->rcView.left; XForm.nYOffset = pData->rcView.top; L_GetBitmapRgnBounds(&pData->LeadBitmap,&XForm,&rcFloater); pData->xFloaterDest = rcFloater.left; pData->yFloaterDest = rcFloater.top; pData->nFloaterWidth = RECTWIDTH(&rcFloater); pData->nFloaterHeight = RECTHEIGHT(&rcFloater); /* delete the previous floater region */ if( pData->hrgnFloater ) DeleteObject( pData->hrgnFloater ); /* get the Windows region handle for the floater. I want it at 0,0 */ XForm.uViewPerspective = TOP_LEFT; XForm.nXOffset -= rcFloater.left; XForm.nYOffset -= rcFloater.top; L_GetBitmapRgnHandle( &pData->LeadBitmap, &XForm, &pData->hrgnFloater ); /* clear the region from the source bitmap */ L_FreeBitmapRgn(&pData->LeadBitmap); /* --------------- START CREATING THE FLOATING BITMAPS --------- */ /* free the previous floater bitmap */ if( pData->bmFloater.Flags.Allocated) L_FreeBitmap( &pData->bmFloater); /* create the floater bitmap */ L_CopyBitmapRect( &pData->bmFloater, &pData->LeadBitmap,sizeof(BITMAPHANDLE), pData->xMoveSrc, pData->yMoveSrc, pData->nMoveWidth, pData->nMoveHeight ); /* create the floater DDB */ if( pData->hbmFloater ) DeleteObject( pData->hbmFloater); pData->hbmFloater = ResizeToDDB(pData, hdc, &pData->LeadBitmap, pData->xFloaterDest - pData->rcView.left, pData->yFloaterDest - pData->rcView.top, pData->nFloaterWidth, pData->nFloaterHeight, RECTWIDTH(&pData->rcView), RECTHEIGHT(&pData->rcView) ); /* --------------- the floating bitmaps are created ------------- */ /* ------- START CREATING THE BACKGROUND BITMAPS ------- */ /* create the background bitmap if it doesn't exist already */ if( pData->bmSave.Flags.Allocated ) { SetRect(&rc, pData->xMoveSrc, pData->yMoveSrc, pData->xMoveSrc + pData->nMoveWidth, pData->yMoveSrc + pData->nMoveHeight); L_RectFromBitmap(&pData->LeadBitmap, TOP_LEFT, &rc); /* restore the background in the big bitmap */ L_CombineBitmap(&pData->LeadBitmap, rc.left, rc.top, RECTWIDTH(&rc), RECTHEIGHT(&rc), &pData->bmSave, 0, 0, L_SRCCOPY); } else /* create the save bitmap. Now, it is exactly as the floater */ L_CopyBitmap(&pData->bmSave, &pData->bmFloater,sizeof(BITMAPHANDLE)); /* create the save DDB */ if(pData->hbmSave) DeleteObject(pData->hbmSave); pData->hbmSave = ResizeToDDB(pData, hdc, &pData->LeadBitmap, pData->xFloaterDest - pData->rcView.left, pData->yFloaterDest - pData->rcView.top, pData->nFloaterWidth, pData->nFloaterHeight, RECTWIDTH(&pData->rcView), RECTHEIGHT(&pData->rcView)); /* ------- the background bitmaps are created --------- */ if( !pData->hbmFloater || !pData->hbmSave || !pData->bmFloater.Flags.Allocated || !pData->bmSave.Flags.Allocated || !pData->hrgnRegion || !pData->hrgnFloater ) MessageBox( hWnd, TEXT("Error allocating bitmaps"), TEXT(""), MB_OK ); /* create the background DDB */ ReleaseDC(hWnd, hdc ); return SUCCESS; } L_VOID DrawShape (HWND hWnd) { HDC hdc; L_INT xCornerEllipse = 0,yCornerEllipse = 0; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return; hdc = GetDC (hWnd); SetROP2 (hdc, R2_NOT); SelectObject (hdc, GetStockObject (NULL_BRUSH)); switch(nRgnType) { case 1: nRgn =5; Rectangle (hdc, pData->ptBeg.x, pData->ptBeg.y, pData->ptEnd.x, pData->ptEnd.y) ; return; case 2: nRgn =5; xCornerEllipse = (pData->ptEnd.x - pData->ptBeg.x)/4; yCornerEllipse = (pData->ptEnd.y - pData->ptBeg.y)/4; RoundRect (hdc, pData->ptBeg.x, pData->ptBeg.y, pData->ptEnd.x, pData->ptEnd.y, xCornerEllipse, yCornerEllipse); break; case 3: nRgn =5; Ellipse (hdc, pData->ptBeg.x, pData->ptBeg.y, pData->ptEnd.x, pData->ptEnd.y); break ; } ReleaseDC (hWnd, hdc); } L_VOID DrawPoly(HWND hWnd) { HDC hPolyDC; HPEN hSavePen,hOurPen; pCHILDDATA pData; pData = (pCHILDDATA) GetWindowLong(hWnd, GWL_USERDATA); if (!pData) return; hPolyDC = GetDC(hWnd); hOurPen =GetStockObject (WHITE_PEN); hSavePen = SelectObject (hPolyDC,hOurPen ); MoveToEx(hPolyDC,pData->pPolyPt[pData->nPtCount-2].x,pData->pPolyPt[pData->nPtCount-2].y,NULL); LineTo(hPolyDC,pData->pPolyPt[pData->nPtCount-1].x,pData->pPolyPt[pData->nPtCount-1].y); DeleteObject(hOurPen); hSavePen = SelectObject (hPolyDC,hSavePen ); ReleaseDC (hWnd, hPolyDC); }