terça-feira, 24 de maio de 2011

Microsoft, Skype e Delphi


Como você certamente sabe, a Microsoft anunciou na última semana a compra do Skype, uma das maiores da história da companhia. De fato, pagaram 8.5 bilhões de dólares para a empresa de telefonia virtual conhecida mundialmente. Aqui eu não entrar em detalhes na questão financeira ou comentar sobre o preço (bastante algo, pelo que vejo, mas possivelmente bom para posicionar a Microsoft além de seus negócios tradicionais).

O que me interessa, ao invés disso, é focar em um detalhe, não menos importante. O cliente do Skype para Windows, de longe mais utilizado e de maior sucesso é escrito em Delphi. Alguém poderia perguntar se uma aplicação feita em Delphi vale 8 bilhões, quanto vale o Delphi? Mas isso não seria realista. Certamente é um bom anúncio para o Delphi, espero que o marketing da Embarcadero possa tirar proveito disso.

Usar Delphi foi bom para o Skype?

Da perspectiva de desenvolvedor, o real e mais importante é tentar descobrir o quanto a decisão de usar o Delphi foi boa para o Skype em primeiro lugar, se isso contribuiu para o sucesso do produto e da companhia, e se eles tivessem escolhido uma ferramenta diferente. Eu acho que a resposta para esta questão destaca alguns aspectos positivos do Delphi para ISVs (independent software vendor – fornecedor de software independente) que querem fazer a distribuição de suas aplicações facilmente.

De fato, a não necessidade de um ambiente de execução (como Java ou .NET) torna a distribuição de um programa em Delphi significativamente mais simples do que uma aplicação C# ou Java. Também, torna possível suportar um grande número de versões de Windows de um único executável. No momento o download do Skype é bem alto, mas costumava ser menor antigamente, quando a banda era mais limitada. Ainda, não requerer dúzias, quando não centenas, de megabytes de bibliotecas torna a distribuição ainda menor do que de aplicações gerenciadas. Além de não necessitar bibliotecas, não existe componente COM ou outras bibliotecas de configuração específica em Windows, novamente fazendo o processo de distribuição e instalação bem simples.

De outro lado, embora eu não conheça muito sobre como é o Skype internamente, a alta qualidade da integração de aplicações Delphi para Windows, o suporte a múltiplas bibliotecas de Socket e conjuntos de componentes visuais, permitem ajudar a criar mais facilmente um clone do Skype do que com outra de ferramentas de desenvolvimento não gerenciadas, como o Microsoft Visual C++.

Skype e Delphi

Sendo assim, acho que o Delphi contribuiu para o sucesso do Skype, embora é difícil dizer o quanto. Agora, pode o Skype contribuir para o sucesso do Delphi? Possivelmente... você não usaria uma ferramenta que lhe permite criar uma empresa de 8 bilhões? Piadas a parte, deixemos que todos saibam que o cliente do Skype para Windows é feito em Delphi e é uma ótima maneira de alavancar a ferramenta de desenvolvimento da Embarcadero. Mas o Skype não esta sozinho, veja o Show Case para uma maior gama de aplicações feitas em Delphi.

domingo, 22 de maio de 2011

Delphi.Net - Evitando o re-envio das informações no Refresh


Olá todos! Segue aqui uma dica para o pessoal que desenvolve para .net com delphi (BDS 2006). Como demorei para encontrar essa solução, resolvi compartilhá-la para ajudar os demais usuários de delphi.net

O problema é o seguinte: desenvolvi uma página em asp.net web forms do delphi que faz insert em um banco de dados SQL Server. Tudo funcionou OK, porém quando o usuário clicava no refresh do browser, este executava o último request feito ao servidor web e, se no caso fosse um insert por exemplo, ele efetuava o insert dinovo, ou seja. "PAU" rsrs !!! Desenvolvi uma solução simples implementando o evento page_prerender e page_load do lado do servidor.

Observação: a procedure Page_PreRender(sender: System.Object; e: System.EventArgs); não é iniciada pelo delphi quando vc cria um novo asp.net web form, portanto, sua declaração, implementação e inicialização tem que ser feita manualmente.

Segue abaixo o código:

unit WebForm1;

interface

uses
  System.Collections, System.ComponentModel,
  System.Data, System.Drawing, System.Web, System.Web.SessionState,
  System.Web.UI, System.Web.UI.WebControls, System.Web.UI.HtmlControls;

type
  TWebForm1 = class(System.Web.UI.Page)
  {$REGION 'Designer Managed Code'}
  strict private
    procedure InitializeComponent;
    procedure Button1_Click(sender: System.Object; e: System.EventArgs);
  {$ENDREGION}
  strict private
    procedure Page_Load(sender: System.Object; e: System.EventArgs);
    procedure Page_PreRender(sender: System.Object; e: System.EventArgs);
  strict protected
    Button1: System.Web.UI.WebControls.Button;
    TextBox1: System.Web.UI.WebControls.TextBox;
    procedure OnInit(e: EventArgs); override;
  private
    { Private Declarations }
  public
    { Public Declarations }
  end;

implementation

{$REGION 'Designer Managed Code'}
///

/// Required method for Designer support -- do not modify
/// the contents of this method with the code editor.
/// By Reinaldo Holanda Carlos
/// Diferenciar postback de um controle em relação ao refresh ... para que o refresh não execute
/// o último request repetidamente , isso pode evitar erros pois se o seu último request foi um insert
/// ele vai executar de novo esse insert clicando no refresh do browser ou com a tecla f5
/// com esse código identifico quando é um postback de um controle e quando é um postback do refresh do browser.
///

procedure TWebForm1.InitializeComponent;
begin
  Include(Self.Button1.Click, Self.Button1_Click);
  Include(Self.Load, Self.Page_Load);
  include(self.PreRender, self.Page_PreRender);
end;
{$ENDREGION}

procedure TWebForm1.Page_Load(sender: System.Object; e: System.EventArgs);
begin
  // TODO: Put user code to initialize the page here
  if not (IsPostBack) then //na primeira vez coloca data
  begin
    Session['CheckRefresh'] := Server.UrlDecode(System.DateTime.Now.ToString());
  end;
end;

procedure TWebForm1.Page_PreRender(sender: TObject; e: System.EventArgs);
begin
  ViewState['CheckRefresh'] := Session['CheckRefresh'];
end;

procedure TWebForm1.OnInit(e: EventArgs);
begin
  //
  // Required for Designer support
  //
  InitializeComponent;
  inherited OnInit(e);
end;

procedure TWebForm1.Button1_Click(sender: System.Object; e: System.EventArgs);
begin
    if (Session['CheckRefresh'].ToString() =
       ViewState['CheckRefresh'].ToString())  then
    begin
      Response.Write('

Request disparado por um CONTROLE

>'+'
');
      Response.Write(Session['CheckRefresh'].ToString()+' - '+ViewState['CheckRefresh'].ToString());
      Session['CheckRefresh'] := Server.UrlDecode(System.DateTime.Now.ToString());
    end
    else
    begin
      Response.Write('

Request disparado por um refresh do Browser: ' + request.Browser.Browser + '


');
      Response.Write(Session['CheckRefresh'].ToString()+' - '+ViewState['CheckRefresh'].ToString());
    end;
end;

end.

Ordenando registros via SQL pelo título das colunas do DBGrid


Esta dica vem para mostrar como fazer a ordenação dos registros do DBGrid ao se clicar no título das colunas, para quem não utiliza o ClientDataSet e precisa fazer a ordenação via SQL.

Caso você utilize o CDS, leia a dica "ClientDataSet - Clicando no Título das Colunas do DBGrid para Ordenar".

Primeiramente, crie um variável global ou pública (no meu caso eu criei com o nome "ordena") do tipo Boolean.

Depois inicialize ela quando abre o formulário, no evento onCreate, passando ela para True.

procedure TfrmLista_Grupo.FormCreate(Sender: TObject);
begin
  Ordena := True;
end;

Depois no evento DBGrid1TitleClick, faça o seguinte código:

procedure TfrmLista_Grupo.DBGrid1TitleClick(Column: TColumn);
var
  i : integer;
  coluna : String;
begin
  //para todas as colunas
  for i := 0 to DBGrid1.Columns.count-1 do
  begin
    DBGrid1.Columns[i].Title.Color := clBtnFace; //fundo padrão
    DBGrid1.Columns[i].Title.Font.Color := clBlack; //texto preto
    DBGrid1.Columns[i].Title.Font.Style := []; //sem efeito
  end;

  coluna := Column.FieldName;
  Column.Title.color := clInfoBk; //quando clicado ele muda a cor do titulo,fonte
  Column.Title.Font.Color := clBlue;
  Column.Title.Font.Style := [fsBold, fsItalic];
  if (Ordena) then
  begin
    IBDataSet.Active := false;
    IBDataSet.SelectSQL.Clear;
    IBDataSet.SelectSQL.Add('SELECT * FROM NOME_DA_TABELA ORDER BY ' + coluna);
    IBDataSet.Active := True;
    Ordena := False;
  end
  else
  begin
    IBDataSet.Active := false;
    IBDataSet.SelectSQL.Clear;
    IBDataSet.SelectSQL.Add('SELECT * FROM NOME_DA_TABELA ORDER BY ' + coluna + ' DESC');
    IBDataSet.Active := True;
    Ordena := True;
  end;
end;

Arredondamento Matemático


Veja nesta dica uma função que faz o arredondamento matemático de um número, assim como é feito pela calculadora

// <--- Faz arredondamento de forma matemática igual da calculadora
function TdmVendas.Arredondamento(Valor: Extended; Decimais: integer): Extended;
var
  Factor, Fraction, Arred : Extended;
  i : integer;
  vFraction : string;
  vlrFrac : Variant;
begin
  Factor := IntPower(10, Decimais);
  Valor := StrToFloat(FloatToStr(Valor * Factor));
  Result := Int(Valor);
  Fraction := Frac(Valor);
  vFraction := floattostr(Fraction);
  for i := 0 to Length(vFraction) do
  begin
      vlrFrac := Copy(vFraction,(Length(vFraction)-i),1);
      if vlrFrac = ',' then
      begin
         if Arred > 0 then
            Result := Result + 1;
         Result := Result / Factor;
         exit;
      end;
      vlrFrac := vlrFrac + Arred;
      Arred  := 0;
      if vlrFrac > 5 then
         Arred := 1;
  end;
end;

Antes de compilar, não esqueça de declarar ao uses a unit Math.

Recompilando as bibliotecas RTL no Delphi 7 - Adequação ao XP SP3


Com a última atualização do windows em vigor (Service Pack 3) percebi que meu Delphi 7 estava produzindo executáveis que estavam sendo bloqueados pelos Antivirus mais populares (como o AVG e o Avast), acusando-os de contaminados

Após muitas pesquisas, baseado na suposição de que a razão do fenômeno seria o SP3, experimentei a recompilação das bibliotecas RTL, o que resultou em solução do problema.

Para tanto, segue abaixo o procedimento:

    Ir para o diretório Delphi7 e fazer um backup do diretório 'lib';
    Ir para o diretório Delphi7\Source\Rtl. Neste local deve haver o arquivo 'makefile';
    Neste local, deve-se criar um subdiretório '\lib';
    Entrar no command-line e digitar 'MAKE';
    Serão produzidos arquivos 'dcu' no diretório 'lib' criado no passo 3;
    Sobrescrever estes arquivos no diretório lib original do Delphi7;

Pronto. RTL re-compilada.

segunda-feira, 16 de maio de 2011

Retornar o mês por extenso, usando array

Nesta dica, vamos criar uma função para retornar o mês por extenso, somente informando o número do mês.

Programando:

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
function MesExtenso( Mes:Word ) : string;
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

function TForm1.MesExtenso( Mês:Word ) : string; const meses : array[0..11] of PChar = ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro','Outubro', 'Novembro', 'Dezembro');
begin
result := meses[mes-1];
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
label1.Caption := MesExtenso(3);
end;

end.

terça-feira, 10 de maio de 2011

Usando MessageBox

Para que as mensagens apareçam em portugues (na lingua no sistema) não é necessário a tradução das units.

Invés de usar a função messagedlg eh melhor usar a função MessageBox

Sintax:

MessageBox (Handle, Messagem, Caption, Botoes)
onde

Handle : Endereço do form na memória ; Sempre usu Application.Handle
Messagem : A messagem a ser mostrada
Caption : O titulo da messagem
Botoes : Os Botoes que irao ser mostrados. Na lingua do sistema

MB_ABORTRETRYIGNORE A messagem mostra os tres botoes: Abort, Retry, and Ignore.
MB_OK A messagem mostra um botoao: OK. This is the default.
MB_OKCANCEL A messagem mostra os dois botoes: OK and Cancel.
MB_RETRYCANCEL A messagem mostra os dois botoes: Retry and Cancel.
MB_YESNO A messagem mostra os dois botoes: Yes and No.
MB_YESNOCANCEL A messagem mostra os tres botoes: Yes, No, and Cancel.
Sons
MB_ICONEXCLAMATION, MB_ICONWARNING: Mostra o icone de exclamação e som conrrespondente. Analo aos demais
MB_ICONINFORMATION, MB_ICONASTERISK
MB_ICONQUESTION
MB_ICONSTOP,
MB_ICONERROR,
MB_ICONHAND
Botoes padrao
MB_DEFBUTTON1: Padrao nao precisa ser colocado.
MB_DEFBUTTON2: Coloca o segundo botao como padrao
MB_DEFBUTTON3: Coloca o terceiro botao como padrao
MB_DEFBUTTON4: Coloca o quarto botao como padrao
Respostas
IDABORT
IDCANCEL
IDIGNORE
IDNO
IDOK
IDRETRY
IDYES

Exemplo:

Case MessageBox (Application.Handle, Pchar ('Deseja excluir o arquivo' + #13 + Label1.caption), 'Exclusao de arquivo', MB_YESNOCANCEL+MB_EXCLAMATION+MB_DEFBUTTON2) of
idYes: Procedimento
idNo: Procedimento
idCancel: Procedimento
end;

Curso de Delphi: 7.Consultas SQL