
Micheus
Veteranos-
Total de itens
3.189 -
Registro em
-
Última visita
Tudo que Micheus postou
-
Ao atribuir um valor para seu Edit utilize a função FormatFloat('0.00', valor): Ex.: Edit1.Text := FormatFloat('0.00', 125.50); Para garantir que ao sair do campo, após o usuário digitar algo (numérico) você pode escrever no evento OnExit do seu edit algo mais ou menos assim: begin // esta parte é para o caso de você querer que quando o texto ficar // em branco, seja assumido o valor zero. Do contrário, você não // deve executar o try except se Text = '' if Edit1.Text = '' then Edit1.Text := '0'; try Edit1.Text := FormatFloat('0.00', StrToFloat(Edit1.Text)); except Edt1.SetFocus; ShowMessage('Deve ser informado um valor'); end; end;
-
Recentemente, num post que tratava sobre outro assunto, quando foi mensionado um exemplo que introduzia um novo botão na barra de título da janela, apareceram questionamentos sobre se ele utilizava ou não o tema do Windows. Ficou a dúvida, a curiosidade. Seria fácil utilizar o recurso de tema do windows para desenhar um novo botão na barra de título? Bom, isto envolveria muito mais que simplesmente desenhar utilizando o tema. É necessário processar mensagens específicas (as Non Client - WM_NC...). Foi discutida também a se o botões padrões na barra de título(Max, Min, Restore, Close) seriam ou não bitmap's. E verificamos que no caso específico do uso de tema, tratam-se de bitmaps (veja figuras neste link) Depois de trocar algumas MP's com o Thales, achei que poderia ser interessante trocar idéia sobre o assunto. Este questionamento não é urgente, mas acredito que possamos descobrir os detalhes mais rápidos se houver mais pessoas interessadas em investigar. Aplicação para este conhecimento? Bom, acho que pensaremos em alguma. Na verdade, uma delas é a personalização de componentes, já que você pode construir componentes e desenhar eles utilizando as configurações de temas como você bem entender - desenhar o THeadControl utilizando a "textura" da barra de títulos, p.e.. Referências msdn: - Tudo sobre as funções/estruturas/... relacionadas a tema -> Visual Style Reference - Partes e estados, os principais parâmetros que as funções utilizam -> Parts and States(P&S) A partir da versão 7 do Delphi, foi incluida a unit UxTheme (delphipath\source\rtl\win), se alguém se interessar pelo assunto e não a possuir acredito que baste conseguir/solicitar para resolver esta questão. Eu comecei meu programa teste com um form e um label, apenas para ter um retorno visual sobre o processo de inicialização do uso de tema: procedure TForm1.FormCreate(Sender: TObject); begin if InitThemeLibrary then begin if UseThemes then Label1.Caption := 'XP Theme inicializado e tema está em uso' else Label1.Caption := 'XP Theme inicializado e tema não está em uso'; end else Label1.Caption := 'Não foi possível inicilizar recuros para uso de temas (XP Theme)'; end; InitThemeLibrary retornará true apenas se conseguir carregar uxtheme.dll e inicializar o ponteiro para as funções nela presentes. Introduzindo um botão e mais um label, tentei obter qual (dos 3) temas está em uso. Encontrei uma forma que foi através da localização das imagens. Utilizando a função GetThemeFilename é possível obter o nome e localização base da figura quando o parâmetro é TMT_IMAGEFILE (veja ref. P&S para especificar a imagem de 1 a 5):procedure TForm1.Button1Click(Sender: TObject); var HndTheme :HTheme; ThemeFileName, ThemeClasseList :array[0..255] of WideChar; ThemePart, ThemeState :LongInt; begin StringToWideChar('WINDOW', ThemeClasseList, SizeOf(ThemeClasseList)); HndTheme := OpenThemeData(Handle, ThemeClasseList); if HndTheme > 0 then begin ThemePart := WP_CLOSEBUTTON; ThemeState := CBS_HOT; // CBS_DISABLED CBS_HOT CBS_NORMAL CBS_PUSHED if GetThemeFilename(HndTheme, ThemePart, ThemeState, TMT_IMAGEFILE, ThemeFileName, SizeOf(ThemeFileName)) = S_OK then begin Label2.Caption := 'GetThemeFilename retornou: '+WideCharToString(ThemeFileName); end else Label2.Caption := 'Houve erro ao executar GetThemeFilename'; CloseThemeData(hndTheme); end else ShowMessage('Não foi possível encontrar a classe '+WideCharToString(ThemeClasseList)); end; Observar a necessidade de os parâmetros "strings" serem utilizados no formato WideChar. A alteração do tema em meu Desktop seguida da execução do programa resutou no seguinte: 1) Metallic\CloseButton.bmp 2) Blue\CloseButton.bmp 3) HomeStead\CloseButton.bmp Isto já confirma que os botões da barra de título são realmente bitmap's. Desabilitar o uso de tema (Estilo tema clássico do Windows), resultou em: - no Label1 -> XP theme inicializado e não está em uso; - no Label2 -> nada escrito e apresentada mensagem Não foi possível encontrar a classe WINDOW. Desenhando o botão na área de cliente da janela principal (apenas a parte alterada): ... end else Label2.Caption := 'Houve erro ao executar GetThemeFilename'; DrawThemeBackground(HndTheme, Canvas.Handle, ThemePart, ThemeState, Rect(150, 32, 150 +25, 32 +25), nil); CloseThemeData(hndTheme); end else ... Observar que a localização é em relação a área de cliente de cujo o HDC é passado. Assim, se introduzirmos um Panel no form, poderemos desenhar a mesma imagem dentro dele, porém, neste caso, como não temos acesso ao canvas do TPanel, teremos que criar um Device Context (DC) para ele (apenas a parte alterada):procedure TForm1.Button1Click(Sender: TObject); var DC :HDC; HndTheme :HTheme; ... end else Label2.Caption := 'Houve erro ao executar GetThemeFilename'; DrawThemeBackground(HndTheme, Canvas.Handle, ThemePart, ThemeState, Rect(150, 32, 150 +25, 32 +25), nil); DC := GetDC(Panel1.Handle); DrawThemeBackground(HndTheme, DC, ThemePart, ThemeState, Panel1.ClientRect, nil); ReleaseDC(Panel1.Handle, DC); CloseThemeData(hndTheme); end else ... Acho que ficou meio com cara de tutorial, mas queria já adiantar um pouco do que descobri (quase nada). Algumas dúvidas: 1) DrawThemeIcon é uma função que parece ser de grande utilidade. Entretanto, tentei adicionar um TImageList e passar seu handle para esta função e não obtive sucesso. Se alguém conseguir fazer uso dela com o componente TImagelist, por favor post aqui. 2) Não consegui, ainda, entender para que serve ou por que utilizar a passagem de mais de uma classe no parâmetro ThemeClasseList em OpenThemaData. Alguma ideia? 3) Será que é possível utilizar/carregar um tema para minha aplicação que não seja o que atualmente está definido no Windows XP? []s p.s. andei dando uma mexida no texto
-
Um conjunto de componentes interessantes permitem a inclusão de um processador de script pascal dentro da sua aplicação. É compatível com as versões 6, 7 e 2006 até 2009 do Delphi. Chama-se Pascal Script™ 3.0 (link). Ver detalhes/exemplo no link Read more about Pascal Script here presente na página.
-
este fragmento deveria ser possível de escrever assim: Bitmap := TBitmap.Create; Bitmap.LoadFromResourceName(HInstance, 'STAY_ON');
-
Posso perguntar por que você quer criar um programa para isto? Acho que talvez não valha o esforço.De qualque modo, acho que deve começar conhecendo a estrutura do aruivo PDF e não há opção melhor que ver o guia de referência da Adobe (link). Este outro link, também da Adobe, da uma idéia da estrutura do arquivo de modo visual (gráfico). []s
-
Paulo, ocorre que TDateTime/TTime/TDate são do tipo Float. Então, não tem problema. Para formatar o resultado no seu programa, basta utilizar as funções de formatação de data/hora que funciona. Você pode também criar um campo calculado do tipo TDateTime, define a propriedade DisplayFormat, e no evento OnCalcField, do seu dataset, atribui o valor do campo retornado ao campo calculado. Eu diria para você tentar fazer um type-cast para TimeStamp na sua consulta - ((chegadadatahora-saidadatahora) as timestamp) tempo_a. Quem sabe consiga modificar o retorno de modo a facilitar as coisas. Pelo que lí neste link, o resultado da subtração de dois timestamp resultam em um decimal(18,9). Se precisar apresentar total de horas, que possa ultrapassar 24 horas(tipo, 32:00hs), dê uma olhada neste post que fiz em outro forum. []s
-
Sempre entendi que a resposta para esta pergunta é NÃO.Com toda a comodidade das janelas encapsuladas em objetos, poucas pessoas passaram pela experiência de ter que escrever todo o procedimento de janela. Naquela oportunidade sempre ficou claro que ao processar a mensagem WM_PAINT, um handler para o DC deve ser alocado no início (BeginPaint) de seu processamento e liberado após seu término (EndPaint). É uma questão de não alocar recursos do sistemas, os quais são limitados. (Because only a limited number of common device contexts exist, an application should release them after it has finished drawing. - msdn) Leve em consideração que cada botão, cada label, cada elemento em uma janela (form) é uma outra janela. Já imaginou quantos DC's estariam alocados integralmente se fossem mantido do início ao fim da aplicação ao invés de serem alocados apenas quando necessário? Eu fiz assim -> var dc : HDC; r : TRect; cn : TCanvas; begin DC:=GetWindowDC(handle); r.left:=0; r.top:=0; r.right:=width; r.bottom:=height; cn:=TCanvas.create; cn.Handle:=DC; cn.FillRect(r); // o form tem 3 botões e ele pinta por cima de todos, fica tudo preto. //Aqui eu movimento o form ou redimensiono, saindo com ele todo pra fora da tela pra que repinte cn.FillRect(r); // Aqui é pintado todo o form menos os botões, a area dos botões não é preenchida. end; Isso aí eu botei uma parte no OnClick de cada botão, um pra pegar DC, um pra FillRect e um pra releaseDC. Observe que preferencialmente o desenho na janela deve ocorrer processando a mensagem WM_PAINT. Mesmo assim, sempre que chamar GetWindowDC ou GetDC, após a "pintura" deve ser chamado ReleaseDC. (After painting is complete, the ReleaseDC function must be called to release the device context. Not releasing the window device context has serious effects on painting requested by applications. - msdn) Pois é, mas o handle do canvas do form só pega área cliente eu eu quero a janela toda. Não seria o caso de criar uma janela sem título? Subscreva CreateParams para este fim. Acho que o primeiro comentário responde a isto. []s
-
acdestefani, Dois bons links que podem lhe ajudar a construir a sua calculadora orientada a objetos:- Calculadora (Clibe Delphi) - RPNCalc (JoãoMorais.com) Supondo que você tenha colocado um botão para cada número e operação, basta no OnClick deste botões adicionar o Caption dos mesmos ao edit que armazena a sua expressão. Daí quando você clicar no igual, terá que avaliar a expressão (o primeiro link fala justamente sobre isto - avaliação de expressões).Ex. do evento OnClick: // este evento seria utilizado(associado) para o OnClick dos botões que // contém os números, ponto e operadores, p.ex. procedure form1.BtnClick(Sender :TObject); begin EdDisplay.Text := EdDisplay.Text +(Sender as TButton).Caption; end; Mas, por este caminho, a única orientação a objeto que você terá é no que diz respeito a inteface (form). []s
-
s3c, Está aí uma boa pergunta! Ele realmente poderia. Mas o fato de permitir este tipo de construção (loop infinito), talvez tornasse complexo o processo para esta avaliação já que a implementação que se encontra no "recheio" poderia "dar um nó" no compilador. Talvez apenas avisar da possibilidade de que ocorra, mas sem garantias. Então: While true do; para mim true seria o retorno booleano da avaliação de uma expressão que neste caso não existe. s3c acho que todo o "problema" na verdade é gerado por uma questão de interpretação. Seja nossa ou de quem compôs o help. Isto porquê as constantes são tratadas como expressões. Vejamos alguns fragmentos do arquivo de ajuda:Tópico: Boolean types [...]Boolean values are denoted by the predefined constants True and False.[...] Assim entendemos que True e False são processadas pelo compilador como contantes. Tópico: True constants (aqui não é sobre a constante TRUE e sim "constantes de verdade") [...]The syntax for declaring a true constant is const identifier = constantExpression where identifier is any valid identifier and constantExpression is an expression that the compiler can evaluate without executing your program. (see constant expression - abaixo)[...] Tópico: Constant Expressions A constant expression is an expression that the compiler can evaluate without executing the program in which it occurs. Constant expressions include numerals; character strings; true constants; values of enumerated types; the special constants True, False, and nil; and expressions built exclusively from these elements with operators, typecasts, and set constructors.[...] Mesmo se chamar não gera código, porque não há nada a fazer. Bom creio que o caso esteja resolvido, né? Pô Thales, agora que eu ia participar. :D Mas daí eu já acho que é uma questão de otimização do compilador.
-
marcelo, você tem que organizar suas idéias! O tópico "fala" em excluir linha do DBGrid e você pergunta no texto como mostrar uma mensagem se o código já existe. :blink: Bom. Pelo jeito você edita (digita) os campos direto no DBGrid. É isto? O Código de que você "fala" é a chave primária? Ao menos é o que parece, já que uma nova entrada resulta em Key-violation. Este código tem que ser digitado, você não poderia utilizar um "auto-increment"? você está utilizando componentes ClientDataSet para acessar os dados? O nome cds sugere isto. No código que você postou, se o que você quer é verificar se o código informado já existe na tabela (cds), seria mais apropriado que você utilizasse uma query auxiliar para este fim. Supondo que seja utilizado o componente TClientDataSet, poderia ser algo como: cdsTestaCodigo.Close; cdsTestaCodigo.CommandText := 'SELECT cod_produto ' + 'FROM produto ' + 'WHERE cod_produto = :cod_produto'; cdsTestaCodigo.Params.ParamByName('cod_produto').AsInteger := cdscod_produto.Value; cdsTestaCodigo.Open; if not cdsTestaCodigo.EOF then ShowMessage('O codigo já existe');
-
(chegadadatahora-saidadatahora) tempo_a: paulobergo, nunca utilizei Visual dBase7, mas esta coluna na sua query já não resulta num campo timestamp (que tem data e hora) já que ambos os campos envolvidos foram assim definidos?
-
Problema Com If No Meu Programa! Ajuda Por Favor!
pergunta respondeu ao schaukoski de Micheus em Delphi, Kylix
if (combobox1.text) = dmData.atlogins.FieldByname('Nível').asstring then begin if combobox1.text = 'ADMINISTRADOR' then begin Form1.Hide; FormADM.SHowmodal; Close; end; if combobox1.text = 'RECEPCIONISTA' then begin Form1.Hide; FormREC.SHowmodal; Close; end; if combobox1.text = 'ENTREGADOR' then begin Form1.Hide; FormENT.SHowmodal; Close; end; end else begin schaukoski, uma palavrinha(dica) sobre esta parte do código... Observe que após validar o if inicial, você faz três testes com o mesmo componente, mesmo que o primeiro já seja verdadeiro. A estrutura lógica implementada ficaria melhor se você a utilizasse da mesma forma que você pensa nela. Vejamos:Se Text for igual a Administrador então faço início do bloco - oculto o Form1 - mosto o FormADM - fecho este form fim do bloco senão for, verifico Se Text for igual a Recepcionista então faço início do bloco - oculto o Form1 - mosto o FormREC - fecho este form fim do bloco senão for, verifico Se Text ... Para isto você deveria introduzir o ELSE. if (combobox1.text) = dmData.atlogins.FieldByname('Nível').asstring then begin if combobox1.text = 'ADMINISTRADOR' then begin Form1.Hide; FormADM.SHowmodal; Close; end else if combobox1.text = 'RECEPCIONISTA' then begin Form1.Hide; FormREC.SHowmodal; Close; end else if combobox1.text = 'ENTREGADOR' then begin Form1.Hide; FormENT.SHowmodal; Close; end; end else begin Agora, se o primeiro teste resultar em verdadeiro, não será feito (desnecessariamente) o segundo e terceiro testes. Isto faz diferença quando se utiliza muitos if's, e deixa seu código mais lógico. ;) Outra coisa. Se está tratando todas as opções possíveis (as 3 implementadas) para o resultado do seu if inicial (teste do nível), então você pode ainda fazer uma otimização do código evitando repetição. Observe que para qualquer uma das 3 opções que você avalia, você inicialmente oculta o Form1 e, após mostrar o Form adequado à opção, fecha o Form "atual". Bom. Se, como sugerí antes, você estiver tratando todas as opções possíveis, então você poderia simplificar para esta forma:procedure TForm1.Button1Click(Sender: TObject); begin usuariologado := Combobox1.text; if (dmData.atlogins.Locate('Senha', maskedit1.text, [loCaseInsensitive])) then begin if (combobox1.text) = dmData.atlogins.FieldByname('Nível').asstring then begin Form1.Hide; if combobox1.text = 'ADMINISTRADOR' then FormADM.SHowmodal; else if combobox1.text = 'RECEPCIONISTA' then FormREC.SHowmodal; else if combobox1.text = 'ENTREGADOR' then FormENT.SHowmodal; Close; end else begin label3.caption := ' * Nível de acesso incompatível com usuário *'; combobox1.Text := ''; combobox1.SetFocus; end; end else begin label3.Caption := ' * SENHA INCORRETA * '; maskedit1.Text := ''; maskedit1.setfocus; end; end; []s -
Relatório? Ou Outro Componente?
pergunta respondeu ao Cleverson Honório Gouvêa de Micheus em Delphi, Kylix
Este componente pode ser o QuickReport (existem outros). Estes dados de um determinado Form vem de uma tabela ou são apenas Edit's? -
Experimente definir a propriedade DisplayFormat do campo(field) em questão (QTD) para '##0'.
-
Não dá para fazer o programinha por você, mas vamos ver ser com algumas sugestões você consegue pelo menos iniciar. Depois vai tirando dúvidas. Não sei se será o modo mais simples, mas acho que seria mais ou menos assim:1) num form, que seria o principal, você declara uma matriz aluno x nota para armazenar a informação. Para isto você cria um record(registro) que aramazena os dados de um aluno e, a seguir, declara uma variável que é um vetor de 10 posições onde em cada posição será armazenado este registro. Algo como: type RegNotas = record Nome :string; Nota1, Nota2, Nota3, Nota4 :Single; end; var MatrizAlunos :array[1..10] of RegNotas; VetorMedias :array[1..10] of single; PosicaoMatriz :Integer; Neste form você poderia adicionar um botão para que as notas sejam informadas. E ao acionar este botão você mostra um segundo form. 2) num segundo form, que seria uma tela de entrada, você adicionaria o seguinte: -> um Edit para receber o nome do aluno; -> quatro Edits, um para cada uma das notas necessárias; -> um label para indicar o nº sequencia do aluno a cada vez que você o inclui; -> um botão para adicionar a informação a sua matriz (alunos x notas). no evento OnClick do botão, você move os valores digitados para a respectiva posição na matriz:procedure TForm2.btAddAlunoClick(Sender :TObject); begin with MatrizAlunos[PosicaoMatriz] do begin Nome := edNome.Text; Nota1 := StrToFloat(edNota1.Text); Nota2 := StrToFloat(edNota1.Text); Nota3 := StrToFloat(edNota1.Text); Nota4 := StrToFloat(edNota1.Text); end; Inc(PosicaoMatriz); // avança uma posição na matriz btAddAluno.Enabled := PosicaoMatriz <= 10; // habilita o botão apenas se ainda não informou os 10 // limpa os campos, viabilizando nova inclusão edNome.Text := ''; edNota1.Text := ''; edNota2.Text := ''; edNota3.Text := ''; edNota4.Text := ''; end; No form principal, você vai precisar ter um procedimento para inicialização da matriz. Este procedimento pode ser declarado dentro da sessão Private do seu form. O código para este procedimento seria mais ou menso assim:procedure TForm1.InicializaMatriz; begin FillChar(MatrizAlunos, 0, SizeOf(MatrizAlunos)); // limpa a matriz FillChar(VetorMedias, 0, SizeOf(VetorMedias)); // limpa a vetor PosicaoMatriz := 1; // inicializa na primeira posição da matriz end; depois no evento OnClick do botão(btEntradaNotas) que aciona o segundo form(o de entrada) você chama este procedimento antes de mostrar o form:procedure TForm1.btEntradaNotasClick(Sender :TObject); var Indice :Integer; begin InicializaMatriz; if Form2.ShowModal = mrOk then begin for Indice := 1 to 10 do begin // cálculo da média VetorMedias[Indice] := (MatrizAlunos[Indice].Nota1 + MatrizAlunos[Indice].Nota2 + MatrizAlunos[Indice].Nota3 + MatrizAlunos[Indice].Nota4) /4; end; // aqui segue com procedimentos após concluído o preenchimento da matriz end; end; Fica a dúvida se este "imprima o número de alunos..." é realente para a impressora. É apenas uma prototipação. Falta a validação dos edits referentes às notas; Falta gerenciar a questão do cancelamento das inclusões (utilizar um botão para este fim, retornando mrCancel) e mais alguns detalhes que aparecem ao gosto do freguês. A entrada de dados é parecida com a que será feita no programinha anterior. A função para testar se o número é primo eu peguei deste link:function NumeroPrimo(Numero: Cardinal): Boolean; var Cont: Cardinal; begin if Numero>1 then begin Result:=True; Cont:=2; while Result and (Cont<Numero) do if (Numero mod Cont)=0 then Result:=False else Inc(Cont); end else Result:=False; end; Acho que você já tem o bastante para começar. Tente avançar, havendo dúvidas questione, talvez mais alguém possa lhe ajudar. []s
-
Infelizmente as vezes a ficha não cai e o cara passa batido por algumas etapas/testes. :angry: Já corrigí no tutorial. Valeu mais uma vez.
-
Neste post o banco do exemplo é Paradox, mas o procedimento se aplica perfeitamente ao seu caso. []s
-
É o Micheus poderia postar isso em Dicas e Tutoriais, By Micheus :D Abs. Progr'amador. Progr'amador está lá - link. Não tenho experiência neste negócio, então, por gentileza, dê uma verificada se está bom. Se ficar alguma pendência mande-me uma mensagem. ;) []s
-
O objetivo da função HoraPorExtenso é a conversão de horas no formato TTime ou TDateTime para texto corrido (extenso). 1) Função auxiliar DecimalExtenso: ela está projetada para trabalhar com números entre 0 e 99, podendo ser ampliada para reaproveitamento em outras aplicações (extenso de valores). O parâmetro Masculino foi introduzido para tratar questões de gênero (masc/fem), que ocorre quando fala-se em horas (fem), mas não em minutos (masc). Com o intúito de otimizar recursos, um type cast deste parâmetro para o tipo Byte é utilizado. Com isto, se este parâmetro for True teremos como resultado 1 ser for False, teremos zero. Ao multiplicarmos este "resultado" por 2 (cnUnidadeGenero[unidade +(Byte(Masculino)*2)]), estaremos indexando corretamente o vetor cnUnidadeGenero. 2) Função HoraPorExtenso: optou-se pelo parâmetro no formado TDateTime de modo a facilitar a processamento da função, bem como pela obrigação da validação do campo sendo passado no momento de sua chamada. Deste modo não há risco de excessões. Como numa variável TDateTime/TTime (equivalente ao float) o valor das horas encontra-se na parte fracionária, multiplicando esta parte por 24 obtemos as horas. Com este processo, a "nova" parte fracionária corresponde aos minutos dentro daquela hora. Assim, multiplicando por 60, teremos o valor dos minutos. const cnUnidadeGenero :array[1..4] of string = ('uma', 'duas', 'um', 'dois'); cnUnidade :array[3..9] of string = ('três', 'quatro', 'cinco', 'seis', 'sete', 'oito', 'nove'); cnDezena10 :array[11..19] of string = ('onze', 'doze', 'treze', 'quatorze', 'quinze', 'dezesseis', 'dezessete', 'dezoito', 'dezenove'); cnDezena :array[1..9] of string = ('dez', 'vinte', 'trinta', 'quarenta', 'cinqüenta', 'sessenta', 'setanta', 'oitenta', 'noventa'); // monta apenas números decimais (até 99) function DecimalExtenso(Num :integer; Masculino :Boolean) :string; var Unidade, Dezena :integer; begin if Num > 0 then begin Unidade := Num mod 10; Dezena := Num div 10; if Dezena = 0 then begin if Unidade <= 2 then // Os números 1 e 2 podem variar em gênero Result := cnUnidadeGenero[Unidade +(Byte(Masculino)*2)] else Result := cnUnidade[Unidade] end else if Unidade = 0 then Result := cnDezena[Dezena] else if Dezena = 1 then Result := cnDezena10[Num] else if Dezena <= 9 then if Unidade <= 2 then // Os números 1 e 2 podem variar em gênero Result := cnDezena[Dezena] + ' e ' +cnUnidadeGenero[Unidade +(Byte(Masculino)*2)] else Result := cnDezena[Dezena] + ' e ' +cnUnidade[Unidade]; end else Result := 'zero'; end; // Monta a hora por extenso. // Pode receber um campo composto por data e hora, sem problemas function HoraPorExtenso(Horario :TTime) :string; var Hora, Minuto :integer; begin Hora := Trunc(Frac(Horario) *24); // Obtém Horas Minuto := Round(Frac(Frac(Horario) *24) *60); // Obtém Minutos if Minuto = 60 then begin Inc(Hora); Minuto := 0; end; Result := DecimalExtenso(Hora, False) + ' hora'; if Hora > 1 then Result := Result +'s'; if Minuto > 0 then begin Result := Result +' e ' +DecimalExtenso(Minuto, True) +' minuto'; if Minuto > 1 then Result := Result +'s' end; end; Testando a função: Para o teste adicione em um Form, um Botão, um Label e um MaskEdit. No evendo OnClick do botão coloque o código a seguir:procedure TForm1.Button1Click(Sender: TObject); begin Label1.Caption := HoraPorExtenso(StrToTime(MaskEdit1.Text)); end;
-
luizf, se for para digitar apenas Inteiros positivos, então pode ficar um pouco mais simples. No OnCreate do form, passe o handle do Edit desejado nas funções do exemplo abaixo: Ex.: SetWindowLong(Edit1.Handle, GWL_STYLE, GetWindowLong(Edit1.Handle, GWL_STYLE) or ES_NUMBER);
-
Valeu Progr'amador. Não tinha testado estas opções. A questão do plural, tinha ignorado mesmo. Mas acho que agora ficou correto. Thales, eu bem que desconfiei que não poderia "ser exatamente a mesma coisa" :D Corrigindo... const cnUnidadeGenero :array[1..4] of string = ('uma', 'duas', 'um', 'dois'); cnUnidade :array[3..9] of string = ('três', 'quatro', 'cinco', 'seis', 'sete', 'oito', 'nove'); cnDezena10 :array[11..19] of string = ('onze', 'doze', 'treze', 'quatorze', 'quinze', 'dezesseis', 'dezessete', 'dezoito', 'dezenove'); cnDezena :array[1..9] of string= ('dez', 'vinte', 'trinta', 'quarenta', 'cinqüenta', 'sessenta', 'setanta', 'oitenta', 'noventa'); function DecimalExtenso(Num :integer; Masculino :Boolean) :string; var Unidade, Dezena :integer; begin if Num > 0 then begin Unidade := Num mod 10; Dezena := Num div 10; if Dezena = 0 then begin if Unidade <= 2 then Result := cnUnidadeGenero[Unidade +(Byte(Masculino)*2)] else Result := cnUnidade[Unidade] end else if Unidade = 0 then Result := cnDezena[Dezena] else if Dezena = 1 then Result := cnDezena10[Num] else if Dezena <= 9 then Result := cnDezena[Dezena] + ' e ' +cnUnidade[Unidade]; end else Result := 'zero'; end; function HoraPorExtenso(Horario :TTime) :string; var Hora, Minuto :integer; begin Hora := Trunc(Frac(Horario) *24); // Obtém Horas Minuto := Round(Frac(Frac(Horario) *24) *60); // Obtém Minutos - sem arredondamento if Minuto = 60 then begin Inc(Hora); Minuto := 0; end; Result := DecimalExtenso(Hora, False) + ' hora'; if Hora > 1 then Result := Result +'s'; if Minuto > 0 then begin Result := Result +' e ' +DecimalExtenso(Minuto, True) +' minuto'; if Minuto > 1 then Result := Result +'s' end; end;
-
Tinha começado hoje cedo(em casa), e deixei para acabar só agora. Não usei funções para obter as partes separadas (hora e minutos), existentes no D7, porque aqui onde estou só tem o D3 :huh: const cnUnidade :array[1..9] of string = ('um', 'dois', 'três', 'quatro', 'cinco', 'seis', 'sete', 'oito', 'nove'); cnDezena10 :array[11..19] of string = ('onze', 'doze', 'treze', 'quatorze', 'quinze', 'dezesseis', 'dezessete', 'dezoito', 'dezenove'); cnDezena :array[1..9] of string= ('dez', 'vinte', 'trinta', 'quarenta', 'cinqüenta', 'sessenta', 'setanta', 'oitenta', 'noventa'); // monta apenas números decimais (até 99) function DecimalExtenso(Num :integer) :string; var Unidade, Dezena :integer; begin if Num > 0 then begin Unidade := Num mod 10; Dezena := Num div 10; if Dezena = 0 then Result := cnUnidade[Unidade] else if Unidade = 0 then Result := cnDezena[Dezena] else if Dezena = 1 then Result := cnDezena10[Num] else if Dezena <= 9 then Result := cnDezena[Dezena] + ' e ' +cnUnidade[Unidade]; end else Result := 'zero'; end; // Monta a hora por extenso. // Pode receber um campo composto por data e hora, sem problemas function HoraPorExtenso(Horario :TDateTime) :string; var Hora, Minuto :integer; begin Hora := Trunc(Frac(Horario) *24); // Obtém Horas Minuto := Round(Frac(Frac(Horario) *24) *60); // Obtém Minutos - sem arredondamento Result := DecimalExtenso(Hora) + ' horas'; if Minuto > 0 then Result := Result +' e ' +DecimalExtenso(Minuto) +' minutos'; end; // Testando o uso procedure TForm1.Button2Click(Sender: TObject); begin Label2.Caption := HoraPorExtenso(StrToTime(MaskEdit1.Text)); end; []s
-
com certeza. Fiz a colocação levando em conta justamente que o algorítimo utilize técnicas que viabilizem a recuperação, que é a situação que se está discutindo. é verdade. E operações com deslocamento de bits também. Lembrei destes casos no chuveiro, pode?!. :D (sabe como é, a gente sai do forum e a cabeça continua processando)
-
Quando agente pergunta essas coisas pra você, você sai pesquisando pra achar ou você já conhece esses lances maneiros?As duas coisas. Alguns anos de NET ajudam. No caso específico do WinRar, eu fui procurar. Já conhecia para Winzip, pois também já precisei relembrar uma senha, mas para acessar coisa mais séria. :D Não seja trágico. Na verdade quanto mais travas mais seguro. Entretanto, devemos levar em conta que a importância do seu programa. Não é qualquer programa que vai ser craqueado. O cara da esquina só vai tentar quebrar suas travas se realmente for útil a ele ou a "comunidade". Tenho minhas dúvidas, as vezes depois de um cálculo, os dados resultantes, ou seja, a senha e o arquivo criptografado, não são suficientes para se recuperar os dados originais. Cheguei a essa conclusão depois de pensar em vários calculos, na tentativa de torná-los o máximo complexos dentro de minhas possibilidades, e me deparar com resultados que não são reversíveis. Ou pelo menos eu não conseguí pensar em um calculo para reverte-los. Não tenho conhecimento de que isso possa ocorrer.
-
Ponteiro Se Movimentando Sozinho. Como Fazer?
pergunta respondeu ao Paulo Nobre de Micheus em Delphi, Kylix
Thales, se você acessou o link que postei no finalzinho (p.s.), então você já viu a imagem que o link problemático mostraria (é a 1ª imagem, que tem a tela do Resource Hacker). Acho que seria mais ou menos isto, também pretendo estudar esta questão.Apenas a título de informação, já que alguns leitores podem não ter conhecimento, é possível fazer a aplicação utilizar o tema no Windows XP apenas incluindo um arquivo .res. Funciona muito bem. Link sobre como criar este arquivo (WinXP.res)