Como criar pastas e mover arquivos(.jpeg) com o delphi?

Delphi

02/09/2010

Ola, gostaria de saber como mover arquivos de lugar e criar diretorios com o delphi. Para que?Eu estava fazendo meu programa com gravação das imagens em um banco de dados, mas estava ficando muito pesado e as imagens estavam dobrando de tamanho ou até mais no processo, o que estava gerando um alto lag no programa.O que quero tentar agora é o seguinte:Eu cadastro a casa de ID 243Apos salvar vou na opção de acrescentar imagem no imovelQuando adiciono a imagem caso não exista é criada a pasta "Fotos" e dentro dela a pasta "243"(Id da casa) e as imagens que eu for adicionando iram sendo copiadas para essa pasta, para exibir a imagem isarei o caminho "Fotos\"IDdaCasa"\foto1.jpeg".Concluindo para casa casa salva ja ser criada altomaticamente a pasta com com o ID da casa em "Fotos" e o programa armazena o caminho das fotos desse modo.
Bom, eu sei o que quero, mas não tenho a minima ideia de como fazer, alguem poderia me ajudar?
Artur Carlos

Artur Carlos

Curtidas 0

Respostas

Eriley Barbosa

Eriley Barbosa

02/09/2010

Vamos criar uma função para criar o subdiretório, visto que a pasta fotos é fixa:function CriaSubDir(const NomeSubDir: string): boolean;
var
  Caminho: string;
begin
  Caminho := 'C:\Fotos' + NomeSubDir;//Substitua 'C:\Fotos' pelo caminho que a subpasta deve ser criada
  if DirectoryExists(Caminho) then
    Result := true
  else
    Result := CreateDir(Caminho);
end;Exemplo de uso: No evento onclick do botão de inserir fotos digite: if not CriaSubDir(SuaQuery.FieldByName('CODiMOVEL').AsString) then
    ShowMessage('Não foi possível criar o sub-diretório ' +   SuaQuery.FieldByName('CODiMOVEL').AsString);   Faça funcionar esta parte, que depois fazemos funcionar a cópia do arquivo para a pasta criada.
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Esqueça meu post acima acredito que o que você quer é o código abaixo, apenas adapte-o a sua necessidade: var
  Origem, Destino, caminho: string;
begin
  caminho := 'C:\Fotos\' + SuaQuery.FieldByName('CODIMOVEL').AsString;
  if  not DirectoryExists(caminho) then
    CreateDir(caminho);
  if OpenPictureDialog1.Execute then
  begin
    //Aqui pego o caminho inteiro inclusive com o nome do arquivo
    origem := OpenPictureDialog1.FileName;
    //Aqui pego somente o nome do arquivo com a extenção
    Delete(Origem, 1, Length(ExtractFilePath(OpenPictureDialog1.FileName)));
    Destino := caminho + '\' + origem;
    CopyFile(PChar(Origem), PChar(Destino), False);
  end;
end;
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

  Funcionou, so tive que fazer uma mudança, a parte em negrito. Aparentemente ele so consegue criar uma pasta, não estava sendo criada nenhuma pasta, depois que tentei azer ele colocar antes apenas a pasta 'Fotos' começou a funcionar. Vlwvar
Origem, Destino, caminho: string;
begin
 if not DirectoryExists('C:\Fotos') then
  CreateDir('C:Fotos');
caminho := 'C:\Fotos\' + DM.ADOQImoveis.FieldByName('ID').AsString;
if not DirectoryExists(caminho) then
CreateDir(caminho);
if OpenPictureDialog1.Execute then
begin
//Aqui pego o caminho inteiro inclusive com o nome do arquivo
origem := OpenPictureDialog1.FileName;
//Aqui pego somente o nome do arquivo com a extenção
Delete(Origem, 1, Length(ExtractFilePath(OpenPictureDialog1.FileName)));
Destino := caminho + '\' + origem;
CopyFile(PChar(Origem), PChar(Destino), False);
end;
end;

Outra duvida, pra mandar o caminho da imagem pro BD é so criar uma tabela com ID(auto), codImovel(integer) e Foto(Texto) e jogar o OpenPictureDialog1.FileName; pra dentro da Foto? O DBImage vai ler o caminho e mostrar a imagem normalmente?
PS: Li o seu artigo, achei muito legal, vou até implementar em um programa mais simples que to fazendo e tem 8 forms diferentes de cadastro, fazer um unico form com botões e usar para todos os formularios fica muito mais pratico.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

Consegui gravar o caminho no BD, mas os DBImage não exibem mais as fotos de determinado Imovel, creio que seja porque o DataSource e DataField não sirvam mais ja qeu apontam para um caminho e não uma imagem como faziam antes.Eu adicionei 5 fotos e ficaram aparecendo 5 DBImages em branco no DBCtrlGrid, detalhe é que esses campos aparecem para qualquer imovel que eu tente alterar.Alguem poderia me ajudar? Como faço para as fotos aparecerem nos DBImages do DBCtrlGrid quando clico em X Imovel no DBGrid?
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Você tem que gravar o conteúdo da variavel destino. Quanto aos campos da tabela está correto, mas tem que ter um relacionamento entre esta tabela e a de imóveis, como fizemos com o clientdataset(masterSource, masterfield). Não há mais como usar o dbctrlgrid e nem o dbimage e nem o dbnavigator. Você vai ter de usar um dbgrid e um image, no evento afterscroll desta nova tabela, testar se não está em modo de inserção ou edição, se não estiver mostra a foto no image, usando o LoadFromFile do openpicturedialog, lembra como fizemos para inserir e editar a foto. Ha vai ter de testar se a foto gravada é jpg ou bmp, para exibir no image. Outra coisa não deixe o usuario editar o dbgrid, ele deve excluir a foto, editar ou inserir por meio de botões. O dbgrid deve apenas mostrar o campo foto, os outros não precisa.   Mãos a obra, tente fazer tudo que mencionei acima.   Uma dica comente o código antigo, pois, podemos aproveita-lo quase que 100%, onde tem um dbimage apenas troque por um image. Onde tem o clientDataset apenas troque por seu componente que está ligado a nova tabela.   Qualquer coisa poste o código aqui, para que eu possa altera-lo.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

  Hum, acho que não entendi, pensei que o DBGrid iria substituir o DBCtrlGrid mas ele so mostra o caminho da imagem, como farei para exibir todas as imagens do imovel X em algum local pequeno como fazia antes com o DBCtrlGrid? Pra mostrar todas as imagens em tamanho grande não se faz necessario mas acho o DBCtrlGrid de grande ajuda pro cliente ter certesa de que imagens ja gravou até o momento. O relacionamento eu tinha feito pelo proprio access mas não parece ter funcionado.Ta dificil, se jogo a imagem na DB ela aumenta 10x de tamanho e torna o processo inviavel, se uso caminho perco o DBCtrlGrid que é uma mão na roda.
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Sim o dbgrid vai substituir o dbctrlgrid, ao usuario navegar pelo dbgrid evento afterscroll da tabela as imagens vão sendo mostradas, uma de cada vez no image. Você não terá apenas a opção de mostrar todas as imagens de uma vez só.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

Fiz um pouco diferente mas funcionou, no afterscroll tava dando erro ae mudei pra OncellClick do DBgrid e coloquei
EDBImage1.Picture.LoadFromFile(DM.cdsFotosImoveisFoto.AsString);
  Uma duvida, tem como tirar a parte C:\Fotos e deixar mostrando somente o nome da foto no DBGridw nem que eu presise criar outro campo pra mostrar so o nome da foto.Agora para montar o Slide Show com as imagens em tamanho grande presiso de uma ajuda, como posso fazer as imagens irem pra frente e pra tras sem o DBNAVIGATOR?
GOSTEI 0
Renan Gouvea

Renan Gouvea

02/09/2010

Tive um problema semelhante para controlar as imagens,não to com o codigo aqui agora, mas tente isso..
procedure TForm.DBCtrlGridPaintPanel(DBCtrlGrid: TDBCtrlGrid; Index: Integer);begin  //TImage dentro do DBCtrlGrid e no evento PaintPanel carregar a imagem gravada no banco  Image1.Picture.LoadFromFile(ClientDataSet.FieldByName('CampoComEndereçoImagem').AsString);end;
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

No evento ongettext do campo que armazena o caminho da foto, digite: var
  i, posicao: Integer;
begin
  if not(sender.Isnull) then
  begin
    for i := 1 to Length(sender.asstring) do
    begin
      if (sender.asstring[i] in ['\']) then
        posicao := i;
    end;
    Text := Copy(Sender.Value, posicao + 1, Length(Sender.Value));
  end;
end;
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Tem que ser no afterscroll, eu disse para você testar: if not(cdsFotosimoveis in [dsEdit, dsInsert]) then   carrega a foto no image.   Fazendo isso até o dbnavigator funciona. Pois, o oncellclick só acontece se você for clicando com o mouse.   Pode tentar também no onclick do dbnavigator carregar a imagem.
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Tenta como o renan disse, também.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

@Renan funcionou, ta carregando todas as fotos no DBCtrlGrid mas quando vc clica em uma das fotos ela é sobreposta pela ultima foto gravada no registro, e como ja vem como se vc tivese clicado na primeira foto ela vem sempre errada mostrando a ultima imagem gravada em vez da primeira, se vc clica em outra foto ela muda pra ultima foto gravada e a anterir fica correta e assim por diante. Tem como alterar isso pra sempre mostrar a correta mesmo quando eu clico na imagem?@Eriley sua função funcionou certinho, ta mostrando so o nome da foto agora.Agora, como alternar entre as fotos com botões? quero simular um DBNavigator so com o avançar,voltar, ir pro final e ir pro inicio.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

  Opa, quando fiz o post acima ainda não tinha suas 3 respostas Eriley.Funcionou, o DBNavigator ta pegando agora, VLW.Agora é so fazer o DBCtrlGrid parar de ficar sobrepondo a foto que clico nele com a ultima imagem gravada no imovel. 
GOSTEI 0
Renan Gouvea

Renan Gouvea

02/09/2010

Aqui testei e não tive este problema, você usa algum evento ou componente diferente?usei um DBText e um Image no BDCtrlGrid, e coloquei um showMessage no onClick do Image e não aconteceu de a imagem ser trocada.
GOSTEI 0
Renan Gouvea

Renan Gouvea

02/09/2010

Enviei para o seu email em anexo o exemplo que usei para teste. (mindormod@hotmail.com)
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

  Manda pra mindormod@yahoo.com.br fazendo favor, o daqui cadastrei errado XD.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

Eu uso um EDBImage em vez do Image porque o EDB da Zoom ou ajusta a imagem pra qualquer tamanho.  O image se vc coloca uma imagem vertical de 400x900 ele estica a figura toda o EDB ajusta certinho deixando a imagem com as proporções originais.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

  O AfterScroll começo a dar erro direto agora, eu mando iniciar o programa ele começa a carregar e da um erro loco cheio de numero, e depois me aponta essa linha em Negrito. if not(cdsFotosImoveis.State in [dsEdit, dsInsert]) then
frmImovel.EDBImage3.Picture.LoadFromFile(cdsFotosImoveisfoto.AsString);
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

  Resolvi o problema da parte de Slides colocando no Onclick do DBNavigator o caminho da imagem, ae a cada vez que passo ele joga um novo caminho no EDBImage.
O CtrlGrid fico lagando muito a tela depois que testei colocar 30 imagens de 2MB nele por isso até ver porque do lag to dropando ele . Se ele so pega o caminho alguem sabe o motivo que pode estar gerando o lag?
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Não é só o caminho, ele vai buscar o arquivo no disco rigido para exibir no image.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

Ta explicado então, CtrlGrid pra muita foto não é viavel.

Eriley você saberia me dizer como fazer o relacionamento que você me mostro no ClientDataSet com o ADOQuery? Não tem o campo mastersource, masterfield, ect no ADOQuery.

É que to querendo jogar a tabela fotos no access pra ficar mais facil, agora que a tabela não carrega mais fotos não tem mais porque deixar ela separada em um arquivo .cds. Relacionei a tabela pelo access mas não funcionou, não sei porque.

Outra duvida, como posso fazer um IF pra saber se o imovel X tem Fotos ou não? Isso evitaria um erro que estou tendo quando clico em um imovel sem fotos.

Quero colocar assim,
IF (tem fotos) EDBImage recebe
 ADOQimobFotosFotos.ASString
ELSE
Exibe Mensagem('O Imovel XXX ainda não possui fotos').


GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Comm query é um pouco diferente: Na AdoQryImoveis em sua propriedade SQL, você deve ter a seguinte instrução: Select * From Imoveis E você deve ter  um DataSource talvez chamado de DsImoveis e conectado a AdoQryImoveis pela propriedade DataSet do DataSource. Este Datasource servirá de ponte entre as duas querys. E você deve ter  uma outra Query chamada de AdoQryFotos, na propriedade DataSource da AdoQryFotos iniciaremos o relacionamento, indicando o Datasource que está ligado ao outro DataSet (DsImoveis). O próximo passo é indicar a instrução sql de acesso na propriedade SQL: Select * From Fotos Where Cod_Imovel = :Cod_Imovel Cod_Imovel após os dois pontos deve ter o mesmo nome do campo código do imóvel da tabela de imóveis. Você achou estranho esta condição criada na instrução sql ? Deve estar se perguntando : Se é pra colocar um parâmetro para filtrar as fotos do imóvel via código eu não precisaria ter este trabalho todo ? Então eu lhe responderei, este parâmetro será automaticamente alimentado por causa do relacionamento entre as Querys através do DataSource, isto é, sempre que for filtrado um imóvel na AdoQryImoveis, automaticamente as fotos deste imóvel serão filtradas por conta do relacionamento. Isto não quer dizer que, em uma eventual manipulação (inclusão), as fotos serão automaticamente associadas ao imóvel em questão, a passagem do código do imóvel para as fotos deverá ser feito manualmente, isto geralmente é realizado no evento before post do AdoQryFotos. AdoQryFotosCod_Imovel.Value := AdoQryImoveisCodImovel.Value;   Sobre sua segunda pergunta, faça assim: IF not(AdoQryFotos.IsEmpty) then    EDBImage recebe ADOQimobFotosFotos.ASString
ELSE
  Exibe Mensagem('O Imovel XXX ainda não possui fotos'). Para que este código funcione as duas querys devem estar abertas no onshow do formulário. AdoQryImoveis.OPen; AdoQryFotos.Open;
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

Funcionou , brigadão Eriley.

Minha proxima duvida é como fazer um botão para sincronizar o banco de dados do meu programa com o mesmo programa em outro computador.

De modo abstrato queria montar algo mais ou menos assim.

Opção 1:Clica no Botão "Atualizar automatico".

If 'Caminho até o servidor= ON' então   // caminho iria até o arquivo do banco de dados do Access no Servidor
                                                              // EX: \\Servidor\Users\Public\Imob\Imobiliaria.mdb

Compara tabelas Servidor x PCFuncionario

Servidor Recebe registros novos que o funcionario possui

PCFuncionario recebe registros novos do servidor caso haja algum
                                                          
Copia Pasta C:\Imob\Fotos                     //Ideal seria copiar so as fotos novas mas acho que seria meio complexo

else
ShowMessage('O Servidor esta OFF')

Opção 2: CLica no Botão "Atualizar Manualmente".

Abre um OpenDialog e vc escolhe o caminho até um Arquivo do Acess do mesmo programa em outro computador

Copia os registros Novos
Copia pasta a pasta Fotos usando o caminho do OpenDialog ja que a pasta Fotos vai estar na mesma pasta do arquivo do Access
ShowMessage('Registro de Imoveis Atualizado').

--------------------------------------------

A parte de ficar copiando toda Pasta Imob\Fotos sempre não me parece boa mas não consigo pensar em uma solução melhor, caso alguem tenha ajudaria muito.

O arquivo do access da pra so copiar o arquivo todo e simplesmente substituir o do computador, mas seria pouco elegante e pratico ja que teria que limitar o acesso a cadastro de imoveis somente no Servidor, os outros somente poderiam visualizar os imoveis e seus dados.

Se houvese uma sincronização de dados de um programa com o outro so seria pego o que tem de novo não apagando os cadastros anteriores, e caso cada um cadastre-se imoveis diferentes em cada computador um novo funcionario teria apenas que sincronizar com os dados dos 5 funcionarios com o programa ou com o servidor que seria sempre mantido atualizado.


GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

Tem que fazer o seu programa funcionar em rede e depois ajustar a inserção das imagens para gravar direto numa pasta do servidor e ajustar o carregamento das imagens para ler do servidor e mostrar no image.   Primeiro vamos fazer funcionar o seu programa em rede e depois ajustamos a parte da imagem.    1º Coloque o banco de dados no servidor.
2º Compartilhe a pasta onde o mesmo se encontra.
3º Faça as maquinas q estao na rede enxergarem no servidor a pasta compartilhada
4º Configure o ADOconnection do seu projeto principal pra enxergar o banco de dados.
Veja o link abaixo: https://www.devmedia.com.br/articles/viewcomp_forprint.asp?comp=13139   Dica crie o arquivo udl no mesmo diretório do executável e após fazer as alterações no delphi e compilar o programa, va de máquina em máquina configurando o udl e depois abrindo o executável.   se fez esses passos todos e pra funcionar, sem problemas...ok
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

Esse metodo é interessante para uma rede de PCs, como eles são fixos sempre teriam acesso ao servidor, mas imagine Notebooks, no caso o corretor iria na casa do cliente e mostraria algumas opções para ele, seria necessario que o programa funciona-se com independencia do servidor, e o utilizase somente para atualizações.

O metodo que você descreveu vou usar nos PCs fixos que de fato é a melhor opção, mas nos Notebooks creio que teria que usar algo diferente que não dependese de estar conectado ao servidor.

O modo Simples creio que seria simplesmente fazer uma copia do Arquivos do Banco de dados e sempre substituir os existentes no Note, um mais elaborado seria acrescentar ao banco de dados do Note os registros novos e modificações, e no caso também copiar a pasta fotos.

Estou aberto a sugestões pro proglema do notebook sem rede
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

O modo mais simples é copiar o banco de dados e as fotos para o notebook do corretor e criar uma interface de consulta para ele, pois, se ele incluir dados ai vai ficar mais complicado de varrer registro por registro e ver se existe no servidor.
GOSTEI 0
Artur Carlos

Artur Carlos

02/09/2010

É vou criar um pro servidor com todas as funções, um para PCs na rede com todas as funções mas com o caminho pro banco de dados direcionado a uma pasta compartilhada ao servidor e um pra modo OFFLINE que copie os arquivos do servidor e so possa olhar os dados, sem modificar ou acrescentar nada.

O dos PCs na rede so me preocupa o conflito de cadastros, se 5 pessoas madam dados ao mesmo tempo iria dar pau nos IDs, o que me leva a crer que nos PCs seria ideial uma interface sem cadastro também.

Quando eu mando copiar um dados pelos delphi ele subistitui se ja tiver um igual na pasta em questão ou da problema? No windows ele pergunta se quer mesmo substituir por exemplo.
GOSTEI 0
Eriley Barbosa

Eriley Barbosa

02/09/2010

substitui, fizemos isso para as fotos lembra? Eu não me preocuparia com os ids, pois, quem se encarrega disso é o próprio access e ele gera o id na efetiva gravação do registro e não antecipadamente.
GOSTEI 0
POSTAR