0.008 release
[imager-screenshot.git] / scwin32.c
1 #include "imext.h"
2 #include <windows.h>
3 #include <string.h>
4 #include "imss.h"
5
6 i_img *
7 imss_win32(unsigned hwnd_u, int include_decor, int left, int top, 
8            int right, int bottom) {
9   HWND hwnd = (HWND)hwnd_u;
10   HDC wdc, bmdc;
11   RECT rect;
12   HBITMAP work_bmp, old_dc_bmp;
13   int window_width, window_height;
14   BITMAPINFO bmi;
15   unsigned char *di_bits;
16   i_img *result = NULL;
17   int width, height;
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
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
68   work_bmp = CreateCompatibleBitmap(wdc, width, height);
69   bmdc = CreateCompatibleDC(wdc);
70   old_dc_bmp = SelectObject(bmdc, work_bmp);
71   BitBlt(bmdc, 0, 0, width, height, wdc, left, top, SRCCOPY);
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   i_tags_setn(&result->tags, "ss_window_width", window_width);
105   i_tags_setn(&result->tags, "ss_window_height", window_height);
106   i_tags_set(&result->tags, "ss_type", "Win32", 5);
107   i_tags_setn(&result->tags, "ss_left", left);
108   i_tags_setn(&result->tags, "ss_top", top);
109
110   /* clean up */
111   myfree(di_bits);
112   SelectObject(bmdc, old_dc_bmp);
113   DeleteDC(bmdc);
114   DeleteObject(work_bmp);
115   ReleaseDC(hwnd, wdc);
116
117   return result;
118 }