DIFICIL APRENDIZADO - Aula 09
Enviado: 14 Nov 2004 23:20
Amiguinhos
Chegou a hora de acrescentar um diálogo ao nosso aplicativo e opto por usar um formulário .RC feito no WorkShop ao invés de posicionar na mão os controles.
http://www.5volution.com.br/downloads/forum/aula09.rc
Será necessário também alguns arquivos constantes em:
http://www.5volution.com.br/downloads/forum/forum5.zip
PERGUNTA: Por usar .RC ao invés de .DLL?
Os arquivos .RC, assim como os .OBJ serão LINKados diretamente ao executável. A manutenção pode ser feita via NOTEPAD também.
A .DLL padrão dos controles Borland deverão ser carregadas no inicio do .PRG:
O diálogo criado e contido dentro do arquivo .RC será acionado via comando:
Uma função de suma importancia nos dará suporte para o COMBO existente no código e para facilitar sua programação um comando de definição foi acrescentado ao inicio do .PRG.
O resultado deverã ser igual ao da figura abaixo:
Figura 09
Digite o código abaixo em um arquivo e de-lhe o nome de AULA09.PRG e compiLe utilizando o BUILD.BAT:
C:\>BUILD AULA09
Veja que no inicio do .PRG são solicitados mais arquivos .CD e um deles esta neste endereço:
Codigo de AULAS.CH
Este .CH tem a definição do comando COMBO, pois a DBCOMBO não trabalha com tabelas muito grandes:
Sendo que:
ALIAS - Nome da tabela em que os dados serão pesquisados
ORDER - Ordem de indice nesta tabela em que o dado será pesquisado
FIELD - Campo que terá o conteúdo retornado dentro da variável em RESULT
HEADER - Colunas que serão apresentadas no listbox de pesquisa.
RESULT - Variável que contém o resultado da busca.
UDF - função do usuário que será executada após ter escolhido o resultado.
Também podemos perceber que a maioria das funções são iniciadas por STATIC, isto quer dizer que as mesmas serão visualizadas somente no .PRG em que estão, e voce pode muito bem possuir funções de mesmo nome em vários .PRG desde que sejam STATIC.
Já a função ZoomLBX será visualizada por todo aplicativo sendo de uso geral.
A função ManReg() possui uma estrutura padrão para manipulação do diálogo, variáveis e tabelas, sendo:
Uma melhoria colocada no código desta aula foi o parâmetro SPINNER no REDEFINE GET onde ao se clicar na scrollbar seus valores são alterados.
Veja no .RC que os controle de ID 104 e 105 possuem ativos o estilo WS_VSCROLL, pois foi forçado no WorkShop para que fossem apresentados scrollbar vertical no controle texto.
No eventos ON UP e ON DOWN a variavel é incrementada/decrementada e o objeto GET é refrescado.
Até a próxima.
Chegou a hora de acrescentar um diálogo ao nosso aplicativo e opto por usar um formulário .RC feito no WorkShop ao invés de posicionar na mão os controles.
http://www.5volution.com.br/downloads/forum/aula09.rc
Será necessário também alguns arquivos constantes em:
http://www.5volution.com.br/downloads/forum/forum5.zip
PERGUNTA: Por usar .RC ao invés de .DLL?
Os arquivos .RC, assim como os .OBJ serão LINKados diretamente ao executável. A manutenção pode ser feita via NOTEPAD também.
A .DLL padrão dos controles Borland deverão ser carregadas no inicio do .PRG:
LoadLibrary( "bwcc.dll" )
O diálogo criado e contido dentro do arquivo .RC será acionado via comando:
DEFINE DIALOG oDlg RESOURCE "dlgAula09"
Uma função de suma importancia nos dará suporte para o COMBO existente no código e para facilitar sua programação um comando de definição foi acrescentado ao inicio do .PRG.
O resultado deverã ser igual ao da figura abaixo:
Figura 09
Digite o código abaixo em um arquivo e de-lhe o nome de AULA09.PRG e compiLe utilizando o BUILD.BAT:
C:\>BUILD AULA09
#include "fivewin.ch"
#include "report.ch"
#include "aulas.ch"
set procedure to aulas
function main()
local oWnd
SET DELETE ON
LoadLibrary("bwcc.dll")
DEFINE WINDOW oWnd TITLE "Janela principal" ;
FROM 5, 5 TO 24, 64 ;
MENU Menu() ;
MDI
DEFINE BUTTONBAR oBar OF oWnd
DEFINE BUTTON OF oBar FILE "exit.bmp" ;
ACTION oWnd:end() ;
MESSAGE "Fecha este aplicativo..." ;
TOOLTIP "Fecha este aplicativo."
DEFINE BUTTON OF oBar GROUP FILE "Open.bmp" ;
ACTION MDIChild( oWnd ) ;
MESSAGE "Abre um browse normal..." ;
TOOLTIP "Abre um browse normal."
DEFINE BUTTON OF oBar FILE "cut.bmp" ;
ACTION MDIChild2( oWnd ) ;
MESSAGE "Abre um browse com botões..." ;
TOOLTIP "Abre um browse com botões."
SET MESSAGE OF oWnd TO "Forum Clipper-On-Line" KEYBOARD DATE CLOCK
ACTIVATE WINDOW oWnd
return nil
FUNCTION Menu()
local oMenu, oMenu1, oMenu2
local oSub1,oSub2,oSub3
MENU oMenu
MENUITEM oMenu1 PROMPT "Opcao &1"
MENU
MENUITEM "&Clientes"
MENU
MENUITEM "Incluir" ACTION MDIChild()
MENUITEM "Excluir" ACTION MDIChild()
SEPARATOR
MENUITEM "Consultar" ACTION MDIChild()
ENDMENU
MENUITEM "&Fornecedores"
MENU
MENUITEM "Incluir" ACTION MDIChild2()
MENUITEM "Excluir" ACTION MDIChild2()
SEPARATOR
MENUITEM "Consultar" ACTION MDIChild2()
ENDMENU
ENDMENU
MENUITEM oMenu2 PROMPT "Opcao &2" DISABLED
MENU
MENUITEM "Item 1" DISABLED ACTION MDIChild()
MENUITEM "Item 2" DISABLED ACTION MDIChild()
ENDMENU
ENDMENU
return oMenu
function MDIChild()
//local oWnd1, oBrw
//USE AULA07 ALIAS AULA09 NEW SHARED
//DEFINE WINDOW oWnd1 TITLE "Janela Normal" MDICHILD ;
// FROM 1, 1 TO 10, 30
//@ 0,0 LISTBOX oBrw FIELDS OF oWnd1 SIZE 225,115
//ACTIVATE WINDOW oWnd1
return nil
function MDIChild2( oWnd )
local oWnd1, oBrw
USE SIGLAS SHARED NEW INDEX SIGLA019
USE REGIAO SHARED NEW INDEX REGIA001
SELE SIGLAS
DEFINE WINDOW oWnd1 TITLE "Janela MDI" MDICHILD ;
FROM 1, 1 TO 10, 30
DEFINE BUTTONBAR oBar1 OF oWnd1
DEFINE BUTTON OF oBar1 FILE "exit.bmp" ;
ACTION MsgInfo( "Coloque uma chamada a uma rotina" ) ;
MESSAGE "Coloque aqui uma mensagem..." ;
TOOLTIP "Sou uma dica rapida para este controle."
DEFINE BUTTON OF oBar1 FILE "Open.bmp" ;
ACTION MsgInfo( "Coloque uma chamada a uma rotina" ) ;
MESSAGE "Coloque aqui uma mensagem..." ;
TOOLTIP "Sou uma dica rapida para este controle."
@ 2,0 LISTBOX oBrw FIELDS OF oWnd1 SIZE oWnd:nWidth()-5,oWnd:nHeight()-125
oBrw:bRClicked := { | nRow, nCol | PopupReg( nRow, nCol, oBrw, oWnd1 ) }
oBrw:bLdblClicked := {|| oBrw:disable(), MsgStop("Duplo Clique - Abrir um Dialog ou executar uma rotina"), oBrw:enable() }
oBrw:bBKColor := { |nRow,nCol,nStyle| if( nStyle==0 .and. nCol==5, CLR_WHITE, ) }
oBrw:nFreeze := 2
oBrw:nClrPane := { || IIF( ( oBrw:cAlias)->(Recno()) %2 == 1, nRGB(187,254,138), nRGB(226,255,196))}
oBrw:lAdjLastCol := .F.
oBrw:nLineHeight*= 1
oBrw:nHeaderHeight*= 1.5
ACTIVATE WINDOW oWnd1 MAXIMIZED
return nil
static function PopupReg( nRow, nCol, oLbx, oWnd )
local oPopup
MENU oPopup POPUP
MENUITEM "&Inserir registro" ACTION ManReg( oWnd, "NOVO" , oLbx )
MENUITEM "E&xcluir registro" ACTION DelReg( oLbx )
MENUITEM "&Alterar registro" ACTION ManReg( oWnd, "MOSTRA", oLbx )
SEPARATOR
MENUITEM "&Imprimir listagem" ACTION RptReg( oLbx )
SEPARATOR
MENUITEM "&Sair" ACTION oLbx:oWnd:End()
ENDMENU
ACTIVATE POPUP oPopup AT nRow, nCol OF oLbx
return nil
static function DelReg( _lbx_ )
if MsgYesNo( "Tem certeza da exclusao deste registro?" )
RLOCK()
DELETE
COMMIT
_lbx_:UpStable()
_lbx_:Refresh()
endif
return .t.
static function ManReg( _num_, lAppend, _lbx_ )
local lSave := .f.
SELE SIGLAS
if lAppend ="NOVO"
goto bottom
skip
endif
M->UF := SIGLAS->UF
M->ESTADO := SIGLAS->ESTADO
M->ICMS := SIGLAS->ICMS
M->IPI := SIGLAS->IPI
M->WALIQICM := SIGLAS->WALIQICM
M->REGIAO := SIGLAS->REGIAO
M->REDUCAO := SIGLAS->REDUCAO
if lAppend ="NOVO"
//
// -> Deficao de valores constantes
M->CANCELADO := "N"
M->CEMP := "N"
M->NATUREZA := "SAIDA"
M->PAGO := "N"
M->VT := "S"
M->REDUCAO := 8.33
endif
SET 3DLOOK ON
DEFINE DIALOG oDlg RESOURCE "dlgAula09"
REDEFINE GET oGet VAR M->UF PICTURE "@!" ID 101 OF oDlg
REDEFINE GET oGet VAR M->ESTADO PICTURE "@!" ID 102 OF oDlg
REDEFINE COMBO oCbx VAR M->REGIAO ID 103 OF oDlg ;
RESOURCE "combo.bmp" ;
VALID .T. ;
ALIAS REGIAO ;
ORDER 1 ;
FIELD REGIAO->REGIAO ;
HEADER REGIAO->REGIAO ;
RESULT M->REGIAO ;
UDF fun()
REDEFINE GET oGet1 VAR M->ICMS PICTURE "@E 999.99" ID 104 OF oDlg ;
SPINNER ;
ON UP (++M->ICMS,oGet1:Refresh()) ;
ON DOWN (--M->ICMS,oGet1:Refresh())
REDEFINE GET oGet2 VAR M->REDUCAO PICTURE "@E 999.99" ID 105 OF oDlg ;
SPINNER ;
ON UP (++M->REDUCAO,oGet2:Refresh()) ;
ON DOWN (--M->REDUCAO,oGet2:Refresh())
REDEFINE BUTTON ID 1 OF oDlg ACTION ( lSave := .t. , oDlg:End() )
REDEFINE BUTTON ID 2 OF oDlg ACTION ( lSave := .f. , oDlg:End() )
ACTIVATE DIALOG oDlg CENTERED
if lSave
SELE SIGLAS
if lAppend ="NOVO"
APPEND BLANK
else
RLOCK()
endif
SIGLAS->UF := M->UF
SIGLAS->ESTADO := M->ESTADO
SIGLAS->ICMS := M->ICMS
SIGLAS->IPI := M->IPI
SIGLAS->WALIQICM := M->WALIQICM
SIGLAS->REGIAO := M->REGIAO
SIGLAS->REDUCAO := M->REDUCAO
COMMIT
_lbx_:UpStable()
_lbx_:Refresh()
endif
return .t.
static function RptReg( _lbx_ )
local oRpt
local n
local cAlias := If( _lbx_ != nil, _lbx_:cAlias, Alias() )
REPORT oRpt TITLE "Relatorio: " + cAlias ;
HEADER "Data: " + DToC( Date() ) + ", Hora: " + Time() ;
FOOTER "Pagina: " + Str( oRpt:nPage, 3 ) ;
PREVIEW
if Empty( oRpt ) .or. oRpt:oDevice:hDC == 0
return nil
endif
COLUMN TITLE "UF" DATA SIGLAS->UF
COLUMN TITLE "ESTADO" DATA SIGLAS->ESTADO
COLUMN TITLE "ICMS" DATA SIGLAS->ICMS
COLUMN TITLE "IPI" DATA SIGLAS->IPI
COLUMN TITLE "REDUCAO" DATA SIGLAS->REDUCAO
ENDREPORT
ACTIVATE REPORT oRpt
GO TOP
return .t.
static function fun( _lbx_ )
return .t.
Function ZoomLbx( oGet, ;
nWidth , ; //
nHeight , ; //
m_relacao , ; // M->CIDADE - dado passado para pesquisa
m_area , ; // "CIDADE" - base de dados pesquisada
m_ordem , ; // 1 - ordem do indice
m_campo , ; // "CIDADE" - campo com conteudo retornado
m_string , ; // "CIDADE+' | '+ESTADO" - cabecalho do box
m_saida , ; // "M->CIDADE" - variavel de retorno
m_funcao , ; // {|| PSQ_FUNCAO() } - funcao acionada
m_lista ) //
Local oCBWnd, oCBLbx, aPoint
Local xVal, bRestore, lNormal
bRestore := {|| IIF( !lNormal, oGet:varput( xVal ), ), oCBWnd:End() }
xVal := oGet:varget()
lNormal := .F.
u_areatua := alltrim( str( select(), 3 ) ) // pega area atual
u_ordem := indexord() // pega ordem atual
sele &m_area // seleciona area de pesquisa
set order to m_ordem // coloca nova ordem
aPoint := AdjustWnd( oGet, nWidth, nHeight )
DEFINE WINDOW oCBWnd FROM aPoint[1] + 1, aPoint[2] TO aPoint[1] + nHeight, aPoint[2] + nWidth pixel STYLE nOR( DS_MODALFRAME, WS_POPUP, WS_BORDER )
oCBLbx := TWBrowse():New( 0, 0, ;
nWidth, nHeight,;
m_string,{""},{100,200},;
oCBWnd,,,,{|| ( oGet:varput( EVAL( m_campo ) ), ;
oGet:refresh() )},;
{|nRow,nCol,nFlags|( oCBWnd:End() )},, ;
oGet:oFont,,,,, .F.,, .T.,, .F.,,, )
oCBLbx:bLdblClicked := {|| (lNormal := .T., eval( bRestore), eval( m_funcao) ) }
oCBLbx:aHeaders := "" // m_string
oCBLbx:nLineStyle := 6
oCBWnd:bKeyDown := {|nKey,nFlag|DOKEYCHECK(nKey,nFlag,oCBLbx),;
IIF( nKey == VK_ESCAPE, ;
eval( bRestore ) , ;
IIF( nKey == VK_RETURN, ;
(lNormal := .T., eval( bRestore), eval( m_funcao) ), ) ;
) }
ACTIVATE WINDOW oCBWnd ;
ON INIT (oCBWnd:bLostFocus := {|| oCBWnd:bLostFocus := nil, eval( bRestore ) } , oCBLbx:Refresh() );
VALID ( lNormal := .T. ) // , oLbx:lCloseArea() )
Return Nil
Veja que no inicio do .PRG são solicitados mais arquivos .CD e um deles esta neste endereço:
Codigo de AULAS.CH
#command REDEFINE COMBO [ <oGet> VAR ] <uVar> ;
[ ID <nId> ] ;
[ OF <oWnd> ] ;
[ <help:HELPID, HELP ID> <nHelpId> ] ;
[ VALID <ValidFunc> ] ;
[ PICTURE <cPict> ] ;
[ <color:COLOR,COLORS> <nClrFore> [,<nClrBack>] ] ;
[ FONT <oFont> ] ;
[ CURSOR <oCursor> ] ;
[ MESSAGE <cMsg> ] ;
[ <update: UPDATE> ] ;
[ WHEN <uWhen> ] ;
[ ON CHANGE <uChange> ] ;
[ <readonly: READONLY, NO MODIFY> ] ;
[ <spin: SPINNER> [ON UP <SpnUp>] [ON DOWN <SpnDn>] [MIN <Min>] [MAX <Max>] ] ;
[ RESOURCE <cResName> ] ;
ALIAS <database> ;
ORDER <nOrder> ;
FIELD <uField> ;
HEADER <cHeader,...> ;
RESULT <cRet>;
UDF <uFunc> ;
=> ;
[ <oGet> := ] TBtnGet():ReDefine( <nId>, bSETGET(<uVar>),;
[<oWnd>],;
<nHelpId>, <cPict>, <{ValidFunc}>, <nClrFore>, <nClrBack>,;
<oFont>, <oCursor>, <cMsg>, <.update.>, <{uWhen}>,;
[ \{|nKey,nFlags,Self| <uChange> \}], <.readonly.>,;
<.spin.>, <{SpnUp}>, <{SpnDn}>, <{Min}>, <{Max}>,;
[<cResName>],;
{|Self| ZoomLbx( <oGet>,350,150,,<(database)>,<nOrder>,;
<{uField}>,{|| {<cHeader>} },<(cRet)>,<{uFunc}> ) } )
Este .CH tem a definição do comando COMBO, pois a DBCOMBO não trabalha com tabelas muito grandes:
REDEFINE COMBO oCbx2 VAR M->IDCCUSTO ID 103 OF oDlg ;
RESOURCE "combo.bmp" ;
VALID .T. ;
ALIAS CENTROS ;
ORDER 1 ;
FIELD CENTROS->IDCCUSTO ;
HEADER STR(CENTROS->IDCCUSTO,3),CCUSTO ;
RESULT M->IDCCUSTO ;
UDF fun()
Sendo que:
ALIAS - Nome da tabela em que os dados serão pesquisados
ORDER - Ordem de indice nesta tabela em que o dado será pesquisado
FIELD - Campo que terá o conteúdo retornado dentro da variável em RESULT
HEADER - Colunas que serão apresentadas no listbox de pesquisa.
RESULT - Variável que contém o resultado da busca.
UDF - função do usuário que será executada após ter escolhido o resultado.
Também podemos perceber que a maioria das funções são iniciadas por STATIC, isto quer dizer que as mesmas serão visualizadas somente no .PRG em que estão, e voce pode muito bem possuir funções de mesmo nome em vários .PRG desde que sejam STATIC.
Já a função ZoomLBX será visualizada por todo aplicativo sendo de uso geral.
A função ManReg() possui uma estrutura padrão para manipulação do diálogo, variáveis e tabelas, sendo:
local lSave := .f.
//
// Aqui seleciono a tabela a ser manuseada
//
if lAppend ="NOVO"
goto bottom
skip
endif
//
// Aqui as variáveis serão preenchidas com dados ou zeradas
//
if lAppend ="NOVO"
//
// No caso de inclusão, se alguma variável necessitar de dado padrão.
//
endif
SET 3DLOOK ON
DEFINE DIALOG oDlg ...
//
// Aqui são colocados todos os REDEFINEs de controles para o diálogo
//
REDEFINE BUTTON ID 1 OF oDlg ACTION ( lSave := .t. , oDlg:End() )
REDEFINE BUTTON ID 2 OF oDlg ACTION ( lSave := .f. , oDlg:End() )
ACTIVATE DIALOG oDlg CENTERED
if lSave // Depende do resultado retornado pelo BUTTON acionado
//
// Aqui seleciono a tabela a ser manuseada
//
if lAppend ="NOVO"
APPEND BLANK
else
RLOCK()
endif
//
// Aqui salvo o conteúdo das variáveis dentro de seus respectivos campos
//
COMMIT
_lbx_:UpStable() // Devem existir sempre
_lbx_:Refresh()
endif
return .t.
Uma melhoria colocada no código desta aula foi o parâmetro SPINNER no REDEFINE GET onde ao se clicar na scrollbar seus valores são alterados.
Veja no .RC que os controle de ID 104 e 105 possuem ativos o estilo WS_VSCROLL, pois foi forçado no WorkShop para que fossem apresentados scrollbar vertical no controle texto.
REDEFINE GET oGet1 VAR M->ICMS PICTURE "@E 999.99" ID 104 OF oDlg ;
SPINNER ;
ON UP (++M->ICMS,oGet1:Refresh()) ;
ON DOWN (--M->ICMS,oGet1:Refresh())
No eventos ON UP e ON DOWN a variavel é incrementada/decrementada e o objeto GET é refrescado.
Até a próxima.