itermediate working result
[imager-screenshot.git] / scwin32.c
CommitLineData
0ddb7051
TC
1#include "imext.h"
2#include <windows.h>
3#include <string.h>
87cd516f 4#include "imss.h"
0ddb7051 5
ece126f9
TC
6/* the SDK headers supplied with cygwin, and with some older strawberry perls */
7#ifndef DISPLAY_DEVICE_ACTIVE
8#define DISPLAY_DEVICE_ACTIVE 1
9#endif
10
11struct moniter_ctx {
12 i_img *out;
13 i_img_dim orig_x, orig_y;
14};
15
16static int
17display_to_img(HDC dc, i_img *im, const RECT *src, int dest_x, int dest_y) {
18 HBITMAP work_bmp;
19 HDC bmdc;
20 HBITMAP old_dc_bmp;
21 i_img_dim width = src->right - src->left;
22 i_img_dim height = src->bottom - src->top;
23 int result = 0;
24 BITMAPINFO bmi;
25 unsigned char *di_bits;
26
27 work_bmp = CreateCompatibleBitmap(dc, width, height);
28 bmdc = CreateCompatibleDC(dc);
29 old_dc_bmp = SelectObject(bmdc, work_bmp);
30 BitBlt(bmdc, 0, 0, width, height, dc, src->left, src->top, SRCCOPY);
31
32 /* make a dib */
33 memset(&bmi, 0, sizeof(bmi));
34 bmi.bmiHeader.biSize = sizeof(bmi);
35 bmi.bmiHeader.biWidth = width;
36 bmi.bmiHeader.biHeight = -height;
37 bmi.bmiHeader.biPlanes = 1;
38 bmi.bmiHeader.biBitCount = 32;
39 bmi.bmiHeader.biCompression = BI_RGB;
40
41 di_bits = mymalloc(4 * width * height);
42 if (GetDIBits(bmdc, work_bmp, 0, height, di_bits, &bmi, DIB_RGB_COLORS)) {
43 i_color *line = mymalloc(sizeof(i_color) * width);
44 i_color *cp;
45 int x, y;
46 unsigned char *ch_pp = di_bits;
47 for (y = 0; y < height; ++y) {
48 cp = line;
49 for (x = 0; x < width; ++x) {
50 cp->rgb.b = *ch_pp++;
51 cp->rgb.g = *ch_pp++;
52 cp->rgb.r = *ch_pp++;
53 ch_pp++;
54 cp++;
55 }
56 i_plin(im, dest_x, width, dest_y + y, line);
57 }
58 myfree(line);
59 result = 1;
60 }
61 else {
62 i_push_errorf(0, "GetDIBits() failure %d", (long)GetLastError());
63 }
64
65 myfree(di_bits);
66 SelectObject(bmdc, old_dc_bmp);
67 DeleteDC(bmdc);
68 DeleteObject(work_bmp);
69
70 return result;
71}
72
0ddb7051 73i_img *
87cd516f 74imss_win32(unsigned hwnd_u, int include_decor, int left, int top,
4e6ce56a 75 int right, int bottom, int display) {
0ddb7051 76 HWND hwnd = (HWND)hwnd_u;
ece126f9 77 HDC cdc = 0, wdc;
4e6ce56a
TC
78 int orig_x = 0;
79 int orig_y = 0;
87cd516f 80 int window_width, window_height;
0ddb7051 81 i_img *result = NULL;
87cd516f 82 int width, height;
ece126f9 83 int channels = 3;
0ddb7051
TC
84
85 i_clear_error();
86
4e6ce56a
TC
87 if (hwnd) {
88 RECT rect;
89 if (include_decor) {
90 wdc = GetWindowDC(hwnd);
91 GetWindowRect(hwnd, &rect);
92 }
93 else {
94 wdc = GetDC(hwnd);
95 GetClientRect(hwnd, &rect);
96 }
97 if (!wdc) {
98 i_push_error(0, "Cannot get window DC - invalid hwnd?");
99 return NULL;
100 }
0ddb7051 101
4e6ce56a
TC
102 window_width = rect.right - rect.left;
103 window_height = rect.bottom - rect.top;
0ddb7051
TC
104 }
105 else {
4e6ce56a 106 if (display == -1) {
4e6ce56a
TC
107 cdc = CreateDC("DISPLAY", NULL, NULL, NULL);
108 orig_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
109 orig_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
110 window_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
111 window_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
ece126f9 112 channels = 4;
4e6ce56a
TC
113 }
114 else {
115 DISPLAY_DEVICE dd;
116 dd.cb = sizeof(dd);
0ddb7051 117
4e6ce56a 118 if (EnumDisplayDevices(NULL, display, &dd, 0)) {
ece126f9 119 printf("Flags %lx\n", (unsigned long)dd.StateFlags);
f7119376
TC
120 if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) {
121 cdc = CreateDC(dd.DeviceName, dd.DeviceName, NULL, NULL);
122 }
123 else {
124 i_push_errorf(0, "Display device %d not active", display);
125 return NULL;
126 }
4e6ce56a
TC
127 }
128 else {
129 i_push_errorf(0, "Cannot enumerate device %d: %ld", display, (long)GetLastError());
130 return NULL;
131 }
132
133 window_width = GetDeviceCaps(cdc, HORZRES);
134 window_height = GetDeviceCaps(cdc, VERTRES);
135 }
136
137 wdc = cdc;
138 }
87cd516f
TC
139
140 /* adjust negative/zero values to window size */
141 if (left < 0)
142 left += window_width;
143 if (top < 0)
144 top += window_height;
145 if (right <= 0)
146 right += window_width;
147 if (bottom <= 0)
148 bottom += window_height;
149
150 /* clamp */
151 if (left < 0)
152 left = 0;
153 if (right > window_width)
154 right = window_width;
155 if (top < 0)
156 top = 0;
157 if (bottom > window_height)
158 bottom = window_height;
159
160 /* validate */
161 if (right <= left || bottom <= top) {
162 i_push_error(0, "image would be empty");
f7119376
TC
163 if (cdc)
164 DeleteDC(cdc);
165 else
166 ReleaseDC(hwnd, wdc);
87cd516f
TC
167 return NULL;
168 }
169 width = right - left;
170 height = bottom - top;
ece126f9
TC
171
172 result = i_img_8_new(width, height, channels);
173
174 if (result) {
175 RECT r;
176 r.left = orig_x + left;
177 r.top = orig_y + top;
178 r.right = r.left + width;
179 r.bottom = r.top + height;
180
181 if (display_to_img(wdc, result, &r, 0, 0)) {
182 i_tags_setn(&result->tags, "ss_window_width", window_width);
183 i_tags_setn(&result->tags, "ss_window_height", window_height);
184 i_tags_set(&result->tags, "ss_type", "Win32", 5);
185 i_tags_setn(&result->tags, "ss_left", left);
186 i_tags_setn(&result->tags, "ss_top", top);
187 }
188 else {
189 i_img_destroy(result);
190 result = NULL;
0ddb7051 191 }
0ddb7051 192 }
0ddb7051 193 /* clean up */
4e6ce56a
TC
194 if (cdc) {
195 DeleteDC(cdc);
196 }
197 else {
198 ReleaseDC(hwnd, wdc);
199 }
0ddb7051
TC
200
201 return result;
202}