- add support for getting a subimage of the window
[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
TC
5
6i_img *
87cd516f
TC
7imss_win32(unsigned hwnd_u, int include_decor, int left, int top,
8 int right, int bottom) {
0ddb7051
TC
9 HWND hwnd = (HWND)hwnd_u;
10 HDC wdc, bmdc;
11 RECT rect;
12 HBITMAP work_bmp, old_dc_bmp;
87cd516f 13 int window_width, window_height;
0ddb7051
TC
14 BITMAPINFO bmi;
15 unsigned char *di_bits;
16 i_img *result = NULL;
87cd516f 17 int width, height;
0ddb7051
TC
18
19 i_clear_error();
20
21 if (!hwnd)
22 hwnd = GetDesktopWindow();
23
24 if (include_decor) {
25 wdc = GetWindowDC(hwnd);
26 GetWindowRect(hwnd, &rect);
27 }
28 else {
29 wdc = GetDC(hwnd);
30 GetClientRect(hwnd, &rect);
31 }
32 if (!wdc) {
33 i_push_error(0, "Cannot get window DC - invalid hwnd?");
34 return NULL;
35 }
36
87cd516f
TC
37 window_width = rect.right - rect.left;
38 window_height = rect.bottom - rect.top;
39
40 /* adjust negative/zero values to window size */
41 if (left < 0)
42 left += window_width;
43 if (top < 0)
44 top += window_height;
45 if (right <= 0)
46 right += window_width;
47 if (bottom <= 0)
48 bottom += window_height;
49
50 /* clamp */
51 if (left < 0)
52 left = 0;
53 if (right > window_width)
54 right = window_width;
55 if (top < 0)
56 top = 0;
57 if (bottom > window_height)
58 bottom = window_height;
59
60 /* validate */
61 if (right <= left || bottom <= top) {
62 i_push_error(0, "image would be empty");
63 return NULL;
64 }
65 width = right - left;
66 height = bottom - top;
67
0ddb7051
TC
68 work_bmp = CreateCompatibleBitmap(wdc, width, height);
69 bmdc = CreateCompatibleDC(wdc);
70 old_dc_bmp = SelectObject(bmdc, work_bmp);
87cd516f 71 BitBlt(bmdc, 0, 0, width, height, wdc, left, top, SRCCOPY);
0ddb7051
TC
72
73 /* make a dib */
74 memset(&bmi, 0, sizeof(bmi));
75 bmi.bmiHeader.biSize = sizeof(bmi);
76 bmi.bmiHeader.biWidth = width;
77 bmi.bmiHeader.biHeight = -height;
78 bmi.bmiHeader.biPlanes = 1;
79 bmi.bmiHeader.biBitCount = 32;
80 bmi.bmiHeader.biCompression = BI_RGB;
81
82 di_bits = mymalloc(4 * width * height);
83 if (GetDIBits(bmdc, work_bmp, 0, height, di_bits, &bmi, DIB_RGB_COLORS)) {
84 i_color *line = mymalloc(sizeof(i_color) * width);
85 i_color *cp;
86 int x, y;
87 unsigned char *ch_pp = di_bits;
88 result = i_img_8_new(width, height, 3);
89
90 for (y = 0; y < height; ++y) {
91 cp = line;
92 for (x = 0; x < width; ++x) {
93 cp->rgb.b = *ch_pp++;
94 cp->rgb.g = *ch_pp++;
95 cp->rgb.r = *ch_pp++;
96 ch_pp++;
97 cp++;
98 }
99 i_plin(result, 0, width, y, line);
100 }
101 myfree(line);
102 }
103
104 /* clean up */
105 myfree(di_bits);
106 SelectObject(bmdc, old_dc_bmp);
107 DeleteDC(bmdc);
108 DeleteObject(work_bmp);
109 ReleaseDC(hwnd, wdc);
110
111 return result;
112}