special_input_device 0.0.1 → 0.1.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.
@@ -1,6 +1,7 @@
1
1
  #include "special_input_device.h"
2
2
  #include "_system_time.h"
3
3
  #include "color.h"
4
+ #include "image.h"
4
5
  #include "rectangle.h"
5
6
 
6
7
  #define MAXIMUM_WINDOW_NAME_LENGTH 256
@@ -136,13 +137,13 @@ static VALUE ruby__find(VARIABLE_ARGUMENTS_C) {
136
137
  SCAN_ARGUMENTS("02", &windowName, &className);
137
138
  if (windowName != Qnil && !RTEST(RUBY_OBJECT_IS_A_qs(windowName, rb_cRegexp)) &&
138
139
  !RTEST(RUBY_OBJECT_IS_A_qs(windowName, rb_cString)))
139
- RAISE_TYPE_ERROR(windowName, "nil, Regexp or String");
140
+ RAISE_SIMPLE_TYPE_ERROR(windowName, "nil, Regexp or String");
140
141
  if (className != Qnil && !RTEST(RUBY_OBJECT_IS_A_qs(className, rb_cRegexp)) &&
141
142
  !RTEST(RUBY_OBJECT_IS_A_qs(className, rb_cString)))
142
- RAISE_TYPE_ERROR(className, "nil, Regexp or String");
143
- cCallbackArguments.className = className;
144
- cCallbackArguments.windowName = windowName;
145
- cCallbackArguments.hWND = 0;
143
+ RAISE_SIMPLE_TYPE_ERROR(className, "nil, Regexp or String");
144
+ cCallbackArguments.className = className;
145
+ cCallbackArguments.windowName = windowName;
146
+ cCallbackArguments.hWND = 0;
146
147
  EnumWindows(callback_find, (LPARAM) &cCallbackArguments);
147
148
  cHWND = cCallbackArguments.hWND;
148
149
  if (GetLastError())
@@ -163,7 +164,7 @@ static VALUE ruby__alloc(VALUE self) {
163
164
  }
164
165
 
165
166
  static VALUE ruby_window_name_EQ(VALUE self, VALUE value) {
166
- HWND cHWND = ruby___window_get_handle_code(self);
167
+ HWND cHWND = ruby___window_get_handle_code(self);
167
168
  LPCTSTR cWindowName = RUBY_VALUE_TO_LPCTSTR(value);
168
169
  SetWindowText(cHWND, cWindowName);
169
170
  return rb_iv_set(self, "@window_name", value);
@@ -177,7 +178,7 @@ static VALUE ruby_window_name_EQ(VALUE self, VALUE value) {
177
178
  * @param [Integer] handle_code the handle code of the window. Handle code is an Integer for identifying windows.
178
179
  */
179
180
  static VALUE ruby_initialize(VALUE self, VALUE handleCode) {
180
- HWND cHWND = (HWND) NUM2ULL(handleCode);
181
+ HWND cHWND = (HWND) NUM2ULL(handleCode);
181
182
  TCHAR cClassName[MAXIMUM_WINDOW_NAME_LENGTH * sizeof(TCHAR)];
182
183
  INT cWindowNameLength = GetWindowTextLength(cHWND) + 1;
183
184
  LPTSTR cWindowName = (LPTSTR) VirtualAlloc((LPVOID) NULL, (SIZE_T) (cWindowNameLength) * sizeof(TCHAR),
@@ -204,7 +205,7 @@ static VALUE ruby_initialize(VALUE self, VALUE handleCode) {
204
205
  return Qnil;
205
206
  }
206
207
 
207
- //<editor-fold desc="relationship">
208
+ //region relationship
208
209
 
209
210
  /*
210
211
  * @overload find_child(window_name = nil, class_name = nil, after = nil)
@@ -228,7 +229,7 @@ static VALUE ruby_find_child(VARIABLE_ARGUMENTS_C) {
228
229
  cWindowName = windowName == Qnil ? NULL : RUBY_VALUE_TO_LPCTSTR(windowName);
229
230
  cClassName = className == Qnil ? NULL : RUBY_VALUE_TO_LPCTSTR(className);
230
231
  cAfter = after == Qnil ? NULL : ruby___window_get_handle_code(after);
231
- cHWND = FindWindowEx(ruby___window_get_handle_code(self), cAfter, cClassName, cWindowName);
232
+ cHWND = FindWindowEx(ruby___window_get_handle_code(self), cAfter, cClassName, cWindowName);
232
233
  if (!cHWND)
233
234
  RAISE_WIN32_ERROR();
234
235
  return ruby___window_new(cHWND);
@@ -262,9 +263,9 @@ static VALUE ruby_root(VARIABLE_ARGUMENTS_C) {
262
263
  return ruby___window_new(GetAncestor(cHWND, includeOwner && includeOwner != Qnil ? GA_ROOT : GA_ROOTOWNER));
263
264
  }
264
265
 
265
- //</editor-fold>
266
+ //endregion relationship
266
267
 
267
- //<editor-fold desc="size">
268
+ //region size
268
269
 
269
270
  /*
270
271
  * Returns the rectangle of the window's client area. The coordinates of rectangle are relative to the client area
@@ -298,9 +299,9 @@ static VALUE ruby_window_rectangle(VALUE self) {
298
299
  return ruby___rectangle_new_from_rect(&cWindowRectangle);
299
300
  }
300
301
 
301
- //</editor-fold>
302
+ //endregion size
302
303
 
303
- //<editor-fold desc="control">
304
+ //region control
304
305
 
305
306
  /*
306
307
  * Brings the window to the foreground.
@@ -402,9 +403,9 @@ static VALUE ruby_restore(VALUE self) {
402
403
  return self;
403
404
  }
404
405
 
405
- //</editor-fold>
406
+ //endregion control
406
407
 
407
- //<editor-fold desc="display">
408
+ //region display
408
409
 
409
410
  /*
410
411
  * @overload color_at(x, y)
@@ -415,18 +416,162 @@ static VALUE ruby_restore(VALUE self) {
415
416
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd144909.aspx Windows Dev Center - GetPixel function
416
417
  */
417
418
  static VALUE ruby_color_at(VALUE self, VALUE x, VALUE y) {
418
- INT cX = NUM2INT(x);
419
- INT cY = NUM2INT(y);
420
- HDC cWindowDC = GetDC(ruby___window_get_handle_code(self));
421
- COLORREF cColor = GetPixel(cWindowDC, cX, cY);
419
+ HWND cWindow = ruby___window_get_handle_code(self);
420
+ COLORREF cColor;
421
+ HDC cWindowDC;
422
+ POINT cPoint;
423
+ RECT cWindowRectangle;
424
+ cPoint.x = NUM2LONG(x);
425
+ cPoint.y = NUM2LONG(y);
426
+ if (!ClientToScreen(cWindow, &cPoint))
427
+ RAISE_WIN32_ERROR();
428
+ if (!GetWindowRect(cWindow, &cWindowRectangle))
429
+ RAISE_WIN32_ERROR();
430
+ cWindowDC = GetWindowDC(cWindow);
431
+ cColor = GetPixel(cWindowDC, cPoint.x - cWindowRectangle.left, cPoint.y - cWindowRectangle.top);
432
+ ReleaseDC(cWindow, cWindowDC);
422
433
  return ruby___color_new_from_color_ref(cColor);
423
434
  }
424
435
 
425
- //</editor-fold>
436
+ typedef struct {
437
+ INT x;
438
+ INT y;
439
+ INT width;
440
+ INT height;
441
+ HWND window;
442
+ HDC memoryDC;
443
+ HDC windowDC;
444
+ LPSTR bitmapFile;
445
+ HANDLE hBitmapFile;
446
+ } SID_WINDOW_CAPTURE_PARAMETER;
447
+
448
+ static VALUE ruby_capture_helper(VALUE arguments) {
449
+ SID_WINDOW_CAPTURE_PARAMETER *cParameter = GET_DATA_OBJECT(arguments);
450
+ HBITMAP cHBitmap;
451
+
452
+ cParameter->windowDC = GetWindowDC(cParameter->window);
453
+ cParameter->memoryDC = CreateCompatibleDC(cParameter->windowDC);
454
+ cHBitmap = CreateCompatibleBitmap(cParameter->windowDC, cParameter->width, cParameter->height);
455
+
456
+ SelectObject(cParameter->memoryDC, cHBitmap);
457
+ BitBlt(cParameter->memoryDC, 0, 0, cParameter->width, cParameter->height,
458
+ cParameter->windowDC, cParameter->x, cParameter->y, SRCCOPY);
459
+
460
+ return ruby___image_new_from_bitmap(cHBitmap);
461
+ }
426
462
 
427
- //<editor-fold desc="input">
463
+ /*
464
+ * @overload capture()
465
+ * Capture the whole screen.
466
+ * @overload capture(x, y, width, height)
467
+ * Capture a rectangle part of screen.
468
+ * @param [Integer] x the x-coordinate of the left edge
469
+ * @param [Integer] y the y-coordinate of the top edge
470
+ * @param [Integer] width the width of rectangle
471
+ * @param [Integer] height the height of rectangle
472
+ * @return [SpecialInputDevice::Image]
473
+ */
474
+ static VALUE ruby_capture(VARIABLE_ARGUMENTS_C) {
475
+ VALUE x;
476
+ VALUE y;
477
+ VALUE width;
478
+ VALUE height;
479
+ VALUE parameter;
480
+ SID_WINDOW_CAPTURE_PARAMETER *cParameter;
481
+ INT cError;
482
+ VALUE result;
483
+ parameter = Data_Make_Struct(rb_cData, SID_WINDOW_CAPTURE_PARAMETER, NULL, RUBY_DEFAULT_FREE, cParameter);
484
+ switch (cCount) {
485
+ case 0: {
486
+ HWND cWindow = ruby___window_get_handle_code(self);
487
+ RECT cClientRectangle;
488
+ RECT cWindowRectangle;
489
+ if (!GetClientRect(cWindow, &cClientRectangle))
490
+ RAISE_WIN32_ERROR();
491
+ if (!ClientToScreen(cWindow, (LPPOINT) &cClientRectangle))
492
+ RAISE_WIN32_ERROR();
493
+ if (!GetWindowRect(cWindow, &cWindowRectangle))
494
+ RAISE_WIN32_ERROR();
495
+ cParameter->x = cClientRectangle.left - cWindowRectangle.left;
496
+ cParameter->y = cClientRectangle.top - cWindowRectangle.top;
497
+ cParameter->width = cClientRectangle.right;
498
+ cParameter->height = cClientRectangle.bottom;
499
+ break;
500
+ }
501
+ case 4:
502
+ SCAN_ARGUMENTS("4", &x, &y, &width, &height);
503
+ cParameter->x = NUM2INT(x);
504
+ cParameter->y = NUM2INT(y);
505
+ cParameter->width = NUM2INT(width);
506
+ cParameter->height = NUM2INT(height);
507
+ break;
508
+ default:
509
+ RAISE_ARGUMENT_ERROR("0, 4");
510
+ }
511
+ cParameter->window = ruby___window_get_handle_code(self);
512
+ result = rb_protect(ruby_capture_helper, parameter, &cError);
513
+ GlobalUnlock(cParameter->hBitmapFile);
514
+ GlobalFree(cParameter->hBitmapFile);
515
+ ReleaseDC(NULL, cParameter->memoryDC);
516
+ ReleaseDC(NULL, cParameter->windowDC);
517
+ if (cError)
518
+ rb_jump_tag(cError);
519
+ return result;
520
+ }
428
521
 
429
- //<editor-fold desc="keyboard">
522
+ /*
523
+ * @overload find_image(image, area: SpecialInputDevice::Screen.primary_screen, similarity: 1.0, _return: RETURN_METHOD::FIRST)
524
+ * @param [SpecialInputDevice::Image, String] image a picture to be search
525
+ * @param [SpecialInputDevice::Rectangle] area the searching area
526
+ * @param [Float] similarity minimum limit of similarity
527
+ * @param [Symbol] _return indicate the behavior of this method, see SpecialInputDevice::Image::RETURN_METHOD
528
+ * @return [NilClass, SpecialInputDevice::Rectangle] a rectangle contain the position and the size of the result
529
+ * @see SpecialInputDevice::Image#find
530
+ * @see SpecialInputDevice::Image::RETURN_METHOD
531
+ */
532
+ static VALUE ruby_find_image(VARIABLE_ARGUMENTS_C) {
533
+ VALUE image;
534
+ VALUE options;
535
+ ID keywords[1] = {
536
+ rb_intern_const("area")
537
+ };
538
+ VALUE option_values[sizeof(keywords)];
539
+ VALUE *area = option_values + 0;
540
+ VALUE x = Qnil;
541
+ VALUE y = Qnil;
542
+ VALUE capture;
543
+ VALUE captureArguments[4];
544
+ VALUE result;
545
+ SCAN_ARGUMENTS("1:", &image, &options);
546
+ rb_get_kwargs(options, keywords, 0, -2, option_values);
547
+ if (RTEST(RUBY_OBJECT_IS_A_qs(image, rb_cString)) || RTEST(RUBY_OBJECT_IS_A_qs(image, rb_cFile)))
548
+ image = rb_funcall(specialInputDevice_image, rb_intern_const("load"), 1, image);
549
+ else if (!RTEST(RUBY_OBJECT_IS_A_qs(image, specialInputDevice_image)))
550
+ RAISE_SIMPLE_TYPE_ERROR(image, "String, File or SpecialInputDevice::Image");
551
+ if (*area == Qundef) {
552
+ capture = ruby_capture(0, captureArguments, self);
553
+ } else {
554
+ CHECK_TYPE_ERROR(*area, ":area", specialInputDevice_rectangle);
555
+ x = rb_funcall(*area, rb_intern_const("x"), 0);
556
+ y = rb_funcall(*area, rb_intern_const("y"), 0);
557
+ captureArguments[0] = x;
558
+ captureArguments[1] = y;
559
+ captureArguments[2] = rb_funcall(*area, rb_intern_const("width"), 0);
560
+ captureArguments[3] = rb_funcall(*area, rb_intern_const("height"), 0);
561
+ capture = ruby_capture(4, captureArguments, self);
562
+ }
563
+ rb_funcall(capture, rb_intern_const("save"), 1, rb_str_new_cstr("D:/2.bmp"));
564
+ result = rb_funcall(capture, rb_intern_const("find"), options == Qnil ? 1 : 2, image, options);
565
+ if (result != Qnil && *area != Qundef)
566
+ result = rb_funcall(result, rb_intern_const("move"), 2, x, y);
567
+ return result;
568
+ }
569
+
570
+ //endregion display
571
+
572
+ //region input
573
+
574
+ //region keyboard
430
575
 
431
576
  /*
432
577
  * @overload key_hold(key_code)
@@ -438,7 +583,7 @@ static VALUE ruby_color_at(VALUE self, VALUE x, VALUE y) {
438
583
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646280.aspx Windows Dev Center - WM_KEYDOWN message
439
584
  */
440
585
  static VALUE ruby_key_hold(VALUE self, VALUE keyCode) {
441
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
586
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
442
587
  HWND cHWnd = ruby___window_get_handle_code(self);
443
588
  WPARAM cWParam = NUM2USHORT(keyCode);
444
589
  LPARAM cLParam = 1 | (WORD) MapVirtualKeyA(cWParam, MAPVK_VK_TO_VSC) << 16;
@@ -487,7 +632,7 @@ static VALUE ruby_key_hold(VALUE self, VALUE keyCode) {
487
632
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646281.aspx Windows Dev Center - WM_KEYUP message
488
633
  */
489
634
  static VALUE ruby_key_release(VALUE self, VALUE keyCode) {
490
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
635
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
491
636
  HWND cHWnd = ruby___window_get_handle_code(self);
492
637
  WPARAM cWParam = NUM2USHORT(keyCode);
493
638
  LPARAM cLParam = 1;
@@ -539,7 +684,7 @@ static VALUE ruby_key_release(VALUE self, VALUE keyCode) {
539
684
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646281.aspx Windows Dev Center - WM_KEYUP message
540
685
  */
541
686
  static VALUE ruby_key_press(VALUE self, VALUE keyCode) {
542
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
687
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
543
688
  HWND cHWnd = ruby___window_get_handle_code(self);
544
689
  WPARAM cWParam = NUM2USHORT(keyCode);
545
690
  LPARAM cLParam = 1 | (WORD) MapVirtualKeyA(cWParam, MAPVK_VK_TO_VSC) << 16;
@@ -580,11 +725,11 @@ static VALUE ruby_key_press(VALUE self, VALUE keyCode) {
580
725
  return self;
581
726
  }
582
727
 
583
- //</editor-fold>
728
+ //endregion keyboard
584
729
 
585
- //<editor-fold desc="mouse">
730
+ //region mouse
586
731
 
587
- //<editor-fold desc="move">
732
+ //region move
588
733
 
589
734
  /*
590
735
  * @overload mouse_move_relatively(x, y)
@@ -597,7 +742,7 @@ static VALUE ruby_key_press(VALUE self, VALUE keyCode) {
597
742
  */
598
743
  static VALUE ruby_mouse_move_relatively(VALUE self, VALUE x, VALUE y) {
599
744
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
600
- HWND cHWnd = ruby___window_get_handle_code(self);
745
+ HWND cHWnd = ruby___window_get_handle_code(self);
601
746
  cData->x += NUM2SHORT(x);
602
747
  cData->y += NUM2SHORT(y);
603
748
  PostMessage(cHWnd, WM_MOUSEMOVE, createMouseMessageWParam(cData), createMouseMessageLParam(cData));
@@ -616,16 +761,16 @@ static VALUE ruby_mouse_move_relatively(VALUE self, VALUE x, VALUE y) {
616
761
  */
617
762
  static VALUE ruby_mouse_move_to(VALUE self, VALUE x, VALUE y) {
618
763
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
619
- HWND cHWnd = ruby___window_get_handle_code(self);
764
+ HWND cHWnd = ruby___window_get_handle_code(self);
620
765
  cData->x = NUM2SHORT(x);
621
766
  cData->y = NUM2SHORT(y);
622
767
  PostMessage(cHWnd, WM_MOUSEMOVE, createMouseMessageWParam(cData), createMouseMessageLParam(cData));
623
768
  return self;
624
769
  }
625
770
 
626
- //</editor-fold>
771
+ //endregion move
627
772
 
628
- //<editor-fold desc="left_button">
773
+ //region left_button
629
774
 
630
775
  /*
631
776
  * Simulate clicking the left button on the mouse in the window.
@@ -637,7 +782,7 @@ static VALUE ruby_mouse_move_to(VALUE self, VALUE x, VALUE y) {
637
782
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms645608.aspx Windows Dev Center - WM_LBUTTONUP message
638
783
  */
639
784
  static VALUE ruby_mouse_left_click(VALUE self) {
640
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
785
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
641
786
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
642
787
  HWND cHWnd = ruby___window_get_handle_code(self);
643
788
  cData->flats |= FLAT_MOUSE_LEFT;
@@ -659,7 +804,7 @@ static VALUE ruby_mouse_left_click(VALUE self) {
659
804
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms645607.aspx Windows Dev Center - WM_LBUTTONDOWN message
660
805
  */
661
806
  static VALUE ruby_mouse_left_down(VALUE self) {
662
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
807
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
663
808
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
664
809
  HWND cHWnd = ruby___window_get_handle_code(self);
665
810
  cData->flats |= FLAT_MOUSE_LEFT;
@@ -679,15 +824,15 @@ static VALUE ruby_mouse_left_down(VALUE self) {
679
824
  */
680
825
  static VALUE ruby_mouse_left_up(VALUE self) {
681
826
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
682
- HWND cHWnd = ruby___window_get_handle_code(self);
827
+ HWND cHWnd = ruby___window_get_handle_code(self);
683
828
  cData->flats &= ~FLAT_MOUSE_LEFT;
684
829
  PostMessage(cHWnd, WM_LBUTTONUP, createMouseMessageWParam(cData), createMouseMessageLParam(cData));
685
830
  return self;
686
831
  }
687
832
 
688
- //</editor-fold>
833
+ //endregion left_button
689
834
 
690
- //<editor-fold desc="right_button">
835
+ //region right_button
691
836
 
692
837
  /*
693
838
  * Simulate clicking the right button on the mouse in the window.
@@ -699,7 +844,7 @@ static VALUE ruby_mouse_left_up(VALUE self) {
699
844
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646243.aspx Windows Dev Center - WM_RBUTTONUP function
700
845
  */
701
846
  static VALUE ruby_mouse_right_click(VALUE self) {
702
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
847
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
703
848
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
704
849
  HWND cHWnd = ruby___window_get_handle_code(self);
705
850
  cData->flats |= FLAT_MOUSE_RIGHT;
@@ -721,7 +866,7 @@ static VALUE ruby_mouse_right_click(VALUE self) {
721
866
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646242.aspx Windows Dev Center - WM_RBUTTONDOWN function
722
867
  */
723
868
  static VALUE ruby_mouse_right_down(VALUE self) {
724
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
869
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
725
870
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
726
871
  HWND cHWnd = ruby___window_get_handle_code(self);
727
872
  cData->flats |= FLAT_MOUSE_RIGHT;
@@ -741,15 +886,15 @@ static VALUE ruby_mouse_right_down(VALUE self) {
741
886
  */
742
887
  static VALUE ruby_mouse_right_up(VALUE self) {
743
888
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
744
- HWND cHWnd = ruby___window_get_handle_code(self);
889
+ HWND cHWnd = ruby___window_get_handle_code(self);
745
890
  cData->flats &= ~FLAT_MOUSE_RIGHT;
746
891
  PostMessage(cHWnd, WM_RBUTTONUP, createMouseMessageWParam(cData), createMouseMessageLParam(cData));
747
892
  return self;
748
893
  }
749
894
 
750
- //</editor-fold>
895
+ //endregion right_button
751
896
 
752
- //<editor-fold desc="middle_button">
897
+ //region middle_button
753
898
 
754
899
  /*
755
900
  * Simulate clicking the middle button on the mouse in the window.
@@ -761,7 +906,7 @@ static VALUE ruby_mouse_right_up(VALUE self) {
761
906
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms645611.aspx Windows Dev Center - WM_MBUTTONUP function
762
907
  */
763
908
  static VALUE ruby_mouse_middle_click(VALUE self) {
764
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
909
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
765
910
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
766
911
  HWND cHWnd = ruby___window_get_handle_code(self);
767
912
  cData->flats |= FLAT_MOUSE_MIDDLE;
@@ -783,7 +928,7 @@ static VALUE ruby_mouse_middle_click(VALUE self) {
783
928
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms645610.aspx Windows Dev Center - WM_MBUTTONDOWN function
784
929
  */
785
930
  static VALUE ruby_mouse_middle_down(VALUE self) {
786
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
931
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
787
932
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
788
933
  HWND cHWnd = ruby___window_get_handle_code(self);
789
934
  cData->flats |= FLAT_MOUSE_MIDDLE;
@@ -803,15 +948,15 @@ static VALUE ruby_mouse_middle_down(VALUE self) {
803
948
  */
804
949
  static VALUE ruby_mouse_middle_up(VALUE self) {
805
950
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
806
- HWND cHWnd = ruby___window_get_handle_code(self);
951
+ HWND cHWnd = ruby___window_get_handle_code(self);
807
952
  cData->flats &= ~FLAT_MOUSE_MIDDLE;
808
953
  PostMessage(cHWnd, WM_MBUTTONUP, createMouseMessageWParam(cData), createMouseMessageLParam(cData));
809
954
  return self;
810
955
  }
811
956
 
812
- //</editor-fold>
957
+ //endregion middle_button
813
958
 
814
- //<editor-fold desc="x_button">
959
+ //region x_button
815
960
 
816
961
  /*
817
962
  * Simulate clicking the x1 button on the mouse in the window.
@@ -823,7 +968,7 @@ static VALUE ruby_mouse_middle_up(VALUE self) {
823
968
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646246.aspx Windows Dev Center - WM_XBUTTONUP function
824
969
  */
825
970
  static VALUE ruby_mouse_x1_click(VALUE self) {
826
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
971
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
827
972
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
828
973
  HWND cHWnd = ruby___window_get_handle_code(self);
829
974
  cData->flats |= FLAT_MOUSE_X1;
@@ -847,7 +992,7 @@ static VALUE ruby_mouse_x1_click(VALUE self) {
847
992
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646245.aspx Windows Dev Center - WM_XBUTTONDOWN function
848
993
  */
849
994
  static VALUE ruby_mouse_x1_down(VALUE self) {
850
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
995
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
851
996
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
852
997
  HWND cHWnd = ruby___window_get_handle_code(self);
853
998
  cData->flats |= FLAT_MOUSE_X1;
@@ -869,7 +1014,7 @@ static VALUE ruby_mouse_x1_down(VALUE self) {
869
1014
  */
870
1015
  static VALUE ruby_mouse_x1_up(VALUE self) {
871
1016
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
872
- HWND cHWnd = ruby___window_get_handle_code(self);
1017
+ HWND cHWnd = ruby___window_get_handle_code(self);
873
1018
  cData->flats &= ~FLAT_MOUSE_X1;
874
1019
  PostMessage(cHWnd, WM_XBUTTONUP, createMouseMessageWParam(cData) | XBUTTON1 << 16, createMouseMessageLParam(cData));
875
1020
  return self;
@@ -885,7 +1030,7 @@ static VALUE ruby_mouse_x1_up(VALUE self) {
885
1030
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646246.aspx Windows Dev Center - WM_XBUTTONUP function
886
1031
  */
887
1032
  static VALUE ruby_mouse_x2_click(VALUE self) {
888
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
1033
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
889
1034
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
890
1035
  HWND cHWnd = ruby___window_get_handle_code(self);
891
1036
  cData->flats |= FLAT_MOUSE_X2;
@@ -909,7 +1054,7 @@ static VALUE ruby_mouse_x2_click(VALUE self) {
909
1054
  * @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms646245.aspx Windows Dev Center - WM_XBUTTONDOWN function
910
1055
  */
911
1056
  static VALUE ruby_mouse_x2_down(VALUE self) {
912
- SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
1057
+ SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
913
1058
  ULONGLONG cCurrentTime = getSystemTimeIdentifier();
914
1059
  HWND cHWnd = ruby___window_get_handle_code(self);
915
1060
  cData->flats |= FLAT_MOUSE_X2;
@@ -931,15 +1076,15 @@ static VALUE ruby_mouse_x2_down(VALUE self) {
931
1076
  */
932
1077
  static VALUE ruby_mouse_x2_up(VALUE self) {
933
1078
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
934
- HWND cHWnd = ruby___window_get_handle_code(self);
1079
+ HWND cHWnd = ruby___window_get_handle_code(self);
935
1080
  cData->flats &= ~FLAT_MOUSE_X2;
936
1081
  PostMessage(cHWnd, WM_XBUTTONUP, createMouseMessageWParam(cData) | XBUTTON2 << 16, createMouseMessageLParam(cData));
937
1082
  return self;
938
1083
  }
939
1084
 
940
- //</editor-fold>
1085
+ //endregion x_button
941
1086
 
942
- //<editor-fold desc="wheel">
1087
+ //region wheel
943
1088
 
944
1089
  /*
945
1090
  * Simulate wheeling the scroll backward in the window.
@@ -950,7 +1095,7 @@ static VALUE ruby_mouse_x2_up(VALUE self) {
950
1095
  */
951
1096
  static VALUE ruby_mouse_scroll_wheel_backward(VALUE self) {
952
1097
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
953
- HWND cHWnd = ruby___window_get_handle_code(self);
1098
+ HWND cHWnd = ruby___window_get_handle_code(self);
954
1099
  PostMessage(cHWnd, WM_MOUSEWHEEL, createMouseMessageWParam(cData) | -WHEEL_DELTA << 16,
955
1100
  createMouseMessageLParam(cData));
956
1101
  return self;
@@ -965,7 +1110,7 @@ static VALUE ruby_mouse_scroll_wheel_backward(VALUE self) {
965
1110
  */
966
1111
  static VALUE ruby_mouse_scroll_wheel_forward(VALUE self) {
967
1112
  SID_WINDOW_DATA *cData = GET_SELF_DATA_OBJECT();
968
- HWND cHWnd = ruby___window_get_handle_code(self);
1113
+ HWND cHWnd = ruby___window_get_handle_code(self);
969
1114
  PostMessage(cHWnd, WM_MOUSEWHEEL, createMouseMessageWParam(cData) | WHEEL_DELTA << 16,
970
1115
  createMouseMessageLParam(cData));
971
1116
  return self;
@@ -1007,11 +1152,11 @@ static VALUE ruby_mouse_scroll_wheel_to_right(VALUE self) {
1007
1152
  #endif
1008
1153
  }
1009
1154
 
1010
- //</editor-fold>
1155
+ //endregion wheel
1011
1156
 
1012
- //</editor-fold>
1157
+ //endregion mouse
1013
1158
 
1014
- //</editor-fold>
1159
+ //endregion input
1015
1160
 
1016
1161
  VOID Init_window() {
1017
1162
  #ifdef YARD
@@ -1058,6 +1203,8 @@ VOID Init_window() {
1058
1203
  rb_define_method(specialInputDevice_window, "resize_to", ruby_resize_to, 2);
1059
1204
  rb_define_method(specialInputDevice_window, "restore", ruby_restore, 0);
1060
1205
  rb_define_method(specialInputDevice_window, "color_at", ruby_color_at, 2);
1206
+ rb_define_method(specialInputDevice_window, "capture", ruby_capture, -1);
1207
+ rb_define_method(specialInputDevice_window, "find_image", ruby_find_image, -1);
1061
1208
  rb_define_method(specialInputDevice_window, "key_hold", ruby_key_hold, 1);
1062
1209
  rb_define_method(specialInputDevice_window, "key_release", ruby_key_release, 1);
1063
1210
  rb_define_method(specialInputDevice_window, "key_press", ruby_key_press, 1);
@@ -6,28 +6,28 @@ class SpecialInputDevice::Color
6
6
  include(SpecialInputDevice::AttributesEqualChecker)
7
7
 
8
8
  # @return [Fixnum] the level of alpha
9
- attr_reader :alpha
9
+ attr_reader(:alpha)
10
10
  # @param [Fixnum] value the level of alpha
11
11
  def alpha=(value)
12
12
  @alpha = [value.to_i, 0, 255].sort[1];
13
13
  end
14
14
 
15
15
  # @return [Fixnum] the level of blue
16
- attr_reader :blue
16
+ attr_reader(:blue)
17
17
  # @param [Fixnum] value the level of blue
18
18
  def blue=(value)
19
19
  @blue = [value.to_i, 0, 255].sort[1];
20
20
  end
21
21
 
22
22
  # @return [Fixnum] the level of green
23
- attr_reader :green
23
+ attr_reader(:green)
24
24
  # @param [Fixnum] value the level of green
25
25
  def green=(value)
26
26
  @green = [value.to_i, 0, 255].sort[1];
27
27
  end
28
28
 
29
29
  # @return [Fixnum] the level of red
30
- attr_reader :red
30
+ attr_reader(:red)
31
31
  # @param [Fixnum] value the level of red
32
32
  def red=(value)
33
33
  @red = [value.to_i, 0, 255].sort[1];
@@ -35,7 +35,7 @@ class SpecialInputDevice::Image < Data
35
35
  end
36
36
 
37
37
  # Find the position of another smaller image in this image.
38
- # @param [SpecialInputDevice::Image] image another image, should be smaller
38
+ # @param [SpecialInputDevice::Image, String] image another image, should be smaller
39
39
  # @param [Float] similarity minimum limit of similarity
40
40
  # @param [Symbol] _return indicate the behavior of this method, see SpecialInputDevice::Image::RETURN_METHOD
41
41
  # @return [SpecialInputDevice::Rectangle, NilClass] the position
@@ -43,6 +43,7 @@ class SpecialInputDevice::Image < Data
43
43
  def find(image, similarity: 1.0, _return: RETURN_METHOD::FIRST)
44
44
  methods = RETURN_METHOD.constants(false).map { |x| RETURN_METHOD.const_get(x) }
45
45
  raise("Undefined return method '#{_return.to_s}' passed, Defined methods are [#{methods.join(', ')}].") unless methods.include?(_return)
46
+ image = Image.load(image) if image.is_a?(String)
46
47
  closest_similarity = 0.0
47
48
  closest_similarity_x = nil
48
49
  closest_similarity_y = nil
@@ -6,14 +6,14 @@ class SpecialInputDevice::Point
6
6
  include(SpecialInputDevice::AttributesEqualChecker)
7
7
 
8
8
  # @return [Integer] the x-coordinate of the point
9
- attr_reader :x
9
+ attr_reader(:x)
10
10
  # @param [Integer] value the x-coordinate of the point
11
11
  def x=(value)
12
12
  @x = value.to_i
13
13
  end
14
14
 
15
15
  # @return [Integer] the y-coordinate of the point
16
- attr_reader :y
16
+ attr_reader(:y)
17
17
  # @param [Integer] value the y-coordinate of the point
18
18
  def y=(value)
19
19
  @y = value.to_i