home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
-
- File: CHILD.C
-
- Purpose: Contains the routines to implement displaying a bitmap in
- an MDI child window. Each window has its own set of
- information stored in its window words which identifies
- the bitmap to be displayed, etc..
-
- Functions: ChildWndProc
- ChildWndCreate
- ChildWndPaint
- ChildWndDestroy
- ChildWndScroll
- ChildWndKeyDown
- ChildWndQueryNewPalette
- ChildWndPaletteChanged
- ChildWndStartAnimate
- ChildWndLeftButton
- ChildWndSize
- SetupScrollBars
- ScrollBarsOff
- GetCurrentMDIWnd
- CurrentDIBPalette
- GetCurrentDIBStretchFlag
- SetCurrentDIBStretchFlag
- ReallyGetClientRect
- Hourglass
- SetMessageToAllChildren
- CloseAllDIBWindows
- TrackMouse
- NormalizeRect
- DrawSelect
- GetCurrentClipRect
- GetCurrentDIBSize
-
- Comments: Special considerations are made in this module to get
- Windows to handle the system palette correctly for
- child windows (MDI child windows in this case).
-
- Noramlly, an application with the focus has the
- "foreground" palette. Since this application uses
- multiple palettes (one per bitmap), special handling
- must be used to force all the windows without the focus
- to "background" palettes.
-
- We accomplish this by forcing the "active" child window's
- palette to be the whole application's foreground palette
- (i.e. get a DC for the frame, and realize the child's
- palette in that DC as a foreground palette).
-
- All other times we realize palettes, we realize them
- as background palettes. If the palette being realized
- was realized as the frame's foreground palette, then
- when it is realized as a background palette, all the
- colors will map to the correct colors! If the palette
- being realized was not the foreground palette, the colors
- are mapped into the system palette on a "best match"
- basis.
-
- History: Date Reason
- 6/ 1/91 Created
- 12/03/91 Fixed palette handling code.
-
- *************************************************************************/
-
-
-
- #include "master.h"
-
-
- // Some magic numbers.
-
- #define TIMER_ID 1 // Timer ID when palette animating.
- #define TIMER_INTERVAL 100 // # of ms between timer ticks when animating.
- #define SCROLL_RATIO 4 // WM_VSCROLL scrolls DIB by 1/x of client area.
-
-
-
- // The following defines are the default values for the OPTIONSINFO
- // structure stored in the child window's INFOSTRUCT (which is a
- // structure containing information on the child window's bitmap,
- // and list of options). See ChildWndCreate() to see how these
- // are used.
-
- #define OPT_DEF_STRETCH FALSE // Don't stretch the DIB on display.
- #define OPT_DEF_BANDING TRUE // Band DIB to printer.
- #define OPT_DEF_USE31PRNAPIS FALSE // Don't use the 3.1 Printing APIs.
- #define OPT_DEF_DISP DISP_USE_DDBS // Display DDBs instead of DIBs.
- #define OPT_DEF_PRNSIZE PRINT_BESTFIT // Print in "best fit" mode.
- #define OPT_DEF_PRNSCALEX 1 // X stretch factor = 1 (in PRINT_STRETCH mode)
- #define OPT_DEF_PRNSCALEY 1 // Y stretch factor = 1 (in PRINT_STRETCH mode)
-
-
-
- // Some useful macros.
-
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-
-
- // Some globals.
-
- HWND hWndAnimate = NULL; // HWND of currently palette animated DIB.
- HWND hWndClip = NULL; // Current Window to be rendered to clipboard.
- POINT ptClipSize = {0,0}; // Size of DIB at time of copy (i.e. was the DIB stretched?)
- int nDIBsOpen = 0; // # of MDI child windows currently open.
-
-
- // Local function prototypes.
-
- void ChildWndCreate (HWND hWnd, LPDIBCREATEINFO lpDIBCreateInfo);
- void ChildWndPaint (HWND hWnd);
- void ChildWndDestroy (HWND hWnd);
- void ChildWndScroll (HWND hWnd, int message, WORD wPos, WORD wScrollType);
- BOOL ChildWndQueryNewPalette (HWND hWnd, HWND hWndFrame);
- void ChildWndPaletteChanged (HWND hWnd);
- void ChildWndStartAnimate(HWND hWnd);
- void ChildWndLeftButton (HWND hWnd, int x, int y);
- DWORD ChildWndKeyDown (HWND hWnd, WORD wKeyCode, LONG lParam);
- void ChildWndSize (HWND hWnd);
- void SetupScrollBars (HWND hWnd, WORD cxDIB, WORD cyDIB);
- void ScrollBarsOff (HWND hWnd);
- void ReallyGetClientRect (HWND hWnd, LPRECT lpRect);
- void Hourglass (BOOL bDisplay);
- void TrackMouse (HWND hWnd, LPRECT lpClipRect, int cxDIB, int cyDIB);
- void NormalizeRect (LPRECT lpRect);
- void DrawSelect (HDC hDC, RECT rcClip);
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndProc
- //
- // Purpose: Window procedure for DIB MDI child windows.
- // Handles all messages destined for these windows.
- //
- // Parms: hWnd == Handle to this MDI child window.
- // message == Message for window.
- // wParam == Depends on message.
- // lParam == Depends on message.
- //
- // History: Date Reason
- // 6/01/91 Created
- // 10/15/91 Moved WM_CREATE handler to own function.
- // Moved WM_DESTROY handler to own function.
- // Moved WM_PAINT handler to own function.
- // Moved WM_?SCROLL handler to own function.
- //
- //---------------------------------------------------------------------
-
- long FAR PASCAL __export ChildWndProc (HWND hWnd,
- UINT message,
- WPARAM wParam,
- LPARAM lParam)
- {
- switch (message)
- {
- // Window being created, do initialization. In MDI, the lParam
- // is a far pointer to a CREATESTRUCT. The CREATESTRUCT's
- // lpCreateParams is a far pointer to an MDICREATESTRUCT.
- // The MDICREATESTRUCT's lParam is an application supplied
- // LONG. In DIBView, this LONG is actually a far pointer to
- // a DIBCREATEINFO structure. This structure is initialized
- // by the routine which sent the WM_MDICREATE message to the
- // MDI frame (in FRAME.C).
-
- case WM_CREATE:
- ChildWndCreate (hWnd,
- (LPDIBCREATEINFO)
- ((LPMDICREATESTRUCT)
- ((LPCREATESTRUCT) lParam)->lpCreateParams)->lParam);
- break;
-
-
-
- // If this window is being activated, simulate a
- // MYWM_QUERYNEWPALETTE message.
-
- case WM_MDIACTIVATE:
- {
- HWND hWndFrame;
-
- if (wParam)
- {
- hWndFrame = GetParent (GetParent (hWnd));
- SendMessage (hWnd, MYWM_QUERYNEWPALETTE, hWndFrame, 0L);
- }
-
- break;
- }
-
-
-
- // Need to paint, call the paint routine.
-
- case WM_PAINT:
- ChildWndPaint (hWnd);
- break;
-
-
-
- // User's dragging a minimized MDI child, return the cursor to drag.
-
- case WM_QUERYDRAGICON:
- return LoadCursor (hInst, DRAGCURSOR);
-
-
-
- // Window's being destroyed, call the destroy routine.
-
- case WM_DESTROY:
- ChildWndDestroy (hWnd);
- break;
-
-
-
- // Ensure that the clipboard data can be rendered even though
- // this window is being destroyed. First open the clipboard.
- // Then empty what we put there earlier and re-render everything.
-
- case WM_RENDERALLFORMATS:
- {
- if (!OpenClipboard (hWnd))
- break;
-
- EmptyClipboard ();
-
- SendMessage(hWnd, WM_RENDERFORMAT, CF_DIB, 0L);
- SendMessage(hWnd, WM_RENDERFORMAT, CF_BITMAP, 0L);
- SendMessage(hWnd, WM_RENDERFORMAT, CF_PALETTE, 0L);
-
- CloseClipboard ();
- break;
- }
-
-
- // Format the data in the manner requested and pass the handle of
- // the data to the clipboard.
-
- case WM_RENDERFORMAT:
- {
- HANDLE hClipBoardData;
-
- hClipBoardData = RenderFormat (hWndClip, wParam, ptClipSize);
-
- if (hClipBoardData)
- SetClipboardData (wParam, hClipBoardData);
- break;
- }
-
-
- // Window's being scrolled, call the scroll handler.
-
- case WM_HSCROLL:
- case WM_VSCROLL:
- ChildWndScroll (hWnd, message, LOWORD (lParam), wParam);
- break;
-
-
-
- // Keypress -- go handle it.
-
- case WM_KEYDOWN:
- return ChildWndKeyDown (hWnd, wParam, lParam);
-
-
-
- // Window's getting focus, realize our palette. We set it
- // up so that the HWND of the frame window is in wParam.
- // This is so we can realize our palette as the foreground
- // palette of the *entire* application (Windows is designed
- // so that the application has one foreground palette -- owned
- // by the top-level window of the app). We could realize it
- // as foreground, and supply our own hWnd, but this can lead
- // to some weird results...
-
- case MYWM_QUERYNEWPALETTE:
- return ChildWndQueryNewPalette (hWnd, (HWND) wParam);
-
-
-
- // Someone changed the system's palette. Update our window
- // to reflect the new palette.
-
- case WM_PALETTECHANGED:
- if (hWnd == (HWND) wParam)
- break;
-
- ChildWndPaletteChanged (hWnd);
- break;
-
-
-
- // User wants to animate palette, call routine to start
- // animation.
-
- case MYWM_ANIMATE:
- ChildWndStartAnimate (hWnd);
- break;
-
-
-
-
- // Timer went off -- this only happens when we're animating
- // the palette.
-
- case WM_TIMER:
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- break;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- MyAnimatePalette (hWnd, lpDIBInfo->hPal);
-
- GlobalUnlock (hDIBInfo);
- break;
- }
-
-
-
- // Restore the DIB's palette after palette animation. Stop
- // animation. Delete what we created for animation. Also,
- // we need to re-create the bitmap, since we earlier re-created
- // it to reflect the animation palette (see MYWM_ANIMATE).
- // Finally, re-draw the bitmap.
-
- case MYWM_RESTOREPALETTE:
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
- SendMessage (hWnd, WM_RBUTTONDOWN, 0, 0L);
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- break;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- if (lpDIBInfo->hBitmap)
- DeleteObject (lpDIBInfo->hBitmap);
-
- if (lpDIBInfo->hPal)
- DeleteObject (lpDIBInfo->hPal);
-
- lpDIBInfo->hPal = CreateDIBPalette (lpDIBInfo->hDIB);
- lpDIBInfo->hBitmap = DIBToBitmap (lpDIBInfo->hDIB, lpDIBInfo->hPal);
-
- GlobalUnlock (hDIBInfo);
-
- InvalidateRect (hWnd, NULL, FALSE);
- break;
- }
-
-
-
-
- // If the user presses the right mouse button and we're
- // palette animating, stop animating. The bitmap is
- // left in it's animated state, as is the palette. The
- // restore option must be picked to return the bitmap/
- // palette to their original states.
-
- case WM_RBUTTONDOWN:
- if (hWndAnimate == hWnd)
- {
- KillTimer (hWnd, TIMER_ID);
- hWndAnimate = NULL;
- }
- break;
-
-
-
- // Left button pressed -- track a clipping rectangle for clipboard.
-
- case WM_LBUTTONDOWN:
- ChildWndLeftButton (hWnd, LOWORD (lParam), HIWORD (lParam));
- break;
-
-
-
-
- // Handle the WM_SIZE message.
- //
- // Note: This routine calls SetupScrollBars, which can
- // change the size of the window's client rectangle.
- // This, in turn, can send a WM_SIZE message to
- // the window. An infinite loop occurs because of
- // this -- therefore, a semaphore is set up to not
- // allow WM_SIZE to be processed while another
- // WM_SIZE is still being processed.
-
- case WM_SIZE:
- {
- static BOOL bInSize = FALSE;
-
- // Check the semaphore, return if it's set.
-
- if (bInSize)
- return NULL;
-
- bInSize = TRUE;
- ChildWndSize (hWnd);
- bInSize = FALSE;
- }
-
-
- /*** WM_SIZE falls through to default (necessary for MDI) ****/
-
-
-
-
- // Since the MDI default behavior is a little different,
- // call DefMDIChildProc instead of DefWindowProc().
-
- default:
- return DefMDIChildProc (hWnd, message, wParam, lParam);
- }
-
-
- return NULL;
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndCreate
- //
- // Purpose: Called by ChildWndProc() on WM_CREATE. Does initial
- // setup of MDI child winodw.
- //
- // The lpDIBCreateInfo contains a handle to the DIB to
- // be displayed in this window. Get information on this
- // DIB, create an INFOSTRUCT, and store the handle to
- // this INFOSTRUCT in this window's window words. This
- // information is then used extensively on many messages
- // handled by ChildWndProc().
- //
- // An OPTIONSINFO structure is in the INFOSTRUCT. All
- // the options are set by the options dialog (in OPTIONS.C).
- // During creation of the DIB window, options are set to
- // default values.
- //
- // Also, on creation, set the focus to this window.
- // And, incremente the # of windows open global variable.
- //
- // Parms: hWnd == Handle to window being created.
- // lpDIBCreateInfo == Far pointer to DIBCREATEINFO structure
- // passed in during WM_MDICREATE message
- // (by FRAME.C).
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_CREATE case.
- // Also cleaned up code, and got rid
- // of the hDIBCreateInfo handle.
- // 10/27/91 Added bPrinterBand to options.
- // Use #define's for options.
- // 10/28/91 Added bUse31PrintAPIs
- //
- //---------------------------------------------------------------------
-
- void ChildWndCreate (HWND hWnd, LPDIBCREATEINFO lpDIBCreateInfo)
- {
- HANDLE hDIB = NULL;
- LPSTR lpDIB;
- HANDLE hDIBInfo = NULL;
- LPDIBINFO lpDIBInfo;
- DWORD dwDIBHeight, dwDIBWidth;
- WORD wBPP, wCompression;
- char szFileName [129];
- char szTitleBuf[160];
-
- hDIB = lpDIBCreateInfo->hDIB;
- lstrcpy (szFileName, lpDIBCreateInfo->szFileName);
-
-
- // Get some information about the DIB. Some of the info
- // is obtained from within the header (be it a BITMAPINFOHEADER
- // or a BITMAPCOREHEADER).
-
- lpDIB = GlobalLock (hDIB);
- dwDIBHeight = DIBHeight (lpDIB);
- dwDIBWidth = DIBWidth (lpDIB);
- if (IS_WIN30_DIB (lpDIB))
- {
- wCompression = (WORD) ((LPBITMAPINFOHEADER) lpDIB)->biCompression;
- wBPP = ((LPBITMAPINFOHEADER) lpDIB)->biBitCount;
- }
- else
- {
- wCompression = BI_PM;
- wBPP = ((LPBITMAPCOREHEADER) lpDIB)->bcBitCount;
- }
- GlobalUnlock (hDIB);
-
-
- // Allocate room for the DIBINFO structure and fill it in.
-
- if (hDIB)
- hDIBInfo = GlobalAlloc (GHND, sizeof (DIBINFO));
-
- if (hDIBInfo)
- {
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- lpDIBInfo->hDIB = hDIB;
- lpDIBInfo->hPal = CreateDIBPalette (hDIB);
- lpDIBInfo->hBitmap = DIBToBitmap (hDIB, lpDIBInfo->hPal);
-
- lpDIBInfo->wDIBType = wCompression;
- lpDIBInfo->wDIBBits = wBPP;
- lpDIBInfo->wDIBWidth = (WORD) dwDIBWidth;
- lpDIBInfo->wDIBHeight = (WORD) dwDIBHeight;
-
- lpDIBInfo->rcClip.left = 0;
- lpDIBInfo->rcClip.right = 0;
- lpDIBInfo->rcClip.top = 0;
- lpDIBInfo->rcClip.bottom = 0;
-
- lstrcpy (lpDIBInfo->szFileName, szFileName);
-
- lpDIBInfo->Options.bStretch = OPT_DEF_STRETCH;
- lpDIBInfo->Options.bPrinterBand = OPT_DEF_BANDING;
- lpDIBInfo->Options.bUse31PrintAPIs = OPT_DEF_USE31PRNAPIS;
- lpDIBInfo->Options.wDispOption = OPT_DEF_DISP;
- lpDIBInfo->Options.wPrintOption = OPT_DEF_PRNSIZE;
- lpDIBInfo->Options.wXScale = OPT_DEF_PRNSCALEX;
- lpDIBInfo->Options.wYScale = OPT_DEF_PRNSCALEY;
-
- wsprintf((LPSTR)szTitleBuf, (LPSTR)"%s (%ld x %ld x %d BPP)",
- (LPSTR) szFileName, dwDIBWidth, dwDIBHeight, wBPP);
-
- SetWindowText (hWnd, (LPSTR) szTitleBuf);
-
- GlobalUnlock (hDIBInfo);
- }
- else
- DIBError (ERR_MEMORY);
-
-
- // Set the window word for the handle to the DIBINFO structure.
-
- SetWindowWord (hWnd, WW_DIB_HINFO, hDIBInfo);
-
-
- // On initial creation, focus isn't set to us, so set it
- // explicitly.
-
- SetFocus (hWnd);
-
-
- // Increment the # of DIBs open variable and insure that the
- // "Window" pull down menu is not grayed.
-
- nDIBsOpen++;
- EnableWindowAndOptionsMenus (TRUE);
- }
-
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndPaint
- //
- // Purpose: Called by ChildWndProc() on WM_PAINT. Does all paints
- // for this MDI child window.
- //
- // Reads position of scroll bars to find out what part
- // of the DIB to display.
- //
- // Checks the stretching flag in the DIBINFO structure for
- // this window to see if we are stretching to the window
- // (if we're iconic, we always stretch to a tiny bitmap).
- //
- // Selects/Realizes the palette as a background palette.
- // ChildWndQueryNewPalette realized it already as the
- // foreground palette if this window is the active MDI
- // child.
- //
- // Calls the appropriate paint routine depending on the
- // option set for this window (i.e. DIB, DDB, or SetDIBits).
- //
- // Draws the selection rectangle for copying to the
- // clipboard.
- //
- // Parms: hWnd == Handle to window being painted.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_PAINT case.
- // 12/03/91 Always force SelectPalette() to a
- // background palette. If it was
- // the foreground palette, it would
- // have been realized during
- // WM_QUERYNEWPALETTE.
- //
- //---------------------------------------------------------------------
-
- void ChildWndPaint (HWND hWnd)
- {
- HDC hDC;
- PAINTSTRUCT ps;
- int xScroll, yScroll;
- HPALETTE hOldPal = NULL;
- RECT rectClient, rectDDB;
- BOOL bStretch;
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- BITMAP Bitmap;
-
- Hourglass (TRUE);
-
- hDC = BeginPaint (hWnd, &ps);
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
- xScroll = GetScrollPos (hWnd, SB_HORZ);
- yScroll = GetScrollPos (hWnd, SB_VERT);
-
- if (!hDIBInfo)
- goto ABORTPAINT;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- if (!lpDIBInfo->hDIB || !lpDIBInfo->hBitmap)
- {
- GlobalUnlock (hDIBInfo);
- goto ABORTPAINT;
- }
-
- bStretch = lpDIBInfo->Options.bStretch;
-
-
- // When we're iconic, we'll always stretch the DIB
- // to our icon. Otherwise, we'll use the stretching
- // option the user picked.
-
- if (IsIconic (hWnd))
- bStretch = TRUE;
- else
- bStretch = lpDIBInfo->Options.bStretch;
-
-
- // Set up the scroll bars appropriately.
-
- if (bStretch)
- ScrollBarsOff (hWnd);
- else
- SetupScrollBars (hWnd, lpDIBInfo->wDIBWidth, lpDIBInfo->wDIBHeight);
-
-
- // Set up the necessary rectangles -- i.e. the rectangle
- // we're rendering into, and the rectangle in the DIB.
-
- GetClientRect (hWnd, &rectClient);
- GetObject (lpDIBInfo->hBitmap, sizeof (Bitmap), (LPSTR) &Bitmap);
-
- if (bStretch)
- {
- rectDDB.left = 0;
- rectDDB.top = 0;
- rectDDB.right = Bitmap.bmWidth;
- rectDDB.bottom = Bitmap.bmHeight;
- }
- else
- {
- rectDDB.left = xScroll;
- rectDDB.top = yScroll;
- rectDDB.right = xScroll + rectClient.right - rectClient.left;
- rectDDB.bottom = yScroll + rectClient.bottom - rectClient.top;
-
- if (rectDDB.right > Bitmap.bmWidth)
- {
- int dx;
-
- dx = Bitmap.bmWidth - rectDDB.right;
-
- rectDDB.right += dx;
- rectClient.right += dx;
- }
-
- if (rectDDB.bottom > Bitmap.bmHeight)
- {
- int dy;
-
- dy = Bitmap.bmHeight - rectDDB.bottom;
-
- rectDDB.bottom += dy;
- rectClient.bottom += dy;
- }
- }
-
-
- // Setup the palette.
-
- if (lpDIBInfo->hPal)
- hOldPal = SelectPalette (hDC, lpDIBInfo->hPal, TRUE);
-
- RealizePalette (hDC);
-
-
- // Go do the actual painting.
-
- switch (lpDIBInfo->Options.wDispOption)
- {
- case DISP_USE_DIBS:
- DIBPaint (hDC, &rectClient, lpDIBInfo->hDIB, &rectDDB,
- lpDIBInfo->hPal);
- break;
-
-
- case DISP_USE_SETDIBITS:
- SetDIBitsPaint (hDC, &rectClient, lpDIBInfo->hDIB, &rectDDB,
- lpDIBInfo->hPal);
- break;
-
-
- case DISP_USE_DDBS:
- default:
- DDBPaint (hDC, &rectClient, lpDIBInfo->hBitmap, &rectDDB,
- lpDIBInfo->hPal);
- break;
- }
-
-
- // Draw the clipboard selection rubber-band.
-
- SetWindowOrg (hDC,
- GetScrollPos (hWnd, SB_HORZ),
- GetScrollPos (hWnd, SB_VERT));
- DrawSelect (hDC, lpDIBInfo->rcClip);
-
-
- if (hOldPal)
- SelectPalette (hDC, hOldPal, FALSE);
-
- GlobalUnlock (hDIBInfo);
-
- ABORTPAINT:
-
- EndPaint (hWnd, &ps);
-
- Hourglass (FALSE);
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndDestroy
- //
- // Purpose: Called by ChildWndProc() on WM_DESTROY. Window is
- // being destroyed, do all necessary cleanup.
- //
- // Window's going away, free up the DIB, DDB, Palette, and
- // DIBINFO structure.
- //
- // If we're palette animating, kill the timer and free
- // up animation palette.
- //
- // If we have the clipboard, send the WM_RENDERALLFORMATS to
- // our window (Windows will only send it to our app if the
- // main window owns the clipboard; in this app, the MDI child
- // window owns the clipboard).
- //
- // Decrement the # of DIB windows open global variable.
- //
- //
- // Parms: hWnd == Handle to window being destroyed.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_DESTROY case.
- //
- //---------------------------------------------------------------------
-
- void ChildWndDestroy (HWND hWnd)
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
-
- // If we have the clipboard, render all our formats
- // now.
-
- if (hWnd == GetClipboardOwner ())
- {
- SendMessage (hWnd, WM_RENDERALLFORMATS, 0, 0L);
- hWndClip = NULL;
- }
-
-
- // Free up resources connected to this window.
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
- if (hDIBInfo)
- {
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- if (lpDIBInfo->hDIB)
- GlobalFree (lpDIBInfo->hDIB);
-
- if (lpDIBInfo->hPal)
- DeleteObject (lpDIBInfo->hPal);
-
- if (lpDIBInfo->hBitmap)
- DeleteObject (lpDIBInfo->hBitmap);
-
- GlobalUnlock (hDIBInfo);
- GlobalFree (hDIBInfo);
-
- SetWindowWord (hWnd, WW_DIB_HINFO, NULL);
-
- if (--nDIBsOpen == 0)
- EnableWindowAndOptionsMenus (FALSE);
- }
-
-
- // If we're animating, turn off the timer.
-
- if (hWndAnimate == hWnd)
- {
- KillTimer (hWnd, TIMER_ID);
- hWndAnimate = NULL;
- }
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndScroll
- //
- // Purpose: Called by ChildWndProc() on WM_HSCROLL and WM_VSCROLL.
- // Window needs to be scrolled (user has clicked on one
- // of the scroll bars.
- //
- // Does scrolling in both horiziontal and vertical directions.
- // Note that the variables are all named as if we were
- // doing a horizontal scroll. However, if we're doing a
- // vertical scroll, they are initialized to the appropriate
- // values for a vertical scroll.
- //
- // If we scroll by one (i.e. user clicks on one of the
- // scrolling arrows), we scroll the window by 1/SCROLL_RATIO
- // of the client area. In other words, if SCROLL_RATION==4,
- // then we move the client area over a 1/4 of the width/height
- // of the screen.
- //
- // If the user is paging up/down we move a full client area's
- // worth.
- //
- // If the user moves the thumb to an absolute position, we
- // just move there.
- //
- // ScrollWindow/re-painting do the actual work of scrolling.
- //
- // Parms: hWnd == Handle to window being scrolled.
- // message == Message being handled (WM_HSCROLL or WM_VSCROLL)
- // wPos == Thumb position (only valid for SB_THUMBPOSITION
- // and SB_THUMBTRACK).
- // wScrollType == wParam to WM_SCROLL (one of the SB_* constants)
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_?SCROLL case.
- //
- //---------------------------------------------------------------------
-
- void ChildWndScroll (HWND hWnd, int message, WORD wPos, WORD wScrollType)
- {
- int xBar; // Where scrollbar is now.
- int nMin; // Minumum scroll bar value.
- int nMax; // Maximum scroll bar value.
- int dx; // How much to move.
- int nOneUnit; // # of pixels for LINEUP/LINEDOWN
- int cxClient; // Width of client area.
- int nHorzOrVert; // Doing the horizontal or vertical?
- RECT rect; // Client area.
-
-
- GetClientRect (hWnd, &rect);
-
- if (message == WM_HSCROLL)
- {
- nHorzOrVert = SB_HORZ;
- cxClient = rect.right - rect.left;
- }
- else
- {
- nHorzOrVert = SB_VERT;
- cxClient = rect.bottom - rect.top;
- }
-
- // One a SB_LINEUP/SB_LINEDOWN we will move the DIB by
- // 1/SCROLL_RATIO of the client area (i.e. if SCROLL_RATIO
- // is 4, it will scroll the DIB a quarter of the client
- // area's height or width.
-
- nOneUnit = cxClient / SCROLL_RATIO;
- if (!nOneUnit)
- nOneUnit = 1;
-
- xBar = GetScrollPos (hWnd, nHorzOrVert);
- GetScrollRange (hWnd, nHorzOrVert, &nMin, &nMax);
-
- switch (wScrollType)
- {
- case SB_LINEDOWN: // One line right.
- dx = nOneUnit;
- break;
-
- case SB_LINEUP: // One line left.
- dx = -nOneUnit;
- break;
-
- case SB_PAGEDOWN: // One page right.
- dx = cxClient;
- break;
-
- case SB_PAGEUP: // One page left.
- dx = -cxClient;
- break;
-
- case SB_THUMBPOSITION: // Absolute position.
- dx = wPos - xBar;
- break;
-
- default: // No change.
- dx = 0;
- break;
- }
-
- if (dx)
- {
- xBar += dx;
-
- if (xBar < nMin)
- {
- dx -= xBar - nMin;
- xBar = nMin;
- }
-
- if (xBar > nMax)
- {
- dx -= xBar - nMax;
- xBar = nMax;
- }
-
- if (dx)
- {
- SetScrollPos (hWnd, nHorzOrVert, xBar, TRUE);
-
- if (nHorzOrVert == SB_HORZ)
- ScrollWindow (hWnd, -dx, 0, NULL, NULL);
- else
- ScrollWindow (hWnd, 0, -dx, NULL, NULL);
-
- UpdateWindow (hWnd);
- }
- }
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndKeyDown
- //
- // Purpose: Called by ChildWndProc() on WM_KEYDOWN. Keyboard interface
- // for MDI DIB Child window.
- //
- // Keyboard interface. Handles scrolling around the DIB
- // using the keypad, and translates ESC's into WM_RBUTTONDOWN
- // messages (to stop any palette animation in progress).
- //
- // The numeric keypad/arrows are translated into scroll
- // bar messages.
- //
- // Parms: hWnd == Handle to window where key was pressed.
- // wKeyCode == Key code pressed (wParam to WM_KEYDOWN -- one
- // of the VK_* constants)
- // lParam == lParam for WM_KEYDOWN.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_KEYDOWN case.
- //
- //---------------------------------------------------------------------
-
- DWORD ChildWndKeyDown (HWND hWnd, WORD wKeyCode, LONG lParam)
- {
- unsigned uMsg;
- WORD wSB;
-
- switch (wKeyCode)
- {
- case VK_ESCAPE:
- SendMessage (hWnd, WM_RBUTTONDOWN, 0, 0L);
- break;
-
- case VK_UP:
- uMsg = WM_VSCROLL;
- wSB = SB_LINEUP;
- break;
-
- case VK_DOWN:
- uMsg = WM_VSCROLL;
- wSB = SB_LINEDOWN;
- break;
-
- case VK_LEFT:
- uMsg = WM_HSCROLL;
- wSB = SB_LINEUP;
- break;
-
- case VK_RIGHT:
- uMsg = WM_HSCROLL;
- wSB = SB_LINEDOWN;
- break;
-
- case VK_NUMPAD9:
- uMsg = WM_VSCROLL;
- wSB = SB_PAGEUP;
- break;
-
- case VK_NUMPAD3:
- uMsg = WM_VSCROLL;
- wSB = SB_PAGEDOWN;
- break;
-
- case VK_NUMPAD7:
- uMsg = WM_HSCROLL;
- wSB = SB_PAGEUP;
- break;
-
- case VK_NUMPAD1:
- uMsg = WM_HSCROLL;
- wSB = SB_PAGEDOWN;
- break;
-
- default:
- return DefMDIChildProc (hWnd, uMsg, wSB, lParam);
- }
-
- return SendMessage (hWnd, uMsg, wSB, 0L);
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndQueryNewPalette
- //
- // Purpose: Called by ChildWndProc() on WM_QUERYNEWPALETTE.
- //
- // We get this message when an MDI child is getting
- // focus (by hocus pockus in FRAME.C, and by passing
- // this message when we get WM_MDIACTIVATE). Normally
- // this message is passed only to the top level window(s)
- // of an application.
- //
- // We want this window to have the foreground palette when this
- // happens, so we select and realize the palette as
- // a foreground palette (of the frame Window). Then make
- // sure the window repaints, if necessary.
- //
- // Parms: hWnd == Handle to window getting WM_QUERYNEWPALETTE.
- // hWndFrame == Handle to the frame window (i.e. the top-level
- // window of this app.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_QUERYNEWPALETTE case.
- // 12/03/91 Added hWndFrame parameter, realization
- // of palette as palette of frame window,
- // and updating the window only if the
- // palette changed.
- //
- //---------------------------------------------------------------------
-
- BOOL ChildWndQueryNewPalette (HWND hWnd, HWND hWndFrame)
- {
- HPALETTE hOldPal;
- HDC hDC;
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- int nColorsChanged;
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return FALSE;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- if (!lpDIBInfo->hPal)
- {
- GlobalUnlock (hDIBInfo);
- return FALSE;
- }
-
-
- // We're going to make our palette the foreground palette for
- // this application. Window's palette manager expects the
- // top-level window of the application to have the palette,
- // so, we get a DC for the frame here!
-
- hDC = GetDC (hWndFrame);
- hOldPal = SelectPalette (hDC, lpDIBInfo->hPal, FALSE);
-
- nColorsChanged = RealizePalette (hDC);
-
- if (nColorsChanged)
- InvalidateRect (hWnd, NULL, FALSE);
-
- if (hOldPal)
- SelectPalette (hDC, hOldPal, FALSE);
-
- ReleaseDC (hWndFrame, hDC);
-
- GlobalUnlock (hDIBInfo);
-
- return (nColorsChanged != 0);
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndPaletteChanged
- //
- // Purpose: Called by ChildWndProc() on WM_PALETTECHANGED.
- //
- // WM_PALETTECHANGED messages are passed to all MDI
- // children by the frame window (in FRAME.C). Normally,
- // these messages are only sent to the top-level window
- // in an application.
- //
- // On a palette changed, we want to realize this window's
- // palette. We realize it always as a background palette.
- // See the comments section at the top of this file for
- // an explanation why.
- //
- // Parms: hWnd == Handle to window getting WM_PALETTECHANGED.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_PALETTECHANGED case.
- // 12/03/91 Always force SelectPalette() to a
- // background palette. If it was
- // the foreground palette, it would
- // have been realized during
- // WM_QUERYNEWPALETTE.
- //
- //---------------------------------------------------------------------
-
- void ChildWndPaletteChanged (HWND hWnd)
- {
- HPALETTE hOldPal;
- HDC hDC;
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- if (!lpDIBInfo->hPal)
- {
- GlobalUnlock (hDIBInfo);
- return;
- }
-
- hDC = GetDC (hWnd);
- hOldPal = SelectPalette (hDC, lpDIBInfo->hPal, TRUE);
-
- GlobalUnlock (hDIBInfo);
-
- RealizePalette (hDC);
- UpdateColors (hDC);
-
- if (hOldPal)
- SelectPalette (hDC, hOldPal, FALSE);
-
- ReleaseDC (hWnd, hDC);
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndStartAnimate
- //
- // Purpose: Called by ChildWndProc() on MYWM_ANIMATE.
- //
- // Animate this DIB's palette. First do some setup (see if
- // we're already doing animation, and start a timer). Then
- // Create a new palette with the PC_RESERVED flag so it can
- // be animated. Then re-create the bitmap so it uses this
- // new palette. Finally, set our window words and re-draw
- // the bitmap.
- //
- //
- // Parms: hWnd == Handle to window getting MYWM_ANIMATE.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from MYWM_ANIMATE case.
- //
- //---------------------------------------------------------------------
-
- void ChildWndStartAnimate (HWND hWnd)
- {
- HPALETTE hNewPal;
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
-
- // Don't allow more than one window to animate at a time.
-
- if (hWndAnimate)
- {
- DIBError (ERR_ANIMATE);
- return;
- }
-
-
- // Set a timer to animate on.
-
- if (!SetTimer (hWnd, TIMER_ID, TIMER_INTERVAL, NULL))
- {
- DIBError (ERR_NOTIMERS);
- return;
- }
-
-
- // Remember who's animating, get the palette for this window,
- // copy it changing its flags to PC_RESERVED (so each palette
- // entry can be animated).
-
- hWndAnimate = hWnd;
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- hNewPal = CopyPalForAnimation (lpDIBInfo->hPal);
-
-
- // Delete the old device dependent bitmap, and palette. Device
- // dependent bitmaps rely on colors mapping to the exact same
- // place in the system palette (for speed reasons). Se we
- // changed the palette flags to PC_RESERVED, the palette entries
- // might not map to the same palette entries. Therefore, it is
- // necessary to create a new device dependent bitmap here!
-
- if (lpDIBInfo->hBitmap)
- DeleteObject (lpDIBInfo->hBitmap);
-
- if (lpDIBInfo->hPal)
- DeleteObject (lpDIBInfo->hPal);
-
- lpDIBInfo->hBitmap = DIBToBitmap (lpDIBInfo->hDIB, hNewPal);
- lpDIBInfo->hPal = hNewPal;
-
- GlobalUnlock (hDIBInfo);
-
- InvalidateRect (hWnd, NULL, FALSE);
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndLeftButton
- //
- // Purpose: Called by ChildWndProc() on WM_LBUTTONDOWN.
- //
- // If the user presses the left button, erase the currently
- // selected rectangle. Then, start drawing a
- // rectangle (for the area of the DIB to be put in the
- // clipboard on an Edit/Paste operation).
- //
- //
- // Parms: hWnd == Handle to window getting WM_LBUTTONDOWN.
- //
- // History: Date Reason
- //
- // 10/15/91 Cut code out from WM_LBUTTONDOWN case.
- //
- //---------------------------------------------------------------------
-
- void ChildWndLeftButton (HWND hWnd, int x, int y)
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- HDC hDC;
- RECT rcClip;
- int cxDIB, cyDIB;
-
-
- // Find the old clip rectangle and erase it.
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return;
-
- hDC = GetDC (hWnd);
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- SetWindowOrg (hDC,
- GetScrollPos (hWnd, SB_HORZ),
- GetScrollPos (hWnd, SB_VERT));
- DrawSelect (hDC, lpDIBInfo->rcClip);
- ReleaseDC (hWnd, hDC);
-
-
- // Determine the DIB's extents. This is different than the
- // DIB's height/width when the DIB's stretched.
-
- if (lpDIBInfo->Options.bStretch)
- {
- RECT rcClient;
-
- GetClientRect (hWnd, &rcClient);
- cxDIB = rcClient.right;
- cyDIB = rcClient.bottom;
- }
- else
- {
- cxDIB = lpDIBInfo->wDIBWidth;
- cyDIB = lpDIBInfo->wDIBHeight;
- }
-
-
- // Start a new clip rectangle. Track the rubber band. Rubber
- // band won't be allowed to extend past the extents of the
- // DIB.
-
- rcClip.top = y;
- rcClip.left = x;
- TrackMouse (hWnd, &rcClip, cxDIB, cyDIB);
-
-
- // Store the new clipboard coordinates.
-
- lpDIBInfo->rcClip = rcClip;
- GlobalUnlock (hDIBInfo);
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ChildWndSize
- //
- // Purpose: Called by ChildWndProc() on WM_SIZE.
- //
- // When the window is sized -- set up the scroll bars.
- // Also, if we're in "stretch to window" mode, the entire
- // client area must be repainted.
- //
- // The window will be repainted if the new size, combined
- // with the current scroll bar positions would create "white
- // space at the left or bottom of the window. For example,
- // if the DIB is 100x100, the window _was_ 50x50, the new
- // size of the window is 75x75, and the current window is
- // scrolled 50 units to the right; then, if the current
- // scroll position weren't changed, we'd need to paint
- // starting at row 50, and extending through row 125. BUT
- // since the DIB is only 100 pixels wide, white space would
- // appear at the right margin! Instead, the thumb is placed
- // at column 25 (in SetScrollPos), and columns 25 through
- // 100 are displayed (by invalidating the client window!
- //
- // Re-read the above paragraph (slowly this time)!
- //
- // Parms: hWnd == Handle to window getting WM_SIZE.
- //
- // History: Date Reason
- // 10/15/91 Cut code out from WM_SIZE case.
- //
- //---------------------------------------------------------------------
-
- void ChildWndSize (HWND hWnd)
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- LPSTR lpDIB;
- int cxScroll, cyScroll, cxDIB = 0, cyDIB = 0;
- RECT rect;
-
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (hDIBInfo)
- {
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
-
- // Find out the DIB's height/width.
-
- if (lpDIBInfo->hDIB)
- {
- lpDIB = GlobalLock (lpDIBInfo->hDIB);
- cxDIB = (int) DIBWidth (lpDIB);
- cyDIB = (int) DIBHeight (lpDIB);
- GlobalUnlock (lpDIBInfo->hDIB);
- }
-
-
- // Find out the dimensions of the window, and the current
- // thumb positions.
-
- GetClientRect (hWnd, &rect);
- cxScroll = GetScrollPos (hWnd, SB_HORZ);
- cyScroll = GetScrollPos (hWnd, SB_VERT);
-
-
- // If we are in "stretch to window" more, or the current
- // thumb positions would cause "white space" at the right
- // or bottom of the window, repaint.
-
- if (lpDIBInfo->Options.bStretch ||
- cxScroll + rect.right > cxDIB ||
- cyScroll + rect.bottom > cyDIB)
- InvalidateRect (hWnd, NULL, FALSE);
-
- if (!IsIconic (hWnd) && !lpDIBInfo->Options.bStretch)
- SetupScrollBars (hWnd, lpDIBInfo->wDIBWidth, lpDIBInfo->wDIBHeight);
-
- GlobalUnlock (hDIBInfo);
- }
- }
-
-
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: SetupScrollBars
- //
- // Purpose: Sets up MDI Child's scroll bars
- //
- // Either we display both scroll bars, or no scroll bars.
- //
- // Parms: hWnd == Handle to window who's scroll bars we'll set up.
- // hDIB == A handle to the current DIB.
- //
- // History: Date Reason
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- void SetupScrollBars (HWND hWnd, WORD cxDIB, WORD cyDIB)
- {
- RECT rect; // Client Rectangle.
- BOOL bNeedScrollBars = FALSE; // Need Scroll bars?
- unsigned cxWindow, // Width of client area.
- cyWindow; // Height of client area.
- int cxRange = 0, // Range needed for horz bar.
- cyRange = 0; // Range needed for vert bar.
-
-
- // Do some initialization.
-
- ReallyGetClientRect (hWnd, &rect);
-
- cxWindow = rect.right - rect.left;
- cyWindow = rect.bottom - rect.top;
-
-
- // Now determine if we need the scroll bars. Since the
- // window is not allowed to be larger than the DIB, if
- // we need one scroll bar, we need _both_. Since if
- // one scroll bar is turned on, it eats up some of
- // the client area.
-
- if ((cxWindow < (unsigned) cxDIB) || (cyWindow < (unsigned) cyDIB))
- bNeedScrollBars = TRUE;
-
-
- // Setup the scroll bar ranges. We want to be able to
- // scroll the window so that all the DIB can appear
- // within the client area. Take into account that
- // if the opposite scroll bar is activated, it eats
- // up some client area.
-
- if (bNeedScrollBars)
- {
- cyRange = (unsigned) cyDIB - cyWindow - 1 + GetSystemMetrics (SM_CYHSCROLL);
- cxRange = (unsigned) cxDIB - cxWindow - 1 + GetSystemMetrics (SM_CXVSCROLL);
- }
-
-
- // Set the ranges we've calculated (0->0 means invisible scrollbar).
-
- SetScrollRange (hWnd, SB_VERT, 0, cyRange, TRUE);
- SetScrollRange (hWnd, SB_HORZ, 0, cxRange, TRUE);
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ScrollBarsOff
- //
- // Purpose: Turns off scroll bars on the specified window.
- //
- // Parms: hWnd == Handle to window to turn the scroll bars off in.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //----------------------------------------------------------------------
-
- void ScrollBarsOff (HWND hWnd)
- {
- SetScrollRange (hWnd, SB_VERT, 0, 0, TRUE);
- SetScrollRange (hWnd, SB_HORZ, 0, 0, TRUE);
- }
-
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: GetCurrentMDIWnd
- //
- // Purpose: Returns the currently active MDI child window.
- //
- // Parms: None.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- HWND GetCurrentMDIWnd (void)
- {
- return LOWORD (SendMessage (hWndMDIClient, WM_MDIGETACTIVE, 0, 0L));
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: CurrentDIBPalette
- //
- // Purpose: Returns a handle to a duplicate of the current MDI
- // child window's palette.
- //
- // This is used whenever anyone wants to use the same
- // palette -- a duplicate is created, since the MDI
- // child window could be destroyed at any time (and it's
- // palette is destroyed when the window goes away).
- //
- // Parms: None.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- HPALETTE CurrentDIBPalette (void)
- {
- HWND hWnd;
- HPALETTE hDIBPal;
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
-
- // Get a handle to the current MDI Child.
-
- hWnd = GetCurrentMDIWnd ();
-
- if (!hWnd)
- return NULL;
-
-
- // Get the current palette from the MDI Child's window words.
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return NULL;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- hDIBPal = lpDIBInfo->hPal;
- GlobalUnlock (hDIBInfo);
-
- if (!hDIBPal)
- return NULL;
-
- return ((HPALETTE)CopyPalette (hDIBPal));
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: GetCurrentDIBStretchFlag
- //
- // Purpose: Returns the current MDI child window's stretch flag
- // (stored in the INFOSTRUCT stored in a DIB window's
- // window words).
- //
- // Parms: None.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- BOOL GetCurrentDIBStretchFlag (void)
- {
- HWND hWndDIB;
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- BOOL bStretch;
-
- hWndDIB = GetCurrentMDIWnd ();
-
- if (hWndDIB)
- {
- hDIBInfo = GetWindowWord (hWndDIB, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return FALSE;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- bStretch = lpDIBInfo->Options.bStretch;
- GlobalUnlock (hDIBInfo);
-
- return bStretch;
- }
- else
- return FALSE;
- }
-
-
- //---------------------------------------------------------------------
- //
- // Function: SetCurrentDIBStretchFlag
- //
- // Purpose: Sets the current MDI child window's stretch flag
- // (stored in the INFOSTRUCT stored in a DIB window's
- // window words).
- //
- // Parms: bFlag == New flag setting.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- void SetCurrentDIBStretchFlag (BOOL bFlag)
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- HWND hWnd;
-
- hWnd = GetCurrentMDIWnd ();
-
- if (!hWnd)
- return;
-
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (!hDIBInfo)
- return;
-
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- lpDIBInfo->Options.bStretch = bFlag;
- GlobalUnlock (hDIBInfo);
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: ReallyGetClientRect
- //
- // Purpose: Gets the rectangular area of the client rect including
- // the area underneath visible scroll bars. Stolen from
- // ShowDIB.
- //
- // Parms: hWnd == Window to get the client area of.
- // lpRect == Where to copy the rectangle to.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- void ReallyGetClientRect (HWND hWnd, LPRECT lpRect)
- {
- DWORD dwWinStyle;
-
- dwWinStyle = GetWindowLong (hWnd, GWL_STYLE);
-
- GetClientRect (hWnd, lpRect);
-
- if (dwWinStyle & WS_HSCROLL)
- lpRect->bottom += GetSystemMetrics (SM_CYHSCROLL);
-
- if (dwWinStyle & WS_VSCROLL)
- lpRect->right += GetSystemMetrics (SM_CXVSCROLL);
- }
-
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: Hourglass
- //
- // Purpose: Displays or hides the hourglass during lengthy operations.
- //
- // Parms: bDisplay == TRUE to display, false to put it away.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- void Hourglass (BOOL bDisplay)
- {
- static HCURSOR hOldCursor = NULL;
- static int nCount = 0;
-
-
- if (bDisplay)
- {
- // Check if we already have the hourglass up and increment
- // the number of times Hourglass (TRUE) has been called.
-
- if (nCount++)
- return;
-
- hOldCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
-
- // If this machine doesn't have a mouse, display the
- // hourglass by calling ShowCursor(TRUE) (if it does
- // have a mouse this doesn't do anything much).
-
- ShowCursor (TRUE);
- }
- else
- {
- // If we haven't changed the cursor, return to caller.
-
- if (!nCount)
- return;
-
-
- // If our usage count drops to zero put back the cursor
- // we originally replaced.
-
- if (!(--nCount))
- {
- SetCursor (hOldCursor);
- hOldCursor = NULL;
- ShowCursor (FALSE);
- }
- }
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: SetMessageToAllChildren
- //
- // Purpose: Passes a message to all children of the specified window.
- //
- // Parms: hWnd == Parent window.
- // message == message to pass to all children.
- // wParam == wParam of message to pass to all children.
- // lParam == lParam of message to pass to all children.
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- void SendMessageToAllChildren (HWND hWnd,
- unsigned message,
- WORD wParam,
- LONG lParam)
- {
- HWND hChild;
-
- if (hChild = GetWindow(hWnd, GW_CHILD)) // Get 1st child.
- do
- SendMessage(hChild, message, wParam, lParam);
- while (hChild = GetWindow(hChild, GW_HWNDNEXT));
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: CloseAllDIBWindows
- //
- // Purpose: Close all DIB windows currently open.
- //
- // First hides the MDI client -- this insures that no drawing
- // occurs in the DIB windows while we delete windows.
- // Then enumerate all the MDI client's children. If the
- // child is a DIB window, delete it. If it's a title bar,
- // leave it alone, and let Windows take care of it.
- //
- //
- // Parms: None
- //
- // History: Date Reason
- //
- // 6/1/91 Created.
- //
- //---------------------------------------------------------------------
-
- void CloseAllDIBWindows (void)
- {
- register HWND hChild;
- BOOL bWasVisible;
-
-
- // hide the MDI client window to avoid multiple repaints
-
- bWasVisible = ShowWindow (hWndMDIClient, SW_HIDE);
-
-
- // As long as the MDI client has a child, destroy it
-
- while (hChild = GetWindow (hWndMDIClient, GW_CHILD))
- {
- // Skip the icon title windows (they have owners, MDI children
- // don't -- child windows have parents, not owners; title
- // bars' owners are the MDI child windows themselves).
-
- while (hChild && GetWindow (hChild, GW_OWNER))
- hChild = GetWindow (hChild, GW_HWNDNEXT);
-
- if (!hChild)
- break;
-
- SendMessage (hWndMDIClient, WM_MDIDESTROY, (WORD)hChild, 0L);
- }
-
-
- // Make the MDI Client visible again, if it was visible when
- // we called ShowWindow(..., SW_HIDE).
-
- if (bWasVisible)
- ShowWindow(hWndMDIClient, SW_SHOWNORMAL);
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: TrackMouse
- //
- // Purpose: This routine is called when the left mouse button is
- // held down. It will continuously draw a rectangle
- // showing where the user has selected for cutting to the
- // clipboard. When this routine is called, lpClipRect's
- // top/left should point at the point in the client area
- // where the left mouse button was hit. It will return the
- // full sized rectangle the user selected. Never allow the
- // rubber band to extend beyond the DIB's margins.
- //
- // Code was stolen almost verbatim from ShowDIB.
- //
- // Parms: hWnd == Handle to this MDI child window.
- // lpClipRect == Rectangle enclosed by tracking box.
- // cxDIB == Width of DIB. Won't allow tracking box
- // to go beyond the width.
- // cyDIB == Height of DIB. Won't allow tracking box
- // to go beyond the height.
- //
- // History: Date Reason
- // ???? Created
- // 9/1/91 Added cxDIB/cyDIB to not allow garbage
- // to be pasted to the clipboard.
- //
- //---------------------------------------------------------------------
-
- void TrackMouse (HWND hWnd, LPRECT lpClipRect, int cxDIB, int cyDIB)
- {
- HDC hDC;
- MSG msg;
- POINT ptOrigin, ptStart;
- RECT rcClient;
-
- hDC = GetDC (hWnd);
- SetCapture (hWnd);
- GetClientRect (hWnd, &rcClient);
-
-
- // Get mouse coordinates relative to origin of DIB. Then
- // setup the clip rectangle accordingly (it already should
- // contain the starting point in its top/left).
-
- ptOrigin.x = GetScrollPos (hWnd, SB_HORZ);
- ptOrigin.y = GetScrollPos (hWnd, SB_VERT);
- lpClipRect->top += ptOrigin.x;
- lpClipRect->left += ptOrigin.y;
- lpClipRect->right = lpClipRect->left;
- lpClipRect->bottom = lpClipRect->top;
- ptStart.x = lpClipRect->left; // Need to remember the
- ptStart.y = lpClipRect->top; // starting point.
-
-
-
- // Display the starting coordinates.
-
- SetWindowOrg (hDC, ptOrigin.x, ptOrigin.y);
- DrawSelect (hDC, *lpClipRect);
-
-
- // Eat mouse messages until a WM_LBUTTONUP is encountered. Meanwhile
- // continue to draw a rubberbanding rectangle and display it's dimensions
-
- for (;;)
- {
- WaitMessage ();
-
- if (PeekMessage (&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
- {
- // Erase the old.
-
- DrawSelect (hDC, *lpClipRect);
-
-
- // Determine new coordinates.
-
- lpClipRect->left = ptStart.x;
- lpClipRect->top = ptStart.y;
- lpClipRect->right = LOWORD (msg.lParam) + ptOrigin.x;
- lpClipRect->bottom = HIWORD (msg.lParam) + ptOrigin.y;
- NormalizeRect (lpClipRect);
-
-
- // Keep the rectangle within the bounds of the DIB.
-
- lpClipRect->left = MAX(lpClipRect->left, 0);
- lpClipRect->top = MAX(lpClipRect->top, 0);
- lpClipRect->right = MAX(lpClipRect->right, 0);
- lpClipRect->bottom = MAX(lpClipRect->bottom, 0);
-
- lpClipRect->left = MIN(lpClipRect->left, cxDIB);
- lpClipRect->top = MIN(lpClipRect->top, cyDIB);
- lpClipRect->right = MIN(lpClipRect->right, cxDIB);
- lpClipRect->bottom = MIN(lpClipRect->bottom, cyDIB);
-
-
-
- // Draw the new rectangle.
-
- DrawSelect (hDC, *lpClipRect);
-
-
- // If the button is released, quit.
-
- if (msg.message == WM_LBUTTONUP)
- break;
- }
- else
- continue;
- }
-
-
- // Clean up.
-
- ReleaseCapture ();
- ReleaseDC (hWnd, hDC);
- }
-
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: NormalizeRect
- //
- // Purpose: Insure that the upper/left corner of the rectangle is
- // kept in rect.top/rect.right. Swaps around coordinates
- // in the rectangle to make sure this is true.
- //
- // Code was stolen verbatim from ShowDIB.
- //
- // Parms: lpRect == Far pointer to RECT to normalize.
- //
- // History: Date Reason
- // ???? Created
- //
- //---------------------------------------------------------------------
-
- void NormalizeRect (LPRECT lpRect)
- {
- if (lpRect->right < lpRect->left)
- SWAP (lpRect->right,lpRect->left);
-
- if (lpRect->bottom < lpRect->top)
- SWAP (lpRect->bottom,lpRect->top);
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: DrawSelect
- //
- // Purpose: Draw the rubberbanding rectangle with the specified
- // dimensions on the specified DC. Rectangle includes
- // a string with its dimensions centered within it.
- //
- // Code was stolen almost verbatim from ShowDIB.
- //
- // Parms: hDC == DC to draw into.
- // rcClip == Rectangle to draw.
- //
- // History: Date Reason
- // ???? Created
- //
- //---------------------------------------------------------------------
-
- void DrawSelect (HDC hDC, RECT rcClip)
- {
- char szStr[80];
- DWORD dwExt;
- int x, y, nLen, dx, dy;
- HDC hDCBits;
- HBITMAP hBitmap;
-
-
- // Don't have anything to do if the rectangle is empty.
-
- if (IsRectEmpty (&rcClip))
- return;
-
-
- // Draw rectangular clip region
-
- PatBlt (hDC,
- rcClip.left,
- rcClip.top,
- rcClip.right - rcClip.left,
- 1,
- DSTINVERT);
-
- PatBlt (hDC,
- rcClip.left,
- rcClip.bottom,
- 1,
- -(rcClip.bottom - rcClip.top),
- DSTINVERT);
-
- PatBlt (hDC,
- rcClip.right - 1,
- rcClip.top,
- 1,
- rcClip.bottom - rcClip.top,
- DSTINVERT);
-
- PatBlt (hDC,
- rcClip.right,
- rcClip.bottom - 1,
- -(rcClip.right - rcClip.left),
- 1,
- DSTINVERT);
-
-
- // Format the dimensions string ...
-
- wsprintf (szStr,
- "%dx%d",
- rcClip.right - rcClip.left,
- rcClip.bottom - rcClip.top );
- nLen = lstrlen(szStr);
-
-
- // ... and center it in the rectangle
-
- dwExt = GetTextExtent (hDC, szStr, nLen);
- dx = LOWORD (dwExt);
- dy = HIWORD (dwExt);
- x = (rcClip.right + rcClip.left - dx) / 2;
- y = (rcClip.bottom + rcClip.top - dy) / 2;
- hDCBits = CreateCompatibleDC (hDC);
-
-
- // Output the text to the DC
-
- SetTextColor (hDCBits, RGB (255, 255, 255));
- SetBkColor (hDCBits, RGB (0, 0, 0));
-
- if (hBitmap = CreateBitmap (dx, dy, 1, 1, NULL))
- {
- hBitmap = SelectObject (hDCBits, hBitmap);
-
- ExtTextOut (hDCBits, 0, 0, 0, NULL, szStr, nLen, NULL);
- BitBlt (hDC, x, y, dx, dy, hDCBits, 0, 0, SRCINVERT);
- hBitmap = SelectObject (hDCBits, hBitmap);
-
- DeleteObject (hBitmap);
- }
-
- DeleteDC (hDCBits);
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: GetCurrentClipRect
- //
- // Purpose: Return the rectangular dimensions of the clipboard
- // rectangle for the specified window.
- //
- // Parms: hWnd == Window to retrieve the clipboard rectangle info
- // from.
- //
- // History: Date Reason
- // 6/1/91 Created
- //
- //---------------------------------------------------------------------
-
- RECT GetCurrentClipRect (HWND hWnd)
- {
- RECT rect = {0,0,0,0};
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
-
- if (hWnd)
- {
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (hDIBInfo)
- {
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
- rect = lpDIBInfo->rcClip;
- GlobalUnlock (hDIBInfo);
- }
- }
-
- return rect;
- }
-
-
-
- //---------------------------------------------------------------------
- //
- // Function: GetCurrentDIBSize
- //
- // Purpose: Return the dimensions of the DIB for the given MDI child
- // window. Dimensions are returned as a POINT.
- //
- // If the DIB is stretched on the screen, return the client
- // area of the window. Otherwise, retrieve the info from
- // the DIBINFO structure stored in the window's words.
- //
- // Parms: hWnd == Window to retrieve the DIB dimensions from.
- //
- // History: Date Reason
- // 6/1/91 Created
- //
- //---------------------------------------------------------------------
-
- POINT GetCurrentDIBSize (HWND hWnd)
- {
- HANDLE hDIBInfo;
- LPDIBINFO lpDIBInfo;
- POINT pt = {0,0};
- RECT rcClient;
-
- if (hWnd)
- {
- hDIBInfo = GetWindowWord (hWnd, WW_DIB_HINFO);
-
- if (hDIBInfo)
- {
- lpDIBInfo = (LPDIBINFO) GlobalLock (hDIBInfo);
-
- if (lpDIBInfo->Options.bStretch)
- {
- GetClientRect (hWnd, &rcClient);
- pt.x = rcClient.right;
- pt.y = rcClient.bottom;
- }
- else
- {
- pt.x = lpDIBInfo->wDIBWidth;
- pt.y = lpDIBInfo->wDIBHeight;
- }
-
- GlobalUnlock (hDIBInfo);
- }
- }
-
- return pt;
- }
-