special_input_device 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/special_input_device/_screen.c +25 -0
- data/ext/special_input_device/_screen.h +16 -0
- data/ext/special_input_device/_system_time.c +10 -0
- data/ext/special_input_device/_system_time.h +6 -0
- data/ext/special_input_device/_vendor__interception.c +331 -0
- data/ext/special_input_device/_vendor__interception.h +196 -0
- data/ext/special_input_device/color.c +25 -0
- data/ext/special_input_device/color.h +10 -0
- data/ext/special_input_device/extconf.rb +6 -0
- data/ext/special_input_device/interception_connector.c +75 -0
- data/ext/special_input_device/interception_connector.h +13 -0
- data/ext/special_input_device/keyboard.c +152 -0
- data/ext/special_input_device/mouse.c +1137 -0
- data/ext/special_input_device/point.c +17 -0
- data/ext/special_input_device/point.h +10 -0
- data/ext/special_input_device/rectangle.c +25 -0
- data/ext/special_input_device/rectangle.h +10 -0
- data/ext/special_input_device/ruby_macro.h +84 -0
- data/ext/special_input_device/screen.c +302 -0
- data/ext/special_input_device/special_input_device.c +40 -0
- data/ext/special_input_device/special_input_device.h +42 -0
- data/ext/special_input_device/win32error.c +69 -0
- data/ext/special_input_device/win32error.h +8 -0
- data/ext/special_input_device/window.c +1108 -0
- data/lib/special_input_device/attributes_equal_checker.rb +13 -0
- data/lib/special_input_device/color.rb +156 -0
- data/lib/special_input_device/image.rb +170 -0
- data/lib/special_input_device/image/bmp.rb +89 -0
- data/lib/special_input_device/image/error/damaged_image_error.rb +4 -0
- data/lib/special_input_device/image/error/image_error.rb +3 -0
- data/lib/special_input_device/image/error/unsupported_image_format_error.rb +4 -0
- data/lib/special_input_device/key_code.rb +268 -0
- data/lib/special_input_device/point.rb +48 -0
- data/lib/special_input_device/rectangle.rb +187 -0
- data/lib/special_input_device/special_input_device.rb +67 -0
- data/lib/special_input_device/table_2d.rb +157 -0
- data/stab/keyboard.rb +35 -0
- data/stab/mouse.rb +189 -0
- data/stab/screen.rb +56 -0
- data/stab/win32_error.rb +20 -0
- data/stab/window.rb +398 -0
- metadata +85 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#include "special_input_device.h"
|
|
2
|
+
|
|
3
|
+
VALUE ruby___point_new(INT cX, INT cY) {
|
|
4
|
+
VALUE newPointArguments[2];
|
|
5
|
+
newPointArguments[0] = INT2NUM(cX);
|
|
6
|
+
newPointArguments[1] = INT2NUM(cY);
|
|
7
|
+
return rb_class_new_instance(2, newPointArguments, specialInputDevice_point);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
inline VALUE ruby___point_new_from_point(LPPOINT cPoint) {
|
|
11
|
+
return ruby___point_new(cPoint->x, cPoint->y);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
inline VOID ruby___point_to_point(VALUE point, LPPOINT cPoint) {
|
|
15
|
+
cPoint->x = NUM2LONG(rb_iv_get(point, "@x"));
|
|
16
|
+
cPoint->y = NUM2LONG(rb_iv_get(point, "@y"));
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#ifndef SPECIAL_INPUT_DEVICE_POINT_H
|
|
2
|
+
#define SPECIAL_INPUT_DEVICE_POINT_H
|
|
3
|
+
|
|
4
|
+
VALUE ruby___point_new(INT cX, INT cY);
|
|
5
|
+
|
|
6
|
+
VALUE ruby___point_new_from_point(LPPOINT cPoint);
|
|
7
|
+
|
|
8
|
+
VOID ruby___point_to_point(VALUE point, LPPOINT cPoint);
|
|
9
|
+
|
|
10
|
+
#endif //SPECIAL_INPUT_DEVICE_POINT_H
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#include "special_input_device.h"
|
|
2
|
+
|
|
3
|
+
VALUE ruby___rectangle_new(INT left, INT top, INT right, INT bottom) {
|
|
4
|
+
VALUE newOriginArguments[2];
|
|
5
|
+
VALUE newEndPointArguments[2];
|
|
6
|
+
VALUE newRectangleArguments[2];
|
|
7
|
+
newOriginArguments[0] = INT2NUM(left);
|
|
8
|
+
newOriginArguments[1] = INT2NUM(top);
|
|
9
|
+
newEndPointArguments[0] = INT2NUM(right);
|
|
10
|
+
newEndPointArguments[1] = INT2NUM(bottom);
|
|
11
|
+
newRectangleArguments[0] = rb_class_new_instance(2, newOriginArguments, specialInputDevice_point);
|
|
12
|
+
newRectangleArguments[1] = rb_class_new_instance(2, newEndPointArguments, specialInputDevice_point);
|
|
13
|
+
return rb_class_new_instance(2, newRectangleArguments, specialInputDevice_rectangle);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
inline VALUE ruby___rectangle_new_from_rect(LPRECT cRectangle) {
|
|
17
|
+
return ruby___rectangle_new(cRectangle->left, cRectangle->top, cRectangle->right, cRectangle->bottom);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
inline VOID ruby___rectangle_to_rect(VALUE rectangle, LPRECT cRectangle) {
|
|
21
|
+
cRectangle->left = NUM2LONG(rb_funcall(rectangle, rb_intern_const("left"), 0));
|
|
22
|
+
cRectangle->top = NUM2LONG(rb_funcall(rectangle, rb_intern_const("top"), 0));
|
|
23
|
+
cRectangle->right = NUM2LONG(rb_funcall(rectangle, rb_intern_const("right"), 0));
|
|
24
|
+
cRectangle->bottom = NUM2LONG(rb_funcall(rectangle, rb_intern_const("bottom"), 0));
|
|
25
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#ifndef SPECIAL_INPUT_DEVICE_RECTANGLE_H
|
|
2
|
+
#define SPECIAL_INPUT_DEVICE_RECTANGLE_H
|
|
3
|
+
|
|
4
|
+
VALUE ruby___rectangle_new(INT left, INT top, INT right, INT bottom);
|
|
5
|
+
|
|
6
|
+
VALUE ruby___rectangle_new_from_rect(LPRECT cRectangle);
|
|
7
|
+
|
|
8
|
+
VOID ruby___rectangle_to_rect(VALUE rectangle, LPRECT cRectangle);
|
|
9
|
+
|
|
10
|
+
#endif //SPECIAL_INPUT_DEVICE_RECTANGLE_H
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#ifndef SPECIAL_INPUT_DEVICE_RUBY_MACRO_H
|
|
2
|
+
#define SPECIAL_INPUT_DEVICE_RUBY_MACRO_H
|
|
3
|
+
|
|
4
|
+
#include "win32error.h"
|
|
5
|
+
|
|
6
|
+
// Hide error messages in CLion
|
|
7
|
+
#ifdef CLION
|
|
8
|
+
|
|
9
|
+
NORETURN(void _RUBY_KERNEL_RAISE();)
|
|
10
|
+
|
|
11
|
+
# define RUBY_KERNEL_RAISE(exception) \
|
|
12
|
+
(rb_funcall(rb_mKernel, rb_intern_const("raise"), 1, exception), _RUBY_KERNEL_RAISE())
|
|
13
|
+
# define RUBY_OBJECT_IS_A_qs(object, _class) rb_funcall(object, rb_intern_const("is_a?"), 1, _class)
|
|
14
|
+
# define RUBY_REGEXP_MATCH(regexp, string) rb_funcall(regexp, rb_intern_const("match"), 1, string)
|
|
15
|
+
# define RUBY_MODULE_CONST_GET(module, id) rb_funcall(module, rb_intern_const("const_get"), 1, id)
|
|
16
|
+
#else
|
|
17
|
+
# define RUBY_KERNEL_RAISE(exception) rb_exc_raise(exception)
|
|
18
|
+
# define RUBY_OBJECT_IS_A_qs(object, _class) rb_obj_is_kind_of(object, _class)
|
|
19
|
+
# define RUBY_REGEXP_MATCH(regexp, string) rb_reg_match(regexp, string)
|
|
20
|
+
# define RUBY_MODULE_CONST_GET(module, id) rb_const_get(module, id)
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
// Encoding
|
|
24
|
+
#define INTERNAL_ENCODING rb_utf8_encoding()
|
|
25
|
+
#ifdef UNICODE
|
|
26
|
+
# define EXTERNAL_ENCODING rb_enc_find("UTF-16LE")
|
|
27
|
+
VALUE __ruby_string_converter_temp_variable;
|
|
28
|
+
# define RUBY_LPTSTR_TO_VALUE(string, length) \
|
|
29
|
+
(\
|
|
30
|
+
__ruby_string_converter_temp_variable = rb_str_new((LPSTR) string, length * sizeof(WCHAR)),\
|
|
31
|
+
__ruby_string_converter_temp_variable = rb_enc_associate(__ruby_string_converter_temp_variable, EXTERNAL_ENCODING),\
|
|
32
|
+
rb_str_export_to_enc(__ruby_string_converter_temp_variable, INTERNAL_ENCODING)\
|
|
33
|
+
)
|
|
34
|
+
# define RUBY_LPCTSTR_TO_VALUE(string) \
|
|
35
|
+
RUBY_LPTSTR_TO_VALUE(string, (INT) wcslen(string))
|
|
36
|
+
# define RUBY_VALUE_TO_LPTSTR(string, _OUT_length) \
|
|
37
|
+
(\
|
|
38
|
+
__ruby_string_converter_temp_variable = rb_str_export_to_enc(string, EXTERNAL_ENCODING),\
|
|
39
|
+
_OUT_length = RSTRING_LEN(__ruby_string_converter_temp_variable) / sizeof(WCHAR),\
|
|
40
|
+
(LPTSTR) StringValuePtr(__ruby_string_converter_temp_variable)\
|
|
41
|
+
)
|
|
42
|
+
# define RUBY_VALUE_TO_LPCTSTR(string) \
|
|
43
|
+
(\
|
|
44
|
+
__ruby_string_converter_temp_variable = rb_str_export_to_enc(string, EXTERNAL_ENCODING),\
|
|
45
|
+
(LPCTSTR) StringValueCStr(__ruby_string_converter_temp_variable)\
|
|
46
|
+
)
|
|
47
|
+
#else
|
|
48
|
+
# define EXTERNAL_ENCODING rb_locale_encoding()
|
|
49
|
+
# define RUBY_LPTSTR_TO_VALUE(string, length) \
|
|
50
|
+
rb_enc_str_new(string, length, EXTERNAL_ENCODING);
|
|
51
|
+
# define RUBY_LPCTSTR_TO_VALUE(string) \
|
|
52
|
+
rb_enc_str_new_cstr(string, EXTERNAL_ENCODING);
|
|
53
|
+
# define RUBY_VALUE_TO_LPTSTR(string, _OUT_length) \
|
|
54
|
+
(_OUT_length = RSTRING_LEN(string), StringValuePtr())
|
|
55
|
+
# define RUBY_VALUE_TO_LPCTSTR(string) \
|
|
56
|
+
StringValueCStr(string)
|
|
57
|
+
#endif
|
|
58
|
+
|
|
59
|
+
#define NEW_DATA_OBJECT(_class, data_type, mark, free) \
|
|
60
|
+
rb_data_object_zalloc((_class), sizeof(data_type), (RUBY_DATA_FUNC)(mark), (RUBY_DATA_FUNC)(free))
|
|
61
|
+
#define NEW_SIMPLE_DATA_OBJECT(_class, data_type) NEW_DATA_OBJECT(_class, data_type, NULL, RUBY_DEFAULT_FREE)
|
|
62
|
+
|
|
63
|
+
#define RUBY_KERNEL_P(object) rb_funcall(rb_mKernel, rb_intern_const("p"), 1, object)
|
|
64
|
+
#define RUBY_KERNEL_PUTS(object) rb_funcall(rb_mKernel, rb_intern_const("puts"), 1, object)
|
|
65
|
+
|
|
66
|
+
#define RAISE_WIN32_ERROR RUBY_KERNEL_RAISE(ruby___win32error_new())
|
|
67
|
+
#define RAISE_WIN32_ERROR_FROM_CODE(code) RUBY_KERNEL_RAISE(ruby___win32error_new_from_code(code))
|
|
68
|
+
#define RAISE_ARGUMENT_ERROR(expected) \
|
|
69
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected %s)", cCount, expected)
|
|
70
|
+
#define RAISE_TYPE_ERROR(object, expected) \
|
|
71
|
+
rb_raise(rb_eTypeError, "Expecting %s, got %s", expected, rb_obj_classname(object))
|
|
72
|
+
#define CHECK_TYPE_ERROR(object, expected) \
|
|
73
|
+
({\
|
|
74
|
+
if (!RTEST(RUBY_OBJECT_IS_A_qs(object, expected)))\
|
|
75
|
+
RAISE_TYPE_ERROR(object, rb_class2name(expected));\
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
#define VARIABLE_ARGUMENTS_C INT cCount, VALUE* cArguments, VALUE self
|
|
79
|
+
#define VARIABLE_ARGUMENTS_RUBY VALUE self, VALUE arguments
|
|
80
|
+
#define SCAN_ARGUMENTS(format, arguments...) rb_scan_args(cCount, cArguments, format, arguments)
|
|
81
|
+
|
|
82
|
+
#define ARGUMENT_AT(index, defaultValue) cCount > index ? cArguments[index] : defaultValue
|
|
83
|
+
|
|
84
|
+
#endif //SPECIAL_INPUT_DEVICE_RUBY_MACRO_H
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
#include "special_input_device.h"
|
|
2
|
+
#include "_screen.h"
|
|
3
|
+
#include "color.h"
|
|
4
|
+
#include "rectangle.h"
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* Returns the rectangle of primary screen. The rectangle is relative to primary screen itself so the upper-left corner
|
|
8
|
+
* of the rectangle is always (0, 0).
|
|
9
|
+
* @return [SpecialInputDevice::Rectangle] the rectangle of primary screen
|
|
10
|
+
* @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385.aspx Windows Dev Center - GetSystemMetrics function
|
|
11
|
+
*/
|
|
12
|
+
static VALUE ruby__primary_screen(VALUE self) {
|
|
13
|
+
return ruby___rectangle_new(0, 0, getPrimaryScreenWidth(), getPrimaryScreenHeight());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* Returns the rectangle of virtual screen. The rectangle is relative to primary screen so the x and y of upper-left
|
|
18
|
+
* corner is always non-positive. Virtual screen is a area that contain all the screens and some position in virtual may
|
|
19
|
+
* not accessible.
|
|
20
|
+
* @return [SpecialInputDevice::Rectangle] the rectangle of virtual screen
|
|
21
|
+
* @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385.aspx Windows Dev Center - GetSystemMetrics function
|
|
22
|
+
*/
|
|
23
|
+
static VALUE ruby__virtual_screen(VALUE self) {
|
|
24
|
+
INT left = getVirtualScreenX();
|
|
25
|
+
INT top = getVirtualScreenY();
|
|
26
|
+
return ruby___rectangle_new(
|
|
27
|
+
left,
|
|
28
|
+
top,
|
|
29
|
+
getVirtualScreenWidth() + left,
|
|
30
|
+
getVirtualScreenHeight() + top
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* @overload color_at(x, y)
|
|
36
|
+
* Returns the color at the specific position on primary screen coordinate system.
|
|
37
|
+
* @param [Fixnum] x the x coordinate of the point for get color
|
|
38
|
+
* @param [Fixnum] y the y coordinate of the point for get color
|
|
39
|
+
* @return [SpecialInputDevice::Color] the color at the specified point at the screen
|
|
40
|
+
* @see SpecialInputDevice::Window#color_at
|
|
41
|
+
* @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd144909.aspx Windows Dev Center - GetPixel function
|
|
42
|
+
*/
|
|
43
|
+
static VALUE ruby__color_at(VALUE self, VALUE x, VALUE y) {
|
|
44
|
+
INT cX = NUM2INT(x);
|
|
45
|
+
INT cY = NUM2INT(y);
|
|
46
|
+
HDC cHDC = GetDC(NULL);
|
|
47
|
+
COLORREF cColor = GetPixel(cHDC, cX, cY);
|
|
48
|
+
ReleaseDC(NULL, cHDC);
|
|
49
|
+
return ruby___color_new_from_color_ref(cColor);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
typedef struct {
|
|
53
|
+
VALUE pipe;
|
|
54
|
+
DWORD cFileSize;
|
|
55
|
+
LPSTR cBitmapFile;
|
|
56
|
+
HANDLE cHBitmapFile;
|
|
57
|
+
} SID_SCREEN_CAPTURE_PARAMETER_THREAD;
|
|
58
|
+
|
|
59
|
+
static VALUE ruby__capture_helper_thread(SID_SCREEN_CAPTURE_PARAMETER_THREAD *cParameters) {
|
|
60
|
+
VALUE bitmapFile = rb_enc_str_new(cParameters->cBitmapFile, cParameters->cFileSize, rb_ascii8bit_encoding());
|
|
61
|
+
rb_funcall(cParameters->pipe, rb_intern_const("write"), 1, bitmapFile);
|
|
62
|
+
return Qnil;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
typedef struct {
|
|
66
|
+
INT cX;
|
|
67
|
+
INT cY;
|
|
68
|
+
INT cWidth;
|
|
69
|
+
INT cHeight;
|
|
70
|
+
HDC cCompatibleDC;
|
|
71
|
+
HDC cHDC;
|
|
72
|
+
LPSTR cBitmapFile;
|
|
73
|
+
HANDLE cHBitmapFile;
|
|
74
|
+
} SID_SCREEN_CAPTURE_PARAMETER_PROTECT;
|
|
75
|
+
|
|
76
|
+
static VALUE ruby__capture_helper_protect(VALUE arguments) {
|
|
77
|
+
VALUE bmpClass;
|
|
78
|
+
VALUE pipesEncoding = rb_str_new_cstr("ASCII-8BIT");
|
|
79
|
+
VALUE pipes;
|
|
80
|
+
VALUE pipeIn;
|
|
81
|
+
VALUE pipeOut;
|
|
82
|
+
|
|
83
|
+
SID_SCREEN_CAPTURE_PARAMETER_PROTECT *cParameterProtect;
|
|
84
|
+
SID_SCREEN_CAPTURE_PARAMETER_THREAD cParameterThread;
|
|
85
|
+
|
|
86
|
+
WORD cBitPerPixel;
|
|
87
|
+
DWORD cPaletteSize;
|
|
88
|
+
DWORD cDataSize;
|
|
89
|
+
DWORD cFileSize;
|
|
90
|
+
BITMAP cBitmap;
|
|
91
|
+
HBITMAP cHBitmap;
|
|
92
|
+
BITMAPFILEHEADER cFileHeader;
|
|
93
|
+
BITMAPINFOHEADER cInfoHeader;
|
|
94
|
+
LPBITMAPFILEHEADER cPFileHeader;
|
|
95
|
+
LPBITMAPINFOHEADER cPInfoHeader;
|
|
96
|
+
LPSTR cPPalette;
|
|
97
|
+
LPSTR cPData;
|
|
98
|
+
HPALETTE cPalette = GetStockObject(DEFAULT_PALETTE);
|
|
99
|
+
HPALETTE cOldPalette = NULL;
|
|
100
|
+
|
|
101
|
+
Data_Get_Struct(arguments, SID_SCREEN_CAPTURE_PARAMETER_PROTECT, cParameterProtect);
|
|
102
|
+
|
|
103
|
+
cParameterProtect->cCompatibleDC = CreateCompatibleDC(NULL);
|
|
104
|
+
cParameterProtect->cHDC = GetDC(NULL);
|
|
105
|
+
cHBitmap = CreateCompatibleBitmap(cParameterProtect->cHDC, cParameterProtect->cWidth, cParameterProtect->cHeight);
|
|
106
|
+
|
|
107
|
+
SelectObject(cParameterProtect->cCompatibleDC, cHBitmap);
|
|
108
|
+
BitBlt(cParameterProtect->cCompatibleDC, 0, 0, cParameterProtect->cWidth, cParameterProtect->cHeight,
|
|
109
|
+
cParameterProtect->cHDC, cParameterProtect->cX, cParameterProtect->cY, SRCCOPY);
|
|
110
|
+
GetObject(cHBitmap, sizeof(BITMAP), (LPSTR) &cBitmap);
|
|
111
|
+
|
|
112
|
+
cBitPerPixel = (WORD) (GetDeviceCaps(cParameterProtect->cHDC, BITSPIXEL) *
|
|
113
|
+
GetDeviceCaps(cParameterProtect->cHDC, PLANES));
|
|
114
|
+
if (cBitPerPixel <= 1)
|
|
115
|
+
cBitPerPixel = 1;
|
|
116
|
+
else if (cBitPerPixel <= 4)
|
|
117
|
+
cBitPerPixel = 4;
|
|
118
|
+
else if (cBitPerPixel <= 8)
|
|
119
|
+
cBitPerPixel = 8;
|
|
120
|
+
else if (cBitPerPixel <= 24)
|
|
121
|
+
cBitPerPixel = 24;
|
|
122
|
+
else
|
|
123
|
+
cBitPerPixel = 32;
|
|
124
|
+
|
|
125
|
+
cPaletteSize = cBitPerPixel <= 8 ? (1 << cBitPerPixel) * sizeof(RGBQUAD) : 0;
|
|
126
|
+
cDataSize = (DWORD) (((cBitmap.bmWidth * cBitPerPixel + 31) / 32) * 4 * cBitmap.bmHeight);
|
|
127
|
+
cFileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + cPaletteSize + cDataSize;
|
|
128
|
+
|
|
129
|
+
cFileHeader.bfType = 0x4D42;
|
|
130
|
+
cFileHeader.bfSize = cFileSize;
|
|
131
|
+
cFileHeader.bfReserved1 = 0;
|
|
132
|
+
cFileHeader.bfReserved2 = 0;
|
|
133
|
+
cFileHeader.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + (DWORD) sizeof(BITMAPINFOHEADER) + cPaletteSize;
|
|
134
|
+
|
|
135
|
+
cInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
136
|
+
cInfoHeader.biWidth = cBitmap.bmWidth;
|
|
137
|
+
cInfoHeader.biHeight = cBitmap.bmHeight;
|
|
138
|
+
cInfoHeader.biPlanes = 1;
|
|
139
|
+
cInfoHeader.biBitCount = cBitPerPixel;
|
|
140
|
+
cInfoHeader.biCompression = BI_RGB;
|
|
141
|
+
cInfoHeader.biSizeImage = 0;
|
|
142
|
+
cInfoHeader.biXPelsPerMeter = 0;
|
|
143
|
+
cInfoHeader.biYPelsPerMeter = 0;
|
|
144
|
+
cInfoHeader.biClrUsed = 0;
|
|
145
|
+
cInfoHeader.biClrImportant = 0;
|
|
146
|
+
|
|
147
|
+
cParameterProtect->cHBitmapFile = GlobalAlloc(GHND, cFileSize);
|
|
148
|
+
if (!cParameterProtect->cHBitmapFile)
|
|
149
|
+
RAISE_WIN32_ERROR;
|
|
150
|
+
cParameterProtect->cBitmapFile = (LPSTR) GlobalLock(cParameterProtect->cHBitmapFile);
|
|
151
|
+
if (!cParameterProtect->cBitmapFile)
|
|
152
|
+
RAISE_WIN32_ERROR;
|
|
153
|
+
|
|
154
|
+
cPFileHeader = (LPBITMAPFILEHEADER) cParameterProtect->cBitmapFile;
|
|
155
|
+
cPInfoHeader = (LPBITMAPINFOHEADER) (cPFileHeader + 1);
|
|
156
|
+
cPPalette = (LPSTR) (cPInfoHeader + 1);
|
|
157
|
+
cPData = cPPalette + cPaletteSize;
|
|
158
|
+
|
|
159
|
+
*cPFileHeader = cFileHeader;
|
|
160
|
+
*cPInfoHeader = cInfoHeader;
|
|
161
|
+
if (cPalette) {
|
|
162
|
+
cOldPalette = SelectPalette(cParameterProtect->cHDC, cPalette, FALSE);
|
|
163
|
+
RealizePalette(cParameterProtect->cHDC);
|
|
164
|
+
}
|
|
165
|
+
GetDIBits(cParameterProtect->cHDC, cHBitmap, 0, (UINT) cBitmap.bmHeight, cPData, (LPBITMAPINFO) cPInfoHeader,
|
|
166
|
+
DIB_RGB_COLORS);
|
|
167
|
+
if (cOldPalette) {
|
|
168
|
+
SelectPalette(cParameterProtect->cHDC, cOldPalette, TRUE);
|
|
169
|
+
RealizePalette(cParameterProtect->cHDC);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
pipes = rb_funcall(rb_cIO, rb_intern_const("pipe"), 2, pipesEncoding, pipesEncoding);
|
|
173
|
+
pipeIn = rb_ary_entry(pipes, 1);
|
|
174
|
+
pipeOut = rb_ary_entry(pipes, 0);
|
|
175
|
+
|
|
176
|
+
cParameterThread.pipe = pipeIn;
|
|
177
|
+
cParameterThread.cFileSize = cFileSize;
|
|
178
|
+
cParameterThread.cBitmapFile = cParameterProtect->cBitmapFile;
|
|
179
|
+
cParameterThread.cHBitmapFile = cParameterProtect->cHBitmapFile;
|
|
180
|
+
rb_thread_create(ruby__capture_helper_thread, &cParameterThread);
|
|
181
|
+
|
|
182
|
+
bmpClass = RUBY_MODULE_CONST_GET(specialInputDevice_image, rb_intern_const("BMP"));
|
|
183
|
+
return rb_funcall(bmpClass, rb_intern_const("load"), 1, pipeOut);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* @overload capture()
|
|
188
|
+
* Capture the whole screen.
|
|
189
|
+
* @overload capture(x, y, width, height)
|
|
190
|
+
* Capture a rectangle part of screen.
|
|
191
|
+
* @param [Integer] x the x-coordinate of the left edge
|
|
192
|
+
* @param [Integer] y the y-coordinate of the top edge
|
|
193
|
+
* @param [Integer] width the width of rectangle
|
|
194
|
+
* @param [Integer] height the height of rectangle
|
|
195
|
+
* @return [SpecialInputDevice::Image]
|
|
196
|
+
*/
|
|
197
|
+
static VALUE ruby__capture(VARIABLE_ARGUMENTS_C) {
|
|
198
|
+
VALUE x;
|
|
199
|
+
VALUE y;
|
|
200
|
+
VALUE width;
|
|
201
|
+
VALUE height;
|
|
202
|
+
VALUE parameter;
|
|
203
|
+
SID_SCREEN_CAPTURE_PARAMETER_PROTECT *cParameter;
|
|
204
|
+
INT cError;
|
|
205
|
+
VALUE result;
|
|
206
|
+
parameter = Data_Make_Struct(rb_cData, SID_SCREEN_CAPTURE_PARAMETER_PROTECT, NULL, RUBY_DEFAULT_FREE,
|
|
207
|
+
cParameter);
|
|
208
|
+
switch (cCount) {
|
|
209
|
+
case 0: {
|
|
210
|
+
cParameter->cX = getVirtualScreenX();
|
|
211
|
+
cParameter->cY = getVirtualScreenY();
|
|
212
|
+
cParameter->cWidth = getVirtualScreenWidth();
|
|
213
|
+
cParameter->cHeight = getVirtualScreenHeight();
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case 4: {
|
|
217
|
+
SCAN_ARGUMENTS("4", &x, &y, &width, &height);
|
|
218
|
+
cParameter->cX = NUM2INT(x);
|
|
219
|
+
cParameter->cY = NUM2INT(y);
|
|
220
|
+
cParameter->cWidth = NUM2INT(width);
|
|
221
|
+
cParameter->cHeight = NUM2INT(height);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
default:
|
|
225
|
+
RAISE_ARGUMENT_ERROR("0, 4");
|
|
226
|
+
}
|
|
227
|
+
result = rb_protect(ruby__capture_helper_protect, parameter, &cError);
|
|
228
|
+
GlobalUnlock(cParameter->cHBitmapFile);
|
|
229
|
+
GlobalFree(cParameter->cHBitmapFile);
|
|
230
|
+
ReleaseDC(NULL, cParameter->cCompatibleDC);
|
|
231
|
+
ReleaseDC(NULL, cParameter->cHDC);
|
|
232
|
+
if (cError)
|
|
233
|
+
rb_jump_tag(cError);
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/*
|
|
238
|
+
* @overload find_image(image, area: SpecialInputDevice::Screen.primary_screen, similarity: 1.0, _return: RETURN_METHOD::FIRST)
|
|
239
|
+
* @param [SpecialInputDevice::Image, String] image a picture to be search
|
|
240
|
+
* @param [SpecialInputDevice::Rectangle] area the searching area
|
|
241
|
+
* @param [Float] similarity minimum limit of similarity
|
|
242
|
+
* @param [Symbol] _return indicate the behavior of this method, see SpecialInputDevice::Image::RETURN_METHOD
|
|
243
|
+
* @return [NilClass, SpecialInputDevice::Rectangle] a rectangle contain the position and the size of the result
|
|
244
|
+
* @see SpecialInputDevice::Image#find
|
|
245
|
+
* @see SpecialInputDevice::Image::RETURN_METHOD
|
|
246
|
+
*/
|
|
247
|
+
static VALUE ruby__find_image(VARIABLE_ARGUMENTS_C) {
|
|
248
|
+
VALUE image;
|
|
249
|
+
VALUE options;
|
|
250
|
+
ID keywords[1] = {
|
|
251
|
+
rb_intern_const("area")
|
|
252
|
+
};
|
|
253
|
+
VALUE option_values[sizeof(keywords)];
|
|
254
|
+
VALUE *area = option_values + 0;
|
|
255
|
+
VALUE x = Qnil;
|
|
256
|
+
VALUE y = Qnil;
|
|
257
|
+
VALUE capture;
|
|
258
|
+
VALUE captureArguments[4];
|
|
259
|
+
VALUE result;
|
|
260
|
+
SCAN_ARGUMENTS("1:", &image, &options);
|
|
261
|
+
rb_get_kwargs(options, keywords, 0, -2, option_values);
|
|
262
|
+
if (RTEST(RUBY_OBJECT_IS_A_qs(image, rb_cString)) || RTEST(RUBY_OBJECT_IS_A_qs(image, rb_cFile)))
|
|
263
|
+
image = rb_funcall(specialInputDevice_image, rb_intern_const("load"), 1, image);
|
|
264
|
+
else if (!RTEST(RUBY_OBJECT_IS_A_qs(image, specialInputDevice_image)))
|
|
265
|
+
RAISE_TYPE_ERROR(image, "String, File or SpecialInputDevice::Image");
|
|
266
|
+
if (*area == Qundef) {
|
|
267
|
+
capture = ruby__capture(0, captureArguments, self);
|
|
268
|
+
} else {
|
|
269
|
+
CHECK_TYPE_ERROR(*area, specialInputDevice_rectangle);
|
|
270
|
+
x = rb_funcall(*area, rb_intern_const("x"), 0);
|
|
271
|
+
y = rb_funcall(*area, rb_intern_const("y"), 0);
|
|
272
|
+
captureArguments[0] = x;
|
|
273
|
+
captureArguments[1] = y;
|
|
274
|
+
captureArguments[2] = rb_funcall(*area, rb_intern_const("width"), 0);
|
|
275
|
+
captureArguments[3] = rb_funcall(*area, rb_intern_const("height"), 0);
|
|
276
|
+
capture = ruby__capture(4, captureArguments, self);
|
|
277
|
+
}
|
|
278
|
+
// return capture;
|
|
279
|
+
rb_funcall(capture, rb_intern_const("save"), 1, rb_str_new_cstr("D:/2.bmp"));
|
|
280
|
+
result = rb_funcall(capture, rb_intern_const("find"), 2, image, options);
|
|
281
|
+
if (result != Qnil && *area != Qundef)
|
|
282
|
+
result = rb_funcall(result, rb_intern_const("move"), 2, x, y);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
VOID Init_screen() {
|
|
287
|
+
#ifdef YARD
|
|
288
|
+
specialInputDevice = rb_define_module("SpecialInputDevice");
|
|
289
|
+
#endif
|
|
290
|
+
/*
|
|
291
|
+
* Document-module: SpecialInputDevice::Screen
|
|
292
|
+
*
|
|
293
|
+
* The <code>Screen</code> module provides an interface to receive the information for the screen and to simulate
|
|
294
|
+
* the signal form the touch screen.
|
|
295
|
+
*/
|
|
296
|
+
VALUE specialInputDevice_screen = rb_define_module_under(specialInputDevice, "Screen");
|
|
297
|
+
rb_define_singleton_method(specialInputDevice_screen, "primary_screen", ruby__primary_screen, 0);
|
|
298
|
+
rb_define_singleton_method(specialInputDevice_screen, "virtual_screen", ruby__virtual_screen, 0);
|
|
299
|
+
rb_define_singleton_method(specialInputDevice_screen, "color_at", ruby__color_at, 2);
|
|
300
|
+
rb_define_singleton_method(specialInputDevice_screen, "capture", ruby__capture, -1);
|
|
301
|
+
rb_define_singleton_method(specialInputDevice_screen, "find_image", ruby__find_image, -1);
|
|
302
|
+
}
|