terça-feira, 29 de maio de 2007

Capturando objetos da GS

Um exercício interessante para quem está começando a se aventurar no mundo da OO é modificar a aparência de alguns objetos na tela, através dos métodos que cada um deles oferece. Quem utiliza o Dialog System pode capturar os objetos da GS através de um simples procedimento. Vamos, por exemplo, capturar um botão da GS, passo a passo:

- Temos que definir a classe PushButton na Class-Control, no início do programa, logo depois do Program-ID:

program-id. Teste.
class-control
.
....PushButton is class "pushbutt".

- No fonte cobol, defina duas variáveis que vão servir de referência ao objeto. São os "handles".
Defina também a variável que vai receber o objeto "pushbutton".

working-storage section.
77 handle8 pic 9(08) comp-x value zeros.
77 handle9 pic 9(09) comp-5 value zeros.
77 umBotao object reference value null.

- Levando-se em consideração que estamos utilizando vocabulários, vamos pegar o "handle" do botão e a partir dele, criar um objeto utilizando o método da classe PushButton:

PegarObjetoBotao section.
...move-object-handle PB-GRAVAR handle8
...move handle8 to handle9
...invoke PushButton "fromHandleWithClass" using handle9 PushButon
..........returning umBotao


- A partir daí, nós temos um botão da GS na variável umBotao, como um objeto. Com esse objeto em mãos, podemos invokar quaisquer métodos para manipular o comportamento e o visual do botão, sem recorrer aos comandos do Dialog System. Utilize, por exemplo, o método a seguir:

invoke umBotao "hide"

- É um método simples, que vai fazer desaparecer o botão. Para mostrá-lo novamente, utilize o método "show":

invoke umBotao "show"

Esse exemplo pode ser utilizado também para outros objetos da GS, como window, selectionbox, listbox, etc. Não esqueça que para cada um desses objetos, a definição das classes correspondentes deve ser feita no início do programa, na class-control. Consulte os arquivos de ajuda (MFNXCL30.chm ou MFNXCL31.chm) para conhecer os métodos que podem ser utilizados para cada classe.

segunda-feira, 28 de maio de 2007

Aumentando o seu vocabulário

Uma das maneiras de facilitar a vida do desenvolvedor que utiliza o Dialog System para criar as interfaces dos aplicativos é a utilização de vocabulários. Alguns comandos que são utilizados pelo Dialog System podem ser utilizados no próprio fonte cobol. Aqui na empresa utilizamos os vocabulários em larga escala, pois evitamos ao máximo colocar comandos dentro das GS´s que criamos. Para utilizar alguns comandos do Dialog System no fonte cobol, insira a seguinte linha logo no início do programa, antes da Identification Division:

copy dslang.cpy.

Depois de compilado o programa, você vai poder utilizar alguns comandos do Dialog System direto no seu fonte cobol. Veja a seguir, a lista de comandos:

MOVE-WINDOW window direction distance
CREATE-WINDOW window
SHOW-WINDOW window
SET-FOCUS object
UNSHOW-WINDOW window focus-target-object
DELETE-WINDOW window focus-target-object
REFRESH-OBJECT object
CLEAR-OBJECT object
VALIDATE object
GET-BUTTON-STATE button state
SET-BUTTON-STATE button state
TOGGLE-BUTTON-STATE button
DISABLE-OBJECT object
ENABLE-OBJECT object
DELETE-LIST-ITEM list-or-selection-box position count
SET-SLIDER-RANGE scroll-bar min max
SET-PAGE-VALUE scroll-bar page-size
SET-LINE-VALUE scroll-bar line-size
SET-SLIDER-POSITION scroll-bar position
SET-SLIDER-SIZE scroll-bar size
REPEAT-EVENT
SET-TOP-LIST-ITEM list-box position
SET-LIST-ITEM-STATE list-box state position
SET-AUTOSWIPE-STATE entry-field state
SET-FIELD-LIMIT entry-field len
SET-PRIVILEGE privilege-level
SET-OCCURRENCE object occurrence
COPY-PAGE page position occurence
DELETE-PAGE page
HIDE-OBJECT object
SHOW-OBJECT object
REFRESH-MENU window
SET-FIRST-WINDOW window
MAXIMIZE-WINDOW window
MINIMIZE-WINDOW window
RESTORE-WINDOW window
GET-LIST-ITEM-STATE listbox state position
GET-OCCURRENCE page occurence
GET-DESKTOP-WINDOW object-id
GET-SELECTED-LIST-ITEM listbox-id found-position start-position
GET-TOP-LIST-ITEM listbox position
INSERT-LIST-ITEM listbox text position
INVOKE-MESAGE-BOX message-box text return-value
MOVE-OBJECT-HANDLE object returned-handle
SET-COLOR object foreground-color background-color
SET-MOUSE-SHAPE object mouse-shape
SET-OBJECT-LABEL object label-text
UPDATE-LIST-ITEM listbox item-text position

Por exemplo, no seu fonte cobol você pode mudar o título de uma window ou setar o foco em um determinado objeto. Veja o exemplo:

SET-OBJECT-LABEL WIN-PRINCIPAL "Cadastro de Empresas"
SET-FOCUS PB-GRAVAR


Note que os comandos acima são realmente colocados no fonte cobol, e não no Dialog System.

Vale lembrar que para utilizar os vocabulários corretamente, a geração do "vocabulary copybook" deve sempre ser feita, quando um objeto novo é colocado na GS. Para fazer a geração do "vocabulary copybook", vá no menu File /Generate / Vocabulary copybook.

quarta-feira, 23 de maio de 2007

Letras maiúsculas, por favor !

Eu nunca precisei ter que ligar a tecla CAPSLOCK em meus programas. Mas já vi muita gente perguntando se isso seria possível. Pesquisando pelo site da Microfocus, achei um exemplo bem fácil de como ativá-la. A rotina provavelmente deva funcionar tanto em modo gráfico como em modo caracter:

program-id. set-caps-on.
environment division.
configuration section.
special-names.
....call-convention 74 is winapi.
data division.
working-storage section
.
78 VK-CAPITAL value 20.
01 KeyState pic x(256) value spaces.
procedure division.
000-begin.
....call "cob32api"

....call WINAPI "GetKeyboardState" using by reference KeyState
....if KeyState(VK-CAPITAL + 1:1) not = x"01"
.......call WINAPI "keybd_event" using by value VK-CAPITAL
.......................................by value x"45"
.......................................by value 1
.......................................by value 0
.......end-call
.......call WINAPI "keybd_event" using by value VK-CAPITAL
.......................................by value x"45"
.......................................by value 3
.......................................by value 0
.......end-call
....end-if
....goback.


Eu ainda estou "apanhando" aqui no blog pra conseguir criar uma "identação" convincente nos exemplos de rotinas que de vez em quando publico por aqui. Enquanto não consigo me entender com o editor do blogger, vou "mascarando" alguns caracteres ao lado esquerdo das linhas. Portanto, se você for fazer um "copiar e colar" da rotina acima, desconsidere os caracteres que vai encontrar ao lado esquerdo de cada uma das linhas, ok ?

A rotina original pode ser encontrada no site da
Microfocus
.

sexta-feira, 18 de maio de 2007

A Microfocus não me deu uma "mãozinha"...

Quem gosta de utilizar os recursos do mouse em telas feitas com o Dialog System já deve ter reparado que existem algumas opções paramudar o ponteiro do mouse, movimentando-o por sobre determinados objetos na GS. Isso é feito com a função SET-MOUSE-SHAPE:

MUDAR-PONTEIRO
SET-MOUSE-SHAPE WIN-PRINCIPAL "SYS-WAIT"

Além do "SYS-WAIT", posso utilizar ainda o "SYS-ARROW", "SYS-TEXT", "SYS-MOVE", "SYS-NWSE", "SYS-NESW", "SYS-WE", "SYS-NS" e "SYS-QUESICON". Pois bem. E se eu quiser usar como ponteiro do mouse, aquela "mãozinha" famosa, utilizada nos links dos browsers ? Bem, isso não é possível através do Dialog System, a não ser que eu crie um arquivo de cursor ".cur" e o especifique em um arquivo DS.ICN, por exemplo. Mas não é exatamente isso que eu quero.

Pesquisei então nas classes do NetExpress. A classe MouseCursor é quem cria os ponteiros do mouse para as aplicações. Mas não existe também nessa classe, métodos para criação da "mãozinha", somente dos ponteiros mencionados acima. Resolvi olhar o programa-fonte dessa classe - sim, o programa-fonte está no seu micro - para ver como eram criados os objetos. Olhei o método de classe "SYS-WAIT", para ver como ele retornava o objeto:

method-id. "SYS-WAIT".
local-storage section.
01 aCursorType pic x(4) comp-5.
01 aCursorId pic x(4) comp-5.
linkage section.
01 lnkCursor usage object reference.
procedure division returning lnkCursor.

move IDC-WAIT to aCursorType
invoke super "new" returning lnkCursor
invoke lnkCursor "initialize" using aCursorType

exit method.
end method "SYS-WAIT".


A constante IDC-WAIT que aparece no método encontra-se no arquivo WINDOWS.CPY. Esse arquivo contém todas as definições de variáveis e constantes que devem ser utilizadas com as API´s do Windows. Ela possui o valor 32514. Baseado nessas informações, resolvi procurar no Google alguma informação sobre essas constantes e seus valores. Rapidamente descobri uma que me interessava: IDC-HAND, com o valor 32649. Essa constante não está documentada no WINDOWS.CPY. Pensei então que poderia fazer a mesma coisa que o método "SYS-WAIT", só que passando como parâmetro a constante IDC-HAND com o seu valor 32649.

working-storage section.
77 i pic s9(09) comp-5 value zeros.
78 IDC-HAND value 32649.

procedure division.
invoke MouseCursor "new" returning umCursor
move IDC-HAND to i
invoke umCursor "initialize" using
i

Teoricamente, eu já teria uma "mãozinha" como ponteiro de mouse, referenciado acima pelo objeto umCursor. Bastava setar esse objeto em uma "window" por exemplo, pra ver se tudo havia funcionado.

invoke umaWindow "setCursor" using umCursor

Utilizei o método "SetCursor" e pronto. A Microfocus não me deu nenhuma "mãozinha" mas ela estava lá, passeando por sobre a tela.

quinta-feira, 17 de maio de 2007

O mundo em um objeto...

A utilização da programação orientada ao objeto (POO) simplifica muito a manutenção de sistemas pela facilidade que ela oferece na reutilização de códigos. Por uma questão de padronização, nossos sistemas possuem uma pasta específica, onde todo os executáveis, bibliotecas e rotinas ficam instaladas. Mas estudando um pouco mais os conceitos de herança e aplicando os conhecimentos que adquiri com a POO, comecei a pensar de uma maneira diferente.

Há algum tempo atrás eu não imaginaria que em uma mesma pasta, por exemplo, poderiam estar instalados um sistema de folha de pagamento, um sistema financeiro, um sistema contábil e um sistema de controle de estoque, por exemplo. Normalmente, cada sistema teria a sua pasta específica. Mas para usufruir de tudo o que a POO me oferece, hoje eu penso que esses sistemas deveriam estar todos em uma mesma pasta. Dessa forma, um objeto criado para um determinado sistema poderia ser utilizado nos outros sistemas, com um aproveitamento total de códigos. Pensando mais além, os objetos criados pelos sistemas seriam independentes. Não pertenceriam a um sistema específico.

Um exemplo desse meu pensamento seria um objeto Cheque. Um objeto Cheque poderia ser utilizado tantono sistema financeiro como no sistema de folha de pagamento. Pensando no cheque como um objeto, isso é perfeitamente possível desde que sejam fornecidos ao objeto Cheque, todas informações necessárias para a sua criação: Banco, Conta-Corrente, Numero, Valor, Data e Nominal.

invoke umCheque "setarBanco" using umBanco
invoke umCheque "setarContaCorrente" using umaContaCorrente
invoke umCheque "setarNumero" using wsNumero
invoke umCheque "setarValor" using wsValor
invoke umCheque "setarData" using wsData
invoke umCheque "setarNominal" using wsNominal
invoke umCheque "gravar" returning wsBool

Não importa, então, qual sistema vai fazer uso do objeto Cheque. Ele por si só, é um objeto independente, que pode ser utilizado por qualquer sistema que o necessite. Pensando dessa maneira, uma empresa que desenvolve software poderia ter diversos tipos de objetos independentes de qualquer sistema. Penso que em um determinado momento, a criação de um novo sistema seria nada mais, nada menos, do que juntar os objetos e criar os relacionamentos entre eles. Isso tudo é possível. E já está acontecendo por aqui.

Estou preparando um curso de POO que vai mostrar todo o lado conceitual da POO e também o lado prático, para quem desenvolve software utilizando o Microfocus NetExpress. Serão duas apostilas, com muitos exemplos de como utilizar os recursos da POO. Terei disponibilidade para viagens nos finais de semana, por isso, pretendo montar algumas turmas em regiões próximas ao Estado de São Paulo. Assim que o curso estiver montado e pronto, vou divulgar aqui no blog.

quarta-feira, 16 de maio de 2007

Dialog System com o visual do Windows XP

Experimentei criar um "manifest file" chamado "dswin.exe.manifest" para tentar fazer o Dialog System (que na verdade é o executável DSWIN.EXE) rodar utilizando o visual do Windows XP. Salvei o "manifest file" na pasta onde se encontra o Dialog System (\Netexpress\DialogSystem\Bin). E não é que o Dialog System passou a mostrar o visual do Windows XP direitinho ?




Fiz o mesmo teste com o IDE do NetExpress (MFNETX.EXE na pasta \Netexpress\Base\Bin). Criei um "manifest file" com o nome de "mfnetx.exe.manifest", mas ao rodar o IDE, notei que algumas toolbars apresentaram áreas transparentes, mostrando o pano de fundo do meu desktop. Portanto, só vou utilizar o "manifest file" junto com o Dialog System, já que ele ainda é o responsável pelas interfaces dos meus sistemas.




A quantidade de registros em um arquivo

Já existe desde março no site da Microfocus um exemplo de como detectar a quantidade de registros em um arquivo ISAM. O exemplo no site está documentado para ser utilizado com a versão 4.0 do NetExpress, mas já fiz testes com a versão 3.0 e 3.1 e funcionou perfeitamente.

O segredo é a utilização de alguns arquivos "cpy" que contém estruturas identificando os cabeçalhos dos arquivos indexados. São feitas chamadas ao "EXTFH.EXE" que retorna as informações sobre qualquer arquivo indexado nos dados dessas estruturas. Pode-se saber, por exemplo, o tipo de arquivo, a quantidade de chaves, o tamanho do registro, se são registros fixos ou variáveis, entre outras informações. Vale a pena dar uma conferida e utilizar esse recurso.

terça-feira, 15 de maio de 2007

Textos transparentes...


Estou fazendo testes com textos transparentes no CSListview. Com um pouco de pesquisa na internet, fica fácil aprender a enviar mensagens aos componentes e manipular todo o visual deles.

Foi utilizada a API "SendMessageA", enviando a mensagem LVM-SETTEXTBKCOLOR com parâmetro CLR-NONE para fazer todo o trabalho. Mas me parece que mesmo sem essa mensagem, o texto já se comporta como transparente quando o CSListview tem imagens de fundo.

segunda-feira, 14 de maio de 2007

Programas controladores...

Eles querem me controlar, mas os famosos "programas controladores" estão com os dias contados aqui na empresa. Já não dependemos deles para interceptar eventos, muito menos para criar os componentes que desejamos nas GS´s. Lembro lá no início, quando começamos a engatinhar com o Netexpress, que iniciei meus estudos sobre os programas controladores e descobri vários segredinhos dentro deles.

Com a ajuda do meu amigo Flávio Maia, da BMA Sistemas, passei a utilizar apenas um programa controlador por GS. Já foi uma grande avanço. Mas hoje em dia, confesso, eles estão morrendo. Daqui há algum tempo, não vou precisar deles pra mais nada. E essa mudança pode ser gradativa, para vocês que ainda possuem essa "dependência".

Uma das formas de começar a se libertar dos programas controladores é utilizando os métodos que o objeto oferece, ao invés de fazer as chamadas-padrões ao programa controlador. Para isso, você deve ler um pouco sobre as classes, os objetos e seus métodos no arquivo de ajuda que se encontra na pasta \NetExpress\Base\Bin.


O arquivo de ajuda chama-se MFNXCL30.CHM ou MFNXCL31.CHM, para quem usa a versão 3.0 ou 3.1 do NetExpress, respectivamente. Nesse arquivo, você encontra todos os métodos para utilizar com todos os componentes que o Netexpress oferece.





















A princípio pode parecer difícil utilizá-lo, mas com um pouco de tempo e dedicação, toda a manipulação de um componente pode ser feita, independente do seu programa controlador.

sábado, 12 de maio de 2007

Problemas com o "grid" no Listview

A Microsoft documentou um "bug" no Listview (desde Janeiro de 2005) em determinadas aplicações rodando no Windows XP. As linha de grade (quando se utiliza o método "grid") podem aparecer de forma incorreta em determinados momentos. Isso acontece quando se clica com o mouse nas barras de rolagem do Listview. Eu passei por isso na última semana, quando comecei a utilizar diversos Listview´s nas janelas de nossas aplicações. Para resolver o problema, a Microsoft recomenda retirar a aplicação de alguns efeitos visuais. Clique com o botão direto do mouse no desktop e vá em Propriedades. Na aba Aparência, clique em Efeitos. Desmarque a opção Usar este efeito de transição para menus e dicas de ferramentas. Dessa forma, o problema com o Listview desaparece.

Um manifesto a nosso favor...

Para quem desenvolve aplicações e deseja oferecer o visual do Windows XP de maneira fácil e rápida, pode criar um "manifest file" e colocá-lo na pasta da aplicação. Esse arquivo informa ao Windows que você deseja utilizar o visual do Windows XP. Nem preciso dizer que isso só vai realmente funcionar nos micros que tiverem o XP instalado, não é ? O "manifest file" deve ser copiado na pasta de sua aplicação. Detalhe: o nome do arquivo deve ser o mesmo do seu executável principal. Por exemplo, se o seu executável for um "seletor.exe", então o "manifest file" deve se chamar "seletor.exe.manifest".

Vale lembrar que ao utilizar o Dialog System, você vai continuar tendo a aparência de botões no estilo Win98. Esse procedimento só tem efeito na execução da aplicação.

Os "QuickView´s"

Me inspirei em alguns sites por aí para criar um novo componente em nossas aplicações. Dei a ele o nome de "QuickView". Na verdade, é uma área de tela sensível ao mouse e quando o usuário passa o mouse nessa área, o componente envia ao Dialog um código identificando os eventos que estão ocorrendo. Posso detectar o "MouseOver" quando o mouse "entra" na área do componente, o "MouseMoved" quando o mouse se movimenta por sobre a área ou o "MouseOut" quando o mouse deixa a área do componente. Esse componente permitiu que fizéssemos diversas telas com informações, que aparecem à medida que o usuário movimenta o mouse nos objetos dispostos na tela. Implementamos também o recurso de imagens nesses objetos (OLEPicture), criando assim uma interface mais amigável ao usuário. Nas imagens abaixo, as áreas na parte de baixo da tela são os nossos "quickview´s". Cada um deles mostra uma tela de informações diferente, deixando o usuário a vontade para escolher a informação que necessita, no momento que desejar.