GEEK TIMES
INDÍCE
02
03
CRIE JOGOS EM VB
07
BRO WSER EM BROWSER VISU AL B ASIC VISUAL BASIC
11
DELPHI, A PRIMEIRA VEZ
15
RÁDIO ON-LINE NO LINUX
17
DELPHI: 100 DICAS
JOGOS EM VISUAL BASIC
03
CRIE JOGOS EM VISUAL BASIC POR THIAGO SOUZA
○
○
○
○
○
○
○
○
○
○
Veja detalhadamente como construir jogos feito em Visual Basic ○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
Criar um jogo completo. Esse é o sonho da maioria dos aficionados por games. Mas diferente do que pode parecer em um primeiro momento, não é preciso ser um programador experiente para desenvolver jogos. Se você não acredita, acompanhe a reportagem a seguir. Nela, é ensinado passo-a-passo como criar um jogo completo usando a linguagem de programação Visual Basic. Aproveite para ampliar seus conhecimentos. Quem sabe você não desenvolve um novo Fifa Soccer?
JOGOS EM VISUAL BASIC
Crie um novo projeto Abra o Visual Basic e crie um novo projeto. Para criar um novo projeto clique em File e em seguida New Project. Na janela de propriedades altere a propriedade name do Form1 para frmcampo, caso não visualize a janela de propriedades tecle F4 para que ela apareça. Na opção BorderStyle do formulário escolha 1 - Fixed Single. Essa opção não deixará que o jogador altere o tamanho do form, altere a propriedade caption para SUPER GOL A GOL. As opções Height e Widh também serão modificadas Height irá ser igual a 6315 e Width a 9285. Altere o StartUpPosition para 2 – CenterScreen , isso fará com que o formulário sempre inicie no meio da tela.
04
Flat e atribua o valor 0 para a opção Text Altere o Label Selecione o objeto Label1 e na janela de propriedades altere a propriedade name para lbljog logo após seu caption JOGADOR. Com o label2 selecionado mude o seu name para lblcomp e seu caption para COMPUTADOR. Com o terceiro label selecionado(label3) mude o caption para VS e seu name para lblvs Configure o Image Clique sobre o Image1 e na janela de propriedades altere seu name para imgjog, com o Image2 selecionado altere seu name para imgcampo. Agora com o Image3 selecionado, o seu name será igual a imgcampo. Altere o CommandButton Selecione o CommandButton1 e na janela de propriedades altere seu name para cmdnovo, seu caption para Novo Jogo e, por fim, a propriedade Style para Graphical. Já com o CommandButton2 selecionado altere a propriedade name para cmdpausar, a opção caption para Pausar e, por fim, altere a propriedade Style para Graphical. Com o CommandButton3 selecionado altere seu name para cmdsair, o caption para Sair e Style para Graphical.
Coloque os Objetos Coloque dois Textbox , três Label , três Image , um Shape e três Command Button. Como mostra a figura abaixo com os objetos em destaque:
Configure o TextBox Selecione o Text1 e altere na janela de propriedade a opção name do Text1 para txtjog, Appearance para 0 – Flat. Atribua o valor 0 para a propriedade chamada Text. Agora, com Text2 selecionado altere a propriedade Appearance para 0 -
Configure o Timer e o Shape Altere a propriedade Interval do Timer para 5. No objeto shape1, seu name deverá ser shpbola e sua propriedade shape será alterada para 3 – Cicle. Após esses procedimentos, a interface deverá estar parecida com a figura abaixo.
Crie o menu Chegou o momento de criar o menu de opções do seu jogo. Para isso, você deve clicar na opção Menu Editor que está localizado ao lado do botão Salvar do Visual Basic. A próxima figura mostra em detalhe o objeto Menu Editor, que possibilita a criação de menus:
JOGOS EM VISUAL BASIC
05
contar os pontos dos jogadores. Por isso, elas estão sendo declaradas como do tipo Integer. Private Sub Form_Load() Call Carregar_Posicoes End Sub Entenda o código: Todo comando colocado no form_load será carregado quando o form for iniciado. Neste caso ele vai chamar a função Carregar_Posicoes para que todos os objetos colocados fiquem em pontos estratégicos para o funcionamento do jogo.Esta função ainda será criada.
Configure o Menu Editor No campo caption do primeiro menu escreva Opções e em seu name menopcao. Em seguida, clique sobre o botão INSERT, cadastre um novo item com o caption Arquivo e name menarquivo. Após concluído o cadastro do itens, selecione o menopção e clique sobre o botão seta direita.
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If KeyCode = vbKeyUp Then imgjog.Top = imgjog.Top - 250 If KeyCode = vbKeyDown Then imgjog.Top = imgjog.Top + 250 If imgjog.Top < 0 Then imgjog.Top = 0 If imgjog.Top > 4560 Then imgjog.Top = 4560 End Sub Entenda o código: Esse Bloco de comandos faz com que o jogador se mova pela tela. Esse bloco de comandos foi declarado no Form_KeyDown para que a ação aconteça no momento que o usuário pressionar uma das teclas vbKeyUp ou vbKeyDown. (Se o jogador apertar a seta para baixo a imagem correspondente ao jogador vai para baixo. Caso a seta para cima seja pressionada, a imagem do jogador vai para cima). Private Sub CMDNOVO_Click() x = MsgBox(“Deseja Realmente Começar um Novo Jogo ?”, vbYesNo, “Aviso”) If x = vbYes Then txtjog.Text = 0 TXTCOMP.Text = 0 Timer1.Interval = 5 Call Inicial Endif End Sub
Início da programação Para programar o jogo, você deve dar um duplo sobre o formulário e digitar os códigos necessários. A seguir, você poderá visualizar as partes principais do código com comentários explicando o que está sendo realizado. Dim bola As Integer Dim pontosjog As Integer Dim pontoscomp As Integer Entenda o código: Essas variáveis serão utilizadas no logo do programa para facilitar a programação, isso porque iremos armazenar valores que vão representar a posição da bola e
Entenda o código: Esse bloco de comandos faz começar um novo jogo. Vale ressaltar que o msgbox está sendo armazenado na variável X. Na linha seguinte é verificado se o x retornou uma resposta positiva. Caso positivo, as caixas de textos recebe o valor 0 e o timer tem seu intervalo específicado em 5. Por último, a função
JOGOS EM VISUAL BASIC
Inicial é chamada através da especificação do comando Call. O Endif fecha a condição IF e o End Sub encerrá o bloco de comandos associado ao botão. Private Sub Timer1_Timer() If bola = 1 Then shpbola.Top = shpbola.Top - 120: shpbola.Left = shpbola.Left - 120 If bola = 2 Then shpbola.Top = shpbola.Top - 120: shpbola.Left = shpbola.Left + 120 If bola = 3 Then shpbola.Top = shpbola.Top + 120: shpbola.Left = shpbola.Left + 120 If bola = 4 Then shpbola.Top = shpbola.Top + 120: shpbola.Left = shpbola.Left - 120 Entenda o código: Esse bloco de comandos faz a verificação dos valores contidos na variável bola. O comando especifica se a variável bola será igual a um, dois, três ou quatro. Se igual a um, então o objeto chamado shpbola terá a sua posição top igual a sua posição top atual menos 120, e terá a sua posição left igual a posição left atual menos 120. Digite o código a seguir: If shpbola.Top <= 0 And bola = 1 Then bola = 4 If shpbola.Top <= 0 And bola = 2 Then bola = 3 If shpbola.Top >= 5280 And bola = 3 Then bola = 2 If shpbola.Top >= 5280 And bola = 4 Then bola = 1
SOBRE O AUTOR THIAGO SOUZA
06
Entenda o código: Esse bloco de comandos faz com que a bola rebata na parede e volte para um dos players (Computador ou Jogador). If shpbola.Left <= 0 Then pontoscomp = pontoscomp + 1 TXTCOMP.Text = pontoscomp Call Inicial End If Entenda o código: Verifica se a bola passa pelo jogador. Ele vai contar um ponto para o computador e, logo após exibe a quantidade de pontos no txtcomp.text (se o objeto shpbola.left for menor ou igual 0, então ele somará a variável pontoscomp um ponto e mostrará no txtcomp.text e em seguida chamara a rotina Inicial. A rotina Inicial será chamada para colocar a bola no centro do campo para que o jogo prossiga. If shpbola.Left >= 8760 Then pontosjog = pontosjog + 1 txtjog.Text = pontosjog Call Inicial End If Entenda o código: Verifica se a shpbola.Left passa pelo computador e se ela passar será contato 1 ponto para o jogador (se a bola passar pela posição 8760, então ele somará na variável pontosjog + 1 e mostrará os pontos do jogador no txtjog.text).
CRIE SEU BROWSER EM VB
07
Mergulhar é preciso Aprenda passo a passo como criar seu próprio navegador de Internet usando a linguagem Visual Basic Por Thiago Souza
P
ara muitos, criar seu próprio navegador é uma idéia que parece sinônimo de missão impossível por sua complexidade. Mas para quem não agüenta mais ver o browser travar, e já adotou a política “se quer uma coisa bem feita, faça você mesmo”, esta é sua oportunidade. Ao contrário do que parece, construir seu pró-
prio browser para navegar rápido e sem problemas é uma tarefa simples. É necessário ter conhecimento intermediário em Visual Basic e, principalmente, força de vontade para aprender. Se este é o seu objetivo, acompanhe esta reportagem e aprenda passo a passo como fazer o seu próprio navegador.
Guia de Referência O componente Microsoft Internet Controls faz a integração da aplicação desenvolvida em Visual Basic com a Web. Confira agora as propriedades do controle WebBrowser para implementar novos recursos ao navegador. Busy – Verifica qual é o status do navegador. LocationName – Valor em que o objeto deposita o título da página exibida. Navigate – Através desta função é possível navegar e visualizar páginas da Internet e exibir diretórios locais. LocationURL – Guarda o endereço acessado no momento. Tem grande valor para implementar históricos e bookmarks. GoBack – Volta para a página visitada anteriormente. GoForward – Avança para a página seguinte visitada. Refresh – Faz a atualização da página ou diretório Web exibidos. GoHome – Retorna para página inicial do navegador do programa. GoSearch – Entra automaticamente em um radar de pesquisa Web. Stop – Interrompe qualquer processo que esteja sendo feito. BeforeNavigate – Executa uma ação momentos antes de iniciar a navegação. NavigateComplete – O evento acontece quando o site é totalmente carregado. DownloadBegin – Inicia o evento quando o navegador estiver pronto para carregar uma página. DownloadComplete – Tem seu início após a conclusão da função DownloadBegin.
CRIE SEU BROWSER EM VB
Interface do navegador O primeiro passo é construir a interface do seu navegador. Para isso, acesse o Visual Basic, clicando em Iniciar, Programas, Microsoft, Visual Basic e Visual Basic, e salve um novo projeto com o nome Pcbrowser.
08
seta para direita para: Calculadora, Bloco de Notas, Explorer, Yahoo, Google, Digerati.
Menus do navegador 1 Uma vez salvo o projeto, adicione os componentes Microsoft Internet Controls e Microsoft Windows Common Controls 5.0 (SP2). Para tanto, clique com o botão direito do mouse sobre a Caixa de Ferramentas, selecione Components e, em seguida, adicione as bibliotecas Microsoft Internet Controls e Microsoft Windows Common Controls 5.0 (SP2).
Configure os objetos 1 O próximo passo é incluir e configurar as propriedades dos objetos. Insira-os no formulário com um duplo clique sobre os objetos imagelist
2 Crie um menu através da ferramenta Menu Editor. Para acessá-la, entre em Tools e clique sobre a opção Menu Editor. Insira a palavra Arquivo na propriedade Caption, altere o name para menuarquivo. Pressione Next para finalizar o processo. Repita o procedimento para os seguintes itens: Sair, Exibir, Sites, Yahoo, Google, Digerati, Programas, Calculadora, Bloco de Notas, Explorer, Help e Sobre o Navegador.
DICA: Você pode acessar o Menu Editor a qualquer momento pressionando Ctrl+E.
3 Criado o menu, é necessário configurar a hierarquia, ou seja, definir os menus principais e seus submenus. Selecione o item Sair e pressione a seta para direita uma vez. Faça o mesmo para: Sites, Programas e Sobre o Navegador. Agora, com os itens a seguir selecionados, pressione duas vezes a
e toolbar
,
2 No formulário, clique com o botão direito do mouse em Imagelist e logo depois em Properties. Acesse a guia Images e clique em Insert Picture. Selecione o ícone e pressione Abrir. Repita a operação mais quatro vezes (para os itens Voltar, Avançar, Parar, Reload e Home).
3 Com o botão direito do mouse, clique sobre o objeto Toolbar e em seguida acesse Properties. Na propriedade Imagelist, altere-a para Imagelist1. Acesse a guia Buttons e insira um novo botão através do Insert Button. Modifique o campo Image para 1 (isso fará com que a primeira imagem inserida no Imagelist seja colocada no primeiro botão da Toolbar). Altere a propriedade Caption para Voltar. Repita o procedimento cinco vezes, respeitando a ordem das imagens (exemplo: botão 2 com a propriedade Image 2 e Caption Avançar. Os outros itens que devem ser acrescentados são Voltar, Avançar, Parar, Reload e Home).
CRIE SEU BROWSER EM VB
09
Private Sub mnuyahoo_Click() WebBrowser1.Navigate (“www.yahoo.com.br”) End Sub Faça o mesmo processo para todos os outros itens deste menu (Google e Digerati), alterando somente o endereço dos sites. Com o formulário aberto, entre no menu Exibir, Programas, Calculadora e digite os códigos abaixo: Private Sub mnucalc_Click() Call Shell(“c:\windows\calc.exe”) End Sub Volte para o modo gráfico e repita a operação, acessando o item Bloco de Notas. Logo após, programe os seguintes comandos: Finalize a Interface Para concluir a parte gráfica do seu navegador, basta inserir o objeto Webbrowser
no formulário e um Combobox
Private Sub mnunotepad_Click() Call Shell(“c:\windows\notepad.exe”) End Sub Repita a operação anterior para o item Explorer, e digite:
para a navegação.
Inicie a programação Após concluir todas as etapas de interface, o próximo passo é começar a programar. A seguir, mostramos como programar cada parte do browser.
Acrescentando Menus O menu está dividido em três partes: Arquivo, Exibir e Help. Clique sobre o menu Arquivo e, em seguida, Sair, e digite os comandos a seguir: Private Sub mnusair_Click() End End Sub
Não deixe seu projeto ser aberto várias vezes pelo mesmo usuário. Para isso, digite o código a seguir no evento Form_Activate: If App.PrevInstance Then x = MsgBox(“Aplicação em uso.”, 64, _ “A aplicação já está em uso.”) erro Unload Me End If Obs: O Underline ( _ ) permite separar as linhas de expressões muito grandes no VB.
Finalize a programação do menu. Selecione o menu Help, em seguida, clique sobre o item Sobre o Navegador, e então digite: Private Sub mnunav_Click() MsgBox “Versão 1.0 do PcBrowser. Desenvolvido pela revista PcBrasil”, vbInformation, “Aviso “ End Sub
Barra de endereços
Volte para a interface gráfica através do menu View, Object e acesse o menu Exibir, Sites, Yahoo. Copie os códigos: DICA 1
Private Sub mnuexplorer_Click() Call Shell(“c:\windows\explorer.exe”) End Sub
Agora é hora de programar o Combo Box para obter o acesso às páginas. Com a interface gráfica aberta, dê um duplo clique sobre o Combobox e digite os códigos a seguir:
DICA 2 Verifique e altere a resolução do monitor que está rodando a sua aplicação. Crie esta função no seu programa: Function Resolucao(pixellargura As Long, pixelaltura As Long) As Boolean Dim TwipsL As Long Dim TwipsA As Long ‘ converte pixels para twips TwipsL = pixellargura * 15 TwipsA = pixelAltura * 15 ‘ verifica comparando com a resolução atual If TwipsL <> Screen.Width Then ‘Width = largura
Resolucao = False Else If TwipsA <> Screen.Height Then ‘Height = altura Else Resolucao = True End If End If End Function ‘ Coloque esta parte do programa no form_activate ou Form_load ‘ Você pode alterar a resolução apenas mudando os números dentro do ‘ Parênteses If Resolucao(800, 600) = False Then MsgBox “A resolução da tela não é 800 x
CRIE SEU BROWSER EM VB
Private Sub Combo1_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then WebBrowser1.Navigate Combo1.Text End If End Sub
Web Browser Com o formulário aberto, dê um duplo clique sobre o objeto Webbrowser e digite os códigos: Private Sub WebBrowser1_StatusTextChange(ByVal Text As String) Combo1.Text = WebBrowser1.LocationURL End Sub
10
formulário e dê um duplo clique sobre ele para a programação. Feito isso, digite estas linhas de código: Private Sub Timer1_Timer() If WebBrowser1.Busy = False Then Timer1.Enabled = False Me.Caption = WebBrowser1.LocationName + “ - Pcbrasil Browser” Else Me.Caption = “Carregando, por favor aguarde...” End If End Sub DICA: O código completo desta reportagem pode ser encontrado na pasta Matérias, que está no CD-ROM desta edição.
Barra de ferramentas Dê um duplo clique sobre o objeto toolbar e digite: Private Sub Toolbar1_ButtonClick(ByVal Button As ComctlLib.Button) On Error Resume Next Select Case Button.Key Case “voltar” WebBrowser1.GoBack Case “avancar” WebBrowser1.GoForward Case “parar” WebBrowser1.Stop Case “reload” WebBrowser1.Refresh Case “home” WebBrowser1.Navigate (“www.yahoo.com.br”) End Select End Sub
Finalize o Navegador Conclua o seu navegador inserindo um objeto relógio, para que o usuário possa receber uma mensagem enquanto não carregar o browser. Para conseguir isso, insira o objeto no
600”, 64, “Aviso” End If
DICA 3 Deixe sempre a primeira letra do text em maiúscula. Para isso, digite o código no evento LostFocus do Text: If TxtNome.Text = Empty Then Exit Sub Else Dim Nome As string Nome = TxtNome.Text Mid(Nome, 1, 1) = UCase(Left(Nome, 1)) TxtNome.Text = Nome End If
DICA 4 Função para abrir e fechar o drive de CD do computador programando os códigos a seguir: ‘Declare em um modulo Declare Function mciSendString Lib “winmm.dll” Alias _ “mciSendStringA” (ByVal lpstrCommand As String, ByVal _ lpstrReturnString As String, ByVal uReturnLength As Long, _ ByVal hwndCallback As Long) As Long
Private Sub Command1_Click() dim res as long, returnstring as string*127 res = mcisendstring(“set CDAudio door open”, returnstring, 127, 0) End Sub Private Sub Command2_Click() dim res as long, returnstring as string*127 res = mcisendstring(“set CDAudio door closed”, returnstring, 127, 0) End Sub
PROGRAME EM DELPHI
11
Programe em Delphi POR THIAGO SOUZA
○
○
○
○
○
○
○
○
Conheça uma das linguagens de programação mais utilizadas atualmente
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
Desenvolver um programa de computador não é algo tão difícil. Basta um pouco de boa vontade e algumas horas de dedicação. Se não acredita, acompanhe a reportagem a seguir. Nela, você aprenderá passo-a-passo como criar seu primeiro programa em Delphi. Além disso, terá contato com alguns conceitos e comandos de uma das linguagens mais usadas por programadores de todo o mundo. ○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
Primeiros passos Criado em 1995 pela Borland, o Delphi se encontra atualmente na versão 6.0. Trata-se de uma linguagem de programação visual orientada a objetos. Para trabalhar com o Delphi é preciso conhecer alguns conceitos básicos: Objetos: São os controles visuais do Windows como, por exemplo, janelas, menus, caixas de textos, dentre outros. Os principais objetos do Delphi são: Form: É a interface padrão do Delphi. É nele que você colocará todos os objetos do seu programa. Button: Serve para colocar um botão de comando na tela. Label: Possibilita apresentar mensagens estáticas no formulário. Image: Permite colocar imagens. Edit: Sua função é acrescentar uma caixa de texto para que o usuário possa entrar com dados. Propriedades: Todo objeto do Delphi possui algumas propriedades que podem ser alteradas. Para que você possa entender, propriedades são as características dos objetos. As formas de
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
alterar uma propriedade são no momento do design ou durante a programação: Design: É quando você está montando a interface do programa. Para alterar o valor de uma propriedade em tempo de design, basta selecionar o objeto, clicar em Object Inspector (se não aparecer pressione F11), posicionar na propriedade desejada e digitar o valor. Execução: É alterada no momento em que o usuário executa o programa. Para isso, você deve digitar um código de programação, que segue a sintaxe: objeto.propriedade:=valor; Um exemplo seria mudar a propriedade Color do formulário:
Width - Define o comprimento do objeto (em pixels) Height - Especifica a largura do objeto em pixels. Eventos Toda a programação no Delphi é feita em eventos, que são as ações executadas pelos usuários do programa. Para codificar um evento, basta dar duplo clique sobre o objeto desejado, ou clicar na aba Events do Object Inspector e selecionar o evento desejado. Os principais eventos do Delphi são: OnMouseMove - Ocorre quando o usuário passa o mouse sobre o objeto. OnClick - Ocorre quando o usuário clica em determinado objeto. OnDbClik- Quando o usuário dá um duplo click sobre o objeto.
form1.color:=clblack; Veja algumas propriedades dos principais objetos do Delphi: Name - Permite modificar o nome do objeto Color - Especifica a cor do objeto XXXXXXXXXXXXXXXXXXXXXX É no Form que são construídas as Caption - É o rótulo ou mensagem XXXXXXXXXXXX interfaces dos programas que será exibida no objeto
PROGRAME EM DELPHI
12
AMBIENTE VISUAL Além de uma linguagem de programação completa, o Delphi fornece um ambiente de desenvolvimento visual. Confira o infográfico com os elementos visuais do Delphi.
Formulário
Caixa de Propriedades Tela de Código
DICA AVANÇADA Para criar formulários não-retangulares usando o Delphi, basta digitar o código a seguir(modificando as coordenadas da função CreateEllipticRgn): //Declare essa variável no início da unit. var hR : THandle; //Dê um duplo clique no formulário e digite o bloco de comandos a seguir: begin hR := CreateEllipticRgn(0,0,100,200); SetWindowRgn(Handle,hR,True); end;
Controles Visuais
PROGRAME EM DELPHI
○ ○ ○ ○
os novos valores que elas deverão receber. Siga o quadro e vá modificando as propriedades: OBJETO NAME CAPTION TAMANHO DA FONTE
○ ○
14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
OBJETO
NAME
CAPTION
TAMANHO DA FONTE
edittext
edtval
0
14
○
○
= CE + * / 1 2 3 4 5 6 7 8 9 0
○ ○ ○ ○
○
○
Após concluir estes passos,a interface ficará assim:
Começo da programação
procedure TCalculadora.Button1Click(Sender: TObject); begin if edtval.Text <> ‘0’ then edtval.Text := edtval.Text + ‘1’ ;
○ ○
○
○
○
○
○
○
○
○
○
Dê um duplo clique sobre o button1e escreva as seguintes linhas de comandos:
○ ○
3 Altere a propriedade dos Objetos Geralmente nós alteramos o nome dos objetos buttons, mas mantemos o prefixo “btn”. Isso facilita na programação, além de deixar o projeto com uma maior organização. Como estamos fazendo um sistema relativamente simples de uma calculadora, não renomearemos todos os buttons, pois podemos aproveitar seus nomes, isso porque, relacionaremos o Button1 que terá seu caption com o número 1, e assim sucessivamente. Na tabela a seguir você encontra todas as propriedades dos objetos, que devem ser alteradas e
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
O atributo Color foi alterado para clHighligh. Isso significa que o formulário terá azul como cor de fundo.
btnigual btnce btnmais btnmenos btnvezes btndividir button1 button2 button3 button4 button5 button6 button7 button8 button9 button0
○
BODERSTYLE COLOR bsDialog clHighlight
○
NAME CAPTION frm calculadora calculadora
button11 button12 button13 button14 button15 button16 button1 button2 button3 button4 button5 button6 button7 button8 button9 button10
○
○
2 Configure o Form O segundo passo a ser feito é a formatação do formulário. Para isso, será necessário que você altere as propriedades:
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
○
1Faça a Interface Coloque 16 objetos Button e um Edit. Para adicioná-los, clique sobre o objeto duas veze conforme assinalado abaixo.
13
if edtval.Text = ‘0’ then
PROGRAME EM DELPHI
edtval.Text := ‘1’; end; Entenda os códigos: Na bloco de comandos anterior, verificamos se o valor do edtval é diferente de zero. Caso afirmativo, ele apenas colocará o numero um ao lado do valor contido no edtval.text.(Observe que o número a ser colocado ao lado do valor do edtval.text é o mesmo número do caption do button1 no qual estamos programando). No bloco dos comandos do segundo if foi verificado se o valor do edtval.text é igual a zero. Se afirmativo, ele subtituirá o valor zero pelo número um, que é o caption do objeto. O resto da programação para os outros objetos do tipo button com o caption numérico será igual a do button1, mas lembrando que o número a ser colocado junto ao edtval.text será o mesmo do caption do botão. (Exemplo: se você estiver programando o button2 deverá escrever os comandos:
14
dos outros botões de cálculo. É importante lembrar que a função strtoint é responsável por transformar valores do tipo string (texto) para integer (Inteiros). Finalize a Programação dos botões O resto da programação para os outros botões de operações será igual a do bntmais, mas lembrando que o valor a ser colocado junto a variável será o mesmo do caption do botão. Se você estiver programando o bntmenos, por exemplo, deverá digitar os comandos: ope:= ‘-’; valor:= strtoint(edtval.Text); edtval.Text :=’’; btmais.Enabled := false; btmenos.Enabled := false; Btdividir.Enabled := false; Btvezes.enabled := false; Em seguida, dê duplo clique sobre o botão CE e digite:
if edtval.Text <> ‘0’ then edtval.Text := edtval.Text + ‘2’ ; if edtval.Text = ‘0’ then edtval.Text :=‘2’ ; end; Declare as variáveis No início da sua tela de códigos (chamada de Unit) você encontrará um campo chamado var assim como está descrito abaixo:
btnmais.Enabled := true; btnmenos.Enabled := true; Btndividir.Enabled := true; Btnvezes.enabled := true; edtval.Text := ‘0’; valor:=strtoint(‘0’); valor2:=strtoint(‘0’); Entenda o código: Ele faz com que todos os botões de cálculos sejam habilitados novamente para o clique , logo após zerar os valores contidos nas variáveis (valor e valor2).
var frmCalculadora : TfrmCalculadora;
Para finalizar a programação, você deve programar o botão =, dando duplo clique no botão referente a ele e digite:
Adicione a esse campo os seguintes comandos: frmCalculadora : TfrmCalculadora; ope : STRING; valor,valor2 : Integer; Programe os botões das operações Dê um duplo clique sobre o botão btnmais e digite: begin ope:= ‘+’; valor:= strtoint(edtval.Text); edtval.Text :=’ ‘ ; btmais.Enabled := false; btmenos.Enabled := false; Btdividir.Enabled := false; Btvezes.enabled := false; Entenda os códigos: Os blocos de comandos acima estão especificando qual operação será efetuada , junto ao travamento
procedure TfrmCalculadora.Button15Click(Sender: TObject); begin valor2:= strtoint(edtval.Text); if ope = ‘+’ then edtval.Text := inttostr(valor+valor2); ifope = ‘-’ then edtval.Text := inttostr(valor-valor2); if ope = ‘*’ then edtval.Text := inttostr(valor*valor2); if ope = ‘/’ then edtval.Text := inttostr(valor div valor2); end; Está pronto o seu primeiro programa em Delphi. Salve o programa, clicando no menu File, opção Save. Em seguida, pressione o botão F9 para testar o resultado. Se estiver tudo correto, a tela do programa será apresentada para que você possa fazer os cálculos.
RADIO ON LINE NO LINUX
15
POR: ALESSANDRO DE OLIVEIRA FARIA (CABELO) ALESSANDROFARIA@NETITEC.COM.BR
STREAMING COM O ICECAST O Alessandro de Oliveira Faria (CABELO) ensina no artigo abaixo como instalar e usar o Icecast para montar uma rádio virtual no Linux. Os exemplos dele são baseados no Conectiva Linux, mas são facilmente adaptáveis para outras distribuições. Este tutorial contempla as configuração básica de como fazer um servidor de RADIO mp3 online.
O Download Usaremos o icecast,que é um serviço de transmissão de áudio pela rede TCP/IP. Achei este pacote em todas distribuições atuais, entretando segue abaixo o link do pacote: ftp://rpmfind.net/linux/ conectiva/9/cd2/conectiva/ RPMS.002/icecast-1.3.118170cl.i386.rpm Exemplo de download: [root@via800 cabelo]# wget ftp:// rpmfind.net/linux/conectiva/9/cd2/ conectiva/RPMS.002/icecast-1.3.118170cl.i386.rpm --17:47:16-- ftp://rpmfind.net/linux/ conectiva/9/cd2/conectiva/RPMS.002/ icecast-1.3.11-8170cl.i386.rpm => `icecast-1.3.11-8170cl.i386.rpm' Conectando-se a rpmfind.net:21... conectado! Logando como anonymous ... Logado! ==> T YPE I ... feito. ==> CWD linux/conectiva/9/cd2/ conectiva/RPMS.002 ... feito. ==> PORT ... feito. ==> RET R icecast1.3.11-8170cl.i386.rpm ... feito. Tamanho: 190,583 (sem autoridade) 0K .......... .......... .......... .......... .......... 26% 0:26 5,21K 50K .......... .......... .......... .......... .......... 53% 0:21 4,12K 100K .......... .......... .......... .......... .......... 80% 0:07 4,88K 150K .......... .......... .......... ...... 100% 0:00 4,39K 17:48:05 (4,52 KB/s) - `icecast-1.3.118170cl.i386.rpm' recebido [190583]
A Instalação Como o pacote é RPM, basta digitar o
comando abaixo: [root@via800 cabelo]# rpm -ivh icecast-1.3.11-8170cl.i386.rpm Preparando... #################################### [100%] 1:icecast #################################### [100%] [root@via800 cabelo]#
A Configuração O Serviço trabalha com dois binários, o icecast e o ice. O icecast é responsável pelo serviço de transmissão e o ices reprodutor do audio.
Começaremos editando o icecast: Ao entrar na pasta /etc/icescast, entraremos os seguintes arquivos: [root@via800 etc]# cd /etc/icecast/ [root@via800 icecast]# ls groups.aut icecast.conf ices.conf mounts.aut users.aut - groups.aut : grupos de usuário que podem administrar o sistema - icecast.conf : configuração do serviço de transmissão de audio - ices.conf : configuração do serviço de reprodução de audio - mounts.aut : libera o acesso dos grupos cadastrados. - users.aut Vou explicar apenas a configuração dos arquivos icecast.conf e ices.conf: Antes efetuaremos o backup dos arquivos.
[root@via800 icecast]# [root@via800 icecast]# cp icecast.conf{,.original} [root@via800 icecast]# cp ices.conf{,.original}
Opções do icecast.conf: max_clients 6 : Numero máximo de clientes max_clients_per_source 6 : Numero máximo de clientes por estação max_sources : Numero máximo de estação max_admins 2 : Numero máximo de administradores throttle 1.0 : máxima permitida para utilização da transmissão encoder_password heukanuki : Senha que será utilizada pelo serviço de reprodução admin_password heukanuki : Senha do administrador oper_password heukanuki : Senha do operadores hostname 10.0.0.254 : IP do servidor port 8000 : Porta de conexão port 8001 : Porta de conexão para compatibilidade com outros sistemas server_name via800.matrix : O nome do seu servidor acl_policy 1 : Habilita a política de regras de acesso allow all * : Regra de acesso http_admin 1 : Habilita a administração via Web
Opções do ices.conf: <ices:File>/rede1/mp3/lista.txt</ ices:File> :Caminho completo da lista de reprodução de musicas. <ices:Randomize>1</ices:Randomize> :Liga o modo de reprodução randomica <ices:Hostname>localhost</ ices:Hostname> :IP ou nome do seu servidor <ices:Port>8000</ices:Port> :Porta usada para conexão <ices:Password>kagikawa</ ices:Password>
RADIO ON LINE NO LINUX
16
POR: ALESSANDRO DE OLIVEIRA FARIA (CABELO) ALESSANDROFARIA@NETITEC.COM.BR
:Senha definida no arquivo icecast.conf na variável encoder_password
Colocando a Rádio Virtual no AR
<ices:Background>1</ ices:Background> :Avisa ao ices para rodar como serviço de segundo plano (Daemon).
[root@via800 init.d]# service icecast stop Iniciando icecast: [ OK ] [root@via800 init.d]# ices Into the land of the dreaded daemons we go... (pid: 3708) [root@via800 init.d]#
<ices:Name>Viva o Linux FM</ ices:Name> :Nome/String que aparecerá no player.
SOBRE O AUTOR ALESSANDRO DE OLIVEIRA FARIA (CABELO) ALESSANDROFARIA@NETITEC.COM.BR
Iniciando o Serviço:
Parando o Serviço:
[root@via800 init.d]# service ices stop Desligando ices: [ OK ] [root@via800 init.d]# service icecast stop Desligando icecast: [ OK ]
Ouvindo a rádio: Entre no XMMS, vá na opção "adicione URL" e digite: http:// ip_do_seu_servidor:8000 Pronto agora a sua rede contem um servidor de audio!
100 DICAS DE DELPHI
17
AUTOR: MARCELO JALOTO MACHADO MJALOTO@BOL.COM.BR
100 DICAS DE DELPHI 1) Mostrar e esconder o Botão Iniciar Crie um subdiretório chamado “Botão Iniciar” utilizando o Windows Explorer. Depois abra o Delphi; feche o projeto que estiver aberto usando a opção Close all dentro do menu File e crie um novo projeto utilizando a opção New Application também no menu File.
MostrarEsconderIniciar(Estado:Boolean); {inclua esta linha} Tarefa Na parte implementation da unit (untEsconderMostrar) inclua a procedure MostrarEsconderIniciar: implementation {$R *.DFM}
a) Mude as seguintes propriedades do Form1: Name: frmEsconderMostrar Caption: programa para Esconder e Mostrar o Botão Iniciar Position: poScreenCenter BorderStyle: bsDialog Height: 104 Width: 403 b) Insira dois Botões no formulário: na Paleta de Componentes Standard Button c) Mude as seguintes propriedades do Button1: Name: btnEsconder Caption: esconder o Botão Iniciar Width: 177 d) Mude as seguintes propriedades do Button2: Name: btnMostrar Caption: mostrar o Botão Iniciar Width: 177 OBS.: Salve o projeto no subdiretório que você criou:
Name: btnEsconder Caption: esconder a Barra de
procedure MostrarEsconderIniciar(Estado:Boolean); Var taskbarhandle, buttonhandle : HWND; begin taskbarhandle := FindWindow(‘Shell_TrayWnd’, nil); buttonhandle := GetWindow(taskbarhandle, GW_CHILD); If Estado = True Then ShowWindow(buttonhandle, SW_RESTORE) {mostra o botão} Else ShowWindow(buttonhandle, SW_HIDE); {esconde o botão} end;
2) Mostrar e esconder A Barra de Tarefas Crie um subdiretório chamado “Barra de Tarefa” utilizando o Windows Explorer. Feche o projeto que estiver aberto usando a opção Close all dentro do menu File e crie um novo projeto utilizando a opção New Application também no menu File.
Width: 177 d) Mude as seguintes propriedades do Button2: Name: btnMostrar Caption: mostrar a Barra de Tarefa Width: 177 OBS.: Salve o projeto no subdiretório que você criou: e) A Unit1 salve com o nome de untBarraTarefa e o Project1 com o nome de BarraTarefa. f) Na parte interface da unit (untBarraTarefa) abaixo da cláusula uses inclua a definição da procedure interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; procedure EscondeBarraTarefa(EstadoBarra: Boolean);{inclua esta linha} Na parte implementation da unit (untBarraTarefa) inclua a procedure EscondeBarraTarefa: implementation
e) A Unit1 salve com o nome de untEsconderMostrar, e o Project1 com o nome de EsconderMostrar f) Na parte interface da unit (untEsconderMostrar), abaixo da cláusula uses, inclua a definição da procedure interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Procedure
a) Mude as seguintes propriedades do Form1: Name: frmBarraTarefa Caption: programa para esconder e mostrar a Barra de Tarefa Position: poScreenCenter BorderStyle: bsDialog Height: 104 Width: 403 b) Insira dois Botões no formulário: na Paleta de Componentes Standard Button c) Mude as seguintes propriedades do Button1:
{$R *.DFM} procedure EscondeBarraTarefa(EstadoBarra: Boolean); var wndHandle : T Handle; wndClass : array[0..50] of Char; begin StrPCopy(@wndClass[0],’Shell_TrayWnd’); wndHandle := FindWindow(@wndClass[0], nil); If EstadoBarra=True Then ShowWindow(wndHandle, SW_RESTORE) {Mostra a barra de
100 DICAS DE DELPHI
tarefas} Else ShowWindow(wndHandle, SW_HIDE); {Esconde a barra de tarefas} end;
18
h) Na parte uses da interface da unit (untEmpresaUsuario) insira a cláusula: Registry interface uses
3) Pegando o nome do usuário e a empresa do Windows Crie um subdiretório chamado “Usuário” utilizando o Windows Explorer. Feche o projeto que estiver aberto usando a opção Close all dentro do menu File e crie um novo projeto utilizando a opção New Application também no menu File. a) Mude as seguintes propriedades do Form1: Name: frmEmpresausuario Caption: programa para ler do Windows nome do usário e empresa Position: poScreenCenter BorderStyle: bsDialog Height: 123 Width: 441 b) Insira um Botão no formulário: na Paleta de Componentes Standard Button c) Mude as seguintes propriedades do Button1: Name: btnUsuario Caption: pegar nome do usuário e empresa no Windows Width: 241 d) Insira duas Caixas de Edição no formulário: na Paleta de Componentes Standard - Edit e) Mude as seguintes propriedades do Edit1: Name: EdtUsuario Text: vazio Width: 417 f) Mude as seguintes propriedades do Edit2: Name: EdtEmpresa Text: vazio Width: 417
OBS.: Salve o projeto no subdiretório que você criou: g) A Unit1 salve com o nome de untEmpresaUsuario, e o Project1 com o nome de Usuario.
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry; No evento onClick do botão btnUsuario inclua as seguintes linhas de código: procedure T Form1.Button1Click(Sender: TObject); var reg: T RegIniFile; begin reg := TRegIniFile.create(‘SOFTWARE\MICROSOFT\MS SETUP (ACME)\’); EdtUsuario.Text := reg.ReadString(‘USER INFO’,’DefName’,’’); EdtEmpresa.Text := reg.ReadString(‘USER INFO’,’DefCompany’,’’); reg.free; end;
4) Como arrastar um Form sem clicar no Caption? Quando você pressiona o botão do mouse, o Windows identifica a posição da tela onde o cursor estava no momento do clique. Se a posição é igual a área do Caption do Form, o Windows ativa o modo de movimentação do Form permitindo que este seja arrastado. Portanto, a maneira mais fácil de solucionar esta questão é “enganar” o Windows. Neste exemplo, vamos considerar que o usuário poderá arrastar o Form ao clicar na área cliente deste Form: a) Crie uma nova aplicação; b) Adicione a seguinte declaração na seção private do Form: procedure WMNCHitTest(var M: T WMNCHitTest); message wm_NCHitTest; c) Adicione o código deste procedimento na seção implementation do Form: procedure T Form1.WMNCHitTest(var M: T WMNCHitTest); begin inherited; { ativa a
herança da mensagem } if M.Result = htClient then {o clique foi na área cliente? } M.Result := htCaption; { se sim, faz o Windows pensar que foi no Caption. } end; Este exemplo tratou o clique na área cliente. Você pode alterar este código para suas necessidades. Eis os possíveis valores para o Result: VALOR - Local do clique HT BORDER - Borda da janela que não tem a borda de tamanho HT BOT TOM - Borda horizontal inferior da janela HT BOT TOMLEFT - Canto inferior esquerdo da janela HT BOT TOMRIGHT - Canto inferior direito da janela HTCAPT ION - Barra de Título(Caption) HTCLIENT - Área cliente HT ERROR - igual ao HT NOWHERE, a diferença é que produz um beep indicando erro HTGROWBOX - Caixa de tamanho (igual ao HTSIZE) HT HSCROLL - Barra de rolagem horizontal HT LEFT - Borda esquerda da janela HT MENU - Em um menu HT NOWHERE - Plano de fundo da janela ou linha de divisão entre janelas HT REDUCE - Botão minimizar HT RIGHT - Borda direita da janela HTSIZE - Caixa de tamanho (igual ao HTGROWBOX) HTSYSMENU - Botão de Sistema/ Fechar da janela MDIChild HT TOP - Borda horizontal superior da janela HT TOPLEFT - Canto superior esquerdo da janela HT TOPRIGHT - Canto direito superior da janela HT T RANSPARENT - Janela em segundo plano HT VSCROLL - Barra de rolagem vertical HT ZOOM - Botão maximizar
5) Bloquear a tecla Ctrl+Del do DBGrid. procedure T Form1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
100 DICAS DE DELPHI
begin if ((Shift = [ssCtrl]) and (key = vk_delete)) THEN Abort; end;
6) ESCONDENDO A APLICAÇÃO DA BARRA DE TAREFAS Para fazer com que o ícone da aplicação em Delphi desapareça da Barra de Tarefas, execute o código a seguir: var H : HWnd; begin H := FindWindow(Nil,’Project1'); if H <> 0 then ShowWindow(H,SW_HIDE); end;
7) OS COMANDOS INC e DEC Você sabia que existe uma opção para a comum linha de comando: Variavel:=Variavel+1; ? Os comandos INC e DEC permitem agilizar o processamento do seu sistema. Para isso, substitua a linha acima por:
19
60/60); end;
KeyPreview do formulário como True. Depois, insira este código no evento OnKeyDown do formulário:
10) DESABILITANDO O SPLASH SCREEN DO REPORT SMIT H
procedure T Form1.FormKeyDown(Sender: TObject; var Key: Word; Shift: T ShiftState); begin if Key = VK_F5 then showMessage(‘I pressed the F5 key’); end;
1 - Localize o arquivo RS_RUN.INI (no diretório do Windows); 2 - Na seção [ReportSmith] inclua a linha seguinte: ShowAboutBox=0 3 - Na seção [RS_RunTime] inclua a linha seguinte: ShowAboutBox=0 4 - Não se esqueça de distribuir com o seu aplicativo o referido arquivo INI.
11) Lendo o volume do HD Function ExtractDiskSerial(Drive:String):String; Var Serial:DWord; DirLen,Flags: DWord; DLabel : Array[0..11] of Char; begin GetVolumeInformation(PChar(Drive+’:\’),dLabel,12,@Serial,DirLen,Flags,nil,0); Result := IntToHex(Serial,8); end;
INC(variavel); ou DEC(variavel) se você quiser diminuir ao invés de aumentar 1.
8) COMO FAZER UM BEEP NO COMPUTADOR messageBeep(0);
9) COMO FAZER UMA PAUSA POR UM PERÍODO DET ERMINADO NumSec é o tempo em segundos de espera var NumSec SmallInt; StartTime: T DateTime; begin StartTime := now; NumSec:=10; repeat Application.ProcessMessages; until Now > StartTime + NumSec * (1/24/
12) descobrindo o número serial do hd procedure T Form1.Button1Click(Sender: TObject); var SerialNum : pdword; a, b : dword; Buffer : array [0..255] of char; begin if GetVolumeInformation(‘c:\’, Buffer, SizeOf(Buffer), SerialNum, a, b, nil, 0) then Label1.Caption := IntToStr(SerialNum^); end;
Você também pode usar as variáveis VK_F1 até VK_F12 referentes às outras teclas de função.
15) T RADUZINDO A MENSAGEM: “Delete Record?” Quando clicamos sobre o botão de deleção no DBNavigator (o do sinal de menos) surge um box com a mensagem “Delete Record?” com botões Ok e Cancel. Para que apareça a mensagem em português, você deverá selecionar o componente Table e mudar a propriedade ConfirmDelete para False e no evento da tabela BeforeDelete colocar o seguinte (flaviojr@cyber.com.br): procedure TForm1.Table1BeforeDelete(DataSet:TDataSet); begin if MessageDlg(‘Eliminar o Registro?’,mtConfirmation,[mbYes,mbNo],0)<>mrYes then Abort; end;
16) INCLUIr UM PREVIEW PERSONALIZADO nO QUICK REPORT No relatório, criar a procedure SHOWPREVIEW, contendo: Procedure Showpreview; begin preview.showmodal; end;
14) INT ERCEPTAR AS TECLAS DE FUNÇÃO (f1, f2, f3...)
Onde preview é o nome do form criado para preview. Não esquecer de incluir o nome da procedure na cláusula uses. Após isso, deve-se incluir no evento CREAT E do formulário principal ou do relatório o direcionamento do objeto Qprinter, como a seguir:
Primeiro, coloque a propriedade
qprinter.onpreview:=showpreview;
13) PARA SABER SOMENT E O PATH DA APLICAÇÃO ExtractFilePath( Application.ExeName )
100 DICAS DE DELPHI
Isso faz com que toda vez que você queira exibir um preview, o programa abra a rotina showpreview, abrindo o formulário criado, chamado preview.
17) EXECUTANDO PROGRAMAS EXT ERNOS Se você precisa abrir programas externos no seu aplicativo Delphi, como a calculadora do Windows, por exemplo, inclua a seguinte linha no seu programa: WinExec(‘calc.exe’, sw_show); ‘calc.exe’ é o nome do programa. Caso queira abrir um outro programa, altere este nome.
18) UTILIZANDO A TECLA ENTER PARA SALTAR DE CAMPO Insira este código em um evento OnKeyPress de um controle de edição: procedure T Form1.Edit1KeyPress(Sender: TObject; var Key: Char); begin If Key = #13 Then Begin SelectNext(Sender as tWinControl, True, True ); Key := #0; end; end;
19) Tocando um som Wav sem o Media Player Acrescente MMSystem na Uses do começo na Unit Utilize a API SndPlaySound(); Para interromper o som sem ele acabar de tocar utilize a API PlaySound(nil,0,0); Ex: SndPlaySound(‘c:\teste.wav’, snd_ASync); PS: snd_Loop serve para repetir continuamente o som.
20) Obter o diretório onde seu programa está instalado Crie uma váriavel do tipo String e insira a seguinte linha no evento ou função
20
desejada do formulário: ExtractFilePath(Application.Exename); Retornará o path atual do arquivo EXE do seu programa.
21) Como bloquear um arquivo em ambiente de rede É uma dica simples, mas muito importante! Quando você programar visando uma rede e quiser bloquear um arquivo é só chamar o metodo edit da tabela que estiver usando. EX: Table1.edit; PS: Se o registro já estiver bloqueado ocorrerá um erro. Então, faça o seguinte : try { para verificar o erro } Table1.edit; exception on T DBEngineError do { o erro..} MessageDlg(‘Registro ja esta sendo usado...!’, mtInformation, [ mbOk ], 0 ); end;
22) Usando Enter para mudar de campo de um DBGrid If ( Chr(Key) <> #13) Then Exit; If ( DBGrid1.SelectedIndex + 1 <> DBGrid1.FieldCount ) Then DBGRid1.SelectedIndex := DBGRid1.SelectedIndex + 1;
23) Função para obter o número do registro atual Function Recno(Dataset: T Dataset): Longint; var CursorProps: CurProps; RecordProps: RECProps; begin { Return 0 if dataset is not Paradox or dBASE } Result := 0; with Dataset do begin if State = dsInactive then DBError(SDataSetClosed); Check(DbiGetCursorProps(Handle, CursorProps)); UpdateCursorPos; try Check(DbiGetRecord(Handle,
dbiNOLOCK, nil, @RecordProps)); case CursorProps.iSeqNums of 0: Result := RecordProps.iPhyRecNum; { dBASE } 1: Result := RecordProps.iSeqNum; { Paradox } end; except on EDBEngineError do Result := 0; end; end; end;
24) Enviando um arquivo para a lixeira uses ShellAPI; Function DeleteFileWithUndo(sFileName : string ) : boolean; var fos : TSHFileOpStruct; begin FillChar( fos, SizeOf( fos ), 0 ); With fos do begin wFunc := FO_DELET E; pFrom := PChar( sFileName ); fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMAT ION or FOF_SILENT; end; Result := ( 0 = ShFileOperation( fos ) ); end;
25)carregarumcursoranimado(*.ani) const cnCursorID1 = 1; begin Screen.Cursors[ cnCursorID1 ] := LoadCursorFromFile(‘c:\win95\cursors\cavalo.ani’ ); Cursor := cnCursorID1; end; PS: O arquivo CAVALO.ANI deverá existir no diretório apontado.
26) Transferir o conteúdo de um Memo para o MemoField var
100 DICAS DE DELPHI
t: T Table; begin t := T Table.create(self); with t do begin DatabaseName := ‘MyAlias’; {Nome do Alias} TableName := ‘MyTbl.db’; open; edit; insert; FieldByName(‘TheField’).assign(Memo1.lines); post; { Requerido!!!} close; end; end;
27) Capturando o conteúdo do Desktop Coloque o código abaixo no evento FormResize do formulário. procedure T Form1.FormResize(Sender: TObject); var R : T Rect; DC : HDc; Canv : TCanvas; begin R := Rect( 0, 0, Screen.Width, Screen.Height ); DC := GetWindowDC( GetDeskTopWindow ); Canv := TCanvas.Create; Canv.Handle := DC; Canvas.CopyRect( R, Canv, R ); ReleaseDC( GetDeskTopWindow, DC ); end;
28) Escrevendo um texto diagonal usando o canvas procedure T Form1.Button1Click(Sender: TObject); var begin with Form1.Canvas do begin Font.Name := ‘Arial’; Font.Size := 24; tf := T Font.Create; tf.Assign(Font); GetObject(tf.Handle, sizeof(lf), @lf); lf.lfEscapement := 450; lf.lfOrientation := 450; tf.Handle := CreateFontIndirect(lf); Font.Assign(tf); tf.Free; TextOut(20, Height div 2, ‘Texto Diagonal!’);
21
end; end; 29) extrair um icone de um determinado aplicativo Para extrair ícones de um executável, deve-se usar a função da API Extraction. Ela usa três parâmetros: Instance - Instância da aplicação FileName - Nome do executável. Deve ser um PChar NumIcon - Número do ícone a ser recuperado. Se for Word(-1), a função retorna a quantidade de ícones do executável. Coloque ShellAPI em uses no começo da unit. procedure T Form1.Button1Click(Sender: TObject); var IconIndex : word; h : hIcon; begin IconIndex := 0; h := ExtractAssociatedIcon(hInstance,’C:\WINDOWS \NOT EPAD.EXE’,IconINdex); DrawIcon(Form1.Canvas.Handle,10,10,h); end;
30) Alinhando items do menu à direita Para alinhar itens do menu principal à direita, deve-se utilizar o seguinte código: {Isto justifica todos itens à direita do selecionado} procedure SetJustify(Menu: T Menu; MenuItem: T MenuItem; Justify: Byte); {$IFDEF WIN32} var ItemInfo: T MenuItemInfo; Buffer: array[0..80] of Char; {$ENDIF} begin {$IFDEF VER80} MenuItem.Caption := Chr(8) + MenuItem.Caption; {$ELSE} ItemInfo.cbSize := SizeOf(T MenuItemInfo); ItemInfo.fMask := MIIM_T YPE; ItemInfo.dwTypeData := Buffer; ItemInfo.cch := SizeOf(Buffer); GetMenuItemInfo(Menu.Handle, MenuItem.Command, False, ItemInfo); if Justify = 1 then
ItemInfo.fType := ItemInfo.fType or MFT_RIGHTJUST IFY; SetMenuItemInfo(Menu.Handle, MenuItem.Command, False, ItemInfo); {$ENDIF} end;
31) abrir automaticamente seu navegador padrão e carregar a página determinada pelo link 1º Declare o procedure na seção Public da unit. procedure JumpTo(const aAdress: String); 2º Coloque a cláusula ShellAPI na uses no início da unit. procedure T Form1.JumpTo(const aAdress: String); var buffer: String; begin buffer := ‘http://’ + aAdress; ShellExecute(Application.Handle, nil, PChar(buffer), nil, nil, SW_SHOWNORMAL); end; procedure TForm1.Label1Click(Sender: TObject); begin JumpTo(‘www.geocities.com/ SiliconValley/Way/1497’); end;
32) copiar registros de uma tabela para outra incluindo valores NULL procedure TtableCopiaRegistro(Origem, Destino: Ttable); begin with TabelaOrig do begin {Inicia um contador para os campos da TabelaOrig} for i := 0 to FieldCount -1 do {Este if verifica se o campo da TabelaOrig é NULL, se for, atribui seu valor ao campo da TabelaDest} if not Fields[i].IsNull then TabelaDest.Fields[i].Assign(Fields[i]); end; {end with} end; Este exemplo funcionará com todos os
100 DICAS DE DELPHI
tipos de campos se você tiver acabado de criar a TabelaDest. Para criar um dado valor NULL : Fields[i].Clear
33) deletar arquivos de um diretório com o caractere curinga ‘*’ procedure TForm1.SpeedButton1.Click(Sender: TObject); var SearchRec: TSearchRec; Result: Integer; begin Result:=FindFirst(‘c:\teste\*.*’, faAnyFile, SearchRec); while result=0 do begin DeleteFile(‘c:\teste\’+SearchRec.Name); Result:=FindNext(SearchRec); end; end;
34) capturar a lista de Aliases disponíveis Tudo o que você precisa é de um componente TSession, um componente T ListBox e uma String List. Defina a propriedade SessionName do TSession para ‘Session’. Utilize o seguinte código: procedure T Form1.Button3Click(Sender: TObject); var MyStringList: TStringList; i: integer; begin MyStringList := TStringList.Create; Session.GetAliasNames(MyStringList); for I := 0 to MyStringList.Count - 1 do ListBox1.Items.Add(MyStringList[I]); end; Utilize o Help do TSession e consulte seus métodos para ver, por exemplo, como capturar o diretório ou caminho de um Alias com o método ‘GetAliasParams’.
35) Abrir e Fechar a bandeja DO drive de CD-ROM
22
{Para Abrir:} mciSendString(‘Set cdaudio door open wait’, nil, 0, handle); {Para Fechar:} mciSendString(‘Set cdaudio door closed wait’, nil, 0, handle);
36) Utilizando o Code Explorer A versão 4 do Borland Delphi está recheada de novos recursos em várias áreas do produto (IDE, Internet, linguagem, aplicações multi-tier, entre outras). Uma das primeiras coisas que notamos quando abrimos o editor de código do Delphi 4 é a presença de um painel ancorado na lateral esquerda, contendo todos os tipos, classes, propriedades, métodos, variáveis globais, rotinas globais e interfaces contidos na unit selecionada. Este painel é chamado Code Explorer e seu objetivo é tornar mais fácil a navegação entre as units do projeto e automatizar alguns processos envolvidos na criação de classes. O Code Explorer também permite que você navegue diretamente para as declarações que são apresentadas nele, bastando dar um duplo clique com o mouse sobre a declaração desejada. Novas declarações podem ser feitas também usando o Code Explorer, facilitando o desenvolvimento do código. Por exemplo, vamos supor que você queira criar uma nova função chamada Calculo com dois parâmetros do tipo real e que retornará também um real. Para isso, deve-se seguir os seguintes passos: Selecione a pasta Variable/Constants dentro do Code Explorer. Dê um clique com o botão direito do mouse e selecione New no menu que aparecerá, como mostra a figura a seguir. O Code Explorer apresentará um novo item que permite identificar qual o tipo de declaração que está sendo feita, por meio da informação que o programador passar a ele. No nosso exemplo, digitaremos o cabeçalho da função Calculo como segue : function Calculo(x, y : real) : real; Após digitar a declaração e pressionar <Enter>, o Code Explorer criará automaticamente o cabeçalho da função na seção
Interface e a sua implementação na seção Implementation da unit, como mostra a figura seguinte, evitando assim que ocorram erros de declaração no interior do código. Um outro recurso que o Code Explorer fornece é conhecido como Class Completion. O programador pode, dentre outras facilidades, criar apenas o básico da declaração de uma propriedade e, com o simples toque de um atalho no teclado, o Code Explorer completará a declaração. Como exemplo, vamos declarar uma propriedade chamada Cor do tipo TColor dentro da nossa classe T Form 1. type TForm1=class(T Form) private {declarações privadas} public {declarações públicas} property Cor:TColor; end; Agora, com o cursor posicionado sobre a declaração da propriedade, pressionamos <Ctrl><Shift>C e o Code Explorer completará toda a declaração da estrutura da classe.
37) Copiando arquivos via Delphi 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;
100 DICAS DE DELPHI
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;
23
end; No exemplo, a variável Data é do tipo T DateTime.
41) Verificar se existe disquete no drive unit UTestaDrive; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type T Form1 = class(T Form) Button1: T Button; procedure Button1Click(Sender: TObject); function TemDiscoNoDrive(const drive : char): boolean; private { Private declarations } public { Public declarations }
38) abrir um TComboBox sem clicá-lo
end;
ComboBox1.DroppedDown := True;
var Form1: T Form1;
39) mudar a cor da célula ativa do DBGrid
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: T Rect; Field: T Field; State: TGridDrawState); begin if gdFocused in State then with (Sender as T DBGrid).Canvas do begin Brush.Color:=clRed; FillRect(Rect); TextOut(Rect.Left, Rect.Top, Field.AsString); end; end;
40) Como incrementar um mês numa data
procedure T Form1.Button1Click(Sender: TObject); begin if TemDiscoNoDrive(‘a’) then ShowMessage(‘Tem disco No drive A:’) else ShowMessage(‘Não tem Disco no Drive A:’); end; end.
42) Acessar o ambiente DOS Para acessar as variáveis do ambiente DOS, deve-se usar a função da API GetDosEnvironment. Ela retorna um PChar que pode ser avaliado.
43) Executar um programa (DOS) e fechar sua janela em seguida Quando você executa um programa DOS no Windows 95, sua janela permanece aberta até ser fechada pelo usuário. Para executar um programa DOS que fecha sua janela após a execução, deve ser especificado “command.com /c programa” na linha de comando. Usando a função da API WinExec para executar um programa chamado proddos.exe, a chamada deve ser:
implementation {$R *.DFM}
A rotina abaixo deverá ser colocada no evento OnDrawDataCell, do DBGrid.
end;
IncMonth(Data, 1);
function T Form1.TemDiscoNoDrive(const drive : char): boolean; var DriveNumero : byte; EMode : word; begin result := false; DriveNumero := ord(Drive); if DriveNumero >= ord(‘a’) then dec(DriveNumero,$20); EMode := SetErrorMode(SEM_FAILCRITICALERRORS); try if DiskSize(DriveNumero$40) = -1 then Result := true else messagebeep(0); finally SetErrorMode(EMode);
WinExec(‘c:\command.com /c progdos.exe’, sw_ShowNormal); Se o programa deve ser executado sem que seja visualizado pelo usuário, o segundo parâmetro deve ser sw_Hide. Deve ser especificada a extensão .com, senão o programa não será executado.
44) instanciar uma única vez um executável correspondente a uma determinada aplicação No Microsoft® Windows®, existe uma tabela do sistema chamada ‘atom table’. Esta tabela armezena strings com seus correspondentes identificadores. Existem várias funções da API do Windows, chamadas de ‘atom functions’, que permitem que uma aplicação insira, apague, procure por uma determinada ‘atom string’, etc. O código abaixo garante que somente uma instância do
100 DICAS DE DELPHI
executável de sua aplicação estará carregado em memória. O form1 seria o form principal da aplicação: procedure T Form1.FormCreate(Sender: TObject); begin {Procura na tabela para verificar se o programa já está rodando} {Substitua a string ‘MINHA ST RING’ por uma de sua conveniência} if GlobalFindAtom(‘MINHA ST RING’) = 0 then {zero significa não encontrar} atom := GlobalAddAtom(‘MINHA ST RING’) else begin {Se o programa já estiver rodando, então mostrar a mensagem e parar} MessageDlg(‘A aplicação já encontra-se em execução!!’, mtWarning, [mbOK], 0); Halt; end; end; procedure T Form1.FormDestroy(Sender: TObject); begin {Remove o item da tabela, de modo que a aplicação possa ser executada novamente} GlobalDeleteAtom(atom); end; 45) Modificar várias propriedades de um objeto ao mesmo tempo Utilize o comando with, desse modo: With Edit1 do begin Text := ‘ @Delphi’; Widht := 30; Enabled := True; end;
46) Para emitir um som quando o ENTER for pressionado No Evento OnKeyPress de um Edit: if Key = Chr(VK_RETURN) then Perform(WM_NEXT DLGCT L,0,0);
47) Encolhendo o executável
24
Em Delphi 1.0, marcando a checkbox Optimize for size and load time, em Options/Project/Linker, não funciona (aparece uma mensagem de erro de disco cheio, mesmo com muito espaço). O Delphi 1.0 vem com um programa DOS, W8LOSS, que faz o mesmo. Para usá-lo, deve-se digitar o seguinte:
s:=StrPas(dummy); w:=StrLen(dummy); for x:=1 to w do begin c:=s[x]; c:=char ( ord (c) xor 159); s[x]:=c; end; StrPCopy(dummy,s); encrypt:=dummy;
W8LOSS programa.exe Isto encolherá o executável em aproximadamente 20%, diminuindo o tempo de carga.
48) criar alias via programação Paradox: Session.AddStandardAlias(‘SeuAlias’, edtPath.text, ‘Paradox’); Session.SaveConfigFile;
49) desabilitar as teclas de acesso (Ctrl+Alt+Del), (Alt+Tab), (Ctrl+Esc) var OldValue : LongBool; begin {liga a trava} SystemParametersInfo(97, Word(True), @OldValue, 0); {desliga a trava} SystemParametersInfo(97, Word(False), @OldValue, 0); end;
50) Fazer um Splash Screen form2:=tform2.create(application); form2.show; form2.update; form2.hide; form2.free; Application.Run; Obs.: apagar a primeira linha, ‘Application.Initialize’.
51) FUNÇÃO PARA ENCRIPTAR UMA ST RING function encrypt( dummy: Pchar):Pchar; var x: Integer; w: Word; s: String; c: Char; begin
end;
52) Função reverter uma string function T Form1.StrReverse(MyString : string) : String; var i: integer; HelpString: string; begin HelpString := ‘’; for i := 1 to Length(MyString) do HelpString := MyString[i]+HelpString; Result := HelpString; end;
53) função de CONVERT ER UM NúMERo inteiro para binário {Integer to Binary} function IntToBin(Value: LongInt;Size: Integer): String; var i: Integer; begin Result:=’’; for i:=Size downto 0 do begin if Value and (1 shl i)<>0 then begin Result:=Result+’1'; end else begin Result:=Result+’0'; end; end; end;
54) função de CONVERT ER UM NúMERo binário para inteiro {Binary to Integer} function BinToInt(Value: String): LongInt; var i,Size: Integer;
100 DICAS DE DELPHI
begin Result:=0; Size:=Length(Value); for i:=Size downto 0 do begin if Copy(Value,i,1)=’1' then begin Result:=Result+(1 shl i); end; end; end;
55) função para encriptar e descriptar uma String const StartKey
25
FICAR ERROS EM TODA A APLICAÇÃO Para tratar erros de forma genérica, em todo o seu programa, insira no método ON CREAT E do formulário principal a linha: Application.OnException:=RotinaGeral; RotinaGeral é uma procedure na qual deverá constar o código para verificar e enviar as mensagens de erro do seu sistema.
57) Enviando informações direto para a impressora
= 981; {Start default
key} MultKey = 12674; {Mult default key} AddKey = 35891; {Add default key} {Encriptar} function Encrypt(const InString: string; StartKey,MultKey,AddKey: Integer): string; var I: Byte; begin Result := ‘’; for I := 1 to Length(InString) do begin Result := Result + CHAR(Byte(InString[I]) xor (StartKey shr 8)); StartKey := (Byte(Result[I]) + StartKey) * MultKey + AddKey; end; end; {Descriptar} function Decrypt(const InString: string; StartKey,MultKey,AddKey: Integer): string; var I: Byte; begin Result := ‘’; for I := 1 to Length(InString) do begin Result := Result + CHAR(Byte(InString[I]) xor (StartKey shr 8)); StartKey := (Byte(InString[I]) + StartKey) * MultKey + AddKey; end; end;
56) UMA ROT INA PARA VERI-
Muitas vezes torna-se necessário, ou até mesmo, imprescindível que você envie informações diretamente para a impressora, uma vez que a utilização da impressão típica do Windows é um pouco demorada e o uso do driver Genérico/ Somente Texto não é muito confiável. Uma boa solução para enviar informações diretamente para a impressora é usar o seguinte código: Procedure TForm1.Button1Click(Sender: Object); var Imp: TextFile; begin AssignFile(Imp, ‘LPT1’); Rewrite(Imp); Write(Imp, ‘Isto vai sair na impressora’); CloseFile(Imp); end; Desta forma será possível, inclusive, utilizar os códigos de configuração da impressora. Para a impressora padrão Epson, por exemplo, você poderia utilizar algo assim: Write(Imp, #27#69 + ‘Teste’ + #27#70); { impressão em negrito } Write(Imp, #15 + ‘Teste’ + #18); { impressão no modo condensado } Write(Imp, #12); { salto de página }
Algumas opções, principalmente em impressoras matriciais, são obtidas através do envio dos chamados “códigos de escape” para a impressora (por exemplo, alterar espaçamento entre as linhas (#45), tipo de fonte (#18, #23), etc). Em versões 16-bit do Windows, isso não era complicado, mas agora, nas versões 32-bit, o acesso direto ao hardware não é mais possível. Portanto, para enviarmos caracteres diretamente a impressora, devemos utilizar o “escape” chamado “PASST HROUGH” do Windows e enviarmos a informação desejada diretamente. Na documentação do Win32 SDK este escape é dado como obsoleto, mas enquanto utilizarmos impressoras matriciais que necessitem de “códigos escape” para certas funcionalidades, ele será necessário. Ao utilizar impressoras Postscript tenha cuidado, pois nem sempre esta técnica irá funcionar. Em impressoras matriciais, você pode enviar qualquer tipo de caracteres que achar necessário. Abaixo segue um código exemplificando o envio de uma string qualquer diretamente ao buffer da impressora: uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type T Form1 = class(T Form) Button1: T Button; procedure Button1Click(Sender: TObject); end; var Form1: T Form1; implementation {$R *.DFM} uses Printers;
58) Enviando Caracteres Diretamente ao Buffer da Impressora Ao trabalharmos com impressão, em certos casos desejamos alterar o comportamento da impressora.
type { Tipo requerido pelo PASST HROUGH } T BufferImpressora = record TamanhoBuffer: Word; Buffer: array [0..255] of Char;
100 DICAS DE DELPHI
end; procedure T Form1.Button1Click(Sender: TObject); var Buff: T BufferImpressora; TestePasstrough: Integer; strFoo: string; begin { Primeiro devemos checar se o “escape” PASST HROUGH é suportado. Para isso, executamos a função “Escape” passando o QUERYESCSUPPORT. Caso o driver suporte, ela irá retornar um valor maior que 0 } TestePasstrough := PASST HROUGH; if Escape(Printer.Handle, QUERYESCSUPPORT, SizeOf(PASST HROUGH), @TestePasstrough, nil) > 0 then begin { Inicializamos o driver } Printer.BeginDoc; { Informação qualquer a enviar diretamente para a impressora } strFoo := ‘Passthrough string’; { Copia da string para a estrutura } StrPCopy(Buff.Buffer, strFoo); { Indicamos o tamanho da informação} Buff.TamanhoBuffer := StrLen(Buff.Buffer); { Enviamos o “escape” } Escape(Printer.Canvas.Handle, PASST HROUGH, 0, @Buff,nil); { Descarregamos... } Printer.EndDoc; end; end; end.
59) Imprimir diretamente para a impressora sem passar pelo gerenciador de impressão procedure T Form1.Button1Click(Sender: TObject); var F : TextFile; i : integer; begin AssignFile(F,&rsquo;LPT1'); Rewrite(F);
26
i := 0; Writeln(F,&rsquo;Teste de impressao Linha 0'); Writeln(F,&rsquo;Teste de impressao Linha 1'); Writeln(F,#27#15+&rsquo;Teste de Impressão - Linha 2'); Writeln(F,&rsquo;Teste de impressao Linha 3'); Writeln(F,#27#18+&rsquo;Teste de Impressão - Linha 4'); Writeln(F,&rsquo;Teste de impressao Linha 5'); Writeln(F,#12); // Ejeta a página CloseFile(F); end;
60) Criar barra de status com suporte às caixas de edição do Windows 95 No evento OnCreate do Form: Application.OnHint := DisplayHint; Crie (e defina) uma Procedure DisplayHint (no Form Principal): StatusBar1.Panels[0].Text := Application.Hint;
61) Capturando uma tela do windows procedure T Form1.Button1Click(Sender: TObject); var DeskTopDC: HDc; DeskTopCanvas: TCanvas; DeskTopRect: T Rect; begin DeskTopDC := GetWindowDC(GetDeskTopWindow); DeskTopCanvas := TCanvas.Create; DeskTopCanvas.Handle := DeskTopDC; DeskTopRect := Rect(0,0,Screen.Width,Screen.Height); Form1.Canvas.CopyRect(DeskTop Rect,DeskTopCanvas,DeskTopRect); ReleaseDC(GetDeskTopWindow,DeskTopDC); end;
62) compactar de uma tabela Paradox Para compactar (remover fisicamente todos registros apagados) de uma tabela Paradox deve-se utilizar o seguinte código:
procedure ParadoxPack(Table : T Table); var T BDesc : CRTblDesc; hDb: hDbiDb; TablePath: array[0..dbiMaxPathLen] of char; begin FillChar(T BDesc,Sizeof(T BDesc),0); with T BDesc do begin StrPCopy(szTblName,Table.TableName); StrPCopy(szTblType,szParadox); bPack := True; end; hDb := nil; Check(DbiGetDirectory(Table.DBHandle, True, TablePath)); Table.Close; Check(DbiOpenDatabase(nil, ‘STANDARD’, dbiReadWrite, dbiOpenExcl,nil,0, nil, nil, hDb)); Check(DbiSetDirectory(hDb, TablePath)); Check(DBIDoRestructure(hDb,1,@TBDesc,nil,nil,nil,False)); Table.Open; end;
63) Configurações internacionais Normalmente o Delphi busca os formatos de data/hora, moeda e formato numérico da Configuração Internacional do Painel de Controle. Isto pode levar a erros quando avaliando datas, números ou listas. Para evitar estes erros, você pode mudar as constantes definidas no Delphi, como DecimalSeparator, ShortFormatDate e outros desta maneira: DecimalSeparator :=’.’; ShortFormatDate :=’mm/dd/yy’; Isto terá precedência sobre a configuração padrão. Para uma lista completa das variáveis, procure em Currency Formating Variables na ajuda do Delphi.
64) Listando todas as janelas abertas Para listas (pegar) todas as janelas abertas, deve-se usar a função API EnumWindows, que usa uma função Callback, com dois parâmetros, um
100 DICAS DE DELPHI
27
Handle para a janela e um ponteiro. Você pode usá-la como um código semelhante a este (este lista as janelas abertas, mesmo invisíveis, em uma listbox):
Turn monitor on SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
em rede.
function EnumWindowsProc(Wnd: HWnd; Form:T Form1): Boolean; Export; {$ifdef Win32} StdCall; {$endif} var Buffer: Array[0..99] of Char; begin GetWindowText(Wnd, Buffer, 100); if StrLen(Buffer)=0 then
67) Invertendo os Botões do Mouse
Para fazer pesquisa incremental numa tabela usando um EDIT, deve-se colocar o seguinte código em seu evento OnChange:
Form.ListBox1.Items.Add(StrPas(Buffer)); Result :=True; end; procedure T Form1.Button1Click(Sender: TObject); begin EnumWindows(@EnumWindowsProc, LongInt(Self)); end;
65) Primeira letra de um EditBox maiúscula Para converter a primeira letra de um EditBox para maiúsculas este código pode ser utilizado: procedure T Form1.Edit1Change(Sender: TObject); var OldStart: Integer; begin with Edit1 do if Text <> ‘’ then begin OnChange :=NIL; OldStart :=SelStart; Text :=UpperCase(Copy(Text,1,1) )+LowerCase(Copy(Text,2,Length(Text))); OnChange :=Edit1.Change; end; end;
66) Desligar e Ligar o Monitor (Off/On) Turn monitor off SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, 0);
Adicionar à cláusula Uses, Shellapi. Digitar os seguintes parâmetros: Swapmousebutton(true) ; Para voltar ao normal basta mudar para False.
70) Pesquisa incremental numa tabela
procedure T Form1.Edit1Change(Sender: TObject); begin Width Edit1 do if Text <>’’ then Table1.FindNearest([Text]); end;
68) Mudar o Papel de Parede do Windows Primeiro deve-se adicionar à cláusula Uses, ShellApi. Em seguida deve-se digitar os seguinte comandos: procedure T Form1.FormCreate(Sender: TObject); var Arquivo: String; begin Arquivo:=’c:\windows\nuvens.bmp’; SystemParametersInfo(SPI_SetDeskWallPaper, 0, PChar(Arquivo), 0); end;
69) Acessando arquivos Paradox em rede Arquivos Paradox podem ser compartilhados em rede. Para que isto ocorra devemos: Adicionar o Database Engine Configuration (BDE Config); Selecionar a página Drivers; Selecionar o driver PARADOX e alterar o parâmetro NET DIR para o local onde serão gravados os arquivos de controle para compartilhamento. Por exemplo, “G:\MEUAPLIC”, onde G corresponde ao drive de rede e MEUAPLIC, o diretório onde está o aplicativo (executável); Depois selecionar a página System; Alterar o parâmetro LOCAL SHARE para T RUE. Após isto o BDE controlará o compartilhamento de arquivos Paradox
71) incluir mais de uma linha no Hint Para incluir mais de uma linha no Hint você deve utilizar o evento OnMouseMove de cada componente. Veja abaixo como ficará o código em um Edit por exemplo: procedure T Form1.Edit1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin Edit1.hint := &lsquo;Primeira Linha&rsquo;+#13+&rsquo;Segunda Linha&rsquo;+#13+ &lsquo;Terceira Linha&rsquo;+#13+&rsquo;Quarta Linha&rsquo;; end; Obs. Não esquecer de mudar para T RUE a propriedade ShowHint.
72) Como saber se o aplicativo já foi aberto Esta dica só funciona em Delphi 1.0 e não no win95, mas como bom micreiro, coloquei também a versão para W95, que segue abaixo: No Projeto (.DPR): uses windows, messages, necessarios acrescentar Forms, ...........
//
var Hwnd: T Handle; // variavel necessaria
100 DICAS DE DELPHI
begin Hwnd:=FindWindow(‘O seu T Form’, ‘O caption do seu form principal’); if Hwnd = 0 then begin Application.Initialize; end else begin if not IsWindowVisible(Hwnd) then begin // se minimizado ShowWindow(Hwnd, SW_SHOWNORMAL); //mostra PostMessage(Hwnd, WM_USER, 0, 0); //restaura end; SetForegroundWindow(Hwnd); visivel end;
//
No Programa principal coloque: private { Private declarations } public procedure WMUser(var msg: T Message); message WM_USER; // definicao { Public declarations } end;
28
uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls; type TfrmSobreManager = class(T Form) btnOK: T Button; ProductName: T Label; Version: T Label; Label1: T Label; Label2: T Label; Label3: T Label; Copyright: T Label; Panel1: T Panel; Image2: T Image; GroupBox1: TGroupBox; Bevel1: T Bevel; stOSVersao: T StaticText; stOSBuilder: T StaticText; stOS: T StaticText; stOSService: TStaticText; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var frmSobreManager: TfrmSobreManager;
implementation
implementation
{$R *.DFM}
{$R *.DFM}
procedure T Principal.WMUser(var msg: T Message); //uso de fato. begin Application.restore; end;
// VERIFICA E APRESENTA AS INFORMAÇÕES do SIST EMA OPERACIONAL (FaC)
73) Mostrar e alterar resoluções de vídeo Para mostrar as resoluções de vídeo disponíveis, deve-se usar a função da API EnumDisplaySettings: ela pega todos os modos de vídeo disponíveis. Para alterar os modos, deve-se usar a função ChangeDisplaySettings, que muda a resolução de vídeo e quantidade de cores.
74) Verificar sistema operacional unit sobreManager; interface
procedure TfrmSobreManager.FormCreate(Sender: TObject); var verInfo : TOsVersionInfo; str : String; I : Word; begin verInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); if GetVersionEx(verInfo) then begin stOSVersao.Caption := ‘Versão : ‘+ IntToStr(verInfo.dwMajorVersion) + IntToStr(verInfo.dwMinorVersion); stOSBuilder.Caption := ‘Compilação : ‘+IntToStr(verInfo.dwBuildNumber); str := ‘Sistema Operacional : ‘; case verInfo.dwPlatformId of VER_PLAT FORM_WIN32s : stOS.Caption := str +’Windows 95';
VER_PLAT FORM_WIN32_WINDOWS : stOS.Caption := str +’Windows 95 Osr2 / 98'; VER_PLAT FORM_WIN32_NT : stOS.Caption := str +’Windows NT ’; end; str := ‘’; for I := 0 to 127 do str := str + verInfo.szCSDVersion[I]; stOSService.Caption := ‘Informações Adicionais : ‘+ str; end end; end.
75) Nome do usuário logado na rede Existe na API do BDE uma funcao chamada DbiGetNetUserName, que retorna o nome do usuário logado. Tente o seguinte: function GetUserName:string; var Nome: array[0..64] of char; begin if DbiGetNetUserName(Nome) <> DBIERR_NONE then Nome:=’’; Result:=StrPas(Nome); end;
76) capturar o nome das tabelas de um banco de dados Crie um Alias para o seu banco da dados(Fizemos com um banco do Interbase). Adicione o seguinte código ao seu programa(Neste caso o código foi feito no evento OnActivate do Form1): procedure TForm1.FormActivate(Sender: TObject); Var MyStringList: TStringList; i: Integer; begin try MyStringList:= TStringList.Create; Session.GetTableNames(‘SeuAlias’,’*.*’,False, False, MyStringList); For i:= 1 To MyStringList.Count-1 do
100 DICAS DE DELPHI
ListBox1.Items.Add(MyStringList.Strings[i]); finally MyStringList.Free; end; end; O método GetTableNames trabalha com cinco parâmetros: 1-Item do tipo String=Nome do Alias do banco desejado. 2-Item do tipo String=Especifique um filtro para retornar somente as tabelas desejadas. Podem incluir símbolos(Wildcards) como por exemplo ‘*’. 3-Item do tipo Boolean=Para pesquisas em Paradox e dBASE, defina True para incluir a extensão do arquivo como parte do nome da tabela. Para tabelas SQL, defina False. 4-Item do tipo Boolean=Defina True para tabelas SQL para receber também o nome das tabelas de sistema as quais contém a estrutura dos dados. Defina False para tabelas Paradox e dBASE. 5-Item do tipo TStringList=Nome do StringList onde serão guardados os nomes das tabelas.
77) Tabela dos caracteres especiais utilizados como máscara: Caracter Definições ! Faz com que a digitação da máscara fique parada no primeiro caracter, fazendo com que os caracteres digitados que se movam. Ex: !;0;_ > Todos os caracteres digitados serão convertidos para maiúsculas. Ex: >aaa;0;_ < Todos os caracteres digitados serão convertidos para minúsculas. Ex: <> Anula o uso dos caractes > e <, ou seja, utilizado para cancelar a opção de máscara para os caracteres a direita. Ex: >aaa<>aaa;0;_ \ Utilizado para marcar determinado caracter não especial como fixo. Ex: !\(999\)000-0000;0;_ L Exige caracteres alfabéticos obrigatórios para a posição, do tipo A-Z, a-z. Ex: LLL;1;_ l Somente caracteres alfabéticos para a posição, mas não-obrigatórios, do tipo AZ, a-z. Ex: lll;1;_ A Exige caracteres alfanuméricos obrigatórios para a posição, do tipo A-Z, a-z, 09. Ex: AAA;1;_ a Somente caracteres alfanuméricos para
29
a posição, mas não-obrigatórios, do tipo A-Z, a-z, 0-9. Ex: aaa;1;_ C Requer um caracter obrigatório para a posição. Ex: CCC;1;_ c Permite o uso de qualquer caracter para a posição, limitando apenas o número de caracteres. Ex: ccc;1;_ 0 Exige caracteres numéricos obrigatórios para a posição, do tipo 0-9. Ex: 000;1;_ 9 Somente caracteres numéricos para a posição, não-obrigatórios, do tipo 0-9. Ex: 999;1;_ # Somente caracteres numéricos para a posição e o uso dos sinais de - ou +, nãoobrigatórios. Ex: ###;1;_ : Utilizado como separador de horas, minutos e segundos. / Utilizado como separador de dia, mês e ano.
78) Traduzir captions e botões da MessageDlg Para traduzir algumas as mensagens do Delphi que aparecem nos botões e nas caixas de avisos da função MessageDlg, você necessita dos arquivos de recursos do Delphi (*.RC). Possuo o Delphi 2 - Developers, que vem acompanhado de alguns destes arquivos de recursos. No meu caso, eles estão gravados em C:\DELPHI2\SOURCE\VCL. Os arquivos *.RC são arquivos “só texto”, e contêm diversas mensagens utilizadas nos programas compilados no Delphi. O exemplo que se segue realiza alterações nos arquivos CONSTS.RC e DBCONSTS.RC. A alteração de outros arquivos “RC” pode ser feita de modo similar. Para maiores detalhes, envie-me um e-mail (paulosd@dglnet.com.br), ou, melhor ainda, consulte o livro “Dominando o Delphi” (edição para o Delphi 1), de Marcos Cantù, ed. Makron Books. O assunto “Usando recursos de tabelas de strings” está no capítulo 21, página 876. Não sei se a edição para o Delphi 2 cobre este assunto. a) Faça uma cópia dos arquivos CONSTS.RC e DBCONST S.RC em um diretório seguro, para o caso de algo sair errado. b) Pelo mesmo motivo, faça uma cópia dos arquivos CONST S.RES e DBCONSTS.RES, que estão no diretório LIB do Delphi. No meu caso, o diretório destes arquivos é C:\DELPHI2\LIB.
c) Use o Bloco de Notas para abrir e alterar os arquivos CONSTS.RC e DBCONSTS.RC. (O Edit também serviria; entretanto, para acentuação correta no Windows, o Bloco de Notas é melhor). Você só deve alterar as strings que estão entre aspas. Não altere o nome das constantes, que estão no início de cada linha. Por exemplo, localize o seguinte bloco, em CONSTS.RC: SCancelButton, “Cancel” SYesButton, “&Yes” SNoButton, “&No” Altere para: SCancelButton, “Cancelar” SYesButton, “&Sim” SNoButton, “&Não” Não é necessário alterar todas as mensagens. Se desejar, altere apenas aquelas que você utiliza em seus sistemas. Lembre-se de salvar as alterações efetuadas. d) Acione o prompt do DOS, e execute do seguinte modo o compilador de recursos do Delphi 2 (BRC32.EXE), que está no diretório BIN do Delphi (no meu caso, C:\DELPHI2\BIN): C:\DELPHI2\BIN\BRC32 -R CONSTS.RC C:\DELPHI2\BIN\BRC32 -R DBCONSTS.RC (No Delphi 1, o compilador tem o seguinte nome: BRC.EXE). e) Os dois comandos anteriores irão gerar os arquivos CONSTS.RES e DBCONSTS.RES. Copie os dois “*.RES” para o diretório LIB do DELPHI (no meu caso C:\DELPHI2\LIB) f) Crie uma aplicação no Delphi que utilize a função MessageDlg, e botões “BitBtn”. Ao rodar o seu programa, as mensagens já devem aparecer traduzidas.
79) último acesso de um arquivo unit Uultimoacesso; {object Form1: T Form1 Left = 230 Top = 186 Width = 435
100 DICAS DE DELPHI
Height = 167 Caption = ‘Ultimo Acesso’ Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -16 Font.Name = ‘Arial’ Font.Style = [] PixelsPerInch = 96 TextHeight = 18 object Label1: T Label Left = 6 Top = 11 Width = 53 Height = 18 Caption = ‘Arquivo’ end object Label2: T Label Left = 6 Top = 58 Width = 101 Height = 18 Caption = ‘Último Acesso’ end object EdArquivo: T Edit Left = 6 Top = 28 Width = 281 Height = 26 TabOrder = 0 end object BtSeleciona: T Button Left = 226 Top = 82 Width = 87 Height = 31 Caption = ‘Seleciona’ TabOrder = 1 OnClick = BtSelecionaClick end object EdUltimoAcesso: T Edit Left = 6 Top = 82 Width = 204 Height = 26 TabOrder = 2 end object ODSelecionaArquivo: TOpenDialog Left = 352 Top = 8 end end } interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
30
type T Form1 = class(T Form) EdArquivo: T Edit; BtSeleciona: T Button; Label1: T Label; Label2: T Label; EdUltimoAcesso: T Edit; ODSelecionaArquivo: TOpenDialog; procedure BtSelecionaClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: T Form1; implementation {$R *.DFM} procedure TForm1.BtSelecionaClick(Sender: TObject); var FileHandle : T Handle; LocalFileTime : T FileTime; DosFileTime : DWORD; LastAccessdTime : T DateTime; FindData : T Win32FindData; NomeArquivo : array[0..255] of char; begin if OdSelecionaArquivo.Execute then begin EdArquivo.Text := OdSelecionaArquivo.FileName; StrPCopy(NomeArquivo,OdSelecionaArquivo.FileName); FileHandle := FindFirstFile(NomeArquivo, FindData); if FileHandle = INVALID_HANDLE_VALUE then begin Windows.FindClose(Handle); if (FindData.dwFileAttributes and FILE_AT T RIBUT E_DIRECTORY ) = 0 then begin FileTimetoLocalFileTime(FindData.ftLastWriteTime, LocalFileTime); FileTimeToDosDateTime(LocalFileTime, LongRec(DosFileTime).Hi, LongRec(DosFileTime).Lo); LastAccessdTime := FileDateToDateTime(DosFileTime); EdUltimoAcesso.Text := DateTimeToStr(LastAccessdTime); end; end;
end; end; end.
80) Obtendo as informações de versão dos arquivos Um dos recursos disponibilizados pelo Delphi é a customização das informações de versão a serem “anexadas” na linkagem. Pouco utilizado, este recurso é muito interessante, pois possibilita o cadastro de diversas informações sobre o arquivo gerado, como: número de versão, nome do produto, nome interno do arquivo, nome da empresa, etc. Podemos alterar as informações na página “Version Info”, da página “Project Options”: Atenção com o item “Auto-increment build number”: ele só será incrementado automaticamente quando for executada a opção “Build All” para compilar o projeto. Porém, não existem rotinas “prontas” para obtermos estas informações. É necessário fazermos chamadas diretamente a API Win32, mais espeficamente, para as funções como a “GetFileVersionInfo” e a “VerQueryValue”. Abaixo encontramos uma função, a “FileVerInfo”, que exemplifica o processo de obtenção das informações. Ela irá retornar “True” caso o arquivo informado no parâmetro “FileName” possuir as informações de versão, e devolverá por referência um “TStringList” contendo as informações.
//Código uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type T Form1 = class(T Form) Memo1: T Memo; Button1: T Button; procedure Button1Click(Sender: TObject); end; var Form1: T Form1;
100 DICAS DE DELPHI
implementation {$R *.DFM} function FileVerInfo(const FileName: string; var FileInfo: TStringList): Boolean; const Key: array[1..9] of string =(‘CompanyName’, ‘FileDescription’, ‘FileVersion’, ‘InternalName’, ‘LegalCopyright’, ‘OriginalFilename’, ‘ProductName’, ‘ProductVersion’, ‘Comments’); KeyBr: array [1..9] of string = (‘Empresa’, ‘Descricao’, ‘Versao do Arquivo’, ‘Nome Interno’, ‘Copyright’, ‘Nome Original do Arquivo’, ‘Produto’, ‘Versao do Produto’, ‘Comentarios’); var Dummy : T Handle; BufferSize, Len : Integer; Buffer : PChar; LoCharSet, HiCharSet : Word; Translate, Return : Pointer; StrFileInfo, Flags : string; TargetOS, TypeArq : string; FixedFileInfo : Pointer; i : Byte; begin Result := False; { Obtemos o tamanho em bytes do “version information” } BufferSize := GetFileVersionInfoSize(PChar(FileName), Dummy); if BufferSize <> 0 then begin GetMem(Buffer, Succ(BufferSize)); try if GetFileVersionInfo(PChar(FileName), 0, BufferSize, Buffer) then { Executamos a função “VerQueryValue” e conseguimos informações sobre o idioma /character-set } if VerQueryValue(Buffer, ‘\VarFileInfo\Translation’, Translate, UINT(Len)) then begin LoCharSet := LoWord(Longint(Translate^)); HiCharSet := HiWord(Longint(Translate^)); for i := 1 to 9 do begin { Montamos a string de pesquisa } StrFileInfo := Format(‘\StringFileInfo\0%x0%x\%s’,
31
[LoCharSet, HiCharSet, Key[i]]); { Adicionamos cada key pré-definido } if VerQueryValue(Buffer,PChar(StrFileInfo), Return, UINT(Len)) then FileInfo.Add(KeyBr[i] + ‘: ‘ + PChar(Return)); end; if VerQueryValue(Buffer,’\’,FixedFileInfo, UINT(Len)) then with T VSFixedFileInfo(FixedFileInfo^) do begin Flags := ‘’; {Efetuamos um bitmask e obtemos os “flags” do arquivo} if (dwFileFlags and VS_FF_DEBUG) = VS_FF_DEBUG then Flags := Concat(Flags,’*Debug* ‘); if (dwFileFlags and VS_FF_SPECIALBUILD) = VS_FF_SPECIALBUILD then Flags := Concat(Flags, ‘*Special Build* ‘); if (dwFileFlags and VS_FF_PRIVAT EBUILD) = VS_FF_PRIVAT EBUILD then Flags := Concat(Flags, ‘*Private Build* ‘); if (dwFileFlags and VS_FF_PRERELEASE) = VS_FF_PRERELEASE then Flags := Concat(Flags, ‘*PreRelease Build* ‘); if (dwFileFlags and VS_FF_PATCHED) = VS_FF_PATCHED then Flags := Concat(Flags, ‘*Patched* ‘); if Flags <> ‘’ then FileInfo.Add(‘Atributos: ‘ + Flags); TargetOS := ‘Plataforma (OS): ‘; { Plataforma } case dwFileOS of VOS_UNKNOWN : TargetOS := Concat(TargetOS, ‘Desconhecido’); VOS_DOS : TargetOS := Concat(TargetOS, ‘MS-DOS’); VOS_OS216 : TargetOS := Concat(TargetOS, ’16bit OS/2'); VOS_OS232 : TargetOS := Concat(TargetOS, ’32bit OS/2'); VOS_NT :
TargetOS := Concat(TargetOS, ‘Windows NT’); VOS_NT_WINDOWS32, 4: TargetOS := Concat(TargetOS, ‘Win32 API’); VOS_DOS_WINDOWS16: TargetOS := Concat(TargetOS, ’16bit Windows ‘, ‘sob MS-DOS’); else TargetOS := Concat(TargetOS, ‘Fora do Padrão. Código: ‘, IntToStr(dwFileOS)); end; FileInfo.Add(TargetOS); TypeArq := ‘Tipo de Arquivo: ‘; { Tipo de Arquivo } case dwFileType of VFT_UNKNOWN : TypeArq := Concat(TypeArq,’Desconhecido’); VFT_APP : TypeArq := Concat(TypeArq,’Aplicacao’); VFT_DLL : TypeArq := Concat(TypeArq,’Dynamic-Link Lib.’); VFT_DRV : begin TypeArq := Concat(TypeArq,’Device driver - Driver ‘); case dwFileSubtype of VFT2_UNKNOWN : TypeArq := Concat (TypeArq, ‘Desconhecido’); VFT2_DRV_PRINT ER : TypeArq := Concat(TypeArq,’de Impressao’); VFT2_DRV_KEYBOARD : TypeArq := Concat(TypeArq,’de Teclado’); VFT2_DRV_LANGUAGE : TypeArq := Concat(TypeArq,’de Idioma’); VFT2_DRV_DISPLAY : TypeArq := Concat(TypeArq,’de Vídeo’); VFT2_DRV_MOUSE : TypeArq := Concat(TypeArq,’de Mouse’); VFT2_DRV_NET WORK : TypeArq := Concat(TypeArq,’de Rede’); VFT2_DRV_SYST EM : TypeArq := Concat(TypeArq,’de Sistema’); VFT2_DRV_INSTALLABLE : TypeArq := Concat(TypeArq,’Instalavel’); VFT2_DRV_SOUND : TypeArq := Concat(TypeArq,’Multimida’); end; end; VFT_FONT : begin TypeArq := Concat(TypeArq,’Fonte - Fonte ‘); case dwFileSubtype of VFT2_UNKNOWN : TypeArq := Concat(TypeArq, ‘Desconhecida’); VFT2_FONT_RAST ER : TypeArq := Concat(TypeArq,’Raster’);
100 DICAS DE DELPHI
VFT2_FONT_VECTOR : TypeArq := Concat(TypeArq,’Vetorial’); VFT2_FONT_T RUET YPE : TypeArq := Concat(TypeArq,’TrueType’); end; end; VFT_VXD : TypeArq := Concat(TypeArq,’Virtual Device’); VFT_STAT IC_LIB : TypeArq := Concat(TypeArq,’Static-Link Lib.’); end; FileInfo.Add(TypeArq); end; end; finally FreeMem(Buffer, Succ(BufferSize)); Result := FileInfo.Text <> ‘’; end; end; end; procedure T Form1.Button1Click(Sender: TObject); var StrLst: TStringList; begin StrLst := T StringList.Create; try FileVerInfo(‘C:\WINDOWS\SYSTEM\TAPI.DLL’, StrLst); Memo1.Lines.Assign(StrLst); finally StrLst.Free; end; end;
32
end;
var ii: integer; begin ShortDateFormat := ‘dd/mm/ yyyy’; DecimalSeparator := ‘.’; ThousandSeparator := ‘,’; for ii := 1 to 7 do begin ShortDayNames[ii] := arrShortDayNames[ii]; LongDayNames[ii] := arrLongDayNames[ii]; end; for ii := 1 to 12 do begin ShortMonthNames[ii] := arrShortMonthNames[ii]; LongMonthNames[ii] := arrLongMonthNames[ii]; end;
var Bitmap: T Bitmap; Offset: Integer; begin with (Control as TComboBox).Canvas do begin FillRect(Rect); Bitmap:= TBitmap(ComboBox1.Items.Objects[index]); if Bitmap nil then begin
-Ajuste a propriedade Style do ComboBox para csOwnerDrawVariable.
BrushCopy(Bounds(Rect.Left + 2, Rect.Top + 2, Bitmap.Width, Bitmap.Height), Bitmap, Bounds(0, 0, Bitmap.Width, Bitmap.Height), clRed); Offset: Bitmap.width + 8; end; TextOut(Rect.Left + Offset, Rect.Top, ComboBox1.Items[index]); end;
var
end;
end;
82) Como colocar um bitmap num ComboBox
Form1: T Form1; Bmp1, Bmp2, Bmp3: T Bitmap;
81) Acerta padrão de data
implementation
procedure AcertaPadraoData;
{$R *.DFM}
const
procedure T Form1.FormCreate(Sender: TObject);
arrShortDayNames: array[1..7] of string[3] = (‘Dom’,’Seg’,’Ter’,’Qua’,’Qui’,’Sex’,’Sab’); arrLongDayNames: array[1..7] of string[15] = (‘Domingo’,’Segunda’,’Terça’,’Quarta’,’Quinta’, ‘Sexta’, ‘Sábado’); arrShortMonthNames: array[1..12] of string[3] = (‘Jan’,’Fev’,’Mar’,’Abr’,’Mai’,’Jun’,’Jul’,’Ago’, ‘Set’,’Out’,’Nov’,’Dez’); arrLongMonthNames: array[1..12] of string[15] = (‘Janeiro’,’Fevereiro’, ‘Março’,’Abril’,’Maio’, ‘Junho’,’Julho’,’Agosto’, ‘Setembro’,’Outubro’,’Novembro’,’Dezembro’);
procedure T Form1.ComboBox1DrawItem(Control: T WinControl; Index: Integer; Rect: T Rect; State: TOWnerDrawState);
begin
procedure TForm1.ComboBox1MeasureItem(Control: T WinControl; Index: Integer; var Height: Integer); begin Height:=20; end;
83) adicionando um Bookmarks
ComboBox1.Items.AddObject(‘Chip’,Bmp1);
Bookmarks permitem ao programador “memorizar” um determinado local da tabela para que possa retornar mais tarde, é muito simples e fácil de usar já que existem apenas três métodos que lhe permitem utilizar este recurso. Para marcar um determinado local em uma tabela necessitamos criar uma nova instancia de T Bookmark e executar o método GetBookMark de uma T Table.
ComboBox1.Items.AddObject(‘Zoom’,Bmp2);
var
ComboBox1.Items.AddObject(‘Disk’,Bmp3);
begin
Bmp1:=TBitmap.Create; Bmp.Loadfromfile(‘c:\chip16.bmp’); Bmp1:=TBitmap.Create; Bmp.Loadfromfile(‘c:\zoom.bmp’); Bmp1:=TBitmap.Create; Bmp.Loadfromfile(‘c:\disk.bmp’);
bmLocalImportante : T Bookmark;
100 DICAS DE DELPHI
bmLocalImportante := table.GetBookMark; {Para retornar a este local em particular a qualquer momento deve-se utiliza o método GotoBookMark() , este método recebe como parâmetro o T Bookmark recebido como retorno de GetBookMark.} table1.GotoBookMark(bmLocalImportante); {Após utilizar o Bookmark para o que desejar é importante que a memória utiliza por este recurso seja novamente liberada para o sistema,para executar esta operação utilize o método FreeBookMark.}
33
7. dê um clique com o botão direito do mouse sobre o Fields Editor e escolha New Field... 8. especifique os parametros para o novo campo a) Name: <algum nome> b) Type: <tipo do campo> c) Size: <tamanho> d) Field type: Lookup e) Key Field: <campo que receberá o valor escolhido no combobox& f) DataSet: Table2 g) LookUpKeys: <campo listado no combo> h) Result Field: <campo que será mostrado para o usuário no Combobox> 9. Execute a aplicação.
table1.FreeBookMark(bmLocalImportante); {Podem ser criados vários Bookmarks para uma mesma tabela, sendo este numero limitado apenas pela quantidade de memória livre no equipamento.}
85) Como conectar uma unidade de rede procedure T Form1.Button1Click(Sender: TObject);
end;
var
OBS:Mas cuidado com o uso indevido deste recurso, cada instancia de T BookMark reserva uma determinada porção de memória que só será novamente liberada para ser reutilizada após a execução de um FreeBookmark. Se vários Bookmarks forem criados e não liberados podem comprometer a execução do programa.
begin
NRW: T NetResource;
84) Inserindo um Combobox num DBGrid 1. insira um Datasource, um DBGrid e dois Table’s no form 2. link o Table1 com Datasource1 e DBGrid1 3. defina um banco de dados, uma tabela e ative o Table1 4. defina também para o Table2, mas use uma tabela diferente 5. adicione todos os campos do Table1 através do Fields Editor 6. mude a propriedade Visble para False do campo do Combobox
with NRW do begin dwType := RESOURCET YPE_ANY; lpLocalName := ‘G:’; lpRemoteName := ‘\\servidor\c’; lpProvider := ‘’; end; WNetAddConnection2(NRW, ‘MyPassword’, ‘MyUserName’, CONNECT_UPDAT E_PROFILE); end;
86) Configurar uma rede Novell Configurar uma rede Novell para trabalhar com Delphi é muito facíl, mais facíl que um rede ponto a ponto como Windows 95 ... Primeiro precisamos de um diretório onde será criado o NET FILE do Paradox, normalmente um diretório partindo do raiz do servidor será o suficiente, vamos usar o drive padrão da Novell para exemplificar o caso ...
Para o diretório onde serão armazenados os arquivos do seus sistema não é necessário nenhum cuidado especial, podemos assumir alguma configuração como a que segue ... F:\SIST EMA\DADOS <— diretório de dados Para quem trabalha todos os dias com uma rede Novell existe uma armadilha que pode causar umas noites mal dormidas :( ... Uma das coisas que muitos tentam para economizar um pouco do HD local é colocar o executável na rede, sem grandes problemas desde que você tenha um cuidado básico. Sempre que você executa um programa que trata com base Paradox o PRIVAT E DIR fica sendo o diretório onde este executável se encontra, no caso de você colocar este executável em um diretório da rede para ser acessado por muitos como fica este diretório PRIVAT E ??? jé não é mais tanto PRIVAT E né ... Para resolver este problema você deve “programaticamente” alterar o Private Dir para um diretório local,para isso você tem de adicionar as seguintes linhas de código ao iniciar a sua aplicação. Session.PrivateDir := ‘C:\WINDOWS\T EMP’; Para ter acesso a Session voce tem de incluir a unit DB na clausula Uses do seu projeto. Este cuidado pode prevenir varias travadas sem razão aparente em redes Novell.
87) Configuração de Rede Windows 95/98 com Delphi Vamos exemplificar com tres maquinas, 1 servidor chamado SERV e duas maquinas clientes. Claro que isto pode ser incrementado de acordo com suas necessidades :). No servidor:
F: <— drive da rede
diretório real D:\SIST EMA\DADOS
F:\NET DIR <— o diretório do NET FILE
compartilhe o subdiretorio
100 DICAS DE DELPHI
34 com todos os dados devidamente setados ...
D:\SIST EMA\DADOS como um recurso chamado Servidor_H
CreateTable; Procedure T MainForm.Inicializa;
no AUTOEXEC.BAT incluir à Subst H: D:\SIST EMA\DADOS
var
Nas maquinas clientes:
begin
Table1 : T Table;
mapear drive de rede H: como \\SERV1\Servidor_H No fim deste processo você terá o drive H: como sendo o seu Drive de rede para o Sistema, este drive estará presente em todas as maquinas e pode ser utilizado como seu NET DIR. No BDE Configuration: NET DIR:
H: (Para o driver Paradox)
Em seu Alias: Path:
H:\DADOS\
Em System: Local Share: True Depois disto você configurar o BDE de forma igual em todas as maquinas da rede.
88) Criar um arquivo em tempo de execução Criar um arquivo em tempo de execução é relativamente simples, você tem que criar uma instancia do objeto T Table, esse objeto (de uma lida no Help T Table e suas propriedades e metodos) tem um metodo de criação e um de Criar tabela. Depois disso é só definir as propriedades da nova tabela ... DatabaseName := ‘c:\lista’; TableName := ‘Produtos.dbf’; TableType := ttDbase; os campos da tabela ... Add(‘codigo’, ftString,7, false); Add(‘Nome’, ftString, 45, false); e os indices ... Add(‘prod1’, ‘codigo’, []); Add(‘prod2’, ‘Fornecedor’, []);
{ Criar componente T Table } Table1 := T Table.create(Application); { Definições de Campos e criação do arquivo } with Table1 do begin DatabaseName := ‘c:\lista’; TableName := ‘Produtos.dbf’; TableType := ttDbase; with FieldDefs do begin Clear; Add(‘codigo’, ftString,7, false); Add(‘Nome’, ftString, 45, false); Add(‘Fornecedor’, ftString, 5,false ); Add(‘Custo’, ftCurrency, 0, false ); Add(‘Venda’, ftCurrency, 0, false ); end; with IndexDefs do begin Clear; Add(‘prod1’, ‘codigo’, []); Add(‘prod2’, ‘Fornecedor’, []); end; CreateTable; end;
then key := #0; if key in [‘,’,’.’] then key := DecimalSeparator; if key = DecimalSeparator then if pos(key,T Edit(Sender).Text) <> 0 then key := #0; end;
if not(key in [‘0’..’9',’.’,’,’,#8,#13]) then key := #0; Se algum numero, ponto, virgula, BackSpace ou Enter for digitado então pode passar normalmente, caso contrario a tecla pressionada é ignorada. if key in [‘,’,’.’] then key := DecimalSeparator; Se ponto ou virgula, assume como separador decimal. if key = DecimalSeparator then if pos(key,T Edit(Sender).Text) <> 0 then key := #0; O separador decimal so pode ser digitado uma unica vez, na tentativa de uma segunda digitação ignora-se o símbolo.
end;
Observem que o mais importante aqui é o conceito utilizado, o fato de se interceptar os caracteres digitados pelo usuário e poder filtrar esses caracteres para evitar uma entrada de dados inconsistente. O exemplo de numero e símbolos não é conclusivo, uma vez que o mesmo efeito poderia ter sido obtido com a aplicação de uma mascara.
Utilizando o tipo ftCurrency, formato de valores do sistema financeiro o Delphi cria um campo Dbase com N,20,4
90) Criar arquivo DBF com indices compostos
89) Controle sobre digitação Quando alguém esta digitando algum valor que posteriormente será utilizado para calculo alguns cuidados são necessários, esse procedimento ValidaKey deve ser ligado no OnChange do T DBEdit para checar qual foi a tecla digitada. procedure ValidaKey(Const Sender:TObject; var key: char); begin if not(key in [‘0’..’9',’.’,’,’,#8,#13])
Quem trabalha com DBF’s já encontrou problemas para criar índices compostos, ou seja um índice que tenha mais de um campo, em tempo de execução. Isto ocorre por dois motivos, embora exista na internet documentação sobre o assunto, dizendo ser possível, ainda não encontrei ninguém que tenha tido sucesso nesta tarefa. O outro motivo é a existência de um parâmetro não documentado necessário para arquivos DBF’s ixExpression que informa o Delphi que se trata de um índice com mais de um campo.
100 DICAS DE DELPHI
35
Como trabalhar com DBF’s é comum para a maioria dos programadores que vem do Clipper acho interessante solucionar este problema da melhor forma possível. Assim a criação do indice fica para logo depois da criação da tabela, como mostra o segmento de codigo abaixo.
dando suporte ao modelo de objetos do Object Pascal e otimiza pra 386/486/ Pentium/Pentium Pro/MMX e Pentium II. O código é todo gerado para modo protegido e, devido a isso, não possui quaisquer limites para arrays ou ponteiros. Mas o melhor de tudo é que ele é GRAT IS!!!
uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, DBTables;
Para pega-lo vá o endereço abaixo:
procedure T Form1.Button1Click(Sender: TObject);
92) desenhar um bitmap no formulário
var Table1 : T Table; begin
var Form1: T Form1; Bmp: T Bitmap;
{ Criar arquivos } Table1 := T Table.create(Application);
<http://www.brain.uni-freiburg.de/ ~klaus/fpc/>
implementation {$R *.DFM}
{ Cria arquivo } with Table1 do begin Active := False; DatabaseName := ‘C:\’; TableName := ‘teste’; TableType := ttdBASE; with FieldDefs do begin Clear; Add(‘Name1’, ftString, 20, False); Add(‘Name2’, ftString, 20, False); Add(‘Name3’, ftString, 20, False); Add(‘Name4’, ftString, 20, False); end; CreateTable; AddIndex(‘Indice1’, ‘Name1 + Name2’, [ixExpression]); AddIndex(‘Indice2’, ‘Name2 + Name3’, [ixExpression]); AddIndex(‘Indice3’, ‘Name3 + Name4’, [ixExpression]); end;
procedure T Form1.FormCreate(Sender: TObject); begin Bmp:=T Bitmap.Create; Bmp.Loadfromfile(‘c:\windows\nuvens.bmp’); end; procedure T Form1.T Form1.FormPaint(Sender: TObject); begin Canvas.Draw(50,50,Bmp); end; procedure T Form1.FormClose(Sender: TObject; var Action: TCloseAction); begin Bmp.Free; end;
end;
93) evitando a saída de formulário
Na pratica criar os índices com AddIndex() logo após CreateTable não vai influenciar em nada o seu programa.
No evento OnCloseQuerie do form escreva o seguinte código:
91) Sistemas em Delphi para Linux Baixe na Internet um dos melhores compiladores de Pascal para DOS/OS2/ Linux. Suporta praticamente todo o set de opções do Borland Pascal e vai além,
procedure T Form1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose:=False; if messagebox(handle,’Deseja realmente fechar esta janela ?’, ‘Aviso’, mb_IconInformation + mb_YesNo + mb_DefButton2 ) = idYes then
CanClose := True; end;
94) desabilitando simultaneamente as teclas ( alt + f4 ) No evento OnCloseQuerie do form escreva o seguinte código: procedure T Form1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose:=False; end;
95) Filtrando Registros O caminho mais fácil e rápido para implementar filtros em tabelas é utilizando o evento OnFilterRecord, este evento é chamado sempre que um registro for lido do arquivo pelo componente T Table. OnFilterRecord é declarado como do tipo TFilterRecordEvent procedure(DataSet: T DataSet; var Accept: Boolean) of object; property OnFilterRecord: TFilterRecordEvent; A variável Accept deverá ser manipulada internamente em OnFilterRecord, assim para que o registro seja mostrado o valor de Accept tem de ser true que é o default. Tradicionalmente aplicar um filtro a uma tabela, qualquer que seja a tabela é um processo muito lento, assim é interessante desenvolver rotinas rápidas e fáceis de serem executadas. procedure TForm1.Table1FilterRecord(DataSet: T DataSet; var Accept: Boolean); begin Accept := (Dataset as T Table). FieldByName(‘Dupr_valida’).AsBoolean; end; Mas pode-se colocar varias verificações para decidir se um deter- minado registro deve ou não ser filtrado. procedure TForm1.Table1FilterRecord(DataSet: T DataSet; var Accept: Boolean);
100 DICAS DE DELPHI
begin with (Dataset as T Table) do if not ( (FieldByName(‘Dupr_Valida’).AsBoolean) and (FieldByName(‘Dupr_DataVenc’).AsString = ’05/09/97') ) then accept := false; end; O filtro pode ser ligado ou desligado a qualquer momento setando a propriedade Filtered da tabela, o evento OnFilterRecord só é chamado se a propriedade Filtered estiver com o valor true.
96) Como saber se um form já esta criado Bem saber se um form já esta ou não criado, melhor dizer instanciado, não é um problema muito critico, abaixo pode-se ver uma unit padrão criada com um form vazio no Delphi, esta unit alem de declarar o nova classe T Form1 cria também uma variável Form1 do tipo T Form1. Isto é muito importante que seja observado, um variável para um tipo “FORM” nada mais é que um ponteiro, ou seja ela apenas mostra em que local da memória esta a instancia do seu form, enquanto o seu form não existir este ponteiro deve apontar para lugar nenhum, ou seja, este ponteiro estará guardando o valor “NIL”. unit Unit1; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs;
36
implementation {$R *.DFM} end. {Partindo deste principio podemos verificar se um form foi ou não instanciado verificando o valor guardado em FORM1, se este valor for diferente de “NIL” significa que o Form já foi instanciado... bem a coisa não é assim tão simples, imagine que um amigo mudouse para São Paulo e lhe passou seu novo endereço, você recebe e anota em sua agenda... depois de dois meses ele resolve que não quer mais morar em São Paulo e vai embora, ok o fato de seu amigo ir embora por si só não vai fazer com que o endereço dele se auto apague da sua agenda, assim sendo quando o form for destruído o ponteiro continuara guardando o endereço de memória onde o form estava e ai o nosso método de controle vai pro brejo :( A forma mais limpa e automática para se contornar este problema nos obriga a codificar o seguinte no evento OnDestroy do Form ...} procedure T Form1.FormDestroy(Sender: TObject); begin Form1 := nil; end;
private { Private declarations } public { Public declarations }
Ex: Dados FORM1 e FORM2 Apenas FORM1 esta no AUTOCREATE Quando no uses de FORM1 for referenciada a unit UNIT2 a variável FORM2 estará acessível, use-a. FORM2 := T FORM2.CREAT E(SELF); 3 - Quando um Form é mostrado com ShowModal este tipo de controle não se aplica já que será impossível mostrar qualquer outro form.
97) não redimensionar o formulário Veja abaixo um exemplo para que o seu Form não seja redimensionado. Inclua o código abaixo em um Form. type
... interessante que o Show quando um form já esta criado tem o efeito de um BringToFront. Bem tudo isso resolve parte do problema, a outra parte tem de ser resolvida por você estruturando o seu programa de forma aos controles funcionem de acordo.
var Form1: T Form1; implementation {$R *.DFM}
1 - Este controle não funciona para forms com múltiplas instancias, a não ser que você crie uma variável para cada
procedure T Form1.WMGetMinMaxInfo(var Msg: T WMGetMinMaxInfo);
assim, quando o “FORM1” for destruído ele apaga o seu endereço junto, ótimo não é mesmo .... Assim quando for instanciar um form utilize a seguinte verificação ... if Form2 = nil then Form2 := T Form2.Create(Self); Form2.Show;
end; var Form1: T Form1;
2 - Quando for criar um novo form não crie variáveis desnecessariamente, utilize a variável que já esta sendo criada na unit do Form.
T Form1 = class(T Form) private { Private declarations } procedure WMGetMinMaxInfo(var Msg: T WMGetMinMaxInfo); message WM_GET MINMAXINFO; procedure WMInitMenuPopup(var Msg: T WMInitMenuPopup); message WM_INIT MENUPOPUP; procedure WMNCHitTest(var Msg: T WMNCHitTest); message WM_NCHitTest; public { Public declarations } end;
type T Form1 = class(T Form)
instancia. Pessoalmente eu nunca usei isso, se um form pode ter múltiplas instancias em MDI então controle por ActiveMDIChild e se for SDI então não sei porque ter mais de uma instancia.
100 DICAS DE DELPHI
begin inherited; with Msg.MinMaxInfo^ do begin ptMinTrackSize.x:= form1.width; ptMaxTrackSize.x:= form1.width; ptMinTrackSize.y:= form1.height; ptMaxTrackSize.y:= form1.height; end; end; procedure T Form1.WMInitMenuPopup(var Msg: T WMInitMenuPopup); begin inherited; if Msg.SystemMenu then EnableMenuItem(Msg.MenuPopup, SC_SIZE, MF_BYCOMMAND or MF_GRAYED) end; procedure T Form1.WMNCHitTest(var Msg: T WMNCHitTest); begin inherited; with Msg do if Result in [HT LEFT, HT RIGHT, HT BOT TOM, HT BOT TOMRIGHT, HT BOT TOMLEFT, HT TOP, HT TOPRIGHT, HT TOPLEFT ] then Result:= HT NOWHERE end;
98) Criando Forms Dinamicamente (SDI) Com certeza criar os forms que vc vai utilizar em tempo de execução é uma das grandes “sacadas” do Delphi, uma tarefa não tão complicada mas com varias alternativas de como ser executada. Vamos supor inicialmente que vc esta trabalhando com uma aplicação SDI (Single Document Interface) ou documento de interface simples, utilizando essa forma de desenvolvimento vc tem janelas sobre janelas, o Delphi é um exemplo disso, para criar um form em tempo de execução siga os seguintes passos: 1- Crie um projeto novo (SDI), o Delphi automaticamente cria o Form1. 2- Crie um Form Novo, ele recebera o nome de Form2. 3- Va em Options/Project, vc vai ver dois list boxes, o da esquerda contêm os forms que devem ser criados automaticamente quando sua aplicação for iniciada, os dois forms devem estar ai, pois bem mova
37
Form2 para o List Box da direita que deve conter os forms que ficam disponiveis porém não são automaticamente criados. (importante) Nesse momento você retirou do Delphi a obrigação de criar o Form2,se vc não o criar e em algum momento fizer referencia a ele isso deve causar um erro. 4- Ok, esqueca temporariamente Form2, em Form1 crie um botao e digite o código abaixo em seu evento TForm1.Button1Click implementation {$R *.DFM} uses Unit2; procedure T Form1.Button1Click(Sender: TObject); begin Form2 := T Form2.Create(self); Form2.Show; end; end. 5- Observe o uses criado logo após {$R *.DFM}, ele deve fazer referencia a Unit de Form2, que no caso do meu exemplo chama-se Unit2. Pronto, com esses pequenos cuidados vc ja estara criando seus forms em tempo de execução :) Agora uma dica interessante, se vc executar esse programa vc vai ver que quando Form2 for criado o usuario pode clicar em Form1 e esse recebera o foco, coisa que pode nao ser interessante. Para evitar este tipo de comportamento da sua aplicação utilize ShowModal e não Show para chamar o segundo form...
... Primeiro que em um projeto MDI não podem existir forms não visiveis, ou sejá, assim que um determinado form é criado ele já se torna visivel,não é necessario um SHOW ou SHOWMODAL para fazer isso, portanto não existe outro caminho senão criar todos os forms de sua aplicação em RUN T IME. Todos os passos descritos no exemplo acima são validos aqui também, mas para que o seu projeto caracterize-se como MDI você tem de mudar a propriedade FormStyle dos forms do projeto como segue : - O form principal da aplicação tem de estar como fsMDIForm. - Os outros forms que fazem parte da aplicação como fsMDIChild. Algum form especial, como o form onde o usuario configura a impressora, deve ser deixado como fsNormal. Vá até Project/Options e deixe apenas o form principal como AutoCreate. (importante) Nesse momento vc retirou do Delphi a obrigação de criar o Form2,se vc não o criar e em algum momento fizer referencia a ele isso deve causar um erro. Pois bem, como uma das caracteristicas de uma aplicação MDI é o form principal conter os outros forms não podemos ficar colocando botões para testar a criação dinamica desses forms, melhor utilizar um componente do tipo Menu e codificar a chamada aos outros forms nele ... implementation {$R *.DFM}
Form2 := T Form2.Create(self); Form2.ShowModal;
uses Unit2;
O ShowModal vai fazer com que a aplicação fique com Form2 permanentemente em primeiro plano, Form1 não poderá ser acessado até que Form2 sejá fechado.
procedure T Form1.Form21Click(Sender: TObject); begin Form2 := T Form2.Create(self); end;
99) Criando Forms Dinamicamente (MDI)
end.
A coisa muda um pouquinho quando voce esta trabalhando em um projeto MDI, basicamente o controle que voce tem de executar é o mesmo, mas as caracteristicas do projeto podem lhe trair
Uma das primeiras coisas diferentes é que não é mais necessário usar o Show :) ... Alguns cuidados devem ser tomados quando trabalhamos com uma aplicação MDI. Primeiro não existe porque ficar discutin-
100 DICAS DE DELPHI
do como evitar que o usuário fique abrindo muitos forms ao mesmo tempo, já que está é a principal qualidade de um projeto MDI, caso voce não queira este tipo de comportamento pare de ler e volte para SDI ...
100) Definido o tamanho mínimo e máximo de um form unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
38
type T Form1 = class(T Form) private { Private declarations } procedure WMGetMinMaxInfo(var MSG: T Message); message WM_GetMinMaxInfo; public { Public declarations } end; var Form1: T Form1; implementation
{$R *.DFM} procedure T Form1.WMGetMinMaxInfo(var MSG: TMessage); begin inherited; with PMinMaxInfo(MSG.lparam)^ do begin ptMinT RackSize.X := 300; ptMinT RackSize.Y := 150; ptMaxT RackSize.X := 350; ptMaxT RackSize.Y := 250; end; end; end.
SOBRE O AUTOR MARCELO JALOTO MACHADO MJALOTO@BOL.COM.BR
GEEK TIMES EXPEDIENTE Compilado por Juliano Barreto juliano@digerati.com.br Arte Fabio Augusto fabio@digerati.com.br