segunda-feira, 22 de julho de 2013
Repositório do Delphi
Fonte: www.activedelphi.com.br
O repositório do Delphi é um local para armazenamento de objetos, como formulários e projetos, que facilita o compartilhamento desses objetos por vários projetos. Quando você clica em File|New... para criar um novo objeto, você pode escolher um dos itens do repositório.
Acrescentando um formulário ao repositório
Abra um projeto DPR, e dentro dele o formulário "Form" (Form1.pas). Esse formulário está sendo compartilhado dentro do mesmo projeto, mas se você quiser reutilizá-lo em outros projetos, pode acrescentá-lo ao repositório.
Para isso, clique com o botão direito e em Add to Repository. Você deve informar o título do item, uma descrição e qual a página onde ele será inserido (se você digitar um nome de página que não existe, uma nova será criada), além do seu nome para indicar qual o autor desse item. Opcionalmente você pode escolher um ícone que será usado para representar o item. Para o exemplo digite o seguinte:
Title: Formulário para uma tabela
Description: Formulário de banco de dados para uma tabela
Page: Forms (default)
Author: seu nome
O botão "Browse" permite você procurar um ícone , para representar sua classe de formulário, caso não informe ele irá mostrar o seguinte ícone . Clique Ok. O novo item será adicionado ao repositório. Agora crie um novo projeto com File|New Application e veremos como o item pode ser reutilizado.
Formas de criar novos objetos
Se você clicar em File|New... e na página "Forms", você verá que o novo item ("Formulário para uma tabela") está dentro do repositório. Agora ele está disponível em qualquer projeto, permitindo criar novos formulários a partir dele.
Existem três opções para criar novos objetos a partir do repositório: copiar [copy] o item, herdar [inherit] do item (criar uma nova classe derivada) ou usar [use] o item diretamente.
Se você marcar a opção "Copy" e clicar Ok, o Delphi cria uma cópia separada do objeto original que está no repositório. Qualquer alteração no original posteriormente não vai afetar essa cópia e qualquer alteração na cópia é independente do que está no repositório. Note que a unidade do formulário não foi salva e está em memória como "Unit2". Isso permite você salvar com um nome qualquer.
A opção "Inherit" (herdar) faz diferente: faz uma referência ao original (ou seja, acrescenta o formulário original dentro do projeto) e cria uma nova classe derivada da original, TForm1. O novo formulário será chamado de 'FormBase1', com a classe 'TFormBase1'. A unidade do formulário não foi salva ainda. Nesse caso, qualquer alteração no original, que está no repositório, será herdada pela classe derivada.
A opção "Use" não copia o objeto original, mas compartilha com o projeto atual. Nesse caso, alterações feitas no item dentro do projeto afetam o item no repositório e vice-versa. Se vários projetos usarem o mesmo item, todos eles compartilham o mesmo item.
Adicionando um projeto ao repositório
Para reutilizar um projeto inteiro, você pode acrescentá-lo ao repositório com o menu Project|Add to Repository... e informar a descrição do item como antes.
Gerenciando o repositório
Para gerenciar as páginas do repositório e os itens de cada página, você pode clicar em Tools|Repository. Na caixa de diálogo você pode criar, renomear ou excluir uma página do repositório (você só pode excluir se ela estiver vazia). É possível também mudar a ordem das páginas.
Você pode mover os itens entre páginas arrastando o item da lista da esquerda e soltando sobre a página desejada. Também é possível renomear ou alterar características de um item ou excluir o item.
Compartilhando o repositório numa equipe
Quando uma equipe de desenvolvedores trabalha em conjunto, é importante que eles possam compartilhar o repositório, de forma que novos itens adicionados a ele estejam disponíveis para toda a equipe.
Para compartilhar o repositório, você deve usar um diretório na rede que seja acessível a todos os desenvolvedores. Por exemplo, se G: é uma letra de drive que aponta para a rede, você pode usar G:\REPOS. Você deve também copiar os arquivos do repositório do Delphi para esse diretório.
Os arquivos do repositório do Delphi são armazenados num subdiretório OBJREPOS, abaixo do diretório onde o Delphi foi instalado (geralmente C:\Arquivos de Programas\Borland\Delphi6). Além desses arquivos, o Delphi usa um arquivo de texto chamado DELPHI32.DRO, localizado no subdiretório BIN do Delphi.
Para compartilhar o repositório na rede, faça o seguinte:
• Crie um diretório compartilhado (e.g. G:\REPOS). Verifique que todos os desenvolvedores têm acesso a ele e usam a mesma letra de drive;
• Copie o repositório de um computador para o diretório compartilhado (G:\REPOS), ou seja, todos os arquivos do subdiretório OBJREPOS do Delphi, mais DELPHI32.DRO, do subdiretório BIN;
• Em cada um dos computadores, no Delphi, clique em Tools|Environment Options. Na página Preferences Em "Shared Repository", digite o caminho do diretório compartilhado.
Agora lembre-se que qualquer alteração ou acréscimo feito por um desenvolvedor afeta todos os outros. É importante também notar que quando você quiser compartilhar um objeto, ele deve ser salvo num diretório compartilhado também, acessível a todos (por exemplo, G:\BIBLIOTECAS).
Autor : Celso Rodrigues
Contato : celso@finta.com.br
segunda-feira, 17 de junho de 2013
Mainmenu e popupmenu personalizados utilizando canvas (muito simples)
Fonte: www.planetadelphi.com.br
Olá Pessoal!!!
Bom estou aqui com mais uma dica que interessa a muitas pessoas! Personalizar
uma aplicação sem utilizar componentes externos.
Estaremos Pesonalizando os Menus de Nossa aplicação.
Mas antes quero esclarecer algumas coisas para quem esta procurando por isso:
-A dica é para personalizar os Menus da aplicação, tanto MainMenu quanto popupMenu.
-Para quem utiliza Delphi 7 (Exemplo) pode utilizar os Componentes ActionMainMenuBar e
ActionManager para fazer alguns MainMenus bacanas(em breve mostrarei passo-a-passo como
utilizar estes componentes que são muito legais de trabalhar).
-Neste exemplo estarei trabalhando com Canvas!
Então... Mãos à Obra!!!!
Neste exemplo que faremos utilizarei o Componentes MainMenu mas o que vai ser aplicado nele
pode ser sem problemas aplicado para um popupmenu.
Vamos deixar os nossos menus com uma aparência bem legal!.
Eventos Utilizados no componente: onDrawItem, onMeasureItem.
1º- Crie uma nova aplicação.
2º- Coloqueno formulario o componente MainMenu (Standard Palette).
3º- Ative a propriedade OwnerDraw do componente MainMenu.
3º- Abra o "Editor de Menus" dando 2 clique no componente e crie 1 menu.
(insira Caption, Name...)
4º- Acesse o Evento onDrawItem de deste item do Menu e vamos implementar o seguinte código:
}
procedure TForm1.Arquivo1DrawItem(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
begin
//Pinta a opção
if Selected then //verifica se o item está selecionado
BEGIN
ACanvas.Brush.Color := $00EFD3C6; //cor de fundo do item (Lembrando que podemos printar um Imagem).
// Canv.Brush.Color := clAppWorkSpace;
ACanvas.Rectangle(Arect); //Desenharemos uma retangulo em todo o Item selecionado.
ACanvas.pen.Color:=$00C66931; //seta a cor da borda do retangulo.
InflateRect (ARect, -1,-1);
end
else
ACanvas.Brush.Color:=clMenu; //se não estiver selecionado o item coloca a cor normal do item.
//--> dietrich 01/02/2007
//coloca o texto
ACanvas.pen.Color:=clBlack; //cor
ACanvas.TextRect(ARect,ARect.Left+5, ARect.Top+1,'Sair');//local onde sera escrito o texto ARect
end;
quinta-feira, 18 de abril de 2013
[Básico] - Tabela temporária com ClientDataSet – Conceito
Uma das vantagens de um fórum de programação é observar as dúvidas mais frequentes dos usuários e tentar ajudá-los de uma forma mais prática. Dessa vez, notei que muitos desenvolvedores têm dificuldades em compreender, criar e manipular tabelas temporárias no Delphi utilizando ClientDataSet. Além de ser um recurso muito útil, trabalhar com tabelas temporárias não exige conhecimentos avançados de programação.
Preparado pra mais um pequeno tutorial sobre desenvolvimento?
Preparado pra mais um pequeno tutorial sobre desenvolvimento?
Tabela temporária? O que é isso?
Também conhecida como “tabela virtual”, uma tabela temporária é capaz de armazenar registros em memória sem a necessidade de estar conectada a um banco dados, diferentes das tabelas físicas, que armazenam os dados em disco. Os registros da tabela temporária são apagados automaticamente quando a aplicação é encerrada ou quando se utiliza um comando próprio pra isso, no qual veremos no próximo artigo. Um grande recurso da tabela temporária é permitir manipular estes dados em memória, como inclusões, alterações, exclusões e filtros, tal como podemos fazer com tabelas físicas no banco de dados.
Mas qual a vantagem de utilizar uma tabela temporária no meu projeto?
Bom, depende do tipo de projeto que você está desenvolvendo. Tabelas temporárias, em linhas gerais, são úteis para trabalhar com dados locais na aplicação de forma dinâmica. Por exemplo, em um ambiente master/detail, uma tabela temporária pode armazenar os registros filhos antes mesmo do registro mestre ser gravado no banco de dados.
Ainda não entendi. Poderia dar um exemplo?
Claro que sim.
Imagine que estamos desenvolvendo um sistema para controle de vendas.
No nosso banco de dados, teremos as seguintes tabelas relacionadas à venda:
-- Tabela VENDAS
COD_VENDA
DATA
COD_CLIENTE
TOTAL
-- Tabela ITENS
COD_VENDA (chave estrangeira referenciando a tabela VENDAS)
COD_PRODUTO
QTDE
VALOR
TOTAL
Agora, suponha que iremos gravar uma nova venda no sistema com os seguintes dados:
COD_VENDA = 1
DATA = 15/02/2013
COD_CLIENTE = 20
TOTAL = ?
Ué, cadê o total?
Você deve concordar que, para informar o valor total, é necessário adicionar os itens, ou seja, precisamos somá-los para calcular o valor total da venda, não é? Por outro lado, para adicionar os itens precisamos do código da venda, já que as duas tabelas são relacionadas por uma chave estrangeira:
(ITENS.COD_VENDA = VENDAS.COD_VENDA).
Agora raciocine comigo: se tentarmos adicionar um item sem o código da venda ou com o código de uma venda que (ainda) não existe, receberemos o erro de “violação de chave estrangeira”, visto que, na verdade, tentaríamos adicionar um registro filho sem a existência do registro pai.
Pois bem, e para obtermos o código da venda, precisamos primeiro gravá-la no banco de dados, certo? Mas espere aí… conforme vimos acima, não temos o valor total pra gravar a venda!
E então entramos em um impasse:
- Não podemos gravar primeiro a venda, pois não temos os itens
- Não podemos gravar primeiro os itens, pois não temos a venda
E agora? Já sei! Vamos gravar a venda sem o valor total!
Muitos desenvolvedores utilizam essa “técnica”, se é que podemos chamá-la assim. Aplicando à nossa realidade, gravamos a venda sem o valor total, apenas para obter o código da venda. Dessa forma, podemos gravar os itens da venda normalmente, e após gravá-los, calculamos o valor total e alteramos o registro da venda, atualizando o total. Em um contexto procedimental, ficaria dessa forma:
Gravar a venda sem o valor total
Obter o código da venda gravada
Gravar os itens utilizando o código da venda obtido
Somar os itens para calcular o total
Editar a venda e atualizar o valor total
Observe que para cada venda será necessário fazer duas operações na tabela de vendas: uma de inserção e outra para alteração. Eu, particularmente, não sou de acordo com esse procedimento.
Em um exemplo, imagine que gravamos a venda, mas ao começar a adicionar os itens, a energia é cortada ou o usuário decide fechar a tela por algum motivo. Obviamente o registro ficará incompleto, já que teremos uma venda sem itens gravada no banco de dados. Tecnicamente, será um registro mestre sem registros filhos.
No caso da energia acabar, o problema pode ainda se agravar um pouco mais. Ao reiniciar o sistema, o usuário irá gerar uma nova venda, visto que, aos olhos do usuário, a outra venda não foi gravada. No fim da história haverá 2 vendas idênticas no sistema: uma sem itens (perdida) e outra válida.
Mas neste caso é só excluir essa venda incompleta, não é?
Sim, pode ser. Mas para isso, você terá que implementar um controle eficiente no seu sistema para identificar esses registros problemáticos. E também, lembre-se que cada vez que isso ocorrer, o código da venda será perdido (“pulado”) no banco de dados.
Aí prepare-se para receber algumas ligações do usuário perguntando:
“Por quê o sistema pulou o número da venda?”
“A venda nº X sumiu do sistema…”
“Tem uma venda aqui sem itens!”
Certo, e qual a sugestão para resolver isso?
Opa, chegou aonde eu queria!
Amigos, todos os problemas citados acima podem ser resolvidos utilizando tabelas temporárias! Durante a inclusão da venda, ao invés de gravarmos os itens no banco de dados, iremos gravá-los em uma tabela temporária. Se a energia acabar, nada será afetado, já que nenhuma alteração foi feita no banco de dados.
Este será o nosso procedimento:
Inserir os itens na tabela temporária;
Ao gravar a venda, os itens da tabela temporária serão “copiados” para a tabela física, tudo em um mesmo método.
Desta maneira, iremos reduzir bastante a possibilidade de uma venda ficar incompleta, visto que a gravação da venda e os itens da venda acontecerão praticamente ao mesmo tempo. E o melhor: durante a inclusão da venda não faremos nenhuma operação no banco de dados, somente na gravação.
Firemonkey: substituição da tecla TAB por tecla ENTER
Antes de tudo, gostaria de deixar claro que esta é uma dica básica; porém alguns encontram dificuldades nesse assunto, então estou aqui com o intuito de esclarecimento. Ultimamente tenho visto algumas dicas na internet de substituição da tecla tab pela tecla enter, porém muitas dicas não funcionam perfeitamente, pulando muitas vezes dos “tedit” para o próximo componente, mas ainda há a possibilidade de o caso ser um botão e ter um comando no evento “onclick”, o comando no “onclick” não ser executado. Pois bem, tenho uma dica aqui que vai funcionar perfeitamente, em ambos aspectos: tanto no salto nos controls, como sem perder os eventos onclick dos botões.
No Evento OnKeyDown do Form digite os comandos abaixo:
begin
if Key = vkReturn then
begin
Key := vkTab;
KeyDown(Key, KeyChar, Shift);
end;
end;
Dica básica mas muito útil, espero que tenham gostado!
No Evento OnKeyDown do Form digite os comandos abaixo:
begin
if Key = vkReturn then
begin
Key := vkTab;
KeyDown(Key, KeyChar, Shift);
end;
end;
Dica básica mas muito útil, espero que tenham gostado!
quarta-feira, 2 de janeiro de 2013
Trabalhando com POO na prática
Fonte: www.activedelphi.com.br
Depois de abrirmos o tema para que todos pudessem opinar, iremos começar a criar nossa série de artigos, segue abaixo a descrição de nosso sistema.
Peço a todos que pretendem colaborar de alguma forma que enviem um e-mail para mim para que possamos facilitar o contato e agilizarmos o processo de publicação dos artigos. Segue meu e-mail, rboaro@gmail.com.
Fica difícil mensurarmos quantos artigos iremos desenvolver sobre o tema, pois desenvolver uma aplicação por menor que seja requer bastante tempo ,muitas coisas precisam ser definidas. Sendo assim iniciamos descrevendo as funcionalidades básicas do sistema, por favor comentem (por e-mail) e sugiram alterações se acharem necessário.
Objetivo do Sistema: Processar vendas de um determinado estabelecimento, quando falo processar vendas, estou me referindo a controlar o estoque dos produtos, e ter as funcionalidades básicas de controle, como por exemplo, gerar títulos a receber , efetuar lançamentos no caixa, quando a venda for a vista etc.
Cadastros que serão criados:
> Cidades
> Clientes
> Produtos
> Pedidos
> Titulos a Receber
Seria interessante criarmos tambem outros cadastros, como por exemplo cadastro de Titulos a Pagar, mas nesse caso precisaríamos criar um cadastro de lançamento de notas fiscais de entrada o que pode ser feito baseado nos exemplos que iremos desenvolver.
> Cidades
> Clientes
> Produtos
> Pedidos
> Titulos a Receber
Seria interessante criarmos tambem outros cadastros, como por exemplo cadastro de Titulos a Pagar, mas nesse caso precisaríamos criar um cadastro de lançamento de notas fiscais de entrada o que pode ser feito baseado nos exemplos que iremos desenvolver.
Banco de dados utilizado: depois de muitas opiniões e como é de costume divergentes, pois cada um de nós simpatiza com um determinado banco de dados, como costumo dizer, "o melhor banco de dados é aquele que dominamos e sabemos utilizar o máximo das suas funcionalidades". Dessa forma pensei em criarmos classes de acesso ao Firebird e ao Sql Server Express (free).
Driver de acesso ao banco: esse não abro mão de usar dbExpress que é o que há de melhor nas ultimas versões do Delphi.
Versão do Delphi utilizada: Delphi XE2, mas me coloco a disposição para auxiliá-los a adaptar o fonte para outras versões.
Versão do Delphi utilizada: Delphi XE2, mas me coloco a disposição para auxiliá-los a adaptar o fonte para outras versões.
Frequência dos artigos publicados: no mínimo um por semana, se possível mais, mas como todos temos nossos compromissos a cumprir, deixamos aqui acordado que não podemos passar uma semana sem publicar nada.
Acredito que os principais itens foram citados. Sendo assim mãos a obra.
Opção online para mpressão e Re-Impressão de DANFE
Fonte: www.activedelphi.com.br
Alguma vez você já precisou imprimir ou re-imprimir um Documento Auxiliar de Nota Fiscal Eletrônica - DANFE?!
É claro que você pode entrar no seu sistema ERP e solicitar uma re-impressão... mas e se você não estiver na sua empresa?! e se o DANFE foi emitido por um fornecedor?!
Dois projetos interessantes e gratuitos estão disponíveis na internet para que possamos imprimir e re-imprimir DANFEs a partir do arquivo XML da NFe ou da chave de acesso da nota, são eles:
www.webdanfe.com.br/danfe/index.html
www.imprimirdanfe.com.br
É claro que você pode entrar no seu sistema ERP e solicitar uma re-impressão... mas e se você não estiver na sua empresa?! e se o DANFE foi emitido por um fornecedor?!
Dois projetos interessantes e gratuitos estão disponíveis na internet para que possamos imprimir e re-imprimir DANFEs a partir do arquivo XML da NFe ou da chave de acesso da nota, são eles:
www.webdanfe.com.br/danfe/index.html
www.imprimirdanfe.com.br
Tipos Genéricos no Delphi
Fonte: www.activedelphi.com.br
Hoje irei falar um pouco sobre tipos genéricos no delphi.
Um tipo genérico no Delphi pode ser definido por qualquer tipo padrão (string, integer, boolean) ou um tipo criado especificamente para sua aplicação.
Como isto é feito???
Defino uma classe Tvalor onde T é o tipo que a classe irá implementar.
Exemplo de Classe genérica:
TValor = class
FValor: T;
end;
Exemplo de utilização da classe:
Procedure teste();
Var
oTexto: Tvalor;
begin
oTexto := TValor.Create;
try
oTexto.Valor := ‘isto é um teste’;
finally
oTexto.Destroy;
oTexto := Nil;
end;
end;
Vamos pensar agora que nem sempre iremos ler o valor diretamente, como exemplo uma lista de objetos (não iremos implementar aqui, mas apenas como ajuda para interpretação OK?), como saberemos o tipo a ser tratado?
Simples, vamos mudar a implementação da classe!
Exemplo:
unit Model.ValorUnit;
interface
uses
System.TypInfo;
type
TValor = class
private
FValor: T;
FTipo: TTypeKind;
function GetValor: T;
procedure SetValor(const Value: T);
function GetTipo: TTypeKind;
public
procedure AfterConstruction; override;
property Valor: T read GetValor write SetValor;
property Tipo: TTypeKind read GetTipo;
end;
implementation
{ TValor }
procedure TValor.AfterConstruction;
var
Info: PTypeInfo;
begin
Info := System.TypeInfo(T);
try
if Info <> nil then
FTipo := Info^.Kind;
finally
Info := nil;
end;
end;
function TValor.GetTipo: TTypeKind;
begin
inherited;
result := FTipo;
end;
function TValor.GetValor: T;
begin
result := FValor;
end;
procedure TValor.SetValor(const Value: T);
begin
FValor := Value;
end;
end.
Nesta segunda implementação (ou alteração) a classe Tvalor agora possui dois campos, Fvalor e Ftipo.
Fvalor irá receber o valor própriamente dito, seja ele string integer ou qualquer outro, enquanto que Ftipo ira receber o tipo de dados que esta sendo utilizado dentro da classe e por consequencia no campo Fvalor.
Para definir o campo Ftipo, utilizei o procedimento AfterConstruction, este procedimento herdado da classe Tobject é chamado após o último construtor da classe ser executado. Segue abaixo o texto do Help do Delphi para melhor entendimento:
“Responds after the last constructor has executed.
AfterConstruction is called automatically after the object's last constructor has executed. Do not call it explicitly in your applications.
The AfterConstruction method implemented in TObject does nothing. Override this method when creating a class that performs an action after the object is created. For example, TCustomForm overrides AfterConstruction to generate an OnCreate event.”.
Neste procedimento, a nossa classe com o auxílio da System.TypInfo busca o tipo repassado ao criar um objeto do tipo Tvalor retornando o TtypeKind.
Tipos de TtypeKind:
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray, tkUString, tkClassRef, tkPointer, tkProcedure).
Porque não usar a RTTI do Delphi?
No caso de Classes Genéricas, a RTTI não consegue achar a classe com o tipo especificado através da RTTI, não podendo retornar a classe e não retornando a classe, não se pode definir o tipo de dado da propriedade.
Um tipo genérico no Delphi pode ser definido por qualquer tipo padrão (string, integer, boolean) ou um tipo criado especificamente para sua aplicação.
Como isto é feito???
Defino uma classe Tvalor
Exemplo de Classe genérica:
TValor
FValor: T;
end;
Exemplo de utilização da classe:
Procedure teste();
Var
oTexto: Tvalor
begin
oTexto := TValor
try
oTexto.Valor := ‘isto é um teste’;
finally
oTexto.Destroy;
oTexto := Nil;
end;
end;
Vamos pensar agora que nem sempre iremos ler o valor diretamente, como exemplo uma lista de objetos (não iremos implementar aqui, mas apenas como ajuda para interpretação OK?), como saberemos o tipo a ser tratado?
Simples, vamos mudar a implementação da classe!
Exemplo:
unit Model.ValorUnit;
interface
uses
System.TypInfo;
type
TValor
private
FValor: T;
FTipo: TTypeKind;
function GetValor: T;
procedure SetValor(const Value: T);
function GetTipo: TTypeKind;
public
procedure AfterConstruction; override;
property Valor: T read GetValor write SetValor;
property Tipo: TTypeKind read GetTipo;
end;
implementation
{ TValor
procedure TValor
var
Info: PTypeInfo;
begin
Info := System.TypeInfo(T);
try
if Info <> nil then
FTipo := Info^.Kind;
finally
Info := nil;
end;
end;
function TValor
begin
inherited;
result := FTipo;
end;
function TValor
begin
result := FValor;
end;
procedure TValor
begin
FValor := Value;
end;
end.
Nesta segunda implementação (ou alteração) a classe Tvalor
Fvalor irá receber o valor própriamente dito, seja ele string integer ou qualquer outro, enquanto que Ftipo ira receber o tipo de dados que esta sendo utilizado dentro da classe e por consequencia no campo Fvalor.
Para definir o campo Ftipo, utilizei o procedimento AfterConstruction, este procedimento herdado da classe Tobject é chamado após o último construtor da classe ser executado. Segue abaixo o texto do Help do Delphi para melhor entendimento:
“Responds after the last constructor has executed.
AfterConstruction is called automatically after the object's last constructor has executed. Do not call it explicitly in your applications.
The AfterConstruction method implemented in TObject does nothing. Override this method when creating a class that performs an action after the object is created. For example, TCustomForm overrides AfterConstruction to generate an OnCreate event.”.
Neste procedimento, a nossa classe com o auxílio da System.TypInfo busca o tipo repassado ao criar um objeto do tipo Tvalor
Tipos de TtypeKind:
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray, tkUString, tkClassRef, tkPointer, tkProcedure).
Porque não usar a RTTI do Delphi?
No caso de Classes Genéricas, a RTTI não consegue achar a classe com o tipo especificado através da RTTI, não podendo retornar a classe e não retornando a classe, não se pode definir o tipo de dado da propriedade.
quarta-feira, 26 de dezembro de 2012
Desenhar Um Ícone (bitmap) Em Células do Dbgrid
A dica abaixo serve para desenhar um ícone(bitmap) em cada célula de um dbgrid de acordo com o valor de um determinado campo da tabela... Ex: temos uma tabela "sexo" com o campo "sexo" que guarda os valores "M" para masculino e "F" para feminino. Então podemos fazer o dbgrid mostrar uma ícone(bitmap) de um homem ou um de uma mulher ao invés dos valores "M" e "F"...
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
Icon: TBitmap;
begin
Icon := TBitmap.Create;
if (Column.FieldName = 'SHARES') then
begin
with DBGrid1.Canvas do
begin
Brush.Color := clWhite;
FillRect(Rect);
if (Table1.FieldByName('SHARES').Value > 4500) then
ImageList1.GetBitmap(1, Icon)
else
ImageList1.GetBitmap(0, Icon);
Draw(round((Rect.Left + Rect.Right - Icon.Width) / 2), Rect.Top, Icon);
end;
end;
end;
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
Icon: TBitmap;
begin
Icon := TBitmap.Create;
if (Column.FieldName = 'SHARES') then
begin
with DBGrid1.Canvas do
begin
Brush.Color := clWhite;
FillRect(Rect);
if (Table1.FieldByName('SHARES').Value > 4500) then
ImageList1.GetBitmap(1, Icon)
else
ImageList1.GetBitmap(0, Icon);
Draw(round((Rect.Left + Rect.Right - Icon.Width) / 2), Rect.Top, Icon);
end;
end;
end;
Copiando Arquivos Via Programação
Function CopiaArquivo(scrname,destname:string):byte;
var
source,destination:file;
buffer:array[1..1024] of byte;
readcnt,writecnt:word;
pname,dname,fname,ename:String;
{ USO: R:=COPIAARQUIVO('C:\diretorio\FILE.EXT','C:\diretorio\FILE.EXT'); Devolve 0=Ok, 1=Erro no Origem, 2=Erro no Destino, 3=Disco Cheio }
begin
AssignFile(source,scrname);
Try
Reset(source,1);
Except
CopiaArquivo:=1;
Exit;end;If destname[length(destname)]='\' then
begin
pname:=scrname;
destname:=destname+separa(scrname,'\',Ocorre(scrname,'\')+1);
end;
AssignFile(destination,destname);
Try
Rewrite(destination,1);
Except
CopiaArquivo:=2;
Exit;
end;
Repeat
BlockRead(source,buffer,sizeof(buffer),readcnt);
Try
BlockWrite(destination,buffer,readcnt,writecnt);
Except
CopiaArquivo:=3; {Disco Cheio?}
Exit;
end;
until (readcnt=0) or (writecnt<>readcnt);
CloseFile(destination);
CloseFile(source);
CopiaArquivo:=0;
end;
var
source,destination:file;
buffer:array[1..1024] of byte;
readcnt,writecnt:word;
pname,dname,fname,ename:String;
{ USO: R:=COPIAARQUIVO('C:\diretorio\FILE.EXT','C:\diretorio\FILE.EXT'); Devolve 0=Ok, 1=Erro no Origem, 2=Erro no Destino, 3=Disco Cheio }
begin
AssignFile(source,scrname);
Try
Reset(source,1);
Except
CopiaArquivo:=1;
Exit;end;If destname[length(destname)]='\' then
begin
pname:=scrname;
destname:=destname+separa(scrname,'\',Ocorre(scrname,'\')+1);
end;
AssignFile(destination,destname);
Try
Rewrite(destination,1);
Except
CopiaArquivo:=2;
Exit;
end;
Repeat
BlockRead(source,buffer,sizeof(buffer),readcnt);
Try
BlockWrite(destination,buffer,readcnt,writecnt);
Except
CopiaArquivo:=3; {Disco Cheio?}
Exit;
end;
until (readcnt=0) or (writecnt<>readcnt);
CloseFile(destination);
CloseFile(source);
CopiaArquivo:=0;
end;
Comparar dois arquivos textos
procedure TForm1.Button1Click(Sender: TObject);
var
filename1 : string;
filename2 : string;
begin
filename1 := Edit1.Text;
filename2 := Edit2.Text;
compfile(filename1, filename2);
showmessage('Veja o resultado no arquivo c:Tempdiff.txt');
end;
procedure tform1.compfile(filename1, filename2 : string);
var
f1 : system.textfile;
f2 : system.textfile;
diff : system.textfile;
buf1 : string;
buf2 : string;
l : integer;
begin
assignfile(f1, filename1);
assignfile(f2, filename2);
assignfile(diff, 'c:Tempdiff.txt');
reset(f1);
reset(f2);
rewrite(diff);
l := 1;
while not eof(f1) do
begin
readln(f1, buf1);
readln(f2, buf2);
if not (compstr(buf1, buf2) )then
begin
writeln(diff, 'line: '+ inttostr(l) + '-' + buf1);
writeln(diff, 'line: '+ inttostr(l) + '-' + buf2);
writeln(diff, ' ');
end;
inc(l);
end;
closefile(f1);
closefile(f2);
closefile(diff);
end;
function tform1.compstr(s1, s2 : string) : boolean;
var
i : integer;
btemp : boolean;
begin
btemp := true;
if (length(s1) <> length(s2)) then begin
btemp := false;
end{if}
else begin
for i:= 1 to length(s1) do begin
if (s1[i] <> s2[i]) then begin
btemp := false;
exit;
end;{if}
end;{for}
end;{else}
result := btemp;
end;
var
filename1 : string;
filename2 : string;
begin
filename1 := Edit1.Text;
filename2 := Edit2.Text;
compfile(filename1, filename2);
showmessage('Veja o resultado no arquivo c:Tempdiff.txt');
end;
procedure tform1.compfile(filename1, filename2 : string);
var
f1 : system.textfile;
f2 : system.textfile;
diff : system.textfile;
buf1 : string;
buf2 : string;
l : integer;
begin
assignfile(f1, filename1);
assignfile(f2, filename2);
assignfile(diff, 'c:Tempdiff.txt');
reset(f1);
reset(f2);
rewrite(diff);
l := 1;
while not eof(f1) do
begin
readln(f1, buf1);
readln(f2, buf2);
if not (compstr(buf1, buf2) )then
begin
writeln(diff, 'line: '+ inttostr(l) + '-' + buf1);
writeln(diff, 'line: '+ inttostr(l) + '-' + buf2);
writeln(diff, ' ');
end;
inc(l);
end;
closefile(f1);
closefile(f2);
closefile(diff);
end;
function tform1.compstr(s1, s2 : string) : boolean;
var
i : integer;
btemp : boolean;
begin
btemp := true;
if (length(s1) <> length(s2)) then begin
btemp := false;
end{if}
else begin
for i:= 1 to length(s1) do begin
if (s1[i] <> s2[i]) then begin
btemp := false;
exit;
end;{if}
end;{for}
end;{else}
result := btemp;
end;
Abrir arquivos com aplicativo associado
Inclua a unit SHELLAPI na clausula uses do seu form.
procedure TForm1.ExecFile(F: String);
var
r: String;
begin
case ShellExecute(Handle, nil, PChar(F), nil, nil, SW_SHOWNORMAL) of
ERROR_FILE_NOT_FOUND: r := 'The specified file was not found.';
ERROR_PATH_NOT_FOUND: r := 'The specified path was not found.';
ERROR_BAD_FORMAT: r := 'The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).';
SE_ERR_ACCESSDENIED: r := 'Windows 95 only: The operating system denied access to the specified file.';
SE_ERR_ASSOCINCOMPLETE: r := 'The filename association is incomplete or invalid.';
SE_ERR_DDEBUSY: r := 'The DDE transaction could not be completed because other DDE transactions were being processed.';
SE_ERR_DDEFAIL: r := 'The DDE transaction failed.';
SE_ERR_DDETIMEOUT: r := 'The DDE transaction could not be completed because the request timed out.';
SE_ERR_DLLNOTFOUND: r := 'Windows 95 only: The specified dynamic-link library was not found.';
SE_ERR_NOASSOC: r := 'There is no application associated with the given filename extension.';
SE_ERR_OOM: r := 'Windows 95 only: There was not enough memory to complete the operation.';
SE_ERR_SHARE: r := 'A sharing violation occurred.';
else
Exit;
end;
ShowMessage(r);
end;
Utilize a função assim:
procedure TForm1.Button1Click(Sender: TObject);
begin
ExecFile('c:\windows\ladrilhos.bmp');
end;
procedure TForm1.ExecFile(F: String);
var
r: String;
begin
case ShellExecute(Handle, nil, PChar(F), nil, nil, SW_SHOWNORMAL) of
ERROR_FILE_NOT_FOUND: r := 'The specified file was not found.';
ERROR_PATH_NOT_FOUND: r := 'The specified path was not found.';
ERROR_BAD_FORMAT: r := 'The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).';
SE_ERR_ACCESSDENIED: r := 'Windows 95 only: The operating system denied access to the specified file.';
SE_ERR_ASSOCINCOMPLETE: r := 'The filename association is incomplete or invalid.';
SE_ERR_DDEBUSY: r := 'The DDE transaction could not be completed because other DDE transactions were being processed.';
SE_ERR_DDEFAIL: r := 'The DDE transaction failed.';
SE_ERR_DDETIMEOUT: r := 'The DDE transaction could not be completed because the request timed out.';
SE_ERR_DLLNOTFOUND: r := 'Windows 95 only: The specified dynamic-link library was not found.';
SE_ERR_NOASSOC: r := 'There is no application associated with the given filename extension.';
SE_ERR_OOM: r := 'Windows 95 only: There was not enough memory to complete the operation.';
SE_ERR_SHARE: r := 'A sharing violation occurred.';
else
Exit;
end;
ShowMessage(r);
end;
Utilize a função assim:
procedure TForm1.Button1Click(Sender: TObject);
begin
ExecFile('c:\windows\ladrilhos.bmp');
end;
Função que preenche strings com qualquer caracter a esquerda ou a direita.
É só incluir a função em sua biblioteca ou na unit que vc estiver usando e chama-la passando os parametros corretos.
A função preenche strings com qualquer caracter a esquerda ou direita retornando a string formatada e no tamanho que vc quiser.
Função Preenche
Preenche uma string com o caracter informado
Parametros Tipo Objetivo
wStr1 String A string a ser preenchida
wStr2 String O caracter que vai preencher a string
wStr3 String D = Direita e E = Esquerda
wTama Integer O tamanho total da string a ser retornada
Retorno String Retorna a string informada preenchida
com o caracter escolhido no tamanho
definido
function Preenche(wStr1, wStr2, wStr3: String; wTama: Integer): String;
var v : Integer;
begin
wStr1 := Trim(wStr1);
Result := '';
for v:=1 to wTama-Length(wStr1) do Result := Result + wStr2;
if wStr3 = 'E' then
Result := Result + wStr1
else
Result := wStr1 + Result;
end;
A função preenche strings com qualquer caracter a esquerda ou direita retornando a string formatada e no tamanho que vc quiser.
Função Preenche
Preenche uma string com o caracter informado
Parametros Tipo Objetivo
wStr1 String A string a ser preenchida
wStr2 String O caracter que vai preencher a string
wStr3 String D = Direita e E = Esquerda
wTama Integer O tamanho total da string a ser retornada
Retorno String Retorna a string informada preenchida
com o caracter escolhido no tamanho
definido
function Preenche(wStr1, wStr2, wStr3: String; wTama: Integer): String;
var v : Integer;
begin
wStr1 := Trim(wStr1);
Result := '';
for v:=1 to wTama-Length(wStr1) do Result := Result + wStr2;
if wStr3 = 'E' then
Result := Result + wStr1
else
Result := wStr1 + Result;
end;
quinta-feira, 22 de novembro de 2012
Ocultar Processo do Gerenciador de Tarefas do Windows
Insira este fonte abaixo dentro de um Timer.
Defina o intervalo do timer para 1.
É uma gambiarra! mas uma boa alternativa para evitar usar DLLs ou criar Hooks
Declare na Uses Commctrl;
var
dwSize,dwNumBytes,PID,hProc: Cardinal;
PLocalShared,PSysShared: PlvItem;
h: THandle;
iCount,i: integer;
szTemp: string;
begin
{Pega o Handle da ListView}
h:=FindWindow('#32770',nil);
h:=FindWindowEx(h,0,'#32770',nil);
h:=FindWindowEx(h,0,'SysListView32',nil);
{Pega o número de itens da ListView}
iCount:=SendMessage(h, LVM_GETITEMCOUNT,0,0);
for i:=0 to iCount-1 do
begin
{Define o tamanho de cada item da ListView}
dwSize:=sizeof(LV_ITEM) + sizeof(CHAR) * MAX_PATH;
{Abre um espaço na memória do NOSSO programa para o PLocalShared}
PLocalShared:=VirtualAlloc(nil, dwSize, MEM_RESERVE + MEM_COMMIT, PAGE_READWRITE);
{Pega o PID do processo taskmgr}
GetWindowThreadProcessId(h,@PID);
{Abre o processo taskmgr}
hProc:=OpenProcess(PROCESS_ALL_ACCESS,false,PID);
{Abre um espaço na memória do taskmgr para o PSysShared}
PSysShared:=VirtualAllocEx(hProc, nil, dwSize, MEM_RESERVE OR MEM_COMMIT, PAGE_READWRITE);
{Define as propriedades do PLocalShared}
PLocalShared.mask:=LVIF_TEXT;
PLocalShared.iItem:=0;
PLocalShared.iSubItem:=0;
PLocalShared.pszText:=LPTSTR(dword(PSysShared) + sizeof(LV_ITEM));
PLocalShared.cchTextMax:=20;
{Escreve PLocalShared no espaço de memória que abriu no taskmgr}
WriteProcessMemory(hProc,PSysShared,PLocalShared,1024,dwNumBytes);
{Pega o texto to item i e passa pro PSysShared}
SendMessage(h,LVM_GETITEMTEXT,i,LPARAM(PSysShared));
{Passa o PSysShared para o PLocalShared}
ReadProcessMemory(hProc,PSysShared,PLocalShared,1024,dwNumBytes);
{Passa o texto do Item para szTemp}
szTemp:=pchar(dword(PLocalShared)+sizeof(LV_ITEM));
{Se esse texto contiver a string proc deleta o item}
if LowerCase(szTemp) = 'rarryeditor.exe' then
ListView_DeleteItem(h,i);
{Libera os espaços de memória utilizados}
VirtualFree(pLocalShared, 0, MEM_RELEASE);
VirtualFreeEx(hProc, pSysShared, 0, MEM_RELEASE);
{Fecha o handle do processo}
CloseHandle(hProc);
end;
end;
Defina o intervalo do timer para 1.
É uma gambiarra! mas uma boa alternativa para evitar usar DLLs ou criar Hooks
Declare na Uses Commctrl;
var
dwSize,dwNumBytes,PID,hProc: Cardinal;
PLocalShared,PSysShared: PlvItem;
h: THandle;
iCount,i: integer;
szTemp: string;
begin
{Pega o Handle da ListView}
h:=FindWindow('#32770',nil);
h:=FindWindowEx(h,0,'#32770',nil);
h:=FindWindowEx(h,0,'SysListView32',nil);
{Pega o número de itens da ListView}
iCount:=SendMessage(h, LVM_GETITEMCOUNT,0,0);
for i:=0 to iCount-1 do
begin
{Define o tamanho de cada item da ListView}
dwSize:=sizeof(LV_ITEM) + sizeof(CHAR) * MAX_PATH;
{Abre um espaço na memória do NOSSO programa para o PLocalShared}
PLocalShared:=VirtualAlloc(nil, dwSize, MEM_RESERVE + MEM_COMMIT, PAGE_READWRITE);
{Pega o PID do processo taskmgr}
GetWindowThreadProcessId(h,@PID);
{Abre o processo taskmgr}
hProc:=OpenProcess(PROCESS_ALL_ACCESS,false,PID);
{Abre um espaço na memória do taskmgr para o PSysShared}
PSysShared:=VirtualAllocEx(hProc, nil, dwSize, MEM_RESERVE OR MEM_COMMIT, PAGE_READWRITE);
{Define as propriedades do PLocalShared}
PLocalShared.mask:=LVIF_TEXT;
PLocalShared.iItem:=0;
PLocalShared.iSubItem:=0;
PLocalShared.pszText:=LPTSTR(dword(PSysShared) + sizeof(LV_ITEM));
PLocalShared.cchTextMax:=20;
{Escreve PLocalShared no espaço de memória que abriu no taskmgr}
WriteProcessMemory(hProc,PSysShared,PLocalShared,1024,dwNumBytes);
{Pega o texto to item i e passa pro PSysShared}
SendMessage(h,LVM_GETITEMTEXT,i,LPARAM(PSysShared));
{Passa o PSysShared para o PLocalShared}
ReadProcessMemory(hProc,PSysShared,PLocalShared,1024,dwNumBytes);
{Passa o texto do Item para szTemp}
szTemp:=pchar(dword(PLocalShared)+sizeof(LV_ITEM));
{Se esse texto contiver a string proc deleta o item}
if LowerCase(szTemp) = 'rarryeditor.exe' then
ListView_DeleteItem(h,i);
{Libera os espaços de memória utilizados}
VirtualFree(pLocalShared, 0, MEM_RELEASE);
VirtualFreeEx(hProc, pSysShared, 0, MEM_RELEASE);
{Fecha o handle do processo}
CloseHandle(hProc);
end;
end;
Desabilitar/Habilitar componentes de um form pela sua classe.
Segue procedure que permite habilitar/desabilitar componentes de determinado form de acordo com as classes passadas como parâmetro. É possível determinar quais controles não serão afetados.
procedure EnableDisableControls(Form: TForm; ClassComponents: array of TControlClass; Exclude: array of TControl; State: Boolean);
var
i,
j,
z: Integer;
begin
for I := 0 to Form.ComponentCount -1 do
for j := Low(ClassComponents) to High(ClassComponents) do
if High(Exclude) > -1 then
begin
for z := Low(Exclude) to High(Exclude) do
if (Form.Components[i] is ClassComponents[j]) and (Form.Components[i] <> Exclude[z]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end
else
if (Form.Components[i] is ClassComponents[j]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end;
Exemplo de uso:
EnableDisableControls(Form1, [TEdit, TMemo, TCheckBox, TRadioButton], [CheckBox1], (not Edit2.Enabled));
Neste exemplo acima todos os edits, memos, checkboxes e radiobuttons serão desabilitados/habilitados, com exceção do checkbox1.
procedure EnableDisableControls(Form: TForm; ClassComponents: array of TControlClass; Exclude: array of TControl; State: Boolean);
var
i,
j,
z: Integer;
begin
for I := 0 to Form.ComponentCount -1 do
for j := Low(ClassComponents) to High(ClassComponents) do
if High(Exclude) > -1 then
begin
for z := Low(Exclude) to High(Exclude) do
if (Form.Components[i] is ClassComponents[j]) and (Form.Components[i] <> Exclude[z]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end
else
if (Form.Components[i] is ClassComponents[j]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end;
Exemplo de uso:
EnableDisableControls(Form1, [TEdit, TMemo, TCheckBox, TRadioButton], [CheckBox1], (not Edit2.Enabled));
Neste exemplo acima todos os edits, memos, checkboxes e radiobuttons serão desabilitados/habilitados, com exceção do checkbox1.
terça-feira, 13 de novembro de 2012
XE3 e o que está por vir!
Fonte: www.activedelphi.com.br
Tenho certeza de que muitos de vocês já estão sabendo dos eventos do
World Tour (http://www.embarcadero.com/world-tour) quando acontecerá o
lançamento do DelphiXE3. Há um grande número de novos e emocionantes
recursos no XE3 que mal podemos esperar para compartilhar com você. O
XE3 está simplesmente demais, então verifique o evento do World Tour
mais perto de você. Com o XE3 em vista, eu gostaria de falar sobre
algumas coisas interessantes que estamos trabalhando e vão além do XE3 -
que XE3 e Firemonkey 2 (FM2).
Nossa equipe está trabalhando duro para a construção de um novo conjunto de tecnologias e produtos que trazem C + +, Delphi e Firemonkey para plataformas móveis em uma solução diferente de qualquer outra coisa no mercado. Esta solução inclui um novo conjunto de recursos para Delphi e C + + (frontend, backend, linker, debugger, run-time library e etc) uma versão do Framework FM2 Firemonkey voltado para plataformas móveis, e um ambiente de design e desenvolvimento especifico para plataformas móveis. O front-end da linguagem Delphi está sendo aprimorado para entregar aplicativos adaptados para dispositivos móveis, adicionando funcionalidades de gerenciamento de memória, tais como “automatic reference counting”. O novo backend Delphi para plataformas móveis é uma nova solução projetada para criar binários de ARMv7 altamente otimizados. Isso inclui um novo linker e debugger para gerenciar os novos formatos de objetos e informações de debug. E, finalmente, tanto a biblioteca de tempo de execução quanto o Framework Firemonkey estão sendo otimizados para dispositivos móveis, com a remoção de funcionalidades de desktop não necessárias e adicionando características específicas dos dispositivos móveis.
Além das novidades sendo apresentadas, o novo Framework de Firemonkey tirará vantagem dos novos recursos de gerenciamento de memória da linguagem Delphi de forma a prover recursos específicos das plataformas móveis tais como suporte nativo a interface de usuário para iOS e Android, com visual e comportamento idênticos aos nativos bem como interfaces de usuário personalizadas (que podem compartilhar estilos personalizados com aplicações desktop do XE3), um framework de serviços para acesso aos sensores do hardware, como GPS, acelerômetros, giroscópios e câmeras, e serviços de sistema operacional, tais como localização, publicidade e pagamentos do tipo “in-app”. Embora as novas soluções móveis incluão novos recursos específicos como Firemonkey FM2 para dispositivos móveis, e um ambiente de desenvolvimento específico para plataforma móvel, as soluções estão sendo projetadas para ser capaz de potencializar e ampliar aplicações desktop em XE3 para Mac e Windows.
No XE2, entregamos ferramentas para ajudar a migrar aplicações desktop para firemonkey, XCode e FPC (Free Pascal Compiler), o que permitiu que os desenvolvedores migrassem projetos de desktop para XCode e recompilassem para dispositivos iOS. Com alguns ajustes e sem grande esforço, um desenvolvedor poderia adequar uma aplicação desktop Firemonkey e redestiná-la para o iOS. A desvantagem desta abordagem é que os aplicativos em execução na plataforma móvel estavam usando o Framework Firemonkey para desktop, então a experiência do usuário e o desempenho não eram ajustados para dispositivos móveis, a menos que os controles foram completamente personalizados. Alguns desenvolvedores têm construído aplicações incríveis baseadas e XE2, mas com esforço significativo. Além disso, não havia nenhuma integração entre a IDE e o Xcode. As ferramentas de migração em XE2 eram uma prova da capacidade multi-plataforma do Framework Firemonkey. Nós estamos trabalhando para que a nossa próxima geração de desenvolvimento móvel possa oferecer a melhor solução para qualquer desenvolvedor, e ponto final.
Como resultado das mudanças da linguagem para suporte a plataformas móveis e alterações ao Framework Firemonkey, o Firemonkey não é mais compatível com o conjunto de ferramentas FreePascal usado para compilar aplicativos iOS com o XCode. Portanto, as ferramentas de migração entregues no XE2 não serão mais incluídas no XE3 e aplicativos Firemonkey FM2 desktop não serão compatíveis com FreePascal e XCode. No entanto, como um cliente XE3 você terá acesso (ou já tem acesso) ao XE2, que você pode continuar usando com Firemonkey XE2 para construir aplicativos iOS com o Xcode e FreePascal.
Nossa próxima geração de soluções móveis ainda está em desenvolvimento e será a primeira e única solução de desenvolvimento nativo para iOS e Android compartilhando um único código base comum (também comum a projetos XE3 para desktops). Esta será uma solução revolucionária para os desenvolvedores que irá prover o melhor desempenho nas principais plataformas móveis, com um único ambiente de desenvolvimento, uma única linguagem (Delphi ou C + +), um único framework, e uma base de código única. Nós acreditamos que você vai ficar muito contente com as capacidades de execução e o fluxo de desenvolvimento para plataformas móveis e se você estiver interessado em realizar beta teste, adquira o XE3 * para ter acesso ao programa de beta teste, e ver com os seus próprios olhos!
* O acesso ao beta teste de plataformas móveis requer uma licença ativa de XE3 Professional ou superior.
Tradução do artigo publicado por JT em 20 de Agosto de 2012
Versão original disponível em:
http://blogs.embarcadero.com/jtembarcadero/2012/08/20/xe3-and-beyond/
Nossa equipe está trabalhando duro para a construção de um novo conjunto de tecnologias e produtos que trazem C + +, Delphi e Firemonkey para plataformas móveis em uma solução diferente de qualquer outra coisa no mercado. Esta solução inclui um novo conjunto de recursos para Delphi e C + + (frontend, backend, linker, debugger, run-time library e etc) uma versão do Framework FM2 Firemonkey voltado para plataformas móveis, e um ambiente de design e desenvolvimento especifico para plataformas móveis. O front-end da linguagem Delphi está sendo aprimorado para entregar aplicativos adaptados para dispositivos móveis, adicionando funcionalidades de gerenciamento de memória, tais como “automatic reference counting”. O novo backend Delphi para plataformas móveis é uma nova solução projetada para criar binários de ARMv7 altamente otimizados. Isso inclui um novo linker e debugger para gerenciar os novos formatos de objetos e informações de debug. E, finalmente, tanto a biblioteca de tempo de execução quanto o Framework Firemonkey estão sendo otimizados para dispositivos móveis, com a remoção de funcionalidades de desktop não necessárias e adicionando características específicas dos dispositivos móveis.
Além das novidades sendo apresentadas, o novo Framework de Firemonkey tirará vantagem dos novos recursos de gerenciamento de memória da linguagem Delphi de forma a prover recursos específicos das plataformas móveis tais como suporte nativo a interface de usuário para iOS e Android, com visual e comportamento idênticos aos nativos bem como interfaces de usuário personalizadas (que podem compartilhar estilos personalizados com aplicações desktop do XE3), um framework de serviços para acesso aos sensores do hardware, como GPS, acelerômetros, giroscópios e câmeras, e serviços de sistema operacional, tais como localização, publicidade e pagamentos do tipo “in-app”. Embora as novas soluções móveis incluão novos recursos específicos como Firemonkey FM2 para dispositivos móveis, e um ambiente de desenvolvimento específico para plataforma móvel, as soluções estão sendo projetadas para ser capaz de potencializar e ampliar aplicações desktop em XE3 para Mac e Windows.
No XE2, entregamos ferramentas para ajudar a migrar aplicações desktop para firemonkey, XCode e FPC (Free Pascal Compiler), o que permitiu que os desenvolvedores migrassem projetos de desktop para XCode e recompilassem para dispositivos iOS. Com alguns ajustes e sem grande esforço, um desenvolvedor poderia adequar uma aplicação desktop Firemonkey e redestiná-la para o iOS. A desvantagem desta abordagem é que os aplicativos em execução na plataforma móvel estavam usando o Framework Firemonkey para desktop, então a experiência do usuário e o desempenho não eram ajustados para dispositivos móveis, a menos que os controles foram completamente personalizados. Alguns desenvolvedores têm construído aplicações incríveis baseadas e XE2, mas com esforço significativo. Além disso, não havia nenhuma integração entre a IDE e o Xcode. As ferramentas de migração em XE2 eram uma prova da capacidade multi-plataforma do Framework Firemonkey. Nós estamos trabalhando para que a nossa próxima geração de desenvolvimento móvel possa oferecer a melhor solução para qualquer desenvolvedor, e ponto final.
Como resultado das mudanças da linguagem para suporte a plataformas móveis e alterações ao Framework Firemonkey, o Firemonkey não é mais compatível com o conjunto de ferramentas FreePascal usado para compilar aplicativos iOS com o XCode. Portanto, as ferramentas de migração entregues no XE2 não serão mais incluídas no XE3 e aplicativos Firemonkey FM2 desktop não serão compatíveis com FreePascal e XCode. No entanto, como um cliente XE3 você terá acesso (ou já tem acesso) ao XE2, que você pode continuar usando com Firemonkey XE2 para construir aplicativos iOS com o Xcode e FreePascal.
Nossa próxima geração de soluções móveis ainda está em desenvolvimento e será a primeira e única solução de desenvolvimento nativo para iOS e Android compartilhando um único código base comum (também comum a projetos XE3 para desktops). Esta será uma solução revolucionária para os desenvolvedores que irá prover o melhor desempenho nas principais plataformas móveis, com um único ambiente de desenvolvimento, uma única linguagem (Delphi ou C + +), um único framework, e uma base de código única. Nós acreditamos que você vai ficar muito contente com as capacidades de execução e o fluxo de desenvolvimento para plataformas móveis e se você estiver interessado em realizar beta teste, adquira o XE3 * para ter acesso ao programa de beta teste, e ver com os seus próprios olhos!
* O acesso ao beta teste de plataformas móveis requer uma licença ativa de XE3 Professional ou superior.
Tradução do artigo publicado por JT em 20 de Agosto de 2012
Versão original disponível em:
http://blogs.embarcadero.com/jtembarcadero/2012/08/20/xe3-and-beyond/
Como tornar um servidor datasnap rest compatível com o cache off-line do HTML5
Fonte: www.activedelphi.com.br
Por padrão, servidores DataSnap stand-alone WebBroker não permitem usar o "novo" HTML5 Aplicação manifesto de arquivo de cache.
Enquanto eu estava me preparando os conteúdos e as demonstrações do meu "HTML5 e aplicação web DataSnap desenvolvimento" eu configurei os componentes DataSnap para suportar esse recurso HTML5. Há apenas uma alteração a fazer ao "WebApplication REST" padrão gerado pelo assistente.
No WebModuleUnit há o componente utilizado
TWebFileDispatcher. Este componente tem as WebFileExtensions propriedade
que é uma coleção de valores-chave contendo todas as extensões de
arquivos permitidas relacionada com o mime-type.
A imagem abaixo mostra o que precisa ser configurado:
domingo, 7 de outubro de 2012
Ping Delphi7 com IdIcmpClient
Estamos aqui novamente com uma dica utilizando-se somente do componente, sem sua ação visual:
Pingando com IdIcmpClient - Delphi 7
Siga as instruções abaixo:
// declare na seção uses:
IdBaseComponent, IdComponent, IdRawBase, IdRawClient, IdIcmpClient // Uses para IdIcmpClient
// caso queira publicar esta função não se esqueça de inclui-la na seção
// private ou na seção public, ou diretamente na parte de procedures e function da unit
// e em caso de um formulario visual, colocar a classe do formulário, ex:
//Function TForm1.Ping(HostName: String): boolean;
Function Ping(HostName: String): boolean;
var
i, Soma, BytesRecebidos : Integer;
PckEntregue : Array[1..3] of Integer;
ICMP : TIdIcmpClient;
begin
try
ICMP := TIdIcmpClient.Create(nil);
try
ICMP.Host := HostName;
ICMP.ReceiveTimeout := 500;
ICMP.Ping;
if ICMP.ReplyStatus.BytesReceived > 0 then
result := true
else
result := false;
except
result := false;
end;
finally
ICMP.Destroy;
end;
end;
Pingando com IdIcmpClient - Delphi 7
Siga as instruções abaixo:
// declare na seção uses:
IdBaseComponent, IdComponent, IdRawBase, IdRawClient, IdIcmpClient // Uses para IdIcmpClient
// caso queira publicar esta função não se esqueça de inclui-la na seção
// private ou na seção public, ou diretamente na parte de procedures e function da unit
// e em caso de um formulario visual, colocar a classe do formulário, ex:
//Function TForm1.Ping(HostName: String): boolean;
Function Ping(HostName: String): boolean;
var
i, Soma, BytesRecebidos : Integer;
PckEntregue : Array[1..3] of Integer;
ICMP : TIdIcmpClient;
begin
try
ICMP := TIdIcmpClient.Create(nil);
try
ICMP.Host := HostName;
ICMP.ReceiveTimeout := 500;
ICMP.Ping;
if ICMP.ReplyStatus.BytesReceived > 0 then
result := true
else
result := false;
except
result := false;
end;
finally
ICMP.Destroy;
end;
end;
Pesquisando em banco Firebird desconsiderando acentos - case insensitive
Se você já tem um banco dados Firebird em uso e não quer Mudar a estrutura do banco ou tabela (não quer usar Character set e não quer usar collate) , pode usar o seguinte comando para fazer pesquisas case-insensitive (ou seja, localizar dados estando gravados em minúsculas ou maiúsculas)
Exemplo:
select nomecampo from NOMETABELA
where nomecampo containing 'ALIENAÇÃO'
or nomecampo containing 'alienação'
Nesta caso ele irá localizar se no campo da tabela estiver gravado uma das seguintes opções:
alienação
ALIENAÇÃO
Alienação
AliEnação
AlieNação
Atenção - NÃO Irá Achar:
alienaÇão (Ç maiúscula e resto minusculo)
ParaSe você já tem um banco dados Firebird em uso e não quer Mudar a estrutura do banco ou tabela (não quer usar Character set e não quer usar collate) , pode usar o seguinte comando para fazer pesquisas case-insensitive:
Exemplo:
select nomecampo from NOMETABELA
where nomecampo containing 'ALIENAÇÃO'
or nomecampo containing 'alienação'
Nesta caso ele irá localizar se no campo da tabela estiver gravado uma das seguintes opções:
alienação
ALIENAÇÃO
Alienação
AliEnação
AlieNação
Atenção - NÃO Irá Achar:
alienaÇão (Ç maiúscula e resto minusculo)
Exemplo:
select nomecampo from NOMETABELA
where nomecampo containing 'ALIENAÇÃO'
or nomecampo containing 'alienação'
Nesta caso ele irá localizar se no campo da tabela estiver gravado uma das seguintes opções:
alienação
ALIENAÇÃO
Alienação
AliEnação
AlieNação
Atenção - NÃO Irá Achar:
alienaÇão (Ç maiúscula e resto minusculo)
ParaSe você já tem um banco dados Firebird em uso e não quer Mudar a estrutura do banco ou tabela (não quer usar Character set e não quer usar collate) , pode usar o seguinte comando para fazer pesquisas case-insensitive:
Exemplo:
select nomecampo from NOMETABELA
where nomecampo containing 'ALIENAÇÃO'
or nomecampo containing 'alienação'
Nesta caso ele irá localizar se no campo da tabela estiver gravado uma das seguintes opções:
alienação
ALIENAÇÃO
Alienação
AliEnação
AlieNação
Atenção - NÃO Irá Achar:
alienaÇão (Ç maiúscula e resto minusculo)
Faixa de Notícias
Essa função tem com o intuito ter uma faixa de notícias, passando na tela.
Primeiro, precisaremos de um label, que colocarei o nome de lblNoticias e um timer que colocarei o nome TimerNoticia;
No TimerNoticia coloque o valor de "interval" para 100, mas caso ache muito rápido é só aumentar esse valor;
Você pode colocar o valor da opção "visible" do HorzScrollBar para "false";
Caso você utilize uma image como fundo e está esteja com o Align colocado para alClient, então você deverá colocar a seguinte linha de código no procedimento OnResize do Form:
Image1.Constraints.MaxWidth := Self.Width - 8;
Agora vamos ao que interessa, o código está preparado para rodar no caso de você pegar o que quer deixar como notícia no banco de dados, e então caso não tenha nada irá procurar no banco de 30 em 30 segundos, esse é o código para rodar a faixa de notícias:
procedure TForm1.TimerNoticiaTimer(Sender: TObject);
begin
DoubleBuffered := True;
if lblNoticias.Visible then
begin
lblNoticias.Left := lblNoticias.Left - 30;
end;
If ((lblNoticias.Left + lblNoticias.Width) <= 15) then
begin
lblNoticias.Caption := 'TESTE DE NOTÍCIAS';
if (lblNoticias.Caption <> EmptyStr) then
begin
lblNoticias.Left := Self.Width + 1;
lblNoticias.Caption := trim(lblNoticias.Caption) + ' *';
TimerNoticia.Enabled := True;
lblNoticias.Visible := True;
TimerNoticia.Interval := 100;
end
else
begin
lblNoticias.Visible := False;
TimerNoticia.Interval := 30000;
end;
end;
end;
Primeiro, precisaremos de um label, que colocarei o nome de lblNoticias e um timer que colocarei o nome TimerNoticia;
No TimerNoticia coloque o valor de "interval" para 100, mas caso ache muito rápido é só aumentar esse valor;
Você pode colocar o valor da opção "visible" do HorzScrollBar para "false";
Caso você utilize uma image como fundo e está esteja com o Align colocado para alClient, então você deverá colocar a seguinte linha de código no procedimento OnResize do Form:
Image1.Constraints.MaxWidth := Self.Width - 8;
Agora vamos ao que interessa, o código está preparado para rodar no caso de você pegar o que quer deixar como notícia no banco de dados, e então caso não tenha nada irá procurar no banco de 30 em 30 segundos, esse é o código para rodar a faixa de notícias:
procedure TForm1.TimerNoticiaTimer(Sender: TObject);
begin
DoubleBuffered := True;
if lblNoticias.Visible then
begin
lblNoticias.Left := lblNoticias.Left - 30;
end;
If ((lblNoticias.Left + lblNoticias.Width) <= 15) then
begin
lblNoticias.Caption := 'TESTE DE NOTÍCIAS';
if (lblNoticias.Caption <> EmptyStr) then
begin
lblNoticias.Left := Self.Width + 1;
lblNoticias.Caption := trim(lblNoticias.Caption) + ' *';
TimerNoticia.Enabled := True;
lblNoticias.Visible := True;
TimerNoticia.Interval := 100;
end
else
begin
lblNoticias.Visible := False;
TimerNoticia.Interval := 30000;
end;
end;
end;
Retorna IP de conexão com a Internet ( IP do Roteador )
Funciona perfeitamente, mas requer que você tenha instalado os componentes Indy em seu Delphi.
Detalhe: Essa função pode pausar o processo do seu aplicativo até que ela receba resposta ou acabe o tempo limite
Function TIPreal : String;
var
IP : TIdHTTP;
Temporario : String;
Endereco : String;
X : Integer;
begin
try IP := TIdHTTP.Create(nil);
with IP do begin
Host := 'checkip.dyndns.org';
Temporario := Get('checkip.dyndns.org');
For X := 1 to Length(Temporario) do
if (Temporario[X] in ['0'..'9']) or (Temporario[X] = '.') then
Endereco := Endereco + Temporario[X];
end;
Result := Trim(Endereco); IP.Free;
except
Result := 'ERRO';
end;
end;
Detalhe: Essa função pode pausar o processo do seu aplicativo até que ela receba resposta ou acabe o tempo limite
Function TIPreal : String;
var
IP : TIdHTTP;
Temporario : String;
Endereco : String;
X : Integer;
begin
try IP := TIdHTTP.Create(nil);
with IP do begin
Host := 'checkip.dyndns.org';
Temporario := Get('checkip.dyndns.org');
For X := 1 to Length(Temporario) do
if (Temporario[X] in ['0'..'9']) or (Temporario[X] = '.') then
Endereco := Endereco + Temporario[X];
end;
Result := Trim(Endereco); IP.Free;
except
Result := 'ERRO';
end;
end;
segunda-feira, 10 de setembro de 2012
Identar código no Delphi 7
Quem está começando a aprender Delphi 7 e já tem alguma familiaridade com alguma outra ferramenta de programação ou editor de textos, fora o bloco de notas, já está acostumado a identar seus códigos de forma que estes fiquem organizados para uma melhor manutenção posteriormente.
Se você é um dos que não identa, pode começar a se acostumar com esta técnica, que é praticamente exigida por alguns padrões lá fora e, como falei anteriormente, é de essencial para uma melhor manutenção e interpretação do código.
Mas o que é identar?
Dentro da computação, indentação é um termo aplicado ao código fonte de um programa para indicar que os elementos hierarquicamente dispostos têm o mesmo avanço relativamente à posição (y,0).
Na maioria das linguagens a indentação tem um papel meramente estético, tornando a leitura do código fonte muito mais fácil (read-friendly), porém é obrigatória em outras. Python, occam e Haskell, por exemplo, utilizam-se desse recurso tornando desnecessário o uso de certos identificadores de blocos ("begin" e/ou "end").
A verdadeira valia deste processo é visível em arquivos de código fonte extensos, não se fazendo sentir tanto a sua necessidade em arquivos pequenos (relativamente ao número de linhas)
Para qualquer programador, deve ser um critério a ter em conta, principalmente, por aqueles que pretendam partilhar o seu código com outros. A Indentação facilita também a modificação, seja para correção ou aprimoramento, do código fonte.
Identando no Delphi 7
Diferente dos outros editores, o Delphi 7 não permite o uso da TAB após a seleção do texto para identarmos aquele bloco, se fizermos isso, a linha selecionada é excluída!!
O comando para finalmente identar nosso código é: CTRL + SHIFT + i (para avançar o código, ou seja, mover pra a direita) e CTRL + SHIFT + u (para retroceder o código ou mover para a esquerda). Lembre-se de SELECIONAR o código antes de utililzar as teclas de atalho.
Se você é um dos que não identa, pode começar a se acostumar com esta técnica, que é praticamente exigida por alguns padrões lá fora e, como falei anteriormente, é de essencial para uma melhor manutenção e interpretação do código.
Mas o que é identar?
Dentro da computação, indentação é um termo aplicado ao código fonte de um programa para indicar que os elementos hierarquicamente dispostos têm o mesmo avanço relativamente à posição (y,0).
Na maioria das linguagens a indentação tem um papel meramente estético, tornando a leitura do código fonte muito mais fácil (read-friendly), porém é obrigatória em outras. Python, occam e Haskell, por exemplo, utilizam-se desse recurso tornando desnecessário o uso de certos identificadores de blocos ("begin" e/ou "end").
A verdadeira valia deste processo é visível em arquivos de código fonte extensos, não se fazendo sentir tanto a sua necessidade em arquivos pequenos (relativamente ao número de linhas)
Para qualquer programador, deve ser um critério a ter em conta, principalmente, por aqueles que pretendam partilhar o seu código com outros. A Indentação facilita também a modificação, seja para correção ou aprimoramento, do código fonte.
Identando no Delphi 7
Diferente dos outros editores, o Delphi 7 não permite o uso da TAB após a seleção do texto para identarmos aquele bloco, se fizermos isso, a linha selecionada é excluída!!
O comando para finalmente identar nosso código é: CTRL + SHIFT + i (para avançar o código, ou seja, mover pra a direita) e CTRL + SHIFT + u (para retroceder o código ou mover para a esquerda). Lembre-se de SELECIONAR o código antes de utililzar as teclas de atalho.
segunda-feira, 27 de agosto de 2012
Quebra textos e retorna frases do tamanho especificado
Quebra textos e cria frases do tamanho especificado, com um detalhe (não reparte as palavras) a função avalia se a palavra seguinte vai caber na frase caso contrario inclui na frase seguinte.
Fiz essa função na necessidade de atender regras de tamanho em comentarios de nota fiscal.
Function QuebraTextString(Texto : String; Largura : Integer):TStringList;
var
Original, Quebrado : TStringList;
i, x, esp : integer;
frase : String;
begin
Original := TStringList.Create;
Quebrado := TStringList.Create;
esp := Largura;
sBreakApart(Texto, ' ', Original);
frase := '';
for i := 0 to Original.Count-1 do begin
if Length(frase) = esp then begin
Quebrado.Add(frase);
frase := '';
end;
if( Length(frase + ' ' +Original.Strings[i]) > esp) then begin
Quebrado.Add(frase);
frase := '';
end;
frase := frase + ' '+Original.Strings[i];
if i = Original.Count-1 then begin
Quebrado.Add(frase);
end;
end;
result:= Quebrado;
end;
Fiz essa função na necessidade de atender regras de tamanho em comentarios de nota fiscal.
Function QuebraTextString(Texto : String; Largura : Integer):TStringList;
var
Original, Quebrado : TStringList;
i, x, esp : integer;
frase : String;
begin
Original := TStringList.Create;
Quebrado := TStringList.Create;
esp := Largura;
sBreakApart(Texto, ' ', Original);
frase := '';
for i := 0 to Original.Count-1 do begin
if Length(frase) = esp then begin
Quebrado.Add(frase);
frase := '';
end;
if( Length(frase + ' ' +Original.Strings[i]) > esp) then begin
Quebrado.Add(frase);
frase := '';
end;
frase := frase + ' '+Original.Strings[i];
if i = Original.Count-1 then begin
Quebrado.Add(frase);
end;
end;
result:= Quebrado;
end;
Desabilitar/Habilitar componentes de um form pela sua classe.
Segue procedure que permite habilitar/desabilitar componentes de determinado form de acordo com as classes passadas como parâmetro. É possível determinar quais controles não serão afetados.
procedure EnableDisableControls(Form: TForm; ClassComponents: array of TControlClass; Exclude: array of TControl; State: Boolean);
var
i,
j,
z: Integer;
begin
for I := 0 to Form.ComponentCount -1 do
for j := Low(ClassComponents) to High(ClassComponents) do
if High(Exclude) > -1 then
begin
for z := Low(Exclude) to High(Exclude) do
if (Form.Components[i] is ClassComponents[j]) and (Form.Components[i] <> Exclude[z]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end
else
if (Form.Components[i] is ClassComponents[j]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end;
Exemplo de uso:
EnableDisableControls(Form1, [TEdit, TMemo, TCheckBox, TRadioButton], [CheckBox1], (not Edit2.Enabled));
Neste exemplo acima todos os edits, memos, checkboxes e radiobuttons serão desabilitados/habilitados, com exceção do checkbox1.
procedure EnableDisableControls(Form: TForm; ClassComponents: array of TControlClass; Exclude: array of TControl; State: Boolean);
var
i,
j,
z: Integer;
begin
for I := 0 to Form.ComponentCount -1 do
for j := Low(ClassComponents) to High(ClassComponents) do
if High(Exclude) > -1 then
begin
for z := Low(Exclude) to High(Exclude) do
if (Form.Components[i] is ClassComponents[j]) and (Form.Components[i] <> Exclude[z]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end
else
if (Form.Components[i] is ClassComponents[j]) then (Form.Components[i] as ClassComponents[j]).Enabled := State;
end;
Exemplo de uso:
EnableDisableControls(Form1, [TEdit, TMemo, TCheckBox, TRadioButton], [CheckBox1], (not Edit2.Enabled));
Neste exemplo acima todos os edits, memos, checkboxes e radiobuttons serão desabilitados/habilitados, com exceção do checkbox1.
Pesquisa SQL de datas amarzenadas em Varchar
Olá Pessoal no meu banco de dado as datas estão gravadas em varhar, estava com dificuldades p/ manipular, em pesquisa pela net adaptei algumas coisas e deu certo.
Ai vai uma parte do codigo fonte.
procedure Tfrm_media_vendas.Label13Click(Sender: TObject);
begin
//=============== calcula total de vendas no mes de janeiro====================
frm_media_vendas.query1.Close;
frm_media_vendas.query1.sql.clear;
frm_media_vendas.query1.sql.add('select SUM(VL_TOT_ORC) from orcamentos');
frm_media_vendas.query1.sql.add ('where DT_ORC like "%01/'+(Edit2.Text)+'"');
frm_media_vendas.query1.sql.add ('ORDER by CD_ORC');
frm_media_vendas.query1.Open;
frm_media_vendas.DBGrid1.Refresh;
frm_media_vendas.Label13.Caption:=IntToStr(Query1.RecordCount);
frm_media_vendas.MaskEdit1.Text:='R$'+ floatTostr(frm_media_vendas.DBGrid1.SelectedField.AsCurrency);
//=====================fim do calculo==================================
//===================Total Orçamentos Janeiro=========================
frm_media_vendas.query1.Close;
frm_media_vendas.query1.sql.clear;
frm_media_vendas.query1.sql.add('select * from orcamentos');
frm_media_vendas.query1.sql.add ('where DT_ORC like "%01/'+(Edit2.Text)+'"');
frm_media_vendas.query1.sql.add ('ORDER by CD_ORC');
frm_media_vendas.query1.Open;
frm_media_vendas.DBGrid1.Refresh;
frm_media_vendas.Label13.Caption:=IntToStr(Query1.RecordCount);
//=========================fim da pesquisa===================
end;
Ai vai uma parte do codigo fonte.
procedure Tfrm_media_vendas.Label13Click(Sender: TObject);
begin
//=============== calcula total de vendas no mes de janeiro====================
frm_media_vendas.query1.Close;
frm_media_vendas.query1.sql.clear;
frm_media_vendas.query1.sql.add('select SUM(VL_TOT_ORC) from orcamentos');
frm_media_vendas.query1.sql.add ('where DT_ORC like "%01/'+(Edit2.Text)+'"');
frm_media_vendas.query1.sql.add ('ORDER by CD_ORC');
frm_media_vendas.query1.Open;
frm_media_vendas.DBGrid1.Refresh;
frm_media_vendas.Label13.Caption:=IntToStr(Query1.RecordCount);
frm_media_vendas.MaskEdit1.Text:='R$'+ floatTostr(frm_media_vendas.DBGrid1.SelectedField.AsCurrency);
//=====================fim do calculo==================================
//===================Total Orçamentos Janeiro=========================
frm_media_vendas.query1.Close;
frm_media_vendas.query1.sql.clear;
frm_media_vendas.query1.sql.add('select * from orcamentos');
frm_media_vendas.query1.sql.add ('where DT_ORC like "%01/'+(Edit2.Text)+'"');
frm_media_vendas.query1.sql.add ('ORDER by CD_ORC');
frm_media_vendas.query1.Open;
frm_media_vendas.DBGrid1.Refresh;
frm_media_vendas.Label13.Caption:=IntToStr(Query1.RecordCount);
//=========================fim da pesquisa===================
end;
Assinar:
Postagens (Atom)