Microsoft.com Brasil Home | Mapa do Site
HyperLink
 
Procurar no Microsoft.com por:
 
  Home | Developer Center | Biblioteca | Downloads | Como Comprar | Assinaturas MSDN




Pesquisa rápida

 
 
  
Home MS Brasil
Compre
Downloads
Suporte
Fale conosco

 

Visual FoxPro

 
  
Faça o download deste documento:
IntelliSense no Visual FoxPro 7.0
 formato Word, 584 Kb

IntelliSense no Visual FoxPro 7.0
Por Daryl Moore, Hazen Hills Software
Andy Kramek, Tightline Computers
Resumo

Aprenda como o IntelliSense é implementado no Visual FoxPro 7.0 e como aproveitar todo o seu potencial. O IntelliSenseTM foi introduzido pela primeira vez no Microsoft® Visual Basic 5.0TM e vem sendo amplamente implementado como um aprimoramento de produtividade essencial para desenvolvedores em diversas linguagens. A implementação no Visual FoxPro 7.0 possui características únicas porque traz uma arquitetura aberta que permite que os desenvolvedores personalizem e ampliem os recursos internos.

Introdução

O termo "IntelliSense" refere-se à funcionalidade que, quando um desenvolvedor está trabalhando em uma janela de edição de código, oferece comandos de preenchimento automático e ajuda contextual durante a digitação com sintaxe. Essa função está disponível há muito tempo em outras ferramentas da Microsoft para desenvolvedores, mas permanecia inexplicavelmente ausente no Visual FoxPro. O IntelliSense foi finalmente introduzido no Visual FoxPro com o lançamento da versão 7.0.

A implementação do IntelliSense no Visual FoxPro 7.0 oferece todos os recursos padrão, além de alguns novos. No entanto, como a implementação é orientada para dados, é possível alterar o comportamento padrão e criar comportamentos inteiramente novos. Esse estudo explica como o IntelliSense foi implementado no Visual FoxPro 7.0 e ilustra como os desenvolvedores podem aproveitar a sua arquitetura aberta para facilitar seu trabalho e aumentar a sua produtividade.

Recursos Básicos do IntelliSense

A funcionalidade básica oferecida no Visual FoxPro 7.0 é ilustrada nas séries de figuras a seguir. Existem dois tipos principais de funcionalidade fornecidos por padrão no Visual FoxPro 7.0. Primeiro, há as informações que estão vinculadas aos comandos e às funções que são digitados. Elas incluem o preenchimento automático de palavras-chaves, comandos e funções e os vários formatos da ajuda contextual associada a eles (consulte as entradas em "Informações rápidas"). Segundo, há uma apresentação dinâmica e interativa das informações de classes e objetos (consulte "Listas de membros").

Informações Rápidas nas Janelas de Edição

Quando você está trabalhando com uma janela de edição de códigos (um arquivo de programa ou um método de uma classe ou formato) ou com a janela de comandos, todos os recursos a seguir estão disponíveis por padrão.


Figura 1: Destaque de sintaxe de comandos parciais

A Figura 1 mostra como, ao escrever códigos, o Visual FoxPro 7.0 reconhece comandos parciais e os destaca usando as configurações definidas para colorir a sintaxe na guia 'Editor' da caixa de diálogo Options (Opções). Não há nenhuma novidade nisso, mas se, quando o código for realçado, a tecla de espaço for pressionada, o Visual FoxPro 7.0 completa o comando e exibe todas as "Informações rápidas" associadas em uma dica de ferramenta (Figura 2) .


Figura 2: Preenchimento automático e dica de ferramenta com Informações rápidas

As Informações rápidas são fornecidas de várias formas, dependendo do contexto. Na figura 2, elas nos informam que o próximo item esperado é uma 'Lista de Parâmetros'. No entanto, esse não é o único formato das Informações rápidas; elas também são utilizadas para exibir extratos contextuais do arquivo de ajuda (Figura 3).


Figura 3: Ajuda contextual enquanto o código está sendo escrito

A próxima linha de código é uma instrução e, depois que a palavra-chave é inserida e a tecla de espaço é pressionada, o texto de ajuda associado ao comando é exibido. Observe que, nesse caso em particular, nós não poderíamos usar o preenchimento automático para o comando porque os quatro primeiros caracteres ("LOCA") são, na verdade, atribuídos ao comando LOCATE.

O próximo tipo de Informações rápidas disponibilizado é uma lista de "Valores" (Figura 4) que é gerada automaticamente para comandos com múltiplas opções.


Figura 4: Lista de valores e Dica de valores de Informações rápidas

Observe a "Dica de valor" adicional que é exibida enquanto você percorre o conteúdo da lista. Uma variável da lista de valores básicos é mostrada na figura 5, onde as opções disponíveis para um comando SET são exibidas e a dica de valor é utilizada para indicar que opção está definida. Listas semelhantes estão disponíveis para definições que aceitam os valores Verdadeiro/Falso.


Figura 5: A Lista de informações rápidas das definições atuais e disponíveis

Todos os exemplos até o momento são disparados quando a tecla de espaço é pressionada, mas essa não é a única forma de disparar o IntelliSense. Quando você insere uma função, digitar a tecla de parênteses esquerdo dispara uma dica "inteligente" de Informações rápidas (Figura 6).


Figura 6: Dicas inteligentes controlam a posição quando o código é inserido

Observe que embora todos os parâmetros da função StrTran() sejam exibidos na dica de Informações rápidas, apenas o segundo (cSearchFor) está realçado em negrito. Não é coincidência que esse seja o parâmetro que será inserido na janela de código. O mecanismo IntelliSense monitora as vírgulas que separam os parâmetros para sincronizar o realce na Janela de dicas com a posição atual na janela de códigos.

Informações rápidas na janela de comandos

Existem dois outros tipos de Informações rápidas, mas, ao contrário de todos os exemplos anteriores, eles só estão disponíveis quando você está trabalhando interativamente na janela de comandos. A primeira é a lista "Mais Recentemente Usados" (MRU) (Figura 7).


Figura 7: A Lista de Mais Recentemente Usados (MRU) - disponível na janela de comandos apenas

Como o nome indica, as listas MRU contêm os nomes e o caminho completo dos itens do tipo apropriado que foram abertos mais recentemente. Listas MRU separadas são mantidas para os tipos de arquivos especificados pelos comandos USE, MODIFY, OPEN, REPORT, LABEL e DO. Observe, no entanto, que a lista MRU sempre inclui o caminho completo e o nome do arquivo. Se o próximo comando inserido na janela de comando fosse apenas "USE fixlist", a entrada adicionada à MRU ainda seria "D:\VFP70\Run\fixlist.dbf".

O número de entradas mantidas nessas listas é estático, o que significa que quando o número definido de entradas é atingido, a entrada mais antiga é descartada sempre que um novo item precisa ser adicionado. O limite é definido na guia "Exibir" da caixa de diálogo Opções e também controla o número de projetos que são mantidos em Arquivo no menu do sistema principal.

Uma variável da lista MRU padrão que relaciona os campos na tabela aberta atualmente está disponível quando o comando REPLACE é utilizado da janela de comando (Figura 8)


Figura 8: MRU para o comando REPLACE (Janela de comandos apenas)

Em vez de exibir uma lista de arquivos, o mecanismo IntelliSense cria uma lista dos campos na tabela selecionada atualmente e inclui as informações de tipo e tamanho de dados na dica de valor de cada campo.

Nota: A mesma lista de campos é disparada digitando-se o ponto ao fazer referência a qualquer tabela aberta no momento na janela de comandos com a sintaxe <alias>.<campo>.

O segundo tipo de lista especial, disponível apenas na janela de comandos, exibe todas as variáveis definidas atualmente e que estejam no escopo, quando o atalho "m." é inserido, seguido por um espaço (Figura 9).


Figura 9: Lista de variáveis definidas (Janela de comandos apenas)

Nesta lista, a Dica de valor é utilizada para exibir o conteúdo da variável. As referências de objeto são mostradas como "(Objeto)" ou ".NULL.", dependendo do objeto ser realmente instanciado ou não.

Listas de membros

As listas de membros estão disponíveis nas janelas de edição e comandos para objetos que foram instanciados e estejam atualmente no escopo (Figura 10).

A lista inclui todas as propriedades, eventos e métodos (PEM) de um objeto e cada tipo de entrada tem seu próprio ícone. A Dica de valor de uma lista de membros exibe o comentário associado a PEM (e, até mesmo, os comentários de PEMs criados nas classes definidas pelo usuário).


Figura 10: Lista de Membros de Objeto

As listas de membros são avaliadas dinamicamente para que selecionar um objeto contido exiba os membros deste objeto e assim por diante. A Figura 11 mostra a lista de membros do filho do filho de um objeto contido no objeto oDM .


Figura 11: As listas de membros são criadas dinamicamente

Isso, por si só, já seria útil, mas o IntelliSense pode fazer muito mais graças a outro novo recurso introduzido no FoxPro 7.0, o "Design Time Strong Typing". O Visual FoxPro sempre foi uma linguagem de pouca digitação. Isso significa que não há exigências para declarar variáveis explicitamente e, essas variáveis, depois de definidas podem ter seu tipo alterado conforme a necessidade. Esse é um método extremamente poderoso e flexível que traz vantagens significativas para uma ferramenta de desenvolvimento orientada para dados. No entanto, como sempre, há pontos negativos. Um deles é que o sistema nunca pode 'saber' se uma variável está sendo usada e, portanto, não pode fazer suposições sobre ela ou usá-la como fonte de informações.

O Visual FoxPro 7.0 agora permite o uso de digitação em determinados lugares, no momento da criação apenas, para oferecer suporte ao IntelliSense. Ele é implementado usando uma nova cláusula AS que pode ser aplicada a classes, parâmetros ou variáveis para indicar ao mecanismo IntelliSense como uma referência deve ser tratada. Existem diversas formas de usá-lo.


Figura 12: Definir uma variável local como Classe principal VFP

Primeiro, ela pode ser utilizada para definir objetos e variáveis como instâncias de outras classes do Visual FoxPro. Elas podem ser classes principais nativas como mostrado na Figura 12, onde a variável local loCombo é definida como uma caixa de combinação e depois, no código, onde a referência é usada em uma construção WITH…ENDWITH para acessar a lista de membros diretamente. Quando o código é concluído, uma pesquisa e substituição global remove "loCombo" deixando apenas o ".". Como o Strong Typing só pode ser utilizado no momento da criação, a instrução pode permanecer no código sem causar problemas de tempo de execução.

A mesma técnica pode ser utilizada com classes personalizadas (Figura 13). Observe que para construir listas de membros para classes, elas devem estar registradas no IntelliSense (veja abaixo) ou especificadas com a cláusula OF como ilustrado.


Figura 13: Usando uma classe personalizada com o IntelliSense

No entanto, o IntelliSense não está limitado às classes do Visual FoxPro. Qualquer classe ou aplicação que exponha uma Biblioteca de Tipos pode ser acessada pelo mecanismo IntelliSense para construir uma lista de membros. (Figura 14).


Figura 14: Explorando o modelo Objeto Palavra com o Intellisense

Ele fornece uma alternativa a usar o Browser de Objetos para descobrir como acessar e controlar os aplicativos do Servidor OLE, os componentes COM e os controles ActiveX.

O Strong typing também permite definir o valor de retorno e os tipos de dados de parâmetros das Funções e dos Procedimentos nas definições de classe. Nessa situação, a lista de membros exibe todos os tipos de dados disponíveis e objetos que foram definidos para o IntelliSense (Figura 15)


Figura 15: Declarar Tipos de Dados

Essas informações são exibidas automaticamente pelo IntelliSense como Informações rápidas sempre que o método resultante for acessado (Figura 16). Observe que não importa para o IntelliSense se a biblioteca de classes está definida visualmente ou em um arquivo de programa.


Figura 16: Tipos de Dados de Parâmetros Definidos pelo Usuário nas Informações Rápidas

Configurar o Intellisense

Existem duas formas de configurar o IntelliSense no Visual FoxPro 7.0.

A primeira é definir o conteúdo de uma nova propriedade no objeto do aplicativo VFP chamado "EditorOptions". A configuração padrão é "LQKT" embora existam, na verdade, cinco recursos que podem ser controlados através desta propriedade, da seguinte forma:
  • Hiperlinks ("K ou k"). Determina como os links são ativados. A definição para "k" exige apenas um único clique no mouse, enquanto "K" exige que CTRL+Clique seja utilizado - que é o padrão. Se nenhum deles for especificado, os hiperlinks serão tratados como texto normal nas janelas de edição e comando.
  • Arrastar e Soltar Palavra ("W"). Quando ativado, o texto só pode ser arrastado para uma posição imediatamente após um espaço. Evita que um texto seja inserido (por engano) no texto existente quando se usa arrastar e soltar em um editor ou na janela de comandos. Esse comportamento está desativado por padrão.
  • Dicas de valores do criador ("T"). Controla se os itens exibidos nas listas mostram suas 'dicas de ferramentas' associadas. Por padrão, elas são exibidas quando você rola pelas listas de membros.
  • Membros da lista ("L ou l"). Controla se e quando as listas de membros objetos são exibidas. Por padrão, as listas são automáticas ("L"), embora você possa preferir usar a opção de "l" minúsculo para impedir a exibição automática, mas ainda ter a lista popup quando pressiona CTRL+J (ou selecione 'Membros de Lista' da opção "Editar" no menu principal do FoxPro).
  • Informações rápidas ("Q ou q"). Controla se e quando os vários tipos de Informações rápidas são exibidos. Por padrão, a exibição é automática ("Q"), embora você possa preferir usar a opção de "q" minúsculo para impedir a exibição automática, mas ainda ter as Informações rápidas disponíveis quando pressionar CTRL+I (ou selecione 'Informações rápidas' na opção "Editar" no menu principal do FoxPro).


Para ativar todos os recursos do IntelliSense (incluindo arrastar e soltar texto de controle), basta inserir o seguinte na janela de comando:

_VFP.EditorOptions = "LQKTW"

ou qualquer combinação de definições que você deseje aplicar.

A segunda forma é usar o novo formulário 'Gerenciador do IntelliSense' que pode ser acessado a partir de Ferramentas no menu principal do sistema. Esse formulário tem quatro páginas e não só fornece acesso aos mesmos detalhes de configuração descritos acima, mas também à outra funcionalidade relacionada ao IntelliSense através da tabela FoxCode que aciona o IntelliSense.

A primeira página (Figura 17) permite uma forma interativa de definir os valores de propriedade _VFP.EditorOptions para Listas de Membros e Informações rápidas. Ele também define como o IntelliSense deve tratar o uso de minúsculas/maiúsculas para Comandos e Funções, e define um valor padrão a ser utilizado sempre que não há instrução específica. A caixa de seleção determina se as definições especificadas são aplicadas aos comandos e funções do Visual FoxPro apenas ou se devem ser aplicadas também a comandos e funções definidos pelo usuário. Os botões ativam a janela Dicas e navegam na tabela FoxCode que armazena as informações utilizadas pelo IntelliSense.


Figura 17: Página de Configuração do IntelliSense

A segunda página "Tipos" (Figura 18) controla as entradas que geram a lista de tipos exibidos quando a cláusula AS é utilizada. O Visual FoxPro 7.0 é comercializado com um conjunto 'principal' que inclui todas as classes principais do Visual FoxPro e todos os tipos de dados padrão,


Figura 18: Lista de Tipos do IntelliSense

quer eles estejam realmente disponíveis no Visual FoxPro ou não. Limpar a caixa de seleção evita que um item seja exibido nas listas de tipos.

A lista de tipos disponíveis pode ser estendida usando os botões nesta página.
  • Editar abre uma janela de browser que exibe a entrada do item selecionada atualmente na tabela FoxCode. Utilizado principalmente para corrigir o nome da exibição de um item.
  • Biblioteca de tipos abre uma caixa de diálogo que relaciona os servidores COM registrados, os controles ActiveX ou os dois e permite que eles sejam adicionados à Lista de tipos (Figura 19).



Figura 19: Adicionar uma biblioteca de tipos à lista de tipos IntelliSense

Classes abre a caixa de diálogo padrão da biblioteca de classes visuais do Visual FoxPro e permite que classes personalizadas sejam adicionadas à Lista de Tipos do IntelliSense (Figura 20).


Figura 20: Adicionar uma classe personalizada à lista de tipos do IntelliSense

Observe que as classes que foram definidas em arquivos de programa podem ser incluídas na Lista de tipos, mas o registro apropriado deve ser adicionado à tabela FoxCode manualmente.
  • Web Services inicia o Assistente de Registro no Web Service e adiciona o serviço da Web especificado à Lista de tipos (Figura 21)



Figura 21: Adicionar um Web Service à lista de tipos do IntelliSense

A terceira página "Personalizar" (Figura 22) fornece uma tela com filtro que pode ser utilizada para adicionar, editar ou excluir entradas personalizadas na tabela FoxCode.


Figura 22: Editor de Tabelas FoxCode

A seção seguinte deste estudo aborda a tabela FoxCode detalhadamente.

A página "Advanced" (Avançado) final (Figura 23) fornece acesso a 2 itens adicionais: Additional Properties (Propriedades adicionais) e Cleanup (Limpeza). As propriedades adicionais são abordadas em detalhes na próxima seção deste documento.


Figura 23: Opções Avançadas do Gerenciador do IntelliSense

O botão de limpeza exibe uma caixa de diálogo de manutenção para a tabela FoxCode e as listas Mais recentemente utilizados (MRU) (Figura 24).


Figura 24: Caixa de diálogo de manutenção da tabela FoxCode e da lista MRU

Para mais detalhes, consulte o Guia do Visual FoxPro.

A Tabela FoxCode

Essa tabela, instalada por padrão na 'pasta pessoal de aplicativos do usuário' da sua unidade local, é parte central da implementação do IntelliSense no Visual FoxPro 7.0. A funcionalidade do IntelliSense pode ser personalizada e aprimorada manipulando-se o conteúdo dessa tabela. Portanto compreender como essa tabela é estruturada e utilizada é essencial para trabalhar com o IntelliSense no Visual FoxPro.

Tabela 1: Estrutura e uso do FoxCode.dbf
CampoDefinido Descrição
Type C (1) Identificador que define como o registro deve ser processado:
  • C (Comando) Itens de preenchimento automático. Disparados por " "
  • F (Função) Itens de Informações rápidas. Disparados por "("
  • O (COM) Biblioteca de tipos, utilizada para lista de tipos
  • P (Propriedade) Ação quando uma propriedade é acessada
  • S (Script) Executar script do campo Data (Dados)
  • T (Tipo) Declarações, utilizado para lista de tipos
  • U (Usuário) Definido pelo usuário
  • V (Versão) Reservado para dados padrão/versão
  • Z (Especial) Define comportamentos personalizados
Abbrev C (24) Atalho que dispara uma ação
Expanded C (26) Expansão ou substituição de texto por atalho quando necessário
Cmd C (15) O nome de um script a executar. Entre "{}"
Tip M ( 4) A dica rápida exibe informações
Data M ( 4) O conteúdo desse registro pode incluir valores de lista, código, texto de script, etc.
CaseC (1) Especifica como o texto estendido é formatado para substituir o texto abreviado
U = use a função Upper() (maiúscula) para formatar
L = use a função Lower() (minúscula) para formatar
P = use a função Proper() (Próprio) para formatar
M = Nenhuma formatação aplicada (Maiúsculas e minúsculas combinadas)
X = Nenhuma substituição aplicada
Nota: O valor especificado no registro 'Versão' define o padrão a ser utilizado para qualquer registro que não tenha sua própria definição.
Save L (1) Marque para indicar se o registro deve ser mantido durante atualizações da tabela FoxCode (Falso para itens VFP)
TimStamp T (8) Carimbo de data (Itens VFP apenas)
Source M ( 4) Origem do conteúdo do registro. (Itens VFP usam "Reservado")
UniqueID C (10) ID único (itens VFP apenas)
User M ( 4) Disponível para informações definidas pelo usuário


A página Advanced (Avançado) (Figura 24) do formulário do Gerenciador do IntelliSense inclui opções para restaurar e limpar a tabela FoxCode. Se a tabela for danificada ou uma entrada for excluída ou alterada por engano, é possível restaurar a tabela ao seu estado original. Os campos TimeStamp, UniqueID e Save são verificados quando a tabela FoxCode é atualizada ou restaurada para determinar a origem dos dados e se eles podem ser substituídos. Por padrão, as entradas nativas do Visual FoxPro têm carimbo de data e um ID exclusivo, mas seu campo Salve (Salvar) é definido para False (Falso) para que elas possam ser substituídas. Entradas definidas pelo usuário, por outro lado, não têm (ou precisam de) um ID único ou um carimbo de data. Se o campo Save estiver definido para True (Verdadeiro), elas não serão substituídas ou excluídas por alterações na tabela.

Os vários tipos de registro, juntamente com um exemplo de uso de cada um, são detalhados abaixo:

Registro de versão (Tipo = "V")

A tabela FoxCode inclui um único registro deste tipo. Ele é para uso interno do mecanismo IntelliSense. O campo Expanded (Expandido) contém o número da versão da tabela FoxCode atual e o campo Case (Maiúsculas/Minúsculas) define a formatação padrão a ser aplicada a qualquer item que exija formatação, mas não tenha especificado explicitamente qual.

Registro de comando (Tipo = "C")

Esse tipo de comando define uma entrada de preenchimento automático que é disparada por um caractere de espaço e é, por padrão, executada chamando o "script padrão" (definido no campo Data (Dados) do registro com Type = S e um campo Abbrev vazio). Todos os comandos básicos do VFP usam essa metodologia para concatenar o conteúdo do campo expandido ao formato abreviado do comando.

Os outros comandos, mais complexos, chamam um script de handler de comando genérico ({cmdhandler}) especificando-o no seu campo Cmd. Esse script substitui o conteúdo do campo Abbrev pelo conteúdo do campo Expanded, em vez de concatená-los. Essa metodologia pode ser facilmente utilizada para criar "comandos personalizados" que associam explicitamente Informações rápidas (do campo Tip) ou uma lista de membros (do campo Data) definindo uma abreviação e incluindo uma chamada para o script de handler de comando.

Exemplo: O comportamento padrão de preenchimento automático do comando ON é exibir uma lista de todas as opções do comando "ON", que inclui todas as opções de impressão e menu. No entanto, nos códigos em geral, o único comando ON utilizado com freqüência é ON KEY LABEL. Para criar um comando de preenchimento automático para a seqüência "OKL" que expanda para "ON KEY LABEL" quando seguido por um espaço, adicione um registro à tabela FoxCode da seguinte forma:

TypeAbbrevExpandedCmdTipCaseSave
COKL on key label {cmdhandler} ON KEY [LABEL KeyLabelName] [Command] U .T.


Registro de função (Tipo = "F")

A função define uma entrada de preenchimento automático disparada pelo caractere de parênteses esquerdo "(". O conteúdo do campo Tip é utilizado para exibir dicas de Informações rápidas 'inteligentes' que monitoram a entrada de parâmetros comparando o padrão do texto que você digita com o que é definido no registro.

Exemplo: Para criar uma entrada de preenchimento automático para uma função definida pelo usuário chamada OpenFile() disparada quando se digita "OPF(", adicione um registro à tabela FoxCode da seguinte forma:

TypeAbbrevExpandedTipCaseSave
F) OPF OpenFile cFileName[, cFileDir[, lReadOnly]] M .T.


Define a função como tendo 3 parâmetros. À medida que vírgulas são adicionadas ao texto digitado, a dica realçada é automaticamente sincronizada.

Registro de propriedade (Tipo = "P")

Um registro de propriedade é utilizado para atribuir uma caixa de diálogo popup (ou lista de valores) que é exibida sempre que um valor é atribuído a qualquer propriedade em qualquer objeto cujo nome corresponda à entrada no campo Abbrev. O campo Cmd é utilizado para indicar se um script definido em outro local da tabela FoxCode ou o conteúdo do campo Data no registro atual devem ser utilizados para gerar um pop-up. A tabela FoxCode é enviada com dois scripts genéricos que são utilizados com esse tipo de registro. O primeiro (chamado {color}) exibe a caixa de diálogo de seleção de cores e é associado a diversas propriedades de definição de cores (ex.: "BackColor", "BorderColor" e "FillColor"). O segundo (chamado {picture}) exibe a caixa de diálogo de abertura de imagem sempre que uma propriedade "Icon" ou "Picture" é atribuída.

Exemplo: Para atribuir o selecionador de cores padrão ao nome de uma propriedade personalizada, basta adicionar um registro à tabela FoxCode, substituindo seu próprio nome de propriedade (observe que o "." inicial é obrigatório no campo Abbrev), conforme apropriado:

TypeAbbrevCmdCaseSave
P .MyColor {color} M .T.


O uso de scripts é abordado em maiores detalhes posteriormente neste estudo. Por enquanto, basta saber que um script pode ser escrito diretamente no campo Data de um registro e executado definindo o campo Cmd para conter chaves vazias ("{}"). Para adicionar um script que exibe a caixa de diálogo GetFile() e retorna o nome de arquivo selecionado para uma propriedade personalizada chamada ".cSourceFile", adicione um registro à tabela Foxcode da seguinte forma:

TypeAbbrevCmdDataCaseSave
P .cSourceFile {} LPARAMETER oFoxCode
LOCAL lcTxt
oFoxcode.valuetype = "V"
lcTxt = ['] + GETFILE() + [']
RETURN lcTxt
M .T.


Sempre que um valor é atribuído a uma propriedade chamada cSourceFile, a caixa de diálogo GetFile() é automaticamente exibida. (Lembre-se de que o IntelliSense só opera no ambiente de desenvolvimento, nada acontece no tempo de execução).

Registro de componente COM (Tipo = "O")

Um registro COM é utilizado para definir, para o mecanismo do IntelliSense, onde localizar a biblioteca de tipos de um componente COM (ou controle ActiveX). O campo Data é utilizado para armazenar a GUID e informações de versão, e o campo Tip armazena o nome completo do controle. O conteúdo do campo Abbrev é utilizado como entrada da Lista de tipos associados a uma cláusula AS (DEFINE CLASS…AS… , LOCAL…AS… ).

Exemplo: Para adicionar o controle Microsoft TreeView a uma opção na Lista de tipos, adicione um registro à tabela FoxCode da seguinte forma

TypeAbbrevTipDataSave
O TreeView Microsoft TreeView Control 6.0 (SP4) {831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0 .T.


Observe que o campo Data deverá conter a GUID correta que pode ser obtida do registro. No entanto, a forma mais fácil de criar um registro deste tipo é utilizar a opção 'Type Libraries' (Bibliotecas de tipos) na segunda página do Gerenciador do IntelliSense e, em seguida, editar o nome padrão (se necessário) usando o editor na terceira página.

Registro de digitação (Tipo = "T")

Um registro de digitação é emitido para definir para o IntelliSense uma entrada que não tem uma biblioteca de tipos, mas, mesmo assim, deve ser incluída na Lista de tipos. Como a biblioteca de tipos não é obrigatória, ela pode ser utilizada para adicionar classes personalizadas à lista. O conteúdo do campo Data é exibido diretamente na lista suspensa e esse é o único campo que precisa ser preenchido. No entanto, adicionar uma descrição ao campo Abbrev facilita a manutenção da tabela FoxCode.

Para classes visuais, a opção 'Classes' na segunda página do Gerenciador do IntelliSense pode ser utilizada. No entanto, para classes definidas na programação, o registro necessário deverá ser adicionado manualmente.

TypeAbbrevDataSave
.T. Container basecnt OF X:\Projects\Libs\base.vcx".T.
.T. Header basecnt OF X:\Projects\Libs\base.vcx".T.


Registro de usuário (Tipo = "U")

O registro do tipo usuário identifica o conteúdo como uma entrada de texto automática "definida pelo usuário" que, como uma entrada de Comando, é disparada digitando-se o caractere de espaço. A diferença é que o comportamento padrão de um Registro de usuário é substituir o conteúdo do campo Abbrev pelo conteúdo do campo Expanded. Como não há necessidade de chamar o script de handler de comando, esse é o método preferido para criar atalhos definidos pelo usuário.

Exemplo: Para criar uma expansão do atalho 'cright', adicione um registro à tabela Foxcode da seguinte forma:

TypeAbbrevExpandedCaseSave
U cright ©2002 Microsoft Corporation. X .T.


Os registros de tipo usuário também podem chamar scripts. O campo Cmd é utilizado para indicar onde o script está localizado. Um par de chaves vazias significa que o script está embutido no registro atual, enquanto especificar um nome indica que o script está definido no Registro de script em outro local da tabela. A variação do atalho a seguir usa um script interno para obter exatamente o mesmo resultado:

TypeAbbrevCmdDataCaseSave
U cright {} LPARAMETER oFoxCode
LOCAL lcTxt
oFoxcode.valuetype = "V"
lcTxt = "© 2003 Microsoft Corporation"
RETURN lcTxt
X .T.


Registro de script (Tipo = "S")

Os registros de script armazenam o código que deve ser compilado e executado dinamicamente. Esses registros são utilizados para definir scripts "genéricos" que podem ser utilizados por outros registros na tabela FoxCode. Outros registros disparam a execução desses scripts, incluindo o nome especificado no seu campo Abbrev (entre chaves "{}") como conteúdo de seu próprio campo Cmd. (Nota: Qualquer tipo de registro, com exceção dos registros "T" e "O", pode incluir um script em seu próprio campo Data. No entanto, para executar esses scripts internos, um par de chaves vazias "{}" deve ser inserido no campo Cmd).

Exemplo: O script a seguir exibe a caixa de diálogo Getfile() quando chamado e retorna à origem da chamada, independentemente do que for retornado desta caixa de diálogo. Basta adicionar um registro à tabela FoxCode com o nome do script no campo Abbrev e o código necessário no campo Data, da seguinte forma:

TypeAbbrevDataSave
S ChooseFile LPARAMETER oFoxCode
LOCAL lcTxt
oFoxcode.valuetype = "V"
lcTxt = ['] + GETFILE() + [']
RETURN lcTxt
.T.


Registro de extensão personalizada (Tipo = "Z")

O tipo de extensão personalizada é utilizado para identificar registros que o IntelliSense não processa automaticamente. Apenas dois registros desse tipo são fornecidos com o Visual FoxPro 7.0.

O primeiro, cujo campo Abbrev contém "CustomPEMs", armazena as definições de propriedades de configuração avançadas no seu campo Data. Essas propriedades podem ser acessadas através do botão 'Properties' (Propriedades) na página Advanced (Avançado) do Gerenciador do IntelliSense.

O segundo, cujo campo Abbrev contém "CustomDefaultScripts", armazena os nomes de todos os scripts definidos pelo usuário que são chamados pelos hooks codificados no script padrão quando a propriedade avançada "lAllowCustomDefScripts" é definida para True.

Criar e Usar Scripts

Todos os scripts são formados, essencialmente, por duas partes. A primeira é o preâmbulo específico do IntelliSense e a segunda é o código do FoxPro em si que gera o resultado desejado. O componente específico do IntelliSense geralmente consiste em três elementos.
  • Uma instrução de parâmetro. Os scripts precisam ser capazes de aceitar um parâmetro único, que é uma referência ao objeto FoxCode. As propriedades do objeto FoxCode estão totalmente documentadas no arquivo de Ajuda e também estão disponíveis no MSDN.
  • Define o tipo de retorno que o script gera. Isso é feito definindo-se a propriedade ValueType do objeto FoxCode. Essa propriedade é utilizada para determinar como o resultado de executar o código no script é interpretado e existem três valores possíveis, como mostrado na Tabela 2:
Tabela 2: Tipos de Retorno de Script
ValorResultado Interpretado como
V Valor: A ação depende do script - pode ser utilizada para substituir o texto disparador ou acrescentar algo a ele.
L Lista: Exibe o conteúdo da matriz FoxCode. Items como uma lista.
.T. Dica: Exibe o conteúdo da propriedade FoxCode.ValueTip como uma dica de Informações rápidas.
  • Verifique o local de onde o script foi chamado. Para isso, defina a propriedade Location do objeto FoxCode. Claramente nem todas as ações são apropriadas a todas as situações e ele permite ignorar o script, a menos que estejamos na janela de edição correta. Os valores gerados para diferentes tipos de janela de edição estão relacionados na Tabela 3:
Tabela 3: Valores do FoxCode.Location
ValorTipo do editor
0 Janela de comando
1 Programa
8 Extrato de menu
10 Extrato de código
12 Procedimento armazenado

Nota: Esses valores, juntamente com muitas outras informações sobre a janela ativa, são obtidos chamando-se a função FoxTools _EdGetEnv(). Essa não é uma funcionalidade específica do IntelliSense.

O restante do script é basicamente o código padrão do FoxPro que manipula as propriedades do Objeto FoxCode e executa as tarefas necessárias. Os exemplos a seguir ilustram a construção e o uso de Scripts.

Exemplo 1: Texto de inserção automática

Talvez uma das mais simples e, ainda assim mais úteis, personalizações que podemos acrescentar ao IntelliSense seja criar scripts para executar tarefas de programação de rotina, como criar cabeçalhos para programas ou métodos ou inserir blocos de códigos padrão. A Figura EG01 mostra um cabeçalho de programa padrão criado usando um script que é disparado digitando-se 'hdr' e pressionando-se a barra de espaços na janela de edição de programas.


Figura EG01: Cabeçalho de programa gerado por script Para criar o script para gerar esse bloco de texto, nós precisamos adicionar um registro à tabela FoxCode e configurá-lo como ilustrado na tabela a seguir:

CampoConteúdo
Type U
Abbrev Hdr
Cmd { }
Data

LPARAMETERS toFoxCode
IF toFoxcode.Location <1
   RETURN toFoxCode.UserTyped
ENDIF
toFoxcode.valuetype = "V"
LOCAL lcTxt, lcName, lcComment
STORE "" TO lcTxt, lcName, lcComment
#DEFINE CRLF CHR(13)+CHR(10)
lcName = WONTOP()
lcVersion = "Visual FoxPro" + VERSION(4)
lcComment = INPUTBOX( 'Comentário do cabeçalho:' )
TEXT TO lcTxt NOSHOW
***********************************************************************
* Program....: <<UPPER(lcName)>>
* Author.....: Andy Kramek
* Date.......: <<DMY(DATE())>>
* Notice.....: Copyright (c) <<TRANSFORM( YEAR(DATE()))>> Tightline Computers Inc
* Compiler...: <<lcVersion>>
* Purpose....: <<lcComment>>
***********************************************************************
~
ENDTEXT
RETURN TEXTMERGE(lcTxt)


Embora seja bem simples, esse script ilustra como um script IntelliSense é realmente construído em duas partes. Primeiro, nós temos a configuração específica do IntelliSense na qual estabelecemos um parâmetro para receber uma referência ao objeto FoxCode:

LPARAMETERS toFoxCode
*** Esse script fornece um Valor
toFoxcode.valuetype = "V"
*** Não faça nada, a menos que estejamos em uma janela de edição de programa
IF toFoxcode.Location <1
   RETURN toFoxCode.UserTyped
ENDIF


Em seguida, nós definimos como o mecanismo IntelliSense deve tratar o valor retornado. Existem 3 possibilidades:
  • V (Valor) Trata o que for retornado deste script como valor. Por padrão, os valores simplesmente substituem o atalho que dispara o script
  • L (Lista) Usa o conteúdo da coleção de itens como a origem de uma lista. O script deve garantir que a coleção seja devidamente dimensionada e populada
  • T (Dica rápida) Exibe o conteúdo da propriedade ValueTip como uma dica 'Informações rápidas'. O script deve gerenciar o conteúdo da propriedade.
Finalmente, nós selecionamos a propriedade Location do objeto FoxCode. A localização é armazenada como valor numérico derivado de uma função FoxTools (EdGetEnv()) que retorna uma matriz contendo vários itens de informações sobre a sessão do editor atual. O tipo de janela (elemento 25) é especificado como sendo:
0 = Janela de comando
1 = Programa
8 = Extrato de menu
10 = Extrato de código
12 = Procedimento armazenado

Como esse script em particular realmente só é aplicável a um arquivo de programa, nós podemos limitar seu escopo a location = 1. Observe que quando chamado de qualquer outro local, nós simplesmente retornamos o conteúdo de outra propriedade de objeto FoxCode, "UserTyped", que, como o nome indica, contém qualquer coisa que o usuário digite para disparar o script. O resultado direto de digitar 'hdr ' em qualquer local, exceto em um programa, é portanto a seqüência de texto 'hdr '.

A segunda parte do script é o código padrão do Visual FoxPro que realmente cria o texto do cabeçalho como uma seqüência. Não é necessário dizer que esse simples script contém uma combinação de funções novas e antigas do Visual FoxPro.

*** Código FoxPro Padrão a partir daqui
*** Define e inicializa variáveis locais
LOCAL lcTxt, lcName, lcComment
STORE "" TO lcTxt, lcName, lcComment
*** Obter o nome da janela (se tiver sido definido)
lcName = WONTOP()
*** Obter o número da versão do VFP
lcVersion = "Visual FoxPro" + VERSION(4)
*** Obter a descrição
lcComment = INPUTBOX( 'Comentário do cabeçalho:' )
TEXT TO lcTxt NOSHOW***********************************************************************
* Program....: <<UPPER(lcName)>>
* Author.....: Andy Kramek
* Date.......: <<DMY(DATE())>>
* Notice.....: Copyright (c) <<TRANSFORM( YEAR(DATE()))>> Tightline Computers Inc
* Compiler...: <<lcVersion>>
* Purpose....: <<lcComment>>
***********************************************************************
~
ENDTEXT
RETURN TEXTMERGE(lcTxt)

Depois de definir e inicializar as variáveis locais necessárias, nós começamos a populá-los obtendo o nome da janela atual com a função WONTOP() antiga. Em seguida, nós recuperamos o número de versão do VFP, usando a opção 4 da função VERSION() e finalmente usamos a nova função INPUTBOX() para obter um comentário para o cabeçalho do desenvolvedor.

O bloco de texto que nós queremos inserir é criado como uma seqüência usando a construção TEXT…ENDTEXT recém-estendida (que agora permite armazenar o texto diretamente como variável). Observe a inclusão do caractere ~ na última linha do cabeçalho para garantir que o cursor seja devidamente posicionado. Finalmente a instrução RETURN usa ainda outra nova função, o TEXTMERGE() que avalia a variável e retorna o texto resultante como substituição para a abreviação definida.

Exemplo 2: Criar Listas de Estatísticas

Um dos recursos mais óbvios do IntelliSense é o uso amplo e variado que ele faz das listas. Muitos dos comandos e funções nativos do Visual FoxPro implementam listas e você também pode facilmente criar suas próprias listas. A versão mais simples é uma lista estática onde você define os itens que deseja exibir diretamente no campo de dados de um registro do tipo "Usuário" e, em seguida, chama o script "CmdHandler" nativo para gerar a lista.

O exemplo a seguir mostra como nós podemos definir uma lista simples desse tipo que nos permite criar atalhos personalizados para comandos nativos do VFP usados com freqüência.


Figura EG02: Lista estática simples

Aqui um atalho definido pelo usuário ("CSPB") exibe, como uma lista, duas opções predefinidas que podem ser utilizadas para completar o comando de buffer CursorSetProp (normalmente nós não usamos nenhum dos outros modos). Para criar esses atalhos (e outros semelhantes), só é preciso adicionar um registro à tabela FoxCode com as características a seguir:

CampoConteúdo
Type U
Abbrev CSPB
Expanded CURSORSETPROP(
Cmd {cmdhandler}
Data "Buffering", 5, ALIAS() ) && Table Buffered
"Buffering", 3, ALIAS() ) && Table Buffered


O comportamento padrão do script CmdHandler é que ele lê as entradas do campo 'data' e as exibe como uma lista. O texto no campo 'abbrev' é substituído pelo conteúdo do arquivo 'expandido' ao qual o item selecionado da lista é anexado.

No entanto, essa não é a única forma de criar uma lista estática. Como nós indicamos na discussão do script de cabeçalho acima, o objeto FoxCode exibe uma coleção de Itens utilizada para gerar listas quando a propriedade ValueType é definida para "L". Nós podemos, no entanto, gerar uma lista criando um script que povoa diretamente a coleção de Itens. Ele tem uma vantagem que o diferencia do método CmdHandler porque a coleção de Itens possui duas colunas. A primeira é usada como o prompt exibido na lista e a segunda, para criar "Dicas de valores" que são vistas na maioria das listas nativas.

O próximo exemplo povoa a coleção de itens com uma lista de 3 possíveis referências a serem utilizadas na criação de uma variável local para se referir a um objeto. A figura EG03 mostra a lista, que é disparada digitando-se 'obj' seguido por um espaço.


Figura EG03: A lista estática usando a coleção FoxCode.Items Neste exemplo, nós estamos mais uma vez utilizando o campo 'expanded' para substituir o texto usado para disparar o script e a lista para completar a instrução da tarefa. O registro necessário do FoxCode é semelhante a:

CampoConteúdo
Type U
Abbrev Obj
Expanded loRef =
Cmd {}
Dados LPARAMETERS toFoxCode
WITH toFoxCode
  .ValueType = "L"
   DIMENSION .Items[3,2]
  .Items[1,1] = "This"
  .Items[1,2] = "Current Object"
  .Items[2,1] = "ThisForm"
  .Items[2,2] = "Current Form"
  .Items[3,1] = "This.Parent"
  .Items[3,2] = "Immediate Parent Container"
  RETURN ALLTRIM( .Expanded )
ENDWITH


Exemplo 3: Criar listas dinâmicas

As listas estáticas certamente podem ser úteis, mas talvez o maior auxílio de produtividade que a implementação do IntelliSense no FoxPro ofereça seja a capacidade de criar listas geradas dinamicamente. O processo é um pouco mais complexo do que qualquer um dos exemplos que nós observamos por enquanto. Como você verá, o potencial de retorno certamente justifica o investimento de um pouco de tempo.

O exemplo a seguir usa um script genérico para criar uma lista de arquivos do tipo especificado no diretório atual e todos os subdiretórios imediatos. A idéia é que ele seja chamado por outros atalhos que definem o tipo de arquivo específico exibido no momento. Para que precisamos disso se já temos as listas MRU? Bem, para que um arquivo apareça em uma MRU, você deve usá-lo, pelo menos, uma vez e ele deve ter sido usado dentro do número de arquivos que você definiu como o limite de arquivos da MRU. A figura EG04 mostra o resultado de digitar o atalho 'mop' (para "Modify Program") na linha de comando.


Figura EG04: Lista dinâmica de arquivos PRG no subdiretório atual e de primeiro nível

A primeira coisa que nós precisamos fazer é criar uma entrada de atalho na tabela FoxCode. Esse é um registro de usuário simples do tipo que nós já vimos antes. A única diferença é que, em vez de chamar o script embutido no campo Data, nós agora estamos dando um nome de script genérico ("ShoFile") no campo Cmd. O registro a adicionar é semelhante a:

CampoConteúdo
Type U
Abbrev Mop
Expanded MODIFY COMMAND
Cmd {shofile}


O script real é um pouco mais complexo do que o que nós vimos até agora porque precisamos manipular a forma como o objeto FoxCode é manipulado. Para fazer isso, nós temos que instanciar uma subclasse personalizada da classe FoxCodeScript (que é definida no FoxCode.prg). A primeira parte do script faz isso da seguinte forma:

LPARAMETERS toFoxCode
IF FILE(_CODESENSE)
   LOCAL luRetVal, loFoxCodeLoader
  *** Certifique-se de que temos a definição de classe raiz
   SET PROCEDURE TO (_CODESENSE) ADDITIVE
  *** Crie uma instância de nossa subclasse personalizada
   loFoxCodeLoader = CreateObject("FoxCodeLoader")
  *** Chame seu método Start() e passe o objeto FoxCode
   luRetVal = loFoxCodeLoader.Start( toFoxCode )
  *** Limpeza total
   loFoxCodeLoader = NULL
   IF ATC(_CODESENSE,SET("PROC"))#0
      RELEASE PROCEDURE (_CODESENSE)
   ENDIF
  *** Retorne o resultado obtido
   RETURN luRetVal
ENDIF

Observe que esse código considera que a nova variável do sistema, _CodeSense, está apontando para um programa que inclui a definição de classe do objeto "FoxCodeScript". A segunda parte deste script (abaixo) define a subclasse personalizada que é instanciada aqui e passa a referência ao objeto FoxCode. O resultado dessa parte do script meramente garante que o objeto seja lançado de forma limpa e não seja deixada nenhuma referência pendente. Esse é o preâmbulo padrão para criar um script personalizado.

A segunda parte do script é onde nós definimos a subclasse para executar as tarefas específicas de que precisamos. A classe FoxCodeScript define uma propriedade personalizada chamada "oFoxCode" que armazena a referência transmitida ao objeto FoxCode e um método de modelo "Main()" chamado do método Start() quando o objeto é iniciado. É aqui que nós inserimos nosso código de manipulação específico:

DEFINE CLASS FoxCodeLoader as FoxCodeScript
  PROCEDURE Main()
    LOCAL lcMenu, lcKey
    lcMenu = THIS.oFoxcode.MenuItem
    IF EMPTY( lcMenu )
      *** Nada selecionado, portanto exibir lista
      lcKey = UPPER( THIS.oFoxcode.UserTyped )
      *** Que tipo de arquivos nós queremos
      DO CASE
        CASE INLIST( lcKey, "MOP","DOP" )
          lcFiles = '*.prg'
        CASE INLIST( lcKey, "MOP","DOP" )
          lcFiles = '*.prg'
        CASE INLIST( lcKey, "MOP","DOP" )
          lcFiles = '*.prg'
        OTHERWISE
          lcFiles = '*.prg'
      ENDCASE
      *** Povoa a matriz de itens para exibição
      This.GetItemList( lcFiles )
      *** Retorna o item expandido
      RETURN This.AdjustCase()


É importante observar que nós, na verdade, chamamos esse script DUAS VEZES. Na primeira vez, ele é chamado quando o mecanismo IntelliSense reage ao nosso atalho definido (nesse caso 'mop'). O script foi chamado explicitamente do registro na tabela FoxCode e passou uma referência ao objeto FoxCode normalmente. É claro, até agora tudo que nós fizemos foi digitar 'mop' para que a propriedade MenuItem no objeto FoxCode fosse esvaziada e o código definido no topo do método Main() executado.

Como você pode ver, isso seleciona a propriedade UserTyped no objeto FoxCode para determinar que atalho foi digitado, define o tipo de arquivo apropriado e chama o método GetItemList() personalizado. Esse método é responsável por executar um ADIR() para recuperar os nomes de arquivos e copiar a lista da coleção Itens no objeto FoxCode. Em seguida, ele define a propriedade ValueType para "L" (para exibir a lista) e, crucialmente, define a propriedade ItemScript para apontar de volta para esse script ShoFile igual.

A propriedade ItemScript é utilizada pelo mecanismo IntelliSense para determinar o que fazer quando o usuário seleciona um item de uma lista. O valor de retorno dessa passagem do script será o resultado normal de chamar um registro do tipo "Usuário" que deve substituir o atalho com o conteúdo do campo Expanded (neste caso "Modify Command"). Além disso, a lista gerada por GetItemList() será exibida. Como a propriedade Itemscript agora aponta para o script ShoFile, quando é feita uma seleção da lista, ocorre uma segunda passagem do script, mas agora a propriedade MenuItem do Objeto FoxCode terá um valor e, portanto, é a segunda parte do método Main() que é executada:
    ELSE
      *** Retorna o item selecionado
      This.oFoxCode.ValueType = "V"
      RETURN lcMenu
    ENDIF
  ENDPROC

Isso só redefine a propriedade ValueType para "V" e passa o que foi selecionado na lista (agora na variável lcMenu) novamente como valor de retorno para concluir a operação.

O código no método GetItemList() é, com a exceção do final que define o objeto FoxCode para a segunda passagem, o código Visual FoxPro padrão para recuperar uma lista de arquivos dos subdiretórios atual e de primeiro nível.
  PROCEDURE GetItemList( tcKey )
  LOCAL ARRAY laFiles[1,2], laDirs[1], laJunk[1]
  LOCAL lcRootDir, lnDirs, lnDCnt, lnFiles, lcNewDir, lnFound, 
  lcCurDir, lnFCnt, lcFile
    *** Salvar diretório raiz
    lcRootDir = FULLPATH( CURDIR())
    *** Obter subdiretórios
    lnDirs = ADIR( laDirs, '*.' , 'D' )
    lnFiles = 0
    *** E processá-los
    FOR lnDCnt = 1 TO lnDirs
      *** Retornar à raiz e redefinir
      CD ( lcRootDir )
      DIMENSION laJunk[1]
      lcNewDir = UPPER( ALLTRIM( laDirs[ lnDCnt, 1 ] ))
      IF lcNewDir = ".."
        *** Não suba na árvore
        LOOP
      ENDIF
      CD ( lcNewDir )
      lnFound = ADIR( laJunk, lcFiles )
      lcRootDir = FULLPATH( CURDIR())
      *** Se não obtivermos nada, prossiga
      IF lnFound < 1
        LOOP
      ENDIF
      *** Agora processe os arquivos
      FOR lnFCnt = 1 TO lnFound
        lcFile = lcCurDir + laJunk[ lnFCnt, 1 ]
        lnFiles = ALEN( laFiles, 1 ) + 1
        IF NOT EMPTY( laFiles[1] )
          DIMENSION laFiles[ lnFiles, 2 ]
        ELSE
          lnFiles = 1
        ENDIF
        laFiles[ lnFiles, 1 ] = lcFile
      NEXT 
    NEXT 
    *** Voltar ao diretório original
    CD ( lcRootDir )
    *** Se obtivermos resultados, exiba a lista
    IF lnFiles > 0
    Nesse ponto, nós temos uma lista de todos os arquivos do tipo 
	exibida na matriz "laJunk". Agora precisamos configurar o objeto 
	FoxCode para exibir a lista e chamar novamente esse script na 
	seleção:

        THIS.oFoxcode.ValueType = "L"
        THIS.oFoxcode.ItemScript = "ShoFile"
        *** Copiar itens para matriz temporária
        DIMENSION THIS.oFoxcode.Items[lnFiles ,2]
        ACOPY(laFiles,THIS.oFoxcode.Items)
     ENDIF
  ENDPROC
ENDDEFINE

Isso não é realmente tão complexo quanto parece. O registro do script ShoFile inteiro é fornecido aqui:

CampoConteúdo
Type S
Abbrev Shofile
Cmd {}
Data
LPARAMETERS toFoxCode
IF FILE(_CODESENSE)
   LOCAL luRetVal, loFoxCodeLoader
  *** Certifique-se de que temos a definição de classe raiz
   SET PROCEDURE TO (_CODESENSE) ADDITIVE
  *** Crie uma instância da nossa subclasse personalizada
   loFoxCodeLoader = CreateObject("FoxCodeLoader")
  *** Chame seu método Start() e passe o objeto FoxCode
   luRetVal = loFoxCodeLoader.Start( toFoxCode )
  *** Limpeza total aqui
   loFoxCodeLoader = NULL
   IF ATC(_CODESENSE,SET("PROC"))#0
      RELEASE PROCEDURE (_CODESENSE)
   ENDIF
  *** Retornar o resultado obtido
   RETURN luRetVal
ENDIF
DEFINE CLASS FoxCodeLoader as FoxCodeScript
  PROCEDURE Main()
    LOCAL lcMenu, lcKey
    lcMenu = THIS.oFoxcode.MenuItem
    IF EMPTY( lcMenu )
      *** Não há nada selecionado, portanto exiba lista
      lcKey  = UPPER( THIS.oFoxcode.UserTyped )
      *** Que tipo de arquivos nós queremos
      DO CASE
        CASE INLIST( lcKey, "MOP","DOP" )
          lcFiles = '*.prg'
        CASE INLIST( lcKey, "MOP","DOP" )
          lcFiles = '*.scx'
        CASE INLIST( lcKey, "MOP","DOP" )
          lcFiles = '*.prg'
        OTHERWISE
          lcFiles = ""
      ENDCASE
      *** Povoar a matriz de itens para exibição
      This.GetItemList( lcFiles )
      *** Retornar o item expandido
      RETURN This.AdjustCase()
    ELSE
      *** Retornar o item selecionado
      This.oFoxCode.ValueType = "V"
      RETURN lcMenu
    ENDIF
  ENDPROC

  PROCEDURE GetItemList( tcKey )
  LOCAL ARRAY laFiles[1,2], laDirs[1], laJunk[1]
  LOCAL lcRootDir, lnDirs, lnDCnt, lnFiles, lcNewDir
  LOCAL lnFound, lcCurDir, lnFCnt, lcFile
    *** Salvar diretório raiz
    lcRootDir = FULLPATH( CURDIR())
    *** Obter subdiretórios
    lnDirs = ADIR( laDirs, '*.' , 'D' )
    lnFiles = 0
    *** E processá-los
    FOR lnDCnt = 1 TO lnDirs
      *** Retorna à raiz e redefine
      CD ( lcRootDir )
      DIMENSION laJunk[1]
      lcNewDir = UPPER( ALLTRIM( laDirs[ lnDCnt, 1 ] ))
      IF lcNewDir = ".."
        *** Não subir na árvore
        LOOP
      ENDIF
      CD ( lcNewDir )
      lnFound = ADIR( laJunk, lcFiles )
      lcRootDir = FULLPATH( CURDIR())
      *** Se nós não obtivermos nada, prossiga
      IF lnFound < 1
        LOOP
      ENDIF
      *** Agora processe os arquivos
      FOR lnFCnt = 1 TO lnFound
        lcFile = lcCurDir + laJunk[ lnFCnt, 1 ]
        lnFiles = ALEN( laFiles, 1 ) + 1
        IF NOT EMPTY( laFiles[1] )
          DIMENSION laFiles[ lnFiles, 2 ]
        ELSE
          lnFiles = 1
        ENDIF
        laFiles[ lnFiles, 1 ] = lcFile
      NEXT 
    NEXT 
    *** Voltar ao diretório original
    CD ( lcRootDir )
    *** Se obtivermos resultados, exiba a lista
    IF lnFiles > 0
        THIS.oFoxcode.ValueType = "L"
        THIS.oFoxcode.ItemScript = "ShoFile"
        *** Copie itens na matriz temporária
        DIMENSION THIS.oFoxcode.Items[lnFiles ,2]
        ACOPY(laFiles,THIS.oFoxcode.Items)
     ENDIF
  ENDPROC
ENDDEFINE


O script como fornecido inclui manipulação de Programas (mop & dop), Formulários (mof e dof) e Relatórios (mor e dor). É obviamente uma tarefa simples adicionar novos tipos a esse script e isso é deixado como um exercício para o leitor.

topo


   Última Atualização: 5 de Novembro de 2002
© 2003 Microsoft Corporation. Todos os direitos reservados. Nota Legal.