4 de dez. de 2004

Como funcionam os Namespaces em Delphi?

Marc Rohloff publicou um artigo no Borland Developer Network sobre como o Delphi 2005 trata a questão dos namespaces.

3 de dez. de 2004

Como criar uma constante array em C#?

O pessoal do C# Team da Microsoft escreveu sobre como criar uma constante array. A sugestão é fazer:

1 static readonly int [] constIntArray = 2 new int[] {1, 2, 3};
para criar um array de constantes inteiras. Mas existe um pequeno problema... embora o array não possa ser modificado, cada elemento individual pode ser alterado!

Como desenhar texto rotacionado em VB.NET?

Duncan Mackenzie escreveu sobre como desenhar texto rotacionado. O exemplo, em VB.NET, é:

1 Public Enum Direction As Integer 2 N = 0 3 NE = 1 4 E = 2 5 SE = 3 6 S = 4 7 SW = 5 8 W = 6 9 NW = 7 10 End Enum 11 12 Protected Overrides Sub OnPaint(ByVal e As 13 System.Windows.Forms.PaintEventArgs) 14 15 e.Graphics.Clear(Me.BackColor) 16 17 Dim bounds As Rectangle 18 Dim g As Graphics 19 Dim rotation As Single = 0 20 21 g = e.Graphics 22 bounds = New Rectangle(50, 50, Me.Width - 100, 23 Me.Height - 100) 24 25 Dim rect As System.Drawing.RectangleF 26 27 g.DrawEllipse(Pens.Black, bounds) 28 29 Dim myMatrix As Drawing2D.Matrix 30 Dim sf As New StringFormat(StringFormatFlags.NoWrap) 31 32 sf.Alignment = StringAlignment.Center 33 myMatrix = g.Transform() 34 rect = New System.Drawing.RectangleF(bounds.X, 35 bounds.Y, bounds.Width, bounds.Height) 36 37 For i As Integer = 0 To 7 38 If i > 0 Then 39 myMatrix.RotateAt(45, 40 New PointF(Me.Width / 2, Me.Height / 2), 41 Drawing.Drawing2D.MatrixOrder.Append) 42 g.Transform = myMatrix 43 End If 44 45 Dim directionString As String 46 47 directionString = 48 System.Enum.GetName(GetType(Direction), i) 49 g.DrawString(directionString, 50 New Font("Arial", 12, FontStyle.Bold), 51 Brushes.Black, rect, sf) 52 Next 53 End Sub

23 de nov. de 2004

Qual o tamanho máximo de um identificador em C#?

Cultura inútil: o tamanho máximo de um identificador no compilador C# da Microsoft é 512 caracteres. O compilador Mono parece ter o mesmo limite (via Jon Skeet no NG ms.p.dn.languages.csharp).

Como centralizar a janela MDI filha na janela MDI pai?

Do fórum do ClubeDelphi:

Quando crio um projeto MDI, e consequentemente os forms MDI filhos, em geral coloco a propriedade Position = poMainFormCenter. Porém, ao abrir o form filho nunca ele aparece posicionado exatamente no centro do form principal. Sempre aparece posicionado um pouco para baixo do centro. Já tentei colocar a propriedade Position em todas as outras opções de "center", mas sempre o form abre decentralizado. Quando os forms são pequenos não tem problema, mas quando ocupam a maior parte da dimensão vertical da tela, eles aparecem cortado embaixo. Ou melhor, uma faixa da parte de baixo fica escondida.

Esse problema ocorre porque o Delphi irá centrar a janela MDI filha na área cliente da janela pai, que não coincide com a área cliente MDI da janela pai. A área cliente é toda área da janela exceto o título e as bordas enquanto a área cliente MDI é a área utilizada pelas janelas MDI filhas.

O código seguinte centra a janela filha na janela pai:

1 type 2 TFormFilho = class(TForm) 3 public 4 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; 5 end; 6 7 ... 8 9 procedure TFormFilho.SetBounds(ALeft, ATop, AWidth, 10 AHeight: Integer); 11 var 12 MainForm: TForm; 13 Rect: TRect; 14 Origem: TPoint; 15 begin 16 if Showing then begin 17 18 MainForm := Application.MainForm; 19 20 // Obtem o retângulo da área cliente MDI 21 Windows.GetWindowRect(MainForm.ClientHandle, Rect); 22 23 // Calcula a origem da área cliente MDI no form 24 Origem := Rect.TopLeft; 25 Dec(Origem.x, MainForm.Left); 26 Dec(Origem.y, MainForm.Top); 27 28 // Calcula nossa nova posição 29 ALeft := (MainForm.Width - Width) div 2 - Origem.x; 30 ATop := (MainForm.Height - Height) div 2 - Origem.y; 31 end; 32 33 inherited SetBounds(ALeft, ATop, AWidth, AHeight); 34 end;

O código seguinte centra a janela filha na área cliente MDI da janela pai:

1 type 2 TFormFilho = class(TForm) 3 public 4 procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; 5 end; 6 7 ... 8 9 procedure TFormFilho.SetBounds(ALeft, ATop, AWidth, 10 AHeight: Integer); 11 var 12 MainForm: TForm; 13 Rect: TRect; 14 OurWidth: Integer; 15 OurHeight: Integer; 16 begin 17 if Showing then begin 18 19 MainForm := Application.MainForm; 20 21 // Obtem o retângulo da área cliente MDI 22 Windows.GetWindowRect(MainForm.ClientHandle, Rect); 23 24 // Calcular largura e altura da área cliente 25 OurWidth := Rect.Right - Rect.Left; 26 OurHeight := Rect.Bottom - Rect.Top; 27 28 // Calcula a nova posição 29 ALeft := (OurWidth - Width) div 2; 30 ATop := (OurHeight - Height) div 2; 31 end; 32 33 inherited SetBounds(ALeft, ATop, AWidth, AHeight); 34 end;

8 de nov. de 2004

Design Patterns em C#

No Borland Developer Network existem alguns artigos discutindo implementações dos Patterns GOF em C#.

26 de out. de 2004

STA vs MTA

No ng microsoft.public.dotnet.languages.csharp apareceu hoje uma thread sobre quando marcar a aplicação como sendo STA (Single Thread Apartment) ou MTA (Multi Thread Apartment). Um dos replies indicou um artigo interessante sobre o assunto, Apartments and Pumping in the CLR. O default para um aplicativo Windows Form é usar STA na thread principal.

In general, the only time you want to explicitly set the apartment state is if you are doing COM interop with STA components. You want your thread apartment type to match the threading model of any COM objects the thread uses to minimize performance hits.

25 de out. de 2004

O que é conformidade CLS?

Lendo hoje a thread "VS.NET vs. Delphi8.NET" no ng borland.public.delphi.language.delphi.dotnet, encontrei a seguinte afirmação:

Both languages [C# and Delphi] contain non-CLS compliant structures, it's up to you to decide if you want to use'm
Essa afirmação gerou a seguinte dúvida: o que é a não-conformidade e em quais pontos exatamente C# é não-conforme com a CLS? O significado de um item ser não-conforme é que tal item é um recurso exclusivo de uma determinada implementação do CLS. O resultado é que um não-conforme de uma classe implementada em uma determina linguagem baseada no CLS pode não ser portável para uma implementação em uma outra linguagem baseada no CLS. Esse problema de portabilidade pode ser detectado marcando a classe (ou o assembly, ou o método, etc) com o atributo CLSCompliant(true), o que gerará um erro de compilação. Note que a questão da conformidade afeta apenas itens públicos de uma classe (ou assembly, ou método, etc); internamente, uma classe pode usar livremente itens não-conformes. Segundo a própria introdução às classes do framework .NET, os seguintes tipos de dados da linguagem C# não estão em conformidade com a CLS:
  • sbyte
  • ushort
  • uint
  • ulong
  • UIntPtr
Para mais detalhes, veja Writing CLS-Compliant Code no MSDN.

23 de out. de 2004

Funções Estatísticas em .NET

Por causa de uma dúvida postada no Fórum MSDN Brasil, descobri que o framework não disponibiliza funções de cálculo estatístico. O que relamente me surpreendeu foi que o framework disponibiliza funções de cálculo financeiro no namespace Microsoft.VisualBasic.Financial.

21 de out. de 2004

Arquivos de Ajuda HTML e o Caractere #

Levei uma boa surra hoje ao tentar ler abrir um arquivo de ajuda em formato HTML compactado (HTML Help, extensão .chm). Primeiro, baixei o arquivo da internet numa pasta qualquer e dei olhada nele sem problemas. Daí movi o arquivo para a pasta onde eu pretendia que ele ficasse. Como era um arquivo relacionado com C#, queria deixá-lo numa pasta dentro de outra de nome C#. Para minha supresa, não consegui mais abrir o arquivo. Tudo que aparecia era a página de erro do IE indicando que "a página não pode ser exibida". Voltei o arquivo para a pasta inicial e, nova surpresa, o arquivo abre sem problemas. Minha primeira idéia: o componente HTML Help mantinha uma lista com os caminhos para os arquivos que ele abria. Pensando dessa forma, revirei o Registro do Windows e meu HD buscando por algo que tivesse essa informação. Resultado: não encontrei nada que indicasse que minha conclusão estava certa. Pesquisando no Google, encontrei a seguinte thread no NG microsoft.public.windowsxp.general. Resumindo:

Arquivos de de ajuda em formato HTML compactado (HTML Help) não podem estar em uma pasta onde o caminho absoluto para essa pasta contenha o símbolo #.
O símbolo # é usado como marcador de página (bookmark) em HTML e sua presença na linha de comando do componente HTML Help confunde o componente. Isso está documentado na Base de Conhecimento da Microsoft sob o número 319247.

19 de out. de 2004

Como usar Reflection para manipular as propriedades de um objeto em C#?

Usando Reflection, é possível manipular as propriedades de um objeto da maneira que você quiser.

Listar as Propriedades de um Objeto

O exemplo seguinte ilustra como acessar as propriedades públicas de um objeto. A chave para isso é o objeto PropertyInfo.
1 using System.Reflection; 2 3 public static void ListarPropriedades(object o) { 4 5 Type t = o.GetType(); 6 7 foreach (PropertyInfo pi in t.GetProperties()) { 8 9 Console.WriteLine(string.Format("{0} {1}", 10 pi.PropertyType.FullName, pi.Name)); 11 } 12 }

Obter o Valor das Propriedades de um Objeto

O exemplo seguinte ilustra como obter os valores das propriedades públicas de um objeto.
1 using System.Reflection; 2 3 public static void ListarValores(object o) { 4 5 Type t = o.GetType(); 6 7 foreach (PropertyInfo pi in t.GetProperties()) { 8 9 Console.WriteLine(string.Format("{0} {1} = {2}", 10 pi.PropertyType.FullName, pi.Name, 11 pi.GetValue(o, null))); 12 } 13 }

Alterar o Valor das Propriedades de um Objeto

O exemplo seguinte é ligeiramente diferente dos anteriores. Ele ilustra como alterar o valor de uma determinada propriedade pública de um objeto.
1 using System.Reflection; 2 3 public static void AlterarValor(object o, 4 string propriedade, object valor) { 5 6 Type t = o.GetType(); 7 8 foreach (PropertyInfo pi in t.GetProperties()) { 9 10 if (pi.Name.Equals(propriedade)) { 11 12 pi.SetValue(o, valor, null); 13 break; 14 } 15 } 16 }

Note que AlterarValor() pode receber qualquer objeto como argumento, independente do objeto possuir ou não a propriedade desejada; se o objeto possuir a propriedade, o valor dela será ajustado para o valor fornecido.

Outro ponto: como o valor é passado como um object, dependendo como o argumento é passado, existe uma penalidade envolvida que é o boxing do argumento.

Componentes de Acesso ao PostgreSQL

Componentes para acesso ao PostgreSQL que podem ser usando com C#:

Atualizado em 13/01/2007

15 de out. de 2004

Ponto de Partida

Este é o primeiro registro neste blog, nada de excepcional, apenas um ponto de partida. Espero poder manter este blog atualizado, já que minha tentativa anterior de manter um site atualizado no GeoCities não foi muito feliz. Manter um blog parece dar menos trabalho e é com isso que estou contando.