source: trunk/bitmap.cpp

Last change on this file was 41, checked in by Gregg Young, 7 years ago

Fix hang on non-full screen capture of window with a menu open; Fix failure of widow to come to the top when program set as always on top are running. Add part of window title to auto file names; Major overhaul of settings dialog for Gotcha Quiet. More _QUIET_ ifdefs added to split code where Gotcha and Gotcha Quiet differ.

  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
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
24HBITMAP 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] = {0};
36
37 // wait for the selected window to rise to the surface
38 if (f)
39 {
40 WinSetFocus(HWND_DESKTOP, hwndParent);
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 if (hwndParent == WinQueryFocus(HWND_DESKTOP)) {
46 break;
47 }
48 else
49 {
50 // check if topmost window is a menu
51 WinQueryClassName (WinQueryFocus(HWND_DESKTOP),
52 sizeof (ach), ach);
53 if (stricmp (ach, "#4") == 0)
54 break;
55 }
56 WinQueryWindowPos (hwndParent, &swp);
57 if ((swp.hwndInsertBehind == HWND_TOP) ||
58 (swp.hwndInsertBehind == hwndSnapshot)) {
59 break;
60 }
61 else
62 {
63 // check if topmost window is a menu
64 WinQueryClassName (swp.hwndInsertBehind, sizeof (ach), ach);
65 if (stricmp (ach, "#4") == 0)
66 break;
67 }
68 }
69 }
70
71 // if no capture rectangle given, we'll take the whole window
72 if (! prcl)
73 {
74 WinQueryWindowPos (hwnd, &swp);
75 sWidth = swp.cx;
76 sHeight = swp.cy;
77 }
78 else
79 {
80 sWidth = prcl->xRight-prcl->xLeft+1;
81 sHeight = prcl->yTop-prcl->yBottom+1;
82 }
83
84 /* create the memory device context and presentation space so they
85 are compatible with the screen device context and presentation space */
86 HDC hdcMem =
87 DevOpenDC (hab, OD_MEMORY, "*", 4, PDEVOPENDATA (pszData), 0);
88 HPS hpsMem =
89 GpiCreatePS (hab, hdcMem, &sizlPage, PU_PELS| GPIA_ASSOC| GPIT_MICRO);
90
91 // determine the device's plane/bit-count format
92 GpiQueryDeviceBitmapFormats (hpsMem, 2, alData);
93
94 // FIXME even if it seems to work ...
95 if (alData[1] == 16)
96 alData[1] = 24;
97
98 BITMAPINFOHEADER2 bmp;
99
100 /* load the BITMAPINFOHEADER2 and BITMAPINFO2 structures. The sWidth and
101 sHeight fields specify the width and height of the destination rect. */
102 bmp.cbFix = ULONG (sizeof(BITMAPINFOHEADER2));
103 bmp.cx = sWidth;
104 bmp.cy = sHeight;
105 bmp.cPlanes = alData[0];
106 bmp.cBitCount = alData[1];
107
108 bmp.ulCompression = BCA_UNCOMP;
109 /*SOME STUFF MISSING IN THIS STATEMENT: 1 << bmp.cPlanes) *
110 (1 << bmp.cBitCount)) + 31) / 32) * sHeight;*/
111 bmp.cxResolution = 0;
112 bmp.cyResolution = 0;
113 bmp.cclrUsed = 0;
114 bmp.cclrImportant = 0;
115
116 bmp.usUnits = BRU_METRIC;
117 bmp.usReserved = 0;
118 bmp.usRecording = BRA_BOTTOMUP;
119 bmp.usRendering = BRH_NOTHALFTONED;
120 bmp.cSize1 = 0;
121 bmp.cSize2 = 0;
122 bmp.ulColorEncoding = BCE_RGB;
123 bmp.ulIdentifier = 0;
124
125 // create a bit map that is compatible with the display
126 HBITMAP hbm = GpiCreateBitmap (hpsMem, &bmp, 0L, NULL, NULL/*pbmi*/);
127
128 // associate the bit map and the memory presentation space
129 HBITMAP hbmOld = GpiSetBitmap (hpsMem, hbm);
130
131 /* Copy the screen to the bit map. */
132 aptl[0].x = 0; /* Lower-left corner of destination rectangle */
133 aptl[0].y = 0; /* Lower-left corner of destination rectangle */
134 aptl[1].x = sWidth; /* Upper-right corner of destination rectangle */
135 aptl[1].y = sHeight; /* Upper-right corner of destination rectangle */
136
137 if (! prcl)
138 {
139 aptl[2].x = 0; /* Lower-left corner of source rectangle */
140 aptl[2].y = 0; /* Lower-left corner of source rectangle */
141 }
142 else
143 {
144 aptl[2].x = prcl->xLeft; /* Lower-left corner of source rectangle */
145 aptl[2].y = prcl->yBottom; /* Lower-left corner of source rectangle */
146 }
147
148 HPS hps;
149
150 // esp. important if serial capture enabled: window may have been closed!
151 if (WinIsWindow (GETHAB, hwnd) || (hwnd == HWND_DESKTOP))
152 hps = WinGetPS (hwnd);
153 else
154 {
155 GpiDeleteBitmap (hbm);
156 DevCloseDC (hdcMem);
157 return NULL;
158 }
159
160 GpiBitBlt (hpsMem, hps,
161 sizeof (aptl) / sizeof (POINTL), /* Number of points in aptl */
162 aptl, ROP_SRCCOPY, BBO_IGNORE);
163
164 SWCNTRL swctl;
165 PID pid;
166 TID tid;
167 BOOL screen = FALSE, region = FALSE;
168 CHAR title[11];
169
170 if (!f) {
171 //hwndParent = WinQueryFocus(HWND_DESKTOP);
172 if (hwndParent == hwndFrame) {
173 hwndParent = WinQueryWindow(hwndFrame, QW_NEXTTOP );
174 }
175 screen = TRUE;
176 if (prcl)
177 region = TRUE;
178 }
179
180 int rc = WinQueryWindowProcess(hwndParent, &pid, &tid);
181 if (WinQuerySwitchEntry(WinQuerySwitchHandle(hwndParent, pid),
182 &swctl))
183 WinQuerySwitchEntry(WinQuerySwitchHandle(NULLHANDLE, pid),
184 &swctl);
185
186 char buffer[MAXNAMEL+4];
187 int length = strlen( swctl.szSwtitle );
188 strcpy(buffer, swctl.szSwtitle);
189 char *p;
190 p = buffer;
191 for (int i = 0; i < (length < 11 ? length : 11); i++) {
192 if ( ispunct( *p ) || *p == '\\' || isblank( *p )) {
193 *p = '_';
194 }
195 p++;
196 }
197
198 if (region)
199 snprintf( title, length < 8 ? length + 3 : 11, "SR%s", buffer);
200 else if (screen)
201 snprintf( title, length < 8 ? length + 3 : 11, "SC%s", buffer);
202 else
203 snprintf( title, length < 8 ? length + 3 : 11, "WD%s", buffer);
204
205 SaveBitmap (hbm, hpsMem, sWidth, sHeight, bmp.cBitCount, title);
206
207 // re-associate the previous bit map and the memory presentation space
208 GpiSetBitmap (hpsMem, hbmOld);
209
210 GpiDeleteBitmap (hbm);
211 WinReleasePS (hps);
212 GpiDestroyPS (hps);
213 DevCloseDC (hdcMem);
214
215#ifdef _DOLOGMEM_
216 LogMem("CaptureWindow", FALSE);
217#endif
218
219 return hbm;
220}
221
222// ** DoTracking ********************************************************** /*FOLD00*/
223
224BOOL DoTracking (RECTL *prclTrack)
225{
226 LONG cxScreen, cyScreen, cxPointer, cyPointer;
227 TRACKINFO ti;
228
229 cxScreen = WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
230 cyScreen = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
231 cxPointer = WinQuerySysValue (HWND_DESKTOP, SV_CXPOINTER);
232 cyPointer = WinQuerySysValue (HWND_DESKTOP, SV_CYPOINTER);
233
234 ti.cxBorder = 1;
235 ti.cyBorder = 1;
236
237 ti.cxGrid = 0;
238 ti.cyGrid = 0;
239
240 ti.cxKeyboard = 4;
241 ti.cyKeyboard = 4;
242
243 ti.rclBoundary.xLeft = 0;
244 ti.rclBoundary.yBottom = 0;
245 ti.rclBoundary.xRight = cxScreen;
246 ti.rclBoundary.yTop = cyScreen;
247
248 ti.ptlMinTrackSize.x = 1;
249 ti.ptlMinTrackSize.y = 1;
250 ti.ptlMaxTrackSize.x = cxScreen;
251 ti.ptlMaxTrackSize.y = cyScreen;
252
253 ti.rclTrack.xLeft = (cxScreen-cxPointer)/2;
254 ti.rclTrack.yBottom = (cyScreen-cyPointer)/2;
255 ti.rclTrack.xRight = (cxScreen+cxPointer)/2;
256 ti.rclTrack.yTop = (cyScreen+cyPointer)/2;
257
258 ti.fs = TF_MOVE | TF_STANDARD | TF_SETPOINTERPOS;
259
260 if (! WinTrackRect (HWND_DESKTOP, NULL, &ti))
261 return FALSE;
262
263 WinSetPointer (HWND_DESKTOP,
264 WinQuerySysPointer (HWND_DESKTOP, SPTR_SIZENESW, FALSE));
265
266 ti.fs = TF_RIGHT | TF_TOP | TF_STANDARD | TF_SETPOINTERPOS;
267
268 if (! WinTrackRect (HWND_DESKTOP, NULL, &ti))
269 return FALSE;
270
271 *prclTrack = ti.rclTrack;
272
273 return TRUE;
274}
275
276// ** StartSelection ****************************************************** /*FOLD00*/
277
278VOID StartSelection (HWND hwnd)
279{
280 WinSetPointer (HWND_DESKTOP, WinLoadPointer (HWND_DESKTOP, GETMODULE, 2));
281 WinSetCapture (HWND_DESKTOP, hwnd);
282}
283
284// ************************************************************************
Note: See TracBrowser for help on using the repository browser.