Libraries: MultiTester - page 54

 
hini #:

The code checks only Russian and English languages

If someone gives the name of the Start button in other languages, I will include in the source code.
 
fxsaber #:
If someone gives the name of the Start button in other languages, I will include it in the source.
For Chinese, the text of the Start and Stop buttons is as follows: "开始" and "停止".
 
hini #:
For Chinese, the text of the "Start" and "Stop" buttons is as follows: "开始" and "停止".
Updated.
 
fxsaber #:
Updated.
Maybe it's easier to read a string from the button and then compare whether it remains the same or has changed? There are a lot of languages, but the button has only two states.
 
Stanislav Korotky #:
Wouldn't it be easier to read a string from the button and then compare whether it remains the same or has changed?

After all, the function should not be dependent on previous states. It would be easier to use colour: green - start, otherwise - stop. But I do everything in WinAPI by poke method, so I don't know how to read the colour (Green component) of the button. If there is a working variant, of course, I will replace it.

 
fxsaber #:

Still, the function should not be dependent on previous states. It would be easier to use colour: green - start, otherwise - stop. But I do everything in WinAPI by poke method, so I don't know how to read the colour (Green component) of the button. If there is a working variant, of course, I will replace it.

This code has been tested by me and it is confirmed that it works.

(I recommend you to keep both methods, maybe in the future MT5 developers will change the colours).

//+------------------------------------------------------------------+
//|CheckButtonColour.mq5|
//+------------------------------------------------------------------+
#include <WinAPI/winapi.mqh>

#define private public
#include <fxsaber/MultiTester/MTTester.mqh>
#undef private

#ifdef __MQL5__
#define  ULONG_PTR   ulong
#else
#define  ULONG_PTR   uint
#endif

#define  WORD           int
#define  DWORD_PTR      ULONG_PTR
#define  BYTE           uchar

#define  LOBYTE(w)           ((BYTE)(((DWORD_PTR)(w)) & 0xff))
#define  GetRValue(rgb)      (LOBYTE(rgb))
#define  GetGValue(rgb)      (LOBYTE(((WORD)(rgb)) >> 8))
#define  GetBValue(rgb)      (LOBYTE((rgb)>>16))
//+------------------------------------------------------------------+
//| Get handle of "Start" button|
//+------------------------------------------------------------------+
long GetStartBtnHandle(void) {
  static const int ControlID[] = {0xE81E, 0x804E, 0x2712, 0x4196};
  static const long Handle = MTTESTER::GetHandle(ControlID);
  if(Handle <= 0) return 0;
  return Handle;
}

//+------------------------------------------------------------------+
//| Generic colour detection function: Check if button's specific |
//| position matches the preset RGB colour |
//+------------------------------------------------------------------+
bool IsButtonBackgroundColor(HWND hButton, color targetClr) {
  if(!hButton || !user32::IsWindow(hButton)) return false;
  // 1. Get button position on screen
  RECT rect;
  user32::GetWindowRect(hButton, rect);
  // 2. Sampling point: 20 pixels from left edge, vertical centre (avoid text)
  int targetX = rect.left + 20;
  int targetY = rect.top + (rect.bottom - rect.top) / 2;
  // 3. Screen sampling
  HANDLE hdcScreen = user32::GetDC(NULL);
  uint clr = gdi32::GetPixel(hdcScreen, targetX, targetY);
  user32::ReleaseDC(NULL, hdcScreen);
  if(clr == 0xFFFFFFFF) return false;
  return targetClr == clr;
}
//+------------------------------------------------------------------+
//| Script entry point OnStart|
//+------------------------------------------------------------------+
void OnStart() {
  HWND hBtn = (HWND)GetStartBtnHandle();
  if(hBtn == 0) return;
  // --- Flexible calls based on user needs ---
  // Check for: Light theme green (156, 204, 101) hover:140, 188, 85
  bool isLightGreen = IsButtonBackgroundColor(hBtn, C'156, 204, 101') || 
                      IsButtonBackgroundColor(hBtn, C'140, 188, 85');
  
  // Check for: Dark theme green (96, 96, 0) hover:80, 80, 0
  bool isDarkGreen = IsButtonBackgroundColor(hBtn, C'96, 96, 0') || 
                     IsButtonBackgroundColor(hBtn, C'80, 80, 0');
  
  // Check for: Light theme red (239, 154, 154) hover:223, 138, 138
  bool isLightRed = IsButtonBackgroundColor(hBtn, C'239, 154, 154') || 
                    IsButtonBackgroundColor(hBtn, C'223, 138, 138');
  
  // Check for: Dark theme red (112, 14, 19) hover:128, 30, 35
  bool isDarkRed = IsButtonBackgroundColor(hBtn, C'112, 14, 19') || 
                   IsButtonBackgroundColor(hBtn, C'128, 30, 35');
  // Business logic
  if(isLightGreen || isDarkGreen) {
    Print("Current button state: Green (Ready to start)");
  } else if(isLightRed || isDarkRed) {
    Print("Current button state: Red (Running/Stopped)");
  } else {
    Print("Current button state: Other color/Unknown");
  }
}
//+------------------------------------------------------------------+
 
fxsaber #:

Still, the function should not be dependent on previous states. It would be easier to use colour: green - start, otherwise - stop. But I do everything in WinAPI by poke method, so I don't know how to read the colour (Green component) of the button. If there is a working variant, of course, I will replace it.

It is probably easier not by the colour of the button, but by the state of the Inputs list - enabled/disabled.
 
Stanislav Korotky #:
It is probably easier not by the colour of the button, but by the status of the Inputs list - enabled/disabled.
Where to get the status of Inputs? There is no official API, we have to determine it by colours and text.
 
hini #:
Where to get the status of Inputs? There is no official API, we have to determine it by colours and text.

Well, there is no official API for all MT5 internals - you have to inspect them through utilities like MS Spy - that's how the control identifiers were found, which are now used in the multitester.

If you don't go into the wilds of Inputs and just use the already tested start button, it seems that the GetWindowLongW(hwnd, 0) call should return the current colour of the button. Mine returns 0xD0B1DF10 for the green one. Only if MQ decides to correct the style, this setting might go away. So checking the activity of Inputs is more reliable anyway.

 
Stanislav Korotky #:

looks like the GetWindowLongW(hwnd, 0) call should return the current colour of the button. I get 0xD0B1DF10 for the green one.

GetPixel seems to return a different G-colour.