6 /* the SDK headers supplied with cygwin, and with some older strawberry perls */
7 #ifndef DISPLAY_DEVICE_ACTIVE
8 #define DISPLAY_DEVICE_ACTIVE 1
12 i_push_win32_errorf(DWORD msg_id, char const *fmt, ...) {
18 vsprintf(buf, fmt, args);
19 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
30 sprintf(buf+strlen(buf), "%#010x", msg_id);
32 i_push_error(msg_id, buf);
38 i_img_dim orig_x, orig_y;
43 display_to_img(HDC dc, i_img *im, const RECT *src, int dest_x, int dest_y) {
47 i_img_dim width = src->right - src->left;
48 i_img_dim height = src->bottom - src->top;
51 unsigned char *di_bits;
53 work_bmp = CreateCompatibleBitmap(dc, width, height);
54 bmdc = CreateCompatibleDC(dc);
55 old_dc_bmp = SelectObject(bmdc, work_bmp);
56 BitBlt(bmdc, 0, 0, width, height, dc, src->left, src->top, SRCCOPY);
59 memset(&bmi, 0, sizeof(bmi));
60 bmi.bmiHeader.biSize = sizeof(bmi);
61 bmi.bmiHeader.biWidth = width;
62 bmi.bmiHeader.biHeight = -height;
63 bmi.bmiHeader.biPlanes = 1;
64 bmi.bmiHeader.biBitCount = 32;
65 bmi.bmiHeader.biCompression = BI_RGB;
67 di_bits = mymalloc(4 * width * height);
68 if (GetDIBits(bmdc, work_bmp, 0, height, di_bits, &bmi, DIB_RGB_COLORS)) {
69 i_color *line = mymalloc(sizeof(i_color) * width);
72 unsigned char *ch_pp = di_bits;
73 for (y = 0; y < height; ++y) {
75 for (x = 0; x < width; ++x) {
76 cp->rgba.b = *ch_pp++;
77 cp->rgba.g = *ch_pp++;
78 cp->rgba.r = *ch_pp++;
83 i_plin(im, dest_x, dest_x+width, dest_y + y, line);
89 i_push_win32_errorf(GetLastError(), "GetDIBits() failure: ");
93 SelectObject(bmdc, old_dc_bmp);
95 DeleteObject(work_bmp);
101 monitor_enum(HMONITOR hmon, HDC dc, LPRECT r, LPARAM lp_ctx) {
102 struct monitor_ctx *ctx = (struct monitor_ctx *)lp_ctx;
104 if (!display_to_img(dc, ctx->out, r,
105 r->left - ctx->orig_x, r->top - ctx->orig_y)) {
113 imss_win32(unsigned hwnd_u, int include_decor, int left, int top,
114 int right, int bottom, int display) {
115 HWND hwnd = (HWND)hwnd_u;
119 int window_width, window_height;
120 i_img *result = NULL;
129 wdc = GetWindowDC(hwnd);
130 GetWindowRect(hwnd, &rect);
134 GetClientRect(hwnd, &rect);
137 i_push_error(0, "Cannot get window DC - invalid hwnd?");
141 window_width = rect.right - rect.left;
142 window_height = rect.bottom - rect.top;
146 cdc = CreateDC("DISPLAY", NULL, NULL, NULL);
147 orig_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
148 orig_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
149 window_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
150 window_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
155 int work_display = 0;
156 int primary_display = -1;
157 int real_display = -1;
160 /* look for the primary display, we need a simulate a gap to put the
162 while (work_display < 100
163 && EnumDisplayDevices(NULL, work_display, &dd, 0)) {
164 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
165 primary_display = work_display;
168 else if (display && display-1 == work_display) {
169 real_display = work_display;
177 if (!work_display && real_display == -1 && primary_display == -1) {
178 /* EnumDisplayDevices() failed for the first call */
179 i_push_win32_errorf(GetLastError(), "Cannot enumerate device %d(0): ", work_display);
183 if (primary_display != -1 && display == 0) {
184 real_display = primary_display;
187 if (real_display == -1) {
188 /* haven't enumerated the display we want yet */
189 /* we're after the primary */
190 real_display = display;
192 if (!EnumDisplayDevices(NULL, real_display, &dd, 0)) {
193 i_push_win32_errorf(GetLastError(), "Cannot enumerate device %d(%d): ",
194 real_display, display);
199 if (!(dd.StateFlags & DISPLAY_DEVICE_ACTIVE)) {
200 i_push_errorf(0, "Display device %d not active", display);
203 cdc = CreateDC(dd.DeviceName, dd.DeviceName, NULL, NULL);
205 i_push_win32_errorf(GetLastError(), "Cannot CreateDC(%s): ", dd.DeviceName);
209 window_width = GetDeviceCaps(cdc, HORZRES);
210 window_height = GetDeviceCaps(cdc, VERTRES);
216 /* adjust negative/zero values to window size */
218 left += window_width;
220 top += window_height;
222 right += window_width;
224 bottom += window_height;
229 if (right > window_width)
230 right = window_width;
233 if (bottom > window_height)
234 bottom = window_height;
237 if (right <= left || bottom <= top) {
238 i_push_error(0, "image would be empty");
242 ReleaseDC(hwnd, wdc);
245 width = right - left;
246 height = bottom - top;
248 result = i_img_8_new(width, height, channels);
252 r.left = orig_x + left;
253 r.top = orig_y + top;
254 r.right = r.left + width;
255 r.bottom = r.top + height;
258 struct monitor_ctx ctx;
264 if (!EnumDisplayMonitors(wdc, &r, monitor_enum, (LPARAM)&ctx)
266 i_img_destroy(result);
271 if (!display_to_img(wdc, result, &r, 0, 0)) {
272 i_img_destroy(result);
277 i_tags_setn(&result->tags, "ss_window_width", window_width);
278 i_tags_setn(&result->tags, "ss_window_height", window_height);
279 i_tags_set(&result->tags, "ss_type", "Win32", 5);
280 i_tags_setn(&result->tags, "ss_left", left);
281 i_tags_setn(&result->tags, "ss_top", top);
289 ReleaseDC(hwnd, wdc);