SimpleChart es una clase creada por Mike Lewis (http://www.ml-consult.co.uk) quien logra, mediante un grupo de propiedades, facilitar el trabajo con MSChart y posibilitar que se obtengan gráficos con mucha rapidez y sin complejidades.
Para ver todos los detalles relativos a esta clase ver:
SimpleChart revisado (Mike Lewis) Traducción
https://comunidadvfp.blogspot.com/2003/10/simplechart-revisitado.html
Nos había quedado pendiente aclarar cómo se pueden imprimir estos gráficos. Pues bien, la pregunta es ¿Se puede copiar un gráfico creado con SimpleChart en un informe de VFP?
¡¡Sí se puede!! Tal y como se indica en el segundo artículo, hay que invocar el método EditCopy del gráfico.
Aquí dejo un ejemplo concreto
* Copiar al Clipboard THISFORM.Grafico.EditCopy * Copiar a un bmp THISFORM.cRutaGrafico = GETENV("Temp")+SYS(2015)+".bmp" DO Graficos WITH (THISFORM.cRutaGrafico),""
Pego directamente el código del programa gráficos escrito por el compañero J. Enrique Ramos Menchaca, quien lo publicó en PortalFox y nos autorizó a modificarlo dadas las nuevas necesidades que yo tenía.
Cambios que hicimos:
- Incluir 2 parámetros: tcArchivo, tcreporte
- tcArchivo - nombre del .bmp que se va a cargar en el objeto imagen del informe
- tcreporte - nombre del reporte a llamar
- No emplear campo general y sí campo de caracteres con la ruta de la imagen a mostrar, mira donde dice código nuevo.
Lo único que necesitamos es copiar y pegar el programa gráfico en nuestra aplicación e invocarlo con los parámetros adecuados.
*********************************************** * Programa Graficos * Autor: J. Enrique Ramos Menchaca * Modificado por Jorge Mota y Ana María Bisbé York *********************************************** LPARAMETERS tcArchivo, tcreporte #DEFINE CF_BITMAP 2 #DEFINE OBJ_BITMAP 7 DO decl LOCAL hClipBmp, lcTargetFile *lcTargetFile = "C:\clipboard.bmp" lcTargetFile = tcArchivo && "grafime.bmp" = OpenClipboard (0) hClipBmp = GetClipboardData (CF_BITMAP) = CloseClipboard() IF hClipBmp = 0 Or GetObjectType(hClipBmp) <> OBJ_BITMAP = MessageBox("No se encontro imagen bitmap en el Portapapeles.",; 64, "Clipboard to BMP") RETURN .F. ENDIF = bitmap2file (hClipBmp, lcTargetFile) = DeleteObject (hClipBmp) *** * crear las referencias para los arreglos * external array laAspecto, lavalor, laporci,; * lavalor1, lavalor2, lavalor3, lavalor4 * Código original *!* CREATE CURSOR GRAFICO (GRAFICA G) *!* APPEND BLANK *!* APPEND GENERAL GRAFICO.GRAFICA FROM "c:\clipboard.bmp" *!* REPORT FORM GRAFICA preview *!* USE IN grafico *!* RETURN * Código modificado CREATE CURSOR GRAFICO (cRuta c(250)) APPEND BLANK REPLACE GRAFICO.cRuta WITH tcArchivo IF !empty(tcreporte) REPORT FORM (tcreporte) to print prompt noconso ENDIF USE IN GRAFICO RETURN *********************************************** * InitBitsArray() *********************************************** PROCEDURE InitBitsArray() #DEFINE GMEM_FIXED 0 LOCAL lnPtr pnBitsSize = pnHeight * pnBytesPerScan lnPtr = GlobalAlloc (GMEM_FIXED, pnBitsSize) = ZeroMemory (lnPtr, pnBitsSize) RETURN lnPtr ENDPROC *********************************************** * String2file *********************************************** PROCEDURE String2File (hFile, lcBuffer) DECLARE INTEGER WriteFile IN kernel32; INTEGER hFile, STRING @lpBuffer, INTEGER nBt2Write,; INTEGER @lpBtWritten, INTEGER lpOverlapped = WriteFile (hFile, @lcBuffer, Len(lcBuffer), 0, 0) RETURN ENDPROC *********************************************** * Bitmap2file *********************************************** PROCEDURE Bitmap2file (hBitmap, lcTargetFile) #DEFINE DIB_RGB_COLORS 0 PRIVATE pnWidth, pnHeight, pnBitsSize, pnRgbQuadSize, pnBytesPerScan STORE 0 TO pnWidth, pnHeight, pnBytesPerScan, pnBitsSize, pnRgbQuadSize = GetBitmapDimensions(hBitmap, @pnWidth, @pnHeight) LOCAL lpBitsArray, lcBInfo lcBInfo = InitBitmapInfo() lpBitsArray = InitBitsArray() LOCAL hwnd, hdc, hMemDC hwnd = GetActiveWindow() hdc = GetWindowDC(hwnd) hMemDC = CreateCompatibleDC (hdc) = ReleaseDC (hwnd, hdc) = GetDIBits (hMemDC, hBitmap, 0, pnHeight, lpBitsArray,; @lcBInfo, DIB_RGB_COLORS) #DEFINE BFHDR_SIZE 14 && BITMAPFILEHEADER #DEFINE BHDR_SIZE 40 && BITMAPINFOHEADER LOCAL hFile, lnFileSize, lnOffBits, lcBFileHdr lnFileSize = BFHDR_SIZE + BHDR_SIZE + pnRgbQuadSize + pnBitsSize lnOffBits = BFHDR_SIZE + BHDR_SIZE + pnRgbQuadSize lcBFileHdr = "BM" + num2dword(lnFileSize) +; num2dword(0) + num2dword(lnOffBits) #DEFINE GENERIC_WRITE 1073741824 && 0x40000000 #DEFINE FILE_SHARE_WRITE 2 #DEFINE CREATE_ALWAYS 2 #DEFINE FILE_ATTRIBUTE_NORMAL 128 #DEFINE INVALID_HANDLE_VALUE -1 hFile = CreateFile (lcTargetFile,; GENERIC_WRITE,; FILE_SHARE_WRITE, 0,; CREATE_ALWAYS,; FILE_ATTRIBUTE_NORMAL, 0) IF hFile <> INVALID_HANDLE_VALUE WAIT WINDOW "Storing to file..." NOWAIT = String2File (hFile, @lcBFileHdr) = String2File (hFile, @lcBInfo) = Ptr2File (hFile, lpBitsArray, pnBitsSize) = CloseHandle (hFile) ELSE = MessageBox("Unable to create file: " + lcTargetFile) ENDIF = GlobalFree(lpBitsArray) = DeleteDC (hMemDC) RETURN ENDPROC *********************************************** * Ptr2File *********************************************** PROCEDURE Ptr2File (hFile, lnPointer, lnBt2Write) DECLARE INTEGER WriteFile IN kernel32; INTEGER hFile, INTEGER lpBuffer, INTEGER nBt2Write,; INTEGER @lpBtWritten, INTEGER lpOverlapped = WriteFile (hFile, lnPointer, lnBt2Write, 0, 0) RETURN ENDPROC *********************************************** * InitBitmapInfo *********************************************** PROCEDURE InitBitmapInfo(lcBIHdr) #DEFINE BI_RGB 0 #DEFINE RGBQUAD_SIZE 4 #DEFINE BHDR_SIZE 40 LOCAL lnBitsPerPixel, lcBIHdr, lcRgbQuad lnBitsPerPixel = 24 pnBytesPerScan = Int((pnWidth * lnBitsPerPixel)/8) IF Mod(pnBytesPerScan, 4) <> 0 pnBytesPerScan = pnBytesPerScan + 4 - Mod(pnBytesPerScan, 4) ENDIF lcBIHdr = num2dword(BHDR_SIZE) + num2dword(pnWidth) +; num2dword(pnHeight) + num2word(1) + num2word(lnBitsPerPixel) +; num2dword(BI_RGB) + Repli(Chr(0), 20) IF lnBitsPerPixel <= 8 pnRgbQuadSize = (2^lnBitsPerPixel) * RGBQUAD_SIZE lcRgbQuad = Repli(Chr(0), pnRgbQuadSize) ELSE lcRgbQuad = "" ENDIF RETURN lcBIHdr + lcRgbQuad ENDPROC *********************************************** * num2dword *********************************************** FUNCTION num2dword (lnValue) #DEFINE m0 256 #DEFINE m1 65536 #DEFINE m2 16777216 LOCAL b0, b1, b2, b3 b3 = Int(lnValue/m2) b2 = Int((lnValue - b3*m2)/m1) b1 = Int((lnValue - b3*m2 - b2*m1)/m0) b0 = Mod(lnValue, m0) RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3) ENDFUNC *********************************************** * GetBitmapDimensions *********************************************** PROCEDURE GetBitmapDimensions(hBitmap, lnWidth, lnHeight) #DEFINE BITMAP_STRU_SIZE 24 LOCAL lcBuffer lcBuffer = Repli(Chr(0), BITMAP_STRU_SIZE) IF GetObjectA (hBitmap, BITMAP_STRU_SIZE, @lcBuffer) <> 0 lnWidth = buf2dword (SUBSTR(lcBuffer, 5,4)) lnHeight = buf2dword (SUBSTR(lcBuffer, 9,4)) ENDIF RETURN ENDPROC *********************************************** * buf2dword *********************************************** FUNCTION buf2dword (lcBuffer) RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ; Asc(SUBSTR(lcBuffer, 2,1)) * 256 +; Asc(SUBSTR(lcBuffer, 3,1)) * 65536 +; Asc(SUBSTR(lcBuffer, 4,1)) * 16777216 ENDFUNC *********************************************** * num2word *********************************************** FUNCTION num2word (lnValue) RETURN Chr(MOD(m.lnValue,256)) + CHR(INT(m.lnValue/256)) ENDFUNC *********************************************** * decl *********************************************** PROCEDURE decl DECLARE INTEGER GetActiveWindow IN user32 DECLARE INTEGER GetClipboardData IN user32 INTEGER uFormat DECLARE INTEGER OpenClipboard IN user32 INTEGER hwnd DECLARE INTEGER CloseClipboard IN user32 DECLARE INTEGER DeleteObject IN gdi32 INTEGER hObject DECLARE INTEGER GetWindowDC IN user32 INTEGER hwnd DECLARE INTEGER ReleaseDC IN user32 INTEGER hwnd, INTEGER hdc DECLARE INTEGER CreateCompatibleDC IN gdi32 INTEGER hdc DECLARE INTEGER DeleteDC IN gdi32 INTEGER hdc DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER wFlags, INTEGER dwBytes DECLARE INTEGER GlobalFree IN kernel32 INTEGER hMem DECLARE INTEGER GetObject IN gdi32 AS GetObjectA; INTEGER hgdiobj, INTEGER cbBuffer, STRING @lpvObject DECLARE INTEGER GetObjectType IN gdi32 INTEGER h DECLARE RtlZeroMemory IN kernel32 As ZeroMemory; INTEGER dest, INTEGER numBytes DECLARE INTEGER GetDIBits IN gdi32; INTEGER hdc, INTEGER hbmp, INTEGER uStartScan,; INTEGER cScanLines, INTEGER lpvBits, STRING @lpbi,; INTEGER uUsage DECLARE INTEGER CreateFile IN kernel32; STRING lpFileName, INTEGER dwDesiredAccess,; INTEGER dwShareMode, INTEGER lpSecurityAttr,; INTEGER dwCreationDisp, INTEGER dwFlagsAndAttrs,; INTEGER hTemplateFile DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject ENDPROC ***********************************************
Espero que sirva como complemento a la información que ya teníamos para trabajar con esta clase SimpleChart
Saludos,
Ana María Bisbé York
www.amby.net
Buenas tardes.
ResponderBorrarEstoy usando la clase SimpleChart con la cual muestro un grafico de lineas.
El problema que se me presenta es que cundo los valores a mostrar supera el 999.999 muestra los valores en notacion cientifica
Como hago para que los valores que superen el mllon se muestran bien.
Gracias