quinta-feira, 30 de dezembro de 2010

Tabela Ascii

Dec
Hex
Char
Dec
Hex
Char
Dec
Hex
Char
Dec
Hex
Char
0
0
NUL
32
20
.
64
40
@
96
60
`
1
1
SOH
33
21
!
65
41
A
97
61
a
2
2
STX
34
22
"
66
42
B
98
62
b
3
3
ETX
35
23
#
67
43
C
99
63
c
4
4
EOT
36
24
$
68
44
D
100
64
d
5
5
ENQ
37
25
%
69
45
E
101
65
e
6
6
ACK
38
26
&
70
46
F
102
66
f
7
7
BEL
39
27
'
71
47
G
103
67
g
8
8
BS
40
28
(
72
48
H
104
68
h
9
9
TAB
41
29
)
73
49
I
105
69
i
10
A
LF
42
2A
*
74
4A
J
106
6A
j
11
B
VT
43
2B
+
75
4B
K
107
6B
k
12
C
FF
44
2C
,
76
4C
L
108
6C
l
13
D
CR
45
2D
-
77
4D
M
109
6D
m
14
E
SO
46
2E
.
78
4E
N
110
6E
n
15
F
SI
47
2F
/
79
4F
O
111
6F
o
16
10
DLE
48
30
0
80
50
P
112
70
p
17
11
DC1
49
31
1
81
51
Q
113
71
q
18
12
DC2
50
32
2
82
52
R
114
72
r
19
13
DC3
51
33
3
83
53
S
115
73
s
20
14
DC4
52
34
4
84
54
T
116
74
t
21
15
NAK
53
35
5
85
55
U
117
75
u
22
16
SYN
54
36
6
86
56
V
118
76
v
23
17
ETB
55
37
7
87
57
W
119
77
w
24
18
CAN
56
38
8
88
58
X
120
78
x
25
19
EM
57
39
9
89
59
Y
121
79
y
26
1A
SUB
58
3A
:
90
5A
Z
122
7A
z
27
1B
ESC
59
3B
;
91
5B
[
123
7B
{
28
1C
FS
60
3C
<
92
5C
\
124
7C
|
29
1D
GS
61
3D
=
93
5D
]
125
7D
{
30
1E
RS
62
3E
>
94
5E
^
126
7E
~
31
1F
US
63
3F
?
95
5F
_
127
7F
DEL

quarta-feira, 29 de dezembro de 2010

Cuidados ao usar o OnExit

É comum fazermos uso do evento OnExit quando queremos validar o conteúdo de um Edit. E essa pode ser uma boa prática quando necessitamos verificar o que foi digitado apenas quando o usuário terminar de fazer a entrada de dados, como, por exemplo, um Edit que vai receber o CPF ou CNPJ.
Ao colocarmos um código qualquer no evento OnExit ele sempre será executado quando o usuário sair do Edit, o que acontece quando ele pressiona a tecla TAB, clica com o mouse em um outro Edit ou pressiona um botão OK, por exemplo.
No entanto, existem algumas situações especiais em que o evento OnExit não é gerado. Quer um exemplo? Você está no Edit e, ao invés de clicar no botão OK, você pressiona as teclas ALT + O (considerando que o botão OK tem a tecla O como atalho). É como se você tivesse pressionado o botão OK, porém, sem perder o foco que está no Edit. Só mais um exemplo: Os botões do tipo SpeedButton não recebem foco, então, mesmo que clique com o mouse sobre um SpeedButton, o foco continuará no Edit e, conseqüentemente, o evento OnExit não será gerado.

E a solução?

A solução para esse pequeno inconveniente é simples. Basta você colocar o seguinte código no evento OnClick do botão.

procedure TForm1.Button1Click(Sender: TObject);

begin

ActiveControl := nil;

...

end;

Suponhamos que você possua 2 Edits em um formulário. Supondo também que você queira dar alguma informação ao usuário da aplicação logo depois que ele sair do Edit1 você faz:

procedure TForm1.Edit1Exit(Sender: TObject);

begin

    MessageDlg('Mensagem...', mtInformation, [mbOk], 0);

end;


A princípio está tudo ok, ou melhor, parece estar tudo ok.

Se você altera o foco para o outro Edit através do pressionamento da tecla TAB, tudo bem. Mas experimente alterar o foco clicando com o mouse sobre o Edit2. Neste segundo caso a mensagem será exibida normalmente. Mas ao fechar o dialogo onde aparece a mensagem, o foco simplesmente se perde. Para setar o foco no Edit2 é necessário clicar novamente sobre ele.

Isso não teria problema nenhum até que seu usuário experimente esta situação. Nada que ele digitar será acatado.

Mas existe uma maneira fácil de resolver o problema. Basta você cancelar o foco e forçar uma reentrada no componente Edit2. Como fazer isso? Veja o código:

procedure TForm1.Edit1Exit(Sender: TObject);

begin

   MessageDlg('Mensagem...', mtInformation, [mbOk], 0);

   // cancela o foco e força novamente a entrada

   ActiveControl := nil;

   PostMessage(Edit2.Handle, WM_SETFOCUS, 0, 0);

   Edit2.SetFocus;

end;

Porém, você nunca terá certeza se o usuário clicou no Edit2. Então temos que criar uma rotina genérica que leva o foco para qualquer outro controle:

procedure TForm1.Edit1Exit(Sender: TObject);

var

   Ctrl: TWinControl;

begin

   MessageDlg('Mensagem...', mtInformation, [mbOk], 0);

   // cancela o foco e força novamente a entrada

   Ctrl := ActiveControl;

   ActiveControl := nil;

   PostMessage(TWinControl(Ctrl).Handle, WM_SETFOCUS, 0, 0);

   TWinControl(Ctrl).SetFocus;

end;

Observe que antes de cancelar o foco com ActiveControl := nil, salvamos qual é o controle que detém o foco fazendo Ctrl := ActiveControl.

Depois enviamos uma mensagem ao controle que detinha o foco, forçando-o a receber o foco novamente.

Rave - Imprimindo Gráficos (Chart)

Uma coisa muito comum nos sistemas, são os relatórios com gráficos estatísticos, os famosos Charts.

Antigamente eu usava o QuickReport e o ReportBuilder, porém relatórios com gráficos só precisei fazer no QuickReport e não tive muitas dificuldade, pois ele já tem um componente que facilita a vida.

Mas, como agora larguei o QuickReport e estou usando somente o Rave, houve então a necessidade de saber como fazer relatórios nele com gráficos.

Comecei então a fuçar no Rave e percebi que não existia nenhum componente que facilitasse a vida. Então fiz algumas pesquisas na internet para saber se não existiam componentes de terceiros, mas infelizmente não achei nenhum, porém nessas pesquisas, achei duas soluções para o caso :

1 – Salvar o conteúdo de um TCustomChart em um BMP e imprimir esse BMP no Rave
2 – Usar o método WriteChartData disponível na unit RPTChart

Esta última solução é a indicada pela Nevrona.

Fiz o teste com as duas soluções e as duas foram satisfatórias, porém gostei mais da última solução, pois como disse, é indicada pela própria Nevrona e não aparenta ser uma "gambiarra" :-) como a primeira solução.

Depois desta pesquisa, resolvi escrever este artigo para demonstrar como não é um bicho de sete cabeças fazer isso funcionar.

Então vamos lá...

Antes de iniciarmos, gostaria de explicar como a "coisa funciona", para depois partirmos para prática.

O método WriteChartData, "escreve" o conteúdo de um TCustomChart dentro de um campo do tipo Graphic. Então, a princípio, nosso gráfico será montado no TChart ou TDBChart do Delphi, e depois disso, iremos utilizar o WriteChartData para fazer com que o conteúdo do gráfico seja impresso, desenhado dentro do nosso relatório.

Agora vamos colocar em prática esta teoria...

Irei utilizar um RVCustomConnection, pois não preciso estar conectado a um DataSet para gerar o gráfico no Rave, só preciso de alguém que me disponibilize um campo para poder usá-lo na impressão, então o RVCustomConnection é o ideal para isso. Para quem não sabe para que serve o RVCustomConnection, vale a pena começar a mexer nele, pois é muito interessante.

Agora é serio, chega de teoria e vamos para prática...:-)

1 - Insira os seguintes componentes no Form:
TRVProject
TRVCustomConnection
TRVSystem
TChart

2 – Na clausula uses, insira a unit RPTChart. É esta unit que nos disponibilizará o método WriteChartData

3 - Ajuste a propriedade Engine do RaveProject, apontando para o RVSystem.

4 - Ajuste o Chart, de forma que represente algum gráfico, só para podermos visualizar o resultado final.

5 – Agora iremos ajustar dois eventos do componente RVCustomConnection:

OnGetCols:
Este evento é chamado quando o Rave necessita extrair os meta-data dos campos. É aqui que criaremos nosso campo do tipo graphic. Para isso, coloque o seguinte código neste evento:

with Connection do
begin
WriteField('CampoChart', dtGraphic, 0, '', '');
end;

 

OnGetRow:
Este evento é chamado quando o Rave necessita extrair os valores dos campos do registro atual. É aqui que iremos alimentar o valor do campo que criamos acima. Para isso, coloque o seguinte código neste evento:

WriteChartData(Connection, Chart1);

 

Chart1 é o nome do TChart que inserimos no Form.

A parte de codificação já está pronta, agora vamos para parte visual.

6 – Entre no RaveDesigner

7 – Crie uma Region e dentro desta Region crie uma banda simples.

8 – Dentro da Band1(que acabou de ser criada), insira o componente MetaFile, que está na palheta Standard do Rave.

9 – Crie uma DataView, da mesma forma que se fosse criar uma outra qualquer, a diferença é que os dados agora virão de um RVCustomConnection.

10 - Após ter criado, perceba que na TreeView o DataView1 está disponível, porém se clicar no sinal de mais do DataView1 para exibir os campos, perceberá que o campo que criamos via código(CampoChart) não está disponível, só tem um campo, que é o que vem de brinde, mas não use-o. Para que o nosso campo possa ser criado, o evento OnGetCols terá que ser chamado, e como fazer isso em tempo de projeto ?

O segredo é : O RaveDesigner tem que estar aberto juntamente com a aplicação e depois chamar o Refresh do DataView.

Então vamos lá...

11 - Execute a aplicação e volte para o RaveDesigner, mas não feche a aplicação ainda.

12 – Selecione o DataView1 lá na TreeView e clique com o botão direito do mouse sobre o DataView1. Aparecerá um item chamado Refresh, basta clicar nele e...bingo :-). Pronto, o campo que criamos via código irá aparecer na lista. Quando clicar pela primeira vez no Refresh, vai aparecer uma mensagem, é uma alerta de que um campo será excluído, isso ocorre pois quando criamos a DataView, já veio aquele campo de brinde, mas como não criamos ele no OnGetCols, então a mensagem alertará de que o mesmo será excluído.

13 – Agora selecione o componente MetaFile que foi inserindo em Band1 e altere duas propriedades dele:

DataField : CampoChart (nome do campo que criamos)
DataView : DataView1 (nome da dataview criada)

Pronto...Pode executar a aplicação e fazer o teste.

Caso queira fazer o teste no próprio preview do RaveDesigner, basta deixar a aplicação aberta, caso contrário, se a aplicação não estiver aberta e você chamar o preview do RaveDesigner, receberá de presente um errinho básico, o famoso "Acess violation..." :-)

Lembre-se, o exemplo que fizemos foi com um TChart, o mesmo poderá ser feito com um TDBChart.

Outro detalhe, utilizamos um RVCustomConnection, mas poderíamos utilizar um RVDataSetConnection sem problemas, porém neste caso, só fique atento com o seguinte:

No evento OnGetCols, antes de criar o campo, chame o método DoGetCols do Connection que vem como parâmetro neste evento. Isso deve ser feito para que primeiro sejam criadas as colunas do DataSet que está associado e depois sim poder criar as suas colunas.

E no evento OnGetRow, antes de chamar o WriteChartData, chame o método DoGetRow do Connection que vem como parâmetro neste evento. Isso deve ser feito para que primeiro seja alimentando os campos do DataSet que está associado e depois sim poder alimentar seus campos criados manualmente.

Espero que um dia possa surgir um componente para utilizarmos no Rave, pois assim ficará muito mais fácil, mas enquanto isso não acontece, temos esta solução

terça-feira, 28 de dezembro de 2010

Usuário e senha do DBA do MySql

Para Windows = ODBC (Maíusculo e sem senha) – usuário root e sem senha

Para Linux = root (Minúsculo e sem senha)

Detalhe importante: O DBA pode ser acessado somente via localhost (máquina local). Depois do primeiro acesso SQL, mude os Rights se quiser acessar de outro micro na rede (mas aconselho a não fazer isso, olha a segurança!!!!!).

 

Alguns comandos básicos para Firebird

Corrigindo problemas de instalação do Borland Data Provider For FireBird:

Em alguns casos, o Borland Data Provider For Firebird têm apresentado problemas de instalação, abaixo segue algumas dicas para tentar auxiliar na resolução dos mesmos:

Verificar se o D8 está atualizado com Update Pack#2;

Se o BDP For Firebird foi instalado 'antes' do D8 ter sido atualizado,desinstalar, atualizar o D8 e após isso instalar o BDP For Firebird novamente;

Efetuar testes diretamente via 'Data Explorer' a fim de verificar se a conexão ocorre sem problemas;

Copiar o arquivo 'FirebirdSql.Data.Bdp' para a pasta

C:\Arquivos de programas\Arquivos comuns\Borland Shared\BDS\Shared\Assemblies\2.0

5. No projeto, acesse 'Project Manager' | 'References' e adicione a referência ao 'Firebirdsql.Data.Bdp'


Listar as tabelas e views do banco de dados (Firebird):

SELECT RDB$RELATION_NAME FROM RDB$RELATIONS;

Listar as tabelas do banco de dados (Firebird):

SELECT RDB$RELATION_NAME FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL;


Listar as views do banco de dados (Firebird):

SELECT RDB$RELATION_NAME FROM RDB$RELATIONS
WHERE NOT RDB$VIEW_BLR IS NULL;


Obter o valor de um generator:

Para obter o valor de um generator use a função GEN_ID do InterBase/FireBird. 

A sintaxe é: 
GEN_ID(NomeDoGenerator, Incremento);

Exemplos

GEN_ID(Gen_Cliente_Codigo, 1);
GEN_ID(Gen_Cliente_Codigo, 0);

Reiniciar a contagem de um generator:

Para re-iniciar a contagem de um generator execute o comando abaixo.
SET GENERATOR TO X;

Excluir generator (Firebird):

DROP GENERATOR NOME_DO_GENERATOR;

Trocar o tipo de um campo (FireBird):

ALTER TABLE <Table1> ALTER <Campo> TYPE <Tipo do Campo>

Excluir código-fonte de stored procedure (Interbase/FireBird):

UPDATE RDB$PROCEDURES SET RDB$PROCEDURE_SOURCE = 'deletado';

Usando um For Select dentro da StoredProcedure no FireBird/Interbase:

create procedure SP_RETORNO(PCOD INTEGER)
returns (COD INTEGER, NOME VARCHAR(30),
VALOR NUMERIC(15,4))

as
begin
for select CODIGO, NOME from CLIENTES
where CODIGO = :PCOD
into :COD, :NOME do
begin

   select VALOR from VALORES
   where CODIGO = :COD
   into :VALOR;
   if ((VALOR IS NULL) or (VALOR = 0)) then
   VALOR = 1;
   suspend;

end;
end

Como traduzir as mensagens do Delphi

Boa tarde,
Abaixo uma dica valiosa de como traduzir as mensagens que o delphi retorna, após identificar uma operação ilegal.
O arquivo das mensagens que você deverá traduzir está em \Arquivos de Programas\ Borland\ Delphixx\ Source\ Vcl\ Consts.pas.
Traduza as mensagens normalmente. Depois de alterar o arquivo, eu salvo uma cópia na pasta \bin e na pasta \lib. O programa já funciona com os alertas traduzidos.
Você deverá traduzir também o arquivo DBConsts.pas que contém as mensagens relativas a componentes database.