| 1 | /***
 | 
|---|
| 2 |  This file belongs to the Gotcha! distribution.
 | 
|---|
| 3 |  Copyright (C) 1998-2002 Thorsten Thielen <thth@c2226.de>
 | 
|---|
| 4 | 
 | 
|---|
| 5 |  This program is free software; you can redistribute it and/or modify
 | 
|---|
| 6 |  it under the terms of the GNU General Public License as published by
 | 
|---|
| 7 |  the Free Software Foundation; either version 2 of the License, or
 | 
|---|
| 8 |  (at your option) any later version.
 | 
|---|
| 9 | 
 | 
|---|
| 10 |  This program is distributed in the hope that it will be useful,
 | 
|---|
| 11 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 12 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 13 |  GNU General Public License for more details.
 | 
|---|
| 14 | 
 | 
|---|
| 15 |  You should have received a copy of the GNU General Public License
 | 
|---|
| 16 |  along with this program; if not, write to the Free Software
 | 
|---|
| 17 |  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|---|
| 18 |  ***/
 | 
|---|
| 19 | 
 | 
|---|
| 20 | // ** CaptureWindow ******************************************************* /*FOLD00*/
 | 
|---|
| 21 | #include <ctype.h>
 | 
|---|
| 22 | #define MAX_WAIT   15
 | 
|---|
| 23 | 
 | 
|---|
| 24 | HBITMAP CaptureWindow (HWND hwnd, HWND hwndParent, PRECTL prcl, BOOL f)
 | 
|---|
| 25 | {
 | 
|---|
| 26 | #ifdef _DOLOGMEM_
 | 
|---|
| 27 |     LogMem("CaptureWindow", TRUE);
 | 
|---|
| 28 | #endif
 | 
|---|
| 29 |     static PSZ pszData[4] = { "Display", NULL, NULL, NULL };
 | 
|---|
| 30 |     SIZEL   sizlPage = {0, 0};
 | 
|---|
| 31 |     POINTL  aptl[3];
 | 
|---|
| 32 |     LONG    alData[2];
 | 
|---|
| 33 |     SWP     swp;
 | 
|---|
| 34 |     SHORT   sWidth, sHeight;
 | 
|---|
| 35 |     CHAR    ach[32];
 | 
|---|
| 36 | 
 | 
|---|
| 37 |     // wait for the selected window to rise to the surface
 | 
|---|
| 38 |     if (f)
 | 
|---|
| 39 |     {
 | 
|---|
| 40 |         WinSetWindowPos (hwndParent, HWND_TOP, 0,0, 0,0, SWP_ZORDER);
 | 
|---|
| 41 |         // FIXME uh, yukki! polling! but seems to be the easiest way for now.
 | 
|---|
| 42 |         for (USHORT i = 0; i < MAX_WAIT; i++)
 | 
|---|
| 43 |         {
 | 
|---|
| 44 |             DosSleep (100);
 | 
|---|
| 45 |             WinQueryWindowPos (hwndParent, &swp);
 | 
|---|
| 46 |             if ((swp.hwndInsertBehind == HWND_TOP) ||
 | 
|---|
| 47 |                 (swp.hwndInsertBehind == hwndSnapshot))
 | 
|---|
| 48 |                 break;
 | 
|---|
| 49 |             else
 | 
|---|
| 50 |             {
 | 
|---|
| 51 |                 // check if topmost window is a menu
 | 
|---|
| 52 |                 WinQueryClassName (swp.hwndInsertBehind, sizeof (ach), ach);
 | 
|---|
| 53 |                 if (stricmp (ach, "#4") == 0)
 | 
|---|
| 54 |                     break;
 | 
|---|
| 55 |             }
 | 
|---|
| 56 |         }
 | 
|---|
| 57 |     }
 | 
|---|
| 58 | 
 | 
|---|
| 59 |     // if no capture rectangle given, we'll take the whole window
 | 
|---|
| 60 |     if (! prcl)
 | 
|---|
| 61 |     {
 | 
|---|
| 62 |         WinQueryWindowPos (hwnd, &swp);
 | 
|---|
| 63 |         sWidth  = swp.cx;
 | 
|---|
| 64 |         sHeight = swp.cy;
 | 
|---|
| 65 |     }
 | 
|---|
| 66 |     else
 | 
|---|
| 67 |     {
 | 
|---|
| 68 |         sWidth  = prcl->xRight-prcl->xLeft+1;
 | 
|---|
| 69 |         sHeight = prcl->yTop-prcl->yBottom+1;
 | 
|---|
| 70 |     }
 | 
|---|
| 71 | 
 | 
|---|
| 72 |     /* create the memory device context and presentation space so they
 | 
|---|
| 73 |      are compatible with the screen device context and presentation space */
 | 
|---|
| 74 |     HDC hdcMem =
 | 
|---|
| 75 |         DevOpenDC (hab, OD_MEMORY, "*", 4, PDEVOPENDATA (pszData), 0);
 | 
|---|
| 76 |     HPS hpsMem =
 | 
|---|
| 77 |         GpiCreatePS (hab, hdcMem, &sizlPage, PU_PELS| GPIA_ASSOC| GPIT_MICRO);
 | 
|---|
| 78 | 
 | 
|---|
| 79 |     // determine the device's plane/bit-count format
 | 
|---|
| 80 |     GpiQueryDeviceBitmapFormats (hpsMem, 2, alData);
 | 
|---|
| 81 | 
 | 
|---|
| 82 |     // FIXME even if it seems to work ...
 | 
|---|
| 83 |     if (alData[1] == 16)
 | 
|---|
| 84 |         alData[1] = 24;
 | 
|---|
| 85 | 
 | 
|---|
| 86 |     BITMAPINFOHEADER2 bmp;
 | 
|---|
| 87 | 
 | 
|---|
| 88 |     /* load the BITMAPINFOHEADER2 and BITMAPINFO2 structures. The sWidth and
 | 
|---|
| 89 |      sHeight fields specify the width and height of the destination rect. */
 | 
|---|
| 90 |     bmp.cbFix           = ULONG (sizeof(BITMAPINFOHEADER2));
 | 
|---|
| 91 |     bmp.cx              = sWidth;
 | 
|---|
| 92 |     bmp.cy              = sHeight;
 | 
|---|
| 93 |     bmp.cPlanes         = alData[0];
 | 
|---|
| 94 |     bmp.cBitCount       = alData[1];
 | 
|---|
| 95 | 
 | 
|---|
| 96 |     bmp.ulCompression   = BCA_UNCOMP;
 | 
|---|
| 97 |     /*SOME STUFF MISSING IN THIS STATEMENT: 1 << bmp.cPlanes) *
 | 
|---|
| 98 |                              (1 << bmp.cBitCount)) + 31) / 32) * sHeight;*/
 | 
|---|
| 99 |     bmp.cxResolution    = 0;
 | 
|---|
| 100 |     bmp.cyResolution    = 0;
 | 
|---|
| 101 |     bmp.cclrUsed        = 0;
 | 
|---|
| 102 |     bmp.cclrImportant   = 0;
 | 
|---|
| 103 | 
 | 
|---|
| 104 |     bmp.usUnits         = BRU_METRIC;
 | 
|---|
| 105 |     bmp.usReserved      = 0;
 | 
|---|
| 106 |     bmp.usRecording     = BRA_BOTTOMUP;
 | 
|---|
| 107 |     bmp.usRendering     = BRH_NOTHALFTONED;
 | 
|---|
| 108 |     bmp.cSize1          = 0;
 | 
|---|
| 109 |     bmp.cSize2          = 0;
 | 
|---|
| 110 |     bmp.ulColorEncoding = BCE_RGB;
 | 
|---|
| 111 |     bmp.ulIdentifier    = 0;
 | 
|---|
| 112 | 
 | 
|---|
| 113 |     // create a bit map that is compatible with the display
 | 
|---|
| 114 |     HBITMAP hbm = GpiCreateBitmap (hpsMem, &bmp, 0L, NULL, NULL/*pbmi*/);
 | 
|---|
| 115 | 
 | 
|---|
| 116 |     // associate the bit map and the memory presentation space
 | 
|---|
| 117 |     HBITMAP hbmOld = GpiSetBitmap (hpsMem, hbm);
 | 
|---|
| 118 | 
 | 
|---|
| 119 |     /* Copy the screen to the bit map.                                  */
 | 
|---|
| 120 |     aptl[0].x = 0;       /* Lower-left corner of destination rectangle  */
 | 
|---|
| 121 |     aptl[0].y = 0;       /* Lower-left corner of destination rectangle  */
 | 
|---|
| 122 |     aptl[1].x = sWidth;  /* Upper-right corner of destination rectangle */
 | 
|---|
| 123 |     aptl[1].y = sHeight; /* Upper-right corner of destination rectangle */
 | 
|---|
| 124 | 
 | 
|---|
| 125 |     if (! prcl)
 | 
|---|
| 126 |     {
 | 
|---|
| 127 |         aptl[2].x = 0;       /* Lower-left corner of source rectangle       */
 | 
|---|
| 128 |         aptl[2].y = 0;       /* Lower-left corner of source rectangle       */
 | 
|---|
| 129 |     }
 | 
|---|
| 130 |     else
 | 
|---|
| 131 |     {
 | 
|---|
| 132 |         aptl[2].x = prcl->xLeft;       /* Lower-left corner of source rectangle       */
 | 
|---|
| 133 |         aptl[2].y = prcl->yBottom;       /* Lower-left corner of source rectangle       */
 | 
|---|
| 134 |     }
 | 
|---|
| 135 | 
 | 
|---|
| 136 |     HPS hps;
 | 
|---|
| 137 | 
 | 
|---|
| 138 |     // esp. important if serial capture enabled: window may have been closed!
 | 
|---|
| 139 |     if (WinIsWindow (GETHAB, hwnd) || (hwnd == HWND_DESKTOP))
 | 
|---|
| 140 |         hps = WinGetPS (hwnd);
 | 
|---|
| 141 |     else
 | 
|---|
| 142 |     {
 | 
|---|
| 143 |         GpiDeleteBitmap (hbm);
 | 
|---|
| 144 |         DevCloseDC (hdcMem);
 | 
|---|
| 145 |         return NULL;
 | 
|---|
| 146 |     }
 | 
|---|
| 147 | 
 | 
|---|
| 148 |     GpiBitBlt (hpsMem, hps,
 | 
|---|
| 149 |                sizeof (aptl) / sizeof (POINTL), /* Number of points in aptl */
 | 
|---|
| 150 |                aptl, ROP_SRCCOPY, BBO_IGNORE);
 | 
|---|
| 151 | 
 | 
|---|
| 152 |     SWCNTRL  swctl;
 | 
|---|
| 153 |     PID      pid;
 | 
|---|
| 154 |     TID      tid;
 | 
|---|
| 155 |     BOOL screen = FALSE, region = FALSE;
 | 
|---|
| 156 |     CHAR title[11];
 | 
|---|
| 157 | 
 | 
|---|
| 158 |     if (!f) {
 | 
|---|
| 159 |         //hwndParent = WinQueryFocus(HWND_DESKTOP);
 | 
|---|
| 160 |         if (hwndParent == hwndFrame) {
 | 
|---|
| 161 |             hwndParent = WinQueryWindow(hwndFrame, QW_NEXTTOP );
 | 
|---|
| 162 |         }
 | 
|---|
| 163 |         screen = TRUE;
 | 
|---|
| 164 |         if (prcl)
 | 
|---|
| 165 |             region = TRUE;
 | 
|---|
| 166 |     }
 | 
|---|
| 167 | 
 | 
|---|
| 168 |     int rc = WinQueryWindowProcess(hwndParent, &pid, &tid);
 | 
|---|
| 169 |     if (WinQuerySwitchEntry(WinQuerySwitchHandle(hwndParent, pid),
 | 
|---|
| 170 |                             &swctl))
 | 
|---|
| 171 |         WinQuerySwitchEntry(WinQuerySwitchHandle(NULLHANDLE, pid),
 | 
|---|
| 172 |                             &swctl);
 | 
|---|
| 173 | 
 | 
|---|
| 174 |     char buffer[MAXNAMEL+4];
 | 
|---|
| 175 |     int length = strlen( swctl.szSwtitle );
 | 
|---|
| 176 |     strcpy(buffer, swctl.szSwtitle);
 | 
|---|
| 177 |     char *p;
 | 
|---|
| 178 |     p = buffer;
 | 
|---|
| 179 |     for (int i = 0; i < (length < 11 ? length : 11); i++) {
 | 
|---|
| 180 |         if ( ispunct( *p ) || *p == '\\' || isblank( *p )) {
 | 
|---|
| 181 |             *p = '_';
 | 
|---|
| 182 |         }
 | 
|---|
| 183 |         p++;
 | 
|---|
| 184 |     }
 | 
|---|
| 185 | 
 | 
|---|
| 186 |     if (region)
 | 
|---|
| 187 |         snprintf( title, length < 8 ? length + 3 : 11, "SR%s", buffer);
 | 
|---|
| 188 |     else if (screen)
 | 
|---|
| 189 |         snprintf( title, length < 8 ? length + 3 : 11, "SC%s", buffer);
 | 
|---|
| 190 |     else
 | 
|---|
| 191 |         snprintf( title, length < 8 ? length + 3 : 11, "WD%s", buffer);
 | 
|---|
| 192 | 
 | 
|---|
| 193 |     SaveBitmap (hbm, hpsMem, sWidth, sHeight, bmp.cBitCount, title);
 | 
|---|
| 194 | 
 | 
|---|
| 195 |     // re-associate the previous bit map and the memory presentation space
 | 
|---|
| 196 |     GpiSetBitmap (hpsMem, hbmOld);
 | 
|---|
| 197 | 
 | 
|---|
| 198 |     GpiDeleteBitmap (hbm);
 | 
|---|
| 199 |     WinReleasePS (hps);
 | 
|---|
| 200 |     GpiDestroyPS (hps);
 | 
|---|
| 201 |     DevCloseDC (hdcMem);
 | 
|---|
| 202 | 
 | 
|---|
| 203 | #ifdef _DOLOGMEM_
 | 
|---|
| 204 |     LogMem("CaptureWindow", FALSE);
 | 
|---|
| 205 | #endif
 | 
|---|
| 206 | 
 | 
|---|
| 207 |     return hbm;
 | 
|---|
| 208 | }
 | 
|---|
| 209 | 
 | 
|---|
| 210 | // ** DoTracking ********************************************************** /*FOLD00*/
 | 
|---|
| 211 | 
 | 
|---|
| 212 | BOOL DoTracking (RECTL *prclTrack)
 | 
|---|
| 213 | {
 | 
|---|
| 214 |     LONG       cxScreen, cyScreen, cxPointer, cyPointer;
 | 
|---|
| 215 |     TRACKINFO  ti;
 | 
|---|
| 216 | 
 | 
|---|
| 217 |     cxScreen  = WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
 | 
|---|
| 218 |     cyScreen  = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
 | 
|---|
| 219 |     cxPointer = WinQuerySysValue (HWND_DESKTOP, SV_CXPOINTER);
 | 
|---|
| 220 |     cyPointer = WinQuerySysValue (HWND_DESKTOP, SV_CYPOINTER);
 | 
|---|
| 221 | 
 | 
|---|
| 222 |     ti.cxBorder = 1;
 | 
|---|
| 223 |     ti.cyBorder = 1;
 | 
|---|
| 224 | 
 | 
|---|
| 225 |     ti.cxGrid = 0;
 | 
|---|
| 226 |     ti.cyGrid = 0;
 | 
|---|
| 227 | 
 | 
|---|
| 228 |     ti.cxKeyboard = 4;
 | 
|---|
| 229 |     ti.cyKeyboard = 4;
 | 
|---|
| 230 | 
 | 
|---|
| 231 |     ti.rclBoundary.xLeft   = 0;
 | 
|---|
| 232 |     ti.rclBoundary.yBottom = 0;
 | 
|---|
| 233 |     ti.rclBoundary.xRight  = cxScreen;
 | 
|---|
| 234 |     ti.rclBoundary.yTop    = cyScreen;
 | 
|---|
| 235 | 
 | 
|---|
| 236 |     ti.ptlMinTrackSize.x = 1;
 | 
|---|
| 237 |     ti.ptlMinTrackSize.y = 1;
 | 
|---|
| 238 |     ti.ptlMaxTrackSize.x = cxScreen;
 | 
|---|
| 239 |     ti.ptlMaxTrackSize.y = cyScreen;
 | 
|---|
| 240 | 
 | 
|---|
| 241 |     ti.rclTrack.xLeft   = (cxScreen-cxPointer)/2;
 | 
|---|
| 242 |     ti.rclTrack.yBottom = (cyScreen-cyPointer)/2;
 | 
|---|
| 243 |     ti.rclTrack.xRight  = (cxScreen+cxPointer)/2;
 | 
|---|
| 244 |     ti.rclTrack.yTop    = (cyScreen+cyPointer)/2;
 | 
|---|
| 245 | 
 | 
|---|
| 246 |     ti.fs = TF_MOVE | TF_STANDARD | TF_SETPOINTERPOS;
 | 
|---|
| 247 | 
 | 
|---|
| 248 |     if (! WinTrackRect (HWND_DESKTOP, NULL, &ti))
 | 
|---|
| 249 |         return FALSE;
 | 
|---|
| 250 | 
 | 
|---|
| 251 |     WinSetPointer (HWND_DESKTOP,
 | 
|---|
| 252 |                    WinQuerySysPointer (HWND_DESKTOP, SPTR_SIZENESW, FALSE));
 | 
|---|
| 253 | 
 | 
|---|
| 254 |     ti.fs = TF_RIGHT | TF_TOP | TF_STANDARD | TF_SETPOINTERPOS;
 | 
|---|
| 255 | 
 | 
|---|
| 256 |     if (! WinTrackRect (HWND_DESKTOP, NULL, &ti))
 | 
|---|
| 257 |         return FALSE;
 | 
|---|
| 258 | 
 | 
|---|
| 259 |     *prclTrack = ti.rclTrack;
 | 
|---|
| 260 | 
 | 
|---|
| 261 |     return TRUE;
 | 
|---|
| 262 | }
 | 
|---|
| 263 | 
 | 
|---|
| 264 | // ** StartSelection ****************************************************** /*FOLD00*/
 | 
|---|
| 265 | 
 | 
|---|
| 266 | VOID StartSelection (HWND hwnd)
 | 
|---|
| 267 | {
 | 
|---|
| 268 |     WinSetPointer (HWND_DESKTOP, WinLoadPointer (HWND_DESKTOP, GETMODULE, 2));
 | 
|---|
| 269 |     WinSetCapture (HWND_DESKTOP, hwnd);
 | 
|---|
| 270 | }
 | 
|---|
| 271 | 
 | 
|---|
| 272 | // ************************************************************************
 | 
|---|