Criação do estranho menu do DELPHI
Tradutor: Li Junyu e-mail: [email protected],[email protected]
Menus personalizados, texto, linhas / Delphi 4, 5
Menu personalizado, texto, linha/Delphi 4, 5
Menus sofisticados, etc.
Menus bizarros, etc.
Menus personalizados, texto girado e linhas especiais
Menus personalizados, texto girado e linhas especiais
Antes do Delphi 4, era difícil personalizar um menu (adicionar um bitmap, alterar uma fonte, etc.), porque o desenho do proprietário (ou seja, desenho personalizado) - embora implementado pelo Windows - não era exposto pela classe TMainMenu desde o Delphi 4. No entanto, esta situação foi corrigida e podemos fazer o que quisermos com os menus.
Antes do Delphi 4, era difícil personalizar um menu (como adicionar uma imagem BMP, alterar fontes, etc.) porque o evento de desenho do proprietário (ou seja, o evento de desenho personalizado) - embora executado pelo Windows, não aparece no TMainMenu classe. Desde Delphi 4,
Esta situação mudou e agora temos a possibilidade de personalizar menus.
Este artigo destacará algumas técnicas que você pode usar para personalizar a aparência dos menus em seus aplicativos Delphi. Discutiremos o posicionamento do texto, o tamanho dos menus, a atribuição de fontes e o uso de bitmaps e formas para aprimorar a aparência de um menu. também apresenta técnicas para criar texto girado e linhas personalizadas. Todas as técnicas discutidas neste artigo são demonstradas em PRojects disponíveis para download.
Este artigo se concentrará em algumas técnicas que você pode usar para personalizar a aparência dos menus em seus aplicativos DELPHI. Abordaremos o posicionamento do texto, o tamanho do menu, as configurações de fonte e os aprimoramentos com arquivos BMP e controles SHAPE. Apenas para fins de diversão, esta postagem também apresentará um close de técnicas para girar texto e linhas personalizadas. Todas as técnicas discutidas neste artigo foram depuradas em arquivos de projeto e podem ser baixadas online.
Fontes e tamanhos personalizados
Definir fonte e tamanho
Para criar um menu personalizado, defina a propriedade OwnerDraw do componente de menu -TMainMenu ou TPopupMenu - como True e forneça manipuladores de eventos para seus eventos OnDrawItem e OnMeasureItem. Por exemplo, um manipulador de eventos OnMeasureItem é declarado assim:
Para criar um menu personalizado, defina a propriedade OwnerDraw do componente TmainMenu ou TpopupMenu como TRUE e crie seus procedimentos de evento OnDrawItem e OnMeasureItem. Por exemplo, um procedimento de evento OnMeasureItem poderia ser declarado da seguinte forma:
procedimento TForm1.Option1MeasureItem(Sender: TObject;
ACanvas: TCanvas; var Largura, Altura: Inteiro);
Defina as variáveis Width e Height para ajustar o tamanho do item de menu. O manipulador de eventos OnDrawItem é onde todo o trabalho pesado é feito; é onde você desenha seu menu e faz quaisquer configurações especiais. , por exemplo, você deve fazer algo assim:
Defina as variáveis Width e Height do item de menu no procedimento de evento acima para os tamanhos apropriados. Todas as coisas principais são acionadas pelo evento OnDrawItem; é aqui que você redesenhará o menu e fará quaisquer configurações especiais. Por exemplo, para redesenhar um item de menu na fonte Times New Roman, você faria o seguinte:
procedimento TForm1.Times1DrawItem(Remetente: TObject;
ACanvas: TCanvas; ARect: TRect; Selecionado: Booleano);
começar
ACanvas.Font.Name := 'Times New Roman';
ACanvas.TextOut(ARect.Left+1, ARect.Top+1,
(Remetente como TMenuItem).Caption);
fim;
No entanto, este código é falho. Se for executado, a legenda do menu será desenhada alinhada com a borda esquerda do menu. Geralmente, há um espaço para colocar bitmaps e marcas de seleção no menu. você deve calcular o espaço necessário para esta marca de seleção com código como o mostrado na Figura 1. A Figura 2 mostra o menu resultante.
No entanto, este código é falho. Se você executar este código, a legenda do item de menu será alinhada à esquerda do item de menu. Este não é o comportamento padrão do Windows. Normalmente, há um espaço no lado esquerdo do menu para a imagem BMP e a seleção. marca. Portanto, você deve usar código para calcular quanto espaço é necessário para colocar o sinalizador de seleção, conforme mostrado na Figura 1. A Figura 2 mostra o menu em ação.
procedimento TForm1.Times2DrawItem(Remetente: TObject;
ACanvas: TCanvas; ARect: TRect; Selecionado: Booleano);
var
dwCheck: Inteiro;
MenuCaption: string;
começar
// Obtenha as dimensões da marca de seleção.
Obtenha o número de pixels necessários para o logotipo de seleção
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// Ajusta a posição esquerda.
Ajustar a posição esquerda
ARect.Left := ARect.Left + LoWord(dwCheck) + 1;
MenuCaption := (Remetente como TMenuItem).Caption;
// O nome da fonte é a legenda do menu.
ACanvas.Font.Name := 'Times New Roman';
//Desenha o texto.
desenhar texto
DrawText(ACanvas.Handle, PChar(MenuCaption),
Comprimento(MenuCaption), ARect, 0);
fim;
Figura 1: Este manipulador de eventos OnDrawItem coloca o texto do item de menu corretamente.
[O tradutor omitiu todas as Figuras, as mesmas abaixo]
Figura 2: Um menu desenhado com fontes personalizadas.
Se o texto for muito grande para ser desenhado no menu, o Windows irá cortá-lo para caber. Portanto, você deve definir o tamanho do item de menu para que todo o texto possa ser desenhado. Essa é a função do manipulador de eventos OnMeasureItem mostrado na Figura 3. .
Se o texto for muito longo, o Windows irá cortá-lo automaticamente para caber. Portanto, você deve dimensionar o menu para que todo o texto possa ser exibido. O mesmo deve acontecer no evento OnMeasureItem, que pode ser visto na Figura 3.
procedimento TForm1.Times2MeasureItem(Sender: TObject;
ACanvas: TCanvas; var Largura, Altura: Inteiro);
começar
ACanvas.Font.Name := 'Times New Roman';
ACanvas.Font.Style := [];
// A largura é o espaço da verificação do menu
Este comprimento é o comprimento da marca de seleção do menu
// mais a largura do texto do item.
Mais o comprimento do item de menu
Largura := GetSystemMetrics(SM_CXMENUCHECK) +
ACanvas.TextWidth((Remetente como TMenuItem).Caption) + 2;
Altura := ACanvas.TextHeight(
(Remetente como TMenuItem).Caption) + 2;
fim;
Figura 3: Este manipulador de eventos OnMeasureItem garante que um item caiba em seu menu.
Formas e bitmaps personalizados
Configurar gráficos e bitmaps
Também é possível personalizar itens de menu incluindo bitmaps ou outras formas. Para adicionar um bitmap, simplesmente atribua um arquivo bitmap à propriedade TMenuItem.Bitmap - com o Object Inspector em tempo de design ou com código em tempo de execução. como legenda de um item de menu, você poderia usar o manipulador de eventos OnDrawItem mostrado na Figura 4. A Figura 5 mostra o resultado.
É possível configurar menus com bitmaps e outros gráficos. Para adicionar um bitmap, basta atribuir um arquivo BMP à propriedade Bitmap de TmenuItem no Object Inspector em tempo de design, ou usar código em tempo de execução. Para substituir o título do menu por um retângulo colorido, você pode usar o evento OnDrawItem, como mostrado na Figura 4. Os resultados são mostrados na Figura 5.
procedimento TForm1.ColorDrawItem(Remetente: TObject;
ACanvas: TCanvas; ARect: TRect; Selecionado: Booleano);
var
dwCheck: Inteiro;
MenuColor: TColor;
começar
// Obtenha as dimensões da marca de seleção.
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
ARect.Left := ARect.Left + LoWord(dwCheck);
// Converte a legenda do item de menu em uma cor.
Converter o título do item de menu em cor
Cor do menu :=
StringToColor((Remetente como TMenuItem).Caption);
// Altera a cor do pincel da tela.
Alterar a cor do pincel da tela
ACanvas.Brush.Color := MenuColor;
// Desenha o retângulo. Se o item estiver selecionado,
Desenha um retângulo se o item do menu estiver selecionado
//desenha uma borda.
desenhar fronteiras
se selecionado então
ACanvas.Pen.Style := psSolid
outro
ACanvas.Pen.Style := psClear;
ACanvas.Rectangle(ARect.Left, ARect.Top,
ARect.Right, ARect.Bottom);
fim;
Figura 4: Usando o evento OnDrawItem para desenhar retângulos coloridos em itens de menu.
Figura 5: Um menu apresentando retângulos coloridos como itens.
Há apenas um problema. Se você estiver usando o Delphi 5, você deve definir a propriedade AutoHotkeys do menu como maManual. Se você deixar como padrão, maAutomatic, o Delphi adicionará um caractere de e comercial (&) à legenda, o que quebrará isso. Outra solução é remover o e comercial com a função StripHotKey.
A abordagem mais popular é que se você estiver usando Delphi 5, você deve definir a propriedade AutoHotkeys do menu como maManual. Se você não fizer isso e deixar o valor padrão de maAutomatic, o Delphi adicionará automaticamente um E comercial ao título, o que quebrará o código. Outra solução é usar a função StripHotKey para remover o e comercial.
Outra maneira de usar os eventos OnDrawItem e OnMeasureItem é escrever o texto verticalmente em um menu (como mostrado na Figura 7). Para fazer isso, você deve criar uma fonte girada. Isso só é possível usando a função da API do Windows CreateFont ou CreateLogFont (consulte). (a dica "Texto girado" mais adiante neste artigo). Então você deve desenhá-lo no manipulador de eventos OnDrawItem. Este evento é acionado toda vez que um item de menu é desenhado, portanto, se um menu tiver. 20 itens, ele será desenhado 20 vezes. Para torná-lo mais rápido, o texto vertical será desenhado somente quando o item de menu for selecionado (já que há apenas um item de menu selecionado por vez). código, e a Figura 7 mostra o resultado em tempo de execução.
Outro uso para os eventos OnDrawItem e OnMeasureItem é escrever texto vertical próximo ao menu (como mostrado na Figura 7). Para fazer isso, você deve criar uma fonte girada. A única maneira é usar a função CreateFont ou CreateLogFont da API do Windows (consulte a técnica de "texto girado" posteriormente neste artigo). Então você tem que redesenhá-lo no evento OnDrawItem. Este evento é executado quando o item do menu é retirado, portanto, se um menu tiver 20 itens, ele será executado 20 vezes. Para torná-lo mais rápido, o texto vertical pode ser redesenhado sempre que um item de menu é selecionado (embora apenas um item de menu seja selecionado por vez). A Figura 6 mostra como o código é executado, enquanto a Figura 7 mostra os resultados.
procedimento TForm1.VerticalDrawItem(Remetente: TObject;
ACanvas: TCanvas; ARect: TRect; Selecionado: Booleano);
var
se: TLogFont;
Fonte Antiga:HFont;
clFore, clBack: LongInt;
Retângulo: TRect;
dwCheck: LongInt;
MenuHeight: Inteiro;
começar
dwCheck := GetSystemMetrics(SM_CXMENUCHECK);
// Isso será feito uma vez, quando o item for selecionado.
Isto será executado quando o item do menu for selecionado
se selecionado, então comece
// Cria uma fonte girada.
Crie uma fonte girada
FillChar(lf, SizeOf(lf), 0);
lf.lfAltura := -14;
lf.lfEscapement := 900;
lf.lfOrientação := 900;
lf.lfPeso := Fw_Bold;
StrPCopy(lf.lfFaceName, 'Arial');
// Selecione esta fonte para desenhar.
Selecione esta fonte para desenhar
OldFont := SelectObject(ACanvas.Handle,
CreateFontIndirect(lf));
// Altera as cores do primeiro plano e do plano de fundo.
Alterar as cores do primeiro plano e do plano de fundo
clFore := SetTextColor(ACanvas.Handle, clSilver);
clBack := SetBkColor(ACanvas.Handle, clBlack);
// Obtém a altura do menu.
Obtenha a altura do menu
MenuHeight := (ARect.Bottom-ARect.Top) *
((Remetente como TMenuItem).Parent como TMenuItem).Count;
Retangular := Rect(-1, 0, dwCheck-1, MenuHeight);
//Desenha o texto.
desenhar texto
ExtTextOut(ACanvas.Handle, -1, MenuHeight, Eto_Clipped,
@Rectang, 'Made in Borland', 15, zero);
//Retorna ao estado original.
Retornar ao estado original
DeleteObject(SelectObject(ACanvas.Handle, OldFont));
SetTextColor(ACanvas.Handle, clFore);
SetBkColor(ACanvas.Handle, clBack);
fim;
// Desenha o texto real do menu.
Desenhe o texto real do item de menu
ARect.Left := ARect.Left + LoWord(dwCheck) + 2;
DrawText(ACanvas.Handle,
PChar((Remetente como TMenuItem).Caption),
Length((Remetente como TMenuItem).Caption), ARect, 0);
fim;
Figura 6: Usando OnDrawItem para desenhar texto vertical em um menu.
Figura 7: Menu com texto vertical.
Um detalhe complicado é saber por onde começar a desenhar o texto. Ele deve começar na parte inferior do último item do menu. Para obter sua posição, obtemos a altura do item do menu, usando:
Você deve saber por onde começar a desenhar texto. Deve começar na parte inferior do último item do menu. Para obter esta posição, obtemos a altura do item de menu da seguinte forma:
ARect.Top - ARect.Bottom
e multiplique pelo número de itens no menu:
E multiplicado pelo número de itens do menu:
(((Remetente como TMenuItem).Parent como TMenuItem).Count)
Texto girado
texto girado
A API do Windows permite desenhar texto em qualquer ângulo. Para fazer isso no Delphi, você deve usar a função API CreateFont ou CreateFontIndirect conforme mostrado na Figura 8.
A API do Windows permite desenhar texto em qualquer ângulo. Para fazer isso no Delphi, você deve usar as duas funções da API CreateFont ou CreateFontIndirect. A Figura 8 mostra como CreateFont é declarado.
função CriarFonte(
nHeight, // Altura lógica da fonte.
nWidth, // Largura média lógica dos caracteres.
nEscapement, // Ângulo de escape.
nOrientation, // Ângulo de orientação da linha base.
fnWeight: Integer; // Peso da fonte.
fdwItalic, // Sinalizador de atributo em itálico. Está em itálico?
fdwUnderline, // Sinalizador de atributo sublinhado.
fdwStrikeOut, // Sinalizador de atributo riscado Se o atributo deve ser riscado.
fdwCharSet // Identificador do conjunto de caracteres.
fdwOutputPrecision, // Precisão de saída.
fdwClipPrecision, // Precisão de recorte.
fdwQuality, // Qualidade de saída.
fdwPitchAndFamily: DWORD; // Pitch e família.
lpszFace: PChar // Ponteiro para a string do nome do tipo de letra.
): HFONT;
Figura 8: A declaração Object Pascal para a função CreateFont da API do Windows.
Embora esta função tenha muitos parâmetros, normalmente você desejará alterar apenas um ou dois atributos do texto. Nesses casos, você deve usar a função CreateFontIndirect. Ela leva apenas um argumento - um registro do tipo TLogFont, conforme mostrado na Figura. 9.
Embora esta função tenha muitos parâmetros, normalmente você só precisa alterar uma ou duas propriedades do texto. Nesse caso, você usaria a função CreateFontIndirect. Requer apenas um parâmetro - um parâmetro de tipo de registro do TlogFont, como pode ser visto na Figura 9.
tagLOGFONTA = registro compactado
lfHeight: Inteiro longo;
lfWidth: inteiro longo;
lfEscapement: Inteiro longo;
lfOrientação: Inteiro longo;
lfWeight: Inteiro longo;
lfItálico: Byte;
lfSublinhado: Byte;
IfStrikeOut: Byte;
lfCharSet: Byte;
IfOutPrecision: Byte;
lfClipPrecision: Byte;
lfQualidade: Byte;
lfPitchAndFamily: Byte;
lfFaceName: array[0..LF_FACESIZE - 1] de AnsiChar;
fim;
TLogFontA = tagLOGFONTA;
TLogFont = TLogFontA;
Figura 9: O registro TLogFont.
Observando este registro, você notará que seus membros correspondem aos parâmetros da função CreateFont. A vantagem de usar esta combinação função/registro é que você pode preencher os membros do registro com uma fonte conhecida usando a função GetObject API, alterando os membros que você deseja. deseja e crie a nova fonte.
Se você observar esse tipo de registro mais de perto, descobrirá que seus membros são muito semelhantes aos parâmetros da função CreateFont. A vantagem de usar essa combinação função/registro é que você pode usar a função da API GetObject para preencher os valores dos membros deste registro com uma fonte conhecida e, em seguida, alterar o valor do membro que deseja alterar para gerar uma nova fonte.
Para desenhar texto girado, o único membro que você deve alterar é lfEscapement, que define o ângulo do texto em décimos de graus. Portanto, se quiser que o texto seja desenhado em 45 graus, você deve definir lfEscapement como 450.
Para desenhar texto girado, o único membro que você precisa alterar é lfEscapement, que define o ângulo da fonte em décimos de grau. Então, se você quiser que o personagem gire 45 graus, você deve definir
lfEscapement é 450.
Observe que existem sinalizadores para desenhar texto em itálico, sublinhado e riscado, mas não há sinalizador para desenhar texto em negrito. Isso é feito com o membro lfWeight, um número entre 0 e 1000. 400 é texto normal, valores acima deste. desenhe texto em negrito e os valores abaixo dele desenham texto claro.
Observe que existem alguns marcadores para colocar em itálico, sublinhar e destacar o texto, mas não há marcadores para deixar o texto em negrito. Isso ocorre porque o membro lfWeight é usado e o valor desse membro está entre 0 e 1000. 400 é o valor normal, qualquer valor acima disso é negrito e qualquer valor abaixo disso é fino.
O código na Figura 10 desenha texto em ângulos que variam de 0 a 360 graus, em intervalos de 20 graus. É o manipulador de eventos OnPaint do formulário, portanto, o texto é redesenhado sempre que o formulário é pintado.
O código na Figura 10 desenha caracteres a cada 20 graus, de 0 a 360 graus. Isso é acionado no evento OnPaint do formulário, de forma que o texto é redesenhado cada vez que o formulário é pintado. O efeito pode ser visto na Figura 11.
procedimento TForm1.FormPaint(Remetente: TObject);
var
OldFont, NewFont: hFont;
LogFont: TLogFont;
eu: Inteiro;
começar
// Obtém o controle da fonte do canvas.
Obtém o identificador para o objeto de fonte do formulário
OldFont := Canvas.Font.Handle;
eu := 0;
// Desenho transparente.
Definir propriedade de transparência
SetBkMode(Canvas.Handle, Transparente);
//Preenche a estrutura LogFont com informações
Preencha a estrutura LogFont com informações
//da fonte atual.
da fonte atual
GetObject(OldFont, Sizeof(LogFont), @LogFont);
// Os ângulos variam de 0 a 360.
de 0 a 360 graus
enquanto eu <3600 começo
// Define o escape para o novo ângulo.
Defina a orientação do texto para um novo ângulo
LogFont.lfEscapement := i;
//Cria uma nova fonte.
Criar nova fonte
NovaFont := CreateFontIndirect(LogFont);
// Selecione a fonte a ser desenhada.
Selecione fontes para saída
SelectObject(Canvas.Handle, NewFont);
// Desenha o texto no meio do formulário.
Texto de saída no meio do formulário
TextOut(Canvas.Handle, ClientWidth div 2,
ClientHeight div 2, 'Texto girado', 21);
// Limpar.
Claro
DeleteObject(SelectObject(Canvas.Handle, OldFont));
//Incrementa o ângulo em 20 graus.
incrementos a cada 20 graus
Inc(i, 200);
fim;
fim;
Figura 10: Código para desenhar texto girado em intervalos de 20 graus.
Figura 11: Texto girado 360 graus.
A fonte do formulário é definida como Arial, uma fonte TrueType. Este código funciona apenas com fontes TrueType; outros tipos de fontes não suportam rotação de texto. Para obter as configurações de fonte atuais e preencher a estrutura TLogFont, você deve usar a função da API GetObject. O código na Figura 12 mostra como preencher e exibir as configurações TLogFont para a fonte do formulário.
A fonte deste formulário está definida como Arial, uma fonte TrueType. Este código funciona apenas com fontes TrueType; outras fontes não suportam rotação de texto. Para obter as configurações de fonte atuais e preencher a estrutura TlogFont, você deve usar a função da API GetObject. No código da Figura 12 você pode ver como preencher e exibir as configurações do TlogFont no formulário.
procedimento TForm1.Info1Click(Remetente: TObject);
var
LogFont: TLogFont;
começar
//Preenche a estrutura LogFont com informações
Preencha os valores dos membros da estrutura LogFont
//da fonte atual.
da fonte atual
GetObject(Canvas.Font.Handle, Sizeof(LogFont), @LogFont);
//Exibe informações da fonte.
Mostrar informações da fonte
com LogFont do ShowMessage(
'lfAltura: ' + IntToStr(lfAltura) + #13 +
'lfWidth: ' + IntToStr(lfWidth) + #13 +
'lfEscapement: '+IntToStr(lfEscapement) + #13 +
'lfOrientação: ' + IntToStr(lfOrientação) + #13 +
'lfPeso: ' + IntToStr(lfPeso) + #13 +
'lfItálico: ' + IntToStr(lfItálico) + #13 +
'lfUnderline: ' + IntToStr(lfUnderline) + #13 +
'lfStrikeOut: ' + IntToStr(lfStrikeOut) + #13 +
'lfCharSet: ' + IntToStr(lfCharSet) + #13 +
'lfOutPrecision: ' + IntToStr(lfOutPrecision) + #13 +
'lfClipPrecision: ' + IntToStr(lfClipPrecision) + #13 +
'lfQualidade: ' + IntToStr(lfQualidade) + #13 +
'lfPitchAndFamily: '+IntToStr(lfPitchAndFamily) + #13 +
'lfFaceName: ' + string(lfFaceName));
fim;
Figura 12: Obtendo e exibindo atributos de fonte.
Depois de definir as configurações em uma estrutura TLogFont, a única alteração que resta é definir lfEscapement para o ângulo desejado e criar uma nova fonte com CreateFontIndirect. Antes de usar esta nova fonte, ela deve ser selecionada com SelectObject. Outra forma é atribuir o identificador. desta nova fonte para o identificador da fonte do canvas, antes de desenhar o texto. Após desenhar o texto, este trabalho deve ser invertido. não for excluído, haverá um vazamento de memória e - se a rotina for executada muitas vezes - o Windows (especialmente o 95/98) ficará sem recursos e travará.
Depois de configurar a estrutura TlogFont, a única coisa que resta a fazer é alterar o valor de lfEscapement para o valor alvo e usar CreateFontIndirect para gerar uma nova fonte. Antes de usar esta nova fonte, você deve usar SelectObject para selecioná-la. Outro método é usar o identificador deste novo objeto de fonte no identificador do objeto de fonte da tela do formulário antes de desenhar o texto. Após o texto ser desenhado, o processo começa; a fonte antiga deve ser selecionada e a nova fonte excluída. Se a nova fonte não for removida, causará um vazamento de memória e -----se o programa for executado várias vezes------ o Windows (especialmente 95/98) ficará sem recursos e
colidir.
Linhas elegantes
linhas populares
Quando você desenha linhas, os pixels individuais geralmente não importam; você simplesmente define o estilo da linha e ele é desenhado pelo Windows. Às vezes, porém, você precisa fazer algo especial e desenhar um estilo de linha não fornecido pelo Windows. usando uma função API do Windows chamada LineDDA, definida na Figura 13.
Quando você desenha linhas, os pixels individuais geralmente não são importantes; você simplesmente define o tipo de linha e cabe ao Windows desenhá-la. Às vezes, porém, você deseja criar alguns tipos de linha especiais que o Windows não fornece. Isso pode ser conseguido utilizando uma função API chamada LineDDA, cuja definição pode ser vista na Figura 13.
função LinhaDDA(
nXStart, // coordenada x do ponto inicial da linha.
Ponto inicial da coordenada X
nYStart, // coordenada y do ponto inicial da linha.
Ponto inicial da coordenada Y
nXEnd, // coordenada x do ponto final da linha.
Ponto final da coordenada X
YEnd : Integer; // coordenada y do ponto final da linha.
Ponto final da coordenada Y
//Endereço da função de retorno de chamada definida pelo aplicativo.
O endereço da função de retorno de chamada definida pelo aplicativo
lpLineFunc: TFNLineDDAProc;
lpData : LPARAM // Endereço dos dados definidos pelo aplicativo.
Endereço dos dados definidos pelo aplicativo
): BOOL;
Figura 13: Declaração Object Pascal para a função API do Windows, LineDDA.
Os primeiros quatro parâmetros são os pontos inicial e final da linha. O quinto parâmetro é uma função de retorno de chamada que será chamada toda vez que você colocar suas rotinas de desenho lá. passado para a função de retorno de chamada Você pode passar qualquer número inteiro ou ponteiro para a função, porque é um LParam (no Win32, é traduzido para um Longint. A função de retorno de chamada deve ter o formato mostrado aqui:
Os primeiros quatro parâmetros são os pontos inicial e final da linha. O quinto parâmetro é uma função de retorno de chamada que será chamada sempre que um pixel for desenhado. Você pode escrever sobre seu processo de desenho aqui. O último parâmetro é definido pelo usuário e pode ser passado para a função de retorno de chamada. Você pode passar qualquer número inteiro ou ponteiro para esta função porque é
Um tipo Lparam (no WIN32, é interpretado como um tipo Longint). Esta função de retorno de chamada deve usar um formato como o seguinte:
procedimento CallBackDDA(x, y: Inteiro;
UserParam: LParam);
onde x e y são as coordenadas do ponto desenhado e UserParam é um parâmetro que é passado para a função. Esta função deve ser declarada como stdcall. A rotina na Figura 14 desenha uma linha de bitmaps e a Figura 15 mostra o resultado.
Aqui X e Y são os pontos de coordenadas que estão sendo desenhados e UserParam é um parâmetro. Esta função deve ser subdefinida como stdcall. O programa na Figura 14 traça uma linha BMP e a Figura 15 exibe os resultados.
tipo
TForm1 = classe(TForm)
ListaImagem1: TImageList;
procedimento FormPaint(Remetente: TObject);
procedimento FormResize(Remetente: TObject);
fim;
var
Formulário1: TForm1;
procedimento CallDDA(x, y: Inteiro; Formulário: TForm1);
implementação
{$R*.DFM}
procedimento CallDDA(x, y: Inteiro; Formulário: TForm1);
começar
se x mod 13 = 0 então
Form.ImageList1.Draw(Form.Canvas, x, y, 0);
fim;
procedimento TForm1.FormPaint(Remetente: TObject);
começar
LineDDA(0, 0, ClientWidth, ClientHeight,
@CallDDA, Integer(Self));
fim;
procedimento TForm1.FormResize(Remetente: TObject);
começar
Invalidar;
fim;
Figura 14: Código para desenhar uma linha de bitmaps.
Figura 15: Janela com linha customizada.
Esta rotina trata o evento OnPaint do formulário, chamando LineDDA, portanto toda vez que o formulário deve ser pintado, ela redesenha a linha. Outro evento que é tratado é o OnResize, que invalida a área cliente do formulário, portanto a linha deve ser redesenhada quando alguém alterar sua linha. size A função de retorno de chamada do LineDDA, CallDDA, é muito simples. A cada 13 pontos ela é chamada, ela desenha o bitmap armazenado no ImageList. a função de retorno de chamada, para que possa acessar os dados da instância.
Este programa manipula o evento OnPaint do formulário, chamando LineDDA, para redesenhar a linha cada vez que o formulário for pintado. Outro evento é o OnResize, que invalida a área cliente do formulário para que as linhas sejam redesenhadas quando alguém alterar seu tamanho. A função de retorno de chamada LineDDA e CallDDA são muito simples. Sempre que for chamado 13 vezes, ele desenhará o bitmap armazenado no ImageList. Talvez você tenha notado que SELF é passado como último parâmetro para a função de retorno de chamada, para que possa acessar os dados do programa.
Conclusão
para concluir
Desde que o desenho do proprietário foi exposto no TMainMenu no Delphi 4, houve muitas maneiras de aumentar seus menus. Usando as técnicas que discutimos aqui, você pode aprimorar facilmente os menus de seu aplicativo Delphi com texto, bitmaps e cores personalizados.
Agora que o desenho do proprietário apareceu no TmainMenu do Delphi 4, ele pode ter muitas maneiras de estender a funcionalidade do menu. Usando as técnicas discutidas acima, você pode aprimorar facilmente a funcionalidade do menu do seu aplicativo DELPHI com texto, bitmaps e cores personalizados.