Página 16 de 23

RMChart

Enviado: 28 Mai 2016 12:33
por JoséQuintas
Lembrem-se que tem inconvenientes na criação de gráficos.
Convém testar mais de uma janela, ao mesmo tempo ou não, porque as funções parecem se lembrar de cada gráfico.

A solução deve variar conforme a LIB gráfica.

A minha dá pra ver acima, vinculei a DLL ao programa que chama os gráficos.
E cada gráfico recebe uma ID diferente.

Também lembro de ter visto em algum lugar sobre um limite de 20 gráficos ou algo assim.
Mas foi tanto lugar que olhei, que não lembro aonde foi... rs

RMChart

Enviado: 28 Mai 2016 12:39
por Daniel
Quintas falei errado e o sexto elemento rs
Eu vi isso mais se mandar deletar primeiro ai gera o novo gráfico sera que resolve??

RMChart

Enviado: 28 Mai 2016 13:39
por JoséQuintas
Mesmo assim tive problemas, como se o ID ficasse vinculado à janela que nem existe mais.
A saída é sempre ir incrementando o ID.

Pensei em tratar isso na classe, somando sempre 1.
(Além de deletar o gráfico no final - DeleteChart( nId ).

Pensei em tratar mais coisas na classe:

- O ID, deixando na classe, eliminaria a necessidade desse parâmetro toda hora.
- O tamanho dos arrays, idem
- Um Begin() pra incrementar o Id, e um End() pra deletar o gráfico no final

Só que deixaria incompatível com os exemplos existentes, ou com o fonte gerado pelo RMDesigner.


Ou a saída mais simples: reservar uma janela pra gráficos, e usar sempre a mesma.
Apenas ocultar quando estiver fora de uso.
Aí dá pra usar sempre o mesmo Id.

Também pensei em usar a opção de gerar JPG/PNG/Bitmap, mas só dá pra fazer isso gravando em disco.
Deste jeito nem precisaria de janela pro RMChart, apenas de uma janela pra mostrar a imagem no final.

Vou começar a usar assim, e ver o que acontece.
Pode ser que assim já esteja resolvido pro uso normal.

RMChart

Enviado: 28 Mai 2016 13:56
por JoséQuintas
Me lembrou disso, então fiz um teste.

Código: Selecionar todos

FUNCTION Main()

   hb_ThreadStart( { || Test() } )
   hb_ThreadWaitForAll()
   RETURN NIL
Executei a mesma rotina de gráfico em uma thread ok.
A mesma rotina em mais de uma thread... GPF.
Cada rotina com sua própria janela e seu própripo RMChart.

RMChart

Enviado: 28 Mai 2016 14:08
por JoséQuintas
Idem alterando o número do gráfico.

Código: Selecionar todos

FUNCTION Main()

   hb_ThreadStart( { || Test( 0 ) } )
   hb_ThreadStart( { || Test( 10 ) } )
   hb_ThreadStart( { || Test( 20 ) } )
   hb_ThreadWaitForAll()
   RETURN NIL
Pelo que andei lendo de janela pra activex (atlaxwin), a janela anterior funciona como "container", guardando dados do activex.
Acho possível que o RMChart, mesmo usando DLL, acabe fazendo algo parecido.
Vou fazer mais testes, mas pelo jeito só dá pra carregar uma vez a DLL (ou não dá pra descarregar).
E por isso não pode repetir Id.

Isso é fácil de contornar, só criar uma variável estática com a classe do RMChart, e outra com a próxima Id, caso não seja feito isso na classe.

RMChart

Enviado: 28 Mai 2016 20:17
por Daniel
Pelo teste aqui com janelas o RMChart apaga a janelas anterior com a mesma ID sem eu mandar deletar e não da erro
com ID diferente cria sem erro o mesmo gráfico em varias janelas
só fechar as janelas que o RMChart delata automático e pode cria de novo sem erro

RMChart

Enviado: 29 Mai 2016 11:42
por asimoes
Olá Quintas,

Você já sabe pelo facebook que eu fiz uma cirurgìa dia 25/05 e graças a Deus já estou em casa.

Já estou acompanhando desde o meu último post aqui e já estou babando com as evoluções sobre Rm.

Temos uma versão vamos dizer assim:

beta 1.0 ou 1.x nas classes os um fonte demo para testar.

Parabéns!

RMChart

Enviado: 29 Mai 2016 12:36
por JoséQuintas
Faltou postar aqui o completo.

http://www.jpatecnologia.com.br/arquivo ... mchart.zip
testrmchart.png
Os #define de cores originais estão em Upper/Lower, por exemplo, Default, Red, Blue, DarkBlue, Goldenred, LightGreen, etc.
Melhor alterar pra RMC_DEFAULT, RMC_RED, RMC_BLUE, RMC_DARK_BLUE, RMC_GOLDENRED, RMC_LIGHT_GREEN.
Só que pode ser que sejam as cores do Windows, que poderíamos usar em qualquer tela, neste caso, melhor COLOR_BLUE, COLOR_RED, etc.
Deixei COLOR_* mas não testei se vale pras LIBs gráficas.
Essa idéia de cores é legal pra aproveitar nos fontes normais de trabalho.

RMChart

Enviado: 29 Mai 2016 13:43
por JoséQuintas
Dica pra mais gráficos:

Carregue um gráfico pronto, ou crie o seu próprio no rmdesigner:
rmdesigner.png
Escolhe obter código fonte
rmdesigner2.png
escolha VB6 usando DLL, código compacto.
rmdesigner3.png
fonte obtido:

Código: Selecionar todos

    Dim i AS LONG
    Dim nC AS LONG
    Dim nDataCount AS LONG
    Dim nRetVal AS LONG
    Dim sTemp AS STRING
    ReDim aData(0) AS DOUBLE
    ReDim aData2(0) AS DOUBLE
    ReDim aPPC(0) AS LONG
    ReDim aColor(0) AS LONG
 
 
    '************** Create the chart ********************** 
    nRetVal = RMC_CreateChartOnDC(Me.hDC,ID_RMC1,10,10,600,450,MidnightBlue,RMC_CTRLSTYLEIMAGE,FALSE,"seasky.jpg","Tahoma", Default)
    IF nRetVal < 0 THEN GOTO IsError
    '************** Add Region 1 ***************************** 
    nRetVal = RMC_AddRegion(ID_RMC1,5,5,-5,-5,"",FALSE) 
    IF nRetVal < 0 THEN GOTO IsError
    '************** Add legend to region 1 ******************************* 
    sTemp = "Apples*Citrons*Bananas*Cherries"
    nRetVal = RMC_AddLegend(ID_RMC1,1,sTemp,RMC_LEGEND_CUSTOM_CENTER,Default,RMC_LEGENDNORECT,White,8,FALSE) 
    IF nRetVal < 0 THEN GOTO IsError
    '************** Add Series 1 to region 1 ******************************* 
    '****** Read color values ******
    Redim aColor(3)
    aColor(0) = LightGreen
    aColor(1) = Yellow
    aColor(2) = Goldenrod
    aColor(3) = Crimson
    '****** Read data values ******
    REDIM aData(3)
    aData(0) = 40 : aData(1) = 30 : aData(2) = 60 : aData(3) = 20
    nRetVal = RMC_AddGridlessSeries(ID_RMC1,1, aData(0), 4,aColor(0),4,RMC_DONUT_GRADIENT,RMC_FULL,0,FALSE,RMC_VLABEL_TWIN,RMC_HATCHBRUSH_OFF, 0) 
    IF nRetVal < 0 THEN GOTO IsError
 
    nRetVal = RMC_SetWatermark(RMC_USERWM,RMC_USERWMCOLOR,RMC_USERWMLUCENT,RMC_USERWMALIGN,RMC_USERFONTSIZE)
    nRetVal = RMC_Draw(ID_RMC1)
    IF nRetVal < 0 THEN GOTO IsError
    Exit SUB 
 
    IsError: 
fonte no Harbour

Código: Selecionar todos

   LOCAL aColors := { COLOR_LIGHT_GREEN, COLOR_YELLOW, COLOR_GOLDENROD, COLOR_CRIMSON }
   LOCAL aData   := { 40, 30, 60, 20 }

   oRmChart:CreateChart( oCrt:hWnd,ID_RMC1,0,0,MAX_SIZE_ONE,MAX_SIZE_TWO,COLOR_MIDNIGHT_BLUE,RMC_CTRLSTYLEIMAGE,.F.,"seasky.jpg","Tahoma", 0, COLOR_DEFAULT )
   oRMChart:AddRegion(ID_RMC1,5,5,-5,-5,"",.F.)
   oRMChart:AddLegend(ID_RMC1,1,"Apples*Citrons*Bananas*Cherries",RMC_LEGEND_CUSTOM_CENTER,COLOR_DEFAULT,RMC_LEGENDNORECT,COLOR_WHITE,8,.F.)
   oRmChart:AddGridlessSeries(ID_RMC1,1, aData, 4, aColors, 4,RMC_DONUT_GRADIENT,RMC_FULL,0,.F.,RMC_VLABEL_TWIN,RMC_HATCHBRUSH_OFF, 0)
   oRmChart:SetWatermark(RMC_USERWM,RMC_USERWMCOLOR,RMC_USERWMLUCENT,RMC_USERWMALIGN,RMC_USERFONTSIZE)
   oRmChart:Draw(ID_RMC1)
Basicamente o jeito de definir variáveis e arrays é que se altera.
Mas IMPORTANTE: o exemplo usa CreateChartOnDC() que tem um parâmetro a menos. Se não adicionar um zero antes do último parâmetro ao trocar pra CreateChart(), dá GPF.

Nota: comecei o print-screen usando o gráfico 4 em 1, mas depois achei melhor usar um exemplo mais simples pra mostrar o fonte, e alterei o gráfico no meio do caminho.

RMChart

Enviado: 29 Mai 2016 13:48
por asimoes
O FALSE e o TRUE poderia até ser um define

#define FALSE .F.
#define TRUE .T.

Já aproveita boa parte do código

RMChart

Enviado: 29 Mai 2016 13:52
por JoséQuintas
Sim.

Esta parte:

Código: Selecionar todos

nRetVal = RMC_AddRegion(ID_RMC1,5,5,-5,-5,"",FALSE)
Geralmente o pessoal copia desse jeito.
Mas se não vai usar o nRetVal, melhor nem colocar, senão o Harbour compilado com -w3 -es2 vai reclamar que não está usando isso pra nada.

Apenas pra curiosidade, no próprio VB6 ficaria diferente se não usa o retorno, porque não seria escrito como função:

Código: Selecionar todos

RMC_AddRegion ID_RMC1 5 5 -5 -5, "", FALSE
Talvez quem montou a rotina pra VB6 também tenha copiado de outra.... rs
Mas já mostrou como detectar se deu erro em cada comando...

IMPORTANTE também:
o RMChart é meio chatinho quanto a coisas erradas. É comum obter GPF dependendo do que estiver errado.
Por exemplo, só no último gráfico houve problema de converter outro parâmetro, e estava gerando GPF sem a conversão, enquanto nos demais funcionava perfeito. Foi o único que usou cores como array. Pode ser que ainda existam situações pela frente onde precise alguma conversão extra em determinados parâmetros.
Geralmente ocorre quando o parâmetro é um array, e até agora o ::ToDouble() resolveu.

RMChart

Enviado: 29 Mai 2016 14:06
por JoséQuintas
Por último:
Até que o fonte da classe ficou interessante, pode servir de modelo pra usar outras DLLs.

Código: Selecionar todos

CREATE CLASS RmChart

   VAR    nHandle

   METHOD New()                            INLINE ::nHandle := hb_libLoad( "RMChart.dll" ), SELF
   METHOD Destroy()                        INLINE hb_libFree( ::nHandle )
   METHOD CreateChart( ... )               INLINE ::CallDllStd( "RMC_CREATECHART", ... )
   METHOD CreateChartOnDc( ... )           INLINE ::CallDllStd( "RMC_CREATECHARONDC", ... )
   METHOD AddBarSeries(a,b,c, ... )        INLINE ::CallDllStd( "RMC_ADDBARSERIES", a, b, ::ToDouble(c), ... )
   METHOD AddRegion( ... )                 INLINE ::CallDllStd( "RMC_ADDREGION", ... )
   METHOD AddCaption( ... )                INLINE ::CallDllStd( "RMC_ADDCAPTION", ... )
   METHOD AddDataAxis(a,b,c,d,e, ... )     INLINE ::CallDllStd( "RMC_ADDDATAAXIS", a, b, c, ::ToDecimal(d), ::ToDecimal(e), ... )
   METHOD AddGrid( ... )                   INLINE ::CallDllStd( "RMC_ADDGRID", ... )
   METHOD AddGridLessSeries(a,b,c,d,e,...) INLINE ::CallDllStd( "RMC_ADDGRIDLESSSERIES", a, b, ::ToDouble(c), d, ::ToDouble(e), ... )
   METHOD AddLabelAxis( ... )              INLINE ::CallDllStd( "RMC_ADDLABELAXIS", ... )
   METHOD AddLegend( ... )                 INLINE ::CallDllStd( "RMC_ADDLEGEND", ... )
   METHOD AddLineSeries( a,b,c, ... )      INLINE ::CallDllStd( "RMC_ADDLINESERIES", a, b, ::ToDouble(c), ... )
   METHOD DeleteChart( ... )               INLINE ::CallDllStd( "RMC_DELETECHART", ... )
   METHOD Draw( ... )                      INLINE ::CallDllStd( "RMC_DRAW", ... )
   METHOD Draw2Clipboard( ... )            INLINE ::CallDllStd( "RMC_DRAW2CLIPBOARD", ... )
   METHOD Draw2Printer( ... )              INLINE ::CallDllStd( "RMC_DRAW2PRINTER", ... )
   METHOD Draw2File( ... )                 INLINE ::CallDllStd( "RMC_DRAW2FILE", ... )
   METHOD Reset( ... )                     INLINE ::CallDllStd( "RMC_RESET", ... )
   METHOD SetWaterMark( ... )              INLINE ::CallDllStd( "RMC_SETWATERMARK", ... )
   METHOD WriteRMCFile( ... )              INLINE ::CallDllStd( "RMC_WRITERMCFILE", ... )
   METHOD CallDllStd( cName, ... )         INLINE hb_DynCall( { cName, ::nHandle, HB_DYN_CALLCONV_STDCALL }, ... )
   METHOD ToDecimal( xValue )              INLINE xValue + 1.01 - 1.01
   METHOD ToDouble( xValue )

   ENDCLASS

METHOD RMChart:ToDouble( xValue )

   LOCAL cDouble := "", oElement

   IF ValType( xValue ) == "N"
      RETURN xValue
   ENDIF
   FOR EACH oElement IN xValue
      cDouble += FToC( oElement )
   NEXT

   RETURN cDouble

RMChart

Enviado: 29 Mai 2016 17:17
por asimoes
Acredito que com relação as cores seja a mesma situação do harupdf onde para produzir as cores precisa dividir por 255 (seria o ::todouble)

nRed := Round(212 / 255, 2),;
nGreen := Round(255 / 255, 2),;
nBlue := Round(255 / 255, 2)

RMChart

Enviado: 29 Mai 2016 18:18
por JoséQuintas
Não é isso.
A minha idéia era, por exemplo, ao criar um pushbutton azul, usar COLOR_BLUE, aproveitando o #define do RMChart.
Mas não deu certo.

RMChart

Enviado: 29 Mai 2016 19:06
por JoséQuintas
Se considerar estas cores:

Código: Selecionar todos

#define RMC_COLOR_WHITE                  -1
#define RMC_COLOR_YELLOW                 -256
Parece que o padrão é CMY e não RGB.
As três cores primárias são diferentes.
colors.png
colors.png (8.92 KiB) Exibido 11209 vezes