//+------------------------------------------------------------------+ //| 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 #ifndef GRAPICHSBYLEO_GENERAL_CANVAS_MQH #define GRAPICHSBYLEO_GENERAL_CANVAS_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include #include "..\\..\\MQLArticles\\Utils\\Basic.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CCanvasCustom : public CCanvas { public: //--- 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 __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);} __forceinline int SetPixelsArray(const uint& src_array_px[]); __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);} __forceinline long ChartId() const { return m_chart_id; } //--- 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); //--- bool CortarAnchoRange(int x_start, int x_end); bool CortarAnchoPx(int left, int right); //--- Pixel Get using CCanvas::PixelSet; __forceinline uint PixelSet(const int index, uint clr) { return(m_pixels[index] = clr); } using CCanvas::PixelGet; __forceinline uint PixelGet(const int index) const { return (m_pixels[index]); } //--- Decompress inline void PixelDecompress(const int px, int&x, int&y); //--- 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); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CCanvasCustom::CortarAnchoRange(int x_start, int x_end) { //--- 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; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ 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[]) { if(src_array_px.Size() != m_pixels.Size()) return 0; // No son iguales return ::ArrayCopy(m_pixels, src_array_px); } //+------------------------------------------------------------------+ 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)]; } //+------------------------------------------------------------------+ inline void CCanvasCustom::PixelDecompress(const int px, int &x, int &y) { y = int(px / m_width); x = (px - (y * m_width)); } //+------------------------------------------------------------------+ #endif //+------------------------------------------------------------------+