2025-10-13 07:15:19 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Canvas.mqh |
|
|
|
|
|
//| Copyright 2025, Niquel Mendoza. |
|
|
|
|
|
//| https://www.mql5.com/es/users/nique_372/news |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#property copyright "Copyright 2025, Niquel Mendoza."
|
|
|
|
|
#property link "https://www.mql5.com/es/users/nique_372/news"
|
|
|
|
|
#property strict
|
|
|
|
|
|
|
|
|
|
|
2025-12-21 13:17:20 -05:00
|
|
|
#ifndef GRAPICHSBYLEO_GENERAL_CANVAS_MQH
|
|
|
|
|
#define GRAPICHSBYLEO_GENERAL_CANVAS_MQH
|
2025-10-13 07:15:19 -05:00
|
|
|
|
2025-12-21 13:17:20 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2025-10-13 07:15:19 -05:00
|
|
|
#include <Canvas\\Canvas.mqh>
|
2026-01-02 10:19:07 -05:00
|
|
|
#include "..\\..\\MQLArticles\\Utils\\Basic.mqh"
|
2025-12-21 13:17:20 -05:00
|
|
|
|
2025-10-13 07:15:19 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
class CCanvasCustom : public CCanvas
|
|
|
|
|
{
|
|
|
|
|
public:
|
2025-11-14 20:56:07 -05:00
|
|
|
|
2025-12-21 13:17:20 -05:00
|
|
|
//--- Creacion por recurso
|
|
|
|
|
// Solo recuros
|
|
|
|
|
bool CreateFromResource(const string& resource_file_name, const string& name, ENUM_COLOR_FORMAT clrfmt);
|
|
|
|
|
|
|
|
|
|
//- Bitmap
|
|
|
|
|
// Crea un bitmap mediante un recurso ya creado o embebido dentro del EX5
|
|
|
|
|
bool CreateBitmapFromResource(const string& resource_file_name, const long chart_id, const int subwin, const string& name,
|
|
|
|
|
const datetime time, const double price, ENUM_COLOR_FORMAT clrfmt);
|
|
|
|
|
|
|
|
|
|
__forceinline bool CreateBitmapFromResource(const string& resource_file_name, const string& name, const datetime time, const double price,
|
|
|
|
|
ENUM_COLOR_FORMAT clrfmt) { return CreateBitmapFromResource(resource_file_name, 0, 0, name, time, price, clrfmt); }
|
|
|
|
|
|
|
|
|
|
//- Label
|
|
|
|
|
// Crea un label en base a un recurso ya creado o embebido
|
|
|
|
|
bool CreateBitmapLabelFromResource(const string& resource_file_name, const long chart_id, const int subwin, const string& name, const int x, const int y, ENUM_COLOR_FORMAT clrfmt);
|
|
|
|
|
__forceinline bool CreateBitmapLabelFromResource(const string& resource_file_name, const string& name, const int x, const int y, ENUM_COLOR_FORMAT clrfmt)
|
|
|
|
|
{ return CreateBitmapLabelFromResource(resource_file_name, 0, 0, name, x, y, clrfmt); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- General
|
2025-10-13 07:15:19 -05:00
|
|
|
__forceinline ENUM_OBJECT ObjectType() const { return m_objtype; }
|
|
|
|
|
__forceinline bool TextOuTF(int x, int y, string text, const uint clr, uint alignment = 0) { return ::TextOut(text, x, y, alignment, m_pixels, m_width, m_height, clr, m_format);}
|
2025-12-21 13:17:20 -05:00
|
|
|
__forceinline int SetPixelsArray(const uint& src_array_px[]);
|
2025-11-14 20:56:07 -05:00
|
|
|
__forceinline int GetIndex(int x, int y) { return (y * m_width + x); }
|
|
|
|
|
__forceinline int TotalPixels() const { return ::ArraySize(m_pixels); }
|
|
|
|
|
__forceinline string RealResourceName() const { return StringSubstr(m_rcname, 2);}
|
2026-01-13 17:15:57 -05:00
|
|
|
__forceinline long ChartId() const { return m_chart_id; }
|
2025-11-14 20:56:07 -05:00
|
|
|
|
2025-12-21 13:17:20 -05:00
|
|
|
//--- Get data
|
|
|
|
|
// Total pixles
|
|
|
|
|
__forceinline int GetPixelsArray(uint& out_array_pixels[]) const;
|
|
|
|
|
|
|
|
|
|
// Row
|
|
|
|
|
void GetPixelsArrayRow(uint& out[], int y, int x_count = WHOLE_ARRAY);
|
|
|
|
|
void GetPixelsArrayRow(uint &out[], int y, int x_start, int x_end);
|
|
|
|
|
|
|
|
|
|
// Col
|
|
|
|
|
void GetPixelsArrayCol(uint& out[], int x, int y_count = WHOLE_ARRAY);
|
|
|
|
|
void GetPixelsArrayCol(uint &out[], int x, int y_start, int y_end);
|
2025-11-14 20:56:07 -05:00
|
|
|
|
|
|
|
|
//---
|
2025-12-21 13:17:20 -05:00
|
|
|
bool CortarAnchoRange(int x_start, int x_end);
|
|
|
|
|
bool CortarAnchoPx(int left, int right);
|
|
|
|
|
|
|
|
|
|
//--- Pixel Get
|
2025-11-14 20:56:07 -05:00
|
|
|
using CCanvas::PixelSet;
|
2025-12-21 13:17:20 -05:00
|
|
|
__forceinline uint PixelSet(const int index, uint clr) { return(m_pixels[index] = clr); }
|
2025-11-14 20:56:07 -05:00
|
|
|
|
|
|
|
|
using CCanvas::PixelGet;
|
|
|
|
|
__forceinline uint PixelGet(const int index) const { return (m_pixels[index]); }
|
|
|
|
|
|
2025-12-21 13:17:20 -05:00
|
|
|
//--- Decompress
|
2025-11-14 20:56:07 -05:00
|
|
|
inline void PixelDecompress(const int px, int&x, int&y);
|
2025-12-21 13:17:20 -05:00
|
|
|
|
|
|
|
|
//--- Guardar
|
|
|
|
|
// Recurso
|
|
|
|
|
bool Save(const string& filename, bool comon);
|
|
|
|
|
|
|
|
|
|
static bool Save(const string& rcname, const string& filename, bool comon);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- Funciones estaticas
|
|
|
|
|
static string CreateFromResourceS(const string &resource_file_name, const string &name, ENUM_COLOR_FORMAT clrfmt);
|
2025-10-13 07:15:19 -05:00
|
|
|
};
|
2025-11-14 20:56:07 -05:00
|
|
|
|
2025-10-13 07:15:19 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2025-12-21 13:17:20 -05:00
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CCanvasCustom::CortarAnchoRange(int x_start, int x_end)
|
2025-10-13 07:15:19 -05:00
|
|
|
{
|
2025-12-21 13:17:20 -05:00
|
|
|
//---
|
|
|
|
|
const int right = m_width - x_end - 1;
|
|
|
|
|
const int left = x_start;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const uint new_w = m_width - (right + left);
|
|
|
|
|
uint data[];
|
|
|
|
|
ArrayResize(data, (m_height * new_w));
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int y = 0; y < m_height; y++)
|
|
|
|
|
{
|
|
|
|
|
uint row[];
|
|
|
|
|
GetPixelsArrayRow(row, y, x_start, x_end);
|
|
|
|
|
ArrayCopy(data, row, (y * new_w), 0, new_w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(!Resize(new_w, m_height))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(ArrayCopy(m_pixels, data) != data.Size())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return true;
|
2025-10-13 07:15:19 -05:00
|
|
|
}
|
2025-12-21 13:17:20 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
2025-10-13 07:15:19 -05:00
|
|
|
//+------------------------------------------------------------------+
|
2025-12-21 13:17:20 -05:00
|
|
|
bool CCanvasCustom::CortarAnchoPx(int left, int right)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const int x_start = left;
|
|
|
|
|
const int x_end = m_width - right - 1;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const uint new_w = m_width - (right + left);
|
|
|
|
|
uint data[];
|
|
|
|
|
ArrayResize(data, (m_height * new_w));
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int y = 0; y < m_height; y++)
|
|
|
|
|
{
|
|
|
|
|
uint row[];
|
|
|
|
|
GetPixelsArrayRow(row, y, x_start, x_end);
|
|
|
|
|
ArrayCopy(data, row, (y * new_w), 0, new_w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(!Resize(new_w, m_height))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(ArrayCopy(m_pixels, data) != data.Size())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CCanvasCustom::Save(const string &filename, bool comon)
|
|
|
|
|
{
|
|
|
|
|
if(!ResourceSave(m_rcname, filename))
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Fallo al guardar el recurso en el archivo '%s'", filename));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//---
|
|
|
|
|
if(comon)
|
|
|
|
|
{
|
|
|
|
|
if(!FileMove(filename, 0, filename, FILE_COMMON | FILE_REWRITE))
|
|
|
|
|
{
|
|
|
|
|
const string local = TerminalInfoString(TERMINAL_DATA_PATH);
|
|
|
|
|
const string common = TerminalInfoString(TERMINAL_COMMONDATA_PATH);
|
|
|
|
|
const string r_l = local + filename;
|
|
|
|
|
const string r_c = common + filename;
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("No se pudo mover el arhcivo %s de:\n%s\na\n%s", filename, r_l, r_c));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
static bool CCanvasCustom::Save(const string &rcname, const string &filename, bool comon)
|
|
|
|
|
{
|
|
|
|
|
if(!ResourceSave(rcname, filename))
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Fallo al guardar el recurso en el archivo '%s'", filename));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//---
|
|
|
|
|
if(comon)
|
|
|
|
|
{
|
|
|
|
|
if(!FileMove(filename, 0, filename, FILE_COMMON | FILE_REWRITE))
|
|
|
|
|
{
|
|
|
|
|
const string local = TerminalInfoString(TERMINAL_DATA_PATH);
|
|
|
|
|
const string common = TerminalInfoString(TERMINAL_COMMONDATA_PATH);
|
|
|
|
|
const string r_l = local + filename;
|
|
|
|
|
const string r_c = common + filename;
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("No se pudo mover el arhcivo %s de:\n%s\na\n%s", filename, r_l, r_c));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
static string CCanvasCustom::CreateFromResourceS(const string &resource_file_name, const string &name, ENUM_COLOR_FORMAT clrfmt)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
uint width, height;
|
|
|
|
|
uint data[];
|
|
|
|
|
if(!::ResourceReadImage(resource_file_name, data, width, height))
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Fallo al leer el recurso = '%s'", resource_file_name));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const string uniq = (string)ChartID() + (string)GetTickCount() + "." + (string)(GetMicrosecondCount() & 0x3FF);
|
|
|
|
|
const string rcname = "::" + StringSubstr(name, 0, 63 - StringLen(uniq)) + uniq;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(ResourceCreate(rcname, data, width, height, 0, 0, 0, clrfmt))
|
|
|
|
|
{
|
|
|
|
|
return (rcname);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, "Error al crear el recurso");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CCanvasCustom::CreateFromResource(const string &resource_file_name, const string &name, ENUM_COLOR_FORMAT clrfmt)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
uint w, h;
|
|
|
|
|
uint data[];
|
|
|
|
|
if(!::ResourceReadImage(resource_file_name, data, w, h))
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Fallo al leer el recurso = '%s'", resource_file_name));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//---
|
|
|
|
|
if(!Create(name, w, h, clrfmt))
|
|
|
|
|
return false;
|
|
|
|
|
//---
|
|
|
|
|
return ::ArrayCopy(m_pixels, data) == ArraySize(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CCanvasCustom::CreateBitmapFromResource(const string& resource_file_name, const long chart_id, const int subwin,
|
|
|
|
|
const string& name, const datetime time, const double price, ENUM_COLOR_FORMAT clrfmt)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
uint w, h;
|
|
|
|
|
uint data[];
|
|
|
|
|
if(!::ResourceReadImage(resource_file_name, data, w, h))
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Fallo al leer el recurso = '%s'", resource_file_name));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(!CreateBitmap(chart_id, subwin, name, time, price, w, h, clrfmt))
|
|
|
|
|
return false;
|
|
|
|
|
//---
|
|
|
|
|
return ::ArrayCopy(m_pixels, data) == ArraySize(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CCanvasCustom::CreateBitmapLabelFromResource(const string& resource_file_name, const long chart_id, const int subwin, const string& name,
|
|
|
|
|
const int x, const int y, ENUM_COLOR_FORMAT clrfmt)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
uint w, h;
|
|
|
|
|
uint data[];
|
|
|
|
|
if(!::ResourceReadImage(resource_file_name, data, w, h))
|
|
|
|
|
{
|
|
|
|
|
FastLog(FUNCION_ACTUAL, ERROR_TEXT, StringFormat("Fallo al leer el recurso = '%s'", resource_file_name));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
if(!CreateBitmapLabel(chart_id, subwin, name, x, y, w, h, clrfmt))
|
|
|
|
|
return false;
|
|
|
|
|
//---
|
|
|
|
|
return ::ArrayCopy(m_pixels, data) == ArraySize(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
__forceinline int CCanvasCustom::GetPixelsArray(uint &out_array_pixels[]) const
|
|
|
|
|
{
|
|
|
|
|
return ::ArrayCopy(out_array_pixels, m_pixels);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
__forceinline int CCanvasCustom::SetPixelsArray(const uint &src_array_px[])
|
2025-11-14 20:56:07 -05:00
|
|
|
{
|
|
|
|
|
if(src_array_px.Size() != m_pixels.Size())
|
2025-12-21 13:17:20 -05:00
|
|
|
return 0; // No son iguales
|
|
|
|
|
return ::ArrayCopy(m_pixels, src_array_px);
|
2025-11-14 20:56:07 -05:00
|
|
|
}
|
|
|
|
|
|
2025-12-21 13:17:20 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CCanvasCustom::GetPixelsArrayCol(uint &out[], int x, int y_count = WHOLE_ARRAY)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
if(y_count == WHOLE_ARRAY)
|
|
|
|
|
y_count = m_height;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(out, y_count);
|
|
|
|
|
//---
|
|
|
|
|
int r = 0;
|
|
|
|
|
for(int y = 0; y < y_count; y++)
|
|
|
|
|
out[r++] = m_pixels[(y * m_width + x)];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CCanvasCustom::GetPixelsArrayCol(uint &out[], int x, int y_start, int y_end)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(out, (y_end - y_start));
|
|
|
|
|
//---
|
|
|
|
|
int r = 0;
|
|
|
|
|
for(int y = y_start; y <= y_end; y++)
|
|
|
|
|
out[r++] = m_pixels[(y * m_width + x)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CCanvasCustom::GetPixelsArrayRow(uint &out[], int y, int x_count = WHOLE_ARRAY)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
if(x_count == WHOLE_ARRAY)
|
|
|
|
|
x_count = m_width;
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(out, x_count);
|
|
|
|
|
//---
|
|
|
|
|
int r = 0;
|
|
|
|
|
for(int x = 0; x < x_count; x++)
|
|
|
|
|
out[r++] = m_pixels[(y * m_width + x)];
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CCanvasCustom::GetPixelsArrayRow(uint &out[], int y, int x_start, int x_end)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(out, (x_end - x_start) + 1);
|
|
|
|
|
//---
|
|
|
|
|
int r = 0;
|
|
|
|
|
for(int x = x_start; x <= x_end; x++)
|
|
|
|
|
out[r++] = m_pixels[(y * m_width + x)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-11-14 20:56:07 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
inline void CCanvasCustom::PixelDecompress(const int px, int &x, int &y)
|
|
|
|
|
{
|
|
|
|
|
y = int(px / m_width);
|
|
|
|
|
x = (px - (y * m_width));
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2025-12-21 13:17:20 -05:00
|
|
|
|
2025-11-14 20:56:07 -05:00
|
|
|
#endif
|
|
|
|
|
//+------------------------------------------------------------------+
|