Vous êtes sur la page 1sur 449

1001coisasquevocqueria

SaberSobre
VisualFoxPro
MarciaAkins
AndyKramek
RickSchummer

HentzenwerkePublishing

Publicadopor:
HentzenwerkePublishing
980MdioCircleDrive
WhitefishBayWI53217EUA

Hentzenwerkepublicaodelivrosestodisponveisatravsdelivrariasedirectamenteapartirdo
editor.ContateHentzenwerkePublishingem:
414.332.9876
414.332.9463(fax)
www.hentzenwerke.com
books@hentzenwerke.com

1001CoisasQueVocQueriaSaberSobreVisualFoxPro
PorMarciaAkins,AndyKramekeRickSchummer
EditorTcnico:JohnHosier
CpiadoEditor:JulieA.Martin

Copyright2000porMarciaAkins,AndyKramekeRickSchummer

Todososoutrosprodutoseserviosidentificadosaolongodestelivrosomarcascomerciaisouregistradas
marcascomerciaisdesuasrespectivasempresas.Elessousadosemtodoestelivroemeditorial
nicaeparaobenefciodetaisempresasdemoda.Semtaisutilizaes,ouousodequalquernomecomercial,
sedestinaatransmitirendossoououtraafiliaocomestelivro.

Todososdireitosreservados.Nenhumapartedestelivro,ouosarquivosCHMajudadisponveispordownload
HentzenwerkePublishing,podeserreproduzidaoutransmitidaporqualquerformaouporqualquermeio,
,Fotocpiaeletrnicamecnica,gravaoououtro,semaprviaeporescrito
permissodoeditor,excetoqueaslistasdeprogramasearquivosdecdigodeamostrapodemserintroduzidas,
armazenadoeexecutadonumsistemadecomputador.

Asinformaesemateriaiscontidosnestelivrosofornecidos"talcomoest",semgarantiade
qualquertipo,expressaouimplcita,incluindosemlimitaoqualquergarantiarelativa
preciso,aadequaoouintegridadedetaisinformaesoumaterialouqueosresultadossejam
obtidoapartirdeutilizartaisinformaesoumaterial.NemHentzenwerkePublishingnemo
autoresoueditoresserresponsvelporquaisquerreivindicaesatribuveisaerros,omisses,ououtra
imprecisesnasinformaesoumateriaiscontidosnestelivro.Emnenhumcasoa
HentzenwerkePublishingouosautoresoueditoresdeserresponsvelpordanosdiretos,indiretos,especiais,
acidentaisouconsequentes,decorrentesdousodetaisinformaesoumaterial.

ISBN:0965509338

FabricadonosEstadosUnidosdaAmrica.

Dedicatrias
AndyKramek
Estetrabalhodedicadoaomeupai,queestavatoorgulhosoquandoeucomeceiateralgunsdosmeus
escritapublicada,masmorreupoucoantesdaconclusodeste,omaisrecente,olivroqueeuseiquefaria
fizeramnoaindamaisfeliz.

MarciaAkins
ParaminhairmNancy,quemeensinouquenuncatardedemaisparatentaresemcujaajudae
apoio,eunoteriasidocapazdefazertudooquetenhonoanopassado.Obrigado,euofaria
notersidocapazdeescreverestelivrosemvoc.

RickSchummer
Estelivrodedicadomemriademeuav,RichardHolden.Vovmedeuum
conversadevitalidadenodiamaisnegrodaminhacarreirauniversitria.Euestavarealmentepensandoemdaromeu
aumgrauemCinciadaComputaopelaUniversidadedeOakland.Estehomemnuncaterminouoensino
caminho
escola,aindaumadasmaissbiaspessoasqueconhecinestavida.Senofosseporsua
perspectiva,podenoseronerddecomputadorqueeusouhoje.Porestadireoqueeusoueternamente
grato.
v

ListadeCaptulos
Introduo 1
Captulo1:ControlaroVFPAmbiente 3
Captulo2:FuneseProcedimentos 31
Captulo3:Design,Designerenadamais 55
Captulo4:ControlesBsicos 85
Captulo5:ComboseListas 127
Captulo6:Grids:OscontrolesMisunderstood 159
Captulo7:Trabalhandocomdados 197
Captulo8:OsdadosembuffereTransaes 239
Captulo9:Vistasemparticular,SQLemGeral 277
Captulo10:ClassesNonVisual 313
Captulo11:FormaseoutrasclassesVisual 363
Captulo12:Ferramentasdeprodutividadedodesenvolvedor 391
Captulo13:coisasdiversas 423
Captulo14:GerenciamentodeProjetos 461
Captulo15:ObjetosdoprojetoeProjectHooks 479
Captulo16:Criaoderelatrios 505
Captulo17:GerenciamentodeRelatrios 529

vi
v ii

ndice
Nossocontratocomvoc,leitor xix
Agradecimentos xxi
Sobrens xxiii
Comoparabaixarosarquivos xxv
Introduo 1
Oqueesteliv ro? 1
Umapalav rasobreocdigonesteliv ro 1
Ento,quemesteliv ro? 1
Oqueestnesteliv ro? 2
Oquenoestnesteliv ro? 2
Ondecomear? 2

Captulo1:ControlaroVFPAmbiente 3
IniciandoVisualFoxPro 3
Osarquiv osdeconfigurao 3
Comoespecificarumarquiv oconfig.fpw 4
ComoVFPlocalizaseuarquiv odeconfigurao 4
ComoVFPiniciasequandonenhumarquiv odeconfiguraoencontrado
4
Incluindoumarquiv odeconfiguraonoproj eto 4
Comosuprimirumarquiv odeconfigurao 5
Comodeterminarqualarquiv odeconfiguraoestsendousada 5
Oquev aiparaoarquiv odeconfigurao? 5
configuraesespeciais 5
ComandosSET 6
comandos 6
DandoVFPumcaminho 7
ComoVFPprocuraporarquiv os 7
Definindoodiretriopadro 7
UsandoocomandoSETPATH 8
Ondeestou? 9
Comodefinirumcaminhodeprogramao 9
CertificarsedeVFPiniciadoapenasumav ez 10
Usandoumarquiv o'semforo' 10
UsandoaAPIdoWindow s 11
CombinaodesemforoeWindow sAPI 12
SETComandoseDataSessions 13
Oqueexatamentesignifica"DefaultDataSession"significa? 13

v iii

Ento,eupossoterum"pblico"Datasession? 14
ComopossogarantircomandosSETaplicamseaumasessodedadospriv
14 ados?
AdicionandocdigoparaBeforeOpenTables() 15
Suprimindotabelasautoaberto 16
Criandoumaclassedeconfiguraodoambiente 16
Comofaoparameliv rardasbarrasdeferramentasdosistema? 18
Abarradeferramentasdosistema"Gotcha!" 18
PossofazerusodemacrosdetecladonaVFP? 19
Comopossoconstruirumamacromaiscomplexa? 19
Oqueum"SetMacro"? 20
QualadiferenaentreumamacroeumnaetiquetaKey? 21
Comofaoparacriarumatela"splash"? 22
Comopossoexecutarminhatelainicial? 22
Umaalternativ aparaatelainicial 23
Comow allpaperseudesktop 23
Ento,comopossoobterotamanhodareaatual_Screen? 24
Eurealmenteprecisoparacriartodosessesbitmaps? 24
Abarradeferramentas'pegadinha!' 25
Arrumarseuambientededesenv olv imento 25
FechandoVFPparabaixo 27
OqueumprocedimentodedesligamentoOn? 27
OquedesencadeiaumprocedimentodedesligamentoOn? 27
Oquev aiparaumprocedimentodedesligamentoOn? 28

Captulo2:FuneseProcedimentos 31
Comodev emosproceder? 31
Parmetros(umaparte) 32
Porreferncia,porv alor? 32
Comoeuseioquefoipassado? 33
Comodev oposicionarmeusparmetros? 33
Comopossodev olv erv aloresmltiplosdeumafuno? 33
Quetalusarparmetrosnomeados? 34
Passandoparmetrosopcionalmente 35
funesdedataehora 35
Tempogasto 35
Dataempalav ras 36
calculandoIdade 37
Quedataasegundaterafeira,emOutubrode2000? 37
Acriaodeumcronogramadepagamento 38
Quedatadedezdiasteisapartirdehoj e? 40
Gotcha!formatodedatarigorosaev istasparametrizadas 41
Trabalhandocomnmeros 41
Conv ertendonmerosparastrings 41
Gotcha!clculosqueenv olv emdinheiro 42
ix

funesdecadeia 42
Gotcha!concatenao 42
Conv ersoentrecadeiasedados 43
Outrasfunesteis 44
Comofaoparadeterminarseexisteumatag? 44
Comofaoparadeterminarseumastringcontmpelomenosumcaracterealfabtico?
45
Comoconv erternmerosparapalav ras 46
Comoextrairumitemespecificadoemumalista 49
Existeumamaneirasimplesdecriptografiadesenhas? 50
Ondev ocquerGOTO? 52

Captulo3:Design,Designerenadamais 55
Ento,porquetodooalaridosobreOOP,afinal? 55
Afinal,oquequetudoistoOOPj argosignifica? 56
Propriedade 56
Mtodo 56
Ev ento 57
mensagens 57
ClasseseObj etos 57
Herana 58
Composio 60
Agregao 60
Delegao 61
encapsulamento 61
Polimorfismo 61
hierarquias 62
obj etoprticodeprogramaoorientada(POOP) 62
Quandov ocdev edefinirumaclasse? 62
Ento,comov ocv aifazersobreacriaodeumaclasse? 63
Issotudosoamuitobom,masoqueissosignificanaprtica? 64
Comov ocv aifazersobreaconstruodesuasaulas? 66
Masserquetodoestematerialproj etorealmentefuncionanaprtica? 67
Comoqueoproj etorealmentetraduziremcdigo? 69
Trabalhandocomsuasclasses 73
Comofaoparaqueminhasaulasnabarradeferramentascontrolesdeformulrio?
73
Enquantoestamosnoassunto,comopossoidentificarminhasclassespersonalizadasnabarra
74
deferramentas?
Massemprequeeuquerobranconasminhasbitmapseleaparececinza! 75
ComopossofazerVisualFoxProusarminhasaulas,emv ezdeclassesdebase?
75
ComofaoparamudaralegendadortuloqueVFPacrescenta? 76
Paraqueeupossaobterumbrow separamostraronomedocampoquandoumalegenda
77
designdeinterfacedeusurio
definida? 78
Perceporegeaceitao 78
Mantenhaseususurioscentrou 80
Useocontrolecertoparaotrabalho 81

Captulo4:ControlesBsicos 85
Oquequeremosdizercom"base"? 85
Ascaixasdetexto 85
Textoclasseetiquetadacaixa 87
caixadetextoData 88
caixadetextodepesquisaincremental 89
caixadetextonumrica 92
Otempodemanipulao 101
Umacaixadetextoentradadetempo 102
Aclassecompostaentradadetempo 103
Ov erdadeirogiradortempo 107
piscandortulos 111
Acaixadeedioemexpanso 111
calendriodecombinao 118
botesdecomando 120
Gotcha!Programaodoscontroleslgicos 121
Pginasequadrosdapgina 122

Captulo5:ComboseListas 127
Combinaoelistabsicodacaixa 127
coleesdelistaeListItem 127
Quandoqueosev entosdefogo? 129
Comofaoparav incularminhascombinaoecaixasdelistagem? 131
Comofaoparaconsultarositensemmeuscombinaoecaixasdelistagem?
132
QualadiferenaentreDisplayValueev alor? 133
QualadiferenaentreRow SourceTypes"Alias"e"campos"? 134
Comopossofazermeuscombinaoecaixasdelistagemapontarparaumitememparticular?
135
combosQuickfill 135
Comofaoparaadicionarnov ositensaosmeuscombinaoecaixasdelistagem?
137
Comofiltrarositensexibidosemumasegundacaixadecombinaooulista
combasenaseleofeitanaprimeira? 139
Umapalav rasobretabelasdepesquisa 142
combosdepesquisagenricoselistas 143
Ento,oqueseeuquiserligaromeucomboparaumv alorquenoestnalista?
145
Comofaoparadesativ aritensindiv iduaisemumacombinaooulista? 150
Comofaoparacriarumacaixadelistagemcomcaixasdeseleo,comoaqueexibidapor
VisualFoxProquandoeuseleciono"Verbarrasdeferramentas"nomenu?151
Aclassedelistamov imentador 153
Eseeuprecisarexibircentenasdeitensnaminhacaixadecombinao?156
Captulo6:Grids:OscontrolesMisunderstood 159
Quandoqueosev entosdefogo? 159
Gotcha!incndiosv lidosdagradeantesdav alidadedocontroleatual160

XI

QualadiferenaentreActiv eRow eRelativ eRow ? 161


Activ eColumnrealmentenodizerlhequeacolunaativ a 162
Comofaoparadestacaralinhadegradeatual? 162
Mantendoumagradederolagemquandoasguiasdeusuriosforadaltimacoluna
164
Comofaoparacriarcabealhosdev riaslinhas? 165
Gotcha!ev entoroladanodisparaquandoasteclasdecursorrolaragrade
169
Usandoaferramentadetextodedicaemv ezdecabealhosdev riaslinhas
171
Comopossoalteraraordemdeexibiodagrade? 172
Comofaoparacontrolarocursor? 173
Comofaoparaexibiraltimapginainteiradeumagrade? 173
Comofaoparausarumagradeparaselecionarumaoumaislinhas? 175
Comopossodaraminhagradecapacidadedepesquisamultiselectincrementais?
176
ComofaoparausarDynamicCurrentControl? 178
Comofaoparafiltrarocontedodeumagrade? 180
Assimquesobregrelhasdeentradadedados? 182
Comofaoparaadicionarnov osregistrosminharede? 182
Comopossolidarcomv alidaodenv eldelinhanaminhagradedeentradadedados?
184
Comofaoparaexcluirregistrosemminhagradedeentradadedados?187
Comofaoparaadicionarumacaixadecombinaominhagrade? 190
Concluso 195

Captulo7:Trabalhandocomdados 197
TabelasnoVisualFoxPro
algunsprincpios 197
197
Comoabriratabelaespecficaquedesej ausar 197
Comoparaobteraestruturadeumatabela 199
Comoparacompararasestruturasdeduastabelas? 200
Comoparatestarquantopresenadeumcampodeumatabela 202
Comov erificarseatabelaestsendousadoporoutrousurio 204
Oqueexatamenteumcursor? 206
ndicesemVisualFoxPro 208
Tiposdendices 209
Comoobterinformaessobreumndice 209
Comoparatestaraexistnciadeumamarcadendice 210
Usandocandidato(eprincipal)Teclas 211
Oqueuma"chav esubstituta"? 211
Gerenciamentodechav esintroduzidospeloutilizador 215
Ousodendicescommesasencadernados 217
Comotiposdedadosmistosndiceaocriarumachav ecomposta 218
Comoindexarumatabelatamponada 218
Trabalhandocomocontinerbancodedados 220
Usandonomesdetabelalongos 220
Usandonomesdecampolongosno!!! 221
Usandorecipientesdebancodedados 222

xii

Comov alidarumrecipientedebancodedados 223


Comoembalarumcontinerbancodedados 223
Mov erumcontinerbancodedados 224
Mudaronomedeumrecipientedebancodedados 226
GerenciandoaintegridadereferencialnoVisualFoxPro 227
LimitaesdoCdigoRIgerado 228
Usandochav escompostasemrelacionamentos 229
OquesobreoutrasopesdeRI? 231
UsandodisparadoreseregrasnoVisualFoxPro 231
Ento,qualadiferenaprticaentreum'gatilho'euma'regra'? 232
Porque,aoadicionarumdisparadorparaumatabela,noVFP,porv ezes,rej
232 eitla?
Possodesativ artemporariamenteumgatilhoougov ernarento? 233
Comofaopararealmentecriarmeusprocedimentosdegatilhoedaregra?
234
Comofaoparaadicionarumdisparadorparaumatabela? 235
Ento,quandoeudev eriausarumgatilho? 235
Equandodev ousarumaregra? 237
Dev eumdisparadorouregrasempresereferemaumanicafuno? 238
Captulo8:OsdadosembuffereTransaes 239
Usandoobufferdedados 239
Ondeestamosv indo? 239
Oquequeremosdizercom'buffer'dequalquermaneira? 239
Oquesignificatudoissoaocriarformasdeligaodedados? 241
Ento,comofaoparaconfigurarobufferemumformulrio? 244
Ento,omododebuffereudev eriausaremmeusformulrios? 245
Alteraromododebufferdeumatabela 246
IsChanged()umaoutrafunoqueFoxProesqueceu? 246
UsandoTableUpdate()eTableRev ert() 249
Gerenciamentodoescopodasalteraes 249
segundoparmetroTableUpdate()'s(fora) 250
Especificandoatabelaaseratualizadaourev ertido 251
Concluso 251
Comopossolidarcom'salv ar'e'desfazer'funcionalidadegenericamente?252
Oproj etodaclassedeformulrio 253
Usandoanov aclassedeformulrio 255
Detecoeresoluodeconflitos 256
OpapeldeOLDVAL()eCURVAL() 257
Ento,comopossorealmentedetectarconflitos? 258
OK,ento,tendodetectadoumconflitodeatualizao,oquepossofazersobreisso?
261
resoluodeconflitossoabememteoria,comofuncionanaprtica? 262
usandotransaes 269
Quandoeuprecisodeumatransao? 269
Qualoefeitoquearev ersoteremmeusdados? 270
ComoqueumimpactotransaoemmecanismosdebloqueiodoFoxPro?
271

xiii

Possousarv riastransaesaomesmotempo? 272


Algumascoisasaprestaratenoparaquandoseutilizaamemriaintermdiaemaplicaes
274
Nopossv elusarOLDVAL()pararev erterumcamposobobufferdetabela
274
Gotcha!bufferdelinhaecomandosquemov eroponteirodoregistro 275
Captulo9:Vistasemparticular,SQLemGeral 277
Asv isualizaesdoVisualFoxPro 277
Oqueexatamenteumav iso? 277
Comofaoparacriarumpontodev ista? 278
Quandodev ousarv ista,emv ezdeumatabela? 279
Espere!Oqueumav istacomparmetros? 280
Comofaoparacontrolarocontedodeumpontodev istaquandoeleaberto?
283
Porqueasalteraesfeitasemumpontodev istanoentrarnatabelasubj
284 acente?
Porquecriarumav istaquesimplesmenteumacpiadeumatabelaexistente?
285
Qualamelhormaneiradeindexarumpontodev ista? 288
Maissobreousodepontosdev ista 289
SQLnoVisualFoxPro 294
associaodetabelas 295
ConstruodeconsultasSQL 296
Comov erificarosresultadosdeumaconsulta 297
ComoestenderumcursorSQLgerado 299
Comov erificaraotimizaodasuaconsulta 306
Qualmelhorparaatualizartabelas,SQLoucomandosnativ osFoxPro? 311
Concluso 311
Captulo10:ClassesNonVisual 313
Comopossofazerusodearquiv osINI? 313
Visogeral 313
Inicializarogerente 314
Oarquiv opadro 314
registrodearquiv o 316
Ainterfacepblica 316
Utilizandoogerenciadordearquiv osINI 320
Comoselecionarumareadetrabalhodiferente,estiloOOP! 322
Visogeral 322
Umapalav rasobreacriaodoobj etoselector 323
Comoaclasseselectorconstrudo 323
Usandoaclasseselector 325
ComopossogerircaminhosnaDataEnv ironmentdeumformulrio? 327
Aclassegerentedecaminhodedados 328
Atabeladegerenciamentodecaminhos 329
Aclassedegerenciamentodecaminhos 330
Utilizandoogerenciadordecaminhodedados 333
xiv

Comopossogerenciarformulriosebarrasdeferramentasnomeuaplicativ
335o?
Aclassedeformulriogerenciado 335
Aclassebarradeferramentasgesto 338
Aclassegerentedeformulrio 339
Utilizandoogerenciadordeforma 350
Comopossocontrolaremanipularerros? 352
ClassificandoerrosVisualFoxPro 353
errosderegistro 354
Comopossosimplificaraobtenodemensagensparameususurios? 357
Atabelademensagempadro 357
Aclassedeprocessamentodemensagens 358
Usandoomanipuladordemensagem 361
Concluso 362

Captulo11:FormaseoutrasclassesVisual 363
Comopossofazerformasdepreencheratela,independentementedaresoluodatela?
363
Comopossocriarformulriosredimensionv eis? 366
Comofaoparaprocurarporregistrosespecficos? 370
ComofaoparaconstruirSQLnamosca? 374
Comopossosimularaj aneladecomandonomeuexecutv el? 377
WrappersparafunescomunsdoVisualFoxPro 379
aulasdeapresentao 381
classedepesquisacdigopostal 381
logingenricoforma 385
Aclassecaixadetextodepesquisa 387
Concluso 389

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
391
Form/editordebibliotecadeclasses 391
UsandooeditorSCX/VCX 392
InspectorForm 393
Apginadeinformaesdatabela 394
Apginadeinformaesdoformulrio 394
Apginalistadeobj etos 396
Construodoformulriodeinspeco 397
Nossoconstrutordegradedeforaindustrial 403
Redimensionarcolunasdegradecorretamente 405
Mudaronomedecolunaseseuscontrolesdeformaadequada 406
Controlaapginapersonalizadadoconstrutordegrade 407
Adicionandocdigomtodoparacolunasdegrade 408
classecatalogador 409
OquefazVCXList 410

xv

Umw rapperpara"modificarclass' 410


A/utilitriodocumentaodabibliotecaclassedeformulrio 412
Share.prgumnav egadordeclasseaddin 415
Umlocalizadordekinder 416
Concluso 421

Captulo13:coisasdiversas 423
UsandoodepuradordoVisualFoxPro 423
Caractersticasdasj anelasdodepurador 423
Configurandoodepurador 425
Definirpontosdeinterrupo 426
expressesdepontodeinterrupoteis 428
Escrev ercdigoparafacilitaradepuraoemanuteno 430
TrabalhandocomDataSessions 433
ComopossopartilharDataSessionsentreasformas? 433
ComofaoparamudarDataSessions? 434
ComofaoparaobterumalistadetodosDataSessionsativ os? 435
Itensv ariados 435
Qualasequnciadeev entosquandoumformulrioinstanciadooudestrudos?
435
Comofaoparaobterumarefernciaaoformulriopaideumformulrio?
437
Comofaoparaobterumalistadetodososobj etosemumformulrio? 437
Comopossodefinirofocoparaoprimeirocontrolenaordemdetabulao?
441
Comofaoparadev olv erumv alorapartirdeumformulriomodal? 441
Comofaoparaalteraroponteirodomouse,enquantoumprocessoestsendoexecutado?
443
Comopossocriarumapropriedade"global"paraaminhaaplicao? 445
Comoposso'procurar'umarray? 445
ChamadasAPIdoWindow s 447
Comofaoparaencontraroarquiv oassociadoaumtipodearquiv o? 447
Comopossoabrirumarquiv ousandoassociaesdearquiv osdoWindow449 s?
ComopossoobteronomedelogindoWindow sdousurio? 450
Comopossoobterinformaesdedirectrio? 450
Comopossoobteronmerodecoresdisponv eis? 452
Comofaoparaobterosv aloresparaasconfiguraesdecoresdoWindow
453 s?
Comofaoparamudarocursor? 454
Comopossopersonalizarmeusbips? 455
Comofaoparadescobrirseumaaplicaoespecficaestfuncionando?456
UsandoocomandoDECLARE 458

xv i

Captulo14:GerenciamentodeProjetos 461
Oqueacontecequandoaconstruodeumexecutv el? 461
Comoutilizarasopesdeproj etoparaasuav antagem 462
Comov ocusaaconfiguraodeinformaesdedepuraodeumproj eto?
462
Comov ocusaaconfiguraocriptografadodeumproj eto? 463
Comov ocdefinirumconepersonalizadoparaumexecutv el? 463
Comov ocgerenciararquiv osnoProj ectManager? 464
Comov ocadministraServ idoresdoGerentedeProj etos? 464
Comov ocdefinirdescriodoobj etodoproj eto? 464
Comoconfigurarasinformaesdav ersoexecutv el 465
Quaissoasv antagensdeincluiroConfig.fpw noproj eto? 467
Comopodemosincluirobj etosnoVFPnoproj eto? 468
ComoreduziratelaimobiliriotomadapeloGerentedeProj eto 470
ComoarrancarguiasdoGerentedeProj eto 471
existemQueproblemasaoabrirumbancodedadosnoproj eto? 472
arrastamentoproj etoetruquesquedeixamcair 473
Oqueacontecequandoarrastaapartirdeumproj etoparaoutro? 473
Comopossoarrastarobj etosdeumproj etoparaumdesigner? 473
Oqueacontecequandoarrastandodeproj etoparaprogramarcdigo? 474
Oqueacontecequandoarrastardenav egadordeclasseoucomponente
Galeriaparaumproj eto? 474
OqueacontecequandoarrastardeumVFPnoaplicaodeumproj eto?
475
Comotomarv antagemdeocampodoutilizadorproj ecto 475
Comoprocederparadocumentaroarquiv odeproj eto 476
Concluso 477

Captulo15:ObjetosdoprojetoeProjectHooks 479
ComousarProj ectHooksparapegarumpeixegrande 479
ComoconfigurarumProj ectHookglobalparatodososproj ectos 481
OqueacontecequandoumProj ectHookperdidoouexcludo? 481
OqueaMicrosoftdeixardeforadaprimeirav ersodoProj ectHooks? 482
Comoacessarinformaesnoproj etoeobj etodeArquiv os 483
Comousarobj etosdeproj etoemdesenv olv imento 483
ComoconstruirumAssistentedeaplicaobsica 484
Proj ectHookeProj ecttruquesObj eto 488
ComoaumentarabasedeProj ectHook 488
ComocriarumProj ectHookdesenv olv imentotil 489
ComoteroProj ectHookdefinirodiretrioatualecaminho 492
ComocontrolarprogramaticamenteasdefiniesVFPIntellidrop 484
Comoremov erasinformaesdaimpressoraapartirderelatriosVFP496
ComocontrolaroquefeitodentrodoGerentedeProj eto 499
Comogerarcpiasdeseguranaautomticasdemetadados 500

xv ii

RASProj ectBuilder 502


Concluso 504

Captulo16:Criaoderelatrios 505
Regrarelatrio#1 506
tcnicasdeformatao 506
Comoav elocidadedeimpressocomfontesdeimpressora 506
Comoparageraroefeitode"greenbar" 507
Comogerarcaixasdeseleoemrelatrios 508
Comoreduzir/aumentaroespaoembrancoaoimprimircamposdememorando
510
Comoexibirumcamponav isualizao,masdemodonoimprimir 511
Comominimizaradorusandolinhasecaixas 511
Comousaroflutuadorparaasuav antagem 512
Comoimprimirsmbolosdebalacomcamposesticv eis 512
Comoconstruirumendereodecorrespondnciasemlacunas 513
ComousarlegendasdecampoDBCemrelatrios 514
problemasdabanda 515
Comoev itarcabealhoserodapsrfsv iv as 515
ComotersegundasbandasderesumocomEOF() 516
Comocriarquebrasdecontroleflexv eis 517
Comoconstruirduas(oumais)conj untosdelinhasdedetalhe 518
Comosimularumalinhadedetalhemaisdeumapgina 520
Comocorrigiralocalizaoderodap 521
Comoimprimir"Continuao"quandodetalheov erflow s 522
Outrastcnicasderelatrio 523
Comoev itarproblemascomaimpressoracodificados 523
UsandoConstrutordeexpressesparaoscamposindefinidosnoDataEnv
524ironment
Comoobterosformatosdeetiquetasparaestardisponv el 525
RelatrioMetadadosManipulao 526
Comov ocalterarfontesdeprogramao? 526
Comoconv erterformatosdepapel(Letter>A4paraimpresso) 527
xv iii

Concluso 528
Captulo17:GerenciamentodeRelatrios 529
Comoaprov eitarrelatrioseDataSessions 529
Comocriarummodeloderelatrioparaumproj eto 530
Comoimprimiruminterv alodepginas 531
Comoimprimir"Pginaxdey'emumrelatrio 531
Comopermitirqueosusuriosparaselecionaronmerodecpias 532
Comoencontrara"Variv elnoencontrado"errosemumrelatrio 533
Comoev itarterumrelatriodesativ aromenudosistema 534
Comoagruparpginasderelatriosdiferentes 534
Comoexibirumcostume'j aneladeimpresso' 536
Comoalterarottulodaj anelaVisualizaodeImpresso 538
Comomostrarumav isualizaoderelatriocomoumformulriodenv elsuperior
539
Comoprv isualizarv riosrelatriosdeumasv ez 540
Comoremov erinformaessobreaimpressora.emrelatriosdeproduo 5 42
Comopermitirqueosusuriosfinaisparamodificarlayoutsderelatrio 543
ComoimprimirumcampomemorandocomformatoRichText 545
Comoselecionarabandej adepapel 547
Outrasalternativ asaoRelatrionativ aDesigner 548
ComousarautomaoOLEparaoWord 548
Comosadaparaoutrostiposdearquiv o 550
ComocriarsadaHTMLetextoASCII 551
ComogerarsadaPDF 553
Comorev isarocdigoapartirdorelatriodedesigner/label 555
Concluso 557

xix

Onossocontratocomvoc,
Oleitor
Emquens,ospovosquecompemHentzenwerkePublishing,descreveroquevoc,o
leitor,podeesperardestelivroedens.

Ol!
Eutenhoescritoprofissionalmente(emoutraspalavras,acabourecebendoumsalrioparaomeu
rabiscos)desde1974eescrevesobredesenvolvimentodesoftwaredesde1992.Comoautor,eutenho
trabalhoucomumameiadziadeeditorasdiferentesesecorrespondeucommilharesdeleitoresmais
osanos.Comoumdesenvolvedordesoftwareetodaatot,eutambmadquiriuumabibliotecademaisdeum
centenadecomputadorelivrosrelacionadoscomsoftware.
Assim,quandoeuvestiuobondopublisherhquatroanosparaproduzira1997Developer
Guiar,eutinhaalgumasidiasmuitoboasdequeeugostava(enogostava)deeditores,oque
leitoresgostavaenogostavaequeeu,comoleitor,gostouenogostou.
Agora,comosnossosnovosttulosparaaprimaveraeoverode2000,estamosentrandoemnossoterceiro
estao.(Paraaquelesquemanterocontrole,o'97DevGuidefoianossaprimeira,emboraabreviada,estao
eolotedeseis"Essentials"paraVisualFoxPro6.0em1999foiasegunda).
JohnWooden,ofamosoUCLAtreinadordebasquete,haviapostuladoqueasequipesnosoconsistentes
Elesestosempreficandomelhoroupior.Nsgostaramosdeficarmelhor...Umdosmeusobjetivosparaeste
temporadaconstruirumrelacionamentomaisprximocomvoc,leitor.
Afimdefazerisso,voctemquesaberoquevocdeveesperardens.

Voctemodireitodeesperarqueoseupedidoserprocessadorapidamenteecorretamente
equeseulivrovaiserentregueavocemestadonovo.
Voctemodireitodeesperarqueocontedodoseulivrotecnicamenteprecisa,at
atdata,queasexplicaessoclarasequeolayoutfcildelereseguir
semummontedebuoouabsurdo.
Voctemodireitodeesperarqueoacessoaocdigofonte,errata,FAQseoutros
informaoquerelevanteparaolivroatravsdonossowebsite.
Voctemodireitodeesperarumaversoelectrnicadoseulivroimpresso(emcompilado
FormatoHTMLHelp)paraestardisponvelatravsdonossowebsite.
Voctemodireitodeesperarque,sevocreportarerrosparans,seurelatrioser
respondeuprontamenteequeoavisoadequadoserincludonaerrata
e/ouFAQsparaolivro.

Naturalmente,existemalgunslimitesquenscolisocontra.Hhumanosenvolvidose
elescometemerros.Umlivrode500pginascontm,emmdia,150.000palavrasevrios
megabytesdecdigofonte.Nopossveleditarereeditarvriasvezesparapegartodososltimos
erroortogrficoeerrodedigitao,nempossveltestarocdigofonteemcadapermutaode
ambientededesenvolvimentoesistemaoperacionaleaindaopreodolivroacessvel.

xx

Depoisdeimpressas,asligaesquebrar,tintaficamanchada,assinaturasseperdeudurantealigao.Em
oladodeentrega,sitesirparabaixo,pacotesdeseperdernocorreio.
Noentanto,nsvamosfazeronossomelhoresforoparacorrigiressesproblemasumavezquevocdeixenossaber
sobreeles.
E,assim,emtroca,quandovoctemumaperguntaoucorreremumproblema,pedimosquevocprimeiro
consultaraerratae/ouFAQsparaoseulivroemnossosite.Sevocnoencontrararesposta
l,envieumemailparabooks@hentzenwerke.comcomtantainformaoedetalhes,
incluindo(1)ospassosparareproduziroproblema,(2)oqueaconteceue(3)oquevocesperava
aacontecer,juntamentecom(4)quaisqueroutrasinformaesrelevantes.
Eugostariadesalientarqueprecisamosdevocparacomunicarquesteseproblemasdeformaclara.Para
exemplo

"Osseusdownloadsnofuncionam"noinformaosuficienteparansparaajudlo."Eureceboum404
deerroquandoeuclicarnodownloaddocdigofontelink
www.hentzenwerke.com/book/downloads.html".algoquepodeajudlo.
"Ocdigonocaptulo14causouumerro"denovonoinformaosuficiente."Eurealizadoo
etapasaseguirparaexecutaroprogramadecdigofonteDisplayTest.PRGnocaptulo14e
receberumerroquedizia"m.liCounterVarivel"noencontrado"algoquepodeajudar
voccom.

Nsvamosfazeronossomelhorparavoltarparavocdentrodeumpardediasoucomumaresposta,oupelo
menosumreconhecimentoquerecebemossuaperguntaequensestamostrabalhandonisso.
Emnomedosautores,editorestcnicos,editoresdetexto,artistasdelayout,artistasgrficos,
indexadoresetodasasoutraspessoasquetrabalharamparacolocarestelivroemsuasmos,eugostariade
obrigadoporadquirirestelivroeesperoqueeleirprovarserumaadiovaliosaparaoseu
bibliotecatcnica.Porfavor,deixenossaberoquevocpensasobreestelivronsestamosolhandoparaafrentea
ouvindodevoc.
ComoGrouchoMarxcertavezobservou,"Foradeumco,umlivroomelhoramigodeumhomem.Dentro
deumco,demasiadoescuroparaler."
whilHentzen
HentzenwerkePublishing
Maiode2000

xxi

Agradecimentos
Sefssemostentarreconhecer,individualmente,todosaquelesquetinhamcontribudo,ainda
indiretamente,aestelivro,teramosumalistadeagradecimentosmaisdoqueolivro
si.Mashalgunscujascontribuiestmsidotosignificativoquedevemos
reconhecemespecificamente.

Emprimeirolugar,gostaramosdereconheceranossaEditorTcnico,JohnHosier.SemJohnolivrofaria
nuncaestiveramemtoboaforma.Noselecorrigirnosquandoestvamoserrados,masoseu
sugestesemelhoriasforaminestimveisparatodosns.Otrabalhodeeditortcnico,em
muitasmaneiras,maisdifcildoquerealmenteescrever(eaindamaisingrata),maseleconseguiuisso
maravilhosamentemuitoobrigado,John.
Emseguida,claro,vemonossoamigoeeditorgalante,WhilHentzen.Elefoio
inspiraoportrsdestelivro,(emboransaindanotemcertezadequeoqueeleconseguiufoioqueele
originalmentequeria)eseuapoioeassistnciatemsidoinestimvel.Graastambmsodevidosa
todaaequipedaHentzenwerkeparatirarnossosrabiscosaleatriosecriarestemaravilhoso
reservarapartirdeles.Nsrealmenteapreciamosisso.
Agora,temosdeenfrentarogrupomaisdifcil,aComunidadeFoxPro.Nsconsideramos
nosmuitofelizporsermembros,pormaishumilde,destemaravilhoso,multinacional,
comunidade.Semvoc,estelivronopoderiatersidoescritoecertamentenunca
tervendidoumanicacpia.
AComunidadeFoxProrealmenteumacomunidadeesustentasefisicamenteatravsda
muitosgruposdeusuriosbaseadosemFoxemtodasaspartesdomundo,porviaelectrnicaatravsdaCompuServe
Fruns,GruposdeNotcias,UniversalThread,FoxForum,oWikieassimpordiante.acamaradagem
eapoiomtuo,acreditamos,incomparveleLongmaioquecontinueaserassim.colocarrostos
anomessemprefoipartedadiversodeassistirDevCon,WhilFest,socal,Frankfurt,
Amesterdo,ouqualquerumadasmuitasoutrasconfernciasFoxProereuniesemtodoomundo.que
muitosdesses"caras"tambmsetornaramamigosumbnusmaravilhosoeestamosansiosos
pararenovarvelhasamizadeseforjarnovosaolongodosanosvindouros.
Emborasejaverdadequetodosnacomunidadetemcontribudo,dealgumaforma,comestelivro,
halgumaspessoascujacontribuiotemsidomuitodiretoemuitoespecficoens
queroaproveitarestaoportunidadeparaagradecerpublicamente.

StevenPreto(porqueo"Share"eutilitrios"MC")
GaryDeWitt(paramineraoasconstantesAPIdoWindows)
TamarGranoreTedRoche(paraoindispensvel"GuiadoHackerparaVisual
FoxPro6.0")
DougHenning(paracompartilharseutrabalhocomosFoxProBuildersvisuais)
ChristofLange(porseumtododefazerumaaplicaoFoxPro"nicainstncia")
JohnPetersen(porsuacontribuiodeOptUtility)

Porltimo,masnomenosimportante,vemapessoamaisimportanteparansautores,voc,nosso
Leitor.Obrigadoporcomprarolivro.Esperamosquetantolheagradaetilparavoc.
xxii

Talvez,seestamossempreloucoosuficienteparalidarcomooutro,vocvailembrarnosedarnosumolhar
emseguida,tambm.

AndyKramek
MarciaAkins
RickSchummer

fev2000

xxiii

Sobrens
AndyKramek
AndyumconsultorindependenteedelongadatadesenvolvedorFoxProbase,nomomentoda
escrita,naInglaterra.BemcomosendoumMicrosoftMostValuableProfessional,eletambm
MicrosoftCertifiedProfessionalparaoVisualFoxProemambasDesktopeDistribuda
aplicaes.AndyummembrodelongadatadosfrunsdesuporteFoxPronoCompuServe,
ondeeletambmumSysOp.
trabalhopublicadodeAndyinclui"OGuiaRevolucionriaparaVisualFoxProOOP"(Wrox
Press,1996)e,juntamentecomseuamigoecolegaPaulMaskens,omensal"Kitbox"
colunanaFoxTalk(PinnaclePublicaes).Andytemfaladoemconfernciasegruposdeusurios
reuniesnaInglaterra,EuropacontinentalenosEUA.
Nopoucotempolivrequetem,Andygostadejogarsquashegolfe(emborano
necessariamenteaomesmotempo),viajareouvirMarcia.
VocpodechegarAndyem:
AndyKr@Compuserve.com

MarciaAkins

Marciaumdesenvolvedorexperienteemvriaslnguas,quetemtrabalhadoprincipalmenteem
VisualFoxProduranteosltimosoitoanos.Elaumconsultorindependentee,nomomentoda
escrita,aabandonaraOhionativodeviveretrabalhar(comAndy)porumanoouassimnaInglaterra.
ElaumMicrosoftMostValuableProfessional,edetmMicrosoftCertifiedProfessional
qualificaesparaoVisualFoxProDesktopeaplicativosdistribudos.
ElatemvriosartigosemFoxProAdvisoraseucrditoeamplamente,epelomenosmeia
srio,conhecidacomoa"Rainha'o'oGrids".Elatemfaladoemconfernciasegruposdeusurios
reuniesnosEUA,InglaterraeEuropacontinentaleumcolaboradorfreqente
CompuServe,aUniversalThreadeFoxForum.com.
Quandoelanoumsoftwarededesenvolvimentoocupado,Marciagostadegolfe,esqui,jogartnis,
trabalhandonoginsio,viajareassdioAndy.
VocpodechegarMarciaem:
MarciaGAkins@Compuserve.com

RickSchummer

RickoDiretordeDesenvolvimentodeKirtlandAssociates,Inc.emTroyMI,EUA.Kirtland
Associatesescreveaplicaesdebancodedadospersonalizadosparaumabasedeclientesemrpidaexpanso.Eleno
sdirigeodesenvolvimentodestaorganizaodivertido,mastambmparticipanaeducaodos
novoseexperientesdesenvolvedoresVisualFoxPro.umatimamaneiradepromoversuasprpriashabilidades.
Depoisdehoras,elegozadeferramentasdeescritadesenvolvedorquemelhoramaprodutividadedesuaequipee
ocasionalmente,canetasartigosparaFoxTalk,FoxProAdvisor,evriosboletinsdegruposdeusurios.

xxiv

RicktornouserecentementeumMicrosoftCertifiedProfessional,passandotantoareadeTrabalhoVFP
eexamesDistribuda.
Elepassaseutempolivrecomsuafamlia,alegraascrianascomoelesjogamfutebol,temum
papelvoluntriocomosescoteiros,eadoragastosvezcamping,ciclismo,coletademoeda,
fotografareleitura.RickummembrofundadoresecretriodetantoareadeDetroit
FoxUserGroup(DAFUGhttp://www.dafug.org)eSterlingHeightsComputerClub
(Http://member.apcug.org/shcc).
VocpodechegarRickem:
rschummer@compuserve.com
ras@kirtlandsys.com
http://my.voyager.net/rschummer

JohnHosier

JohntemsidoativonacomunidadeFoxProdesde1987etemsidoumdesenvolvedor,
consultor,autor,conferencistaeinstrutor.Johneratambmummembrodoconselhofundadorda
oGrupoedeUsurioMidAtlanticFoxProtemservidocomoseupresidenteetesoureiro.Comoum
consultor,JohntrabalhoucomambososclientesgrandesepequenosnaEuropaOcidentaleOriental,
oMdioOriente,CarabaseemtodoosEstadosUnidos.crditosdepublicaodeJohnincluem
FoxProAdvisor,FoxTalk,JornaldousuriodoFoxProeumarevistaalemchamada"Basededados:
DasFachmagazinfrDatenbankentwickler".No,Joonofalaalemo,maseleachaque
muitoengraadoqueeleescreveuumartigoquefoilidoincapazesnapublicaofinal.Comoum
MicrosoftCertifiedProfessionalemVisualFoxPro,Johntrabalhouemumagrandevariedadede
projetos,incluindoclienteservidor,internet/intranet(incluindoumanalisadorXMLescritoemVFP)e
aplicaesdistribudas.JohnatualmentefazsuacasanareadeChicago.
VocpodechegarJohnem:
JHosier@earthlink.net

xxv

Comoparabaixarosarquivos
Hdoisconjuntosdearquivosqueacompanhamestelivro.Oprimeiroocdigodefonte
aolongodotexto,eobservoupeloconeteiadearanhaosegundooe
versodolivrodestelivrooarquivocompiladoHTMLHelp(CHM).Aquiestcomoobtlos.

TantoocdigofonteeoarquivoCHMestodisponveisparadownloadnoHentzenwerke
site.Afimdefazerisso,seguindoestasinstrues:

1.AponteseunavegadordaWebparawww.hentzenwerke.com.

2.Procureolinkquediz"DownloaddoCdigo&.CHMFontearquivos".(Otextoparaestaligao
podemmudaraolongodotemposeissoacontecer,procureumlinkquefazrefernciaalivrosouDownloads).

3.Umapginaquedescreveoprocessodedownloadiraparecer.Estapginatemduassees.

Seo1:Sevocfosseemitidoumnomedeusurio/senhadeHentzenwerkepublicao,vocpode
inserilosemdestapgina.

Seo2:Sevocnorecebeuumnomedeusurio/senhadeHentzenwerkePublishing,no
preocupao!Bastadigitaroseuapelidodeemaileolharparaaperguntasobreoseulivro.Notequevoc
precisodoseulivroquandovocresponderapergunta.

4.Umapginaquelistaoslinksparaosdownloadsadequadosaparecer.

ObservequeoarquivoCHMcobertopelasmesmasleisdedireitosautoraiscomoolivroimpresso.
Reproduoe/oudistribuiodoarquivoCHMcontraalei.

Sevoctiverdvidasouproblemas,amaneiramaisrpidadeobterumarespostaemailpara
books@hentzenwerke.com.
xxv i
Introduo 1

Introduo
Obrigadoporcomprarestelivro.Esperamosquevocsedivirtatantollocomofizemos
aoescrevloequevocconsegueencontrartantascoisasteis,comofizemosduranteacompilao
isto.Osobjetivosportrsdestelivropassoupormudanasconsiderveisentreasuacriao
(Na"ConfernciaparaoMax"DutchUserGrouprealizadaemArnhem,Holanda,emMaiode1999)
eaversodotextoqueagoratememsuasmos.Noentanto,ospargrafos
abaixodescrevemoquefinalmenteesperavamalcanarcomolivro.

Oqueestelivro?
Emprimeirolugar,hquereferirqueestenoumlivroquevaiteensinarcomousaroVisualFoxPro.Nosso
objectivoprincipaltemsidotentaredestilaralgumasdasexperincias(muitasvezesdolorosas)que,
emuitosoutros,tmacumuladoaolongodosanos,demodoquevocpodeevitarcairnamesma
armadilhasquefizemosetalvezatmesmoencontraralgumasmaneirasalternativasdefazerascoisas.Issonoquerdizer
quehsempreum"melhor"oumesmoum"direitomaneira"defazerascoisasemFoxPro.Alinguagemto
ricosepoderososquenormalmenteexistemvriasformasdecombaterqualquerproblema,noentanto,
tambmhmuitasarmadilhasparaosincautostcnicas,emuitosquetmsemostradotil.o
problemaquetemostentadoresolvercoletaressestruquesearmadilhasjuntos,agruplos
emalgumaordemlgicaetentarforneceranicacoisaquequasetododesenvolvedorque
sabevempedindocdigoconcisoeexemplo"relevante".

Umapalavrasobreocdigonestelivro
Osexemplosdecdigodestelivroforamconscientementeescritoparatornlosfceisdeseguirpelo
vezesissosignificaquetemosprescindidoalgumasotimizaesbvias.Assim,vocvaiencontrar
muitoslugaresondevocpodedizer'Porqueelesnofazloassim?Teriasalvouumadzia
linhasdecdigo!'Tenhanos,elembresequenemtodomundotoperspicazquantovoc.
Voctambmvainotarque,porrazessemelhantes,notemosrepetido,emcadatrechodecdigo,
mtodooufuno,ostestes"padro"etratamentodeerrosdecdigoquevocfarianormalmente
esperaencontrar(comoaverificaodotipodeparmetrospassadosparaumafuno).Nsassumimos
quevocsabecomofazerissoe,sevocquiserusarocdigodestelivro,iradicionlo
se,semprequenecessrio.

Ento,quemestelivro?
Comojdisse,estelivronovaiteensinarausaroVisualFoxProeleassumequevoc
temumgraurazoveldeconfortocomofuncionamentobsicodobancodedadosVFPe
CommandLanguageecomosprincpiosbsicosdeProgramaoOrientadaaObjetos.Gostaramos
EsperamosquevoctenhalidoeusadotaisrefernciasexcelenteseteiscomoWhilHentzende
'ProgramaoVFP,''OGuiaRevolucionriaparaVFPOOP'porWillPhelps,AndyKramek
eBobGrommese,claro,aindispensvelGuiadoHackerparaVFP,"porTamarGranor
eTedRoche.
Sevocestprocurandomaneirasalternativasdelidarcomosproblemas,sugestesdemelhoriadecdigo,
soluesalternativasparaarmadilhascomunse"histriasdeguerra"daquelesqueforamlefezisso(sim,
temosatoteeshirts),entoestelivroparavoc.

2 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Oqueestnestelivro?
EstelivroincluiexperimentadasetestadassoluesparaproblemascomunsnoVisualFoxProemconjunto
comalgumastcnicasbsicasparaaconstruodeferramentasecomponentesdoVisualFoxPro.Olivro
organizadoemcaptulosquetentamsujeitosdogruponasposieslgicas.cadacaptulo
consiste,essencialmente,deumasriede"HowDoI...?questes.Cadaperguntaincluiumtrabalho
exemplo,ecdigodeexemplodecadacaptulopodemserbaixadasindividualmente.
TodoocdigoexemplofoiescritoetestadousandooVisualFoxProVerso6.0(comService
Pack3).EmboramuitodoquedeveserexecutadoemqualquerversodoVisualFoxPro,h,obviamente,
algumascoisasquesoversoespecfica.(CadanovaversodoVisualFoxProintroduziualguns
inteiramentenovoscomandosefunesparaoidioma.)

Oquenoestnestelivro?
Umaenormequantidade!Afimdemanterestelivroparaumtamanhogerenciveltemosdeixadodeforaummontedecoisas.
Umavezqueesteessencialmenteumlivro'HowTo'paraVisualFoxPro,notemossequertentou
cobrirtpicostaiscomocomponentesdeconstruoCOM,oupginasdaInternet(existemexcelentes
livrossobreessestemasdisponveis).NemtemoscobertocontrolesActiveXouAutomao
(Outrolivroserianecessrioparaestetpicosozinho).Reconhecemosqueexistemsignificativas
omisses,massentiuqueumavezquenopoderiacobrirtudo,devemosnosconcentrarem
asquestesFoxPro'puros'Visuaisenofazemosqualquerpedidodedesculpasporfazlo.

Ondecomear?
Arespostacurtaondequerquevocquer!Emboratenhasidoumadasnossasprincipaispreocupaesparafazer
istouma"leitura"dolivro,reconhecemosqueprovavelmentevocestolhandoparaestelivroporquevoc
temumproblemaespecfico(outalvezmaisdeum)paralidarcomeestoprocuradeinspirao
Senoumasoluoreal.Nopodemosesperarparafornecer"solues"paratodos,massepudermos
oferecerlheumpoucodeinspirao,apoiadosporcdigodeexemploparavoccomear,entoteremos
conseguidonossosobjetivosevocpoderelaxarsabendoqueseugastomodestosobre
estetomojprovouseruminvestimentorentvel.

Captulo1:ControlaroVFPAmbiente 3

Captulo1
ControlandooVFP
MeioAmbiente
"Paracomearnoincio"(Narrador,"UnderMilkWood",deDylanThomas)

UmdosprincipaisbenefciosdodesenvolvimentonoVisualFoxProquevoctemquase
controlecompletosobreoambienteemqueseucdigoserexecutado.Noentanto,comomuitos
beneficiaestapodeserumafacadedoisgumesehmuitascoisasateremconta
aoestabelecerecontrolartantoosseusambientesdedesenvolvimentoeproduo.
Nestecaptulo,vamoscobriralgumasdastcnicasquetemosencontradoparafuncionarbem.

IniciandoVisualFoxPro
VisualFoxPro,comoamaioriadosaplicativos,suportavriosparmetrosdalinhadecomando'.Amaioriados
tempo,estestendemaseresquecidos,maselesexistemeestotodosdocumentadosnaAjudaonline
ficheirosna'PersonalizandoVisualFoxProopesdeinicializaotpico'.Provavelmenteosmaisteis
paralembrarso:

C,Queespecificaoarquivodeconfiguraoparausar
TQuesuprimeasignonVFPtela
RQueatualizaasdefiniesderegistoVFP(Nota,osajustesquesoatualizadosso
asrelativasinformaosobreVFP,taiscomoassociaesdearquivo.OinterruptorRfaz
noatualizarasconfiguraescontroladaspormeiodedilogoOpesdoVisualFoxPro.Isto
feitosomentequando'Definircomopadro'usadoparasairdodilogo).

Ento,paracomearVisualFoxProsemaexibiodesignontelaecomumaatualizaodo
configuraesdoregistrodalinhadecomandonecessrioseria:
G:\VFP60\vfp6.exeRT

Osarquivosdeconfigurao
ExistemvriasmaneirasdelidarcomainicializaodoVisualFoxPro,masomaisfcile
maisflexvel,aindausarumarquivodeconfigurao.VisualFoxProusaumtextoformatadosimples
arquivo,chamado"CONFIG.FPW"porpadro,comoafontedeumasriedevaloresambientais
quepodeserdefinidacomoosistemainiciado.

4 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comoespecificarumarquivoconfig.fpw
OnomedoarquivorealnoimportacomovocpodeespecificaroarquivodeconfiguraoqueVisual
FoxProusarcomoumparmetrodelinhadecomandousandoaopo'c'nalinhadecomando
queusadoparainiciaroVisualFoxPro.Ento,paracriarseuprprioarquivodeconfigurao(porexemplo,para
umaaplicaoespecfica)useaseguintelinhadecomando:
G:\VFP60\APPS\MYAPP.EXEcG:\VFP60\myconfig.txt

ComoVFPlocalizaseuarquivodeconfigurao
OcomportamentopadrodoVisualFoxPro,naausnciadeumarquivodeconfiguraoespecfico,
procurarosseguinteslocaisparaumarquivochamado'config.fpw'nestaordem:

Odiretriodetrabalhoatual
OdiretriodoqualVisualFoxProestsendoiniciado
TodososdiretriosnocaminhoDOS

Sevocestiverusandoointerruptor'c'paraespecificarumarquivonomeadodiferentedopadro,ouemum
localespecfico,vocdeveincluirocaminhoeonomedoarquivocompletos.Istoproporcionaum
mtodosimplesdelidarcomainicializaodediferentesaplicaesinstaladasnomesmo
mquina.

ComoVFPiniciasequandonenhumarquivodeconfiguraoencontrado
Senenhumarquivodeconfiguraoforencontradoouespecificado,VisualFoxProseriniciadoapenascomaqueles
definiesquesoespecificadasnacaixadedilogoOpes(localizadonaTOOLSpaddoprincipalVisual
menudeFoxPro).
Poressasconfiguraesemparticular?
Arespostasimplesmentequetodasasconfiguraesdestedilogosorealmentearmazenadosno
RegistroeWindowspodeserencontradosobachavederegisto:
HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\6.0\Options

Incluindoumarquivodeconfiguraonoprojeto
Umpoucode"armadilha"paraverparasevocadicionarumarquivodeconfiguraochamado'config.fpw'paraoseu
projetocomoumarquivodetexto,elaserINCLUDOnoprojetoporpadro.Quandovocconstrium.exe
doprojeto,oconfig.fpwarquivoserincorporadoaoarquivoresultante.DesdeVisualFoxPro
procuraporumarquivochamado'config.fpw'duranteainicializao,elesemprevaiencontraraversobuiltinprimeira
enoolharmaislonge.Issoseaplicamesmosevocfosseparaespecificarexplicitamenteum
arquivodeconfiguraodiferenteusandoaopo'C'!Seuarquivoespecificadoseriaignorado,eo
arquivocongfigurationbuiltinseriaexecutado.Amelhorsoluonoparaadicionarseu
arquivodeconfiguraoparaoprojetoemtudo,masseofizer,tercertezadequeelemarcadocomo"excludos"
dacompilao.
Captulo1:ControlaroVFPAmbiente 5

Comosuprimirumarquivodeconfigurao
ApartirdoVisualFoxProcomoparmetrodelinhadecomando'c'porsissuprimeopadro
comportamentoeimpedequalquerarquivodeconfiguraoquepodemserencontradosapartirsendoexecutado.O
quevocpodeforarVisualFoxProparainiciarcomapenassuasconfiguraespadro.
resultado

Comodeterminarqualarquivodeconfiguraoestsendousada
UmdosmaiscomunsproblemascomarquivosdeconfiguraonoestagarantirqueVisualFoxPro
estlendoocorretoCONFIG.FPW.Comomencionadoacima,seoVisualFoxPronoconsegueencontrarum
arquivodeconfigurao,eleirprocurarocaminhoDOSesimplesmenteusaroprimeiroqueencontrar.Issopoderia
estaremqualquerlugaremumarede.O SYS(2019)funoirretornarocaminhocompletoeonomedoarquivo
oarquivodeconfiguraoqueVisualFoxProrealmenteutilizados.Senenhumarquivodeconfiguraofoiencontrado,o
funomeramenteretornaumacadeiavazia.

Oquevaiparaoarquivodeconfigurao?
Agoraquesabemosalgosobrecomooarquivodeconfiguraousado,aprximapergunta
oquepodemoscolocarnele?Arespostabastante!Basicamente,existemtrscategoriasde
coisasquepodemserespecificadosnoarquivodeconfiguraodaseguinteforma:

configuraesespeciais
HumnmerodeconfiguraesquepodemSOMENTEserfeitaemumarquivodeconfigurao.(Paradetalhes
vejaos"TermosEspeciaisparaarquivosdeconfigurao"tpiconaAjudaonlinedoVisualFoxProeo
completos
entradaem"ConfigurandoVisualFoxPro"nadocumentaoonline.)Observequeacapacidade
paradefinirolocalparaarquivostemporriostambmestdisponvelnacaixadedilogoOpes.especificandoo
TMPFILESlocalizaonoarquivodeconfiguraosubstituirqualquerconfiguraoquefeitole
podesertilquandovocprecisadiferenciarentredesenvolvimentoeexecutarlocaisdetempopara
arquivostemporrios.

Tabela1.1Exemplodeconfiguraoespecficatermosdearquivo

KeyWord Descrio
MVCOUNT= Defineonmeromximodevariveisq ueVisualFoxPropodemanter.Estevalorpode
nn gamade128a65.000padro1024.
TMPFILES= EspecificaondeEDITWORK,SORTWORKearquivosdetrabalhotemporriossoPROGWORK
dirigir: armazenadossenotiveremsidoespecificadocomqualquerumadasoutrasopes.Comoosarquivosdetrabalho
podesetornarmuitogrande,especificarumlocalcommuitoespaolivre.paramaisrpido
desempenho,especialmenteemumambientemultiusurio,especifiqueumdiscorpido(comoumlocal,
disco).Opadroodiretriodeinicializao.
outshow= Desativaacapacidadedeescondertodasasjanelasemfrentedasadadecorrentepressionando
FORA SHIFT+CTRL+ALT.OpadroON.

Umaoutraconfiguraoquepodeserutilizadanoapenasoficheirodeconfigurao,masquenoincludo
nalistadearquivodeAjuda"screen=OFF".IssoevitaqueatelaprincipalVisualFoxProapartir
sendoexibidoquandooaplicativoiniciadoeimpedequeo'flash'irritantedoVFP
telaqueaindaocorremesmoseoseuprogramadearranquedesligaatelaprincipalcoma

6 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

comando _Screen.Visible=.F.(oquelhepermiteapresentarainicialasuaaplicao
formulrio,ouumatela"splash",semexibirajanelaprincipalVFPprimeiro).

ComandosSET
Praticamentetodososcomandosconjuntopadropodeseremitidoemumarquivodeconfigurao.Onico
coisaaobservarquealgunsajustessorealmenteescopoodatasession.(Vejao"Definir
DataSessiontpico"naAjudaonlineparaobterumalistacompleta).Assim,hpoucopontonaespecificao
losnoarquivodeconfigurao,sevocpretendeusarDataSessionsprivadosparaosseusformulrios.o
sintaxeparaespecificarcomandosSETnoarquivodeconfiguraoumatarefasimplesemque
apalavrachave'SET'omitido:
Padro=C:\VFP60\TIPSBOOK
DATE=BRITISH

comandos
Bem,naverdade,vocpodeespecificarapenasum(conteos!)Decomando,edeveseraltimalinhade
oarquivodeconfigurao.Comooutrasentradasdoarquivodeconfigurao,eleinseridocomoumaatribuiosimples:

COMMAND=DOsetupfox

Oqueousodeapenasumcomando?Bem,muitacoisa,porquerealmenteaquelecomando
podechamarumprogramaFoxPro,equepodefazerummontedecoisas!
Umadasprincipaislimitaesdoarquivodeconfiguraoquevocnopoderealmentedefinirascoisas
quesointernosaoFoxPro(porexemplo,variveisdosistema)Visuaisporque,quandooarquivodeconfigurao
runs,VisualFoxPronotemrealmentecomeou.Usandoessaconfiguraopermitequevocespecifiqueumprograma
arquivoparaserexecutadoimediatamenteapsVisualFoxProiniciousemesmoantesdeajaneladecomando
exibido.
Esteprogramapodeserusadoparaconfiguraroambientededesenvolvimentodamaneiraquevoc
realmentequer.Porexemplo,aquiestoalgumasdascoisasqueestoemnossoarquivodeconfiguraopadro:

***'set'Padroopes(Elaspodemserinseridosdiretamentenaconfigurao
Arquivo)
SETOFFCONVERSA
SETBELLOFF
OFFSEGURANASET
SETOFFSTATUS
SETSTATUSBARON
SETDATEBRITISH
SETCENTURYON
***Redefinirteclasdefuno
SETfuno2para"TABELASfechartodasoWindowsClaro"
SETfuno3"CancelarSETSYSMENUTODEFAativarajanelaCOMMAND"
SETFUNO4para"CLEARALLSETCLASSLIBTOSETPROCTO"
SETFuno5TO"DISPSTRU"
SETFUNODE6A"DISPSTAT"
SETFUNO7TO"MEMODISPCOMO*"
SETFUNO8para"limparoWindowsClaro"
SETFUNO9TO"MODIFORM"

Captulo1:ControlaroVFPAmbiente 7

SETFUNODE10A"MODICOMM"
SETFUNO11para"fazerSetPathCOM"
SETFUNO12TO"=CHGDEFA()"
***ConfiguraraspropriedadesdaTela
_Screen.Caption="VFP6.0(MododeDesenvolvimento)"
_SCREEN.CLOSABLE=.F.
_SCREEN.FONTNAME="Arial"
_SCREEN.FontSize=10
_SCREEN.FONTBOLD=.F.
***extensesRunCobbeditor
DOG:\VFP60\CEE6\CEE6.APP
***Configuraralgumnosrtuloschave
ONKEYLABELCTRL+F10suspenso
ONKEYLABELCTRL+F11o=SYS(1270)
ONKEYLABELCTRL+F12releaseo
***Configurarquaisquervariveisdesistemanecessrios

_Include=HOME()+"FOXPRO.H"
_Throttle=0,1
***Configurarqualquervariveis
padro"Pblico"

gcUserNamePBLICO,gcAppPath,gcDataPath
STORE""paragcUserName,gcAppPath,gcDataPath
***ExecutePadroCaminhoSetup
FAZERCOMSetPath1

Comovocpodever,almdeconfiguraroambientebsicodosistemaVFPeadministrarnossa
prpriosrequisitosespecficos,este'um'comandodisponvelnoarquivodeconfiguraotemagora
foiusadoparaexecutarumpardeoutrosprogramas(CEEeonossoprprioprocedimentoSetPath)entotemos
trspelopreodeum.Aocolocaressasconfiguraesemumprograma,temostambmumaformasimplesde
reinicializaodomeioambienteatravsdareexecutaresteprogramaaqualquermomento.

DandoVFPumcaminho
VisualFoxProtemacapacidadedeusaroseuprpriocaminhodepesquisae,comoregrageral,vocdeve
sempreespecificarumcaminhoparaoVisualFoxProparaambososambientesdedesenvolvimentoedeproduo
emborapossamsermuitodiferente(veracimaparaumamaneiradelidarcomestaexigncia).
DefinirumcaminhoparaVisualFoxPronoalterarocaminhodepesquisanormalDOS,maspode
acelerarsignificativamenteasuaaplicao,limitandooslugaresqueVisualFoxProtemdeprocurar
afimdeencontrarosseusarquivosespecialmentenumambientederede.
ComoVFPprocuraporarquivos
PorpadroVisualFoxProusaodiretrioatualcomooseu"caminho"evocsemprepoderestauraresta
definiosimplesmenteemitindo: SETPATHTO
Noentanto,paraaplicaesmaissofisticadaseemdesenvolvimento,vocternormalmente
algumtipodeestruturadediretriosevocdevesempredefinirumcaminhodepesquisaadequadaparaincluirtodos
diretriosnecessrios.

Definindoodiretriopadro
Normalmente,vocaindavaiquererdefinirumpadro(ou"trabalhar")anurioistoondeVisual
FoxProvaiolharprimeiroparaqualquerarquivoqueelerequer.Istopodeserfeitonumnmerodemaneiras,
dependendodesuasnecessidades:

8 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Especifiqueumpadronoarquivodeconfiguraousandodefault=<caminhoparaodiretrio>
DefiniropadrodiretamentenocdigousandoSETDEFAULTTO<caminhoparaodiretrio>
MudanaparaumdiretriousandooCD<caminhoparaodiretrio>eemissoSETPATHTO

ObservequeusaroGET,PUToulocalizarfunes(porexemploGetDir())nomudatantoo
diretriopadroouocaminho.Paraalterarodiretriopadroutilizardeformainterativa: SETDEFAULT
AO(GetDir()).(A' CD'(ou' CHDIR')decomandotambmpodeserutilizadoparaalterareunidade
diretrioparaolocalespecificado).

UsandoocomandoSETPATH
Definirocaminhoaprpriasimplicidade.ApenasemitirocomandoSETPATHseguidodeumalistade
osdiretriosquevocdesejaincluir.Vocnoprecisaqualificartotalmentesubdiretrios
separandooscomvrgulasoupontoevrgulasuficiente.Oexemplomostraumatpica
VisualFoxProcaminhodepesquisa:
SETPATHTOG:\VFP60C:\VFP60\TIPSBOOK\DADOSformasLIBSPROGSUTILS

PararecuperarconfiguraoquevocpodeusarafunoSET()(queirtrabalharcomocaminhoatual
amaiorpartedoscomandosdoVisualFoxProSET)comomostradoabaixo.Vocpodeatribuiroresultadodiretamente
aumavarivelou,comomostradoabaixo,diretamenteparaareadetransfernciaparaquevocpossa,emseguida,coleo
caminhoparaumarquivodeprogramaoudocumentao:
atual
_ClipText=SET('caminho')

VisualFoxPropermiteousodeambososnomesdecaminhoUNC,como:

\\SERVERNAME\DirectoryName\.

epermiteousodeespaosincorporados(quandoentreaspas)nodiretrio
Nomescomo:
"..\COMMONDIRETRIO\"

Noentanto,enquantooltimopodeserpermitido,quetendemaseinscreverparaoprincpiodeque
'Emboravocpossausarespaosincorporados,arsnicomaisrpido.'(Omesmo,alis,seaplicaa
nomesdearquivoscomespaos!)Apesardemelhoraralegibilidade,espaostambmpodecausarproblemasquando
tentandolidarcomarquivosediretriosprogramaticamenteensaindasentimosqueomelhorconselho
evitlossemprequepossvelemaplicaes.Porexemplo,ocdigoaseguirfunciona
perfeitamentebemparanomesdediretrioconvencionais,masfalharseodiretrioselecionadocontm
espaosincorporados:

lcDirLOCAL
lcDir=GETDIR()
ESE!VAZIO(lcDir)
SETDEFAULTTO&lcDir
FIMSE
Captulo1:ControlaroVFPAmbiente 9

Ondeestou?
Felizmente,VisualFoxProfornecenoscomumasriedefunesqueirnosajudaralocalizar
ondeestamosaqualquermomento:

SYS(2004)retornaodiretriodoqualVisualFoxProfoiiniciado,masemum
aplicativotempodeexecuodistribudos,estesersempreolocaldaVfp6r.dll
(Quenormalmenteaversoapropriadadodiretrio'Sistema'doWindows)
HOME()retornaodiretriodoqualVisualFoxProfoiiniciadoporpadro,mastem
umasriedeopesadicionaisteisemVFP6queretornaminformaessobreoVisual
Componentesdeestdio
_VFP.FULLNAMEAcessaumapropriedadedoobjetoaplicativoVisualFoxProque
contmocaminhoeonomedoarquivocompletoquefoiutilizadaparainiciarVFP
FULLPATH('')ou FULLPATH(CURDIR())retornaaunidadeplenaediretriodo
atualdiretriodetrabalho(incluindooterminal"\").
SYS(5)retornaaunidadepadro(incluindoo':')
CDmostraaunidadeepastaatuaisnajaneladesadaatualmassertambm
alterarunidadeeodiretrioemumnicocomando
CHDIRseralteradoparaoespecificadoDrive/Driectory(como CD),masnoirrelataro
estadoactual(eassimnoatrapalharsuasformas)
CURDIR()retornaapenasodiretrioatual(comterminalde'\'),masnoaunidade

Comodefinirumcaminhodeprogramao
Comoumaalternativaaodiscorgidocodificaooscaminhosnoseuarquivodeconfigurao,possvelderivaro
(Supondoquevocusaestruturasdediretriopadro)usandoasfunesdoVisualFoxPronativos.
caminho
Afunopoucoabaixomostracomoissopodeserfeitoparateremcontaodesenvolvimentoea
executarestruturasdetempo.Eleusao PROGRAM()funoparadeterminarcomoelefoichamadoeretornaum
caminhodiferentequandochamadodeumformulrioouumprogramadoquequandochamadoapartirdeumarquivo
compilado:
*******************************************************************************
*Programa :CalcPath.prg
*Verso :1,0
*Autor :AndyKramek
*Encontro :16deagostode1999
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:DefineumcaminhoVFPcombasenotipodeprogramadechamada.
* :Assumeestruturasdediretriopadromaspoderiausarpesquisas
*******************************************************************************
CalcPathfunction()
lcSys16LOCAL,lcProgram,lcPath,lcOldDir
***Obteronomedoprogramaquechamoueste.
lcSys16=SYS(16,1)
***Salvediretriodetrabalhoatual
lcOldDir=(SYS(5)+CURDIR())
***Faaodiretriodoqualelefoiexecutadoatual
lcProgram=SUBSTR(lcSys16,AT(":",lcSys16)1)
CDLEFT(lcProgram,RAT("\",lcProgram))
IFINLIST(JUSTEXT(lcProgram),"FXP","SCX")

10 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***SeestiverexecutandoumPRG/Formdiretamente,emseguida,encontrarodiretriopai
CD..
***ConfigurarcaminhoparaincluirVFPIncioalmdarvoredediretriosDEVpadro
lcPath=(HOME(+)''+SYS(5)+CURDIR(+)"DADOSformasLIBSPROGSUTILS")
OUTRO
***EstamosusandoumEXE/APP!Ajustecaminhoparaarvoredediretriodedistribuio
lcPath=(HOME(+)''+SYS(5)+CURDIR(+)"DATA")
FIMSE
***Restaurardiretriooriginal
CD(lcOldDir)
***Retornaocaminhocalculada
RETURNlcPath
ENDFUNC

CertificarsedeVFPiniciadoapenasumavez
Porenquanto,tudobem!ConseguimoscobriroprocessodeiniciarVFPeconfiguraodabase
ambientesparaodesenvolvimentoeproduo.Nesteponto,umadascoisasquetodosnsvm
dooutroladoousuriodistradoqueminimizaumaaplicaoe,emseguida,dezminutosdepois,
iniciaumanovacpiadeseudesktop.Dentrodeumahoraelestmseiscpiasdopedido
correndoesequeixamdequeasuamquinaestaabrandar.Oquefazer?(Almde
fotografarousurioque,apelandoqueaidiapodeser,geralmentedesaprovadoe,
emfunodasuaantiguidade,tambmpodeserummovimentodelimitaocarreira.)Naverdade,existemvrios
abordagensquepodemsertomadas,comodescritoabaixo.

Usandoumarquivo'semforo'
Esteprovavelmenteomtodomaissimplesdetodos.Elesebaseiaemsuacriaodeaplicativos,emprimeiro
lanar,umarquivodezerobytes,cujonicopropsitoindicarqueoaplicativoexecutado.Qualquer
tempooaplicativoiniciado,eleprocuraporestearquivoe,seeleencontralo,simplesmentedesliganovamente:

*******************************************************************************
*Programa :ChkSFile.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:verificaumarquivoSemaphore,criaum,senoencontradoe
* :Retornaumabandeira
*******************************************************************************
FUNOChkSFile(tcAppName)
lcAppNameLOCAL,lcFile,lnHnd,llRetVal

***LcAppNamepadrosenadapassado
lcAppName=IIF(VAZIO(tcAppName)ORVARTYPE(tcAppName)#"C",
'Apprun',BAIXA(ALLTRIM(tcAppName)))

***ForarumaextensoTXTparaoarquivosemforonodiretrioatual
lcFile=(SYS(5)+CURDIR()+FORCEEXT(lcAppName,'txt'))

***Agoraverifiqueoarquivo?
ESE!ARQUIVO(lcFile)
***Arquivonoencontrado,entocrilo
lnHnd=FCREATE(lcFile)
IFlnHnd<0

Captulo1:ControlaroVFPAmbiente 11

***Nopossvelcriaroarquivo,algumtipodeerro!DefinirBandeiraderetorno
llRetVal=.T.
OUTRO
***Fecheoarquivo
FCLOSE(lnHnd)
FIMSE
OUTRO
***DefinirBandeiraderetorno
llRetVal=.T.
FIMSE
***BandeiraEstadoRetorno
RETURNllRetVal

Afunoretornaumvalorlgicoquepodemserusadasparadeterminarseapermitirqueo
aplicativoatualparacontinuar,comootrechoaseguirilustra:

***Verifiqueparaumasegundainstnciadoaplicativo
IFChkSFile()
SAIR
FIMSE

Claroqueacapturacomestaabordagemqueoaplicativodeveexcluiroarquivocomoparte
dasuarotinaclosebaixo(amenosquevocrealmentequerumavezsdeaplicao).Issolevantaa
questodeoquevocpodefazerse,Deusnoslivre,aaplicaoterminadeformaanormal
(Eufemismopara'Crash')ouousuriofazumasadaimprpria(desligarofornecimentodeenergiapara
exemplo!).Aresposta"Nomuito."Normalmente,issovaiexigiraintervenodo'Sistema
Suporte'paraeliminarfisicamenteoarquivo.
Masumaboaabordagem,fcil,semoutrosinconvenientesreaisdesdequeosemforo
arquivosemprecriadanamquinadousuriofinal,ouemumdiretriodeusurioespecfico.
UsandoaAPIdoWindows
AfunoabaixofazusodetrsfunesdaAPIdoWindowsparaprocurarumajanelaqueest
chamadoomesmoqueaaplicao(FindWindow),parafazerumajanelaexistenteomaisalto
window(BringWindowToTop)emaximizlo(ShowWindow):

*******************************************************************************
*Programa :OnceOnly.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Abstract...:Verificasehumainstnciaexistentedajaneladoaplicativo
* :E,seencontrado,ativaooriginaleretornaumsinalizador.
*******************************************************************************
FUNOOnceOnly
lnHWNDLOCAL,lcTitle,llRetVal

***configurarchamadasdeAPI
DeclareIntegerFindWindowINWin32APIASFindAppString,String
DeclareBringWindowToTop INWin32APIASMakeTopInteger
DeclareShowWindow INWin32APIASShowWinInteger,Integer

***ObteroCaptionTelaatual
lcTitle=_Screen.Caption

12 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Alterloparaevitarencontrarainstnciaatual
_Screen.Caption=SYS(3)

***Agora,localizeoutrainstncia
lnHWND=FindApp(NULL,lcTitle)

***Erestauraralegendaoriginais
_Screen.Caption=LcTitle

***Verifiqueosresultados
IFlnHWND>0
***Nsdescobrimosalgumacoisa!
***Assimtornlomaisaltoemaximizlo(ShowWin=>3)
MakeTop(lnHWND)
ShowWin(lnHWND,3)
***DefinaoValorderetorno
llRetVal=.T.
FIMSE

***StatusdeRetornoparaaao
RETURNllRetVal

Afunoretornaumvalorlgicoquepodemserusadasparadeterminarseapermitirqueo
aplicativoatualparacontinuar,comootrechoaseguirilustra:

***Verifiqueparaumasegundainstnciadoaplicativo
IFOnceOnly()
SAIR
FIMSE

Humagrandedesvantagemqueatenteparaaqui.AsfunesdaAPIdeverificaoutilizadosparaa
nomedeumajanelanestecaso,estamosusando _Screen.Caption.Seasalteraesdeaplicao
Legendadatelaemtempodeexecuo(comomuitosfazem),estaabordagemnovaifuncionar.

CombinaodesemforoeWindowsAPI
Oltimoexemplomostracomoaquicombinandoosprincpiosdosoutrosdoisexemplosdum
abordagemmelhorallround:

******************************************************************************
*Programa :IsAppRun.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:VerificasehumajanelaquecriadocomumUniqueIDpore
* :naaplicao.CombinaodesemforoeAPI.
* :Baseadonocdigooriginalmenteemdomniopblico
* :PorChristofLange
******************************************************************************
FUNOIsAppRun(tcUniqueID)
LOCALllRetVal,lcUniqueID

***DevepassarporumIDdeaplicaoparaestafuno!
IFEMPTY(tcUniqueID)ORVARTYPE(tcUniqueID)#"C"
MESSAGEBOX('UmaAplicaoIDEspecificidadeobrigatria'+CHR(13)
+'AochamarafunoIsAppRun()',16',desenvolvedordeerro')
RETURN.T.
Captulo1:ControlaroVFPAmbiente 13

OUTRO
***Tiraforatodososespaos
lcUniqueID=STRTRAN(tcUniqueID,"")
FIMSE
***PrimeiroverifiqueaexistnciadajaneladoSemaphore
IFWEXIST("_Semaphore_")
RETURN.T.
FIMSE
***ProcureumaocorrnciadesteIDcomoumnomedejanela
DECLAREINTEGERFindWindowINWin32APIASFindAppString,String
IFFindApp(NULL,lcUniqueID)>0
***Nsencontramosum!DefinirValorderetorno
llRetVal=.T.
OUTRO
***CriarumanovajanelacomesteID
DEFINEWindow_Semaphore_Nareadetrabalhode1,1para2,2TTULOlcUniqueID
FIMSE
***BandeiraEstadoRetorno
RETURNllRetVal

Parautilizarestafuno,maissimplesparaincluirum#DEFINEnoseuarquivodeinicializaopadro,demodo
quevocpodeespecificarumnovoIDnicoparacadaaplicao:

#DEFINEAPPID"App000199"
IFIsAppRun(APPID)
SAIR
FIMSE

Estasoluomuitoeleganteevitatantooproblemados'arquivospendurados'nosemforo
emtodoquedemudarosubttulonomtodoAPIporqueajanelapodeserapenas
criadoemantidodentrodeumexemplodeaplicao.Assimqueterminaemqualquer
formamesmocomoumresultadodeumacidenteajaneladestrudoenohnadaalimpar.
Desdeajanelarecebeonomeexplicitamenteapartirdaaplicao,elenocontarcomalegenda
sendoconstantequalquer.CoolstuffChristof,obrigado!

SETComandoseDataSessions
OKtemosVisualFoxProinstaladoefuncionando(esecertificoudequespodeiniciarum
instnciadenossaaplicao)porissoagora?Existem,nocasodevocnotenhanotado,umaenormequantidadede
SETcomandosnoVisualFoxProquepermitemconfiguraroambienteemdetalhe.Muitos
delasafetamomeioambienteglobal,masalgunssoescopoparaoativonomomento
datasession(consulteo"SetDataSessiontpico"naajudaonlineparaobterumalistacompletadestes).
QuandovociniciaroVisualFoxProquevocestsemprenoPADROdatasession.

Oqueexatamentesignifica"DefaultDataSession"significa?
ODicionriodeInglsOxford(NinthEdition)ofereceumadefiniode"default"como:
"Aopodeprselecionadosadotadoporumprogramadecomputadorquandonohouveralternativa
ousurioouprogramador"
especificadopor
InfelizmenteVisualFoxProparecepreferirparadefinirapalavradeacordocomasregras
proferidaporHumptyDumptyemLewisCarroll"AliceAtravsdoEspelho":

14 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
"Quandoeuusoumapalavra",disseHumptyDumpty,emvezumtomdedesprezo",issosignificaapenasoqueeu
escolhloparadizernemmaisnemmenos".
Naverdade,oDataSessionpadrorealmenteDataSession#1nemmaisnemmenos.Tem
nenhumsignificadoespecialdiferentedoquequandovociniciarVisualFoxPro,eleserselecionado(talcomo
readetrabalho#1sempreselecionadacomoaprimeirareadetrabalhodisponvelemqualquerDataSession).Isto
facilmentedemonstradautilizandoajanelaDATASESSIONoSETejaneladecomando.
QuandovocabreajaneladeDataSession,eleirexibironomedoatual
DataSessioncomo'Default(1)',noentanto,ocomando:

SETDATASESSIONTODEFAULT

resultaemum"padroVarivelnoencontrado"erro,enquanto
SETDATASESSIONTO1

aceitosemcomentrios.
Noentanto,quandovocexecutarumformulriocujapropriedadeDataSessiondefinidocomo"Dados1Default
Session",VFPinterpretaotermo"default"nosentidode"correntes"emoutraspalavras,umformulrio
queprojetadousandoessaconfiguraousarqualquersessodedadosestativoquandooformulrio
inicializado.Issonoparecemuitolgicoprimeiravista,umavezquesepoderazoavelmenteesperar
que,porcausadasessodedados#1nomeado'Default',definindoapropriedadeDataSessiondeumformulriopara'1
Padrosessodedados"seriagarantirqueaformaseriarealmenteusaressasessodedadosenenhuma
deoutros.Noto!
Ocomportamentorealfazsentidoquandosedesejaformasdecompartilharumasessodedados.Definindo
DataSessionpropriedadesdoformulriofilhopara1(Padrosessodedados),eleusaroquequer
DataSessionseuformulriopaiestavausandoseissoDataSessionprivadoouno.

Ento,eupossoterum"pblico"Datasession?
Arespostacurtano!VisualFoxProsuportaoconceitodeum'default'verdadeiramente(ou'pblico')
DataSession.Emoutraspalavras,seumatabelaespecificadonoencontradonacorrentededadosdeSessoVFP
novaiprocurloemoutrolugar.TodososDataSessionssoefetivamente"Private"mesmoSessodedados
#1.

ComopossogarantircomandosSETaplicamseaumasessodedadosprivados?
Estarealmenteumaquestocomplexaearesposta,comotantasvezesnoVFP,"depende".
Normalmentevocirutilizarsessesdedadosqueestosendocriadosporumaforma(ouformset)como
'Privado'.TambmimportasevocestusandoDataEnvironmentnativadoFormulrioouno.em
qualquercaso,importantecompreenderaordemnaqualascoisasacontecemasequnciaabaixo
mostracomoumformulriocomumDataSessionprivada,eumamesaemseuDEnativa,inicializado:

MTODO:DATAENVIRONMENT.OPENTABLES()
DATASESSION:2
ALIAS():<nenhum>

MTODO:DATAENVIRONMENT.BEFOREOPENTABLES()
DATASESSION:2

Captulo1:ControlaroVFPAmbiente 15

ALIAS():<nenhum>

MTODO():Form.Load()
DATASESSION:2
ALIAS(): <TableName>

MTODO:DATAENVIRONMENT.INIT()
DATASESSION:2
ALIAS(): <TableName>

NotesequeoDataSessionsempre2,onovoDataSessionprivada,equeatabelaest
jdisponvelnoDataSessionquandooformulrioLoad()eventoacionado.

AanomaliaqueOpenTables()ocorreantesBeforeOpenTables()
maisaparentequerealecausadopelofactodeo
BeforeOpenTablesevento()sejaaccionadopelosOpenTables()
Mtodo.

Umanotaaquinecessriaparaexplicaraterminologiaqueestamosusandopara
"Eventos"e"Mtodos".InfelizmenteVisualFoxProusatanto
termosnafolhadepropriedadesquepodeserconfuso.Naverdade,
realmentemuitosimples,jquevocnopode,noVisualFoxPro,criaroumodificar
um"evento",apenasocdigodomtodo"associadoaesseevento."Oqueistosignifica
queoacessoao"<xxx>Evento"apartirdafolhadepropriedades,naverdade,levaopara
o"<xxx>Method".Aprticaqueadotamosaolongodolivro,
portanto,parasereferir"<xxx>MTODO"quandoestamosafalardolugaronde
vocescreverocdigo,eparaoevento<xxx>quandoserefereao,ou'gatilho'
oquefazcomqueocdigoaserexecutado.

Ento,sevocprecisamudarexplicitamenteconfiguraesqueseaplicammaneirapelaqualastabelasso
manipulados(porexemploMULTILOCKS)vocrealmenteprecisafazlonaDataEnvironmentdo
BeforeOpenTables()cdigonadamaistardedemais,porqueoDataSessionjest
Actualmente,commesasdeabrir,pelotempoqueaprimeiraformamtodobaseado(load())incndios.
IstoapresentaumproblemaporqueumformulrioVFPclassenotemumDataEnvironment,ento
vocnopodesimplesmenteadicionarcdigoparaaclassedaqualvoccriasuasformas.Hrealmenteapenas
duassoluessevoctiverqueusarDataEnvironmentdoformulrio,eambosnecessitamdecdigo,oumais
especificamentealgumaaoemcadainstnciadeumformulrio:

Adicioneocdigorelevante(ouumachamadaparaumprocedimento)paraBeforeOpenTablesdetodaaforma()
evento
NopermitaqueoDataEnvironmentnativaparaabrirsuastabelasautomaticamente.Conjunto
AutoOpenTables=.F.echamarosOpenTables()mtodoexplicitamenteapartirdo
CargaForm()

16 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

AdicionandocdigoparaBeforeOpenTables()
Istomuitosimples,masdeveserfeitoemcadainstnciadoformulrio.BastaabriroFormulrio
DataEnvironmentnodesignereadicionaroqueasconfiguraesdoambientequevocnecessitadiretamente
paraoBeforeOpenTablesmtodo.Alternativamente,vocpodecolocarocdigorelevanteemum
procedimentoechamloapartirdomtodooucriarumaclassedeconfiguraodoambiente(vejaabaixo)e
instanciloutilizandooformulrioAddObject()mtodo.(ADataEnvironmenttemum
AddObject()doseuprprio,masvocspodeadicionarobjetoscombaseemclassesdecursoreRelao
directamenteparaoDataEnvironment.)
Umasugestoadicional,sevocadotarestametodologia,colocarcdigonoLoad()
casodesuaclassedeformulrioqueverificaumaconfiguraoespecficaeseelenoforencontradoexibeuma
Caixademensagem.Assim:

IFThis.DataSessionId#1
***TemosumDataSessionprivada
IFSET('MULTILOCKS')='desligado'
***Ouqualquerconfiguraoquevocsempredefinido!
lcText="VocnodefiniuosBeforeOpenTables()CdigoUp"
MESSAGEBOX(lcText,16,'desenvolvedorBlunder!')
FIMSE
FIMSE

Suprimindotabelasautoaberto
SevocdesejausardoformulrioCargamtodoparadefiniropesparaumDataSession,vocdeveprimeiro
suprimirocomportamentopadrodoDataEnvironmentqueatabelasautomaticamenteabertos.este
umasimplesquestodedefiniroAutoOpenTablespropriedadeparafalsenoDataEnvironment,mas
maisumavez,deveserfeitodeformaexplcitaemcadainstnciadoformulrio.Depoisdetersuprimidoesta
propriedadequevocpodecolocarcdigonomtododecarregamentodoformulrioparachamarumprocedimentoouum
mtodo,queirlidarcomaconfiguraodoambiente.Omtodopreferencialautilizaodeum
formulrio
ambientedeclassedefinioesimplesmenteinstanciarumobjetocombasenessaclassediretamentena
doformulrioCargamtodo,conformeilustradonaprximaseo.

Criandoumaclassedeconfiguraodoambiente
PensamosqueomelhormtododecriaodeseuprprioambienteemumDataSessionprivada
usarumaclasse.AocolocartodososcomandosSETnecessriasemummtodoquechamadopor
oInitmtododaclasse,apenasinstanciarumobjetocombasenestaclasseirdefinirascoisas
dojeitoquevocquerqueeles.Ocdigoparafazerissopodeserentocolocadonacargamtododasua
classedeformulrioparaquecadavezqueoformulrioinstanciado,asconfiguraescorretassoaplicadas.Onico
limitaodestametodologiaque,comomencionadoacima,vocnopodepermitirqueoDataEnvironment
paratratarautomaticamenteaaberturadetabelas.Ocdigoaseguirmostracomoumaclassepode
serdefinidaspormeiodeprogramao(emboranohajanenhumarazoparaquetalclassenodeveser
criadonodesignerdeclassevisual):
******************************************************************************
*Programa :EnvSet.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows

Captulo1:ControlaroVFPAmbiente 17

*Resumo...:definiodeclasseparaadefiniodeopesambientais.
instanciar
* :Aclassedefineasopesnecessrias.O()MtodoGetOption
espectculos
* :Comooobjetopodeserusadopararecuperarasconfiguraestambm.
******************************************************************************
DEFINECLASScusEnvSetASpersonalizado
*****************************************************************************
***InitsimplesmentechamaosSetOptions()Mtodo
*****************************************************************************
PROCEDIMENTOInit
This.SetOptions()
ENDPROC
*****************************************************************************
***setsnecessriosopesambientais
*****************************************************************************
SetOptionsPROCEDIMENTO
***LockingeMeioAmbiente
SETOFFCONVERSA
SETMULTILOCKSON
SETREPROCESSparaAutomtico
SETDELETEDON
OFFSEGURANASET
SETBELLOFF
SETECHOOFF
SETNOTIFYOFF
SETOFFCONFIRM
ConjuntoexatoOFF
SETREFRESHTO60,60
SETSTATUSBARON
***Path

***DataeMoeda
SETCENTURYON
SETCENTURYpara19ROLLOVER75
SETDATADEBRITISH
LEFTMOEDASET
MOEDAdefinidocomo""
ENDPROC
*****************************************************************************
***Retornadefinioactualdeumaopodeambiente
*****************************************************************************
PROCEDIMENTOGetOption(tcOption)
LOCALluRetVal,lcOption
STORE""paraluRetVal
lcOption=UPPER(ALLTRIM(tcOption))
***Senosfoidadaumadefinio,obterseustatusatual
***NOTA:Serealmentenecessrioestemtodoexigiriamaisverificao
***Eopes,porquenemtodasasdefiniespodemsimplesmenteserdevolvido
***PelafunoSET()masistoilustraoponto!
IFVARTYPE(lcOption)="C"E!VAZIO(lcOption)
luRetVal=SET(lcOption)
FIMSE
RETURNluRetVal
ENDPROC
ENDDEFINE

Parausaressaclasse,bastaadicionaroseguintecdigoparaacargamtododesuaclassedeformulrio:
18 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Adicionarobjetoparadefiniroambiente(suprimirqualquerexibioexplicitamente)
SETOFFCONVERSA
ESE!"ENVSET"$UPPER(SET("Procedimento"))
PROCEDIMENTOPARAenvsetaditivoconstante
FIMSE
This.AddObject("oCusEnv","CusEnvSet")

Istovaiumainstnciadoobjecto,criandoassimasopesdefinidos,eaomesmotempo
criaumareferncianoformulriodemodoquequaisquermtodosadicionaisquevocpodeterdefinidos(porexemplo,
oGetOption()mtododescritoacima)podeseracessado.

Comofaoparamelivrardasbarrasdeferramentasdosistema?
QuandovociniciaroVisualFoxPro,umaoumaisdasbarrasdeferramentasdosistemasernormalmentevisvel.
(Oestadodabarradeferramentasreaissoarmazenadosnoarquivoderecurso.)Felizmentetodasasbarrasdeferramentasdo
podemserresolvidosusandoseusnomesdejanelas(queso,naverdade,omesmoquesuaslegendas)e
sistema
assimmanipullosrelativamentesimples.
Amaneiramaissimplesdegarantirqueapenasasbarrasdeferramentasdequenecessitaestovisveis
criarumamatrizdetodososnomesdabarradeferramentas,emseguida,umloopporisso,testandoparaversecadaum
escondendoaquelesquenosonecessrios.Ocdigoaseguirirescondertodasasbarrasdeferramentasdosistemavisveis:
visvele

DIMENSOlaTbState[11]
laTbState[1]="paletadecores"
laTbState[2]="Designerdebancodedados"
laTbState[3]="Controlesdeformulrio"
laTbState[4]="FormDesigner"
laTbState[5]="Layout"
laTbState[6]="VisualizarImpresso"
laTbState[7]="criadordeconsultas"
laTbState[8]="Controlesderelatrio"
laTbState[9]="ReportDesigner"
laTbState[10]="Standard"
laTbState[11]="ViewDesigner"
PARAlnCnt=1a11
IFWEXIST(laTbState[lnCnt])
FECHARJANELA(laTbState[lnCnt])
FIMSE
PRXIMO

Claro,issolevantaaquestodoqueacontecesevoc,emseguida,desejarreexibirumsistema
barradeferramentas.Talvezsemsurpresa,o VITRINEcomandopodeserusadopararedisplayum
anteriormenteocultobarradeferramentasdosistema,enquanto LIBERTAOJANELAvairealmenteliberaroespecificado
barradeferramentas.

Abarradeferramentasdosistema"Gotcha!"
Mashumporm!ParautilizarMostrarjanela,ajanelacomonomedevetersidodefinido
paraVFPemesmoqueasbarrasdeferramentasdosistemasogeradosporVFP,nohnenhumamaneirade
naverdade,definirouativarasbarrasdeferramentasdeprogramao.Aconsequnciaqueamenosqueum
barradeferramentasativadopelaprimeiravez,porsisVFP,nopodemaistardetornarvisvel.Asnicasbarrasde
podeserfeitavisvelporpadrosoo'Standard','Esquema'e'DesignerForm',masnofaz
ferramentasque

Captulo1:ControlaroVFPAmbiente 19

Noparecehavernenhumamaneiraconfiveldeforarprogramaticamentequalquerumadasoutrasbarrasdeferramentas
aserfeitavisvelnainicializao.
dosistema

PossofazerusodemacrosdetecladonaVFP?
Arespostacurtasim.Naverdade,umadascapacidadesmuitasvezesesquecidosdoVisualFoxProasua
capacidadedeusarmacrosdeteclado.Estespodem,comumpoucodepensamento,fazerasuavidacomoum
muitomaisfcilquandovocatribuirsuasprpriascombinaesdeteclasespecficasaumasimplescombinaode
desenvolvedor
exemplo,emvezdeexecutarumprograma"Reset"parafecharmesasebancosdedados,classedeliberao
teclas.Para
bibliotecaserestauraromenupadroFoxPro,vocpodeprogramaroscomandosnecessriossobrea
o"F2tecladefuno'comoeste:

SETFUNOF2para"CLEARALL"
+"SETCLASSLIBTO"
+"SETPROCTO"
+"CLOSEALL"
+"SETSYSMENUinadimplncia"
+"AtivarajanelaCOMMAND"

ClaroquevoctambmpodeusaroEditorMacro(chamadoapartirdoFerramentas|Macrosopode
Nomenuprincipal)paracriarasmacros.Amacrocriadopelocomandoacimavisvel,
eeditvel,noEditordeMacrocomo:

LIMPAR{}barradeespaosALL{barradeespaos}{ENTER}
SET{}barradeespaosCLASSLIB{barradeespaos}para{barradeespaos}{ENTER}
SET{}barradeespaosPROC{barradeespaos}para{barradeespaos}{ENTER}
Fechar{}barradeespaosALL{barradeespaos}{ENTER}
SET{}barradeespaosSYSMENU{barradeespaos}para{}barradeespaospadro{barrade
ACTIVATE{}barradeespaosJANELA{}barradeespaoscomando{ENTER}
espaos}{ENTER}

Comopossoconstruirumamacromaiscomplexa?
Vocpodeusaramacrofacility"record"(sim,assimcomonoWordouExcel!)Parasalvarseo
dordetrabalharforaexatamentecomoescreveroscomandosdetecladonecessrios.Nsnormalmenteusamos
umarquivodeprogramavazioparafazeressetipodecoisa,comoasetapasaseguirilustram:

AbraumarquivoPRG(Comandodemodificao)
EscolhaFerramentas,macros,RecordapartirdomenuSistemaPrincipal
Escrevaocdigocomonormal
EscolhaFerramentas,macrosparapararagravao
Testeasuamacro!

Usandoestatcnica,ocdigoaseguirparaescreverumSim/NomanipuladorMessageboxsimples
(EdeixarocursorposicionadoentreoprimeiroconjuntodecitaesnafunoMessageBox
chamam)foiatribudoteclaF9.Ocdigoescritoera:

lnOptLOCAL
lnOpt=MessageBox('',36'')

20 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

IFlnOpt=6 &&SIM

FIMSE

Eamacroresultantefoiaseguinte:

LOCAL{}barradeespaoslnOpt{ENTER}
lnOpt{barradeespaos}={}barradeespaosMessageBox({barradeespaos}'',
{}Barradeespaos36,{}barradeespaos''{}barradeespaos){ENTER}
IF{SHIFT+barradeespaos}{lnOptbarradeespaos}={}barradeespaos6
{TAB}&&{barradeespaos}YES{ENTER}
{ENTRAR}
ENDIF{UPARROW}{}{UPARROWUPARROW}{END}{}{LEFTARROWLEFTARROW}{}LEFTARROW
{LEFTARROW}{}{LEFTARROWLEFTARROW}{}{LEFTARROWLEFTARROW}{}LEFTARROW
{LEFTARROW}{}LEFTARROW

Oqueum"SetMacro"?
VisualFoxPropermitedefiniresalvar"conjuntos"demacros.Estessoarmazenadosnumficheiroespecial
formatocomumaextensopadro'.FKY'(oficheirodeajudatemumtpicodedicadoaFKYarquivo
estrutura).Vocpodecriarvriosconjuntosdemacrosesalvlosemarquivosquepodemsercarregadose
descarregadoatravsdoeditordemacro.Voctambmpodeespecificarumconjuntodemacros'desenvolvedor'comodefaults
parasercarregadoautomaticamentequandoVisualFoxProiniciado.(Emborasevocadotaressaabordagem,
aconselhaseaincluirum LIMPARMACROScomandoemtodososprogramasdearranquedaaplicao.)
Algumasmacros'desenvolvedor'quetemosencontradotilso:

inserocomeste...ENDWITH( ALT+T)
COMESPAO{}Este{ENTER}
{ENTRAR}
ENDWITH{UPARROW}{TAB}
INSERTcomThisForm...ENDWITH( ALT+F)
COMESPAO{}ThisForm{ENTER}
{ENTRAR}
ENDWITH{UPARROW}{TAB}
InserirCitadoparnteses("")( ALT+B)
(""){LEFTARROW}{}LEFTARROW
inserirumaespera"',ajanelaNOWAIT( ALT+W)
ESPERA{barradeespaos}""{}barradeespaosJANELA{}barradeespaosNOWAIT
{LEFTARROW}{}{LEFTARROWLEFTARROW}{}{LEFTARROWLEFTARROW}
{LEFTARROW}{}{LEFTARROWLEFTARROW}{}{LEFTARROWLEFTARROW}
{LEFTARROW}{}{LEFTARROWLEFTARROW}{}{LEFTARROWLEFTARROW}
Open'Localizarprxima'Windowecolarnotextorealado( SHIFT+ALT+F)
{CTRL+C}{CTRL+HOME}{CTRL+F}{CTRL+V}{TAB}{}{BACKSPACECTRL+ENTER}

Oespaoparaacriaodeatalhospersonalizadoscomoesteslimitadoapenaspelasuaimaginao,mas
podemelhorarsignificativamenteasuaprodutividadeaoescrevercdigooumesmoquandosetrabalhadeformainterativa
atravsdajaneladecomando.
Finalmente,tambmverificara reproduzirosmacroscomando,quepermiteexecutarmacros
programaticamente(paracriardemosdeexecuoautomtica,oumesmoscriptsdetestesimples),emborao
comportamentodestecomandotemalgumaspeculiaridadestodososseusprprios.

Captulo1:ControlaroVFPAmbiente 21

QualadiferenaentreumamacroeumnaetiquetaKey?
AprincipaldiferenaqueumamacroapenasumprogramaVisualFoxProqueemanadoteclado
entrada.Nestesentido,nodiferentedequalqueroutroprogramaeexecutadodentrodonormal,Visual
FoxProciclodeeventos.Umachavenaetiqueta,poroutrolado,operanoexteriordoeventonormal
processamentoepermiteumcomandoespecficoparaserexecutadomesmoquandoVFPostensivamente
envolvidoemalgumaoutratarefa.Istopodesermuitotil,mastambmpotencialmenteperigosa!o
seguintepequenoprogramailustraadiferenanocomportamentoclaramente.Aetiquetanatecla
interromperopendente LEIAcomandoimediatamenteesuspenderoprograma,enquantoo
Macrodotecladosimplesmenteignorado:
******************************************************************************
*Programa :MACOKL.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:ilustraradiferenaentreumamacrodeteclado
* :EumcomandoONKeyLabel.Enter'99'parasairapartirdequalquerciclo
* :Econtinuarcomoprograma!
******************************************************************************
***DefinirumnaetiquetaKey
ONF10LABELKEYSUSPENDER
CLARO
***BufferdechaveInicializar
lnKeyLOCAL
lnKey=0
***IniciarLoopUse99parasair
DoWhile.T.
***Verifiquepara'x'parasair
?"DentrodeumcircuitodeOKL"
@10,10GETlnKeyPICT"99"
LER
IFlnKey=99
SADA
FIMSE
ENDDO
***LimparoOKL
ONF10LABELKEY
CLARO

***AgoradefinirumaMacroKeyFunction
Conjuntodefunes10"suspender"
***BufferdechaveInicializar
lnKey=0
***IniciarLoopUse99parasair
DoWhile.T.
***Verifiquepara'x'parasair
?"DentrodeumloopF10"
@10,10GETlnKeyPICT"99"
LER
IFlnKey=99
SADA
FIMSE
ENDDO
***Desmarqueamacro
SETFUNODE10A""
22 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Claramente,porquenosrtuloschavepodeoperarforadamanipulaoeventonormal
mecanismos,seuimpactosobreocdigoaexecutarjpodeserimprevisvel.AlmdissoOnKey
Asetiquetaspodemserchamadorepetidamenteamenosquevocincluira tecladepremirLIMPAR/POPteclaCLEAR
comandosparadesativaraetiquetaOnKeysi,enquantoarotinaquechamaoprocessamento.
Porestasrazes,recomendofortementecontraseuusoindiscriminadoemaplicaes
especialmentedesdequehquasesempreumaformaalternativa(normalmentepormeiodecdigono
KeyPressmtodo)delidarcomcombinaesdeteclasespeciais.

Comofaoparacriarumatela"splash"?
EstaumadastarefasqueVisualFoxProVerso6.0lidacomumpoucomelhordoqueoseu
antecessores.Aprimeiracoisaquenecessrioumaformaquedesprovidodeumabarradettuloenormal
controlesdeformulrio.Naverso6.0doTitleBarpropriedadefoiadicionadaparaaclassedeformulrioesimplesmente
definindo TitleBar=.F.dlheumaformasimples.EmversesanterioresdoVFP,humasrie
depropriedadesquedevemsertodosajustadosparaconseguiromesmoresultado:

Caption=""
ControlBox=.F.
Closable=.F.
MaxButton=.F.
MinButton=.F.
Movable=.F.

Oformulriotambmdeveserconfiguradocomoumformulriodenvelsuperior( ShowWindow=2,AlwaysOnTop=
.T.).Oquevaiparaaformadependentedesuasnecessidades,masnormalmenteelevai
incluemumgrficodealgumtipoeprovavelmentealgumtexto.Voctambmpodequereradicionarqualquerum
oucdigoparapermitirqueousurioparalimparexplicitamenteatelainicial.
temporizador

Comopossoexecutarminhatelainicial?
Amaneiramaiseficazdeexecutarumateladeabertura:

Incluir'TELA=OFF'emseuarquivodeconfigurao
Executaroformulrioinicialcomoaprimeiralinhadesuaaplicaostartup
Faaoquesetupnecessrioincluindoseumenuinicial
RestaurarajanelaprincipaldoVisualFoxProeremoveratelainicial
Inicieolaodeeventosdoaplicativo

Otrechodecdigoaseguirmostracomooprogramadearranqueficarianaprtica:

***Mostraratelainicial

DOFORMrespingorespingonomeligado
***SerquealgummaterialSetupaqui
***Naconcluso
***RestaurarVFPTela/Menu,senecessrio
FAZER<mainmenu.mpr>
_SCREEN.WINDOWSTATE=2
_SCREEN.Visible=.T.

Captulo1:ControlaroVFPAmbiente 23

***RetireEcrSplashquandoestiverpronto
respingoLIBERTAO
***StartApplicationloopdeeventos
READEVENTS

Umaalternativaparaatelainicial
SeasuaaplicaovaiestarusandoajanelaprincipaldoVisualFoxProcomoseudesktop,emseguida,
emvezdeutilizarumaformacomoumateladeabertura,quemaissimplesdeadicionarumobjectodirectamenteao
Screeneremovloquandoestiverpronto.OVisualFoxPro_ScreenobjetotemtantoAddObject()e
VFP
RemoveObject()mtodosquepodemserchamadosdedentrodeseusprogramas.
Tudooquenecessrioacriaodeumaclasserecipientequeincluioelementogrfico,equalqueroutra
controla,eadicionlodiretamenteparaatela.Umavezqueseuaplicativocriadoforconcluda,oobjeto
podesimplesmenteserremovido.Istomaissimplesdeimplementar,umavezquenonecessitaqueoecr
serdesligadonoarranque,comooseguintetrechodecdigomostra:

***Maximizaratela
COM_Screen
.WindowState=2
***AdicioneoContainer
SETCLASSLIBTOsplashfiles
.AddObject('CntSplash','xCntSplash')
***RelatriodeProgresso
COM.cntSplash.txtProcess
.Value='Bibliotecascarregamentodeclasse'
***Libscarregaroaplicativo
.Value='Dadosinitialising"
***ConfigurarDBC
***Configurarmenuseassimpordiante...
ENDWITH
.RemoveObject('CntSplash')
ENDWITH
***StartApplicationloopdeeventos
READEVENTS

(Nota:Estamosassumindoqueadefiniodeclasseincluiasconfiguraessuperior/esquerdaeuma
THIS.VISIBLE=.T.comandonocontinerInit()mtododemodoquenohnecessidadedeexplicitamente
tornaroobjetovisvel,oureposiolo,nocdigodoaplicativo.)

Comowallpaperseudesktop
Adicionandoumfundo(porexemplo,umlogotipodaempresa)paraodesktopdoseuaplicativopodeadicionarum
olhar"profissional"esentirasuaaplicaoVFP.Noentanto,nemsempretofcilcomoprimeiro
aparece.OprincpiobsicobastantefcilbastadefiniroImagempropriedadedaVisual
objeto_ScreendoFoxProparaobitmapnecessrio.
Oproblemaqueocomportamentopadro'telha'obitmap,seassuasdimensesnofazerexatamente
corresponderaotamanhodareadoecrdisponvelnaresoluoactualmenteseleccionada.Oresultadoque
oquefuncionaem,digamos,800x600resoluonoolhardiretamenteparamaisouparamenos
resolues.Almdisso,areadisponveldependesevoctemabarradeestadoligadooudesligado,
sevoctemummenuapresentadoesevoctiverbarrasdeferramentasancoradasouno.Portanto,afim

24 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

paraobtlodireito,parecequevocprecisasaberotamanhorealdareadetrabalhoemvrios
resoluesecriarumbitmapdetamanhoadequadoparacadapossibilidade.

Ento,comopossoobterotamanhodareaatual_Screen?
OVisualFoxProSCOLS()eSROWS()funesretornaronmerodecolunaselinhas
nareadatelaatual(combasenafontedeexibioselecionado).Assim,paradeterminar,empixels,a
tamanhodareadeexibioquevoctambmprecisausaroFONTMETRIC()funo,comosegue:

lnScreenHeight=SROWS()*FONTMETRIC(1,_SCREEN.FONTNAME,_SCREEN.FontSize)
lnScreenWidth =SCOLS()*FONTMETRIC(6,_SCREEN.FONTNAME,_SCREEN.FontSize)

Usandoessasfrmulasobtemososseguintesresultadoscomumnicomenulinhavisvel:

Tabela1.2.Heightsteladisponvelemvriasresoluescomconjuntodefontesdetelapara
10ptArial

Tela Barradestatus= Barradestatus=


EM FORA
Resoluo ancoradoTbar desencaixadoTbar
ancoradoTbar desencaixadoTbar
1024x768 646 678 670 702
800x600 478 510 502 534
640x480 358 390 382 414
Alarguradatela(amenosqueasbarrasdeferramentasseencontranapartelateraldatela)sempreamesma
comoaresoluohorizontal.Aoprojetarseuaplicativoquevocvai,naturalmente,sprecisa
usarumconjuntodevaloresdesdequevocsempreiriniciaraaplicaodamesmamaneira(noquedizrespeito
menus,barrasdeferramentasebarrasdestatus).
Sevocfosseagoraparacriarumasriedebitmaps,dimensionadoscorretamenteparacadaresoluo,vocpode
bastadefiniro_SCREEN.Picturepropriedadeparaoapropriadonaaplicaodearranque.
Eurealmenteprecisoparacriartodosessesbitmaps?
Bem,naverdade,arespostano,possivelmente!Humaestratgiaalternativa,emboraseusucesso
vaidependerdanaturezadaimagemquevocdesejaexibir.Vocpoderiasimplesmentecriarumaclasse
(combaseno IMAGEMbaseclass,chamado,porexemplo,aImgWallPaper)quetemasuaimagem
propriedadedefinidacomoumnicobitmap,esuaestiramentopropriedadedefinidacomo2(expandirparapreenchero
ummtodochamado'AdjustSize'echamloapartirdomtododeinicializaodestaclasse.Devesercodificada
controle).Adicionar
comoisso:

Comisso
.Altura =FONTMETRIC(1,_SCREEN.FONTNAME,_SCREEN.FontSize)*SROWS()
.Largura =FONTMETRIC(6,_SCREEN.FONTNAME,_SCREEN.FontSize)*SCOLS()
.Visible=.T.
ENDWITH

Agoraemsuaaplicaostartupvocsimplesmenteadicionarumobjetocombasenessaclassediretamentepara
atelaimediatamenteantesdeexecutarseus EVENTOSDOcomosegue:
_Screen.AddObject('OWallPaper','aImgWallPaper')

Captulo1:ControlaroVFPAmbiente 25

Aimagemserentoaprpriaautosizeparapreencherareadeteladisponveldandoumrealmente
aparnciaprofissionalparaasuaaplicao.Anicacoisaaobservarque,seomapadebitsno
simtrica,acriaodaimagem doestiramento=2podedarumaimagemdistorcida.Umasoluopossvel
autilizaode estiramento=1(isomtrica),quevaimanterapropororelativadooriginal
bitmap,masissonopodeinteiramentepreencheratelaquandoresized.Omelhorconselhoaqui
experimentar.

Abarradeferramentas'pegadinha!'
Umproblemacomousodepapisdeparedeemconjuntocombarrasdeferramentasqueatracaoedesatracao
umabarradeferramentasalteraareavisveldatela,masnootamanhodaimagem.Manusearoencaixedeum
barradeferramentasbastantesimplesumavezqueo_SCREEN.Resize()eventoacionadoapsabarradeferramentas
BeforeDock()evento,masantesoAfterDock()evento.Naverdade,orastreadoreventoindicaque
do
osfogoseventoResizeduasvezes!(Presumivelmente,issoparaqueatelaredimensionaquandoabarradeferramentas
movidodareadoecrprincipalparaabarradettulo,enovamentedepoisqueele,naverdade,acoplado).Entoseu
classeimagem'AdjustSizemtodo'podeserchamadoapartirdabarradeferramentasAfterDock()eventoparamanipular
encaixedeformalimpa,assim:

IFVARTYPE(_Screen.oWallPaper)='O'
COM_Screen
.LockScreen=.T.
.oWallPaper.AdjustSize()
.LockScreen=.F.
ENDWITH
FIMSE

Infelizmente,parecequedesencaixeumabarradeferramentasnodisparao_SCREEN.Resize()
eventoemtudo!Emboraatelarealmentefazresize,quandoumabarradeferramentasdesencaixado,onovotamanho
noestdisponvelparaqualquermtodoquepodeserchamadodedentrodabarradeferramentas.Nspensamosque
umerroporqueumachamadaexplcitaparaaimagemAdjustSizemtodo(deforadabarradeferramentas),aps
estedeveser
desancoragemforconcluda,recalculaotamanhocorretamenteeajustaaimagemdeformaadequada.Ns
notemumasoluosatisfatriaparaesteproblemaquenosejaparaevitarbarrasdeferramentasmveisemcasode
usandopapisdeparedequenosodefinidosdiretamentenaimagempropriedade.

Arrumarseuambientededesenvolvimento
UmdosperigosquevocpodeocasionalmenteencontraraodesenvolvimentonoVisualFoxPro
queumdosseusprogramasirfalhar.(Sabemosqueissoextremamenteraro,masestcertodeque
querealmenteacontececomalgumasoutraspessoasaolongodotempo.)Emumatalsituaotil
temumamaneirasimplesdelimparevoltaraopontodepartida.Nsgostamosdeusarumpouco
programachamado'ClearAll'paralidarcomissoparans,quegarantequetudoestdevidamente
fechadoelimpo.
Aprimeiracoisaqueesteprogramafazdesligarqualquermanipulaodeerro.Istoirpermitirnos
paraforaratravsdequaisquercomandosanmalos(comoaseleodeumdatasessionquenoexiste)
seminterrupoafinaldecontas,umavezqueesclarecerquenoseimportamrealmentecomerrosdequalquer
Mais!
26 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

**********************************************************************
*Programa :ClearAll.PRG
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Limpaoambientededesenvolvimento
**********************************************************************
lnCntLOCAL,lnCntUsed
ArraylocallaUsed[1]
***Desligueotratamentodeerrosporenquanto
ERRORON*

Emseguidansapenaslimparatelaepostarumajaneladeespera,antesderolarparatrsqualqueraberto
transaes:

***Telalimpa
CLARO
WAITWINDOW'Clearing...aguarde..."NOWAIT
***Reverterastransaes
IFTXNLEVEL()>0
FazerenquantoTXNLEVEL()>0
ROLLBACK
ENDDO
FIMSE

Agoraprecisamoslidarcomquaisqueralteraesnoconfirmadas.claroquenopossvelsaberquantas
formasnopodeseraberta,ouoquedatasessioncadaformulrioestrealmenteusando.Asoluo
usaracoleoFormsetrabalharatravsdatasessiondecadaformaderevertertodasastabelasem
quedatasessionefechlosantesdeliberaroprprioformulrio.

***ReverterTabelasefechlos
PARACADAloFormIN_SCREEN.FORMS
***DescubraoqueDatasessioneleestem
lnDS=loForm.DataSessionID
***Temquenenhumatabelaaberta?
lnCntUsed=AUSED(laUsed,lnDS)
IFlnCntUsed>0
SETDATASESSIONTO(lnDS)
***Seassimfor,revertertodasasalteraesnoconfirmadas
PARAlnCnt=1alnCntUsed
SELECIONAR(laUsed[lnCnt,2])
IFCURSORGETPROP('buffer')>1
=TABLEREVERT(.T.)
FIMSE
USAR
PRXIMO
FIMSE
***Eliberaraforma
loForm.Release()
PRXIMO

Tendoselivroudasformasagorapodemosfechartodasasrestantesmesaseseusassociados
bancosdedadoselimpartodososprogramasnamemria,variveisdememriaebibliotecas:

***Agorafecheoutrasmesasebancosdedados
TABELASfechartodas

Captulo1:ControlaroVFPAmbiente 27

TODOSOSDADOSFECHAR
***variveis
dememrialanamento,Procedimentos

***ebibliotecasdeclasse
LIMPARMEMRIA
LIMPARTUDO
PROCEDIMENTOSETTO
SETCLASSLIBTO

Comtudoissoidopodemosseguramenterestaurarajaneladocomandoedosistemapadro
menuelimpartodasasconfiguraesglobaisdefinidasusandoo ONcomandos:

***Obteromenudejaneladecomandoesistemadeback
AtivarajanelaCOMMAND
SETSYSMENUTODEFAULT
***configuraesglobaisLimpar
ONSHUTDOWN
ONERROR
ONKEY
ONESCAPE
ESPERAAPAGAR

Opassofinalparacancelartodososprogramasabertos(incluindoeste).Istonecessrioparaassegurar
quequaisquerformasquetmchamadodilogosmodaisestodevidamenteliberado:

***Cancelartodososprogramasabertos
CANCELAR

FechandoVFPparabaixo
AtagoratemosvindoaconcentrarnacriaoegestodoVisualFoxPro
meioambiente,noentanto,amaneiraemquevocencerrarVisualFoxProtoimportante.em
oambientedetempodeexecuo,existemduasmaneirasdeiniciaroprocessodeencerramento.primeiramente
atravsdautilizaodo limparoseventosdecomando,querdentrodeummenuounolanamentomtodo
deumformulrio.EmsegundolugaratravsdobotopadrodoWindowspertodaprincipalVisualFoxPro
janela.Felizmente,VisualFoxProfornecenoscomummanipuladorglobalparaaprximaparabaixo
processo,independentementesecomoeleiniciadoa ONSHUTDOWNcomando.

OqueumprocedimentodedesligamentoOn?
semelhanadeoutrossobreoscomandos,o ONSHUTDOWNcomandoimplementadoporummanipuladorespecialque
estforadoFoxProloopdeprocessamentodeeventosVisualnormal.Quandochamado,ocontrole
imediatamentetransferidoparaqualquercomando,oufuno,tenhasidoespecificadacomooalvo.
Estadelongeamelhormaneira(senoanicamaneira)paragarantirqueVisualFoxProfecha
limpasemoirritanteo"NopossvelsairVisualFoxPro"mensagem.

OquedesencadeiaumprocedimentodedesligamentoOn?
Ocomandoespecificadona ONSHUTDOWNexecutadosevoctentarsairdoVisualFoxPro,
clicandonoboto"Fechar"natelaprincipaldoVisualFoxPro,escolhendoSairno
MenudecontroleFoxPro,ouaoemitiro QUITcomandoemumprograma(ouocomando
janela!).Almdisso,eleseracionadosevoctentarsairdoWindows,enquantoVisualFoxPro

28 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

aberto.(ControleretornadaparaVisualFoxProeoespecificado ONSHUTDOWNprocedimento
executado.)

OquevaiparaumprocedimentodedesligamentoOn?
Oprocedimentochamadoporum ONSHUTDOWNcomandocontmqualquercoisaquevocpodelegalmente
colocaremumprogramaVisualFoxPro,comexceode suspenderou cancelarcomandos(ambos
dequeircausarumerro),mas,nomnimoeledevelidarcomasseguintesquestes:

Fechetodasastransaesabertas
Commitoureverterquaisqueralteraespendentesemtabelasouexibies
Fechetodasasformas(umformulriomodalabertaumadascausasdamensagem"Nopossvelsair')
EmitirumaclaraEventos(umativoeventosReadoutracausado"nopossoparar'
mensagem)
Restauraroambientededesenvolvimento(senoexecutarumaAPPou.exearquivo)OR
SaiadoVisualFoxPro(serodarumaAPPou.exearquivo)

OcomportamentoemVFP3.0foiqueumcomandoSAIRiriafecharaberto
formasmodaisecancelarqualquerReadeventosexistentes.Estanoa
Emambososcaso,aVerso5.0ou6.0.

Vocvainotarqueesseselementossoquaseidnticosaosquecolocamosemnossa
'ClearAll.prg'paralimparoambientededesenvolvimentoeocdigoquefoiutilizadoh
pode,compequenasmodificaes,serutilizadacomoabaseparaoprocedimentoencerrado.
Umatalmodificaoadeincluirumtesteparadeterminarseaexecuoactualmente
programafoirealmentechamadoapartirdodesenvolvimentoouambientesdetempodeexecuo.Esteumdosmais
algumascoisasparaasquaisdefendemousodeumavarivelPblico.Emnossainicializaodoaplicativo
Programaqueincluemoseguintecdigo:

***VerifiqueparaomodoRun
LIBERTAOglExeRunning
glExeRunningPBLICO
glExeRunning="EXE"$UPPER(SYS(16))OR'APP'$UPPER(SYS(16))
IFglExeRunning
***Faaocompletostartup,telaSplash,loginetc
OUTRO
***Comecesenomododedesenvolvimento
FIMSE

Enquantovocrealmentenoprecisadeumavarivelpblica(avarivelprivadonormal,naverdade,
trabalharaqui)nsgostamosdedefiniressasvariveis"sistemas"deformaexplcitaetratloscomoexceesa
asregrasgerais.Tendodefinidoavarivelagorapodemosusloemnossarotinadedesligamentopara
detemineserealmentesairdoVisualFoxProousimplesmenteparacancelaroprogramaatualcomo
segue:

IFglExeRunning
SAIR
OUTRO

Captulo1:ControlaroVFPAmbiente 29

CANCELAR
FIMSE

Algumaspessoastambmdefendemcolocandoum'Temcerteza'caixademensagemnodesligamento
Procedimentoenquantoissoumaquestodeestilo,nogostodisso!Parecenosquenopodehaver
nadamaisirritanteparaumusurioqueacabouescolhidoespecificamente'Sair'doqueserperguntadoseeles
realmenteaintenodefazlo.Seasuainterfacedeusurioprojetadodetalformaqueumusuriopode
"Acidentalmente"encerraroaplicativo,emseguida,teramos,muitorespeitosamente,sugerirquevoc
podeprecisarderevisitarodesigndainterfacedousurio.
30 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo2:FuneseProcedimentos 31

Captulo2
FuneseProcedimentos
"Podemosperdoaraumhomemparafazerumacoisatil,contantoqueelenoadmirlo.A
nicadesculpaparafazerumacoisaintiladmirlaintensamente."("ORetratode
DorianGray",deOscarWilde)

Quantasvezesvocherdouumaaplicaodeoutrodesenvolvedorqueusou
vintelinhasdecdigoquandoumoudoisteriasidosuficiente?Quantasvezesvoc
aradoatravsdemilhasdecdigoeseperguntouporqueelenofoidivididoemseparado
mtodosparalidarcomfuncionalidadediscreta?Umabibliotecabemabastecidodefunesreutilizveis
reduzonmerodelinhasdecdigonecessriaspararealizarumadeterminadatarefa.Almde
reduzindocdigodemtodononveldainstncia,funeseprocedimentosnomesdescritivos
tornarocdigomaisautodocumentado.Nestecaptulovamospartilharalgumasdasfresco
funesquedescobrimosaolongodosanos,bemcomoalgumasarmadilhasqueatentepara.
TodoocdigonestecaptuloestcontidonoarquivodeprocedimentoCH02.PRGna
subdiretriocomomesmonome.

Comodevemosproceder?
EmversesanterioresdoFoxPro,asaplicaesforamlimitadasaumnicoarquivodeprocedimentoactivaemqualquer
Tempo.Issosignificavaquetodasasfunesdefinidaspelousurioeprocedimentoscomumenteutilizadosforam
nicoarquivo.ComVisualFoxPro,acapacidadedeterprocedimentodemltiplosarquivosativosemumdado
mantidosem
tempo,proporcionamuitomaisflexibilidade.Taisprocedimentospodemagoraseragrupadasdemaneiralgica,por
funcionalidade,emdiferentesficheirosprocedimentoquepodesercarregadodeformaincrementalconformenecessrio.o
desvantagem,claro,queosarquivosdeprocedimentosocarregadosnamemriaporVisualFoxProemantido
atquesejaexplicitamenteliberado.Istopodenoseromelhorusodessepreciosorecurso.
Felizmente,tambmpossveldefinirclassesdeprocedimento.Asfunesindividuaisque
antesteriasidomantidoemumarquivodeprocedimentopodeagorasetornarmtodosdeumaclasse.este
abordagemtemavantagemdeque,quandodefinidovisualmentenoClassDesigner,todasasfunesem
oprocedimentopodeserperfeitamentevistosobaguiamtodosdafolhadepropriedades.Procedimento
asclassesquecontmfuncionalidadesespecficaspodemserlargadosformasqueexigemessa
funcionalidade.Asegundagrandevantagemqueumaclasseprocedimentopodesersubclassificadosparaaqueles
situaesespeciais,quandoafuncionalidadepadrodeveseraumentada.
Aabordagemquegostaumacombinaodestasduasabordagens.Recomendamosautilizaode
umarquivodeprocedimentoparafunesverdadeiramentegenricos(ouseja,aquelesquesousados,inalterada,por
diferentesaplicaes).Porexemplo,onossoarquivodeprocedimentocontmumaNewIDfunopara
muitos
geraodechavesprimriassubstituto,umSetPathfunoparadefinirocaminhoparaaaplicaoeuma
algumasfuneschavequeVisualFoxProdeveter,masnoofaz.Doisexemplosdetais
funessoasStr2ExpeExp2Strfunes(usadomaisadiantenestecaptuloEstasfunes,como
osnomessugerem,soutilizadasparaconvertercadeiasdecaracteresparaosvaloresdeoutradadosespecificado
tipoeviceversa.

32 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SeparadosClassesProcedimentocontmfuncionalidadeespecficadoaplicativo.Porexemplo,uma
aplicaodecontabilidadepodeexigirvriasfunesparacalculartotaisfiscaisefaturas.o
ProcedimentosdeContabilidadedeclassepodesercolocadoemqualquerformulrioquerequeressasfunesou
podeserinstanciadocomoumobjetoNveldeAplicao.evidentequeestasfunesnosogenricos,nem
soelesatmesmoexigidoportodaaaplicao.Agrupandoosemumnicoprocedimento
classe,podemosfazerestafuncionalidadedisponvelparaaspartesespecficasdoaplicativoque
exigiremsemcomprometerorestodaaplicao.

Parmetros(umaparte)
TemostodososparmetrosusadosextensivamenteemFoxPro,masemVisualobjetodoFoxProorientada
meioambiente,parmetrosassumiramumanovaimportnciacomooprincipalmeiode
implementaodemensagensaprpriaalmadeumaaplicaoOO!(Nstemosmaisadizersobre
esteassuntomaistarde!)

Porreferncia,porvalor?
Osparmetrossopassadosporrefernciaouporvalor.Quandoumparmetropassadoparauma
funoouprocedimentoporreferncia,todasasmudanasfeitasaoseuvalornocdigodechamadaso
refletidonovalororiginalnoprogramadechamada.Poroutrolado,quandoumparmetropassado
porvalor,ocdigodechamadapodealteraressevalor,masovalornoprogramadechamadapermanece
inalterada.
VisualFoxProinterpretaocdigoqueestsendochamadopelomecanismopeloqualosparmetrosso
passado.Ento,quandoasintaxechamarparececomisso:
luRetVal=CallMyFunction(param1,param2)

VisualFoxProtrataissocomoumachamadadefunoepassaosparmetrosporvalor.Contudo
seomesmocdigochamadoassim:
FAZERCOMCallMyFunctionparam1,param2

emseguida,VisualFoxProtrataissocomoumachamadadeprocedimentoepassaosparmetrosporreferncia.
Aregradecodificaoantigaquea"Funodevesempreretornarumvalor"noverdadenoVisual
FoxPro,masfazsentidoquandoasintaxedechamadaconsiderado.
Vocpodealteraressecomportamentopadrodeduasmaneiras.Umamaneira:
UDFPARMSconfiguradoparafazerrefernciaouSETUDFPARMSavalorizar

Noentanto,noconsideramosestaumaboaidia,porqueafetaamaneiracomotodasasfunesem
seuaplicativointeirolidarcomosparmetrosquesopassados.(Nuncaumaboaidiausarum
soluoglobalpararesolverumproblemalocal).Nestecaso,humasoluosimples,porque
parmetrospodemserpassadosporvalorexplicitamenteapenasquandocolocadasentreparnteses.Assim:
FAZERCOMCallMyFunction(param1),(param2)

Captulo2:FuneseProcedimentos 33

passaosparmetrosporvalor,mesmoqueasintaxeutilizadanormalmentefariacomqueeles
aserpassadoporreferncia.Parapassarparmetrosexplicitamenteporreferncia,simplesmenteprecedao
parmetrocomosmbolo"@".(Esta,alis,anicamaneiradepassarumamatrizinteiroparauma
procedimento,funooumtodo).Ento,nstambmpodemosfazeranossachamadadefunoepassarasua
parmetrosderefernciacomoeste:
luRetVal=CallMyFunction(@param1,param2@)

Comoeuseioquefoipassado?
Hduasmaneirasparaumafunoparadeterminarquantosparmetrosforampassadosparaele.o
PARMETROS()devolveonmerodeparmetrosqueforampassadosparaomais
recentementechamadofunoouprocedimento.Istopodedarresultadosinesperadosumavezquereiniciadocada
tempodeumafunoouprocedimentochamado.Maisimportante,eletambmrepostopeloquesofunes
nochamadoexplicitamente,comoONKEYLABELrotinas.
Amelhorformadedeterminaronmerodeparmetrosforampassadosparaumafunoadeutilizaro
PCOUNT()funo.Estasempredevolveonmerodeparmetrosqueforampassadosparao
atualmenteemexecuodecdigo.Salveseummontededorecabelosdesnecessriopuxandopelosempre
usandoPCOUNT()paradeterminaronmerodeparmetrospassados.

Comodevoposicionarmeusparmetros?
Omelhorconselhoqueseumafunotemparmetrosopcionais,vocdevecoloclasna
fimdalistadeparmetros.PCOUNT()podeentoserusadonafunoparadeterminarseou
Noosparmetrosopcionaisforampassadospermitindoafunodetomarasmedidasadequadas.
VocpodetirarproveitodofatodequeVisualFoxProsempreiniciaosparmetrosdecomo
falsalgica.Atravsdacriaodesuafunoparaesperarumafalsalgicacomopadro,vocpodeinvocar
afunosempasslatodososparmetros.Ento,noscasosemquevocquerum
comportamentoalternativo,bastainvocarafuno,passandoalgicaverdadeira.

Comopossodevolvervaloresmltiplosdeumafuno?
Claro,retornandovaloressimplesmenteoinversodapassagemdeparmetroscomumapegadinha!.
Enquantovocpodefacilmentepassarvriosparmetrosparaumafuno,nohnenhummecanismobviopara
retornodevriosvalores!OcomandoRETURNspermiteumnicovaloraserpassado
voltarparaoprogramadechamada.
Umasoluopassarvriosvalorescomoumacadeiadelimitadaporvrgulas.Istoumpoucoconfuso,
noentanto,comovocvaiprecisarparaconverterseusvaloresemformatodecaractereparaconstruiroretorno
cordae,emseguida,analisarosvaloresindividuaisdenovonocdigoderecepo.
Outrapossibilidadedefinirtodososvaloresquepretendepovoadaspelafunocomo
Privadasvariveisnoprogramadechamada.Comotal,elasestarodisponveisparaqualquerfunoou
processoquedenominadoposteriormenteequepodemserpreenchidosdirectamente.Noentanto,esta
especficasnemfcildemanterenorealmenteumaboasoluo.
Amelhorpossibilidadecriarumamatriznocdigodechamadaparaosvaloresderetornoe,emseguida,
passaressamatrizporreferncia.Afunochamadapodeentosimplesmentepreencheramatrizea
Osvalorestambmestarodisponveisnoprogramadechamada.Estevivel,pelomenos,eestava

34 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

provavelmenteomtodomaiscomumdelidarcomoproblemaantesdaintroduodoVisual
FoxPro.
MaisumavezVisualFoxProtornouavidamuitomaisfcil.Retornandovriosvaloresdeuma
UDFfcilsevoccriareusar,umaclassedeparmetro.AnossabaseadanaLinhabaseclasse
nomeadoxParameters.VocpodeencontrlonabibliotecadeclassesCH02.VCX.Tudoqueprecisaum
propriedadedematrizcostume,aParameters,paramanterosvaloresderetornoeestalinhadecdigoemsua
INIT():

LPARAMETERStaArray
ACOPY(taArray,This.aParameters)

Afunodefinidapelousuriopode,ento,simplesmentepreencheroseuprprioarraylocalcomosvaloresqueela
precisaretornarecriaroobjetodeparmetroemtemporealepreenchermatrizdoobjeto
propriedadecomumanicalinhadecdigo:
RETURNCREATOBJECT('xParameters',@laArray)

Quetalusarnomeadoparmetros?
Oobjetodeparmetrodiscutidoacimapassaparmetrosporposio,damesmaformaque
VisualFoxPro.EmboraVisualFoxPronaverdadenosuportaoconceitodechamada
parmetros,vocpode,naverso6.0,useoAddProperty()mtodoparaadicionarparmetrosnomeadospara
seuobjeto,criandoumapropriedadeparacadaparmetroouvalorquedesejatransferir
Mesmoquandoseutilizaestaabordagem,nohnecessidadedesecriarumaclasseespecialparaoparmetro
objeto.Elepodesercriadoemtemporealusandoumbaseclassleves,comoLinhaouSeparatorcomo
osseguintesespectculostrechodecdigo:

oParamLOCAL
oParam=CREATEOBJECT('linha')
COMoParam
.AddProperty("Nome","ChristineJohannson")
.AddProperty("Idade",34)
.AddProperty("Sex","Feminino")
ENDWITH
RETURNoParam

Pararecuperarosvaloresdestaformaoseucdigodechamadasimplesmenteatribuirovalorderetornode
afunochamadaparaumarefernciadeobjetoelersuaspropriedadeslocalmente:

LOCALoRetVal
oRetValCallMyFunction=()
lcName=oRetVal.Name
lnAge =oRetVal.Age
lcSex =oRetVal.Sex

Detodasaspossibilidadesdiscutidoatagora,nsgostamosesteomelhor!
Captulo2:FuneseProcedimentos 35

Passandoparmetrosopcionalmente
Humimportantebenefcioladoparaacapacidadedeusarparmetrosnomeados.Istotornase
especialmenteimportantequandoafunorecebeumgrandenmerodeparmetros,muitosdosquaisso
opcional.Porexemplo,umafunoparadefinirfontespodetermuitosparmetros(nome,tamanho,negrito,
itlico,sublinhado,tachadoeassimpordiante).Umaverificaosimplespara:
PEMSTATUS(toParameterObject,'FontName', 5)

determinaclaramenteseounoumparmetroespecficofoiaprovada.estaabordagem
removeatarefatediosadecontagemvrgulasnoprogramadechamada(bemcomoanecessidadede
lembraraordemespecficanaqualosparmetrossoesperadospelafunochamada).o
funodotempodecorridoaseguirmostracomoumobjectoutilizandoparmetrosnomeadospodemserusadaspara
retornarvriosvalores.

funesdedataehora
VisualFoxProtemvriosdandyacessvel,construdoemfunesparaasdatasdemanipular.o
funesabaixoilustramaformacomoelespodemserusadosparaexecutaralgumasdasfunesmaiscomuns
necessriaquandoselidacomdatasemseusaplicativos.

Tempogasto
BastasubtrairumexpressoDateTimeapartirdeoutrodlheotempodecorridoeste
Boa.InfelizmenteVisualFoxProlhedesseresultadocomoonmerodesegundosentreo
doisissoruim.Essevalorraramentediretamentetil!Vocpodeusarestepequenoconjuntodefunes,
quecontamcomooperadormdulo(% ),paracalcularascomponentesdetempodecorridoemdia,
horas,minutosesegundos.

GetDaysFuno(tnElapsedSeconds)
RETURNINT(tnElapsedSeconds/86400)

GetHoursFuno(tnElapsedSeconds)
RETURNINT((tnElapsedSeconds%86400)/3600)

GetMinutesFuno(tnElapsedSeconds)
RETURNINT((tnElapsedSeconds%3600)/60)

GetSecondsFuno(tnElapsedSeconds)
RETURNINT(tnElapsedSeconds%60)

Claro,existemaisdeumamaneiradeesfolararaposa.Voctambmpodeusarumanicafuno
pararetornarumarraycontendootempodecorridoposicionalmente,comdiascomoseuprimeiroelemento
pormeiodesegundos,comoseuquartoassim:

FUNOObterTempoDecorrido(tnElapsedSeconds)
LOCALlaTime[4]
laTime[1]=int(tnElapsedSeconds/86400)
laTime[2]=int((tnElapsedSeconds%86400)/3600)
laTime[3]=int((tnElapsedSeconds%3600)/60)
laTime[4]=INT(tnElapsedSeconds%60)
RETURNCreateObject('xParameters',@laTime)

36 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Sepreferirnomeadoparmetrosparaavariedadedeposio,ocdigoaseguirrealiza
atarefa:

FUNOObterTempoDecorrido(tnElapsedSeconds)
loObjectLOCAL
loObject=CREATEOBJECT('Line')
COMloObject
.AddProperty('Ndays',int(tnElapsedSeconds/86400))
.AddProperty('NHours',INT((tnElapsedSeconds%86400)/3600))
.AddProperty('NMins',int((tnElapsedSeconds%3600)/60))
.AddProperty('NSecs',Int(tnElapsedSeconds%60))
ENDWITH
RETURNloObject

Alternativamente,sevocsimplesmenteexigirumacadeiaquecontmotempodecorridoempalavras,voc
podeapenasreduzilaaumanicalinhadecdigo!
FUNOObterTempoDecorrido(tnElapsedSeconds)
RETURNPADL(INT(tnElapsedSeconds/86400),3)+'Days'
+PADL(INT((tnElapsedSeconds%86400)/3600),2,'0')+'Hrs'
+PADL(INT((tnElapsedSeconds%3600)/60),2,'0')+'Min'
+PADL(INT(tnElapsedSeconds%60),2,'0')+'Sec'

Dataempalavras
Convertendoumvalordeformatodedataemtextopodeserumnegciocomplicado,especialmentequandovocest
escreveraplicaesinternacionais.VisualFoxProtornaessatarefamuitomaisfcilcomasuanativa
MDY(),CMONTH(),CDOW(),MONTH(),Dia()eYEAR()funes,paracitarapenasalguns.
Verso6.0,comasuacapacidadedeusardatasrigorosos,tornaessatarefaaindamaisfcil.Osseguintes
funoforneceumexemplodecomousaressasfunes.

DateInWordsFUNO(tdDate)
RETURNCDOW(tdDate)+','+MDY(tdDate)

Noentanto,afunoacimaenumeradosnoiranexarosufixoordinalparaapartedodiade
adata.Seseuaplicativorequeressessufixosaoformataradataempalavras,useo
formamaislongadafunolistadaabaixo.Vocpodeatextrairapartequecalculao
sufixoecolocloemumafunochamadaMakeOrdinal.Elepode,ento,serinvocadosemprequeprecisar
paraformatarumdeterminadonmeroncomoensimo.

DateInWordsFUNO(tdDate)
LOCALlnDay,lnNdx,lcSuffix[31]
***Inicializarsufixoparaodia
lnDay=DAY(tdDate)
lnNdx=10%lnDay
SENOENTRE(lnNdx,1,3)
lcSuffix='th'
OUTRO
SEINT(lnDay/10)=1
lcSuffix='th'
OUTRO

Captulo2:FuneseProcedimentos 37

lcSuffix=SUBSTR('Stndrd',(2*lnNdx)1,2)
FIMSE
FIMSE
RETURNCDOW(tdDate)+','+CMONTH(tdDate)+
''+ALLTRIM(STR(lnDay))+lcSuffix+
','+ALLTRIM(STR(ANO(tdDate)))

calculandoIdade
Calcularaidadeaindamaiscomplicadodoquecalcularotempodecorrido.Issoocorreporquemesesno
contmomesmonmerodediasecadaquartoanoumanosalto.Afunoabaixo
calculaaidadeemumadeterminadadataeretornaovalorcomoumastringformatadacontendoonmero
deanosemeses.Elepodeserfacilmentemodificadopararetornarosvaloresemumobjetodeparmetroscomo
oElapsedTime()funolistadaacima.

FUNOCalcAge(tdDob,tdBaseDate)
***DataBasePadroparaHoje,sevazia
IFTYPE("tdBaseDate")#"D"ouvazio(tdBaseDate)
tdBaseDate=DATE()
FIMSE

lnYrsLOCAIS,lnMth,lcRetVal,lnBaseYear,lnBaseMnth
lnYrs=ANO(tdBaseDate)ANO(tdDob)

***Calculeaniversriodesteano
ldCurBdy=CTOD('^'+STR(ANO(tdBaseDate))+''+
PADL(MS(tdDob),2,'0')+''+
PADL(DIA(tdDob),2,'0'))

***Calcularaidade
IFldCurBdy>tdBaseDate
lnYrs=lnYrs1
lnMth=12(MS(tdBaseDate)MS(tdDob))1
OUTRO
lnMth=MONTH(tdBaseDate)MS(tdDob)
FIMSE
***CadeiadesadaFormat
lcRetVal=PADL(lnYrs,4)+"Anos",+PADL(lnMth,2,'0')+"Ms"+
IIF(lnMth=1,"","S")
RETURNALLTRIM(lcRetVal)

Quedataasegundaterafeira,emOutubrode2000?
Estaumafunopoucoprticoquepodeserutilizadoparacalcularadataexactadefriasnumdado
ano.Porexemplo,nosEstadosUnidos,Thanksgivingsemprecainaquartaquintafeiraem
Novembro.Outroexemploqueencontramosrecentementefoiqueoanolectivoparaasescolas
easuniversidadessemprecomeanaprimeirasegundafeiraemagosto.Acapacidadedecalcularo
datasreaisparaessesdiasdefinidoessencialemqualqueraplicaoquerequerplanejamentodeum
calendrioanual.

38 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

**********************************************************************
*Programa :nthSomeDayOfMonth
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Retornaadatadeumtipoespecficodediaporexemplo,a
* :Segundaterafeira,emNovembrode2001
* :NthSomedayOfMonth(4,3,7,2000)devolveadatade
* :3quartafeiraemJulhodoano2000
*TnDayNumParmetros.::Nmerododia1=Domingo7=Sbado
* :TnWhich:Qualdeencontrar1,2,etc.
* : Setnwhich>onmerodestetipodedia
* : noms,oltimodevolvido
* :TnMonth:Nmeromsparaencontrarodia
* :tnYear :Anoemqueparaencontrarodia
**********************************************************************
FUNOnthSomedayOfMonth(tnDayNum,tnWhich,tnMonth,tnYear)
ldDateLOCAL,lnCnt

***Comecenoprimeirodiadomsespecificado
ldDate=DATE(tnYear,tnMonth,01)

***Encontreoprimeirododiadasemanaespecificado
FazerenquantoDOW(ldDate)#tnDayNum
ldDate=+1ldDate
ENDDO

***Encontreoespecificadoumdestes...porexemplo,2,3,ouoltimo
IFtnWhich>1
lnCnt=1
FazerenquantolnCnt<tnWhich
lnCnt=+1lnCnt
***Avanarumasemanaparaobteroprximoumdelesnoms
ldDate=ldDate+7
***Serqueestamosaindanomscorreto?
IFMS(ldDate)#tnMonth
***Seno,puledevoltaparaoltimodestesencontramosesair
ldDate=ldDate7
SADA
FIMSE
ENDDO
FIMSE

RETURNldDate

Acriaodeumcronogramadepagamento
Outroproblemainteressanteodacriaodeumcalendriomensal.Tomemos,porexemplo,um
cronogramadepagamentosmensaisaseremrecolhidosatravsdedbitodirectodacontacorrentedeumdevedor.
bvioqueestespagamentosnopodemserrecolhidosemdomingosouferiados.Elestambmnopodemser
recolhidosmaiscedodoqueodiaespecificadoquandoaprogramaoprimeiroconfigurar.Istocolocaalguns
problemasinteressantesseadatadesementeinicialparaohorrioentreo28 eo31 stde
oms.Assim,nestecaso,bastausaroGOMONTH()funopoderetornarum
datainaceitvel.
Essafunomanipulafinsdesemana,feriadoseGOMONTH()epressupequevoctenha
criadosuatabeladefriascomduascolunas:umaparaadataeumparaonomedo
Captulo2:FuneseProcedimentos 39

feriado.Umndicenadatadefriastambmdesejvel.Tambmtenhaemmenteque,parasertil,este
tabeladoferiadodeveconter,nomnimo,osferiadosparaesteanoenoprximoano.

FUNOMonthlySchedule(tdStartDate,tnNumberOfMonths)
laDateslocal[1],lnCnt,ldDate,llok,llUsed

***Certifiquesedequetemabibliotecadeclasseloaded
SE'CH02'$SET('CLASSLIB')
***Nofazernada...bibliotecadeclassecarregada
OUTRO
SETCLASSLIBTOCH02ADITIVO
FIMSE

***Certifiquesedequetemosatabeladeferiadosdisponveis
SE!Utilizados('Feriados')
Holidaysusoem0
llUsed=.F.
OUTRO
llUsed=.T.
FIMSE
HolidaysSELECIONAR
SETPARAdHoliday

PARAlnCnt=1atnNumberOfMonths
***Queremosretornaradatapassadacomodata[1]
IFlnCnt>1
ldDate=GOMONTH(tdStartDate,lnCnt1)
OUTRO
ldDate=tdStartDate
FIMSE
***AgoratemosqueverificarparatercertezadequeGoMonthnonosdeudevoltaumdia
***Queanteriordatadesemente...nopodefazerumdbitodirectoperanteo
***Especificadoouseja,data,dia28doms
SEDIA(tdStartDate)>28
SEENTRE(DIA(ldDate), 28,DIA(tdStartDate)1)
ldDate=+1ldDate
FIMSE
FIMSE
llok=.F.
DoWhile!Llok
***Seadataatualforumsbado,irasegundafeira
IFDOW(ldDate)=7
ldDate=+2ldDate
OUTRO
***Seadataatualforumdomingo,irparaasegundafeira
IFDOW(ldDate)=1
ldDate=+1ldDate
FIMSE
FIMSE
***OK,agoraverificarparaferiados
SE!SEEK(ldDate,'Holidays','dHoliday')
llok=.T.
OUTRO
ldDate=+1ldDate
FIMSE
ENDDO
laDatesDIMENSO[lnCnt]
laDates[lnCnt]=ldDate

40 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ENDFOR

SE!LlUsed
USOEMHolidays
FIMSE
RETURNCreateObject('xParameters',@laDates)

Quedatadedezdiasteisapartirdehoje?
Umproblemaumtantosimilarcomocalcularumadataemqueumnmeroespecificadodenegcios
diasapartirdeumadeterminadadata.Talcomoacontececomoexemploanterior,esteassumeaexistnciadeumferiado
tabelaquetantoregioeaplicaoespecfica.

BusinessdaysFuno(tdStartDate,tnNumberOfDays)
lnCntLOCAL,ldDate,llok,llUsed

***Certifiquesedequetemosatabeladeferiadosdisponveis
SE!Utilizados('Feriados')
Holidaysusoem0
llUsed=.F.
OUTRO
llUsed=.T.
FIMSE
HolidaysSELECIONAR
SETPARAdHoliday

ldDate=tdStartDate
PARAlnCnt=1atnNumberOfDays
ldDate=+1ldDate
llok=.F.
DoWhile!Llok
***Seadataatualforumsbado,irasegundafeira
IFDOW(ldDate)=7
ldDate=+2ldDate
OUTRO
***Seadataatualforumdomingo,irparaasegundafeira
IFDOW(ldDate)=1
ldDate=+1ldDate
FIMSE
FIMSE
***OK,agoraverificarparaferiados
SE!SEEK(ldDate,'Holidays','dHoliday')
llok=.T.
OUTRO
ldDate=+1ldDate
FIMSE
ENDDO
ENDFOR

SE!LlUsed
USOEMHolidays
FIMSE

RETURNldDate

Captulo2:FuneseProcedimentos 41

Gotcha!formatodedatarigorosaevistasparametrizadas
formatoSTRICTDATEdoVisualFoxProespecialmentereconfortantecomoespectrodomilnio
bugaparecergrandenafrentedens.Pelomenoscomoestamosescrevendoeste.H,noentanto,uma
pequenoerroquevocdeveestarciente.Sevoctiver SETSTRICTDATEPARA2etentarabriruma
vistacomparmetrosquelevaumadatacomoparmetro,vocvaiestaremapuros.Seavista
parmetronofordefinidoounoestnoescopoquandovocabreoureconsultaavista,oamigvel
pequenacaixadedilogopedindoparaoparmetrodevistanovaiaceitarqualquercoisaquevocentra.Ser
manterdizendoquevocentrouumaconstantededata/datetimeambgua.
Asoluogarantirqueoseuparmetrodevistadefinidaenoescopoantesdetentar
abertasoureconsultaavista.Istosignificaque,seoseupontodevistapartedoambientededadosdeumformulrio,
sua NoDataOnLoadpropriedadedeveserdefinidaparaevitaracaixadedilogocomooformulriocarregado.
Aoutrasoluo,definindoSTRICTDATEa0e,emseguida,voltaa2,norecomendado.Como
jmencionado,usandoumasoluoglobalparaumproblemalocalumpoucocomo
golpearvoacomumamarreta.

Trabalhandocomnmeros
ClculosmatemticostersidotratadomuitobemdesdeosdiasdoEniaceManiac,
excetoparaobugnotvelnocoprocessadormatemticoPentium.surgemosproblemasmaiscomuns
porquemuitosclculosproduzirresultadosirracionais,comonmerosquecarregamporum
nmeroinfinitodecasasdecimais.errosdearredondamentosoimpossveisdeevitar,porqueacomputao
exigeestesnmerosserrepresentadanumaformafinita.Oestudodeofertasdeanlisenumrica
comaformademinimizaresseserros,alterandoaordememqueasoperaesmatemticasso
realizada,bemcomoofornecimentodemtodostaiscomoomtodotrapezoidalparacalculararea
sobacurva.Adiscussodestetpicoestalmdoescopodestelivro,maspodemosdar
lhealgumasdicasetruquesparaestaratentoquandosetrabalhacomnmerosemsuaaplicao.

Convertendonmerosparastrings
Convertendonmerosinteirosparacordasbastantesimples. ALLTRIM(STR(lnSomeNumber))
vailidarcomaconversoseointeirocontmdezdgitosoumenos.Seointeirocontmmais
dedezdgitos,estafunoirproduzirumacadeianoformatodenotaocientficaamenosquevoc
especificarocomprimentodoresultadodecadeiacomoosegundoparmetro.Aoconvertervaloresnumricos
contendopontosdecimaisouvaloresdemoeda,provavelmentemelhorusaroutrafuno.
EmborapossaserconseguidautilizandooSTR()funo,difcilescreverumgenrico
rotinadeconverso.Paraconverteronmerointeirovocdeveespecificarocomprimentototal
donmero(incluindoopontodecimal)eonmerodedgitosparaadireitadodecimal
ponto.Assim STR(1234.5678)irproduzir'1235'comoseuresultado,eparaobteraconversocorreta
vocdeveespecificar STR(1234.5678,9,4).
NoVisualFoxPro6.0,oTRANSFORM()funofoiestendidoparaque,quandochamado
semquaisquerparmetrosdeformatao,elesimplesmenteretornaovalorpassadocomooseuequivalente
cadeiadecaracteres.Assim TRANSFORM(1234.5678)retornarcorretamente"1234.5678".
EmtodasasversesdoVisualFoxPro,vocpodeusar ALLTRIM(PADL(lnSomeNumber,32))
paraobteromesmoresultado(desdequeocomprimentototaldelnSomeNumbermenordoquetrintaedois
dgitos).

42 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Gotcha!clculosqueenvolvemdinheiro
Estepodemordersevocnoforcuidadoso.Tenteistonajaneladecomandoevocver
oquequeremosdizer.
?($1000/3)

retornaoresultadoesperadode333.3333jqueosvaloresdemoedasosemprecalculadosaum
precisodequatrocasasdecimais.Contudo,
?($1000*(1/3))

retorna333.3000,quenoumresultadomuitopreciso!Especialmentequandovocconsideraro
resultadodoclculonumricoequivalente:
DECIMALSdefinidopara4
?(1,000*(1/3))

retorna333,3333.Aprecisorealdoresultadoapresentadodependedadefiniode
SETDECIMALS,emboraoresultadorealmentecalculadopara8lugaresporpadro.
Amoraldestahistriaquevaloresdemoedadevesempreserconvertidoparanumricoantes
eutilizlosemoperaesaritmticas.AsfunesMton()eNTOM()soessenciaisneste
cenrio,emboraatentepararesultadosinesperadossevocnoconverteremambosossentidos!
?(Mton($1000)*(1/3))

exibe333.333333mesmocomdecimaisdefinidopara2.Enquanto
?NTOM((Mton($1000)*(1/3)))

finalmenteconsegueoresultadoesperadode333,3333.

funesdecadeia
VisualFoxProtemvriasfunesseqnciademanipulaonativaparalidarcomquasetudo
oquepodeprecisar.ALLTRIM()pararemoveresquerdaedireitaespaos,PADL()eAPRD()
paraaesquerdaeaalmofadadireitaeSTRTRAN()eCHRTRAN()parasubstituircaracteresindividuaisdentrodeum
corda.Masvocsabiaquevocpodeusarestalinhadecdigo:
cString1cString2cString3

pararealizaramesmacoisacomoesta?
RTRIM(cString1)+RTRIM(cString2)+RTRIM(cString3)

Gotcha!concatenao
Mesmoseastabelasemsuaaplicaonopermitemvaloresnulos,vocaindapodeprecisarparalidarcom
eles.Muitasvezes,asinstruesSQLusandoassociaesexternasresultaremumaoumaiscolunasquecontm
valoresnulos.Istopodeserproblemticonoscasosemquevocpodequererexibirumconcatenado
valorapartirdeumconjuntoderesultados,porexemplo,emumalistasuspensa.Tenteistonajaneladecomando:
Captulo2:FuneseProcedimentos 43

c1='YadaYadaYada"
c2=NULL.
?+C2c1

Comovocpoderiaesperar,VisualFoxProreclamadeumaincompatibilidadedetipooperador/operando.
Se,noentanto,vocfazerissoemvezdisso:

?ALLTRIMC1+(C2)

vocvaiver .NULL.apresentadonoecrVisualFoxPro.
Nenhumerro,apenas.NULL.SevocnoatenderavaloresnulosusandoNVL()parainterceptarparaeles,
vocpodeencontrarestecomportamentoumpoucodifcildedepuraoquandoocorreemsuaaplicao.Ns
comcertezafezaprimeiravezqueencontramosestecomportamento!

Conversoentrecadeiasedados
OsseguintessoexemplosdefunesqueVisualFoxPronotem,masemnossaopinio
definitivamentedeveter.Nsmantlosemnossoarquivodeprocedimentogeralparatodososfins,porquensusamos
loscomtantafrequncia.
Combinaoelistacaixasdearmazenarsuaslistasinternascomovaloresdecadeia.Ento,quandovocprecisausar
estesparaatualizaroubuscarvaloresdeoutrostiposdedados,vocprecisaconverteressasstringsao
tipodedadosapropriadoantesquevocpossauslos.Aprimeiradestasfunesusadaparafazer
sisso:

FUNOStr2Exp(tcExp,tcType)
***Converteracadeiapassadaparaotipodedadospassada
LOCALluRetVal,LCType

***Retireaspasduplas(sehouver)
tcExp=STRTRAN(ALLTRIM(tcExp),CHR(34),"")
***Senenhumtipopassadomapaparatipodeexpresso
LCType=IIF(TYPE('tcType')='C',UPPER(ALLTRIM(tcType)),TYPE(tcExp))
***Conversodecaracteresparaotipocorreto
DOCASO
CASEINLIST(LCType,'I','N')AND
INT(Val(tcExp))==Val(tcExp) &&Integer
luRetVal=INT(Val(tcExp))
CASEINLIST(LCType,'N','Y','B') &&NumricoouMoeda
luRetVal=VAL(tcExp)
CASEINLIST(LCType,'C','M') &&Characterounota
luRetVal=tcExp
CASELCType='L' &&Logical
luRetVal=IIF(!empty(tcExp),.T.,f.)
CASELCType='D' &&Encontro
luRetVal=CTOD(tcExp)
CASELCType='T' &&Datahora
luRetVal=CTOT(tcExp)
DEOUTRAFORMA
***Nohoutraformaanoser,claro,VisualFoxProadiciona
***Umnovotipodedados.Nestecaso,afunodevesermodificado
ENDCASE
***Valorderetornocomotipodedados
RETURNluRetVal
44 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Sevocescreveraplicaescliente/servidor,vocjsabequevocdeveconvertertodos
expressesemstringsantesdeuslosdentrodeumSQLEXEC().Mesmosevocnoestfazendo
desenvolvimentocliente/servidor,vocvaiprecisardessafuncionalidade,afimdeconstruirqualquertipodeSQL
novo.
Afunoaseguirnosconverteoparmetropassadoparaumvalordecaractere,eletambm
embrulhaoresultadoentreaspasquandoapropriado.Istoespecialmentetilquandoinvocando
afunodeumgeradordeSQLOnTheFly.aindamaisfcilnoVisualFoxPro6.0,porque
vocpodeusaroTRANSFORMARfunosemumacadeiadeformatoparaconverteroprimeiroargumentopara
personagem.TRANSFORM(1234.56)produzomesmoresultadoqueALLTRIM(PADL(1234.56,
32)).

FUNOExp2Str(tuExp,tcType)
***Converteraexpressopassouacadeia
lcRetValLOCAL,LCType
***Senenhumtipopassadomapaparatipodeexpresso
LCType=IIF(TYPE('tcType')='C',UPPER(ALLTRIM(tcType)),TYPE('tuExp'))
***Conversodetipoparachar
DOCASO
CASEINLIST(LCType,'I','N')eINT(tuExp)=tuExp &&Integer
lcRetVal=ALLTRIM(STR(tuExp,16,0))
CASEINLIST(LCType,'N','Y','B') &&NumricoouMoeda
lcRetVal=ALLTRIM(PADL(tuExp,32))
CASELCType='C' &&Personagem
lcRetVal='"'+ALLTRIM(tuExp)+'"'
CASELCType='L' &&Logical
lcRetVal=IIF(!empty(tuExp),".T.','f.")
CASELCType='D' &&Encontro
lcRetVal='"'+ALLTRIM(DTOC(tuExp))+'"'
CASELCType='T' &&Datahora
lcRetVal='"'+ALLTRIM(TTOC(tuExp))+'"'
DEOUTRAFORMA
***Nohoutraformaanoser,claro,VisualFoxProadiciona
***Umnovotipodedados.Nestecaso,afunodevesermodificado
ENDCASE
***Valorderetornocomopersonagem
RETURNlcRetVal

Outrasfunesteis
Existemvriasoutrasfunesgenricasquepodemvivernoseuarquivodeprocedimentogeraloubase
classeprocedimento.UmexemplobviooSetPath()function(apresentadosnoprimeirocaptulo).
Nsencontramosasseguintesfunesparticularmentetileesperoquevoctambm.

Comofaoparadeterminarseexisteumatag?
NoseriabomseVisualFoxProtinhaumafunonativaqueretornouverdadeiroseexistiaumaetiqueta?
Istoseriaespecialmentetil,porexemplo,duranteacriaodeumaclassedegrelhapersonalizadaquepermitequeo
usurioaclicaremumcabealhodecolunaparaclassificararedepelatagnessacoluna.Tambmseria
tilparatestaraexistnciadeumndice,seeledevesercriadopormeiodeprogramao.estecdigo
queforneceafuncionalidade.

Captulo2:FuneseProcedimentos 45

FUNOISTAG(tcTagName,tcTable)
lnCntLOCAL,llRetVal,lnSelect

IFTYPE('tcTagName')#'C'
***ErrodevepassarporumaNameTag
ERRO'9000:DevepassarumnomedeTagaochamarISTAG()'
RETURN.F.
FIMSE

***NmeroGuardarreadetrabalho
lnSelect=SELECIONAR()
IFTYPE('tcTable')='C'E!VAZIO(tcTable)
***Seatabelaespecificada,selecioneo
lcTableSELECIONAR
FIMSE
***VerifiqueEtiquetas
PARAlnCnt=1aTAGCOUNT()
IFUPPER(ALLTRIM(tcTagName))==UPPER(ALLTRIM(TAG(lnCnt)))
llRetVal=.T.
SADA
FIMSE
PRXIMO
***Restaurarreadetrabalho
SELECT(lnSelect)
***RetornoSeTagEncontrado
RETURNllRetVal

Apropsito,observeousodo ERROcomandonestafuno.Emvezdesimplesmente
exibirumamensagemquandoumparmetrofalhadevalidao,essafunogerarumerroaplicativo
quepodeserpresoporummanipuladordeerro,assimcomoumerrodoVisualFoxPronormal.

Comofaoparadeterminarseumastringcontmpelomenosumalfabtica
personagem?
OVisualFoxProISALPHA()retorna.seacadeiapassadaparaelecomeacomumaletra.
Damesmaforma,isdigit()vaifazeromesmoseaseqnciacomeacomumnmero.Masesevocprecisa
saberseacadeiacontmquaisquercaracteresalfabticos?Cdigocomoesteiriafuncionar,mas
lentasevolumosas:

FUNOContainsAlpha(tcString)
LOCALlnChar,llRetVal
llRetVal=.F.
***Loopatravsdacordaetestarcadapersonagem
PARAlnChar=1aLEN(tcString)
IFISALPHA(SUBSTR(tcString,lnChar,1)
llRetVal=.T.
SADA
FIMSE
ENDFOR
RETURNllRetVal

Noentanto,porqueescreverdezlinhasdecdigoquandodoisvofazeromesmotrabalho?

46 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FUNOContainsAlpha(tcString)
RETURNLEN(CHRTRAN(UPPER(tcString),"ABCDEFGHIJKLMNOPQRSTUVWXYZ",""))
#LEN(tcString)

Obviamente,umametodologiasemelhantepodeserusadoparadeterminarseumacadeiadecaracterescontmquaisquer
Noentanto,nsnosrecusamosainsultaraintelignciadosnossosleitores,listandoloaqui.Afinal,vocforamtodos
dgitos.
inteligenteosuficienteparacomprarestelivro,no?

Comoconverternmerosparapalavras
Umproblemacomumadeconverternmerosemcadeiasdecaracteres,paraimpressodecheques,
oucomoconfirmaodeumafacturaouordemtotal.Temhavidomuitassoluespropostaspara
issoaolongodosanos,masaindacomoesteomelhor,porqueelelidacomgrandesnmeros,negativo
nmeroseadotaumaabordageminovadoraparadecimaistambm.

**********************************************************************
*Programa :NumToStr
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Converternmeroemumaseqnciadetexto
*Notas :Trataosnmerosdeat99.999.999epodeacomodar
* :Nmerosnegativos.Decimaissoarredondadosparaduascasas
* Evoltoucomo'ecentsimosxxxx'
************************************************************************
NumToStrFUNO
LPARAMETERStnvalue
LOCALlnHund,lnThou,lnHTho,lnMill,lnInt,lnDec
llDecFlagLOCAL,llHFlag,llTFlag,llMFlag,llNegFlag
lcRetValLOCAL

***Avaliarosparmetros
DOCASO
CASETYPE('tnValue')#'N'
RETORNA('')
CASEtnvalue=0
RETURN'Zero'
CASEtnvalue<0
***Definirosinalizadordenegativoeconverterovalorparapositiva
llNegFlag=.T.
tnvalue=ABS(tnvalue)
DEOUTRAFORMA
llNegFlag=.F.
ENDCASE

***InicializarVariveis
.FSTORE.AllHFlag,llTFlag,llMFlag
STORE0alnHund,lnThou,lnMill
STORE""paralcRetVal
***Obteraparteinteira
lnInt=INT(tnvalue)
***Verifiqueparaascasasdecimais
IFMOD(tnValue,1)#0
lnDec=ROUND(MOD(tnvalue,1),2)
llDecFlag=.T.
OUTRO
llDecFlag=.F.
FIMSE

Captulo2:FuneseProcedimentos 47

***Faaaparteinteiraprimeira
DoWhile.T.
DOCASO
CASElnInt<100 &&TENS
IFEMPTY(lcRetVal)
lcRetVal=lcRetVal+ALLTRIM(con_tens(lnInt))
OUTRO
IFRIGHT(lcRetVal,5)#"e"
lcRetVal=lcRetVal+'e'
FIMSE
lcRetVal=lcRetVal+ALLTRIM(con_tens(lnInt))
FIMSE
CASElnInt<1000 &&CENTENAS
lnHund=INT(lnInt/100)
lnInt=lnInt(lnHund*100)
lcRetVal=lcRetVal+ALLTRIM(con_tens(lnHund))+"Hundred"
IFlnInt#0
lcRetVal=lcRetVal+"e"
LOOP
FIMSE
CASElnInt<100000 &&MILHARES
lnThou=INT(lnInt/1000)
lnInt=lnInt(lnThou*1000)
lcRetVal=lcRetVal+ALLTRIM(con_tens(lnThou))+"Mil"
IFlnInt#0
lcRetVal=lcRetVal+""
LOOP
FIMSE
CASElnInt<1000000 &&centenasdemilhares
lnHTho=INT(lnInt/100000)
lnInt=lnInt(lnHTho*100.000)
lcRetVal=lcRetVal+ALLTRIM(con_tens(lnHTho))+"Hundred"
IFlnInt#0
lcRetVal=lcRetVal+"e"
LOOP
OUTRO
lcRetVal=lcRetVal+"Mil"
FIMSE
CASElnInt<100000000 &&Milhes
lnMill=INT(lnInt/1000000)
lnInt=lnInt(lnMill*1000000)
lcRetVal=lcRetVal+ALLTRIM(con_tens(lnMill))+"Million"
IFlnInt#0
lcRetVal=lcRetVal+","
LOOP
FIMSE
ENDCASE
SADA
ENDDO
***Agoralidarcomqualquerdecimais
IFllDecFlag
lnDec=lnDec*100
lcRetVal=lcRetVal+"e"+ALLTRIM(con_tens(lnDec))+'centsimos'
FIMSE
***FinalmentePegaabandeiraNegative
IFllNegFlag
lcRetVal="[MINUS"+ALLTRIM(lcRetVal)+"]"
FIMSE
***Retornarastringacabado
48 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

RETURNlcRetVal
***********************************************
***LidarcomaconversoTENS
***********************************************
con_tensFUNO
LPARAMETERStndvalue
lcStrValLOCAL,lcStrTeen
STORE''paralcStrVal,lcStrTeen
DOCASO
CASEtnDValue<20
Retorno(con_teens(tnDValue))
CASEtnDValue<30
lcStrVal='Vinte'
tnDValue=tnDValue20
CASEtnDValue<40
lcStrVal='Trinta'
tnDValuetnDValue=30
CASEtnDValue<50
lcStrVal='Quarenta'
tnDValuetnDValue=40
CASEtnDValue<60
lcStrVal='Fifty'
tnDValuetnDValue=50
CASEtnDValue<70
lcStrVal='Sixty'
tnDValuetnDValue=60
CASEtnDValue<80
lcStrVal='Setenta'
tnDValuetnDValue=70
CASEtnDValue<90
lcStrVal='Oitenta'
tnDValue=tnDValue80
CASEtnDValue<100
lcStrVal='Noventa'
tnDValuetnDValue=90
ENDCASE
***Agoraconverterqualquerparcelaremanescente
lcStrTeen=con_teens(tnDValue)
IFLEN(lcStrTeen)#0
***Adicionarnotextorelevante
lcStrVal=lcStrVal+''+lcStrTeen
FIMSE
RETURNTRIM(lcStrVal)

***********************************************
***ManipularasUnidades/ConversoAdolescentes
***********************************************
con_teensFUNO
LPARAMETERStntvalue
DOCASO
CASEtntvalue=0
RETORNA('')
CASEtntvalue=1
RETURN('One')
CASEtntvalue=2
RETURN("dois")
CASEtntvalue=3
RETURN('Three')
CASEtntvalue=4

Captulo2:FuneseProcedimentos 49

RETURN('Quatro')
CASEtntvalue=5
RETURN('Five')
CASEtntvalue=6
RETURN('Seis')
CASEtntvalue=7
RETURN('Seven')
CASEtntvalue=8
RETURN('Oito')
CASEtntvalue=9
RETURN('Nine')
CASEtntvalue=10
RETURN('Ten')
CASEtntvalue=11
RETURN('Eleven')
CASEtntvalue=12
RETURN('Doze')
CASEtntvalue=13
RETURN('AosTreze')
CASEtntvalue=14
RETURN('Catorze')
CASEtntvalue=15
RETURN('Quinze')
CASEtntvalue=16
RETURN('Sixteen')
CASEtntvalue=17
RETURN('Seventeen')
CASEtntvalue=18
RETURN('Eighteen')
CASEtntvalue=19
RETURN(dezanove)
ENDCASE

Oprojetoaquiinteressanteporsis.Oproblemafoiresolvidoatravsdareduodo
vrioscomponentesdeumnmeroaummnimo,eoresultadoumafunoquepodesertil
usadocomoumanicachamadadelinhadaseguinteforma:

lcOutStr=NumToStr(1372.23)+"Dlares"
Retorna:"ummil,trezentosesetentaedoisevinteetrs
Dlarescentsimos"

Comoextrairumitemespecificadoemumalista
Maisemaisfrequentementeprecisosercapazdeaceitareinterpretardadosquesofornecidosemum
listaseparadaformato.Estepodeserumsimplesarquivo,delimitadoporvrgulasoupossivelmenteoresultadodeuma
mecanismodetransfernciadedadosouapenasalgunsdadosmaiscomplexo,precisamospassaraoredorinternamente.
Aconstruodeumacadeiadecaracteresquecontmdadosemumaseparadaformatobastantesimples.
Recuperarosdadosapartirdeumatalcadeia,noentanto,podeserumpoucomaisproblemtico.Introduziro
GetItem()funo.
Estafunoanalisaacadeiadado,olhandoparaaocorrnciaespecificadado
separadoreextrairoitemqueencontrar.Assumeseque,salvoindicaoemcontrrio,vocquer
oprimeiroitemeoseparadorumavrgula.Noentanto,ambososelementospodeserespecificado.aqui
:

50 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

**********************************************************************
*Programa :GetItem.PRG
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Extraioelementoespecificadodeumalista
**********************************************************************
FUNOGetItem(tcList,tnItem,tcSepBy)
LOCAISlcRetVal,lnStPos,lnEnPos,lcSepBy
lcRetVal=""
***PadroparaCommaSeparatorsenadaforespecificado
lcSep=IIF(VARTYPE(tcSepBy)#'C'ouvazio(tcSepBy),',',tcSepBy)
***Padroparaoprimeiroitemsenadaespecificado
tnItem=IIF(TYPE('tnItem')#"N"ouvazio(tnItem),1,tnItem)
***Adicionarseparadordeterminalparalistarparasimplificarapesquisa
tcList=ALLTRIM(tcList)+lcSep
***Determineocomprimentodacordanecessria
IFtnItem=1
lnStPos=1
OUTRO
lnStPos=AT(lcSep,tcList,tnItem1)+1
FIMSE
***Encontreprximaseparador
lnEnPos=AT(lcSep,tcList,tnItem)
IFlnEnPos=0ou(lnEnPoslnStPos)=0
***Fimdacorda
lcRetVal=NULL
OUTRO
***Extraiaoitemrelevante
lcRetVal=SUBSTR(tcList,lnStPos,lnEnPoslnStPos)
FIMSE
***Resultadoderetorno
RETURNALLTRIM(lcRetVal)

Normalmenteusamosestafunodentrodeumlooppararecuperarositensdeumalistaseparadano
aordememquefoiconstrudo,comosesegue:

lcStr="David|Jones|12TheStreet|Someplace|"
lnCnt=0
DoWhile.T.
lnCnt=+1lnCnt
lcItem=GetItem(lcStr,lnCnt,"|")
ESE!ISNULL(lcItem)
***Faaoquecomele
OUTRO
***Fimdacordasada
SADA
FIMSE
ENDDO

Existeumamaneirasimplesdecriptografiadesenhas?
Aresposta(eumavezquefezapergunta,vocnoesperarianadamenos)Sim!Aprxima
pardefunesfornecemumamaneirafcildeadicionarumnvelrazoveldeseguranadesenha.o
processodecriptografiabaseadanaconversodecadacaracterenaseqnciaplanciesuaASCII
nmeroe,emseguida,adicionandoumaconstante.Temosusado17nesteexemplo,massugeremquesevoc
adoptaremessasfunesvocusaumnmerodiferente,almdeumnmerobasealeatrio,maiso

Captulo2:FuneseProcedimentos 51

posiodaletranaseqnciaaessevalor.Opersonagemrepresentadoporestenovonmero
emseguida,retornoucomoaversocriptografada.Aseqnciadecaracteresretornadaincluionmerodesementes
geraocomooprimeirocaractereparaqueelesemprepodeserdecodificado.Estametodologiatemvrios
utilizado,emsua
benefcios:

Amesmacadeiavai,dentrodoslimitesdoVisualFoxPro()RANDfuno,produzem
diferentescadeiasdecaracterescodificadosdecadavezquepassadoatravsdafuno
Nohnenhumamaneirafcildetraduzirumcaracterecriptografadajqueoresultadodeumdeterminado
carterdependedonmerodesementesesuaposionacadeia
Asenhacriptografadasempreumcarctermaisdoqueooriginalporcausada
ovalordesemente
Nohnenhumarestriosobreonmerodecaracteres(ouseja,elevailidarcom6,8ou12
senhasdecaracteresigualmentebem)
Asenhapodeincluirnmerosecaracteresespeciais
Apesardenoserinfalvel,realmentemuitodifcildecortarumavezque,emboraa
cadeiasimplessempreconvertidoparamaisculas,astringencriptadapodeconterqualquer
combinaodecaracteres
Umavezqueasenhacontmsuasemente,umadministradorpodesempredecodificarsenhas

Dequalquerforma,aquiestotantoasfunescodificaredecodificar:

**********************************************************************
*Programa :AEnCode.PRG
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:criptografiadesenhas
**********************************************************************
FUNOaencode(tcKeyWord)
lcRawLOCAL,lnVar,lcEnc
IFTYPE('tcKeyWord')#"C"ouvazio(tcKeyWord)
***Devepassarporumachavedecaracteresparaesteprocesso
ERROR("9000:UmacadeiadecaracteresoparmetronecessrioparaAEnCode")
RETORNA""
FIMSE
lcRaw=UPPER(ALLTRIM(tcKeyWord))&&Keyword
lnVar=INT(RAND()*10) &&RandomNumberKey:09
lcEnc=ALLTRIM(STR(lnVar)) &&Stringencriptadacomeacomchave#
***Analiseapalavrachaveecriptografarcadapersonagem
***UsandoseucdigoASCII+17+aleatriaKey+PosionoKeyword
PARAlnCnt=1aLEN(lcRaw)
lcChar=SUBSTR(lcRaw,lnCnt,1)
lcEnc=lcEnc+CHR(ASC(lcChar)+17+lnVar+lnCnt+1)
PRXIMO
RETURNlcEnc

**********************************************************************
*Programa :ADeCode.PRG
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:decodificaumasenhacriptografadacomAEnCode()
**********************************************************************
FUNOadecode(tcKeyWord)
lcRawLOCAL,lnVar,lcEnc
52 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

IFTYPE('tcKeyWord')#"C"ouvazio(tcKeyWord)
***Devepassarporumachavedecaracteresparaesteprocesso
ERROR("9000:umastringcriptografadaoparmetronecessrioparaADeCode")
RETORNA""
FIMSE
lcEnc=ALLTRIM(tcKeyWord) &&Keyword
lnVar=VAL(LEFT(lcEnc,1)) &&Chavedecriptografia
lcRaw="" &&SenhaDecoded
***Analiseapalavrachaveedescriptografarcadapersonagem
***UsandoseucdigoASCII+17+aleatriaKey+PosionoKeyword
PARAlnCnt=2ALEN(lcEnc)
lcChar=SUBSTR(lcEnc,lnCnt,1)
lcRaw=lcRaw+CHR(ASC(lcChar)(17+lnVar+lnCnt))
PRXIMO
RETURNlcRaw

Eaquiestoalgumasamostrasdesadacriptografado:

passe1 ?AEnCode('Andy%Kr#02') 8\jawDksESV


passe2 ?AEnCode('Andy%Kr#02') 6Zh_uBiqCQT
passe3 ?AEnCode('Andy%Kr#02') 3We\r?Fn@NQ

Cadaumquedecodificavoltaparaamesmastringoriginal:

passe1 ?ADeCode('8\jawDksESV') ANDY%KR#02


passe2 ?ADeCode('6Zh_uBiqCQT') ANDY%KR#02
passe3 ?ADeCode('3We\r?Fn@NQ') ANDY%KR#02

Temoscertezaquevocvaiencontrarformasdemelhorarouadaptaressasfunes,maselestm
nosservidobemdurantevriosanosagoraensesperamosquevocgostadeles.

OndevocquerGOTO?
Todosnsusamoso GOTO<nn>comandodevezemquando,masumdoVisualFoxPro
pequenosaborrecimentosdoprogramadorqueGOTOnofazqualquerverificaodeerrosdeseuprprio.Sevocs
dizerVisualFoxProparaGOTOumnmeroderegistroespecficoqueapenastentairparal.Claro,seo
nmerorecordequeespecificounoestnamesa,ousevocinadvertidamenteteroerrado
readetrabalhoselecionada,vocreceberumerrofeio.
Oproblemadaselecodareadetrabalhotemsidolargamenteresolvidocomaintroduode
aINclusulademuitoscomandosincluindoGOTO.Noentantoissonoresolvero
problemadeoutroserros.TemoscansadodecolocarchequesemtornodecadainstruoGOTOemnossa
cdigoparaqueconcebeuumapequenafunoparaembrulharocomandoGOTOetornlomaisseguroe
maisamigvel.ChamamosissoGOSAFE()eaquiest:

**********************************************************************
*Programa :GoSafe.PRG
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:invlucroemtornodocomandoGOTO
**********************************************************************
FUNOGoSafe(tnRecNum,tcAlias)
laErrsarraylocal[1]
lcAlias
local,lnCount,lnCurRec,lnErrCnt,llRetVal

Captulo2:FuneseProcedimentos 53

***Verifiqueoparmetronumricoevlido
IFVARTYPE(tnRecNum)#"N"ouvazio(tnRecNum)
ERROR"9000:UmparmetronumricovlidodeveserpassadoparaGoSafe()"
RETURN.F.
FIMSE
***Alias
padroparaapelidoatualsenoespecificado

IFVARTYPE(tcAlias)#"C"ouvazio(tcAlias)
lcAlias
OUTRO =ALIAS()

lcAlias
=UPPER(ALLTRIM(tcAlias))

FIMSE
***Verifiquequetemosoaliasespecificado
Seestivervazio(lcAlias)OR!Utilizado(lcAlias)
ERROR"9000:Nenhumatabelafoiespecificadoouatabelaespecificadanoaberto"
RETURN.F.
FIMSE
***GetMaxNenhumregistroeoselecionado
***Nmeroderegistronoaliasespecificado
lnCount=RECCOUNT(lcAlias)
lnCurRec=RECNO(lcAlias)
***SalveTratamentodeerrosedesliguevudeerroporenquanto
lcOldError=ON("ERROR")
ERRORON*
***Agoratenteirparaoregistronecessrio
GOTOtnRecNumIN(lcAlias)
***Serquevamostersucesso?
IFRECNO(lcAlias)#tnRecNum
***Verificarseherros
lnErrCnt=AERROR(laErrs)
IFlnErrCnt>0
DOCASO
laErrscasos[1,1]=5
***GraveForadoalcance
lcErrTxt='RecordNumber'+ALLTRIM(PADL(tnRecNum,32))
+'NoestdisponvelemAlias:'+lcAlias
laErrscasos[1,1]=20
***GraveNonondice
lcErrTxt='RecordNumber'+ALLTRIM(PADL(tnRecNum,32))
+'NoestnondicedeAlias:'+lcAlias
+CHR(13)+'Tableprecisaserreindexado'
DEOUTRAFORMA
***Umerroinesperado
lcErrTxt='UmerroinesperadoimpediuoGOTOsucedendo'
ENDCASE
MESSAGEBOX(lcErrTxt,16,'CommandFailed')
FIMSE
***Restauraroregistrooriginal
GOTOlnCurRecIN(lcAlias)
llRetVal=.F.
OUTRO
llRetVal=.T.
FIMSE
***Restauraridentificadordeerro
ONERROR&lcOldError
RETURNllRetVal

54 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Umacoisaanotarnesteprogramaousodo ON("ERROR")funoparasalvarforada
manipuladordeerroatualparaquepossamossuprimircomseguranaoerronormalmanipulaocom ONERROR*
erestaurarascoisasnofinaldafuno.
Esteumpontomuitoimportanteemuitofacilmenteesquecidonocalordabatalha.Qualquer
procedimentooufunodevesalvarasconfiguraesambientaisantesdealterarqualquerumdeles(bem,
talveznsdevemosafirmarquemelhorparavalidarparmetrosemprimeirolugar.Afinal,seestiveremincorretos,
afunonovaifazernadadequalquermaneira.)Emconcluso,oprocedimentooufuno
absolutamentenecessrioredefinirtudoexatamentecomoeraantesafunofoichamada.
Captulo3:Design,Designerenadamais 55

Captulo3
Design,DesignereNada
Outro
"pordesign."(Anonymous,masmuitasvezesassociadaaMicrosoftCorporation)

Vocconsegueadivinharoqueestecaptulotudoisso?Correta,sobreostrsmais
coisasimportantesaconsiderarquandosetrabalhacomobjetosdoVisualFoxProorientada
meioAmbiente.Nsnosoestritamentecertoqueestecaptulocompreende'Dicas',mas
certamentecheiodeconselhosamaiorpartedeladuramenteconquistadaaolongodosanosquetemos
comoVisualFoxPro.Nsvamoscobrircompletamenteumagamadetemas,comeandocomalguns
vindoatrabalhar
lembretesdoqueOOPtudo.
bsicos

Ento,porquetodooalaridosobreOOP,afinal?
sempredifcilsaberporondecomear.Nestecaso,nssentimosqueeraprovavelmenteapenacomeando
comalgumaspalavrassobreporquenaterravocdevesepreocuparcomtodoestematerialOOPeque
adoodoparadigmaOOPvaisignificarparavoccomoumdesenvolvedor.
OprimeiropontoafazersobreOOPqueeleno,porsis,umanovalinguagemdeprogramao,
masrealmenteumamaneiradiferentedeolharparaamaneiradeprojetareconstruirprogramasdecomputador.
EmtermosdeVFPestaaboanotciaissosignificaquevocrealmentenotemqueaprenderumtodo
novalinguagemapenasumamaneiradiferentedefazerascoisas.Amnotciaqueanovaformade
fazerascoisastoradicalmentediferentequevocprovavelmentevaidesejarstinhadeaprenderumanova
lngua.Comotantosaspectosdaprogramao,fazendoOOPfcil,fazlobemmuito
maisduro!
Doisdosmaioresbenefciosbsicosqueosprogramadoreshmuitoprocuradasoreusabilidade
(Escreverumpedaodecdigoumavez,depurloumavezeuslomuitasvezes)eextensibilidade(fazer
amudanadeumapartedeumsistemasemtrazerorestodeladesabaraoseuredor).
Adequadamenteimplementado,OOPtemacapacidadedeofereceressesdoisbenefcios.Onico
questocomo?
Emprimeirolugar,comosugereseunome,OrientaoaObjetosestfocadaem"objetos"quesoprojetados
ecriadoindependentementedeaplicaes.Aprincipalcoisaalembrarsobreumobjetoqueele
devesabercomofazeroqueelesedestinaafazer.Emoutraspalavras,umobjectotemdeterum
funo.Seessafunototalmenteautocontido,ouapenasumelodeumacadeia,
irrelevantedesdequeafunoestclaramentedefinidacomosendoaresponsabilidadedeum
determinadoobjeto.
Emtermosdeumaaplicaoouumsistema,afuncionalidadeglobalconseguidoatravs
manipulandoascaractersticaseasinteracesdosobjectosqueconstituemosistema.isto
Segueseentoqueasmodificaesparaafuncionalidadedosistemairserfeitapelaadiode,ou
remoodeobjectos,emvezdeatravsdaalteraodocdigodentrodeumobjectoexistente.
H,naturalmente,consequnciasinerentesaadotaressaabordagemparaosistema
desenvolvimento.Primeiroeleirsignificarumamudanananfasedociclodedesenvolvimento.Muito
56 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

maistempoterdesergastonaconcepo,criaoetestedosobjetosnecessriosparauma
aplicao.Felizmente,serrealmentenecessriomenostempoparadesenvolverosistema.Quandochegarahora
voctemumestoquedeobjetosdevidamentetestados,voctambmteramaioriadafuncionalidade
necessrioporumaplicativoetudoquevocprecisafazerligarascoisascorretamente.(Soamuitobem
tolonge.)
claro,htambmumacurvadeaprendizagem.Noapenasemtermosdemecnicade
programaoemambienteOOPdoVisualFoxPro(queapartefcil),mastambmaprendera
mudaramaneiradepensarsobreoseutrabalhodedesenvolvimento.Amnotciaque,emboratenha
nuncafoiumsubstitutoparaobomdesigndesoftware,naconcepomundoOOPnoapenascrtico,
issotudo!Obtenhaseudireitodesignoriginaletudosimples.Obtloerradoevida
tornaserapidamenteumamisria.
Obitfinaldemsnotciasquenosoprojetocrtico,masassimadocumentao.
Desdequeseuobjetivoescreverumpedaodecdigoumavez,eapenasumavez,edepoisbloqueloafastado
parasempre,imperativoquevocdocumentaroquecadaobjetofaz,quaisasinformaesqueeleprecisa
eoqueeleoferecefuncionalidade.(Notequenoprecisamossabercomoelefazoquefor
fazquedaresponsabilidadedoobjeto).

Afinal,oquequetudoistoOOPjargosignifica?
Talcomoacontececomqualquernovatecnologia,oadventodaOrientaoaObjetosintroduziuummontedenovo
palavrasefrasesnalnguadedesenvolvimentoFoxPro.Enquantoamaioriadojargo
'Standard'domundoorientadoaobjeto,nemsempreimediatamentebvioparaaquelesdensque
vmdeumfundoFoxPro.TrabalhandocomobjetosrequerumacompreensodePEMs
(propriedades,eventosemtodos).Apenasoqueessestermosrealmentesignificam?

Propriedade
Apropriedadedeumobjetoumavarivelquedefinealgumascaractersticasdesseobjeto.Todososobjetos
temumpadro'Definir'depropriedades(derivadoinicialmenteapartirdadefiniodeclasse)quedescrevema
estadodoobjeto.
Porexemplo,umacaixadetextoobjetotempropriedadespara:

tamanhoelocalizao(porexemplo,altura,largura,Top,Left)
Aparncia(porexemplo,FontName,FontSize)
Status(porexemploReadOnly)
Contedo(porexemplocontrolsource,Valor)

OconjuntodepropriedadesdeumobjetopodeserprorrogadoemVisualFoxPropelaadiode
"propriedadespersonalizadas"paraadefiniodeclassedoqualoobjetoderivado.
Propriedadesresponderpergunta:"Qualoestadodoobjeto"

Mtodo
Ummtododeumobjetoumprocedimentoassociadoaesseobjeto.Todososobjetostmumpadro
'Definir'demtodos(derivadosinicialmenteapartirdadefiniodeclasse)quedefinemcomoumobjeto
secomporta.Porexemplo,umacaixadetextoobjetotemmtodospara:

Captulo3:Design,Designerenadamais 57
Atualizaoemsi(Refresh)
Fazerumacorrentedeobjeto(SetFocus)
Mudarasuaposio(Move)

OmtodoconstantedeumobjetopodeserprorrogadoemVisualFoxPropelaadiode"custom
mtodos"paraadefiniodeclasse.
Mtodosderesponderpergunta:"Oquequeoobjetofazer"

Evento
Umeventoumaaoqueumobjetopodereconhecer,eaoqualelepoderesponder.Todososobjetos
temumpadro'Definir'deeventosqueherdamdaclassebaseFoxPro.Assim,por
exemplo,umobjetodecaixadetextopodereconhecereventoscomo:

aesdemouseouteclado
Alteraesaoseuvaloratual
Receberouperderofoco

Aacodeumobjectoqueseexecutaquandoocorreumeventodeterminadapeloteordeum
mtodoassociadoaoevento.Noentanto,chamaressemtododiretamenteNOcause
oeventoaofogo,eleapenasexecutaomtodo.Algunseventostmaespadroemsua
mtodosquesodefinidospeloFoxProClasseBase(porexemploGotFocus),enquantooutrosno(porexemplo,
Clique).
Oeventoconjuntodeumobjetonopodeserestendidavocnopodecriar"eventospersonalizados".
Noentanto,ocdigopodeseradicionadocomomtodoassociadocomumeventoparachamarumoutromtodo.
Eventosresponderpergunta:"Quandoqueoobjetofaaalgo"

mensagens
Umamensagemoresultadodaacodeumobjectoeomecanismopeloqualelecomunica
comoseuambiente.NoVisualFoxPromensagenssomanipuladosporpassarparmetros/voltar
valoresoudefinindopropriedades/chamarmtodos.
Mensagensderesponderpergunta"Comosabemosqueumobjetotenhafeitoalgoassim?"

ClasseseObjetos
CompreenderadiferenaentreumaclasseeumobjetocrucialparaOOP.Umaclassea
modelodoqualosobjetossocriados.Noentanto,osobjetosnoso"cpias"deumaclasse
definio,elessorefernciasaele.Aconsequnciaque,quandoumadefiniodeclassealterado,
qualquerobjetoderivadodequeaclasseirrefletiressamudana.Istooqueseentendepor
'Herana'.
Arelaoentreumobjetoesuaclassesemelhantequeexisteentreumareceitaparaum
boloeobolorealareceitadizlhecomofazerobolo,masvocnopoderealmente
comerareceita!Damesmaformaumaclassenofaznada.somentequandoum
objetocriadocomoum"INSTNCIA"dessaclasse(oprocesso,portanto,chamado'instanciao')
quenadadetilpoderealmenteserfeito.

58 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

EmClassesdoVisualFoxPropodemserdefinidashierarquicamente,eosobjectospodemserinstanciado
apartirdequalquernveldehierarquia.importante,portanto,queadefiniodeclasses
realizadautilizandoumametodologialgicaeconsistentedenominadoAbstraction".o
princpioportrsdacaptaoidentificarasprincipaiscaractersticasapropriadasparaonvelde
hierarquiasobconsiderao.
Issoparecemaiscomplexadoquerealmentetodosnsfazemosissotodososdiassempensar
sobreisso.Porexemplo,sealgumafirmou:"Dmeumacaneta,"nsnormalmentenohesiteem
considerarapenasoqueuma'caneta'realmentensapenas"saberoqueumacaneta."
Naverdadenoexistetalcoisacomo"umapena"otermonaverdadeumaabstraoquedescreve
umaclassedeobjetosfsicosquecompartilhamcertascaractersticasequediferemdeoutros
classesdeobjetosfsicos.Nsnormalmentenoconfundirumacanetaeumlpisembora
ambosestoescrevendoclaramenteimplementos.
EsteprincpiobsicotraduzsedirectamentenaconstruodeclassesdentrodeVFP.Iniciando
comasclassesbaseVFPpodemosconstruirnossasprpriashierarquiasdeclasse,adicionandoao
funcionalidade(aumento)oualterarafuncionalidade(Especializao)emsubclasses
queentoformamahierarquiadeclasses.

Herana
Aheranaotermousadoparadescreveramaneirapelaqualumobjeto(uma"Instncia"deumaclasse)
derivasuafuncionalidadedesuaclassepai.NoVisualFoxProsemprequevocusarumobjeto,
naverdadevocestcriandoumarefernciaparatrsaessadefiniodeclassepai.Estarefernciano
estticaereavaliadoacadavezqueoobjetoinstanciado.Oresultadoquesevocmudar
adefinionaclassepai,qualquerobjetocombaseemqueaclasseirapresentaroresultadoda
alteraraprximavezqueforinstanciado.

porissoque,quandosetrabalhaemVisualFoxPro,vocvaiocasionalmentese
umamensagemdeerrodizendo'Nopossvelmodificarumaclassequeestemuso".o
issoestlhedizendoquevocrealmentetemumaoumaisdefiniesno
que
memriaquesonecessriospeloobjetoquevocesttentandoeditar.
Aemissodeuma'CLEARALLcomando'normalmenteirresolveresseproblemaparavoc.

ComoVFPimplementaherana
VisualFoxProimplementaaheranadeumaformaascendenteinferior.Quandoocorreumevento
querequerqueumobjetolevaalgumaao,VisualFoxProcomeaporexecutarqualquercdigo
quefoidefinidonomtodoassociadoaesseeventonoobjecto(talcdigo,
portanto,referidocomo"nveldeinstncia"eeleirsubstituirqualquercdigoherdadoamenosqueum
explcita' DODEFAULT()"chamadadefunoestincludoemalgummomento).
Senohouvernenhumcdigonoobjecto(ouumDoDefault()foiespecificada),continuaporVFP
executarqualquercdigodefinidonomesmomtodonaclasseidentificadanoobjetodo
ParentClasspropriedade.Esteprocessocontinuaatahierarquiadefinidapelosucessivo
ParentClassrefernciasatqueummtodoquecontmocdigosemumaexplcitaDoDefault()
ouumaclasseondeosParentClasspontospropriedadediretamenteparaabaseclassVisualFoxPro,

Captulo3:Design,Designerenadamais 59

encontrados.Dequalquercondioidentificao'Top'dahierarquiadeclassesparaesseobjetoenomais
refernciassoprocurados.
Apsaconclusodequalquercdigodenveldeinstncia,equalquercdigoherdado,VisualFoxPro,finalmente,
executaqualquercdigoqueestdefinidonomtodobaseclassnativacorrespondente.(Nenhumcdigodevontade
sempreserexecutadoamenosquevocincluirumaexplcita NODEFAULTcomandoemalgumlugarno
cadeiadeherana).Infelizmentenohnenhumadocumentaoparalhedizerquebaseclass
mtodosrealmentetmcdigoexecutvel,emboraalgunssobvios.KeyPress,GotFocus
eLostFocussoexemplosdeeventosqueexigemcomportamentonativaeque,portanto,
tmcdigonosbaseclasses.Poroutrolado,heventosque,obviamente,notmqualquernativa
comportamentoClique,QuandoeValidsoexemplosdemtodosbaseclassquesimplesmentedevolv
ovalorpadro(algica.T.).

Aherana"armadilha"
Heranaparece,primeiravista,paraencarnaraprpriaessnciadotrabalhoemumobjetoorientada
maneira.Aodefinirumaclasse,eemseguida,criarsubclassesque,ousoaumentadosou
especializada,parecequepodemossimplificarmuitoatarefadeconstruirumaplicativo.
Noentanto,existeumaarmadilhasutildeconfiardemaisemheranacomooseguintesimples
exemploilustra.
Vamossuporquequeremoscriarumaclassedeformulriopadroqueusaremosemtodososnossos
aplicaes.Nsdecidimosqueumacoisaqualquerformaterum"Exitboto'eporissoadicionarum
adequadamentelegendabotodecomandoparaanossaclassedeformulrioeemseuClickmtodo,coloqueum
'ThisForm.Release()'chamada.Issomuitobem,ecadavezquecriarumnovoformulrioquevem
concluircomumboto"Exit",quefunciona,emboranohajacdigonobotodeClick
Mtodo.(claroquehrealmentecdigo,masemvezdeseremtodasasformasqueelaexisteapenasumavez
nobotoquensdefinimoscomopartedaclassedeformulrioeparaoqualobotoemcadainstncia
danossaclassedeformulrioreferesesempre).Porenquanto,tudobem.Comotempo,adicionarmais"standard"
funcionalidadeparaanossaclassedeformulrioatravsdacriaodepropriedadesemtodospersonalizadosparalidar
comasnossasnecessidades.
Ento,umdiaagentesesolicitadoacriarumanovaformaque,emvezdeumboto"Sair",temdois
botes'OK'e'Cancelar'.Oprimeirodeve"salvarasalteraesesairdoformulrio"eosegundodeve
"Descartarasalteraesesairdoformulrio".Temosimediatamenteumproblema,porquenopodemos
bastacriarumasubclassedenossoformulriopadro!Qualquersubclassesersempretmumboto"Sair"
quesimplesmenteliberaoformulrio,enopodemosexcluiressebotoemumasubclasseporqueoVisual
FoxProirreclamarque"Nopossvelexcluirobjetosporquealgunssomembrosdeumpai
classe'.Claroquepoderamossimplesmentecriarumanovasubclassedaclassebasedeforma,masqueseria
notemqualquerumadenossasoutraspropriedadesemtodospersonalizados!Teramosdeadicionlostodos
novamenteecopiarecolarocdigoparaanossanovaclassedeformulrio,criando,assim,doisconjuntosdecdigo
mantersempremaiseperderumdosprincipaisbenefciosdousodeOrientaoaObjetosemtudo.
para
Umasoluovimosparaestedilemairemfrenteecriarasubclassedequalquermaneira.
Ento,emquesubclasse,dobotoExitherdadoshabilitadoseVisiblepropriedadessodefinidascomo
FALSEeosnovosbotesnecessriossoadicionados!OK,issovaifuncionar,mas,temoscertezaquevocvai
concordo,noexatamenteamelhormaneiradefazerascoisas.
Aabordagemcorreta,comoexplicamosno"Ento,comovocvaifazersobreacriaodeumaclasse"
maisadiantenestecaptulo,aconcepodesuasaulasdeformaadequadaeemvezdeconfiarinteiramenteem
herana,parautilizaracomposioparaadicionarfuncionalidadeespecficaquandonecessrio.

60 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Composio
Acomposioumtermousadoparadescreveratcnicaemqueumaclassedadoacessoaos
comportamentoespecfico(oufuncionalidade)poradiodeumobjectoquejtemqueocomportamento,emvez
que,adicionandoocdigodiretamenteparaaclasse.Estarealmenteumamaneiramuitomelhordeconstruir
objetoscomplexosdoquedependerdiretamentesobreherana,porqueelepermitequevocdefina
funcionalidadeemunidadesdiscretasquepodemserreusadoemmuitassituaesdiferentes.(Tambmo
melhormaneiradeevitara"armadilhaherana"descritonaseoanterior.)
Maisimportantequevocnoestlimitadoausarcomposiosomenteemtempodedesign.TodosVisual
recipientesFoxPro(ouseja,aquelasclassesquepode'conter'outrosobjetosincluindoasformase
Barrasdeferramentas,PageFramesePages,Gridsecolunas,bemcomotantoorecipientee
Classespersonalizadas))tmnativasADDOBJECTeRemoveObjectmtodosquefazemuso
composioemtempodeexecuoumaquestorelativamentesimples.(Paraumarepresentaoesquemtica
dacategorizaodasclassesdebasever"Captulo3:ProgramaoOrientadaaObjetos"no
GuiadoProgramadorouadocumentaoonline.)
Oresultadodousodecomposio,sejanodesenhooutempodeexecuo,semprequeoagregado
objetotornaseum"filho"(ou"membro")doobjetoaoqualeleestsendoadicionado.Istoassegura
queoobjetofilhocompartilhaomesmotempodevidacomoseupaiquandoopaidestrudo,porissoso
todososseusfilhos.
Finalmente,notarqueacomposionoestlimitadaadeterminadostiposdeclassesperfeitamente
possvel(epermitido)paramisturarasclassesvisuaisenovisuaisnomesmoobjetocomposto.
Anicarestrioqueoobjetopaipretendidodeveserbaseadaemumaclassequecapaz
daquecontmotipodeobjectoaseradicionado.Emoutraspalavras,vocnopodeadicionarumobjetocombaseem
umFoxPro"Visualcoluna"classeparaoutracoisasenoumagrade,noimportacomovocodefine.

Agregao
Aagregaootermousadoparadescreveratcnicaemqueumaclassedadoacessoaos
comportamentoespecfico(oufuncionalidade),criandoumarefernciaaumobjectoquejtenhaessa
comportamento,emvezdeatravsdaadiodecdigodirectamenteparaaclasse.Seissosoasemelhantecomposio,
,umavezqueacomposionaverdadeumcasoespecialdeagregao.Adiferenaque
agregaobaseadanacriaodeumarefernciaaumobjetocomoummembrodaclasse,enquanto
composiorequerqueoprprioobjetofilhosercriadocomoummembrodaclasse.o
consequnciaqueaagregaonolimitadasclassesdecontentoresenohnenhumaexigncia
paraoobjetoagregadoparacompartilharomesmotempodevidadoobjetoqueserefereaele.
precisamenteporcausaagregaodependede"acoplamentofraco"entreosobjetosque
tantomaisflexveldoqueacomposioepotencialmentemaisperigosos.maisflexvel
porquenorequercontentoresdirecta(demodoque,porexemplo,umobjectocombaseemumtexto
classedecaixapoderiaserdadaumarefernciadiretaaumoutroobjetocombaseemumDataEnvironment
classe).maisperigosos,porqueotempodevidadoobjetoquepossuiarefernciaea
objetoreferenciadonoestodiretamenteligados.Vocdevegarantirquetodasasrefernciassopropriamente
resolvidasaoliberarqualquerobjetoeissopodeserdifcilnoVisualFoxProporqueh
hnenhumamaneiraparaumobjetodesaberoqueasrefernciasexternasparaquepossaexistiraqualquermomento.
Aformamaissimplesdeagregao(e,portanto,omaisseguro)quandoumobjectorealmente
criaoobjetodedestinoemsieatribuirefernciadesseobjetodiretamenteparaumdosseusprprios
Captulo3:Design,Designerenadamais 61

propriedades.Aformamaiscomplexa,quandoumobjectoquertransmiteumarefernciaparaaprpria
outroobjeto,ouadquireumarefernciaaumobjetoexistente.

Delegao
Delegaootermoutilizadoparadescreverasituaoemqueumobjectoaoutroinstrui
executarumaaoemseunome.,efectivamente,umaformadeheranasemclassesporque
permiteafuncionalidadequenaverdadepertenceaobjetosdeumaclasseespecficaparaseracessadoporobjetos
quenoherdamessaclasse.Estaumaferramentaextremamentepoderosanoarsenaldodesenvolvedor
porquenospermitecentralizaronossocdigoechamarloquandonecessrio.
Opoderdedelegaopodeservistoquandoseconsideraasituaoemquevocprecisa
controlesparaumformulrioaserimplementadocomoobjetoscontidos(botes,porexemplo)ouCommand
comoobjetosautnomos(porexemplo,umabarradeferramentas).Obviamenteasituaocombotesemumformulrio
fcilosbotespertencemformadepoisdetudoparaqueocdigopodesercolocadonosseusprpriosmtodos.
bastante
Noentanto,umabarradeferramentasmaisdifcil.
Parafornecerbarrasdeferramentasdiferentesparacadatipodeformaseriatantodemoradae
umdesperdcioderecursos,paranodizerdifcildemanter.Aoadicionarocdigodiretamenteparaaformapadro
mtodospossvelcodificarasduasbarrasdeferramentasebotesgenericamentedemodoqueumnicoconjuntode
oubarradeferramentas(ouambas)podeserutilizadacomqualquerforma.Cadateclaindividual,ondequerqueelese
boto
podedelegarafunoaummtododeformaativanomomentoque,porsinal,
situa,
inteiramentedeacordocomanossadefinioanteriordeobjetosqueprecisamdesabercomoobteralgo
feito,semrealmenteprecisarsabercomoeleimplementado.

encapsulamento
Hdoisaspectosparaencapsulamento.Aprimeiraqueumobjetodeveserautosuficiente,e
quenodependedomodoemquepodeexistirumobjectotrabalhosforadoobjecto
si.evidentequesefossepermitidotaisdependncias,aherananoiriafuncionarcorretamentedesde
umaalteraonamaneiraemqueumaclassefoidefinidaafetarianoapenasosobjetosque
derivadadessaclasse,mastambmobjetosquedependiadeobjetosderivadosdefuncionamentoemuma
modoparticular.
Asegundaaexignciadeprotegerofuncionamentointernodeumobjetodeseuambiente.
Istonecessrioparaassegurarqueumobjectopodedesempenharasuafunodistribudosdeformafivelemtodos
situaesesegueapartirdoprimeiro.
Omecanismoparadefinirainteracodeumobjectocomoseuambientereferido
comoseu'InterfacePblico.MuitosdoschamadoslinguagensOOP'puros'exigirenvolventes
deumobjetoelimitarainterfacepblicaparaalgunsmtodosespecficos"geteset".Visual
FoxPro(paramelhoroupior)maisabertoe,porpadroumobjetoexpetodososseusPEMsem
suainterfacepblica,amenosqueoutrainstruoespecfica.O"acesso"e"Assign"
mtodos,introduzidasnoVisualFoxProVerso6.0,correspondem,emmuitosaspectosaoGete
mtodosindicadosacimareferidos,emboraaimplementaodiferente.

Polimorfismo
Polimorfismoumacaractersticadaslinguagensorientadasaobjetoquesurgedaexigncia
que,aochamarummtododeumobjeto,arefernciaparaoobjetodeveserincludocomopartedo
achamada.Aconsequnciaqueperfeitamentepossveltermtodosquetmomesmo

62 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

nomeemvriosobjectosdiferentes,masquenaverdadefazercoisasdiferentesemdiferentesobjetos.o
chamadaparaummtodosfazsentidonocontextodeumobjetoespecficoenoh,portanto,nenhuma
possibilidadedeconfuso.
Estaumaferramentamuitopoderosa,nocontextododesenvolvimentodeaplicaesemanuteno
porquepermitequeosobjectosseradicionadosoutrocadosunspelosoutros,semanecessidadede
naverdade,alterarocdigodoaplicativodetrabalho.

hierarquias
QuandotrabalharnoVisualFoxProimportantelembrarqueexistemdoisdistintos
hierarquiascomoqualvocestinteragindo:

Aprimeirao(ou"Inheritance")hierarquia"Classe"quedefinidopelasrelaes
dasdiversasclassesquevoccriar.orelacionamentodeumobjecto(atravsdasua
classepai)destahierarquiaquedeterminaoquePEMseleherdar.O
construoegestodahierarquiadeclasses,portanto,essencialmenteum
problema'tempodedesign".
Asegundaa(ou"Containership")hierarquia"Objeto".Istodeterminadopela
relaesentreosobjetos(independentementedasuaclasse)eosrecipientesemque
elesresidem.aposiodeumobjectonestahierarquiaquedeterminacomo
devegerirassuasinteracescomoutrosobjetos.Enquantoaconstruodoobjeto
Hierarquiapodeseriniciadanomomentodaconcepo,agestodoque,essencialmente,um"correr
questodetempo'.

objetoprticodeprogramaoorientada(POOP)
Tantoparaateoria,agoravamosaoquealgumasquestesmaisprticas.Aquestochave
comopodemostransformartodaestateoriaemprtica?Issooqueotombadilhotudoaver!(Temos,pela
forma,notouque"RegrasdeTrs'desempenhamumpapelimportantenomundodaPOOP).

Quandovocdevedefinirumaclasse?
Imediatamentensbatemosnossoprimeiro'RegradeTrs",quedefineoscritriosparadecidirqueumanova
classe(ouumanovasubclassedeumaclasseexistente)necessria.Estes,sugerimos,so:

Oobjetoestindoparaserreutilizado?
Serquevaifacilitaragestodecomplexidade?
Valeapenaoesforo?

Reusabilidade
Estaprovavelmentearazomaiscomumparaacriaodeumaclasseeparaarealizaodere
usabilidade,afinal,umdosprincipaisobjetivosdaOOP.Emseunvelmaissimples,issopodesignificarque
poucocomoacriaodesuasprpriasprefernciaspessoaisparaobjetosfonte,coreestilopara
exemplo,paraquetodososobjetosdesuaclassesocriadoscomasconfiguraescorretasnolugar.

Captulo3:Design,Designerenadamais 63

Ascoisasficamumpoucomaiscomplicadoquandovocconsiderarafuncionalidade.Quantasvezes,naprtica,no
fazerexatamenteamesmacoisa,exatamentedamesmamaneira,paraalcanarexatamenteosmesmosresultados,em

exatamenteomesmoambiente?Arespostaprovavelmente"nomuitofrequentemente"evocpodeat
comeamaseperguntarsereusabilidadetovaliosodepoisdetudo.Istolevanosperfeitamenteparaosegundo
critrio.

gerenciaracomplexidade
Comonssugeridonaseoanterior,realmentemuitoraroquequalquercoisaquenosejao
maissimplesdeclassesfuncionaispodesimplesmenteserreutilizado"talcomoest".Quasesemprehdiferenas
noambiente,aentradaouosrequisitosdesadae,porvezes,todoseles.este
aparentecomplexidadesvezespodeobscureceraquesto,oquequeafuncionalidadedesejada
mantmseconstante,emboraaimplementaopodemserdiferentesempormenorentreasaplicaes.
Aoaplicarasregrasparaaconcepodeaulasdescritasnaprximaseo,vocdeveencontrlo
maisfcildedecidirseusarumaclassefacilitaragestodestacomplexidadeouno.
Mesmoseacriaodeumaclassepoderiafacilitaragestodacomplexidade,aindatemosque
consideraronossoterceirocritrio.

Valeapenaoesforo?
Vocdeveselembrardissemosacimaqueumobjetodeveserencapsuladoparaqueelecontmdentro
setodasasinformaesnecessriasparacompletarasuamisso,equenenhumobjetodevesemprecontarcom
aimplementaointernadeoutroobjeto.
evidentequeestapodetornaravidaextremamentedifcil.Issopodesignificarquesuaclasseterque
verificardezenasdepossveiscondiesparadeterminar(porsis)exatamenteoqueoestadodo
sistemaantesqueelepossadesempenharasuafunoalocado.Aoconsideraracriaodeumnovo
classe,importanteteracertezadequerealmentevaleapenaoesforodefazlo.

Ento,comovocvaifazersobreacriaodeumaclasse?
Aprimeiraemaisbsicaexignciatercertezadequevocsabeoqueaclasserealmente
voufazer.Istopodeparecerbvio,masnoumaarmadilhasutilaqui.muitofcildeconstruirassim
muitoemcadaclassequevoccriarclassesqueantesquevocperceba,vocconstruiuquenoso
reutilizvelporqueelesfazemmuito!Asoluosempretercertezadequevoctenhaidentificado
dasResponsabilidadesdosdesuaclasse,ecategorizadoslosantesdecomearaescrevercdigo.
Aresponsabilidadepodesersimplesmentedefinidaaquicomo"umelementodefuncionalidadequetemde
serconcluda".Estacategorizao,deacordocomasnossas"Regrasdetrs",podeserfeitopor
atribuiodecadaresponsabilidadeidentificadosparaumdostrscompartimentoscomosesegue:
Imperdvel
poderiafazer
deveserfeito

Aesqueseenquadramnaprimeira'devemfazercategoriasoaquelascoisasqueumobjeto
derivadadaclasseteriaquefazeremcadasituaoeso,portanto,claramenteadireta
eresponsabilidadesnicosdaclasse.Estesdevemfazerpartedadefiniodeclasse.

64 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Coisasquevmnacategoria'poderiafazer'normalmentesoindicadoresdequeaclassepode
seexigirumaoumaissubclasses(ou,maisraramente,acooperaodeobjetosde
outraclasse).Emoutraspalavrasestassoascoisasqueseriapossvelparaaclasseparafazer,
masquenoseriarealmentenecessrioemcadasituao.Eleainclusodetais"poderia
Do'itensemumadefiniodeclassequerealmentepodemimpedirqueadefiniodeserreadequadamente
utilizvel.
Altimacategoriamuitoimportante.Estaacategoriaquedefineo
'suposies'queumaclassedevemtercumprido,afimdefuncionarcorretamente.Ositenslistadosaquiso
definitivamentenodaresponsabilidadeexclusivadaclasseemquesto,devendo,noentanto,serfeito
dealgummodo.
Tendodefinidoecategorizadasasresponsabilidadesdanovaclasse,vocdevedefinirasua
Interfacepblicapordecidiropropriedadesemtodosquevaiexigir,ecomoeleirrevelar
seaoutrosobjetoscomosquaiseleirinteragir.
Porfimvocpodecodificaradefiniodeclasse,instanciarumobjetocomeleetestlo
(completamente).Masquandotudoestiverfeito,vocaindanoterminouporquevocdevecuidadosamente
documentaranovaclasseequaisquersubclasses.

Issotudosoamuitobom,masoqueissosignificanaprtica?
Considereumexemplosimples.Acriaodeumabarradenavegaopadrotabelaquepodeparecer
algoassim:

Figura3.1UmpadroTabelaBarradeNavegao

Serqueprecisamosdeumaclasseparaissoemtudo?
Seguindoospassosdescritosacima,podemosavaliaranecessidadedeaclassedaseguinteforma:

Serquevaiserreutilizvel?Enquantoissoir,decertaforma,dependemdotipode
aplicaesquevocestconstruindo,navegaoatravsdeumatabela(oucursorouvista)um
exignciafundamentaleporissoestarealmentedeveserreutilizveisemmuitosdiferentes
situaes.
Serquevainosajudaragerenciaracomplexidade?Arespostaaquitambm"sim".Atarefareal
denavegarentreosregistrosemumatabela,cursorouexibionoparticularmentedifcilem
VisualFoxPro.Masaindahquestesqueprecisamsertratadas(comooquefazerno
inciooufimdeumarquivo,porexemplo).
Valeapenaoesforodecriaraclasse?Dadasasrespostasaosdoisprimeiros
perguntas,esteumacfalobastanteclaroquensrealmenteprecisamosdeumaclassepara
estatarefa.
Captulo3:Design,Designerenadamais 65

Ento,quaissoasresponsabilidadesdaclassev aiser?
Issofcilelevailidarcomanavegaoentreosregistrosemumatabela,cursorou
Viso!Infelizmente,enquantoissodescreveainteno,elerealmentenonosdizemoqueo
"responsabilidades"daclasserealmenteso.Amelhormaneiraqueencontramosdefazerissoescrever
parabaixotodasascoisasquepodemospensarcomoelesocorremparansassim(isto,nosignificauma
listacompleta):

EcrdemensagemparaReCyclenaBOF()/EOF()
CertifiquesedeDadosdatabelaestaberta
Certifiquesederegistrosestodisponveis
PegaBOF()/EOF()Erros
ponteiroderegistroMover
formulriopaiAtualizar
Escolhareadetrabalhocorreto
ativarseletivamente/Desativarbotes
EscolhacampoespecficonaConcluso

Tendocriadonossalista,emseguida,aplicaro"MustpoderiaCaso"regraparacadaitem,afimde
refinaranossadefiniooresultadopoderiaseralgocomo:

Tabela3.1refinadolistaderesponsabilidades

Responsabilidade Categoria
EcrdemensagemparaReCyclenaBOF()/EOF()
Poderia
Garantirqueosdadosdatabelaestaberta Devemos
Garantirqueosregistrosestodisponveis Devemos
LidarcomBOF()/EOF()Erros Devo
Moverponteiroderegistro Devo
Formulriopaideatualizao Devo
Selecionereadetrabalhocorreto Devemos
Seletivamentehabilitar/desabilitarBotes Devo
SelecionecampoespecficonaConcluso Poderia

Apartirdestalista,podemosverimediatamentequetemosquatroitens'devefazer'.Estessero
necessriaemtodasassituaesedeveformarabasedadefiniodeclasse.Osdois"poderiaDo'
itensclaramenteseaplicaapenasemsituaesespeciaiseso,portanto,candidatossubclasses
umavezquenoqueremosqualquerumdessescomportamentosemtodasassituaes.
Ostrsitens'devefazer'somaisinteressantes.Claramentenossaclassenofuncionarsenohouver
mesaestdisponvel,ouseeleestaberto,masnocontmregistros,masnem(presumivelmente)seria
qualqueroutracoisanoformulrioqueabrigaocontrole.Comoparaselecionararea"correta",porque
deveocuidadobarradenavegaodatabelaquesenavegaem?Nenhumdestessotarefasqueserelacionam
unicamenteparaaclassebarradenavegaotodostmramificaesmaisamplasedevemserendereadas
foradestaclasse.

66 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Simplificando,afunodaclassebarradenavegaoparamoveroponteirodoregistro,manusear
quaisquererrosquepossamsurgirapartirdessemovimentoeatualizarseuformulriopaiquandoeletiverterminado.
Nenhumaoutraclassepoderialidarcomqualquerumadessastarefas,enohtarefasaquiquenoserelacionem
unicamenteparaaclasseemquesto.
Esteagoraseparececomumadefiniodetrabalhoepodemosavanarparaaprximafase.

Comovocvaifazersobreaconstruodesuasaulas?
Aquioutra"regradetrs"destavezrelacionadacomamaneiraemquevocprojetareconstruir
suasbibliotecasdeclasseseasclassesneles.

Projetesuaestruturadeclassecomoumtodoantesdecodificarqualquercoisa
Procurepadresquandoadefiniodeclasses
CdigoemMtodos,noEventos

Estruturabibliotecadeclasses
Nohregrasrgidaserpidassobreoassunto.NaverdadeVisualFoxPronotavelmenteflexvelneste
respeito(umabibliotecadeclassesapenasumatabelaapstodos)enofazsuposiesqualquersobre
bibliotecasdeclasses.Sevocquisesse,vocpoderiamantertodososseusclassesetodasassuassubclassesemum
bibliotecanica.Noentanto,esteseriaprovavelmenteficarumpoucopesadodepoisdeumtempo,porisso
recomendadoquevoctrabalhadentrodeumaestruturadebibliotecalgica.Outraconsideraoaterem
mentequequandosetrabalhaemumambientedeequipe,sobcontroledeorigem,mantendotodooseu
classesemumabibliotecapodetornaramanutenomuitodifcilmesmo!
Essencialmente,vocpodediferenciarasclassesemtrsgrupos(maisuma"regradetrs"):

Raiz(sumrio)Classes
Classesgenricas
Aplicaoclassesespecficas

AsclassesderaizsoassuassubclassespessoaisdasClassesVFPbasesobreaqualtodaa
restantedesuasclassessoconstrudas.Estesnuncadeveserusadoparainstanciarobjetosdiretamente
eporissosoasclasses"abstratos".Classesgenricossoaquelesquenosoespecficosparaqualquerparticular,
aplicaoenormalmenteconsistemdeseuscontrolespadro.Aaplicaoespecfica
classesso,naturalmente,osquesocriadosparaumaaplicaoesersubclassesdequalquerseu
classesderaizouum(oumais)dasclassesgenrico.
Sevocoptarporsubdividiraindamaisvocbibliotecas,naturalmente,inteiramenteatvoc.
Fazemosmantertodososnossosclassesdeformulrioemumabibliotecaseparada.Nstambmcriarbibliotecasindividuais
gruposdeclassesqueestorelacionadoscomafuncionalidadeespecfica.(Nosso'Graphics.vcx'umexemplo
para
deumabibliotecafuncional.Todasasclassesnestabibliotecaestopreocupadoscomaexibiodevrios
tiposdeinformaesgraficamentenatela.Istopermiteaexclusodetodaabibliotecaapartirdeum
aplicaosenofornecessrio).

Captulo3:Design,Designerenadamais 67

Procurepadres
padresdeprojetosoumaformadecomunicarexperinciaemdesigneconhecimento,porque
problemassempreprecisamdesolues.Naturalmenteproblemassemelhantestendemagerarsoluessemelhantes
earazoqueassoluessosemelhantesqueelescompartilhamumncleocomum,ouabordagem,a
resolveroproblema.Umpadrodedesignsimplesmenteumreconhecimentodeumncleotaleumadescrio
dequeoncleodetalformaqueelepodeserusadoemmuitoscenriosdiferentes.,emsuma,um
descriogenricadecomoresolverumproblema.Note,noentanto,queumDesignPatternnoum
soluoparaumproblema.Padressotorelevantesnocontextodaconcepodeaulascomoeles
soparaodesigndaaplicao.Aoprojetarsuasprpriasclassesimportanteolharparaospadres
emsuasexignciasparaquesuasprpriasclassespoderefletirospadresqueserousados
quandoelessoimplantados.
Delonge,amelhorrefernciaquetemosencontradoatagoraparaaprendersobreospadresoexcelente
'DesignPatterns,elementosdesoftwarereutilizveisorientadaaobjetos,'porGamma,Helm,Johnson
eVlissidespublicadopelaAddisonWesley.Nsfortementerecomendamosquevocobterumacpiadesta
livro,queremsuportedepapel(ISBN0201633612)paraquevocpossarabiscarnasmargens,ouna
formatomaisrecenteCD(ISBN0201634988),assimvocpodelevloaoredor,procurarloecitlo
maisfacilmente.

Cdigonosmtodos,enoev entos
Istonorealmenteumaregra,masachamosqueumaboaprtica.Aocodificarsuasclassestentarevitar
colocandocdigodiretamentenosmtodoseeventosnativasdoVisualFoxPro.Emvezdissocriarpersonalizado
mtodosechamarosdosmtodosnativos.H,naverdade,nenhumaexignciaparafazer
ascoisasdessamaneira,masvaitornarsuavidamaisfcilpara(maisumavez)trsrazes:

Emprimeirolugar,permitelhedarnomessignificativosaoseucdigomtodo.Issopode
parecertrivial,mastornaamanutenomuitomaisfcilquandoocdigoquerealmente
'calculaoimposto'chamadopor' ThisForm.CalcTax()'emvezde
' ThisForm.CmdButton1.Click()'
Emsegundolugar,permitelhemudarainterface,senecessrio,porsimplesmenterelocalizaro
nicalinhadecdigoquechamaomtodo,emvezdeterdecortarecolar
cdigofuncional(comtodasaspossibilidadesdeatendimentoparaoerroqueissoimplica).
Finalmenteelepermitequevocquebrarocdigocomplexoemmltiplas,(epotencialmentere
utilizveis)mtodos.Ocdigonomtodoassociadoaoeventoapenasatuacomoo
iniciadorparaoseucdigo.

Masserquetodoestematerialprojetorealmentefuncionanaprtica?
Bem,nscertamentepensoassim!Osarquivosdeacompanhamentoparaestecaptulo,nodiretrioCH03,
incluemumprojetoqueimplementaosconceitosdedesigndiscutidosacima.Figura3.2(abaixo)
mostraaguiaClassesdoprojetoemumestgioinicialnodesenvolvimentodasbibliotecasdeclasse.
Mesmoqueapenasparcialmenteconstruda,aestruturadebasejevidente.

68 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura3.2estruturadeclasseExemplo

Teremosmaisadizersobreaconvenodenomenclaturamaistarde.Porenquanto,vamosolharpara
aestruturadeclasseaqui.Oquevocvoinciodenossasbibliotecasdeclasse"genrico".medidaqueo
nomeindicaestasbibliotecascontmasclassesquenocontenhamqualqueraplicaoespecfica
funcionalidadeesoefetivamentea'padro'controlesquecriamos.

AbibliotecaRootClas.v cx
Oprimeiro(nvelmaisbaixo)bibliotecaemnossaestruturanomeadoRootClas.vcxeestecontmoprimeiro
subclassesnveldoscontrolesVFPBasededadosdeclasse.umabibliotecaabstrato(anicafunode
essasclassesseropaideoutrasclasses)eaulasdestabibliotecaso,portanto,
Nuncainstanciadodiretamente.Damesmaformaasnicasclassesquesosempreadicionadosaesta
bibliotecaso"deprimeironvel"classesabstratas.Essaregraserveduasfunes:

Eleforneceuma"isolamento"camadaentrenossasclasseseasclassesVFPBase.
CasoumanovaversodoVFPpadresoucomportamentodaclassebasemudana,cdigoexistentepode
sercorrigidosimplesmentemudandoaclasseraizapropriado.
Elegarantequeasconfiguraespadro(equaisquerpropriedadesemtodospersonalizadosqueso
adicionadosclasseroot)estodisponveisparatodasasclassesdescendentes.Alteraesnaraiz
classeser,pordefinio,serrefletidaemtodasasclassescombasenelas.
Captulo3:Design,Designerenadamais 69

AbibliotecaGenForms.v cx
Aprximabibliotecaumabibliotecafuncional,usadoparaconternossasclassesdeformulrio.Arazopara
dividilosparaforaemumabibliotecadesuaprpriasimplesmenteparaquensnotemosclassesdeformulrio
desordenarabarradeferramentasControles.Umadasmuitasmelhoriasamigvelparadesenvolvedores,que
VFP6.0introduzida,foiumaextensoparao CREATEFORMcomandoquelhepermite
especificaraclassedaqualonovoformulrioestasercriado.Aodesenvolver,noh
maisnecessidadedemexercomaconfigurao"Opesdeformulrio",oucriarumformset,adicionarumaformade
aclassenecessriaeexcluiraclassebasequefornecidoporpadroeassimpordiante.estecomando
agorafazotrabalho:

CRIARMeuNovoFormulrioFORMAASxFrmStdDEgenforms

Todasasclassesnestabibliotecaemltimaanlise,descendemdeclasseraizdo'xfrm'.Apropsito,
nanossaconvenodenomenclaturaonomedeumaclassesempreindicaasualinhagem(istoconseguidoatravs
nomeandoocomumsufixoaonomedaclassedaqualderiva).Nscomoesteporque
garanteque,quandoumabibliotecalistadoemordemalfabtica(comonogestordeprojecto,ouo
ModificardilogoClasse)elestambmestoemordemdeherana.Ento,sensparaadicionarumnovoformulrio
classeparaestabibliotecacombasenaclassedeformulrio'standard',eleserianomeado"xFrmStdData"e
'Dados'
aparecerianalistagemimediatamenteabaixodaclasse'xFrmStd'.
Esteumpontoimportanteporquenohnenhumarazoparaquetodasasclassesemumabibliotecadeveser
nomesmonveldeherana,mastilparasercapazdedistinguir,emresumo,ondeapenas
umadeterminadaclassesesentaemsuahierarquia.

AbibliotecaGenClass.v cx
Estabibliotecacontmtodasasnossasaulas"genricos"eabibliotecaque,porpadro,carregado
emcontrolesdeformulriobarradeferramentas,VFPnainicializao(Vejaabaixoparaobterdetalhessobrecomofazer
acontecer).Soasclassesnestabibliotecaqueusamosparacriarnossosobjetos.Nossaconvenoque
isso
cadacontrolenabibliotecadeclasseraiztemumaverso"Std"nabibliotecaGenClassquea
baseparatodasasoutrasclasses,subeaverso'standard'docontrolequeusamosquando
criarcontrolescompostos.
Emalgunscasos,aclassepadroefectivamenteumacpiasimplesdaclasseraiz,enquantoqueemoutros
aclassepadropodeintroduzirumafuncionalidadeadicionalquensprojetamosconformeaplicvel
atodasasclassesfuturas.Porexemplonossaclassebotodecomandopadrotemumnovomtodopersonalizado
adicionadosaelechamado'OnClick'.OVFPnativoCliqueMtodofoialteradodemodoaque,por
padro,elesimplesmentechamaomtodoOnClickaquetodoonossocdigonveldeinstnciaser
colocou.
Mesmoquemaistardemudaranossamenteeacharqueprecisamosdeumaclassequenoincluitais
funcionalidadeadicional,noestamostotalmenteperdidoporquepodemossimplesmenteusaranossaclasseraizquea
paiparaumanovahierarquiadeherana.

Comoqueoprojetorealmentetraduziremcdigo?
Sevocolharparaaclassebarradenavegao(sim,finalmente,voltaraele),vocvaiverquetemos
construiuloparaquetudooqueosbotesdecomandofazerchamarseparaopairecipientede
NavegarmtododasuaAoFazerCliquemtodo.Istoestdeacordocomoprincpiodequeumobjecto

70 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

sprecisasabercomofazeralgumacoisasemrealmentesaberoqueocdigoestsendo
implementado,oqual,nestecaso,foiexecutadousandoadelegao.Todososbotespodem
agoratmomesmocdigoemseuOnClickmtodo(eapenasumalinha)emboracadapassagem
umparmetrodiferente,comomostrado:

PrimeiroButton:This.Parent.Navigate('first')
AnteriorButton:This.Parent.Navigate("PREV')
Botoseguinte:This.Parent.Navigate('Avanar')
ltimaButton: This.Parent.Navigate(last)

DoContainerNavigatemtodoondeamaioriadotrabalhofeitoeondeo
cdigorealquemoveoponteirodoregistroestlocalizado.Emboraestesejaummtododo
navegaoclassebar,ocdigonodependedeoutracoisasenoqueestsendopassadoum
parmetroindicandootipodenavegaonecessriaeassimfuncionarigualmentebemsesetrata
chamadoapartirdeumdosbotescontidosououtra,externa,objeto:

LPARAMETERStcMoveTo
lcMoveToLOCAL,lcNewPos,lnRec
IFVARTYPE(tcMoveTo)#"C"ouvazio(tcMoveTo)
RETURN.F.
FIMSE
lcMoveTo=UPPER(ALLTRIM(tcMoveTo))
lcNewPos='MID'
***Agorapodemosprocessaroparmetro
DOCASO
CASElcMoveTo="NEXT"
***Irparaoprximoregistro
PULAR
IFEOF()
***Estvamosnoltimoregistrodequalquermaneira
GOBOTTOM
***SituadoBandeiraPosioconformidade
lcNewPos="LAST"
OUTRO
***Serquevamosmoverparaoltimoregistro
lnRec=RECNO()
PULAR
IFEOF()
***Simnsfizemos,definirosinalizadorposio
lcNewPos="LAST"
FIMSE
GOlnRec
FIMSE
CASElcMoveTo="PREV"
***Irparaoregistroanterior
SKIP1
IFBOF()
***EstvamosnoPrimeiroregistrodequalquermaneira
SEJAOMELHOR
***SituadoBandeiraPosioconformidade
lcNewPos="primeiro"
OUTRO
***Serquevamosmoverparaoprimeiroregistro
lnRec=RECNO()

Captulo3:Design,Designerenadamais 71

SKIP1
IFBOF()
***Simnsfizemos,definirosinalizadorposio
lcNewPos="primeiro"
FIMSE
GOlnRec
FIMSE
CASElcMoveTo="LAST"
***Vaidurarregistro,assimfazloedefinirosinalizador
GOBOTTOM
lcNewPos="LAST"
CASElcMoveTo="primeiro"
***Indoparaoprimeiroregisto,assimfazloedefinirosinalizador
SEJAOMELHOR
lcNewPos="primeiro"
DEOUTRAFORMA
***Temosumparmetroinvlido!Nesteexemplo
***Vamossimplesmenteignorloeabandonaromovimento
***Masretornaruma".F."nocasodeestemtodoestsendo
***Chamadoexternamente!
RETURN.F.
ENDCASE

Observequeainstruocasoseordenaparaqueoprximo/mtodosanterioresvirantesdo
OsltimosPrimeiro.NoVisualFoxProavelocidadedeexecuodeum DOCASOdeclaraodependedo
posiorelativadainstruoquevaiserexecutada.provvelqueestecdigoser
chamadonamaioriadasvezesparaanavegaoetapanicadoqueparasaltos,porisso,estasopessocolocadosem
,nesteexemplo,umpequenoponto,masvaleapenaficarohbitodefazer.
primeirolugar.isto
Tambmadotamosumaestratgiadeatribuirumavarivellocalqueindicaacolocaode
oponteirodoregistronatabeladepoisdenavegao(lcNewPos).Estefoiinicializadapara
"MID"omeiodatabelasendooresultadomaisprovvelemumaplicativoemexecuo.estevalor
entopassadaparaoutromtododerecipientequemanipulaaativaoedesativaodo
botesdeacordocomovalorquerecebe:

***ContactaromtodoSetButtonsparaativar/desativar
***Masdesativaratelaemprimeirolugar!
Thisform.Lockscreen=.T.
This.SetButtons(lcNewPos)
***ContactaromtodoRefreshParentparaatualizaraexibio
This.RefreshParent()
***Reativaratela
Thisform.Lockscreen=.F.
***Qualquermtodoretorna.porpadro,demodoqueestenorealmentenecessrio
***Mastilquandopercorrendoocdigo,umavezquepermiteuma
***Pontodeinterrupoparaserconfiguradoparaverificarvalores
RETURN.T.

Aresponsabilidadefinal(refrescaroformulriopai)tratadoporumoutrorecipiente
mtodo,oRefreshParentmtodo.Aodividirseafuncionalidadecomoestequepodemoslidarcom
diferentesmtodosdenavegao(chamandomtodosdeformulrioemvezdisso,porexemplo),simplesmente
substituindooNavigatemtodoquandonecessrio.Damesmaforma,podemosmudarocomportamentodoboto
ouatualizarcomportamento,semafetarqualqueroutracoisa.

72 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Esteltimopontomuitoimportante.SevocexaminaroRefreshParentmtodoquevocvainotar
querefereexplicitamenteaThisForm:

***Estemtodoatualizaoformulriopaiparaabarradenavegao
***SenstemosummtodoRefreshForm,chamlo,casocontrrio,usaAtualizarnativa
IFPEMSTATUS(ThisForm,'RefreshForm',5)
ThisForm.RefreshForm()
OUTRO
ThisForm.Refresh()
FIMSE

IssonoumasuposiorazovelporqueparafazerumobjetovisvelnoVisual
FoxProquedeveestarcontidoemumformulrioouumabarradeferramentaseoaspectovisualdeste
controlecomoatemosagoraotornaimprprioparaumabarradeferramentasnoseuformatoatual.

Criarumasubclasseparausoemumabarradeferramentas
Paracriarumabarradenavegaoqueseriaadequadoparaumabarradeferramentasquepodemossimplesmentesubclasseeste
controleesubstituiroRefreshParentmtodonasubclassedeutilizaraformade
referenciandomaisapropriadoparaumabarradeferramentas(ouseja_SCREEN.ACTIVEFORM,emvezdeThisForm).Tal
umasubclasseincludonoprojetoCH03,evocvainotarque,almdemudaro
aparecimentodaclasse,onicocdigoquetevequemudaronicomtodoquetrata
comaatualizaoqueagoraseparececomisso:

***Essemtodosubstituiocomportamentodaclassepaiqueatualizaaforma
***Eusa_SCREEN.ACTIVEFORMvez
COM_SCREEN.ACTIVEFORM
IFPEMSTATUS(_SCREEN.ACTIVEFORM,'RefreshForm',5)
.RefreshForm()
OUTRO
.Refresh()
FIMSE
ENDWITH

One'pegadinha'possvelaquiocorrequandovocestiverusandoformulrioscomDataSessionsprivados.
Qualquerbarradeferramentasqueestcontandocom_SCREEN.ACTIVEFORMparaacessarosdadosassociadosaessa
devegarantirqueeleligaseemprimeirolugarnamesmadatasession.Istonotosimplesquanto
forma
poderiaparecerprimeiravista,porqueabarradeferramentasnopodereceberofoco.Noentanto,vocpodeusaro
seguintecdigonoMoverRatomtodoparalidarcomoproblema:

IFTYPE("_SCREEN.ACTIVEFORM")="O"E!ISNULL(_SCREEN.ACTIVEFORM)
This.DataSessionId=_Screen.ActiveForm.DataSessionId
FIMSE

Outrasextensesparaaclasse
Outraextensotilparaestaclasseseriaadicionarcomportamentoparaqueeleajustaautomaticamente
asconfiguraesdobotoquandoeleinicializadoetalvezsemprequeoformulrionoqualelereside
reativado.Parafazerisso,seriaadicionaroutromtodopersonalizado(talvezCheckRecPointer
seriaadequadoumnome).Esteseriadeterminarseoponteirodoregistroaprimeira,altima
ouumregistrointermediriaechamaroSetButtonsmtodocomoparmetroadequado.o

Captulo3:Design,Designerenadamais 73

novomtodopoderia,ento,serchamadoapartirdoInitdoprpriorecipienteparalidarcomainicializao
eporumeventoexterno,comoumaformaAtivarouumabarradeferramentasMouseMoveparaforarumestatuto
atualizar.

Concluso
Esteexemplo,emboratrivialemdetalhes,mostraoquoimportanteprojetoestnaObjectOriented
meioAmbiente.Odesenhofinaldessecontroleumlongocaminhodesdeaabordagem"tradicional"
ondeocdigoparamoveroponteirodoregistroteriasidocolocadodiretamentenosbotes.
Osegredodeumbomdesign,naverdade,estemdeterminaroquecadacomponentenaclasse
realmenteresponsvel.Assim,noexemplobarradenavegaoacima,averdadeiraresponsabilidadedo
botesreconhecerqueousuriodesejanavegardeumaformaparticular,epara
comunicaressefatoparaomanipuladorapropriado.Estesbotesquenoprecisaserresponsvel
parafazerqualqueroutracoisae,portanto,nodeveFAZERqualqueroutracoisa!

Trabalhandocomsuasclasses
Depoisdeterdefinidoassuasaulasvocvai,naturalmente,quercomearauslosemseudirio
trabalharemvezdesimplesmentecortarasclassesbasedoVisualFoxPronumabase"conformenecessrio".Faam
issoefetivamentevocprecisasercapazdeinstruirFoxProquandousarsuasclassesemvezdo
defaultspadrofornecidoscomoproduto.

Comofaoparaqueminhasaulasnabarradeferramentascontrolesdeformulrio?
Abarradeferramentascontrolesdeformulriomostraocontedodeumabibliotecadeclassesaqualquermomentoe,por
abreasClassesdeBaseVFPcomo'Standard'.Paraalteraroqueexibido,selecioneoconedabiblioteca
padro
decontrolesdeformulriobarradeferramentas(Figura3.3).

Figura3.3A"Biblioteca"conenabarradeferramentasdecontroledeformulrio

Istoirabrirummenupopupquemostratodasasbibliotecasdisponveisatualmente,quevoc
podeselecionaretornaratual,equetambmpermitequevocadicioneumabibliotecaadicionalao
barradeferramentas.
74 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura3.4OAdicionarBibliotecadeclassespopup

Asentradaspara'controlesActiveX''padro'eestosemprepresentes.Vocpodeadicionarumou
mais,bibliotecasaestalistacomopartedoprocedimentodeinicializaodoVisualFoxPro,especificandoo
arquivosdebibliotecanecessriosnaguiacontrolesdacaixadedilogoOpesdoVFP.Quaisquerbibliotecasdefinidasaqui
soarmazenadosnoRegistrosobachave:

HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\6.0\Options\VCXList

EmboraalistadebibliotecasparacarregararmazenadonoRegistro,abibliotecaquevocestavausando
ltimaarmazenadonoarquivoderecurso.Ento,sevocquiserpreservarasuaposioentre
SessesdeFoxPro,vocdeveter conjuntoderecursosON.
Paraalterarabibliotecaqueserexibido,bastaabrirtantooformulriooudesignerdeclasse,
selecioneabibliotecaquedesejatornaratual,emseguida,salvarasalteraesaofecharo
designer.Aprximavezquevocabrirodesigneraltimabibliotecausadasernabarradeferramentaspara
voc.

Enquantoestamosnoassunto,comopossoidentificarminhasaulaspersonalizadasno
barradeferramentas?
Todasasclassestmduaspropriedades(quepodemseracessadospormeiododilogoInformaesdeclassepor
selecionandooblocodeclasseapartirdomenuenquantonaclasseDesigner)chamado'Containercone'e
"conedabarra'.Aprimeirarefereseaoconequeapareceaoladodonomedaclassenoprojeto
Gerente.Asegundarefereseaoconequeserexibidonabarradeferramentascontrolesdeformulrio.
VFPestesperandoumtamanhodeimagemde16x16pixelsparaessescones,eapesardesereferiuaelescomo
'cones',vaiaceitarqualquerformatoBMPconeouparaexibio.
AbarradenavegaonabibliotecadeclassesCH03.vcxfoiatribudobitmapsseparadospara
asduaspropriedades.Arazoparaanecessidadedoisqueofundoparaoconedabarradeferramentas
cinzaclaro,masparaoconedocontinerdeveserdecorbranca.
Assim,bastantefcildefazer,masacriaodeimagenssuficientementedistintivasememorveis
revelouseumpoucomaisdifcil,econfessamosquetemosatendnciadeficarcomoVFPpadro
conesmenosquehajaumamaioriaesmagadoraboarazoparafazerocontrrio.Depoisdetudo,onomedeclasse

Captulo3:Design,Designerenadamais 75

automaticamenteexibidonadicadeferramentaparacadabotonaformacontrolabarradeferramentasens
acharqueissogeralmentesuficienteparaasnossasnecessidades.(Emboraumdosnossoslistadedesejositensqueo
dicadeferramentaexibiradescriodaclasse,emvezdonome,seestiverdisponvel.)

NoVisualFoxProVerso5.0eposterioraexibiodeumaclassede
'coneContainer'nogerenciadordeprojetocontroladopelaconfiguraodo
umacaixadeseleonaguiaProjectdacaixadedilogoOpesglobais.Aentrada
nosarquivosdeAjudasobreosconesdecontentoresnomencionaestapeaemvezdevital
emformao.

Massemprequeeuquerobranconasminhasbitmapseleaparececinza!
UmadaspeculiaridadesirritantesdoWindows'queeleinterpretabrancoemumarquivodebitmapouconecomo
transparenteeexibe,emvezdisso,acordefundopadro.Paraevitarqueisso
acontecendo,vocprecisacriaruma"mscaradearquivo"paracadabitmapqueusabranco,emquetodaa
reasquevocdesejavercomobranconobitmapapresentadossodecorpreta.Esteomelhorfeito
modificandooseubitmaporiginalesalvlocomum'.mskextenso'namesma
diretrio.Figura3.5mostracomoosmapasdebitsearquivosdemscaraqueusamosparaanossabarradenavegao
exemplorealmenteolhar.

Figura3.5UsandoumarquivoMSKparaexibirbrancoembitmaps

Semoarquivodemscara,bitmapdo'CNNavbar"olhariaexatamenteomesmoqueo
"TBNavbar"bitmap,mascomamscaradearquivoeleserexibidocorretamente.Vocpodevero
resultarnaguiaClasseprojetoCH03.

ComopossofazerVisualFoxProusarminhasaulas,emvezdabase
aulas?
VisualFoxPro5.0introduziuo"Intellidropfuncionalidade",quepermitedefinirquais
classessousadasparacontrolesquesocriadosquandoumcampodedadosarrastadoparaumformulriode
ouoDataEnvironmentounaguiadadosgerentedeprojeto.Hduasmaneirasdeconfigurar
Essainformao.
AsinformaespadroqueVFPusaarmazenadonoRegistronachave:

HKEY_CURRENT_USER\Software\Microsoft\VisualFoxPro\6.0\Options\Intellidrop

76 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Senohnadanessachave,emseguida,soutilizadasasClassesVFPBase.Paraconfiguraroseuprprio
classescomopadresquevocpodeusaraguiadacaixadedilogoOpesdo'mapeamentodecampo'.Issopermitequevoc
paradefinirqualaclasse,apartirdoqualbiblioteca,aserusadoparaoscontroloscombasenotipodedadosdocampo
(verFigura3.6abaixo).Quaisquerconfiguraesdefinidasaquiserosalvasparaoregistroeusadopara
todasastabelasporpadro.
Sevocestiverusandoumrecipientedebancodedados,voctemoutramaneiradecriarIntellidropque
substituirquaisquerconfiguraespadroemumcampoporcampobase.Nodesignerdetabelaparaolimite
mesashum"Mapadotipodecampoparaasaulas",ondepodedefiniraclasseebiblioteca
paraserusadosemprequeumcampoespecficoarrastadoparaumformulrio.Issosubstituiqualquerconfiguraopadro
etilquandovoctemumcampoondeaclasseaserusadodependedorealcontedo
emvezdotipodedados(porexemplo,vocpodeterumaclassecaixadetextoZipCodeespecialque
deveserutilizadaemqualquermomentonecessrioumCEP).

Figura3.6MapeamentodecamposdedilogoparadefinirasclassesIntellidroppadro
ComofaoparamudaralegendadortuloqueVFPacrescenta?
Aoarrastarumcampoparaumformulrio(ounodesignerdeclasse)apartirdequalquerambientededados,
ouapartirdogestordeprojecto,ocomportamentopadrodoIntellidropadicionarumaetiquetacujalegenda
onomedecampo.Estaanicaopoqueestdisponvelparaumamesalivre,masparatabelas
quefazempartedeumbancodedadosexistemalgumasconfiguraesadicionaisquepodemserfeitas.

Captulo3:Design,Designerenadamais 77

NovamentenaguiaMapeamentodecamposdacaixadedilogoOpesforneceomecanismoparaacriao
comportamentospadro.Observeascaixasdeseleoaopdestedilogohquatrodeles.

Arrastaresoltarcampolegenda:Quandomarcado,VisualFoxProiradicionarumaetiqueta(de
qualquerclassequetiverdefinido)paracadacampoquandoelearrastadoedefinasualegendapara
o"Legenda",definidanodesignerdetabelaparaessecampo.Senohouverumsubttulodefinido,
ouamesaumamesa"livre",onomedocamposerinseridoemseulugar.Paraevitarqueo
adioautomticadeumaetiqueta,apenasdesmarqueestacaixa.
campoCopiarcomentrio:Cadacontroletemumapropriedade'Comentrio'.Quandoestaopo
verificouocontedodo"Comentrio"propriedadedocamposoinseridosno
propriedade"comentrio"docontrolededestino.
Cpiamscaradeentradacampo:Garantequequalquermscaradeentradaquefoidefinidona
bancodedadoscopiadoparaoInputMaskpropriedadedocontroleinserido.
formatodecampoparatexto:Garantequequalquerformatoquefoidefinidonobancodedados
copiadoparaoformatodepropriedadedocontroleinserido.

Quandosetrabalhacomtabelasligadas(aquelesquefazempartedeumrecipientedebasededados)daTabela
Designerforneceacapacidadededefinirtodosositensacimanoterrenoindividual.Essesso
extremamentetile,emnossaexperinciadequalquermaneira,lamentavelmentesubutilizadopelosdesenvolvedores.
partedeseuprojetodebancodedadosvocdevesempredefiniraspropriedadesdalegendaecomentrioComoum
Como
mnimo.
OnicoinconvenientequealegendatambmusadopeloVisualFoxProparaGradeHeader
(Oquetil)eExplorarjanelas(quesevoc,comons,tendemausarumalinhadecomando
NAVEGARparaverificarnomesdecamponototil).Podeseroltimocomportamento,paraoqualexiste
nosubstituir,oqueexplicaporquemuitosdesenvolvedoresparecemrelutantesemusaronveldecampo
capacidadesfornecida.

Paraqueeupossaobterumbrowseparamostraronomedocampoquandouma
conjunto?
legenda
Bem,naverdade,vocpode,porquenoVisualFoxPro,ajanelaProcurarpassaaserumagrade
objeto!Tenteestecdigoapartirdalinhadecomando:

Osclientesusam
PesquisarNOMEoBrowseNOWAIT
***Minimizarjaneladenavegao(paraquevocpossaveratela)
EXIBIODEMEMRIACOMOoB*

Oresultadoser:
OBROWSE bar O GRADE

Ento,sevocprecisasercapazdenavegarnumatabelaeverosnomesdecampo,tudoquevocprecisaumpouco
programa'decorador'paramelhoraropadrodecomandoProcurar.Oprogramaaseguirfaz
apenasissoepoderiaserumcandidatoparaoseuarquivodeprocedimento'DevelopmentEnvironment"(ns
esperoqueissonoteriavaloremtempodeexecuo!):
78 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

**********************************************************************
*Programa :BrowExt.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:DecoratorparaopadroNavegarcomandoquerestaurao
* :NomedecamponolugardealegendanajanelaProcurar
**********************************************************************
***EstaversosfuncionanoVFP5oumaistarde
lnCntLOCAL
PesquisarNOMEoBrowseNOWAIT
PARACADAloColINoBrowse.Columns
loCol.Header1.Caption=PROPER(SUBSTR(loCol.ControlSource,
Derato('.',LoCol.ControlSource)1))
PRXIMO

designdeinterfacedeusurio
Atagoratemosvindoaconcentrarseemalgumasdasquesteschavenaconcepoetrabalharcom
classes.Noentanto,odesigndoseuinterfacedeutilizador,emltimaanlise,aindamaisimportantequeapenas
porqueparaseususuriosfinaisdainterfacedousurionaverdadeaaplicao.Naverdade,osusuriosseassemelhama
queraramente,oununca,precisamossabercomoalgofeitoapenasparaondeirparaobtlofeito!
objetos
Osprincpiosqueregemoseudesigndeinterfaceso,portanto,nodiferentesdosquejtemos
expsparaaconcepodeclasses.
Nestaseo,novomedebruarsobreessasquestesbsicascomousandofontes,coreseo
colocaodeetiquetas,caixasdetextoeoutroscontroles.Nssupomosquevocquerjtem,ou
iradoptar,umconjuntodenormasparadecidirtaisquestes.Emvezdisso,queremostentarcobriralgumas
dasquestesmenosbviasque,muitasvezes,soimplementadosmal,senodeformaincorreta.

Perceporegeaceitao
Aprimeira,eprovavelmenteaquestomaisimportante,quemaisfrequentementedoquenousuriosfinaisiro
julgarasuaaplicaopeloseudesempenhopercebido.Seumaplicativointuitivoefcilde
usar,eolhaesenterpidoeresponsivo,entoprovvelquesejabemaceito,mesmoque
nofazascoisasexatamentedamaneiraqueaspessoasinicialmenteesperado.Poroutrolado,seoseu
aplicaovistocomosendo"difcil"deusar,lentoounoresponder,osusuriossomenospropensos
aaceitlamesmoqueelefazexatamenteoquesequeriaexatamentedaformaquefoisolicitado.
Ento,comovocpodegarantirqueseuaplicativonotransmitirapercepoerrada?

Fazeralgoacontecerimediatamente!
Aprimeiraregra,douradogarantirquealgoacontece,logoqueousuriointeragecom
suaaplicao.AinterfacedoMicrosoftWindows95/98temumexcelenteexemplodisso
princpio.Clicandonoboto"Iniciar"ir,emquasetodasassituaes,apresentarimediatamentea
todoprimeironvel"menuiniciar".Claroquepodeentolevarvriossegundos,dependendodoque
osistemaestfazendo,paraumaseleoapartirdessemenuparaserexecutadomasissonooponto.
Achavequenohumarespostainstantnea.
Infelizmente,todasasaplicaesmuitasvezesnsvimosemqueumusurioclicaemumbotoedepoisdeum
algunssegundosumajanelademensagemaparecedizendo"Working...Espereporfavor'.Claroque,poreste
vezqueousuriogeralmentetemclicounobotovriasvezesejtrancouo
todaaplicaodurantevriashoras,fazendocomqueomesmoprocessodemoradoparaexecutarumameiadzia

Captulo3:Design,Designerenadamais 79

vezesseguidas.(Osusuriosrealmenteachoqueosistemasvezesno'ouvir'oclique?)O
soluousual,emseguida,pareceserade"Ctrl+Alt+Delete!"
claroquehsituaes,especialmenteemaplicaesderedeoucliente/servidor,quando
haverumatrasoenquantoosdadossorecuperados,masissonomotivoparanoforneceraousurio
umfeedbackimediato.Umasoluoeleganteparaesteproblemaparticularadefazer
botodecomandodesativarseimediatamentedepoisdeumclique.Istoconsegueduascoisaselefornece
umadicavisualquealgoaconteceu,emaisimportantequeelapareousurio
inadvertidamentedispararoprocessovriasvezesporreclicandonoboto.o
classe'xCmdStdDisable'nabibliotecaCH03.VCXbaseadoemnossobotodecomandopadro
classe,massubstituiomtodocliqueparaadicionarestafuncionalidade:
Comisso
.Enabled=.F.
DODEFAULT()
.Enabled=.T.
ENDWITH

Claro,sevocusargrficosemseusbotesdecomando,vocpodeatmesmoespecificardiferentes
imagensparacadaumdostrsestadosdobotosimplesmentedefinindopropriedades.

Tabela3.2Propriedadesbotodeimagemdecomando

Propriedade Funo
fotografia Exibidoquandoobotoativo,masnoselecionados
DownPicture Exibidoquandoobotoclicadoepressionada
DisabledPicture Exibidoquandoobotoestdesabilitado

Manterousurioinformadosobreoprogresso
Asegundaregraimportantemanterosusuriosinformadossobreoqueosistemaestafazerespecialmentese
oaplicativoexecutadoumprocessoquelevaumaquantidadesignificativadetempo..Quantotempo
significativa?Anicarespostarealque'depende'.Nsnormalmenterecomendamosque
nadamaisdecincosegundosrequeralgumtipodeinformao,mesmoqueapenasumajaneladeespera,e
qualquercoisaquecorreaolongodeumminutodeveteralgumtipodevisualizaoprogresso.
Issolevantaaquestodequetipodeexibiodeprogressoquevocdeveusar?Opadro
abordagemdoWindowsusarum"bartermmetro".Nsinclumosumaauladeamostra
(ThermBar.VCX)ededemonstrao(ShoTherm.PRG)nocdigodeexemploparaeste
captulo.Noentanto,elenoonicomecanismoparaaexibiodeprogresso,eemalguns
circunstncias,nomesmoomelhor.Porexemplo,quandovoctemumtempomuitolongooumultiestgio
processoquenonecessariamenteprogridemlinearmentecomotempo,umabarratermmetronomuito
til.
Emtaissituaes,nsgostamosdeusarumacaixadelistagemporquetemagrandevantagemqueumusuriopode
rolarparacimaeveroquetemsidofeito,e,assim,terumaidiadecomooprocessoestprogredindo.
Maisumaveznsinclumosumaclassedeexemplo(ListProg.VCX)ededemonstrao
(ShoList.PRG)nocdigoparaestecaptulo.

80 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Noexagererelatriosdeprogresso!
Humaressalvaemrelaoaoprogressodorelatrio.Vocdevegarantirqueoprocessode
relataroprogressono,porsis,umimpactosignificativosobreoprocessoqueestsendorelatado.Tambm
tantotomaucomomuitopoucoaesterespeitoe,enquantomtodos"bonito"paramostraroprogressopodeser
divertidoprograma,elespodemrapidamentetornarseirritanteparaousuriofinal.MaisumavezaMicrosofttem
forneceuumexemploclssicoaocopiararquivosnoWindowsExplorer,apequenavibrao
pginassodivertidosaprimeiravezquevocvlos,masnodemoroumuitoparaperceberque,sevocusarum
comandoDOScpia,possvelcopiararquivosmuitomaisrpidodoqueoExplorer.Porqu?Aresposta
quecontinuamenteatualizandoaexibioprogressoretardasignificativamenteoprocessodecpia.

Mantenhaseususurioscentrou
Umadasfalhasmaiscomunsquevemoseminterfacesdeusuriosotelasquesorecheadoscheiade
controlacomquaseumpixelquadradolivre.Issogeralmentesignificaqueastelassolentosparacarregar
equaseimpossveltrabalharcomamenosquevoctemolhoscomoumfalcoparamancharo
cursorentreamassadoscontrolos.Normalmente,arazodadaqueosusuriosprecisamvertodaa
informaoaomesmotempoeissopodeapresentaralgunsproblemasgravesparaodesenvolvedor.Tem,
noentanto,algunspassosquevocpodetomarparaajudarseususurios.

Faaseuscontrolesselecioneonentrada
controleseditveisnoVisualFoxProtemumapropriedadeSelectOnEntryquevocpoderiapensarqueseria
assegurarque,semprequeumcontroloseleccionado,(ouseja,recebeofoco)todoocontedodocontrolo
serdestacadocomo'selecionada'.Estaobviamenteumacoisatilparafazer,especialmentenadesordenado
telas,jquetornamaisclaroparaousurioondeofocoresideatualmente.OarquivodeAjudapara
SelectOnEntryafirmaque:

Especificaseotextoemumacluladacoluna,caixadeedio,oucaixadetextoselecionadoquandoousurio
moveseparaisso.Disponvelemtempodedesignetempodeexecuo.

Eletambmobservaqueapenasoscontrolescontidosemcolunasdegradeirapresentarestecomportamento
padro.Observe,porm,queotextousaafrase"quandoousuriomoveaele'.emoutra
palavras,elesfuncionaquandoumcontrolerecebeofocoemvirtudedesuaposioelenofunciona
quandoousurioclicaremumcontrolecomomouse(nemasoluoalternativade
definindoapropriedadeFormat='K').Ento,vocprecisaescreverumcdigo,sevocquerumverdadeiro'Select
Nacapacidadedeentrada'.
AmelhorsoluoqueencontramosusaroGotFocusmtodoe,(nasuaclasse)adicionar
oseguintecdigo:

TextBox::GotFocus()
This.SelStart=0
This.SelLength=999
NODEFAULT

EstepropsitodestecdigopodenoserevidenteatquevoclembresequeGotFocusumdos
oseventosnativasquetemumcomportamentodefinido.Partedestecomportamentonativa,
aparentemente,paradefinirtantoSelStarteSelLengtha0!

Captulo3:Design,Designerenadamais 81

Ento,parafazeronossotrabalhodecdigoemtodasascircunstncias,devemosprimeiroforarVFPparaexecutaro
comportamentodaclassebase'foradasequncia".(Normalmenteocdigodeclassebaseexecutadoapsqualquer
ensprecisadele,porquesemele,ocontrolenovaiseconcentraremtudo!)Umavezquetenhasido
cdigopersonalizado
feito,podemosdefiniraspropriedadesparaposicionarocursor(SelStart)eadicionarodestaque
(SelLength)pararealartodoocontedodocontrole.Finalmente,devemospararaclassebase
cdigosejaexecutadoemseulugarnormal,porisso,adicionarum NODEFAULTcomandos.OxTxtStdSeltexto
classedecaixa(verGenClass.VCXbibliotecanocdigodestecaptulo)temessecomportamentoe
selecionarcorretamentetodootexto,noentanto,ousuriodfocoparaumcontrole.

Useasdicasdeferramentasparaaj udarosusuriostrabalharcomaforma
UmadascaractersticasmaisagradveisdoVisualFoxProquetodososcontrolestmumapropriedadeToolTipText
quesecomportacomotodasasoutrasdicasdeferramentasnoWindows.Aopassaromousesobreumcontrole,o
dicaexibidodepoisdeumpardesegundos.Istonointrusivaesaparecequandoousurio
realmente'pede'paraele.Maisimportante,eleaparecenalocalizaodoponteirodomousecomo
oposioaotextoespecificadopelapropriedadeStatusBarTextquesaparecenabarradestatus.
(Isso,ento,requerqueseuaplicativousarumabarradestatuseassimintil,amenosqueoseu
aplicativoexecutadodentrodatelaprincipalVFP).
Lembreseemboraacapacidadedeterumadicadeferramentaumapropriedadedeumobjeto,acapacidadede
mostrarqueumapropriedadedoformulrio(oubarradeferramentas)naqualelereside.Paraativarasdicasquevoc
deve,definaapropriedadeShowTipspara VERDADEIROnasuaclasseraiztantoparaFormaeBarradeFerramentas
classes.
Masasdicassonoumsubstitutoparaaajudasensvelaocontexto!Ocomprimentomximopermitido
de127caracteres(emesmoquerealmentemuitolongo!).Nsrecomendamosousodedicasdeferramentaspara:

avisandoaousurioquenecessriaumaentradaemumcampo
Aespecificaodequeocontroloestlimitadoaumtipoparticulardeentrada
usuriosLembrandoquandoexistemopesadicionais(porexemplo,menusbotodireitodomouse)

Useocontrolecertoparaotrabalho
Istopodeparecerbvio,masincrvelcomomuitasvezesouvimosaspessoasdizemalgo
como"Euestoutentandocarregarumacaixadecombinaocom13.000linhaselento."Bem,humasurpresa!
Bytheway,apenascomoqueumusuriodevefuncionarcomumacaixadecombinaoque,emtodasasversesdo
antesdaVerso6.0,limitadoaumdisplayde7linha,mascontm13.000linhasdedados?Mesmocom
VFP
pesquisaincremental,queumacombinaobastanteassustadora.Piorainda,umacaixadecombinaonofcil
controledemanipular,omelhordostemposumdeslizedomouseevoctemquecomeartudodenovo
maisumavez.

Useumagradeparalongaslistas
Teremosmuitomaisadizersobreamecnicadecontrolesdelistaentreganocaptulo
dedicadaespecificamenteaeles,poisagoraqueremosconcentrarseno"quando"emvezdo
'Como'devemosuslos.Entoaquianossaorientaoideal,emboransreconhecemosque,naprtica,
poderterdequebrlo:
82 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Paralistascomalgumasdezenasdelinhas,umcombo(caixadelistaou)bom,masnadamais
doquev ocrealmentedev econsiderarousodeumagradedesomenteleitura.

Porqueusarumagradedesomenteleitura?Arazoqueumagradeircarregardadossequencialmente,conforme
aoinvsdeterderecuperartodososdadosdeinicializao,queumacaixalistaoudecombinaodevefazer.o
necessrio,
truqueaquiacriaodeumaclassedegradequeseparececomumacaixadelistacomum.Estebastantesimples,
apenasdefiniralgumaspropriedadesparaagrade(verxGrdStdListclassenoGenClass.VCXbiblioteca):

ColumnCount=1
AllowHeaderSizing=.F.
AllowRowSizing=.F.
DeleteMark=.F.
GridLines=0
HeaderHeight=0
ReadOnly=.T.
RecordMark=.F.
ScrollBars=2
SplitBar=.F.

Emseguida,definaapropriedadeMovablepara.F.paraacoluna.
Umpardeaperfeioamentosforamadicionados.PrimeironsadicionamosumapropriedadenRowsao
classeparadefinirquantaslinhasdevemservisveis.Istousado,naInitmtododaclasse,
paradefiniraalturadagradeexatamenteeevitaraslinhasparciaisfeiasquemuitasvezesestragara
aparecimentodegrades.Emsegundolugar,tambmdimensionaracolunavisvelparapreenchertodaalargurada
readeexibio(menosalarguradabarraderolagemverticalclaro):

***DefinirheightcomoonmeroexatodelinhasespecificadasnonRowspropriedade
This.Height=This.RowHeight*This.nRows
***ColunaForaparapreencheralarguradisponvel
This.Columns[1].Width=this.widthSYSMETRIC(7)

Finalmentecaixadetextodagradeincluiocdigoselectonentrada,oqueexplicamosanteriormente,a
assegurarque,quandoumusurioclicanarededa'linha'devidamenterealado.Noentanto,porque
acaixadetextoestemumagrade,emvezdecolocarocdigonacaixadetextoGotFocusmtodo,eledeve
vnoClickmtodo!
Dependendodoseuusoporumlongoclasselistaquevocvaiprecisaradicionarqualquercdigonecessrioe
talvezalgumaspropriedadesemtodospersonalizados,masocomportamentobsicojestprevista.Desde
rolagememumagradeirmoveroponteirodoregistroemseuOrigemDoRegistro,ficandooitemselecionado
noumproblemabastapegaronmerodoregistro(oucontedodequalquercampoquevocquiser).
Maisimportanteainda,porqueagradepodeusartodososcamposnatabelaquevocestprocurando,vocfaz
nemmesmotemqueespecificarquaisoscamposquevocprecisa.Vocaindapodeusarumcursor(ouvisualizar)paracriar
subconjuntodedadosdevriastabelas.
um
Onicoproblemaquevocpodeprecisarusarumacaixadecombinao,emvezdeumacaixadelistagem,a
conservaroespaoemumformulrio.Pararesolveresseproblema,criamosumaclasse"combogrid",que
imitaocomportamentodeumcombo,masusaumagradeemvezdaquedadepadronalistasuspensavejaa
captulosobreComboselistasparaobterdetalhes.
UmexemplousandoumaformamodalpararetornaroIDdoclienteseleccionadoestincludonaamostra
cdigoparaestecaptulo.Notequeparaconfigurarodestaqueinicial,bastalocalizaroregistrodesejado

Captulo3:Design,Designerenadamais 83

noformulrioInitmtodoedefinirofocoparaagrade.Paraexecutaresteformulrio,bastafazeroseguinte:
dajaneladecomando(109simplesmenteumvalordechaveparaatabela):
?lcSelection
DOFORMfrmGListcom109TOlcSelection

Figura3.7AclassegrdListemuso

84 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo4:ControlesBsicos 85

Captulo4
Controlesbsicos
"Humagrandesatisfaonaconstruodeboasferramentasparaoutraspessoasusarem."
("DisturbingtheUniverse"porFreemanDyson)

Amaioriadetemponecessrioparaprojetaredesenvolverumaplicativogastonacriaodo
interface.Umabibliotecabemconcebidodeclassesdecontrolereutilizveisi rreduzirsignificativamente
q uantidadedetrabalhonecessrioparacriarestainterface.Heranapermitecomum
o
funcionalidadeparaserconstrudoemsuasaulasumaveznosnveismaisaltosdahierarquiadeclasses
deixandoolivreparaseconcentraremprocessoslgicoscomplexosdasuaespecfica
aplicao.Nestecaptulo,vamoscompartilharalgunsrecursosinteressantesqueconstrumosnonosso
classesdebase.VocvaiencontrartodasasclassesdescritasnabibliotecaCH04.VCX.
conjuntode

Oquequeremosdizercom"base"?
Vocpodeseperguntaroqueentendemosporcontroles"bsicos".Paraefeitosdopresentecaptulo,so
referindoseacontrolosqueformamamaiorpartedequalquerinterfacedeutilizador.Issonormalmenteincluitexto
caixas,caixasdeedio,spinners,botesdecomandoesimilares.Todososcontrolespersonalizados
apresentadonestecaptuloirfuncionarquandocaiuemumformulrio,pgina,ouquandocolocadodentrodeum
recipiente.Noentanto,elesnosogarantidosparatrabalharquandocolocadosemumagradecomogradesimpor
diferentesrequisitosnaconstruodeseuscontroles.controlespersonalizadosparausonointerior
grades,portanto,seroabordadosnocaptulo6"Grids:oscontrolesmalentendido".grades,
especialmentegrelhasdeentradadedados,estosuficientementecomplexoquetemosdedicadoumaseointeira
exclusivamenteparaeles.

Ascaixasdetexto(exemplo:CH04.VCX::txtBase)
Amaioriadoscontrolesemsuainterfaceser,provavelmente,quercombaseemcaixasdetextooucaixasdeedio.
Elessoinequvocos,compreendidapelosusurios,mesmonovatos.Elespodemserusadoscomoelessaem
dacaixa,masnopossuemnadamaisdoqueafuncionalidademaisbsica.Porexemplo,a
fazerumacaixadetexto,selecionetodooseucontedoquandorecebeofoco,vocpodeapenasdefiniro
SelectOnEntrypropriedadepara.T.(oudefinirapropriedadeFormatpara"K").Naverdadequalquerumdestesvontade
sfuncionamquandoocontrolerecebefocopelomovimentodeoutrocontroleenovaifazer
nadaquandoousuriocliquesdomousenacaixadetexto.Felizmente,fcilosuficienteparadaratodos
caixasdetextoestafuncionalidadebsica,colocandoestecdigonoGotFocusmtododesua
padrodeclassecaixadetexto:
TextBox::GetFocus()
.SelStart =0
.SelLength=999
NODEFAULT

Umavezqueestaumaclassederaiz,vocpodeseperguntarporqueusaralinha decaixadetexto::
emvezdeapenasaemissodeumaDODEFAULT().ArazoquenoVisualFoxPro5.0a,houveum
GotFocus()
86 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

bugnoDODEFAULT()quecausouocomportamentodaclassebaseVisualFoxProaserexecutadodepois
executarocdigonaclassepai.Istosignificavaque,amenosquevoctinhaumNODEFAULTno
finaldomtodonaclassesubrotina,ocdigodeclassebasedeveriaserexecutadoduasvezes.(Isto
porque,porpadro,VisualFoxProexecutadoqualquercdigopersonalizadoquetenhasidocolocadoemummtodoe
emseguida,executaocdigodeclassebasedepois.)EmVisualFoxPro6.0,DODEFAULT()nofunciona
ocdigodeclassebase,amenos,claro,asubclassedescendediretamentedoVisualFoxProde
classebase.Assim,emVisualFoxPro6.0,ocomportamentodaclassebasegarantidoparaexecutaraochamar
lodiretamentecomooperadorderesoluodeescopo.
Comodecostume,hmaisdeumamaneiradeesfolarumaraposa.Estanicalinhadecdigonotexto
dacaixadeGotFocus()mtodorealizaamesmacoisaqueasquatrolinhaslistadasacima:
This.SetFocus()

Nsgostamosnossascaixasdetextoaserselecionadonaentradaporpadro.Voc,noentanto,podepreferir
comportamentodiferente.Afimdeproporcionarflexibilidade,quecondicionalmenteexecutarocdigoacimasomente
sedacaixadetextoSelectOnEntrypropriedadedefinidacomotrue.
NstambmadicionamosumcostumeSetInputMaskmtodoparaaclasseraizcaixadetexto,comosegue:

LOCALlcAlias,lcField,LCType,laFields[1],
lnElement,lnRow,lcIntegerPart,lcDecimalPart
Comisso
ESE!VAZIO(.ControlSource)
IFEMPTY(.InputMask)
***DefinirApenasoMscaraDeIntroduoparacamposnumricosedecaracteres
***Everifiqueotipodedadosdocamposubjacenteparaque
***Podeconfigurlodeformaadequada
LCType=TYPE(This.ControlSource)
IFINLIST(LCType,'C','N')
***Analiseoapelidoeonomedocampoapartirdaorigemdocontrole
lcAlias =JUSTSTEM(.ControlSource)
lcField =JUSTEXT(.ControlSource)
***Notenteverificaraspropriedadesdosubjacente
***Camposesomosobrigadosaumapropriedadedeformulrio
IFUPPER(lcAlias)#'THISFORM'
***Formatarocamposeeleopersonagem
IFLCType='C'
InputMask=REPLICATE('X',FSIZE(lcField,lcAlias))
OUTRO
AFIELDS(laFields,lcAlias)
lnElement=ASCAN(laFields,UPPER(lcField))
IFlnElement>0
lnRow=ASUBSCRIPT(laFields,lnElement,1)
lcIntegerPart=REPLICATE('9',laFields[lnRow,3]
laFields[lnRow,4]1)
lcDecimalPart=REPLICATE('9',laFields[lnRow,4])
.InputMask=LcIntegerPart+'.'+lcDecimalPart
FIMSE
FIMSE
FIMSE
FIMSE
FIMSE
FIMSE
Captulo4:ControlesBsicos 87

ENDWITH

Estecdigosimplesmenteconfiguraumamscaradeentradapadroparacontrolosdependentesquenotm
especificadoseocontroleestvinculadoapersonagemedadosnumricos.Nocasodedadosdecaracteres,
nenhumamscaradeentrada
osusuriossoimpedidosdedigitarmaiscaracteresquepoderiamsersalvasparaosubjacente
camposemrestrio,oqueessespersonagenspodemser.Paracamposnumricos,impedenumrica
errosdeestouro.

gotchascaixadetexto
VocprovavelmentesabequevocnopodeemitirumachamadaparaumcontroleSetFocusmtododaValid
mtododequalquercontrolenoVisualFoxProverso5.0esuperior.Issofazsentidoquando
seconsideraqueonicopropsitodoVlidomtodoparadeterminarseounoo
controledevemserautorizadosaperderofoco.Paramanterofocoemumcontrolequandoasuavalidaofalhar,
vocpodesimplesmenteemitirum RETURN0,queinformaVFPqueseconcentramdevepermanecernoatual
aocontrole.Amelhormaneiradepassarexplicitamentefocoparaoutrocontroleusarumcdigocomoesteno
LostFocusmtodo:

This.Parent.SomeControl.SetFocus()
NODEFAULT

Issofuncionabem,masvoctambmdeveestarcientedequequandovoccolocaressecdigono
LostFocusmtododeumacaixadetexto,asuaValidmtodoseracionadonovamentesemprequeeleexecuta.
EstenoumproblemaamenosquevoctemocdigonaValidmtodoquesebaseiaemumanica
execuoantesdacaixadetextoperdeofoco(porexemplo,incrementandoumcontadorouexibindouma
caixademensagem).

Textoclasseetiquetadacaixa(Exemplo:CH04.VCX::txtLabel)
Quandovocprecisaterumrtuloquepodeserligadoaalgunsdados,achamostilterumtexto
classedecaixaquepareceefuncionacomoumrtulo.Porqueumrtulonotemumaatualizaoeumacaixadetexto
faz,fcilmudarovisorquandooformulrioatualizado.Nstambmgostamosdenossosrtulosparaser
justificadosdireitaporissomontamosanossatxtLabelclasseparafazerissoporpadro.(Vocpodefacilmentedefinir
oseumximoaseraesquerdaoucentrojustificou.)AnicalimitaomenorparaanossatxtLabelclasseque
emborasejafcilosuficienteparafornecerparaasteclasdeatalho(adicionandocdigoparaoKeypressmtodo),h
simplesmentenenhumamaneiradeindicaroqueatecladeatalhorealmente.Acriaodeumacaixadetextopara
comoumrtuloumaquestosimpleseenvolvemudarosvalorespadrodaseguinte
olhareagir
Propriedades:

Alinhamento =1Direito
BackStyle =0Transparent
Estilodeborda =0nenhum
IntegralHeight =.T.
Efeitoespecial =1Plain
StrictDateEntry=0solta
TabStop =.F.

88 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Paraimitarperfeitamenteocomportamentodeumrtulo,tambmprecisamosdeassegurarqueanossacaixadetexto
classenopodereceberofoco.IstoconseguidoatravsdaadiodeumanicalinhadecdigoparaasuaQuandoMtodo
alterado
paraqueelesempreretornaumalgicaFALSEvalor:
RETURN.F.

CaixadetextoData(Exemplo:CH04.VCX::txtDate)
Acaixadetextoentradadedataumaformamuitosimplesdecontrole,maseficaz.Elefazusodoformato
propriedadeparaexibiradataemqualquerformatoespecificadopelousuriodoWindowsLongDate
configurao(Format="YL").AlgumcdigosimpleschamadodeGotFocuseLostFocusforao
configuraesdosculoeRoleparavaloresquesodefinidoscomopropriedadesdeclasseegarantequeosusurios
queinsistememinserirdatascomumsculopassadodedoisdgitosnocausamdadosinvlidosparaser
empenhadaemsuastabelas.(Nstambmgostodestaformadeexibioparaasdatas.)

Figura4.1CaixadeEntradadeTextoData
Tabela4.1Aspropriedadespersonalizadasdecaixadetextoadata

propriedadepersonalizada
propsito
nRollYear DefiniremtempodedesigneusadopelocostumeSetCentmtodoparadefiniroanorollover
nCentury DefiniremtempodedesigneusadopelocostumeSetCentmtodoparadefinirosculo
cCentWas UsadointernamentepelocostumeSetCentmtodoparasalvarosvaloresatuaisdeSET
('CENTURY'),SET('CENTURY',1)eSET('CENTURY',2)

SetCentchamadoapartirdacaixadetextoGotFocusmtodoparasalvarasconfiguraesatuaisdosculo
eredefinilasusandodocontrolenRollYearenCenturypropriedadesOsculooriginais
configuraessorestauradasnaRestCentmtodoquechamadoapartirdoLostFocusmtodo.este
cdigodocontroleSetCentmtodomostracomopodemossalvarasconfiguraesoriginaisantes
usandoaspropriedadespersonalizadaspararedefinilas:

lcCentWaslocal,lcCentury,lcRollOn,lnRollYear,lnCentury
Comisso
***Salveasconfiguraesatuais
STORE''paralcCentWas,lcCent,lcRollOn
***CenturyOn/OFF
lcCentWas=PADL(SET("Century"),3)
***CenturyBasedeDados
lcCentury=PADL(SET("Century",1),2,'0')
***AnoRollover
lcRollOn =PADL(SET("Century",2),2,'0')
***Salveforacomocadeiadecaracteres
.cCentWas=lcCentWas+lcCentury+lcRollOn
***Setivermosumanocapotamentoespecficauslo,opadromaisaatual
lnRollYear=IIF(!empty(.nRollYear),.nRollYear,INT(VAL(lcRollOn)))
***Setivermosumsculoespecficouslo,opadromaisaatual

Captulo4:ControlesBsicos 89

lnCentury=IIF(!empty(.nCentury),.nCentury,INT(VAL(lcCentury)))
***SetCenturyeCapotamento
SETCENTURYTO(lnCentury)ROLLOVER(lnRollYear)
***ForaCenturyOn
SETCENTURYON
ENDWITH

Issosimplesmentesalvaquaisquerdefiniesestoactualmenteemvigorparaosculoeestabelecenovo
configuraescombasenaspropriedadesdocontrole.IssotilporqueSETCENTURYumdos
muitasconfiguraesquetemcomoescopoaumDataSessionepodesernegligenciado.Almdisso,porque
cadacontrolelidacomsuaprpriaversodosculo,vocpodeconfigurarvrioscontrolescom
diferentessculosdebaseediferentesanosderolagemparalidarcomascoisastaiscomodatasdenascimentoe
maturaoaplicedesegurodedatasnomesmoformulrio.ORestCentmtodorestauraooriginal
configuraes,aosairdocontrole:

lcCentWasLOCAIS,lnCentury,lnRollOn
STORE''paralcCentWas
Comisso
***Leiavoltaasconfiguraessalvas
ESE!Vazio(.cCentWas)
lcCentWas=ALLTRIM(substr(.cCentWas,1,3))
lnCentury=int(Val(substr(.cCentWas,4,2)))
lnRollOn =int(Val(substr(.cCentWas,6,2)))
***SetCenturyparaopadro
SETCENTURY&lcCentWas
***Restaurarconfiguraesoriginais
SETCENTURYTO(lnCentury)ROLLOVER(lnRollOn)
FIMSE
ENDWITH

Caixadetextodepesquisaincremental(Exemplo:CH04.VCX::txtSearch)
Umacaixadepesquisadetextoincrementalumaferramentaextremamentetil.Nospodeserutilizadocomopara
elementosespecficosdedadosdeumaforma,quetambmpodeserfeitaemumasubclasseparausoemperidica
encontrar
redesdepesquisaeoutroscontrolescompostosqueexigemessafuncionalidade.Porexemplo,vocpode
usarestaclasseparacriarumcontrolequeatuacomoondicedeAjudadearquivos(vocdigitaemumacaixadetextoe
caixadelistaexibeacorrespondnciamaisprxima).
um
AmaioriadascaixasdetextodepesquisaincrementaisquevimosusaroKeyPressmtodoparachamar
mtodospersonalizadosquelidamcomasteclasdigitadas,manipulardacaixadetextoSelStarteSelLength
propriedadesefazerabusca.Emnossaversodaclassenschamamosessesmtodosda
InteractiveChangemtodoemvezdisso.DesdeInteractiveChangedisparaapsKeyPressmaisfcil
(erequermenoscdigo)paradeixarKeyPresslidarcomaentradarealcomosemprefazedepoisfazer
oquequerfazerdepois.Porumaquestodefacto,anossacaixadepesquisadetextoincrementaisnotem
cdigopersonalizadoemtudonasuaKeyPressmtodo.OnicocdigoestemInteractiveChange,que
simplesmentechamaocostumeHandleKeymtodoquandonecessrio,comosegue:

90 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Seateclapressionadafoiumcarcterdeimpresso,umbackspaceouexcluir
***Lidarcomopressionamentodeteclasepesquisa
IFThis.SelStart>0
IF(LASTKEY()>31eLASTKEY()<128)ou(LASTKEY()=7)
This.HandleKey()
FIMSE
FIMSE

Ento,oqueafuncionalidadequeumacaixadetextodepesquisaincrementalexige?Obviamente,deve
procuraratabelaespecificadaparaumapartidanocampoespecificadocomoousurioestdigitandooem.Almdisso,
deveotimizarabuscausandoumamarcadendice,sedisponvel.Paraatenderaessesrequisitosque
adicionaralgumaspropriedadespersonalizadasparaanossaclassedecaixadetextodepesquisaincremental:
cAlias
=Atabeladepesquisa

cField=Ocampodepesquisa
CTAG =Amarcadendice(sehouver)parautilizarnapesquisa

Acaixadetextodevetambmautocompletaraentradacaixadetexto(assimcomodoQuickenpreenchimentorpida
faz).Masdevetambmatualizaroscontrolesemseucontinerpaidepoisdereposicionaro
ponteirodoregistronatabelaespecificada?Talvez,mas,novamentenemsempre.Umavezqueestaltimacaracterstica
necessriaapenasemcircunstnciasespecficas,precisamosadicionarumapropriedadelgicaparadeterminarquando
Estecomportamentodeveocorrer.ApropriedadelRefreshParentadicionadoclasseedefinidocomoverdadeiropela
padroparaforneceressaflexibilidade.SomentequandolRefreshParentverdade,seranossaHandleKey
chamadademtododacaixadetextoRefreshParentmtodo:

loControlLOCAL
PARACADAloControlINThis.Parent.Controls
IFloControl.name#This.name
***Verifiqueseocontroletemummtododeatualizao!!!
***Lembrese,rtulosnotemummtododeatualizao!
IFPEMSTATUS(loControl,'Atualizar',5)
loControl.Refresh()
FIMSE
FIMSE
ENDFOR

Finalmente,umacaixadetextodepesquisaincrementaldeve,pordefinio,serumdesacopladocontrole.(Seisso
estavamatadas,ovalorespecificadopelasuaorigemdocontroleteriadeseralteradoacadatoquedetecla.)
Ento,precisamosdeumamaneiraparaatualizarovalorinicialquandoousurionavegaparaumnovorecorde.
Portanto,umnicoSincronizarmtodofoiadicionadoechamadoapartirdaatualizaomtodo.
Istofaztodootrabalhonecessrio:
Captulo4:ControlesBsicos 91

lnSelStartLOCAL
Comisso
***Salveopontodeinsero
lnSelStart=.SelStart
***Atualizeovalordacaixadetextocomocamposubjacente
.Value=Eval(.cAlias
+'.'+.cField)

***Reporopontodeinseroeselecionarorestantedotexto
.SelStart=LnSelStart
.SelLength=LEN(ALLTRIM(.Value))lnSelStart
ENDWITH

OrestodocdigonanossaclassecaixadetextodepesquisaincrementalresidenoHandleKey
Mtodo.Apesardofatodequeelerealmentefazamaioriadotrabalho,aquantidadedecdigo
surpreendentementepequeno.Nsfortementerecomendamosqueosmtodosdesermuitocentradoemtermosdasua
funcionalidade.Elepermitequevocmantenhaocdigocurto,tornandoastarefasdedepuraoe
manteraclassemuitomaissimples.Ento,agora,semmaisdelongas,aquiestocdigoquevocesteve
morrendoparaver:

LOCALlcSofar,lnSelect,lnSelStart,lnSelLength
Comisso
***Salveopontodeinsero
lnSelStart=IIF(LASTKEY()#127,.SelStart,.SelStart1)

Aquinoscertificardequenoapresentamvaloreserradosnacaixadetextose,porexemplo,o
backspacesusuriopassadooprimeirocaracterenacaixadetexto,deixandoavazia.Vocpodepreferir
tmcaixadetextoexibirovalorparaoprimeiroregistronatabelaqueestsendopesquisada.Seassimfor,este
ondeparamudarnossocomportamentopadro:

***Pegaumvalorvazionacaixadetexto
IFlnSelStart=0
.value=''
.SelStart=0
GOBOTTOMIN(.cAlias)
SKIPIN(.cAlias)
OUTRO

Agora,paraascoisasimportantes!Temosdegarantirocursorestposicionadonofinaldo
cadeiadecaracteresdigitadosatomomentopelousurio.Portanto,temosdeobteressaseqnciaeprocuraratabela
especificadapelodacaixadetextocAliaspropriedadeparaumapartida.Apesquisausaatagndiceindicado
naCTAGpropriedade,seumfoiespecificado.Casocontrrio,eledeveusar LOCALIZARparatentarencontraruma
combinandoregistro.Desdeo LOCALIZARcomandodelimitadaparaareadetrabalhoatual(enopode
refernciaaqualqueroutro),devemostercertezadequesalvarareadetrabalhoatualantesdeselecionarcAlias
paraquepossamosrestaurarostatusquodepois:

***Seovalordigitadonamedida
lcSofar=LEFT(.Value,lnSelStart)
.Value=LcSoFar
***Useprocuramencontraroregistroseumtagfoifornecida
ESE!VAZIO(.cTag)
SeSEEK(UPPER(lcSoFar),.cAlias,.cTag)

92 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

.Value=Eval(.cAlias
+'.'+.cField)

FIMSE
OUTRO
***Casocontrrio,salvarareadetrabalhoatual
***Antesdemudarparaatabelaespecificada
lnSelect=SELECIONAR()
Seleccione(.cAlias)
***Elocalizaroregistroespecificado
LOCALIZARPARAUPPER(ALLTRIM(EVAL(.cField)))=UPPER(lcSoFar)
SEACHADO()
.Value=Eval(.cAlias
+'.'+.cField)

FIMSE
***Restaurarareadetrabalhooriginal
SELECT(lnSelect)
FIMSE
FIMSE
NestemomentotemostantoencontradooregistrodesejadonacAliasouestamosnofinaldo
Arquivo.Tudooquerestaaserfeitoparareporapartedestacadadacaixadetextocorretamentee
atualizaroscontrolesnocontinerpai(seestafoiespecificadodefinindo.lRefreshParent=
.T).:
***Seprecisamosparaatualizarocontinerpaifazloaqui
IF.lRefreshParent
.RefreshParent()
FIMSE
***Destaqueapartedovalorapsopontodeinsero
.SelStart=LnSelStart
lnSelLength=LEN(.Value)lnSelStart
IFlnSelLength>0
.SelLength=LnSelLength
FIMSE
***Serecrearamoscontrolesnocontinerpai,
***Existemproblemasdetemporizaoparasuperar
***Embora.SelStarte.SelLengthtemosvalorescorrectos,
***Caixadepesquisanoapareaemdestaquecorretamentesemesseatraso
=INKEY(0,1,'H')
ENDWITH

Observeo INKEY()comandoaqui,elevaralgumtempoparalerocomentrioacima,sevoc
jnoofez.Esseproblemanoespecficoparaanossacaixadepesquisadetextoincrementaisesincronismo
questescomoestanosoincomunsnoVisualFoxPro.(Temostambmcorrerparaeleaoexibir
multiselecionecaixasdelistagememqueasseleesanterioressorealados.Nessecaso,usar
INKEY()naatualizaodoformulriopermitequeacaixadelistagemaserdestacadocorretamente.)interessante
notequeo INKEY()comandononecessrianocdigoacima,quandolRefreshParent=.F.
Issodsuportehiptesedequeistononadamaisdoqueumproblemadetempo.Ocurto
pausapermitequeVisualFoxPropararecuperaroatraso.

Caixadetextonumrico(exemplo:CH04.VCX::txtNumetxtNumeric)
VisualFoxProherdoualgumasdeficinciasgravesnoquedizrespeitointroduodedadosnumricos
deseusancestraisFoxPro.Nomuitoruimquandoocampointeiroestselecionadoeonmero
noformatadoscomseparadores.Noentanto,osproblemascomeamaocorrerquandoopontodeinseroest

Captulo4:ControlesBsicos 93

nonoinciodovalorapresentado.svezesousurioesttentandodigitaronmero10,
mastudoqueelepodedigitar1e,comconfirmaopartiu,ovalordacaixadetextotornaseumeo
cursorsemoveparaoprximocampo.Vimostambmoproblemaoposto.Ousurioquer
digite3,masdepoisdedigitar3esairdocontrole,onmero30exibidoemvezdo
destina3.Ento,oquepodeumdesenvolvedorVisualFoxProfazerparaajudar?
Existemalgumassoluesparaesteproblema.Vocpoderiacriarumacaixadetextonumricapara
selecionarocampointeiroeremoverquaisquerseparadoresutilizadosparaformataronmero.Estecdigono
dacaixadetextoGotFocusmtodopermitequeonmeroaserdigitadocorretamente:

Comisso
***Salveamscaradeentrada
.cOldInputMask=.InputMask
***Retireseparadoresdemscaradeentrada
.InputMask=STRTRAN(.cOldInputMask,',','')
***ExecuteVisualFoxProGotFocusnativa()
TextBox::GotFocus()
***Selecioneocampointeiro
.SelStart=0
.SelLength=LEN(.cOldInputMask)
***NodeixequeocomportamentodaclassebaseredefinirSelStart/SelLength
NODEFAULT
ENDWITH

DesdequeprecisamosmudardacaixadetextoMscaraDeIntroduoparaalcanaresteobjetivo,nsadicionamos
propriedadechamadacOldInputMaskparasegurarooriginalMscaraDeIntroduoatribudoaocontrole.Nsvamos
umcostume
precisadesteimvelemdacaixadetextoLostFocusmtodo,afimderestauraraformataodaseguinteforma:

This.InputMask=This.cOldInputMask

Claro,nsjtemosumaclassecaixadetextoqueselecionacorretamenteocampointeiroondevoc
guiaparaeleoumousecliquesobreele.NossacaixadetextoclassebasefazissoquandoSelectOnEntry=.T.assim
tudooquetemosafazerbasedenossacaixadetextonumricoemnossocaixadetextoclassebase,definido
verdade,ecolocaressecdigoemsuaGotFocusmtodo:
SelectOnEntrypara

Comisso
***Salveamscaradeentradaoriginal
.cOldInputMask=.InputMask
***Retireseparadoresdemscaradeentrada
.InputMask=STRTRAN(.cOldInputMask,',','')
***Executarocomportamentodaclassepai
DODEFAULT()
ENDWITH

Acaixadetextonumricadescritoacimapodesersuficienteparavoc.fcildecriar,no
contmumagrandequantidadedecdigoetrabalhaemtornodosproblemasenvolvidosnaentradadedadosnumricos
corretamente.Masnoseriamelhorterumacaixadetextonumricaquefazestilocalculadoraentrada
dadireitaparaaesquerda?Vimosvriosexemplosdessascaixasdetextoe,emnossaopinio,eles
todossofremdomesmoinconveniente.Ouocursorpodeservistoapiscarparaaesquerda,conforme
caracteresaparecemdoladodireitoounohcursoremtudo.Ambasestassoluestendema
tornarascoisasconfusasparaousurio.Ento,nsnospropusemosacriaromximonumricoVisualFoxPro

94 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

caixadetexto.Ensmuitorapidamentedescobriuporqueactualmentenoexistem.FoiDURO!Entons
esperoquevocencontrarestetil,poisoresultadodainteiramentedemasiadomuitashorasemuitosangue,
suorelgrimas.Nosfazerentradadeestilocalculadora,ocursortambmposicionadasobreo
caracterecorreto.Quandoovalornacaixadetextonoselecionado,vocpodeatmesmoexcluirouinserir
dgitosindividuaisnomeiodonmeroexibidonacaixadetexto.
Acaixadetextonumricaumcontrolesimplesdeusar.Apenassoltloemumformulrio,pginaourecipiente
edefinaseuOrigemDoControlopropriedade.Issotudo!VocnoprecisamesmodedefinirsuaInputMaskamenos
vocquerocontroledeserdesacopladoporquecapazdeformatarsiquandoligado.o
maneiramaisnumricocaixasdetextotrabalhoalterandoovaloremumacadeiadecaracteres,
manipularacordaeoInputMaskeentoreconverteracadeiaparaumvalornumrico.
Noentanto,anossacaixadetextonumricarealmenteumcontroloindependente(mesmoquevocpodeconfigurlo
comoseestivesseligado)efuncionaporqueoseuvalor,naverdade,umacadeiadecaracterese
manipuladacomotal.Eleusacdigopersonalizadoparaactualizarasuaorigemdocontrolecomonumrico
equivalentedacadeiadecaracteresqueoseuvalor.
Esteexemploprojetadoparafuncionartantodesvinculadoouvinculadoaumcampoemumatabela,cursorou
Viso.Sevocprecisadeseligaraumapropriedadedeformulrio,ocdigoterumapequenamodificaoparaaconta
porisso.UmexemplodecomoofazerpodemserencontradosnoUpdateControlSourcemtododo
spnTimeclassedescritoposteriormentenestecaptulo.
Osseguintes,oitopropriedadespersonalizadasforamadicionadosnossacaixadetextonumricopersonalizado.Eles
sotodosusadosinternamentepelocontroleevocnoprecisafazernadacomelesexplicitamente.

Tabela4.2Aspropriedadespersonalizadasdacaixadetextonumrica

Propriedade Descrio
CcontrolSource SalvaaorigemdocontroleseesteumcontroledelimiteantesquesejaindependentenaInit
Mtodo
cField partedonomededomniodaorigemdocontroleseforligado
CinputMask StoresMscaraDeIntroduooriginalquandoespecificado,casocontrrio,armazenaoMscaraDeIntroduo
construdospelocontrole
ColdConfirm configuraooriginaldoSET("confirmar")salvonoGotFocusparaquepossaserrestauradoem
LostFocus.
ColdBell configuraooriginaldoSET('Bell')salvosnoGotFocusparaquepossaserrestauradoem
LostFocus
CPoint CarterretornadoporSET("ponto")
Cseparator CarterretornadoporSET('SEPARATOR")
CTable partedonomedetabeladeorigemdocontroleseeleligado
LchangingFocus AbandeiraajustouparasuprimirTECLADO'{END}'queusadoparaposicionarocursorno
aposiomaisdireitanacaixadetexto.Sefizermosisso,quandoocontroleperderofoco,
elemexeseaordemdetabulao
NmaxVal valormximopermitidonocontrole

OSetUpmtodo,chamadopelodeTextBoxInitmtodo,salvaocontedodo
OrigemDoControlepropriedadeparaocostumecControlSourcepropriedadeantesliberandoocontrole
apartirdasuaorigemdocontrole.Eletambmdeterminaedefinese,aInputMaskparaocontrole.At
emboraessecdigoexecutadoapenasumavezquandoacaixadetextoinstanciado,nscolocloemum
mtodopersonalizadoparaevitarcodificaoexplicitamenteemeventossemprequepossvel.Observequeusamos
Captulo4:ControlesBsicos 95

SET("ponto")eSET('SEPARATOR")paraespecificaroscaracteresutilizadoscomoo
pontodecimaleseparadoremvezdecodificarumcarcterespecfico.Istopermiteocontrole
paraserutilizadocomamesmafacilidadenaEuropacomonosEstadosUnidos,semanecessidadede
modificarocdigo:

laFieldslocal[1],lnElement,lnRow,lcIntegerPart,lcDecimalPart,lcMsg
Comisso
***Salveoscaracterespontoeseparadordecimalparaquepossamosusareste
***ClasseemqualquerEUAounaEuropa
.cPoint =SET("ponto")
.cSeparator=SET('SEPARATOR")
***Salveocontrolsource
IFEMPTY(.cControlSource)
.cControlSource=.ControlSource
FIMSE

Emseguidansanalisaronomedatabelaecampodenomeforadaorigemdocontrole.Parece
redundanteparaarmazenarestasduaspropriedades,umavezquefacilmentepodeserobtidoporexecutareste
seodocdigo.Noentanto,porquehvriasseesdocdigoquesereferemaumou
outra,muitomaisrpidoparasalvloscomopropriedadeslocalizadasquandoacaixadetextoinstanciado.
VocpodeseperguntarentoporquesepreocupouemterumcControlSourcepropriedadequando
poderiafacilmentetersereferidoaThis.cTable+'.'+This.cField.Acreditamosqueestemais
autodocumentadosetornaocdigomaislegvel.Istotoimportantequantoodesempenho
consideraes.Sejalegalcomodesenvolvedorqueherdaseutrabalho.Vocnuncasabequandovoc
podeacabartrabalhandoparaela!Estecdigodedacaixadetextodeinstalaomtodofazoseupropsito
bemclaro:

ESE!VAZIO(.cControlSource)
***SeEsteumcontroleacoplado,salvaratabelaecampoacopladoa
***AnalisaronomedatabelaemcasoControlSourceprefixadaporumalias
SEAT('.',.cControlSource)>0
.cTable=LEFT(.cControlSource,AT(,.cControlSource)'.'1)
.cField=SUBSTR(.cControlSource,AT('.',.cControlSource)+1)
OUTRO
.cField=.cControlSource
***Noaliasnaorigemdocontrole
***Assumiramesaadareadetrabalhoselecionado
.ctable=ALIAS()
FIMSE

ArotinadeinstalaotambmeconomizaqualquerespecificadoInputMaskaocInputMaskpropriedade.Seestefor
umcontrolodependente,vocnoprecisaespecificarumaInputMask,emboravocpodefazlosedesejar.
Estaseodocdigoirfazerissoporvoc,obtendoaestruturadocamposubjacente.isto
tambmdefineocontrolenMaxValpropriedade,necessriaduranteaentradadedadosparagarantirqueousuriono
introduzirumnmeroquemuitogrande,causandoumerrodeestouronumrico:
pode

***DescubracomoocampodeveserformatadosenenhumInputMaskespecificado
IFEMPTY(.InputMask)
AFIELDS(laFields,.cTable)
lnElement=ASCAN(laFields,UPPER(.cField))

96 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

IFlnElement>0
***Seocampodointeiroouamoedatipo
***EnenhumInputMaskforespecificado,configurlopara
***Omaiorvalordocampoiracomodar
DOCASO
laFieldsCASE[lnRow,2]='I'
.cInputMask="9999999999"
.nMaxVal=2147483647
laFieldsCASE[lnRow,2]='Y'
.cInputMask="999.999.999.999.999,9999"
.nMaxVal=922.337.203.685.477,5807

CASElaFields[lnRow,2]='N'
lcIntegerPart=REPLICATE('9',laFields[lnRow,3]
laFields[lnRow,4]1)
lcDecimalPart=REPLICATE('9',laFields[lnRow,4])
.cInputMask=lcIntegerPart+'.'+lcDecimalPart
.nMaxVal=VAL(.cInputMask)

DEOUTRAFORMA
lcMsg=IIF(INLIST(laFields[lnRow,2],'B','F'),
'Vocdeveespecificarumamscaradeintroduoparatiposdedadosdecasalefloat',
"Tipoinvlidodedadosparaestecontrole')+':'+This.Name
MESSAGEBOX(lcMsg,16,'desenvolvedorErro!')
RETURN.F.
ENDCASE
FIMSE
OUTRO
.cInputMask=STRTRAN(.InputMask,',','')
.nMaxVal=VAL(.cInputMask)
FIMSE
OUTRO
.cInputMask=STRTRAN(.InputMask,',','')
.nMaxVal=VAL(.cInputMask)
FIMSE

AgoraquejsalvouoControledeorigemparaanossainternacControlSourcepropriedade,ns
podeseguramentedesvincularocontrole.NstambmdefinirolChangingFocusbandeiraparatrue.Issogaranteonosso
caixadetextonumricairmanterofocoseoprimeiroobjetonaordemdetabulaoquando SET(
'Confirmar')='desligado'.Istoessencialporqueanossacaixadetextoposicionaocursorusandoum
TECLADO'{END}'.Istoimediatamentedefinirofocoparaosegundoobjetonaordemdetabulao
quandooformulrioinstanciado,porquenopodemosforarum SETCONFIRMAROFFatqueanossacaixadetexto
naverdade,temofoco:

.ControlSource=''
***Issonosimpedededigitaodeum'{END}'emovendoseparaoprximocontrole
***Seesteoprimeironaordemdetabulao
.lChangingFocus=.T.
.FormatValue()
ENDWITH

OFormatValuemtodoexecutaamesmafunoqueonativoVisualFoxPro
mtododeactualizaofazparacontrolesacoplados.Eleatualizaovalordocontroledesuaorigemdocontrole.
Naverdade,nestecaso,eleatualizaovalordocontroledesuacControlSource.Desde

Captulo4:ControlesBsicos 97

cControlSourceavaliadacomoumvalornumrico,aprimeiracoisaquedevemosfazerconverteressevalorem
umalinha.Emseguida,formataracadeiadebemcomseparadoreseposicioneocursornofinaldo
acorda:

Comisso
***CControlSourcenumrico,entoconvertloparacadeia
ESE!VAZIO(.cControlSource)
ESE!VAZIO(EVAL(.cControlSource))
.Value=ALLTRIM(PADL(EVAL(.cControlSource),32))
OUTRO
.value=''
FIMSE
***Eformatlomuitobemcomseparadores
.AddSeparators()
OUTRO
.value=''
.InputMask='#'
FIMSE
***Posicioneocursornaextremidadedireitadacaixadetexto
IF.lChangingFocus
.lChangingFocus=.F.
OUTRO
TECLADO'{END}'
FIMSE
ENDWITH

OAddSeparatorsmtodousadoparaexibirovalorformatadodacaixadetexto.Oprimeiro
passocalcularocomprimentodasporesinteirasedecimaisdostringactual:

lcInputMaskLOCAL,lnPointPos,lnIntLen,lnDecLen,lnCnt
***ReporoInputMaskcomseparadoresparaovaloratualdacaixadetexto
lcInputMask=''
Comisso
***Encontrarocomprimentodaparteinteiradonmero
lnPointPos=AT(.cPoint,ALLTRIM(.Value))
IFlnPointPos=0
lnIntLen=LEN(.Value)
OUTRO
lnIntLen=LEN(LEFT(.Value,lnPointPos1))
FIMSE
***Encontrarocomprimentodapartedecimaldonmero
SEAT(.cPoint,.cInputMask)>0
lnDecLen=LEN(SUBSTR(.cInputMask,AT(.cPoint,.cInputMask)+1))
OUTRO
lnDecLen=0
FIMSE

Umavezquetenhamoscalculadoestescomprimentos,podemosreconstruiraMscaraDeIntroduo,inserindo
vrgulasseforcasodisso.Amaneiramaisfcilcontarcaracterescomeandocomomaisdireita
carterdaparteinteiradacadeia.Podemos,ento,inserirumavrgulaapsoformato
caracteres,seocarctercorrenteestnaposiodemilhares(lnCnt=4),aposiomilhes
(LnCnt=7)eassimpordiante.Noentanto,seacaixadetextocontmumvalornegativo,issopoderia
resultado",123.456"sendoexibidocomoovalorformatado.Nsverificarsehestapossibilidadedepois
soinseridasasvrgulas:

98 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Insiraoseparadornointervaloapropriado
lcInputMask=''
PARAlnCnt=lnIntLenTO1STEP1
IFINLIST(lnCnt,4,7,10,13,16,19,21,24)
lcInputMasklcInputMask=+"#"+.cSeparator
OUTRO
lcInputMasklcInputMask=+"#"
FIMSE
ENDFOR
***Certifiquesedequeosnmerosnegativossoformatadocorretamente
IFLEFT(ALLTRIM(.Value),1)=''
IFLEN(lcInputMask)>3
IFLEFT(lcInputMask,2)='#'
lcInputMask='#'+SUBSTR(lcInputMask,3)
FIMSE
FIMSE
FIMSE

Nsterminarpelaadiodeummarcadorparaopontodecimalequaisquerespaosreservadosqueso
necessriapararepresentarapartedecimaldonmero:

IFlnPointPos>0
***Permitirparaopontodecimaldamscaradeentrada
lcInputMask=lcInputMask+'#'
***Adicionarmscaradeentrada,sehouverumapartedecimal
IFlnDecLen>0
lcInputMask=lcInputMask+REPLICATE('#',lnDecLen)
FIMSE
FIMSE
.InputMask=LcInputMask
ENDWITH

Paraqueousurioinsiradados,ocontroledevereceberofoco.Istorequerqueum
sriedecoisasserfeitonoGotFocusmtodo.Aprimeiratercertezadeque SET(
'Confirmar')='ON'equeosinosilenciada,casocontrrio,teremosproblemasquando
TECLADO'{}FIM'paraposicionarocursornofinaldocampo.Emseguida,temosadespojaros
separadoresparaforadoInputMaske,finalmente,queremosexecutaropadroSelectOnEntry
comportamentodanossacaixadetextoclassebase.Assim,oherdou'SelectentradacdigonoGotFocus
mtodotemdesermodificadoparalidarcomestesrequisitosadicionais,comosesegue:

This.cOldConfirm=SET('Confirmar')
This.cOldBell=SET('Bell')
SETCONFIRMON
SETBELLOFF
This.SetInputMask()
DODEFAULT()

NotesequeoSetInputMaskmtodotambmchamadoapartirdaHandleKeymtodoparaajustaro
InputMaskcomoousurioinseredados.Aquiest:

lcInputMaskLOCAL,lnChar
***ReporoInputMaskparaovaloratualdacaixadetexto
Captulo4:ControlesBsicos 99

lcInputMask=''
PARAlnChar=1aLEN(This.Value)
lcInputMask=lcInputMask+'#'
ENDFOR
lcInputMask=lcInputMask+'#'
This.InputMask=lcInputMask

Talcomoanossacaixadepesquisadetextoincremental,caixadetextonumricalidacomopressionamentode
HandleKeymtodoquechamadodeInteractiveChangeapsKeyPresstenhaprocessadoa
teclasno
keystroke.AcaixadepesquisadetextoincrementaisnorequerqualquercdigonoKeyPressmtodo
porquetodosospersonagenssopotencialmentevlido.Nacaixadetextonumrica,noentanto,apenasumsubconjunto
ascombinaesdeteclassovlidos.PrecisamosinterceptarquaisquerteclaspressionadasilegaisnocontroleKeyPress
de
mtodoequandodetectadauma,emitirum NODEFAULTparasuprimiraentrada.Fazemosisso
passandoopressionamentodeteclasatualparaoOK2Continuemtodo.Seumcarcterinvlido,este
mtodoretornafalseparaoKeyPressmtodo,queemiteonecessrio NODEFAULTcomando:

LPARAMETERStnKeyCode
LOCALlcCheckVal,llRetVal
llRetVal=.T.
Comisso

Desdeocarteratualnosetornarumapartedovalordacaixadetextoatdepoisdo
InteractiveChangemtodofoiconcluda,podemosevitarquevriascasasdecimais,verificando
paraelesaqui:

DOCASO
***Certifiquesedequespermitemumpontodecimalnaentrada
CASECHR(tnKeyCode)=.cPoint &&pontodecimal
SEAT(.cPoint,.Value)>0
llRetVal=.F.
FIMSE

Damesmaforma,novamospermitirqueumsinaldemenosparaserdigitadoemmenosquesejaoprimeiro
corda:
caracterena
***Certifiquesedequestemosumsinaldemenosnoinciodonmero
CASEtnKeyCode=45
IF.SelStart>0
llRetVal=.F.
FIMSE

AtarefamaiscomplexatratadapeloOK2Continuemtodoochequeparanumrica
transbordar.Fazemosissoatravsdadeterminaodoqueovalorsersepermitirmosqueopressionamentodeteclas
ecompararestevaloraoarmazenadanocontrolenMaxValpropriedade:
atual
***Proteocontraestouronumrico!!!!
DEOUTRAFORMA
ESE!VAZIO(.cInputMask)
IF.SelLength=0
IFtnKeyCode>47etnKeyCode<58
DOCASO

100 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
CASE.SelStart=0
lcCheckVal=CHR(tnKeyCode)+ALLTRIM(.Value)
CASE.SelStart=LEN(ALLTRIM(.Value))

lcCheckVal=ALLTRIM(.Value)+CHR(tnKeyCode)
DEOUTRAFORMA
lcCheckVal=LEFT(.Value,.SelStart)+CHR(tnKeyCode)+
ALLTRIM(SUBSTR(.Value,.SelStart+1))
ENDCASE
IFABS(VAL(lcCheckVal))>.nMaxVal
llRetVal=.F.
FIMSE
***Certifiquesedeque,seamscaradeentradaespecificaum
***Determinadonmerodecasasdecimais,nopermitirmais
***Doqueonmerodecasasdecimaisespecificado
SEAT('.',LcCheckVal)>0
SEAT('.',.cInputMask)>0
IFLEN(JUSTEXT(lcCheckVal))>LEN(JUSTEXT(.cInputMask))
llRetVal=.F.
FIMSE
FIMSE
FIMSE
FIMSE &&TnKeyCode>47etnKeyCode<58
FIMSE &&0=.SelLength
FIMSE &&!VAZIO(.cInputMask)
ENDCASE
ENDWITH

RETURNllRetVal

Estecdigopodeparecerumpoucofeio,masnaverdadeeleexecutadodeformaextremamenterpidaporqueo
IFaninhadasestruturagarantequevriasverificaessoexecutadassequencialmenteequesequalquerum
falhar,orestonuncasoprocessadosemtudo.
Talcomoanossacaixadepesquisadetextoincremental,muitotrabalhofeitousandoumpoucodecdigoemnosso
HandleKeymtodo.Podemosmanipularoposicionamentodocursoreaformataodovalor
aquiporqueInteractiveChangesfogodepoisKeyPressfoibemsucedido.Portanto,
lidarcomasteclasdigitadasaquirequermenoscdigoquelidarcomelesdiretamentenoKeyPress:

lcInputMaskLOCAL,lnSelStart,lnEnd
***Salvepontodeinserodocursoreocomprimentodovalordigitadonamedida
lnSelStart=This.SelStart
lnEnd=LEN(This.Value)1
Comisso
***Selivrardequalquerespaoparaquepossamosdireitojustificarovalor
.Valor =ALLTRIM(.Value)
***Precisamosdeumtratamentoespecialpararemoveropontodecimal
IFLASTKEY()=127 &&backspace
IF.Value=.cPoint
.value=''
.InputMask='#'
FIMSE
FIMSE
.SetInputMask()

Captulo4:ControlesBsicos 101

Seopersonagemacaboudeentrarestavanomeiodacaixadetexto,deixamosocursoronde
estava.Casocontrrio,posicionlaexplicitamentenofinaldovaloraserinserido:

IFlnSelStart>=lnEnd
TECLADO'{END}'
OUTRO
.SelStart=LnSelStart
FIMSE
ENDWITH

Quaselagora!Seesteeraoriginalmenteumcontrolodependente,precisoatualizarocampo
especificadapelocControlSourcepropriedade.AValidmtodoolugarapropriadoparaisso,
assimquensuslo:

Comisso
ESE!VAZIO(.cControlSource)
REPLACE(.cField)COMVAL(.Value)IN(.cTable)
FIMSE
ENDWITH

Finalmente,precisamosdeumpoucodecdigodacaixadetextoLostFocusmtodopararepor CONFIRMpara
seuvalororiginaleparaformatarovalorexibidocomosseparadoresapropriados:
Comisso
***Setbandeirademodoquenotecladofimeatrapalharaordemdetabulao
.lChangingFocus=.T.
.Refresh()
IF.cOldConfirm='desligado'
SETOFFCONFIRM
FIMSE
ENDWITH

Otempodemanipulao
Umdosproblemasperenesnaconstruodeumainterfacedeutilizadorcomocontrolaraentradade
Tempo.Muitasaplicaesrequeremesteapoioevimosabordagensvariadas,muitasvezesbaseados
noscontrolesgiratrios.Sentimosnaverdadeexistemdoistiposdeentradadetempoqueprecisamser
considerada,esuasdiferenasrequeremdiferentescontroles.
Primeiro,haentradadirectadeumahorareal.Tipicamente,estavaiserusadoemumtempo
gravaosituaoquandoousurioprecisadigitar,porexemplo,umcomeoeumtempodeacabamentoparauma
tarefa.Esteumcenriodeentradadedadospuraeumacaixadetextoamelhorferramentaparaotrabalho,mash
algumasquestesqueprecisamserabordadas.
Emsegundolugarhaentradadetempoqueumintervaloouconfigurao.Normalmenteserutilizadoestetipo
emumasituaodeplanejamentoquandoousurioprecisadigitar,porexemplo,aduraoestimadaparaum
tarefa.Nestecaso,umspinnerbemadequadoparaatarefa,poisosusuriospodemfacilmenteajustarovalorparacima
ouparabaixoepodeveroimpactodesuasalteraes.

102 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Umacaixadetextoentradadetempo(exemplo:CH04.VCX::txtTime)
Asuposiobsicaaquiqueumvalordetemposersemprearmazenadocomoumacadeiadecaracteresno
formulriohh:.mmNsnoesperamosparalidarsegundosnestetipodesituaoaentradadirecta.Narealidade
issonorazovel,jqueamaioriademanipulaodotemposexigeumaprecisodehorase
minutos.Issomaisfcilquandoovalorjestnaformadecaracteres.(Sevocrealmenteprecisaparaentrar
segundos,seriaumasimplesquestodefazeressecontroleemumasubclassedelidarcomeles.)Tambm
decidimostrabalharemumrelgiode24horas.Maisumavezistosimplificaainterfaceatravsdaremoo
anecessidadedeadicionaroconceitofamiliardeumdesignadorAM/PM.
Estasdecisesfazemaclasse'interfacedeusuriosimplesparaconstruirporqueoVisualFoxPro
nosproporcionatantoumInputMaskeumaFormatpropriedade.Oexespecificacomoosdados
inseridosnocontroledevemserinterpretados,enquantoquealtimadefinecomodeveser
exibida.EmnossatxtTimeclasse(combasenanossatxtbaseclasse)estaspropriedadessodefinidoscomo
segue:

InputMask=99:99
Format=R

O'R'noformatoinformaVisualFoxProparausaramscaradeentradadefinido,masnoincluir
oscaracteresdeformatao,comopartedovaloraserarmazenado.Emboraspodeserusadocom
caracteresedadosnumricos,muitotil.Nestecaso,oseparadorde':'sempre
visveis,masnoarmazenadocomovalor.,portanto,sempreumacadeiadequatrocaracteres.
NstemosalgunscdigosadicionaisemambososGotFocuseLostFocusmtodosparasalvare
restauraraconfiguraoatualdo CONFIRMeforloa ONenquantoacaixadetextodeentradaotempotem
foco.Emboranosejaabsolutamentenecessrio,nsacreditamosqueumaboaprticaaolimitarcomprimentosentrada
paragarantirqueconfirmamparaimpedirqueosusuriosinadvertidamentedigitaoatravsdocampo.
TodoocdigorestantenaclassenoVlidomtododacaixadetextoeesta
ondetemosdeabordarasquestesaludidoacimasobrecomoosusuriosvousarestecontrole.o
questochavecomolidarcomtemposparciais.Porexemplo,seumusuriodigitaastring:' 011'eles
realmentesignifica" 01:10"(dezminutosdepoisdaumadamanh)ou" 00:11"(onzeminutospassado
ameianoite)?Comosobreumaentradade' 09'?
Naverdadenohnenhumamaneiraabsolutadesaber.Tudooquepodemosfazerdefinireimplementaralgumas
razovelrulesforestaclassedaseguinteforma:

Tabela4.3Regrasparaentrarumvalordetempo

Ousuriodigita
interpretarcomo Resultado
1 Umahoraespecfica,hminutos 01:00
11 Horasapenas,hminutos 11:00
111 Horaseminutos,zeroesquerdaomitidos 01:11
1111 Tempoexato 11:11
Ocdigodeaplicaodessasregrasbastantesimples:

Captulo4:ControlesBsicos 103

Lhrslocal,lumins,lcTime,lnLen
***Nota:nstemosqueassumirqueumusuriosomiteaesquerdaoudireita
***Zeros.Nopodemosadivinharoresultadopretendidodeoutraforma!!!
lcTime=ALLTRIM(This.Value)
lnLen=LEN(lcTime)
DOCASO
CASElnLen=4
***Temos4dgitosporissotemosumtempocompleto!
***Nofazermaisnada
CASElnLen=3
***Suponhaminutosestiveremcorretos,nashorasqueantecederamzerofoiomitido
lcTime=PADL(lcTime,4,'0')
CASElnLen=2
***Suponhaquepossuemacaboudehoras,hminutos
lcTime=APRD(lcTime,4,'0')
DEOUTRAFORMA
***Umniconmerodeveserumahora!
lcTime="0"++lcTime"00"
ENDCASE
***VejaasHorasecomponentesminutos
Lhrs =LEFT(lcTime,2)
lumins=RIGHT(lcTime,2)
***Verifiquequenotemosidomais23:59,oumenosde0:00
ESE!ENTRE(INT(Val(lumins)),0,59),ou!ENTRE(INT(VAL(Lhrs)),0,23)
ESPERE"Invalidtempoinserido"NOWAITJANELA
This.Value=""
RETURN0
OUTRO
This.Value=Lhrs+lumins
RETURN1
FIMSE

Aclassecompostaentradadetempo(exemplo:CH04.VCX:: cntTime)
Comoobservadonaintroduodestaseo,umcontrolegiratriotilquandovocprecisadar
ousurioacapacidadedemudarostempos,aocontrriodeintroduzilosdiretamente.Noentanto,uma
diferenasignificativaentreousodeumgiradoreumacaixadetextoparainserirotempoqueumspinner
requerumvalornumrico.Istosignificaquesensaindadesejaarmazenaronossovalordetempocomoumpersonagem
corda,precisamosconverterdepersonagemparanumricoeviceversa.Parasimplificar,este
controleestconfiguradoparaexibirsempreumtempoemhh:mm:ssformatoeesperaque,seestivesseligado,elevai
servinculadoaum(6)Campodecaracteres.(Oobjetivoaquimostrarastcnicasbsicas.Modificando
ocontroleparaoutroscenriosdeixadocomoumexerccioparaoleitor.)
Aprximaquestocomochegarahoradesersignificativacomoumvalornumricoparaexibir
devidamente.FelizmentepodemosnovamentefazerusodasFormatoeMscaraDeEntradapropriedadespara
resolverestedilema.AodefinirInputMaskdoSpinner=99:99:99,eaFormat="RL"
podemosexibirumvalornumricodeseisdgitoscomzerosesquerda.(O"Lopo'sfuncionacom
valoresnumricos,portanto,nopoderiauslonoexemploanterior.)
Altimaquestoquetemosdeabordarcomodeterminarqualpartedonossoseisdgitos
nmeroseralteradoquandodarotadoresparacima/baixobotessoclicados.Asoluo
criarumaclassedecompostoquebaseadoemumrecipientecomumgiradoreumaopodetrsbotes
grupo.Ogrupoopousadaparadeterminarqualpartedogiradorincrementado
104 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

(ouseja,horas,minutosousegundos)edogiradorUpClickeDownClickmtodossocodificados
paraagirapropriadamente.Aquiaclasseemuso:

Figura4.2TimeControlSpinner

recipienteotempodogirador
OrecipienteumasubclassedenossopadrocntBaseclasse,comumanicapropriedadepersonalizada
(CControlSource)eummtodopersonalizado(SetSpinValue).Esteslidarcomorequisitode
converterentreumafontededadosdecaracteresparaanossaclasseeovalornumricorequeridopela
giratrio.OcControlSourcepropriedadepreenchidaemtempodedesigncomonomedocontrole
fonteparaospinner.CdigofoiadicionadoaoActualizarmtododorecipienteparaligaro
SetSpinValuemtodopararealizaraconverso,quandoocontroleestvinculado.Aatualizaodocdigo
simplesmente:

Comisso
IF!EMPTY(.cControlSource)
This.SetSpinValue()
FIMSE
ENDWITH

OcdigonaSetSpinValueigualmentesimples,elesimplesmenteconverteovalordafontedecontrolepara
umnmerodeseisdgitospreenchidoscomzeros.Noentanto,existeumapanhadoaquinotarousode
oINT()funonestaconverso.Temosdegarantironossovalornumriconaverdadeumnmerointeiro
emtodososmomentos.Seestamosalidarcomhoras,minutosousegundosbaseiasenasposiesde
osdgitosnovalornumricoecasasdecimaisiriainterferirquandoseutilizaopadx()
funes:

Comisso
IF!EMPTY(.cControlSource)
.spnTime.Value=INT(Val(PADL(EVAL(.cControlSource),6,"0")))
FIMSE
ENDWITH

grupodeopootempodogirador
Estaapartemaissimplesdaclasse.Notemnenhumcdigopersonalizadoquesejadiferentedamudanade
seunomedopadrodoVisualFoxProparaOptPick.Ocomportamentonaturaldeumgrupodeopo
paragravar,novalordepropriedadedoprpriogrupo,onmerodobotodeoposelecionado.
Umavezquesprecisasaberqualbotoselecionado,noprecisafazermaisnada.

Captulo4:ControlesBsicos 105

giradorotempodogirador
Este,semsurpresa,ondeamaioriadotrabalhonaclassefeito.Trspropriedadestersido
setoInputMaskeFormat(paralidarcomosproblemasdeexibio)edoincremento.Istotemsido
definidocomo0parasuprimirocomportamentonativadogiradorumavezqueprecisamosparalidarcomaalteraodo
deumamaneiramaissofisticada.
valor
OsGotFocuseLostFocusmtodossousadosparatransformarocursorparaforaeligadonovamente,
Umavezqueestecontrolonosedestinaadigitaodirecta,eliminandoanecessidadedemostrarocursor.
AValidmtodomanipulaaconversodovalornumricodocontrolegiratrioparatrsemum
cadeiadecaracterese,seocontroleestvinculado,lidacoma REPLACEparaatualizarafontedecontrole.
Estecdigotambmbastantesimples:

COMThis.Parent
IF!EMPTY(.cControlSource)
REPLACE(.cControlSource)COMPADL(INT(This.Value),6,"0")
ENDWITH
FIMSE

OsbitscomplicadossotratadosnasUpClickeDownClickmtodos.Enquantoestecdigopode
olharumpoucoassustadoraprimeiravista,realmentebastantesimplesebaseiasenainterpretao
aposiodosdgitosnovalornumricoemanuselosemconformidade.oUpClick
mtodoverificaaconfiguraodogrupodeopoeincrementaapororelevantedo
valornumrico:

LOCAISlnPick,lnNewVal,lnHrs,lnMins,lnSecs
lnPick=This.Parent.optPick.Value
DOCASO
CASElnPick=1 &&Hrs
***ObteroprximovalorHoras
lnNewVal=This.Value+10000
***Se24oumais,redefinira0subtraindo
This.Value=IIF(lnNewVal>=240000,lnNewVal240000,lnNewVal)
CASElnPick=2 &&Mins
***Obteroprximovalorcomoumacadeiadecaracteres
lcNewVal=PADL(INT(This.Value)+100,6,'0')
***horasextratocomoumvalormultiplicadopor10.000
lnHrs=VAL(LEFT(lcNewVal,2))*10000
***Vejaosminutoscomoumacadeiadecaracteres
lnMins=SUBSTR(lcNewVal,3,2)
***Verifiqueovalordessaseqncia,equermultiplicarpor100
***Ou,seacimade59,rollasobrea00
lnMins=VAL(IIF(VAL(lnMins)>59",00",lnMins))*100
Extraiseaporo***segundo
lnSecs=VAL(RIGHT(lcNewVal,2))
***Reconstruirovalornumrico
This.Value=lnHrs+lnMins+lnSecs
CASElnPick=3 &&Secs
***Obteroprximovalorcomoumacadeiadecaracteres
lcNewVal=PADL(INT(This.Value)+1,6,'0')
***horasextratocomoumvalormultiplicadopor10.000
lnHrs=VAL(LEFT(lcNewVal,2))*10000
***minutosextratocomoumvalormultiplicadopor100
lnMins=VAL(SUBSTR(lcNewVal,3,2))*100
***Vejaossegundoscomoumacadeiadecaracteres

106 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

lnSecs=RIGHT(lcNewVal,2)
***Verifiqueovalordessaseqncia,
***Seforsuperiora59,rollasobrea00
lnSecs=VAL(IIF(VAL(lnSecs)>59",00",lnSecs))
***Reconstruirovalornumrico
This.Value=lnHrs+lnMins+lnSecs
ENDCASE

Durantehorasoincremento10000,poralgunsminutos,100eparasegundosapenas1.
Ocontrolefoiprojetadodemodoqueseousuriotentaincrementaraporohorasacima'23',que
rolapara'00'simplesmentesubtraindoovalor240000donovovalordogirador.tantoo
minutosesegundossoroladasde"59"para"00",mas,nestecaso,precisamosrealmentetira
paracadacomponentedotempoparaverificaraparterelevanteantesdereconstruirovalorem
somandoseaspartesindividuais.
UmaabordagemsemelhantefoitomadanaDownClickmtodo,quediminuio
ovalordocontrole.Nestecaso,necessrioarmazenarovaloratualeusloparamanterasconfiguraes
daspartesdocontroloquenoestoaserafectadas.Casocontrrio,osprincpiossoosmesmos
paraoUpClickmtodo:

LOCAISlnPick,lcNewVal,lnHrs,lnMins,lnSecs,lcOldVal
***Obterovaloratualdocontrolecomoumastring
lcOldVal=PADL(INT(This.Value),6,'0')
lnPick=This.Parent.optPick.Value
DOCASO
CASElnPick=1 &&Hrs
***Diminuiraporohoras
lnHrs=VAL(LEFT(lcOldVal,2))1
***Seeleestnagamadesejada,usla,deoutromododefinidacomo0
lnHrs=IIF(ENTRE(lnHrs,0,23),lnHrs,23)*10000
***Extraiaosminutos
lnMins=VAL(SUBSTR(lcOldVal,3,2))*100
***Extraiaossegundos
lnSecs=VAL(RIGHT(lcOldVal,2))
CASElnPick=2 &&Mins
***Determinaranova,diminudo,ovalor
lcNewVal=PADL(INT(This.Value)100,6,'0')
***RecuperaraparteHorasatual
lnHrs=VAL(LEFT(lcOldVal,2))*10000
***Obteraporominutosdonovovalor
lnMins=Val(SUBSTR(lcNewVal,3,2))
***Verifiqueavalidadecomafaixa,definidocomo0seinvlida
lnMins=IIF(ENTRE(lnMins,0,59),lnMins,59)*100
***RecuperaraparteSegundosatual
lnSecs=VAL(RIGHT(lcOldVal,2))
CASElnPick=3 &&Secs
***Determinaranova,diminudo,ovalor
lcNewVal=PADL(INT(This.Value)1,6,'0')
***RecuperaraparteHorasatual
lnHrs=VAL(LEFT(lcOldVal,2))*10000
***RecuperaraparteMinutosatual
lnMins=VAL(SUBSTR(lcOldVal,3,2))*100
***Obterapartesegundosapartirdonovovalor
lnSecs=VAL(RIGHT(lcNewVal,2))
***Verifiqueavalidadecomafaixa,definidocomo0seinvlida
lnSecs=IIF(ENTRE(lnSecs,0,59),lnSecs,59)

Captulo4:ControlesBsicos 107

ENDCASE
***Definirovalorparaanova,diminudo,resultado
This.Value=lnHrs+lnMins+lnSecs

Concluso
Estegiradortempoumpoucorestritoemsuacapacidadedelidarcommaisdoqueasimples
ambientequedefinidoparaele.Enquantoclaroparaoutilizadorfinal,omecanismodeseleco
quepartedotempodeveserincrementadooudecrementadoumpoucoincmodo.Amais
soluoeleganteoferecidonocontrolefinalnestaseo.

Overdadeirotempogirador(Exemplo:CH04.VCX::spnTime)
EstaaparnciadecontroleeagecomootempogiradorquevocvquandoseusaoDate/TimePicker
controleActiveXqueacompanhaoVisualStudio.Noentanto,eletemvriascaractersticasqueotornam
maisgeralmentetildoqueocontroleActiveX.Emprimeirolugar,estecontrolenoexigequeseja
vinculadoaumcampodotipodedadosDateTime.Comojdissemos,omelhorformatoparaarmazenarusurio
tempoinseridoestemumcampodecaracteresformatadaparaincluirouniversal":"separadordehora.o
controlepodeserconfiguradoparaexibirereconhecertantoa5caracteres'hh:mm'formatoouumcompleto
8caracteres'hh:ss:mm'formatoeactualizao,querdeformaadequada.Istocontroladoporumanica
propriedade,lShowSeconds.Finalmente,porqueesteumcontroledoVisualFoxPronativaissonoacontecer
sofrerdosproblemasinerentesqueproliferamcontrolosActiveXcomrelaoaomltiplo
versesdeDLLsdoWindowsespecficos,nemexistemquaisquerproblemasassociadoscomoregistodo
aocontrole.
Talcomoacontececomospinnercombaseemcontiner,essecontroleutilizaumacControlSourcepropriedadepara
ligaoaumafontededadosexternaetemassociadomtodos(RefreshSpinnere
UpdateControlSource)paralidarcomaquestodaconversoentrecaracteres(fonte)e
numricosvaloresevolta(interno).Aocontrriodogiradorcombaseemcontiner,estecontroletambmpode
seguraraserligadoaumapropriedadedeforma,bemcomoaumafontededados.oUpdateControlSource
mtodo,chamadoapartirdogiradorValidmtodo,permitequeospinnertempo,oquerealmenteuma
controloindependente,acomportarsecomoaquelequeestligadoquandooseucControlSourcepropriedadedefinida:

lcTableLOCAL,lcField,lcValue,lcTemp
Comisso
***AnalisaronomedatabelaeocamponocControlSource
ESE!VAZIO(.cControlSource)
***Obteronomedatabelaseaorigemdocontroleprefaciadoporumalias
ESE'.'$.cControlSource
lcTable=LEFT(.cControlSource,AT(,.cControlSource)'.'1)
lcField=SUBSTR(.cControlSource,AT('.',.cControlSource)+1)
OUTRO
***Assumaoaliasoatualapelidoselecionadosenenhumforespecificado.
***Esteumpoucoperigoso,masseumamhiptese,a
***Programavaiexplodirmuitorapidamentenomododedesenvolvimentodoao
***Odesenvolvedorumaindicaomuitoclaradoqueesterrado,umavezqueeleverifica
***Oproblemanodepurador.
lcTable=ALIAS()
lcField=.cControlSource
FIMSE
108 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Temosagoradeconverterovalornumricodobotorotativoparaovalorcaracteredesejado,
ocampoouformadepropriedadeespecificadonocControlSourceseesteumlimitedecontrole.Devemostambm
formatarestacadeiadecaracterescomdoispontoseteremcontaseestamosusandohh:mmou
hh:mm:ssformato:
lcTemp=IIF(.lShowSeconds,PADL(INT(.Value),6,'0'),
PADL(INT(.Value),4,'0'))
lcValue=LEFT(lcTemp,2)+':'+SUBSTR(lcTemp,3,2)+
IIF(.lShowSeconds,':'+RIGHT(lcTemp,2),'')
***VerifiqueaquiparaverseonossoaliasThisForm.Sefor,
***Vamosassumirqueestamosdestinadosaumapropriedadedeformulrio
IFUPPER(lcTable)='THISFORM'
STORElcValueTO(.cControlSource)
OUTRO
REPLACE(lcField)COMlcValueIN(lcTable)
FIMSE
FIMSE
ENDWITH

Poroutrolado,oRefreshSpinnermtodoatualizaovalordogiradordasua
cControlSource.Emverdadeiroscontrolesacoplados,estafunofeitaautomaticamentesemprequeo
ocontroleatualizado.NossaRefreshSpinnermtodochamadodedogiradorActualizarparafornecer
essafuncionalidade:

Comisso
ESE!VAZIO(.cControlSource)
.Value=IIF(.lSHowSeconds,
VAL(STRTRAN(EVAL(.cControlSource),':','')),
VAL(STRTRAN(LEFT(EVAL(.cControlSource),5),':','')))
OUTRO
.Value=IIF(.lShowSeconds,VAL(STRTRAN(TIME(),':','')),
VAL(STRTRAN(LEFT(TIME(),5),':','')))
FIMSE
ENDWITH

Paraalterarotempo,umutilizadorapenastemdeclicarnashoras,minutosousegundosexibidos
e,emseguida,aumentaroudiminuiressevalor.Alternativamente,otempopodeserinseridodigitando
diretamenteparaocontroleeocursorteclasesquerdaedireitapodeserusadoparanavegardentrodo
aocontrole.Ashorassolimitadasaointervalode023,eminutosesegundosparao0gama59.
Cadaunidadedetempoagedeformaindependenteerolaapartirdoseusuperiorparalimiteinferioreviceversa
(Assimcomodefinirumdespertadordigital).
Aprincpio,acheiqueseriaimplementarumafunoderolagemcontnuacomonossotempo
giratrio.Nodemoroumuitoantesdensdesistiudaidia.Nsrapidamentedescobriuquenohavia
maneiraconvenientedeimplementarestafuncionalidadedevidoordememqueospinner
eventosfogo.Comovocpoderiaesperar,oMouseDowneventoacontecepelaprimeiravez.Isto,noentanto,
seguidopelaMouseUpeventoseguidoquerpeloUpClickouDownClickmtodo.Voc
podeverseestecomportamento,mantendoasetaparabaixodogiradordeprimido.o
giradornoaumentaroudiminuirseuvaloratvocsoltaromouse!
Algicautilizadaparaaumentarediminuirosdiferentessegmentosdetemposemelhanteao
discutidasanteriormente.Aprincipaldiferenaentreestecontroleeorecipientediscutido

Captulo4:ControlesBsicos 109

acimaomtodoutilizadoparadeterminarqualosegmentodetempoparaaumentaroudiminuir.
DesdeclicarnasetaparacimaouparabaixodobotorotativofazcomqueocontroleSelStart
propriedadeaserrepostoazero,estevalorguardadoparaapropriedadegiradorcostumenSelStart
semprequeumsegmentodeterminadomomentoselecionado.Ocontroleusadoismtodospersonalizados,
SetHighlighteMoveHighlightparaselecionarosegmentodetempoapropriadoearmazenarocursor
posioparaestapropriedade.OSetHightlightmtodoabaixousadoparaselecionarotempoadequado
segmentosemprequeousurioclicanobotorotativocomomouse:
Comisso
DOCASO
***HorasHightlight
CASOENTRE(.SelStart,0,2)
.SelStart=0
***minutosDestaque
CASOENTRE(.SelStart,3,5)
.SelStart=3
DEOUTRAFORMA
***SegundosHightlightseforocaso
.SelStart=IIF(.lShowSeconds,6,0)
ENDCASE
.SelLength=2
***Salvarpontodeinsero
.nSelStart=.SelStart
ENDWITH

OMoveHighlightmtodomanipulamoverodestaqueparaosegmentoadequado
ospinnerquandoousuriopressionatantoadireita(cdigodeacesso=4)ouparaaesquerda(cdigodeacesso=19)do
chaves.ElechamadoapartirdogiradorKeyPressmtodoseosegmentodetempoatualcontmuma
cursor
valorvlido.Quandoousuriodigitaumsegmentodetempodiretamentenocontrole,oValidateSegment
mtodochamadoparasecertificardequeestnafaixacorreta.Senofor,otemporotadoresdo
lSegmentIsValidpropriedadedefinidacomofalsa.Istoevitaqueoutilizadorsemova,querum
segmentodiferentedentrodocontroleouaqualqueroutroobjetonoformulriosemantescorrigir
aentrada:

llDecrementLOCAL
Comisso
DOCASO
CASEnKeyCode=19ORnKeyCode=4
IF.lSegmentIsValid
.MoveHighlight(NKeyCode)
FIMSE
NODEFAULT

CASEnKeyCode=5ORnKeyCode=24 &&Cimaouparabaixo
IFnKeyCode=24
llDecrement=.T.
FIMSE
ChangeTime(llDecrement)
SelStart=.nSelStart
SelLength=2
NODEFAULT

DEOUTRAFORMA

110 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Ento,nsnoatrapalharahoraformatada
***Secomearmosnmerosdedigitaoepartedovalorselecionado,
***Perdemosdgitoseosrestantesqueridosturno
.SelLength=0
***Seestamosdigitandoumnmerodiretamentenocontrole,
***Secertificardequeumvalorvlidohoras,minutosousegundos
SEENTRE(nKeyCode,48,57)
Spinner::KeyPress(nKeyCode,nShiftAltCtrl)
.ValidateSegment()
ESE!.lSegmentIsValid
.SelStart =.nSelStart
.SelLength=2
FIMSE
NODEFAULT
FIMSE
ENDCASE
ENDWITH

OMoveHighlightmtodoumtantosemelhanteSetHighlightmtodoacima.Sediada
sobrealocalizaoatualdocursoreachavequeacaboudeserpressionado,eledecidequeotempo
segmentoparaselecionar:

Comisso
DOCASO
CASOENTRE(.SelStart,0,2)
IF.lShowSeconds
.SelStart=IIF(nKeyCode=19,6,3)
OUTRO
.SelStart=3
FIMSE
CASOENTRE(.SelStart,3,5)
IF.lShowSeconds
.SelStart=IIF(nKeyCode=19,0,6)
OUTRO
.SelStart=0
FIMSE
DEOUTRAFORMA
.SelStart=IIF(nKeyCode=19,3,0)
ENDCASE
.SelLength=2
.nSelStart=.SelStart
ENDWITH

AumentandoeDiminuindoossegmentosdetempotratadopeloChangeTimemtodo.
EsteummtodosobrecarregadoquechamadodetantooUpClickeDownClickgirador
mtodos.Umparmetrodelgicanicapassadoparaestafunodizquesedeveounoparaincrementar
oudecrementarosegmentoespecificado.OChangeTimemtodo,emseguida,chamaoapropriado
mtodoparalidarcomashoraseminutosclculos.Umavezqueamanipulaodossegundos
valortosimples,eletratadodirectamentenoChangeTimemtodo:

LPARAMETERStlDecrement
***QuandotlDecrementverdade,estamosdiminuindootempo,casocontrrio,nssomos
***Incremento.Primeiro,temosdeseleccionarqualosegmentoestsendomodificada
***Examinandoovalorsalvoanteriormentedenselstart
Comisso

Captulo4:ControlesBsicos 111

DOCASO
CASOENTRE(.nSelStart,0,2)
.IncrementHours(TlDecrement)

CASOENTRE(.nSelStart,3,5)
.IncrementMinutes(TlDecrement)

DEOUTRAFORMA
IFtlDecrement
.Value=IIF(INT(.value%100)=0ouINT(.value%100>59),
INT(.Value/100)*100+59,.Value1)
OUTRO
.Value=IIF(INT(.value%100)>58,
INT(.Value/100)*100,.Value+1)
FIMSE
ENDCASE
.lSegmentIsValid=.T.
ENDWITH

Etiquetaspiscando(Exemplo:CH04.VCX::cntLblBlink)
Mesmoquealgunsdessaequipeescritabritnica,estenoumcomentrioderisivesobrertulos.
VoltarnosdiasdeFoxProparaDOSeFoxProparaWindows,poderamosespecificartextointermitente
definindoumcdigodeformatode'B'.Infelizmente,issonofuncionanoVisualFoxPro.Contudo
sevocprecisardeumrtulodepiscardevezemquando,criandoestaclassemuitosimples.
TudoquevocprecisadeumrecipientecomasuaBackStyledefinidacomo0transparenteeborderwidthseta0.
Soltarumrtuloeumtemporizadorparaorecipiente.Definirointervalodotemporizadorpara300eadicioneaseguinte
linhadecdigoparaoseumtododetemporizador:

COMThis.Parent.lblBase
.Visible=!.Visible
ENDWITH

Voila!Piscandoetiquetas!

Acaixadeediodeexpanso(Exemplo:CH04.VCX::edtBase)
UmdosdefeitosdacaixaclassebaseedioVisualFoxProqueelepodesermuitopequenopara
permitiraousuriovertodootextonocampodememorandoqueestsendoexibido.Podemosresolveresteproblema
combastantefacilidade,adicionandoalgumaspropriedadesparaanossacaixadeedioclassebaseeumpardemtodos
encolhereexpandilo.
para
primeiravista,podesertentadoaexpandirautomaticamenteacaixadeedioquandoseobtmofoco
ereduzilonovamentequandoseperdeofoco.Noentanto,nareflexoprovavelmentevocvaiconcordarcomeste
nofariaumbomdesigndeinterfaceeseria,nomnimo,serumpouco
desconcertanteparaousuriofinal.Porisso,optouporpermitirqueousurioparaexpandireencolher
caixadeedioatravsdacriaodeummenudeatalhochamadoapartirdacaixadeedioRightClickmtodo.este
menutambmdaousurioacapacidadedealterarafontedotextoexibidonacaixadeedio.
(Seususuriosfinaisiroapreciaracapacidadedealiviarapressosobreosolhos,ampliandoafonte,
especialmentequandooscamposdememorandoasereditadosolongos.)
112 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura4.3Acaixadeedioexpandindoainstanciao

Figura4.4Acaixadeedioexpandindoquandomaximizadocomafontealterada

Captulo4:ControlesBsicos 113

Nossaclassecaixadeedioemexpansoutilizanovepropriedadespersonalizadas,dosquaisapenasostrs
primeiros
requerqualquermanipulaodiretamasssevocquiseralterarocomportamentopadro.
Tabela4.4Aspropriedadespersonalizadasdecaixadeediodeexpanso

Propriedade Descrio
lCleanUpOnExit Definacomotruepararemovercaracteresnoimprimveisforadaextremidadedomemo
lPositionAtEnd Quandoverdadeiro,posicionaocursornofinaldotextoexistentequandoacaixadeedio
obtmofoco
lResize Quandotrue,permiteaopodeexpandireencolheracaixadeedioquandoo
usurioclicadireitodomousenacaixadeedioparaexibiromenudeatalho
lMaximized Definidocomoverdadeiroquandoacaixadeediomaximizadaefalsoquandono
nOrigColWidths Salvaaslargurasdascolunasoriginaisdetodasascolunasnagradequecontmesse
caixadeedioparaquepossamosexpandiracaixadeedioparaocuparoespaodetodaa
porovisveldagrelha
nOrigHeight Alturadacaixadeedionainstanciao
nOrigLeft Esquerdadacaixadeedionainstanciao
nOrigRowHeight RowHeightOriginaldagradequecontmacaixadeedio(seacaixadeedio
encerradonumagrade)
nOrigTop Partesuperiordacaixadeedionainstanciao
nOrigWidth Larguradacaixadeedionainstanciao

Bytheway,estecontroleespecialirfuncionarcomo,mesmoquandodentrodeumagradeapesarda
cautelanoinciodestecaptulo.Ento,comoissofunciona?Quandoocontroleinstanciado,a
chamardeseuInitmtodoexecutaocostumeSaveOriginalDimensionsmtodo,quefazexatamente
queseunomeimplica:

lnColLOCAL
Comisso
***SalvedimensesoriginaisdoEditBoxeposio
.nOrigHeight=.Height
.nOrigWidth =.Width
.nOrigTop =.Top
.nOrigLeft =.Left
***Seeleestiveremumagrade,salvarrowHeighteColumnWidthsdagrade
IFUPPER(.Parent.BaseClass)='Coluna'
.nOrigRowHeight=.Parent.Parent.RowHeight
PARAlnCol=1a.Parent.Parent.ColumnCount
.nOrigColWidthsDIMENSO[lnCol]
.nOrigColWidths[lnCol]=.Parent.Parent.Columns[lnCol].Width
ENDFOR
FIMSE
ENDWITH

Talcomoacontececomnossasaulasdecaixadetexto,nsgostamosdesercapazdeselecionartodososcontedos
foco,portanto,verificarseSelectOnEntry=.T.eselecionetodootexto,senecessrio.Almdisso,ns
quandoacaixadeediofica
posicionarocursornofinaldotextoselecionadousandoum teclado'{CTRL+END}',seonosso
lPositionAtEndpropriedadedefinida:

114 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comisso
IF.SelectOnEntry
.SelStart =0
.SelLength=LEN(.Value)
ENLSE
IF.lPositionAtEnd
TECLADO'{CTRL+END}'
FIMSE
FIMSE
ENDWITH
NODEFAULT

DacaixadeedioRightClickmtodochamasuaShowMenumtodoseasualResizepropriedadedefinida
paratrue.OShowMenumtodo,emseguida,exibeomenudeatalho(mnuEditBox)eassumea
medidasadequadascombasenoquefoiescolhidoapartirdomenu:

lcFontStringLOCAL,lcFontStyle,lcFontName,lcFontSize,llBold,llItalic,
lnComma1Pos,lnComma2Pos
pnMenuChoicePRIVADO
pnMenuChoice=0
DOmnuEditbox.mpr
Comisso
DOCASO
***SeAlargarfoiselecionado,expandaacaixadeedioamenosqueseja
***Jexpandida
CASEpnMenuChoice=1
SE!.lMaximized
.Prolongar()
FIMSE

***Sepsiquiatrafoiselecionado,psiquiatradacaixadeedio,seeleexpandido
CASEpnMenuChoice=2
IF.lMaximized
.Encolher()
FIMSE

CASEpnMenuChoice=3
lcFontStyle=IIF(.FontBold,'B','')+IIF(.FontItalic,'I','')
***Obterescolhadousuriodafonteaserusada
lcFontString=GETFONT(.FontName,.FontSize,lcFontStyle)
***Analisaraspropriedadesdefontedacadeiadevolvida
***Apsaverificaoparacertificarsedequeousurioselecionadoalgo
ESE!VAZIO(lcFontString)
lnComma1Pos=AT(',',lcFontString)
lcFontName=Esquerda(lcFontString,lnComma1Pos1)
lnComma2Pos=RAT(',',lcFontString)
lnFontSize=VAL(SUBSTR(lcFontString,lnComma1Pos+1,
lnComma2PoslnComma1Pos1))
lcFontStyle=SUBSTR(lcFontString,lnComma2Pos+1)
llBold=IIF('B'$lcFontStyle,.T.,f.)
llItalic=IIF('I'$lcFontStyle,.T.,f.)
.FontName=LcFontName
.FontSize=LnFontSize
.FontBold=LlBold
.FontItalic=LlItalic
FIMSE

Captulo4:ControlesBsicos 115

ENDCASE
ENDWITH

O GETFONT()funoretornaumstringnoFontNameforma,FontSize,FontStyle
(OndefontStyle'B'secorajoso,"eu"seItlicoe"BI"seaomesmotempo).Depoisdeanalisarestetipodeletra
corda,queconverteroscaracteresfontStyle,sehouver,paraosvaloreslgicosesperadospela
Propriedadesdacaixadeediocorrespondente.
AAlargaromtodousadoparaexpandiracaixadeedio,masamaneiraemqueocontrole
efectivamenteexpandidatemdetomaremconsideraoosvriostiposderecipientenoqualelepodeser
colocou.

Poderamosterchamadoomtodo'expandir',masesteotipode
nomedescritivoquepodemuitobemsetornarumapalavrareservadaemalgum
versomaisrecentedoVisualFoxPro.Paraprogramardefensivamentequetendema
longedeusarpotenciaispalavrasreservadascomonomesdemtodosedecampo.Estetem
recuar
sidoumproblemanopassadocomovriasversesdoFoxProintroduziramnova
comandosefunes.IssovaleparaVisualFoxProtambm,comonovo
propriedades,eventosemtodostmsidointroduzidos.Porexemplo,muitos
desenvolvedores,umavezusadovariveisn omeadasOLDVALouCurvalemFoxProV2.xapenas
temsuarupturacdigoquandoexecutadonoVisualFoxProondeambososnomesreferemse
para
funes.
nativa

Ocdigo,portanto,umpoucocomplexa:

Comisso
DOCASO
MAISCULAS(.Parent.BaseClass)='Coluna'

SeesteoCurrentControlemumacolunadegrade,devemosexpandiracluladagradeatualantes
expandiracaixadeedio.Ento,podemosajustarotamanhodacaixadeedioparapreenchertodaagrade:

.ExpandGridCell()
.Height=.Parent.Parent.RowHeight
.Largura=.Parent.Width

MAISCULAS(.Parent.BaseClass)='pgina'

Estetambmumcasoespecialporqueaspginasnotemumapropriedadedealtura.aocontrrio,o
PageFrameemsitemumaPageHeightpropriedade,porissotemosdeusarissoparaexpandiracaixadeedio:
.Topo =0
.Esquerda
=0
.Height=.Parent.Parent.PageHeight
.Largura=.Parent.Parent.PageWidth

Emseguida,temosdenoscertificarcaixadeedioaparecenotopodetodososoutroscontrolesnapgina.
ChamandoseuZOrdermtodocomumparmetrode0irfazerisso:

116 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

.zOrder(0)

Quecuidadoscasosespeciais.Todasasoutrassituaespodemsertratadasno Casocontrrio
clusulacomosegue:

DEOUTRAFORMA
.Topo =0
.Esquerda
=0
.Height=.Parent.Height
.Largura=.Parent.Width
.zOrder(0)
ENDCASE

Finalmente,devemosdefinirosinalizadorparaindicarqueacaixadeedioestagoraemumestadomaximizado:

.lMaximized=.T.
ENDWITH

Seacaixadeedioestemumagrade,otratamentorequerummtodoseparadoparaajustartantoo
largurasdecolunaedagradeRowHeightpropriedadeantesdecaixadeediopodeserexpandido.o
expandGridCellmtodofazissocomapenasalgumaslinhasdecdigo:

lnColLOCAL
COMThis.Parent

Primeiro,vamosdefiniroColumnWidthpropriedadedetodasascolunasnagradeparazero:

PARAlnCol=1a.Parent.ColumnCount
.Parent.Columns[LnCol].Width=0
ENDFOR

Emseguida,redimensionaroColumnWidthdacolunaquecontmacaixadeedioparaamesmalargura
medidaqueagrade.TambmdefinimosdagradeAlturaDaLinhaalturadaprpriagrade(menoso
HeaderHeightdagrelha):

.Largura =.Parent.Width
.Parent.RowHeight =.Parent.Height.Parent.HeaderHeight

Finalmente,devemosdeslocaragrelhaparabaixoatalinhaatualnapartevisvelda
grade.Ocdigoabaixofuncionaporqueapartevisveldagrelha,depoisdeserredimensionado,contm
apenasumanicalinha:

Fazerenquanto.Parent.RelativeRow#1
.Parent.DoScroll(1)
ENDDO
ENDWITH

OShrinkmtododacaixadeedio,comooprprionomeindica,redimensionaacaixadeedioaoseuoriginal
dimensesecontmumcdigosemelhanteaodoAlargaromtodo.Naverdade,umbom
otimizaoparaessecontroleseriaadicionarum"SetParentmtodo"queiriaavaliara
Captulo4:ControlesBsicos 117

continerpai,faaosajustesnecessrios,evoltaraalturaelarguraparaoqualo
caixadeediodeveagoraserdefinida.Noentanto,umtalmtodoteriadesersobrecarregadoparalidarcom
expandindoecontraindocaixadeedio.Aabordagemqueadotamostantomaissimplese
maisclara.Comosempretentamoscodificarcomamanutenoemmente.
Finalmente,coloqueumpoucodecdigoemdecaixadeediovlidomtodoparareduzilo,casoousurio
decideparanavegarparaumnovoregistroenquantoeleestivermaximizada.Amaioriadosdesenvolvedoresusaralgum
WriteBuffermtodoquechamadoquandoousurioclicaemumbotodenavegaonabarradeferramentas.este
tipode
mtodo,nasuaformamaissimples,contmcdigosemelhanteaeste:

IFTYPE('_Screen.ActiveForm.ActiveControl.Name')='C'
***Paragradedevocdeveaprofundaredefinirofocoparaocontrolecontido
IFUPPER(_Screen.ActiveForm.ActiveControl.BaseClass)#'Grid'
_Screen.ActiveForm.ActiveControl.SetFocus()
FIMSE
FIMSE

IssofarcomqueaValiddaActiveControlaofogo.Obviamente,eletambmseracionadoseousurio
clicaemumbotodecomando,afimdenavegarparaumnovorecorde.Assim,ocdigonacaixadeediode
Vlidomtodogarantequeocontrolelimpaapssimesmoquandoousurioesquece.Issotambm
retiraquaisquercaracteresnoimprimveisaolargodaextremidadedocampomemoseousuriotemrepetidamente
pressionadoo ENTERchave,numatentativaparasairdocampo.Estafuncionalidadechamadoquandoo
ediodacaixadelCleanUpOnExitpropriedadedefinida:

Comisso
IF.lCleanUpOnExit
.Limpar()
FIMSE
IF.lMaximized
.Encolher()
FIMSE
ENDWITH

Omtododelimpezatrabalhaparatrsapartirdoltimocaracterenocampoeremovequalquer
caracteresASCIIcujovalorinferiora33(oprimeirocarcterdeimpresso,nonoespao
conjuntodecaracteresASCII):

lcMemoFldLOCAL,lnChar
***Issovaiselivrardaslinhasvaziasqueocorremquandoousuriopressiona
<Enter>
***ououtraschavesestranhosemvezde<Tab>parasairdacaixadeedio
Comisso
lcMemoFld=IIF(VAZIO(.Value),'',ALLTRIM(.Value))
***TiraoffcaracteresinvlidosnofinaldoMEMOcampo.
***Loopparatrsatravsdocampoeobteraposiodo
***Primeirobyte,quenoumespao,TABouCR/LFouqualqueroutra
***PersonagemcomumvalorASCIImenor,emseguida33:
PARAlnChar=LEN(lcMemoFld)a1STEP1
IFASC(SUBSTR(lcMemoFld,lnChar,1))>32
SADA
FIMSE
ENDFOR
IFlnChar>1

118 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

lcMemoFld=LEFT(lcMemoFld,lnChar)
FIMSE
.Value=LcMemoFld
ENDWITH

Calendriodecombinao(Exemplo:CH04.VCX::cntCalendar)
Estaclassenaverdadeumacomposioprojetadaparaimitarocomportamentodeumalistadropdownpara
inserirdatas.Nstloincludoemnossoscontrolesbsicosdefinidosporqueamaioriadasaplicaesrequerem
aentrada/atualizaodoscamposdedata.
OprimeiropassoparacriaressecontroleeracriarumasubclassedeVisualnativodoFoxPro
classedecontinercomoanossaprpriacntBaseclasse.BaseamosanossacntDateclassenesterecipiente,emvez
dediretamentenaclassebaseVisualFoxPro.Paraanossanovaclassensadicionamosumacaixadetexto,uma
botodecomandoe,finalmente,umobjetoOLEContainer.(UsamosoInserircontroleopode
nativodoContainerOLEInserirobjetodedilogoparaselecionarocontroledecalendrioqueacompanhao
VisualFoxProeadicionloaorecipiente.)
Figura4.5dilogoInserirobjeto

Emgeral,projetarnossasclassescompostasdemodoqueosobjetosmembroschamarmtodosdecontentores
pararealizarsuasfunes.Porexemplo,poderamosterapenasdefiniroOrigemDoControlodotexto
caixanocontentorparaseligarafontededadossubjacente.Emvezdisso,nsadicionamosumcControlSource
propriedadeparacntDate,bemcomoumSetControlSourcemtodo.Arazoparaqueemtempodedesign,
nsnoprecisamosdeseaprofundardentrodorecipienteparadefiniraspropriedadesindividuaisdocontido
objectos.Assim,paraconfiguraracaixadetextocontidoprecisamosapenasdefiniroexpostocControlSource
propriedadenorecipienteedeixarorestoparaoSetControlSourcemtodo,quechamado
apartirdocontinerInitmtodo.Omesmomtodotambminicializaalegendadocomando
botoparaqueelecomeaavidacomoumbaixoseta.
Poderamosterfeitoestepadronobotoe,naverdadenstentamosfazlo.Contudo,
testandoocontroledepoisqueelefoiabandonadoemumformulrioproduzidoresultadosinconsistentes.Porvezes,
exibiriaasetadesejadaparabaixo,enquantoemoutrosmomentoseleiriamostrarumasetaparacimaquando
oformulriofoiinstanciado.Nsnoencontramosnenhumaexplicaobviaparaocomportamento,masseestabelecem

Captulo4:ControlesBsicos 119

queanicamaneiradeevitarestainconsistnciafoiparainicializaralegendadobotoemcima
instanciao:

Comisso
.txtDate.ControlSource=.cControlSource
.CmdDrop.Caption=CHR(25)
ENDWITH

Afuncionalidadededropdownexecutadoatravsdetrsmtodospersonalizados
DropCalendar,PopCalendareSetCalendar.
DropCalendarfazocalendriovisvelealteraalegendanobotodecomando
apartirdeumasetaparabaixoparaumasetaparacima.Elechamadoapartirdomtodocliquedobotodecomando
eoKeyPressmtododecaixadetexto.Desdequensqueremosessecontroleparasecomportarcomoumacombinao,
ocalendrioabertoquandoousuriopressionatanto F4ou ALT+DNARROW:

Comisso
.OleCalendar.Visible=.T.
.cmdDrop.Caption=CHR(24)
ENDWITH

PopCalendarescondeocalendrioabertoquandoouobotodecomandoclicadoouum
entradafeitaapartirdocalendrio.Eletambmatualizaovalordacaixadetextocomovalor
seleccionadoapartirdocalendrio.Finalmente,elemudaoconenobotodecomandoapartirdeumup
setaparaumasetaparabaixo:

Comisso
.txtDate.Value=TTOD(.OleCalendar.Object.Value)
.OleCalendar.Visible=.F.
.cmdDrop.Caption=CHR(25)
ENDWITH

SetCalendarsincronizaaexibiodedatadocalendriocomovalorcontidono
caixadetexto.ElechamadoapartirdoLostFocusmtododacaixadetextonocasodeocalendriovisvel
quandoousuriodigitaumanovadatanacaixadetexto.tambmchamadodeoAtualizarmtodoparatomar
cuidardapossibilidadedequeousuriotenhanavegadoparaumnovorecorde,enquantoocalendriovisvel
assegurandoquetantoacaixadetextoeocalendrioexibiramesmadata.Finalmente,chamamoso
SetCalendardirectamenteapartirdocontinerDropCalendarmtodoparagarantiradatacorreta
sempreexibidaquandoocalendriofeitavisvel:
Comisso
.OleCalendar.Object.Value=.txtDate.Value
.OleCalendar.Refresh()
ENDWITH

Tambmprecisamosdealgumcdigoparaimitarocomportamentonaturaldelistasdropdown,quepodeser
abertousando F4ou <ALT>+<DNARROW>.NsarmadilhaestaschavesnoKeypressmtododotexto
boxparaquepossamosfazerocalendriovisvelquandoelessodetectados:

120 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***VerifiqueparaF4eALT+DNARROW
IF(nKeyCode=3)OR(nKeyCode=160)
COMThis.Parent
***Faaocalendriovisvelsenofor
ESE!.OleCalendar.Visible
.DropCalendar()
NODEFAULT
FIMSE
ENDWITH
FIMSE

Figura4.6CalendrioCombo

OnicooutrocdigonestaclasseestnoAfterUpdatemtododocontroledecalendrio
si.ElesimplesmentechamaocontinerPopCalendarmtodoparaatualizaracaixadetextocomovalor
quefoiselecionadoefazerocalendrioinvisvel.

Botesdecomando(Exemplo:CH04.VCX::cmdBase)
Almdepermitirqueousurioinsiradados,amaioriadosaplicativostambmpermitemaousurioteralgumtipo
deao.Esteolugarondebotesdecomandooualgumavariaocomobotesdabarradeferramentas,digiteo
imagem.Comodiscutimosnocaptulosobredesign,clicandoemumbotodecomandodevedara
userfeedbackinstantneoquealgoocorreu.Vocpodefazerissofacilmente,desativlo,
impedindoqueousuriocliquesobreelevriasvezese,talvez,paraoencerramentodosistema.Colocamosesta
funcionalidadeemnossaclassebasebotodecomando.Claro,vocnopodequerercadacomando
Captulo4:ControlesBsicos 121

botoemtodasassuasaplicaesparaapresentaressetipodecomportamento.Nsplanejadocomantecednciae
apropriedadelDisableOnClickparaaclasse.Destaforma,aoclicarnobotodecomandonica
acrescentou
desactivaoquandoestapropriedadedefinidacomotrue.NstambmadicionamosumcostumeOnClickmtodopara
classe.CliquedobotodecomandochamaseuonClickmtodo.Qualquercdigoespecficoinstnciasempre
este
vainesseonClickmtodo.
Onicocdigonanossaclassebasebotodecomandoresideemseumtododeclique:

Comisso
***Desativarobotoseespecificado
IF.lDisableOnClick
.Enabled=.F.
FIMSE
***Executeocdigopersonalizado
.OnClick()
***Rehabilitaroboto
ESE!.lDisableOnClick
.Enabled=.T.
FIMSE
ENDWITH

Notesequeestaabordagemnospermitedesativarumbotoedeixlodesativado,alterandoasua
lDisAbleOnClickpropriedadeemumainstnciadeOnClickmtodo.Istotilparaqueosbotes
deveserutilizadoapenasumavezeapenassoativadosquandoalgumacondioexternaatendida(porexemplo,um
'Save'ouoboto'Revert').

Gotcha!Programaodoscontroleslgicos
Ascaixasdeseleosoprojetadosprincipalmenteparalidarcomdadoslgicos(ouseja,Sim/No,On/Offetc).o
propriedadedeterminaseacaixadeseleoexibidoconvencionalmenteoucomoumboto.Quando
Estilo
usandoomouse,existemapenasdoisvalorespossveisparaumacaixadeseleo,aT.lgico.(Ounumrica1)
e.Flgico.(Numrico0).
Apropriedadevalorpodeaceitarvalorestantolgicasounumricasepodeatmesmointercmbio
entreosdoistiposqueprevemqueocontrolenoestvinculado.Noentanto,adefiniodovalor
programaticamenteparaoutracoisaseno.T.ou.F.ouparaqualquervalornumricodiferentede0ou1
dumresultadoestranho,comoFigura4.7mostra:

122 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Figura4.7Caixadeverificaocomportamentoprogramtico

Observequeacaixadeseleoconvencionalparecesertantomarcadaedesativadano
mesmotempo,quandoumvalorinvlidoforespecificado.Piorainda,paraacaixadeseleoestilogrfico,h
nenhumadiferenaaparenteentreumpositivovlidoeumvalorinvlido!Noentanto,apoupana
graaqueemtodososcasoseapesardaaparnciavisual,apropriedadeValuenodevolvero
valoratual.

Pginasequadrosdapgina(exemplo:CH04.VCX::pgfBaseeCH04.PRG)
VocpodesubclassedoVisualFoxPropageframeclassebasevisualmentenodesignerdeclasse.Hsim
apenasumpequenoproblematodasaspginascontidassopginasdeclassebasedoVisualFoxProe
nohnenhumamaneiradeumasubclassedapginaclassebasevisualmente.Piorainda,sevocfizerumasubclasse
paraopageframeedarlhe,porexemplo,trspginas,vocnopodemaistardeusloemumformulrioe
removerumadaspginasnodesignerdeformulrio.Voctambmvaidescobrirquesevocusaressetipode
quadrodepginasubclasse,vocnopodemesmomudarosnomesdaspginasemumainstnciadele.
Issoporquevocnopodeapagaroualterarosnomesdosobjetoscontidosquepertencema
umaclassepai.Porestemotivo,melhor,quandosubclasseoquadrodepgina,paradefinirasuaPageCount
propriedadepara0nasubclasse.Noentanto,podehaversituaesemquevocprecisaparaadicionar
mtodosdiretamenteparapginasemvezdeparaoquadrodepgina,algoquevocspodefazersevoc
criarumaclassedepginapersonalizada.
Naverdade,vocpodesubclassedaclassebasepgina.Vocsimplesmentenopodefazlovisualmentenaclasse
designer.Eledeveserfeitodecdigo.Aboanotciaqueissoumatarefafcil.Agorasmsnotcias
Anicamaneiraqueencontramosparausarnossaspginaspersonalizadasfoiadicionandoasnossapginapersonalizada
quadroemtempodeexecuo.Oquadrodepginanotemqualquerpropriedadeacessvelparaarmazenaraclasse
sobreaqualbasearsuaspginasesempreinstanciaonmerodepginasnecessriasdo
classeVisualFoxProbasedePgina.Istosignificaqueaspginaspersonalizadassopraticamenteinteisamenosquevoc
pretendeusarinstanciaoatraso.

Captulo4:ControlesBsicos 123

Alm:oque"instanciaoatraso'?
instanciaoretardadaumatcnicanaqualumobjectosinstanciadoquandorealmente
requeridos.Nocontextodeumquadrodepgina,issosignificaquequandovoctivercriadoumapgina,voc
selecionetodososseuscontroles( CTRL+Avaifazerisso)e,emseguida,escolha'Salvarcomoclasse"nomenu
IssoircopiartodososcontrolesemumaclassedecontinerVisualFoxProeguardlocomoumanovaclasse.
Arquivo.
Agoravocpodeexcluirtodososcontrolesdapginaeadicionlosdevolta,largandooseunovo
classedecontinerparaapginaeposicionla.FaaumanotadoTopeesquerdapropriedade
valoresparaonovorecipientevocvaiprecisardelesmaistarde,quandovocadicionarorecipienteemrun
Tempo!Finalmente,vocpodeapagartodoocontedodapgina,deixandooembrancoerepitaoprocessopara
todasaspginasemseuquadrodepgina.
Notequevocdeveplanejarhierarquiadeobjetosdasuapginacorretamenteparaqueissofuncione.
Adicionandooscontrolesparaumrecipientetambmadicionaumacamadaextradereferenciamentoporqueocontiner
agoraficaentreoscontrolesqueelecontmedapgina.Assim,qualquerrefernciaspginacomo:

This.Parent.<Algo>

Devesersubstitudopor:

This.Parent.Parent.<Algo>
paradarcontadeste.Outrapossibilidadeusarumaconstanteseestiveraprototipagemedepois
salvaraclasserecipiente.Assim,emvezdesereferiraThis.Parent.<Algo>,vocpoderia
#DEFINEMomThis.Parentereferemseaoutrosobjetoscomome.<Algo>.Entovoc
sprecisamudaramaneiracomoaconstantedefinidaapsorecipienteguardadacomoumaclasse.
FinalmentevocacaboudeadicionarocdigodiretamenteparadecadapginaActivatemtodocomoeste:

IFThis.ControlCount=0
This.AddObject('pagctrls',<controlclass>)
COMThis.pagctrls
.Top=<Posiodetoposalvos>
.Left=<Salvoposioesquerda>
.Visible=.T.
ENDWITH
FIMSE
Agora,quandovocexecutaroformulrioquecontmestequadrodepgina,cadapginaestarvaziaquandoo
formainstancia,demodoqueoformulrioaparecermuitomaisrpidodoqueonormal(apstodososVisualFoxPro
noagoratemqueinstanciarevinculartodososcontrolesnaspginasde"invisveis").Quandoo
utilizadorclicaemumapgina,pelaprimeiravez,orecipienteapropriado,comtodososcontrolos,
instanciado.Emborahaja,obviamente,umpequenoatrasoapsaprimeiraclicaremumapgina,eleraramente
perceptvelparaosusuriosquenormalmenteseriammuitofelizqueassuasformasparecemmuitomaisrpido!

Agora,dev oltaparapginaspersonalizadas
Afimdefazerusodepginaspersonalizadascriamosumaclassedepginacustomframe(pgfBase)na
designerdeclasseedefinirsuasTotalPginaseActivePagepropriedadesa0.Eletemummtodopersonalizado
nomeadasSetPagesquechamadodeoInitmtodoecujonicoobjectivoremover
pginaseclassebaseVisualFoxProadicionarnossaspginaspersonalizadasemtempodeexecuo.Aquiest:

124 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

lnPageCountLOCAL,lnCnt
***Certifiquesedequepodemosencontraroprgquedefineaspginaspersonalizadas
SETPROCTOCH04ADITIVO
***Retirepginasclassebaseeadicionarnossaspginaspersonalizadas
Comisso
lnPageCount=.PageCount
.PageCount=0
.ActivePage=0

PARAlnCnt=1alnPageCount
***Adicionarnovo
.AddObject('PgBase'+ALLTRIM(STR(lnCnt)),'PgBase')
ENDFOR
.PageCount=LnPageCount
.ActivePage=1
ENDWITH

Noentanto,noconseguiapensaremqualqueroutrapropriedadepersonalizadaoumtodoqueanossanovapgina
classequadronecessrio.Acomunicaoentrepginaspoderiamsermanipuladospormtodospersonalizadosde
oquadrodepginaqueoscontm.Normalmenteestetipodecomunicaotratadapelocostume
mtodosdeformulrio.Indiscutivelmenteoquadrodepginanaverdadeseriaomediadormaisadequado.
Emseguida,definimosanossaclassedepginapersonalizadanocdigo.Demoslheumapropriedadepersonalizada
lRefreshOnActivate.Quandodefinidocomoverdadeiro,apginaatualizadaquandoelesetornaativoens
chamada
adicioneiummtodopersonalizadochamadoRefreshPagequeusadoparaembrulharmtododeactualizaodapginana
damesmaformaqueonossoRefreshFormmtodoenvolvemtododeactualizaodoformulrio.Nstambmadicionamos
apropriedadelReadOnlyparapermitirqueonossoquadrodepginaparaconterumacombinaodeeditvelevista
apenasaspginas.NossapginapersonalizadaverificaessapropriedadeemseuActivateedefineseuscontrolescontidos
apropriadamenteusandoumanicalinhadecdigo:

Comisso
.SetAll("Ativado",!.lReadOnly)
ENDWITH

Sparaserflexvel,nstambmacrescentouestecdigoparaonossoRefreshPagemtodonocasodealgumaao
tomadapeloutilizador(clicandoemumbotodabarradeferramentas,porexemplo)poderiaalteraroestadode
apginaatual.Finalmente,deulheumcPrimaryTablepropriedadeaserutilizadoparaasformasque
atualizarvriastabelas.Emformasdestetipo,amaioriadospromotorestendemaexibiroindivduo
tabelasempginasseparadas.Estaadiodestapropriedadeparaapginapermitequeocdigoque
escritoparasermaisgenrico:

DEFINECLASSPgBaseASPgina

lRefreshOnActivate=.T.
lReadOnly=.F.
cPrimaryTable=''

activarafuno
Comisso
.SetAll("Ativado",!.lReadOnly)
ENDWITH
ENDFUNC
Captulo4:ControlesBsicos 125

RefreshPageFUNO
***EsteummtododemodelosemelhanteaoRefreshForm
***Sevocprecisaratualizarestapgina,colocarocdigoaquiemvezdeemAtualizar
Comisso
.SetAll("Ativado",!.lReadOnly)
ENDWITH
ENDFUNC

ENDDEFINE

Parecequeadefiniodeclassedoquadrodepginaestintrinsecamenteligadasuacontido
pginasainstanciao.Nscriamosumconstrutorpoucoquadrodepgina(pgfbuild.prg)emumatentativade
nossaspginaspersonalizadasparaoquadrodepginaemtempodedesign.Eleapareceuparatrabalharatquetentou
adicionar
Formato.Ento,paranossasurpresa,ossnazzynovaspginaspersonalizadasquetnhamosacabadoadicionadostinha
executaro
peloFoxPropginasVisualclassebaseparanenhumarazoaparente!
sidosubstitudo
ArazotornaseaparentesevocabrirumSCXarquivoquecontmumquadrodepginacomoumatabela
enavegarnele.Nohregistrodequalquerumadaspginasdoquadrodepginae,portanto,nohmeios
paraoquadrodepginaparadeterminarqualclassedebasearassuaspginason.Emvezdisso,ocampodepropriedades
paraoquadroobjetopginadefinetodasaspropriedadesparaassuaspginascontidas.outrainteressante
pontoquedepoisdeexecutaronossoconstrutor,ocampodepropriedadesdoquadrodepginareferenciadaaqueles
pginaspelosnomesquelhesderaemostroulhescomosendonossaspginaspersonalizadas!Mas
quandoolhamosparaestemesmoformulrionodesignerforma,afolhadepropriedadeslistadasaspginascomo
pginasdeclassebasecom'Pgina1'osnomespadro,'Page2',eassimpordiante.(Alis,omesmo
pareceserverdadeiroparaGridsesuascolunas.Enquantovocpodeespecificarcabealhospersonalizadospara
colunasequalquercontrolequevocgostaparainclusoemumacoluna,asredessempreinstanciaroreal
colunasdiretamentedaclassebaseVisualFoxPro.)
Sevocgostariadeverestecomportamentoporsimesmo,bastaexecutaroprogramapages.prgque
includocomocdigodeexemploparaestecaptulo.Definaonmerodepginasnamolduradepginapara
umnmeromaiordoquezeroeexecutaroconstrutor.Quandoajaneladenavegaoaparece,preencha
osnomeselegendasdesuaescolha.Fecheesalveoformulrio.Quandoofizer,pages.prgexecutado
aformaqueacaboudesersalvo.
Aconcluso,portanto,que,emboravocpodedefinirumaclassedepginapersonalizadaeusarum
construtorparaadicionarpginascombasenessaclasseparaumquadrodepginaemtempodedesign,asalteraes
soperdidasquandooquadrodepginainstanciado.Parausarpginascombaseemumaclassepersonalizada,voc
feitas
adicionlosemtempodeexecuo,oquesignificaquesedeveouserdefinidacomtodososcontrolosnecessrios,ou
deve
vocdeveadicionaroscontrolesindividualmente(usandooAddObjectmtodo)ouusarodiferido
tcnicainstanciaoacimareferido.
Nossaintenoaquifoiparadarlheumamaneirafcileconvenientedeadicionarpginaspersonalizadaspara
seuprprioquadrodepginapersonalizadanodesignerdeformulrio.Muitoanossadecepo,ns
descobriuqueelesimplesmentenopodiaserfeito.Maspelomenosagorasabemos.

126 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo5:ComboseListas 127

captulo5
ComboseListas
"Porquenopodealgumdarnosumalistadecoisasquetodomundopensaeningumdiz,e
outralistadecoisasquetodomundodizeningumpensa."
("OProfessordoalmooTable",deOliverWendellHolmes)

Comboselistassodoiscontrolesmuitopoderosasquepermitemqueousurioselecioneapartirde
predeterminadoconjuntodevalores.Usadocorretamente,elesfornecemumvaliosomeiodegarantir
uma
validadedosdados.Usadosd eformainadequada,elespodemserseupiorpesadelo.Sevocusarum
caixaparaapresentarousuriocommilharesdeitens,vocestpedindoparaterproblemas!Nisso
combo
captulo,apresentamosalgunsdecombinaoelistasteisclassesquepodemserutilizadospara
polidointerface,profissional,reduzindosignificativamenteotempodedesenvolvimento.Todos
fornecerum
asclassesapresentadasnestecaptulopodemserencontradosnabibliotecadeclassesCH05.

Combinaoelistabsicodacaixa
Umolharparaaspropriedadesemtodosdecaixasdecombinaoelista,evocpodeverelesfuncionam
internamenteemmuitodamesmamaneira.Emboraumacombinaodropdownpermiteadicionaritensaoseu
OrigemDaLinha,vocnopodefazerissocomumdropdownoulistaderolagemoumelhor,nocomabasenativa
controlesdeclasse.ComnadamenosdoquedezpossveisRowSourceTypeseduasformasdiferentesde
lidarcomsuaslistasinternas(ListItemIdeListIndex),essasclassesforneceraodesenvolvedor
quasedemasiadaflexibilidade.DosdezRowSourceTypes,0Nenhum,1Value,2Alias,3SQL
Declarao,5matrize6Campossoosmaisteis.Estecaptulocontmexemplosusando
estesseisRowSourceTypes.
Osquatro,mantendose4consulta(.QPR),7Files,8Estruturae9Popupnosoabrangidos
porquesooumuitoespecficoemsuanatureza(7Filese8Estrutura)ousoincludospara
fornecercompatibilidadecomversesanteriores(4consultae9Popup)enoseencaixamnocontextodeum
aplicaodoVisualFoxPro.

coleesdelistaeListItem
Estasduascolecespermitemacessarositensnalistainternadocontrolesemter
sabernadasobreasuaespecficaOrigemDaLinhaouTipoDeOrigemDaLinha.Porcausadisto,estes
coleesesuaspropriedadesemtodosassociadospodeserusadoparaescreveralgumasmuitogenrico
cdigo.AListacoleoreferenciaositenscontidosnalistanamesmaordememque
elessoexibidos.OListItemcoleofazrefernciaaessesmesmositensporseusItemIdde.o
ItemIDumnmeronico,anlogaaumachaveprimriaqueatribudoaartigosquandoso
adicionadolista.Inicialmente,ondiceeoItemIDdeumitemespecficonalistasoidnticos.
Mascomoositenssoordenados,removidoseadicionados,estesnmerosnosonecessariamenteosmesmos
nomais.

128 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela5.1Aspropriedadesemtodosassociadoscomacoleodelista

oupropriedade Oqueissofaz?
Mtodo
Lista Contmumacadeiadecaracteresusadoparaacessarositensnalistadendice.No
disponvelemtempodedesign.Somenteleituraemtempodeexecuo.
ListIndex Contmondicedoitemselecionadonalistaou0senadaforselecionado
NewIndex Contmondicedoitemmaisrecentementeadicionadolista.muitotil
aoadicionaritensaumalistaordenada.Noestdisponvelemtempodedesign.Leiaseapenascom
tempodeexecuo.
TopIndex Contmondicedoitemqueaparecenotopodalista.Nodisponvel
emtempodedesign.Somenteleituraemtempodeexecuo.
AdicionarItem AdicionaumitemparaumalistacomTipoDeOrigemDaLinha0nenhumou1valor
IndexToItemId RetornaoItemIDparaumitemnalistaquandovocsabequeseundice
Removeritem RemoveumitemdeumalistacomTipoDeOrigemDaLinha0nenhumou1valor

Tabela5.2PropriedadesemtodosassociadoscomacoleoListItem

oupropriedade Oqueissofaz?
Mtodo
ListItem ContmumacadeiadecaracteresusadoparaacessarositensnalistadeItemID.No
disponvelemtempodedesign.Somenteleituraemtempodeexecuo.
ListItemId ContmoItemIDdoitemselecionadonalistaou1senadaforselecionado
NewItemID ContmoItemIDdoitemadicionadomaisrecentementelista.muitotil
aoadicionaritensaumalistaordenada.Noestdisponvelemtempodedesign.Leiaseapenascom
tempodeexecuo.
TopItemID ContmoItemIDdoitemqueaparecenotopodalista.Nodisponvel
emtempodedesign.Somenteleituraemtempodeexecuo.
AddListItem AdicionaumitemparaumalistacomTipoDeOrigemDaLinha0nenhumou1valor
IItemIDToIndex RetornaondicedeumitemnalistaquandovocsabeoseuitemID
RemoveListItem RemoveumitemdeumalistacomTipoDeOrigemDaLinha0nenhumou1valor

Gotcha!AdicionarItem
Aajudaonlineafirmaqueasintaxedestecomando Control.AddItem(CITEM[,
nndice][,nColumn]).Elecontinuaadizerquequandovocespecificaronndiceopcionale
parmetrosnColumn,onovoitemadicionadoaessalinhaecolunanocontrole.Sevocs
especificarumalinhaquejexiste,onovoiteminseridonessalinhaeosdemaisitens
somovidosporumalinha.Parecebom!Infelizmente,elenofuncionabemassim.
OAddItemmtodorealmenteadicionaumalinhainteiraparaalista.Sealistatemvriascolunas
evocusarestasintaxeparaadicionaritensacadacoluna,oresultadonooquevocesperaria.
AousaroAddItemmtodoparapreencherumacombinaooulista,adicioneonovoitemparaoprimeiro
colunadecadalinhautilizandoasintaxe Control.AddItem('MyNewValue').atribuirvaloresa
ascolunasrestantesnessalinhausandoasintaxe Control.List[Control.NewIndex,
nColumn]='MyOtherNewValue'.OAddListItemmtodo,noentanto,funcionacomo
anunciado.EsteGotcha!claramenteilustradonaListAndListItemforma,includocomo
cdigodeexemploparaestecaptulo.
Captulo5:ComboseListas 129

Quandoqueoseventosdefogo?
Arespostaparaisso,comodecostume,"depende".Oseventosdispararumpoucodiferentedependendo
oestilodacaixadecombinao.Aordememqueelestambmdisparardependeseousurio
navegareselecionaritenscomomouseoucomoteclado.umbruta
eufemismoparadizeracompreensodomodelodeeventoimportantequandoseestaprogramarem
umambienteorientadoaobjeto.Istoabsolutamentecrticoaocriarclassesreutilizveis,
especialmenteasclassescomplexas,comocaixasdecombinaoelista.
Comoesperado,osprimeiroseventosquedisparamquandoocontroleobtmfocosoQuandoeGotFocus.
Istoverdadeparacaixasdecombinaodeambososestilos,bemcomocaixasdelistagem.Eesseseventosocorrem
encomendarsevocguiaparaocontroleoucliquesobreelecomomouse.Depoispequenaparticularidade
nesta
sobreacombinaodropdownqueoprximoeventoaofogoCombo.Text1.GotFocus!Text1
noacessvelparaodesenvolvedor.VisualFoxProrespondeaqualquertentativadeacesslonocdigocom
"Membrodesconhecido:TEXT1".Assumimosquetext1ummembroprotegidodoVisualFoxProde
classebasedecombinaoquandoestilodefinidopara0combinaosuspensa.
Aseguintelistacontmoseventosquevocvaisermuitasvezespreocupadoscomquando
lidarcomcaixasdecombinaoelista.denenhumamaneiraumalistaexaustiva,mastodosos
eventossignificativosestol.Porexemplo,oseventosMouseDowneMouseUpfogoantesda
doobjetodeeventoClick.Porrazesdesimplicidadeeclareza,oseventosdomouseestoomitidos.
130 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela5.3caixadelistagemdecombinaoeseqnciadeeventos

Aao Suspenso listasuspensa ListBox


Combo
Percorreralistausandoobaixo Noaplicvel PremirATecla(24,0) PremirATecla(24,0)
arrow(semdeixarcaira InteractiveChange InteractiveChange
listadecombinaoprimeiro) Clique Clique
Vlido Quando
Quando
Useomouseparasoltaralista Suspenso Suspenso Noaplicvel
UseALT+DNARROWparasoltara PremirATecla(160,4) PremirATecla(160,4 Noaplicvel
Lista Suspenso )
Suspenso
Percorreralistacaiuparabaixo PremirATecla(24,0) PremirATecla(24,0) PremirATecla(24,0)
utilizandoasetaparabaixo InteractiveChange InteractiveChange InteractiveChange
Clique
Quando
Selecioneumitemnalistausandoo InteractiveChange InteractiveChange InteractiveChange
rato Clique Clique Clique
Vlido Vlido Quando
Quando Quando
Selecioneumitemnalista, PremirATecla(13,0) PremirATecla(13,0) PremirATecla(13,0)
pressionandoatecla<ENTER> Clique Clique FazerDuploClique
Vlido Vlido Vlido
Sairdocontrolo,clicandoem Vlido LostFocus LostFocus
emoutroslugarescomomouse LostFocus
Text1.LostFocus
Sairdocontroleusandoo<TAB> PremirATecla(9,0) PremirATecla(9,0) PremirATecla(9,0)
chave Vlido LostFocus LostFocus
LostFocus
Text1.LostFocus

interessantenotarqueaValideventoquenodisparaquandoocontroleperdeofocopara
oualistasuspensaoucaixadelistagem.Umadasconsequnciasdestecomportamentoquequalquercdigo
chamadoapartirdaValidmtodonoirobterexecutadoquandoousuriosimplesmentetablaturaatravsdeum
Listasuspensaouumacaixadelistagem.Emnossaopinio,issoumacoisaboa.Issosignificaquepodemoscolocar
cdigoqueatualizafontesdedadossubjacentesemmtodoschamadosapartirdaValidmtododestes
controlesenosepreocuparcomasujarosbuffersseousurionomudounada.
Tambmimportantenotarque,paraComboBoxes,osvlidoseventoacionadosemprequeousurio
selecionaumitemdalista.(Noentanto,seousurioselecionaumitemnalistaclicandonele
comomouse,oAoeventotambmdispara.)PoroutroladoparaListBoxes,aValidnicoevento
acionadoquandoousurioselecionaumitempressionandoa ENTERchaveouclicandoduasvezessobreele.Isto
interessantenotarqueaseleodeumitemcomo ENTERchavetambmdisparaodblClickevento.
OutraanomaliadignodenotaqueoClickeventodosincndiosListBoxdeformainconsistente
dependendodequalchaveusadaparanavegarnalista!Quandoousuriopressionaa setaparacimae
parabaixosetachaves,osClickeventoacionado.Quandoa pginaparacimae pginaparabaixoteclasso
no.
usadas,ele

Captulo5:ComboseListas 131

Comofaoparavincularminhascombinaoecaixasdelistagem?
Obviamente,vocvincularsuascaixasdecombinaoelista,definindoaorigemdocontrolepropriedadeparao
nomedeumcampoemumatabela,cursorouvistaouparaumapropriedadedeformulrio.Umapegadinha!aterem
quevocspodevincularessescontrolesparacaractere,numrico,oufontesdedadosnulos.Sevoctentar
conta
vincularumacombinaooucaixadelistaparaumcampodedataouDateTime,VisualFoxProirreclamareexibio
oseguinteerroemtempodeexecuo:

Errocom<ComboName>Value:Tipodedadosincompatvel.
objetoDesvinculao<ComboName>

SevocdevevincularumacombinaooucaixadelistaparaumadataouumcampoDateTime,vocvaiterque
umpoucodeartifcios.Nestecaso,vocnopodeusarRowSourceTypesde2Alias
recorrera ou6Fields.Vocpode,
porexemplo,definiraTipoDeOrigemDaLinhaDeclaraode3SQLeusarumainstruoSQLsemelhanteao
istocomoaOrigemDaLinha:

DTOCSELECIONAR(DateField)ASDisplayDate,yada,nada,blFROMMyTable
ORDERBYMyTable.DateFieldINTOCURSORMyCursor
DeixeaorigemdocontroleembrancoeadicionarestecdigoaoseuValidmtodoparaatualizaradata
camponatabelasubjacente:

SUBSTITUIRDateFieldCOMCTOD(This.Value)INMyTable

Voctambmvaiprecisarparaescreveralgumcdigoparaatualizarmanualmenteocontroledovalordasua
ControlSourceparaimitarocomportamentodeumcontroleacopladoquandovocAtualizarlo.Estecdigono
combinaooulistadecaixadeActualizarmtodofazotruque:

This.Value=DTOC(MyTable.DateField)

Outrapegadinha!quepodemmorderlheocorrequandoaorigemdocontroledesuacaixadecombinao
refereseaumvalornumricoquecontmnmerosnegativos.Estepareceserumproblemaque
socorrequandoaTipoDeOrigemDaLinhadocontroleInstruo3SQLepoderealmenteserum
bugnoVisualFoxPro.Oresultadoquenadaestapresentadanapartedetextoda
decontroloparatodososvaloresnegativos.Noentanto,mesmoqueodocontroloDisplayValueestembranco,oseu
Valorestcorreto.AsoluofcildeusarumTipoDeOrigemDaLinha,diferentede3SQL
Declarao,quandoocontroleestvinculadoaumafontededadosquepodecontervaloresnegativos.No
comosehouverumafaltadealternativas.

Ento,oqueBoundToeBoundColumnutilizado?
Essaspropriedadesdeterminamcomoocontrolerecebeoseuvalor.Ovalordeumacaixadecombinaooulista
tomadasapartirdacolunadesualistainternaqueespecificadopeloseuBoundColumn.Acaixadecombinaode
DisplayValue,ovalorqueexibidonapartedetextodocontrole,semprevem
umacoluna!Oseuvalor,poroutrolado,podeserfeitaapartirdequalquercolunadesualistainterna.
Istosignificaquevocpodeexibirtextosignificativo,comoadescriodeumatabeladepesquisa,na

132 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

mesmotempo,ocontrolerecebeoseuvalorapartirdachaveassociada.Vocnotemsequerparaexibir
estachaveassociadanalistaparateracessoaele.
Porexemplo,suponhaqueousuriodeveatribuirumtipodecontatoespecficoparacadacontatoquandoele
inserido.Otipodecontatoadequadopodeserselecionadoapartirdeumalistasuspensacomoseu
TipoDeOrigemDaLinhadefinidapara6Fields,asuaOrigemDaLinhadefinidapara" ContactType.CT_Type,CT_Key",
onde
CT_Type adescrioe CT_KeyasuachaveassociadanaContactTypemesa.Paraconfigurar
ocontrole,definaprimeirodalistasuspensaColumnCounta2eseusColumnWidthsa150,0.
Emseguida,definaoBoundColumna2paraatualizarocampoacopladonaContatostabeladachave
valor,emvezdadescrio.
AdefiniodeBoundToespecificaseapropriedadevalordeumacaixadecombinaooulista
determinadapelasualistaouasuaListIndexpropriedade.AdefiniodeBoundTosimportaquandoo
controleestvinculadoaumafontededadosnumricos.Seaorigemdocontroledacaixadecombinaoouumalistarefere
comdadosnumricos,acriaodocontroleBoundTopropriedadecomotrueinformaVisualFoxProparaatualizar
se
aorigemdocontroleutilizandoosdadosdacolunadependentedalistainternadocontrole.Deixando
BoundTodefinidacomofalsaaquifazcomqueaorigemdocontroleparaseratualizadocomocontroleListIndex,
isto,onmerodalinhadoitematualmenteselecionado.
Amaneiramaisfcilparailustrarcomoissofuncionausandoumpoucodecdigoquesimulacomoo
configuraodoBoundTopropriedadeafetaamaneiraemqueocontroledovalordapropriedade
Atualizada:

Comisso
IF.BoundTo
.Value=VAL(.List[.ListIndex,.BoundColumn])
OUTRO
.Value=.ListIndex
FIMSE
FIMSE

Comofaoparaconsultarositensemmeuscombinaoecaixasdelistagem?
Comodiscutidoanteriormente,vocpodeusaralistaouListItemcoleoparasereferiraositens
suacaixadecombinaooulista.Agrandevantagemdeusaressascoleesparaacessarositensna
docontroleOrigemDaLinhaquenonecessriosabernadasobreissoOrigemDaLinha.Voc
podeusarListIndexouListItemIdpropriedadeparasereferirlinhaselecionadanomomento.Senada
nalistaselecionado,ocontroleListIndexpropriedade0esuaListItemIdpropriedade1.assim
naValidmtododecaixadecombinaoouoLostFocusmtododecaixadelista,vocpodeverificar
paraverseousurioselecionadoalgocomoisto:

Comisso
IF.ListIndex=0 &&Voctambmpodeusar.ListItemID=1aqui
MESSAGEBOX('Vocdeveselecionarumitemdalista',16,
"Porfavor,faaumaseleo')
Seforinferior(.BaseClass)='combobox'
RETURN0 &&Seestecdigoestnovlidadeumacaixadecombinao
OUTRO
NODEFAULT &&SeestecdigoestnoLostFocusdeumListBox
FIMSE
FIMSE
ENDWITH

Captulo5:ComboseListas 133

Htambmvriasmaneirasdesereferiraovalordeumacaixadecombinaooulista.Omaissimplesdos
todoseles Control.Value.Quandonadaforselecionado,ovalordocontrolevazio.Isto
algoaserconsideradoseaRowSourceparaaslicenasdecontroledevaloresvazios.Issosignifica
vocnopodedeterminarseousuriofezumaseleoapenasatravsdaverificaodeumvazio
propriedadedevalor.
PorqueaslistaeListItemcoleessoarrays,vocpoderesolvloscomofaria
qualqueroutramatriz.(Noentanto,emboravocpossaabordarestascolecescomomatrizes,vocnopode
realmentemanipullosdiretamenteusandoasfunesdematrizdoVisualFoxPronativostaiscomo
ASCAN(), ADEL()ou ALEN().)
ParaacessaroitemselecionadonalistainternadocontrolequandooseuListIndexmaiordoque
zero,vocpodeusar:

Control.List[Control.ListIndex,Control.BoundColumn]

enquantoissofazexatamenteamesmacoisaquandoasuaListItemIdno1:

Control.ListItem[Control.ListItemID,Control.BoundColumn]

Voctambmpodeacessarositensnasoutrascolunasdalinhaselecionadadocontrolepor
referindoseaControl.List[Control.ListIndex,1],Control.List[Control.ListIndex2,],eassimpordiantetodos
ocaminhoateincluindoControl.List[Control.ListIndex,Control.ColumnCount].
Lembreseque,aousarocontroledelistaeListItemcoleesdestaforma,todos
ositensnalistainternadocontrolesoarmazenadoscomocadeiasdecaracteres.SeocontroleOrigemDaLinha
contmnumrico,dedataoudedataehoravalores,essesitensvosempreserrepresentadointernamentecomo
cadeiasdecaracteres.Istosignificaquesevocdesejarealizaralgumasatualizaes"nosbastidores"
usandoositensdalinhaatualmenteselecionadadalista,vocvaiprecisarparaconverteressesitenspara
osdadosapropriadosdigitapelaprimeiravez.Casocontrrio,VisualFoxProirreclamar,dandolheumtipodedados
errodeincompatibilidade.
CaixasdelistagemcomMultiSelectdefinidocomoverdadeirosecomportamumpoucodiferente.SuaListIndexe
ListItemIdpropriedadesapontamparaaltimalinhanocontrolequefoiselecionado.Fazeralgumacoisa
comtodosositensselecionadosdocontrole,necessrioparapercorrerasualistainternaeverificao
oSelectedpropriedadedecadaitemdaseguinteforma:

COMThisform.LstMultiSelect
PARAlnCnt=1a.ListCount
IF.selected[lnCnt]
***Oitemselecionado,tomarasmedidasadequadas
OUTRO
***Noselecionado,fazeroutracoisasenecessrio
FIMSE
ENDFOR
ENDWITH

QualadiferenaentreDisplayValueevalor?
caixasdecombinaosocontrolosparticularmentepoderososporqueelespermitemexibirdescritivo
textodeumatabeladepesquisa,enquantoaligaodecontroleparaoseuvalorchaveassociadas.Issopossvel
134 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

sporqueacaixadecombinaotemessasduaspropriedades.Compreenderopapeldecadaumdeles
peaspodeserconfuso,paradizeromnimo.
DisplayValueotextodescritivoqueexibidonapartedecaixadetextodocontrole.
Istooquevocvquandoacaixadecombinaoest"fechado".AcombinaodeDisplayValuesempre
vemdaprimeiracolunadasuaOrigemDaLinha.Poroutrolado,acombinaodevalorvem
apartirdequalquercolunaespecificadocomoseuColunaDependente.SeoColunaDependentedacombinao
caixaestcolunaum,oseuvaloreDisplayValuesoosmesmosquandoousurioescolheumitem
alista.QuandoocontroleBoundColumnnocolunaum,essasduaspropriedadesnooso
mesmo.VerTabela5.4abaixoasdiferenasentreestasduaspropriedadesemdiferentes
situaes.

Tabela5.4caixadelistagemdecombinaoeseqnciadeeventos

Limite Aao DisplayValue Valor


Coluna
1 Selecioneumitemnalista Coluna1doselecionado Coluna1dalinhaselecionada
linha
1 itemTiponoestnalista textodigitado Vazio
N#1 Selecioneumitemnalista Coluna1doselecionado Colunandalinhaselecionada
linha
N#1 itemTiponoestnalista textodigitado Vazio

QualadiferenaentreRowSourceTypes"Alias"e
"Campos"?
AdiferenabsicaqueRowSourceType"2Alias"permitequeoRowSourcepropriedadepara
conterapenasumnomedeAlias.Ocontroloencheonmerodecolunasquetemdisponvel(definidopela
oColumnCountpropriedade)atravsdaleituradosdadosdoscamposnosaliasespecificadono
ordemnaqualsodefinidas.Poder,noentanto,especificarumalistadecamposquesoparaserusadas
mesmoquandoaTipoDeOrigemDaLinhaestdefinidacomo"2Alias".Nestecasonohnenhumadiferenaprtica
entreoscamposeasAliasconfiguraes.
AousarRowSourceType"6Fields"apropriedadeOrigemDaLinhadeveserpreenchidousando
oseguinteformato:

<Alias
Nome>.<Primeirocampo>,<segundocampo>,.......<ltimocampo>

AousarqualquerRowSourceType"2Alias"ou"6Fields,"vocaindapodeacessarqualquerdo
camposnafontededadossubjacentemesmoqueelesnoestejamespecificamenteincludosno
OrigemDaLinha.Tambmvaleapenalembrarquesemprequefeitaumaseleo,oponteirodoregistro
nafontededadossubjacenteautomaticamentetransferidaparaoregistroadequado.Noentanto,senenhum
nmerovlido,oponteirodoregistrodeixadonoltimoregistronafontededadosno,como
vocpoderiaesperar,a EOF().

Captulo5:ComboseListas 135

Bytheway,quandoseutilizaTipoDeOrigemDaLinhade"3SQL",selecionesempre
INTOumcursordestinoaoespecificaroOrigemDaLinha.Nafaltade
especificarumcursoralvoresultaremumajaneladepesquisaqueestsendoexibido!
Ocomportamentodocursoromesmoqueaousarumatabelaouexibiodiretamentetudo
camposnocursorestodisponveis,eselecionarumitemnalistamoveoregistro
ponteironocursor.

Comopossofazermeuscombinaoecaixasdelistagemapontam
parauma
itememparticular?
Quandoestessoobrigadoscontroles,elesautomaticamenteexibiraseleoespecificadaspeloseu
ControlSourcesparaquevocnoprecisafazernada.Maseseocontrolenoestvinculadoou
vocdesejaexibiralgumvalorpadroaoadicionarumnovodisco?Comodecostume,hmais
deumamaneiradeesfolarumfox.Talvezamaneiramaisfcildeconseguirisso:

Thisform.MyList.ListIndex=1

Estadeclarao,quernoformulrioInitmtodoouimediatamentedepoisdeadicionarumnovorecorde,
selecionaoprimeiroitemnalista.Voctambmpodeinicializarumacombinaooucaixadelistagem,definindo
valor.Noentanto,quandoainicializaocomboselistasquesoobrigadosadadosembuffer,oatode
diretamenteasua
issoirsujarasbuffers.Istosignificaquesevoctemumarotinaqueverificasehalteraesem
oregistroatualusando GETFLDSTATE(),afunoirdetectara"mudana"naatual
registromesmoqueousurionotenhatocadoumanicatecla.Paraevitarefeitossecundriosindesejveis,tais
comoousurioqueestsendosolicitadoasalvaralteraesquandoeleachaquenofezqualquer,uso
SETFLDSTATE()pararedefinirtodososcamposafectadosdepoisdeinicializarovalordasuacombinaoligadoou
caixadelista.
Umacoisaquevainoinicializarovalordeumacaixadecombinaooulistadefiniroselecionado
propriedadedeumdosseusitensdelistacomotruenoInitmtododeumformulrio.Adeclarao:

Thisform.MyList.Selected[1]

noformulrioInitmtodo,senoselecionarumitememumacaixadecombinaooulista.Essemesmo
declaraonoformulrioActivatemtodo,noentanto,atingiroresultadodesejadoporissosuspeitamos
ofracassodadeclarao,quandoutilizadosnoformulrioInitmtodopoderealmenteserumbug.

CombosQuickfill(Exemplo:CH05.VCX::cboQFill)
UmexemplodemetodologiaQuickfill(eumaexplicaomaisdetalhadadoqueapenas
"Quickfill")foiapresentadonoCaptulo4nabuscaTextBoxincremental.este
metodologiaaindamaisfcildeimplementarparaaclasseComboBox.caixasdecombinaoQuickfilldar
suasformasumolharpolidoeprofissional.Elestambmfazematarefadeselecionarumitemem
alistamuitomaisfcilparaousuriofinal.Bastadigitaraletra'S'napartedetextodacombinao,e
'Samuel'exibida.Emseguidadigitealetra'm'eosDisplayValuemudapara'Smith'.Muito
coisaslegais!

136 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

NossaQuickfillcombinaopodeserusadanoimportaoqueoOrigemDaLinhadacaixadecombinao
passaaser,porqueeleoperaemlistainternadocontrole.Porestarazo,deveserapenas
usadoparacontrolesquemostram,nomximo,algumasdezenasdeitens.Senecessitardestafuncionalidade,mas
precisaexibircentenasdeitens,nsencaminhloparaoartigodeTamarGranorsobreoassuntona
Setembro1998emissodeFoxProAdvisor.
AcombinaoQuickfilltemumapropriedadepersonalizadachamadacOldExact.Porquensestamosolhando
paraoprimeiroitemquecorrespondeaoquefoidigitadonamedida,queremos SETOFFexato.Em
docontroleGotFocusmtodo,ovalororiginaldo SET("exactido")salvoporissopodeser
restauradaquandoocontroleperdeofoco.Quando SET("exactido")='desligado',nohnecessidadede
usaraesquerda()funoparacompararoqueousuriodigitouatagoraparaencontrarovalormaisprximona
alista.Istomelhoraodesempenhodabusca.
Assimcomonacaixadetextodepesquisaincrementaldescritoanteriormente,oHandleKeymtodo
invocadaapartirdocontroleInteractiveChangemtodoapsascombinaesdeteclasjforam
processado.Naverdade,noexisteumcdigodetodoemdacaixadecombinaoKeyPressmtodo.o
InteractiveChangemtodocontmsomenteocdigonecessrioparadeterminarseachavedeveser
tratadas:

IFThis.SelStart>0
***Handlecarcterdeimpresso,backspaceeexcluirchaves
IF(LASTKEY()>31eLASTKEY()<128)ou(LASTKEY()=7)
This.HandleKey()
FIMSE
FIMSE

AmaiorpartedotrabalhorealizadonoHandleKeymtodo.Elepercorreo
listainternadecombinaoparaencontrarumacorrespondnciaparaoqueousuriodigitounamedidaemque:

LOCALlcSofar,lnSelStart,lnSelLength,lnRow

Comisso
***TecladeretrocessoHandle
IFLASTKEY()=127
.SelStart=.SelStart1
FIMSE

***Salveopontodeinseroeextrairoqueousuriodigitouatagora
lnSelStart=.SelStart
lcSofar=LEFT(.DisplayValue,lnSelStart)

***Encontreumjogonaprimeiracolunadalistainternadacombinao
PARAlnRow=1a.ListCount
IFUPPER(.List[lnRow,1])=UPPER(lcSoFar)
.ListIndex=LnRow
SADA
FIMSE
ENDFOR

***Destaqueapartedovalorapsopontodeinsero
.SelStart=LnSelStart
lnSelLength=LEN(ALLTRIM(.DisplayValue))lnSelStart
IFlnSelLength>0
.SelLength=LnSelLength

Captulo5:ComboseListas 137

FIMSE
ENDWITH

IssotudooquenecessrioparaumcomboQuickfillquefuncionacomqualquerTipoDeOrigemDaLinha.Apenas
soltloemumformulrioedefinasuaRowSourceType,OrigemDaLinhaeorigemdocontrole(separaserum
controledelimite).Nadapoderiasermaisfcil.AformaQuickfill.scx,fornecidacomaamostra
cdigoparaestecaptulo,ilustraousodestaclassecomvriosdiferentesRowSourceTypes.

Comofaoparaadicionarnovositensaosmeuscombinaoecaixas
delistagem?
(Exemplo:CH05.VCX::cboAddNewelstAddNew)

Figura5.1Adicionarnovositenseeditaritensexistentesemcaixasdecombinaoelista

Adicionandoumnovoitemparaumacaixadecombinaocomestilo=0DropDownComboumabonita
processosimples,porquedocontrolevlidoseventoacionadosemprequeumaseleofeita
apartirdalistae,novamente,antesqueeleperdeofoco.Quandoumutilizadordactilografoualgoquenono
listaatual,docontroleDisplayValuepropriedadeirarmazenarosdadosrecmintroduzidos,masoValor
propriedadeestarvazia.UmcdigopouconaValidmtododecontrolepermitequevocdetermine
seousurioselecionouumitemnalistaoudigitarumvalornoestnalista.Porexemplo,a
seguintecdigopodeserusado:

SENO(VAZIO(This.DisplayValue))EVAZIO(This.Value)
***Ousuriodigitouemumvalornoestnalista

Noentanto,estenoserconfivelseoOrigemDaLinhapermitevaloresvaziosassimumamelhor
soluousarqualquerum:
SENO(VAZIO(This.DisplayValue))EThis.ListIndex=0
138 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OU

SeNO(VAZIO(This.DisplayValue))EThis.ListItemId=1

Vocdeve,emseguida,tomarmedidasparaadicionaronovoitemparaocontroleOrigemDaLinha.Ocdigousado
aofazerissovaiserinstnciaespecfica,dependendodecomoocontrolopreenchida.Seacombinaode
RowSourceType"0None"ou"1Value,"usaroAddItemouAddListItemmtodoparaadicionaro
novovalorlista.SeoTipoDeOrigemDaLinha"2Alias","Declaraode3SQL"ou"6Fields",o
novoitemdeveseradicionadatabelasubjacenteecaixadecombinaooulistaconsultadapararefrescar
sualistainterna.ParaRowSourceType"5Array,"adicionaroitemparaamatrizerepetiraconsultao
aocontrole.
EmborasejasimplesosuficienteparaadicionarumnovoitemaumDropDownCombo,estesimplista
soluopodenoseradequada.Seonicorequisitoadicionarumanovadescrio,juntamentecomasua
chaveprimriaparaumatabeladepesquisa,ametodologiadiscutidaacimaatatarefa.Grandepartedo
tempo,noentanto,umatabeladeconsultacontmmaisdeduascolunas.(Porexemplo,atabeladepesquisa
fornecidocomocdigodeexemploparaestecaptulotemumacolunaparaumcdigodefinidopelousurio.)
Camposadicionaispodemtambmprecisamserpreenchidosquandoumnovoitemadicionadocaixadecombinao.
Devemosconsiderartambmofatodequenohnenhumamaneirarpidaefcildeadicionarnovositensaum
ListBox.ConsiderandooquosemelhantesasclassesComboBoxeListBoxso,pensamosque
apropriadoqueelescompartilhamumainterfacecomumparaaadiodenovositens.Seosusuriosfinaisadicionarnovos
itensdamesmamaneira,elestmumacoisaalembrar,emvezdedois.ocboAddNew
elstAddNewclassesfornecemessafuncionalidadeatravsdeummenudeatalhoinvocadopordireito
clicandonocontrole.Estemenudeatalhotambmfornecefuncionalidadedeedio.Maisfrequentementedoqueno,se
umitememumacombinaooulistaestmalescrito,ousuriovaiperceberissoquandoeleestselecionandoumitem
apartirdalista.muitomaisconvenienteparacorrigiroerro,nesteponto,deterdeusarum
formademanutenoseparado.
CriamoscboAddNewcomoumasubclassedecboQuickfillparaalcanarumusuriomaisconsistente
interface.TodasasnossasclassesdecaixapersonalizadadecombinaoherdardenossaclasseQuickfillcombinao,ento
secomportamdeummodosemelhante.Estetipodeconsistnciaajudaafazerumaaplicaosentirintuitivo
tudo
usuriosfinais.
O"AdicionarNovo"combinaoelistaasclassesdecaixatemtrspropriedadesadicionais.o
cForm2Callpropriedadecontmonomedoformulriodemanutenoparainstanciarquandoousurio
queradicionaroueditarumitem.AsdefiniesdoslAllowNewelAllowEditpropriedades
determinarsenovositenspodemseradicionadosouitensexistenteseditado.Elesso,porpadro,definidocomo
verdade,porqueoobjetivodesteexercciopermitirquenovositensaseremadicionadoseitensatuaispara
sereditado.Noentanto,aoprojetaraclassefizemosonossomelhorparaconstruirnomximodeflexibilidade,
demodoqueessaspropriedadespodemserdefinidasparasubstituiressecomportamentononveldeinstncia.
OcdigoquefazamaioriadotrabalhoresidenocostumeShowMenumtodoe
chamadoapartirdoRightClickmtododeambos.Nesteexemplo,acombinaodeColunaDependente
contmachaveprimriaassociadacomosdadossubjacentes.Supesequeo
formulriodemanutenoirretornarachaveprimriadepoisqueadicionaumnovoitem(Sevocprecisardediferentes
funcionalidade,cdigoloemconformidade.):

LOCAISlnRetVal,loparameters
pnMenuChoicePRIVADO

Captulo5:ComboseListas 139

Comisso
***Noexibiromenusenopodemosadicionaroueditar
IF.lAllowNewOU.lAllowEdit
***Exibiromenudeatalho
pnMenuChoice=0
DOmnuCombo.mpr
IFpnMenuChoice>0
***Criaroobjetodeparmetroepreenchlo
loParameters=CREATEOBJECT('Line')
loParameters.AddProperty('cAction',IIF(pnMenuChoice=1,'Adicionar','EDIT'
))
loParameters.AddProperty('uValue',.Value)
***Adicionequaisquerparmetrosopcionais,senecessrio
.AddOptionalParameters(@loParameters)
***Agorachamaraformademanuteno
DOFORM(.cForm2Call)COMloParametersPARAlnRetVal
lnValue=IIF(lnRetVal=0,This.Value,lnRetVal)
.Requery()
.Value=LnValue
FIMSE
FIMSE
ENDWITH

Asespecificidadesdoformulriodemanuteno,obviamente,dependemdatabelasendoatualizada.
Noentanto,qualquerformademanutenochamadoapartirdacaixadecombinaooulistadeShowMenumtodo
precisaaceitaroobjetoparmetropassadoparaasuaInitmtodoeusarasinformaespassadaspara
fazeroseutrabalho.Eletambmterdevoltarparaachaveprimrianecessriadepoisqueelefoiadicionadocomsucesso
umanovaentrada.Emboraoscamposespecficosparaseractualizadoporesteprocessopodevariardependendodo
tabelasendoatualizada,oprocessoemsibastantegenrico.Todososformulriosusadosparaadicionareeditar
entradassobaseadasnofrmAddOrEditclassedeformulriofornecidocomocdigodeexemploparaeste
captulo.Estaclasseilustraclaramentecomooprocessofunciona,evocpodeconferir
Itineraries.scxparavercomoestaformademanutenochamadopelolstAddNewecboAddNew
objectos.

Comofiltrarositensexibidosemumasegundacombinaoou
caixadelistagemcombasenaseleofeitanaprimeira?(Exemplo:
FilterList.SCX)
Istomuitomaisfcildoquevocpodepensar.FilterList.scx,nocdigodeexemploparaestecaptulono,
filtrasomenteumacaixadelistagem,dependendodoqueforselecionadoemumacaixadecombinao,eletambmfiltra
ComboBoxdependendodoqueforselecionadonaOptionGroup.
o

140 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura5.2dinamicamentefiltrarocontedodeumacaixadecombinaooulista

NossopreferidoRowSourceTypeparaoscontrolosfiltrados"Declaraode3SQL"porquefaz
configuraradependnciafcil.Nsapenasespecificar ONDESomeField=(
Thisform.MasterControl.Value)naONDEclusuladocontroledependentede
OrigemDaLinha.Ento,cadavezqueocontroledependenteconsultada,elepreenchidocomo
valoresapropriados.
Hdoispequenossenesaqui.Emprimeirolugar,seusarmosaexpressoThisFormnadependentes
docontroleOrigemDaLinhadiretamentenafolhadepropriedades,VisualFoxProchutaumaconfusoemtempodeexecuo.
diznosqueThisFormspodeserusadodentrodeummtodo.Emsegundolugar,emborapudssemosdefiniro
isto
docontroledependenteOrigemDaLinhanasuaInitmtodo,issotambmpoderesultaremalgumavez
desagradveissurpresasdetempodeexecuo.Seocontroledependenteinstanciadoantesdocontrolemestre,
VisualFoxProirreclamarqueThisForm.MasterControlnoumobjeto.
OtruqueparafazerestetrabalhocorretamentecolocarocdigodeinicializaodosRowSourcesdo
controlesdependentesnolugarcerto.Desdeoscontrolesdoformulriosoinstanciadoantesdo
doformulrioInitincndios,ummtodopersonalizadochamadoapartirdoformulrioInitmtodoumbomlugarpara
tipodecdigo.EsteexatamenteoquetemosfeitonadonossoformulriodeexemploSetFormmtodo:
colocaresse

lcRowSourceLOCAL

***SelecioneapenasosartigosquetmumCat_Noigualoposelecionada
***Nogrupodeopo

Todososcontrolesnoformulriodeexemplosoobrigadosaformarpropriedades.OOptionGroup
ligadoaThisform.nType.Comoessapropriedadeinicializadacom1nafolhadepropriedades,todoo
controlesdeconterumvalorquandooformulrioexibidopelaprimeiravez:

lcRowSource='SELECTCat_Desc,Cat_Key,UPPER(Categories.Cat_Desc)AS'
lcRowSource=lcRowSource+'UpperDescapartirdecategorias'
lcRowSOurce=lcRowSOurce+'WHERECategories.Cat_No=(Thisform.nType)'
lcRowSource=lcRowSource+'INTOcsrCategoriesCURSORORDENARUpperDesc'

***Agoraconfiguraraspropriedadesdacombinao

Captulo5:ComboseListas 141

COMThisform.cboCategories
.RowSourceType=3
.RowSource=LcRowSource
***Noseesqueaderepovoarlistainternadocontrole
.Requery()
***Inializeloparaexibiroprimeiroitem
.ListIndex=1
ENDWITH

Agoraquetemosinicializadocaixadecategoriasdecombinao,podemosconfigurarainstruoSQL
parausarcomoaOrigemDaLinhaparaacaixadelistadedetalhes.Queremosselecionarapenasositensque
Itemselecionadonacaixadecombinao:
correspondema

lcRowSource='SELECTDet_Desc,Det_Key,UPPER(Details.Det_Desc)AS'
lcRowSource=lcRowSOurce+'UpperDescdosdetalhes'
lcRowSource=lcRowSource+'WHEREDetails.De_Cat_Key=(Thisform.nCategory)
'
lcRowSOurce=lcRowSOurce+'INTOCURSORcsrDetailsORDERBYUpperDesc'

***Agoraconfigurarpropriedadesdacaixadelista
COMThisform.lstDetails
.RowSourceType=3
.RowSource=LcRowSource
***Noseesqueaderepovoarlistainternadocontrole
.Requery()
***Inicializarloparaexibiroprimeiroitem
.ListIndex=1
ENDWITH

Estecdigo,noVlidomtododoOptionGroup,actualizaocontedodo
ComboBoxquandoumanovaseleofeita.Eletambmatualizaocontedodacaixadelistagemparaquetodosos
trscontrolesficaremsincronia:

COMThisform
.cboCategories.Requery()
.cboCategories.ListIndex=1
.lstDetails.Requery()
.lstDetails.ListIndex=1
ENDWITH

Finalmente,estecdigonacaixadecombinaodaValidmtodoatualizaocontedodacaixadelistagem
cadavezqueumaseleofeitaapartirdacombinao.Estecdigoirfuncionartobemsecolocadono
DoComboBoxInteractiveChangemtodo.Aescolhadomtodo,nestecaso,umaquestode
prefernciapessoal:

COMThisform
.lstDetails.Requery()
.lstDetails.ListIndex=1
ENDWITH
142 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Umapalavrasobretabelasdepesquisa
inevitvelqueumadiscussosobrecaixasdecombinaoelistadevevoltarseparaotemada
tabelasdepesquisa.Afinal,comboselistassomaiscomumenteusadoparapermitirqueousurioselecione
Entreumconjuntodevaloresmantidosdetaltabela.Deummodogeral,otextodescritivodo
tabeladepesquisaexibidoemumcontrolequevinculadoaovalordechaveestrangeiraemumarquivodedados.Mas
qualamelhorformadeestruturarumatabeladepesquisa?Devehaverum,mesaparatodososfinsdepesquisa?
Oudeveriaaaplicaousarmuitastabelasdepesquisaespecializados?Maisumavez,aresposta"It
Depende."Vocprecisaescolherasoluomaisadequadaparasuaaplicaoparticular.De
cursoparatomarumadecisoinformada,queajudaaconhecerasvantagensedesvantagensde
cadaabordagem.Ento,vamosl...
Hduasgrandesvantagensemusarumnico,tabeladepesquisaconsolidada.Oprimeiro
que,usandoumanicaestrutura,vocpodecriargenricos,combinaoreutilizveiselistadepesquisacaixade
classesquesocapazesdepreencherse.Issominimizaaquantidadedecdigonecessrioem
onveldeexemplo,emenoscdigosignificamenosdepurao.Asegundavantagemdestaabordagem
quesuaaplicaorequerapenasumformulriodeentradadedadosparamanterasvriaspesquisas.
Umaformademanutenodepesquisadeduaspginasrealizaessatarefamuitobem.Outilizadorpodeseleccionar
acategoriadepesquisadeumalistanaprimeirapgina.Asegundapgina,emseguida,exibeoapropriado
itensparaacategoriaselecionada.Umbotodeedionapginadoispodeentoserusadoparalanarummodal
formarparaeditaroitematual.Agrandedesvantagemdestaabordagemquetodasaspesquisas
partilhamumaestruturacomum.Istosignificaquesevoctemumacategoriadepesquisaqueexigemais
informaesparacadaitem,vocdevecriarumatabeladepesquisaespecialparaacategoriaou
adicionarcolunasextrasparaoseuquadroconsolidadoqueraramenteserusado.
Usandoumatabelaseparadaparacadatipodepesquisaemseuaplicativofornecemaisflexibilidade
doqueaabordagemanterior.Maiorflexibilidadetambmtrazmaiorsobrecarga.mais
difcilcriar,aulasdepesquisareutilizveisgenricos.Estasoluotambmrequerpesquisamltipla
formasdemanutenodatabela.
Nsusamosumacombinaodasduasabordagens.Atabeladepesquisa,paratodososfinsnicafuncionapara
itenssimplesquepossamserreutilizadosentreaplicativos.Nsusamostabelasseparadaspara
consultasespecializadasquesosusceptveisdeterumaestruturanica.Nossatabeladepesquisapadro
naverdade,duastabelas:umatabeladecabealhodepesquisacontendoascategoriasdepesquisaeumassociado
tabeladedetalhesdepesquisaquecontmositensparacadacategoria.

Tabela5.5EstruturadatabeladepesquisaHeader

NomedocampoTipodedados
Comprimentodocampo
propsito
Lh_Key nmerointeiro ChavePrimriaidentificarexclusivamenterecorde
Lh_Desc Personagem 30 LookupCategoriaDescrio
Lh_Default nmerointeiro Valorpadro(sehouver)parausarapartirLookup
detalhesTabela

Captulo5:ComboseListas 143
Tabela5.6OsdadoscontidosnatabeladepesquisaHeader

Lh_Key Lh_Desc Lh_Default


1 Tiposdecontacto 1
2 telefoneTipos 5
3 pases 10
4 Tiposdenegcios 23
5 relaes 63
6 cores

Tabela5.7EstruturadatabelaLookupdetalhesdo

Nomedocampo
TipodedadosComprimentodocampo
propsito
Ld_Lh_Key nmerointeiro chaveestrangeiradapesquisacabealhodatabela
Ld_Key nmerointeiro ChavePrimriaidentificarexclusivamenterecorde
Ld_Code Personagem 3 cdigodefinidopelousurio(sehouver)paraoitem
Ld_Desc Personagem 30 Lookupdescriodedetalhesdoitem

Tabela5.8listaparcialdedadoscontidosnatabelaLookupdetalhesdo

Ld_lh_key Ld_Key Ld_Code Ld_Desc


1 1 Cliente
1 2 prospecto
1 3 Concorrente
1 4 Pessoal
2 5 Casa
2 6 Onegcio
2 7 Fax
2 8 Celular
2 9 pager
3 10 EUA EstadosUnidos
3 11 ReinoUnido Unido
Reino
3 12 POSSO Canad
3 13 GER Alemanha

Comovocpodeverapartirdaslistas,bastantefcildeextrairdadosdetabeladedetalhesparaqualquer
categoria.Umavezquecadaitemnatabeladedetalhestemasuaprpriachavenica,noexisteambiguidademesmo
Seamesmadescriousadoemdiferentescategorias"."

Combosdepesquisagenricoselistas(exemplo:CH05.VCX::cboLookup
elstLookUp)
Genricos,combinaoreutilizveledecaixadelistaasclassesdepesquisapermitemquevocimplementaroseutodos
tabeladepesquisacommuitopoucoesforo.Devidoformacomoatabeladeconsultaestruturada,eleempresta
osfins

144 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

muitobemparaRowSourceType="Declaraode3SQL."Tudooquenecessrioumparpersonalizado
propriedadeseumpoucodecdigoparainicializarocontrole.
OcCursorNamepropriedadeusadaparaespecificarocursorquecontmoresultadodaSQL
selecionar.Issonecessrionocasodeexistiremvriasinstnciasdocontroleemumnicoformulrio.
CadainstnciarequerseuprpriocursorparaseguraroresultadodainstruoSQLnasuaOrigemDaLinha.
Seomesmonomeusadoemtodososcasos,ocursorsersubstitudocomocadacontrole
instancia.Vocvaiacabarcomtodososcontrolesreferindoseaversodocursorcriadopor
ocontroleinstanciadopassado.
Figura5.3genricosclassesdecaixadelistadepesquisadecombinaoeemao

OnHeaderKeypropriedadeusadaparalimitarocontedodalistadocontroleparaumnico
categorianatabeladepesquisaHeader.Contmovalordachaveprimriadodesejado
categoriaeusadoparaconstruiroONDEclusulaparaocontroleOrigemDaLinha.
Docontroledeconfiguraomtodo,invocadosobreinstanciao,preencheseusRowSourceutilizandoo
propriedadesacimaespecificado:

lcRowSourceLOCAL

***Certifiquesedequeodesenvolvedorconfiguraraspropriedadesnecessrias
ASSERTVAZIOMENSAGEM(This.cCursorName!)
'CCursorNamedeveconteronomedocursorresultadoparaoSQLSELECT!'
ASSERTVAZIOMENSAGEM(This.nHeaderKey!)
'NHeaderKeydeveconteroPKdeumitememLookupHeader.dbf!'

***ConfigurarOrigemDaLinhadocombinao
lcRowSource='SELECTld_Desc,ld_KeyDELookUpDetailWHERE'
lcRowSource=lcRowSource+'LookUpDetail.ld_lh_key=(This.nHeaderKey)'
lcRowSource=lcRowSource+'INTOCURSOR(This.cCursorName)'
lcRowSource=lcRowSource+'ORDERBYld_Desc'

Captulo5:ComboseListas 145

***Configuraraspropriedadesdacombinao
Comisso
.RowSourceType=3
.RowSource=LcRowSource
.ColumnWidths=ALLTRIM(STR(.Width))+',0'
.Requery()
ENDWITH

Usandoacombinaodepesquisamuitofcil.Apenassoltloemumformulrio,definaaorigemdocontrole,e
noscCursorNameenHeaderKeypropriedades.DesdequeherdadaclassecboAddNew,
preencher
tambmpossveladicionarnovasentradasparaatabeladepesquisaeeditaritensexistentesnamosca.Desde
todasasinstnciasdenossascaixasdepesquisadecombinaoelistadegenricospreenchersuaslistasdomesmo
tabeladepesquisagenrica,podemosatcolocaronomedoformulriodemanutenodepesquisanaclassede
cForm2Callpropriedade.Oquepoderiasermaisfcil?Lookups.scx,queestincludocomoexemplo
cdigoparaestecaptulo,ilustraoquofcil.

Ento,oqueseeuquiserligaromeucomboparaumvalorqueno
estna
alista?(Exemplo:CH05.VCX::cboSpecialeCH05.VCX::cboNotInList)
Aprimeiraperguntaquesaltaparanotaraqui"Entoporquevocestusandoumacaixadecombinao?"Combo
ecaixasdelistagemsousadosparalimitaraentradadedadosaumconjuntodeseleespredefinidas.Permitindoqueo
paraintroduzirumitemquenoestnalistadederrotaopropsitodeusarumacaixadecombinao,emprimeirolugar.
usurio
Ditoisto,percebemosquepodehaverocasiesemquenecessrioessetipodefuncionalidade.
Porexemplo,vamossuporqueumdeterminadocampodeumatabelageralmentepreenchidaapartirdeumconjuntode
seleespadro.Noentanto,ocasionalmente,nenhumadasopespadrosoapropriadosea
utilizadorfinalnecessitadeentraralgoquenoestnalista.Claramente,seositensnopadroforam
adicionadosregularmentetabeladerefernciasubjacente,atabelairiacrescerrapidamentecompoucoutilizada
entradas.Nestecaso,ocampoligadocaixadecombinaodevemincluiradescriodo
itemnatabeladepesquisaenooseuvalorfundamental.Obviamente,sepermitirmosqueocampoaserobrigadoa
itensquenoestonalista,devemosarmazenarasinformaesdestaformanonormalizada.o
nicolugarpara"olharparacima"taisitensadhocestnoprpriocampoacoplado!
146 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura5.4classedecombinaoespecialqueseligaaitensnoestnalista

Umavezqueumatalcombinaopodeserusadoapenasquandoamesaqualestligadono
normalizada,somostentadosausarumacaixadecombinaocomTipoDeOrigemDaLinha=1NoneesuaOrdenado
propriedadedefinidaparatrue.Estecdigo,nocomboInitmtodo,preenchecomostiposque
Atualmenteexistememnossamesa"Pessoas":

lnSelectLOCAL
LnSelect=SELECIONAR()
SELECIONECtypeDISTINCTdepessoasORDERBYCtypeINTOCURSORcsrTypes
IF_TALLY>0
csrTypesSELECIONAR
SCAN
THIS.Additem(csrTypes.cType)
ENDSCAN
FIMSE
SELECT(lnSelect)

Emseguida,nocomboValidmtodo,podemosverificarparaverseousuriodigitouumvalornoem
alistaeadicionlo:
Comisso
SE!(UPPER(ALLTRIM(.DisplayValue))==UPPER(ALLTRIM(.Value)))
.AddItem(.DisplayValue)
FIMSE
ENDWITH

Emborasejaverdadequeessecdigofunciona,existemalgunsproblemasfundamentais.Emprimeirolugar,seafonte
tabelatemumgrandenmeroderegistros,aconsultainicialpoderiacausaratrasosignificativoquandoo
formulrioinstanciado.Emsegundolugar,issonovairesolveroproblemaoriginal.Senovositenssosempre
adicionadoslista,alistavaicontinuaracrescer,tornandosedifcilparaousurioparaselecionarum
Captulo5:ComboseListas 147

entrada.Estailustraotambmnopermiteaousuriodistinguirquaisitenssoos
selees"padro"nalistaequesomeramenteentradasadhoc.
NossaclassecboSpecial,queconsisteemumacaixadetexto,caixadelistagemebotodecomandodentrodeum
recipiente,resolveoproblema.Acaixadetextoocontroledelimite.Acaixadelistagemdeixadodesacoplado
esuaOrigemDaLinhaeTipoDeOrigemDaLinhasopreenchidosparaexibirasseleespadro.o
classecontmcdigoparaforneceracaixadetextocomafuncionalidadede"quickpreenchimento"eparasincronizar
aexibioemseuscontrolescontidos.
ApartecaixadetextodaclasseusaestecdigoemseuKeyPressmtodoparafazeralista
partevisvelquandoousuriopressiona ALT+DNARROWou F4.Eletambmgarantequealistasetorna
invisvelquandoas TABouESCteclassopressionadas:

***<ALT>+<DNARROW>ou<F4>forampressionados
IFnKeyCode=160ounKeyCode=3
This.Parent.DropList()
NODEFAULT
FIMSE

***<TAB>ou<ESC>forampressionados
IFnKeyCode=9ounKeyCode=27
This.Parent.lstSearch.Visible=.F.
FIMSE

OnicooutrocdigonacaixadetextoresidenasuaInteractiveChangemtodoesuanica
finalidadeparainvocarocontinerPesquisamtodo:

***Seumcarctervlidofoiinserido,vamosmtododebuscadopailidarcomisso
IFThis.SelStart>0
IF(LASTKEY()>31eLASTKEY()<128)ou(LASTKEY()=7)
This.Parent.Search()
FIMSE
FIMSE

DocontinerPesquisamtodo,emseguida,fazotrabalhonecessrio:

LOCALlcSofar,lnSelStart,lnSelLength,lnRow

Comisso
COM.txtqFill
***TecladeretrocessoHandle
IFLASTKEY()=127
.SelStart=.SelStart1
FIMSE
***Seovalordigitadonamedida
lnSelStart=.SelStart
lcSofar=LEFT(.Value,lnSelStart)
ENDWITH
***Encontreumfsforonacoluna#1daporolistadestecontrole
COM.lstSearch
***Reporondicedelistanocaso,temostipoionalgoqueno
***nalista
.ListIndex=0
PARAlnRow=1a.ListCount
IFUPPER(.List[lnRow,1])=UPPER(lcSoFar)

148 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

.ListIndex=LnRow
***Sincronizarocontedodecaixadetexto,comoqueseleccionado
***nalista
This.txtQfill.Value=.Value
SADA
FIMSE
ENDFOR
ENDWITH

COM.txtqFill
***Destaqueapartedovalorapsopontodeinsero
.SelStart=LnSelStart
lnSelLength=LEN(ALLTRIM(.Value))lnSelStart
IFlnSelLength>0
.SelLength=LnSelLength
FIMSE
ENDWITH
ENDWITH
PartecaixalistadocontrolecontmocdigoemseuKeyPresseInteractiveChange
mtodosparaatualizarovalordacaixadetextocomoseuvalorquandoousurioselecionaapartirdalista.este
cdigonecessrioemambososmtodos,porquepressionandoa ENTERteclaoua barradeespaopara
selecioneumitemdalistafarcomqueasuaKeyPresseventosejaacionado,masnovaidispararasuaInteractiveChange
evento.AseleodeumitemcomomousedisparaoInteractiveChangeevento,masnodisparao
KeyPress,embora LASTKEY()retornaovalor13seoratoouo ENTERchave
usado.Estecdigo,apartirdacaixadelistaInteractiveChangemtodo,semelhante,masnoidnticoao
ocdigoemseuKeyPressmtodo:
IFLASTKEY()#27
This.Parent.TxtQFill.Value=This.Value
***UmcliquedomousedumvalorLASTKEY()de13(assimcomopressionarenter)
IFLASTKEY()=13
THIS.VISIBLE=.F.
This.Parent.txtQfill.SetFocus()
FIMSE
FIMSE

OnicooutrocdigonapartecaixadelistagemdaclasseresidenasuaGotFocusmtodo.
EstecdigosimplesmentechamaocontinerRefreshListmtodoparagarantiracaixadelistaselecionada
itemsincronizadocomovalordacaixadetextoquandoacaixadelistafeitavisvel:

lnRowLOCAL
COMThis.lstSearch
.ListIndex=0
PARAlnRow=1a.Listcount
IFUPPER(ALLTRIM(.List[lnRow]))=
UPPER(ALLTRIM(This.txtQFill.Value))
.ListIndex=LnRow
SADA
FIMSE
ENDFOR
ENDWITH

Captulo5:ComboseListas 149

Umadasdeficinciasdaclassederecipientequenopodeserfacilmenteusadoemumarede.Para
cumpriresterequisito,criamosaclassedecombinaocboNotInList.ComovocpodevernaFigura
5,4,quandoalistanagradedescartado,oprimeiroitemrealadoquandooDisplayValue
noestnalista.porissoqueprefervelutilizaraclassecboSpecialquandoelenoprecisadeser
colocadonumagrelha.QuandoDisplayValuenoestnalista,observenenhumaselecodocompsito
classerealado.
AclassedecombinaocboNotInListusaomesmotruquequeusamosaoconstruiro
caixadetextonumricanoCaptulo4.Emborapossaserumcontrolodependente,nsdesvincularloatrsdo
cenasemseuInitmtodoesalvarasuaorigemdocontroleparaocostumecControlSourcepropriedade:

IFDODEFAULT()
Comisso
.cControlSource=.ControlSource
.ControlSource=''
ENDWITH
FIMSE

DacombinaoRefreshDisplayValuemtodochamadodetantoasuaatualizaoeGotFocus
mtodosparaactualizaroseuDisplayValuecomovalordocampoaoqualestligado.Isto
interessantenotarquesnecessrioparachamaressemtodoapartirdacombinaoGotFocus
quandoacombinaoemumagrade:

lcControlSourceLOCAL
Comisso
ESE!VAZIO(.cControlSource)
lcControlSource=.cControlSource
.DisplayValue=&LcControlSource
FIMSE
ENDWITH

Finalmente,dacombinaoUpdateControlSourcemtodochamadoapartirdoseuVlidopara(vocadivinhou
lo)atualizarasuafontedecontroledeseuDisplayValue:
LOCALlcAlias,lcControlSource
Comisso
ESE!VAZIO(.cControlSource)
lcAlias
=JUSTSTEM(.cControlSource)

IFUPPER(ALLTRIM(lcAlias))='THISFORM'
STORE.DisplayValueTO&lcControlSource
lcControlSource=.cControlSource
OUTRO
REPLACE(.cControlSource)COM.DisplayValueIN(lcAlias)
FIMSE
FIMSE
ENDWITH

VejaNotInList.scxnocdigodeexemploparaestecaptuloparaverambasestasclassesemao.

150 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comofaoparadesativaritensindividuaisemumacombinaoou
lista?
Nossaprimeirareao"Porquevocestexibindoitensemumacaixadecombinaoqueousurionopermitido
paraselecionar?"Elecertamentepareceestaremcontradiocomoraciocniobsicoparautilizarumacaixadecombinao
primeirolugar:parapermitirqueousurioescolhaapartirdeumalistaprdefinidadeentradaspermitidas.Seo
usurionotempermissoparaselecionarumitem,oquediaboseleestfazendonacaixadecombinaoouumalistapara
com?Maisumavezpercebemosquepodehavercenriosvlidosqueexigemtalfuncionalidade.Para
comear
exemplo,oscdigosdeCPTutilizadosemaplicaesmdicasparadefinirdiferentesoperaeseo
ICD9cdigousadoparadefinirdiagnsticospadropodemmudaraolongodotempo.Nosepodesimplesmenteexcluir
cdigosquejnosoutilizadosporquedetalhehistricopodeserligadoaestescdigosobsoletos.
Aoexibiressesdadoshistricos,seriatilparaexibirocdigoinativocomodesativado.
Destaforma,umacaixadecombinaoligadaaocdigodaCID9noiria"perder"oseuvalordeexibioporqueo
cdigonopoderiaserencontradonalistadocontrole.Nemousuriopermitidoparaselecionloparaum
entradaatual,umavezqueseriadesativado.

Figura5.5Itensdesativadosemumacaixadecombinao

Paradesativarumitememumacaixadecombinaooulista,bastaadicionarumabarradevoltaparaoinciodo
cadeiaquedefineocontedodaprimeiracolunadocontroloOrigemDaLinha.Noentanto,esta
sfuncionaparaRowSourceTypes"0None","1Value"e"5matriz".Aforma
DisabledItems.scx,fornecidocomocdigodeexemploparaestecaptulo,forneceumexemploparauma
decombinaocomTipoDeOrigemDaLinha"5matriz".EstecdigodacaixadecombinaoInitpovoamtodo
amatrizedesabilitaitenssomenteseadatanatabelasubjacenteindicaesteitem
inativo.Estetipodelgicapodetambmserusadaparadesactivarositensespecficoscombasenovalordeum
campolgicoquedeterminaseoitemaindaestativo:

SELECIONEIIFASpm_Desc,(VAZIO(PmtMethods.pm_dStop),'\'+pm_Desc,pm_Desc!)
pm_KeyDEPmtMethodsORDERBYThis.aContentsARRAYpm_DescEM
Captulo5:ComboseListas 151

This.Requery()

PoderamosapenasdefinirtofacilmenteacaixadecombinaocomumTipoDeOrigemDaLinhade"0None",defina
Classificadaspropriedadeparatrueepreenchidolocomoesteemvezdisso:
sua

lcItemLOCAL

PmtMethodsSELECIONAR
SCAN
lcItem=IIF(VAZIO(DSTOP),DSTOP,'\'+DSTOP)
THIS.Additem(lcItem)
ENDSCAN

Comofaoparacriarumacaixadelistagemcomcaixasdeseleo
exibidopeloVisualFoxProquandoeuselecione"View
comooque
Barrasdeferramentas"nomenu?(Exemplo:CH05.VCX::lstChkBox)
Vocjnotouqueascaixasdelistagemtemumaimagemimvel?Vocpodeencontraressapropriedadelistada
sobaguiadelayoutdafolhadepropriedades.Tecnicamentefalando,apropriedadedeimagemrealmente
pertenceadacaixadelistadeitens,emvezdeparaacaixalistacomoumobjeto.Essencialmente,vocpode
manipularaImagempropriedadedoatualListItemeconfigurloparaumacaixaverificadoseele
seleccionadoeumacaixasimples,seno.

Figura5.6caixadelistagemMultiselectusandocaixasdeseleo

Caixasdelistagemdestetipoapresentaroutrocomportamentoforadopadroquerequerespecial
programao.Porexemplo,aoclicaremumitemselecionadonacaixadelistadeselecionalo.premente

152 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

abarradeespaotambmfuncionacomoumaalavancaparaaseleoeitensseleode.Istomuitomais
convenientedoqueopadro Ctrl+cliquee CTRL+BarradeEspaocombinaesnormalmenteutilizados
paraselecionarvriositensemumacaixalista.
Estaclassedecaixadelistarequerumapropriedadedematrizpersonalizadoparacontrolarositensselecionados.No
bastausaronativoSelectedpropriedadeporquenosempredefinidodamaneiraesperada.Para
podemos
exemplo,pressionarabarradeespaoselecionaoitematual.Masdoitemselecionadopropriedadejnoest
definidocomoverdadeiroatdepoisdaKeyPressmtodoforconcludo.Suponhaquensqueremosmanipularesta
propriedadeemdecaixadelistaKeyPressmtodo. This.Selected[This.ListIndex]retornaria
falsemesmosetivssemosapenaspressionadoabarradeespaoparaselecionaroitematual!Vocpodevero
dilema.Etornaseaindamaiscomplicadoquandosetentausarateclaparaalternara
doitemselecionadopropriedade.Asoluosimplesediretamanteranossaprprialistade
seleesatuaissobreosquaistemoscontroletotal.Istoimplementadousandoumamatrizdecostume
alojamento(aSelected),inicializadonocontroleRedefinirmtodo,quechamadodeseuInit:

Comisso
***Limpartodasasselees
***Seoutrocomportamentonecessriaporpadro,coloqueoaquiechamoeste
***Mtododequalquerlugarqueocontedodacaixadelistadeveserreposto
.ListIndex=0
DIMENSO.aSelected[.ListCount]
.aSelected=.F.
ENDWITH

OSetListItemmtodochamadodedacaixadelistaCliqueeKeyPressmtodos.Desdeo
Cliqueeventoacionadotofreqentemente(cadavezqueousuriorolaalistausandoocursor
chaves)TemosdenoscertificarqueschamaroSetListItemmtodoquandoousurioclicaem
umitem.Fazemosissoatravsdaverificaode LASTKEY()=13.Damesmaforma,eleschamadoapartirdo
KeyPressmtodoquandoousuriopressionatantoo ENTERteclaoua barradeespao.Estemtodo
definealinhaespecificadanamatrizpersonalizadoqueacompanhaasseleesdecaixadelistaedefineoitemdo
Imagempropriedadeparaaimagemadequadaparaseuestadoatual:

Comisso
IF.ListIndex>0
***Oitemselecionadodemododeselecionlo
IF.aSelected[.ListIndex]
.Picture[.ListIndex]='Box.bmp'
.aSelected[.ListIndex]=.F.
OUTRO
***Oitemaindanoestseleccionada,entoselecionlo
.Picture[.ListIndex]='CheckBx.bmp'
.aSelected[.ListIndex]=.T.
FIMSE
FIMSE
ENDWITH

comportamentopadroVisualFoxProparacancelaraseleodetodosositensdecaixadelistaquandoseobtmofoco.
Parecequeessecomportamentopadrotambmredefinetodasasimagensnalista.Porquenofazer
isto
queremosqueonossomultiselectcaixadelistaparaapresentaressetipodeamnsia,quechamamosdenossaseucostume
mtododasuaReceberFocomtodo:
RefreshList

Captulo5:ComboseListas 153

lnItemLOCAL
Comisso
PARAlnItem=1a.ListCount
.Picture[LnItem]=IIF(.aSelected[lnItem],'CheckBx.bmp','Box.bmp')
ENDFOR
ENDWITH

Aclassedelistamotor(exemplo:CH05.VCX::cntMover)
listasdemotor,comoaclassedecaixadelista"caixadeseleo"discutidoacima,somaisuserfriendlydoqueo
multiselectlistbox.Emboraelesparecemsercontrolescomplexos,relativamentesimplesde
criarumreutilizveisclassegenrica,listamover.Nossaclasselistamotorconsistedeumrecipientecomum
caixadelistaparaseguraroconjuntodeitensapartirdoqualousuriopodeescolhereoutraqueser
preenchidacomositensselecionados.Eletambmcontmquatrobotesdecomandoparamoveritens
entreasduaslistas.Asbarrasmovimentadornalistadedestinoestohabilitadosparaforneceromximo
flexibilidade.Seaordemdositensselecionadosfundamentalparaafuncionalidadedalistamotor,este
forneceummecanismoparaqueousurioparaordenarsuasselees.DocontinerResetListmtodo,
queinicialmentepreencheaslistas,onicomtodoqueestinstnciaespecfica.Aforma
MoverList.scx,fornecidocomocdigodeexemploparaestecaptulo,usaestemtodoparapreenchero
listadeorigemdomotordanossamesa"PmtMethods":

Comisso
.lstSource.Clear()
.lstDestination.Clear()
pasesSeleco
SCAN
.lstSource.AddItem(c_Desc)
ENDSCAN
ENDWITH

Nossaclasselistamotordenenhumamaneiraaltimapalavraemmotores,maselevaitedaralgopara
construirsobre.

154 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura5.7listamotorSimples

Osbotesdecomandonosoanicamaneirademoveritensentreasduaslistas.Duplo
clicaremumitemremovedalistaatualeadicionaloparaooutro.Ositensselecionadospodem
tambmserarrastadosdeumalistaecaiuparaooutro.Naverdade,noimportaaformacomoo
itenssomovidosentreaslistas.Todoomovimentorealizadochamandoorecipientede
MoveItemmtodoepassloumarefernciaparaalistadeorigemparaomovimento.Humachamadapara
estemtodoapartirdosDblClickeDragDropmtodosdecadaumadascaixasdelistagem,bemcomoem
oOnClickmtododosdoisbotesdecomando,cmdMoveecmdRemove:

LPARAMETERStoSource
lnItemLOCAL,toDestination

Umavezqueestemtodopassadoumarefernciadeobjetoparaalistadeorigem,podemosusarestareferncia
paradeterminarqualalistadedestinos:

Comisso
IFtoSource=.lstSource
toDestination=.lstDestination
OUTRO
toDestination=.lstSource
FIMSE
ENDWITH

***Bloquearatelademodoaevitarosefeitoscolateraisvisuaisdistraem
***Queresultamdemoveroitem(s)
Thisform.Lockscreen=.T.

Temosagoraumloopatravsdalistadeorigemparaadicionarcadaitemselecionadoparaalistadedestinoe
removlodalistadeorigemdepois.Comoitenssoremovidosdalistadeorigem,asua
ListCountpropriedadessodiminuiuemum.Ento,nsusamosuma DOTEMPOcircuitoemvezdeum FORlooppara
termaiscontrolesobrequandoondiceparaalistadeorigemincrementado.Nsincrementlo
somentequandooitematualnalistanoestseleccionadaparapassarparaaprxima:
Captulo5:ComboseListas 155

lnItem=1
COMtoSource
FazerenquantolnItem<=.ListCount
IF.selected[lnItem]
toDestination.AddItem(.List[lnItem])
.RemoveItem(LnItem)
OUTRO
lnItem=+1lnItem
FIMSE
ENDDO
ENDWITH

***Noseesqueadedesbloquearatela!
Thisform.Lockscreen=.F.

Implementaodearrastarefuncionalidadegotarequerumpoucomaisdecdigo.Paraconseguirisso,
nsadicionamosonMouseX,nMouseYenDragThresholdpropriedadesparaorecipiente.o
MouseDownmtododascaixasdelistacontidosdefineosnMouseXenMouseYpropriedadespara
acorrentecoordenaquandoobotoesquerdodomousepressionado.Istofeitoparaevitar
arrastarumitemquandoousurioacaboudeclicarparaselecionlo.Aoperaodearrastarnocomea
amenosqueoratopassou,pelomenos,onmerodepixelsespecificadopelonDragTheshold
propriedade.DocontinerstartDragmtodo,chamadoapartirdascaixasdelistagemMouseMovemtodo,
verificaparaverseomousefoimovidosuficientementeparainiciaroarrastooperao.OChamado
listapassaumarefernciadeobjetoparasimesmoeascoordenadasatuaisdomouseparaestemtodo:

LPARAMETERSToList,TNX,TNY

Comisso
***Siniciaraoperaodearrastarseomousefoimovido
***pelomenosonmerominumunpixels
IFABS(TNX.nMouseX)>.nDragThresholdOR
ABS(TNY.nMouseY)>.nDragThreshold
toList.Drag()
FIMSE
ENDWITH

Finalmente,dalistaDragIconpropriedadeapartirdoqualaoperaodearrastaroriginou,precisaser
alteradoparaoconeapropriado.Quandoocursorestemumapartedatelaqueno
permitirqueoitemaserdescartado,nsqueremosmostrarocrculofamiliarcomumabarranoseuinteriorque
universalmentesignifica"NO!"FazemosissochamandoocontinerChangeIconmtododo
dalistaDragOvermtodo.Estemtodo,comoonomeindica,apenasmudaoconedearrasteparaa
coneapropriado:

LPARAMETERStoSource,tnState

IFtnState=0
***Permitiuacair
toSource.DragIcon=THIS.cDropIcon
OUTRO
IFtnState=1
***Nopermitidaacair
toSource.DragIcon=THIS.cNoDropIcon

156 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FIMSE
FIMSE
Noapenasalistademovermuitomaisfcildeusardoquemulticaixadeseleodalista,eletambmda
aplicaoumaaparnciamaisprofissionalesentirsemmuitoesforoextra.

Eseeuprecisarexibircentenasdeartigosemminhacombinao
caixa?
Nestecaso,umacaixadecombinaomuitolentoporquenecessriosemprepreenchersualistainternacomtoda
itensdafontededadossubjacente.Sefomoscapazesdecombinaraeficinciadeumagrade
(Quepodecarregardados,conformenecessrio)comacapacidadedepesquisaincrementaldonossoQuickfilldecombinao
box,teramosasoluoprefeito.Felizmente,usandocomposio,podemosfazerexatamente
issoecriamosumaclasseparaisso"ComboGridcontrole"queusaumacaixadetexto,umcomando
botoeumagradecomoseusprincipaiscomponentes.
Aconstruosemelhantedescritaparaanossa"cboSpecialclasse"usadoparapermitir
aligaodeumcontroleparaumvalornocontidosnalistainterna.Aprincipaldiferenaque
emvezdacaixadelistausadonocontroleantes,agorausamosumagradeparaodropdown
funcionalidade.Algunstratamentoespecialnecessrianonveldecontinerparagarantirquetudo
funcionasemproblemas,masastcnicassoomesmo.
Estecontrolefoioriginalmenteescritoepublicadocomoum"FreeHelpcontribuio"parao
FrumFoxProCompuServe,edepoisfoiusadocomoabaseparaumartigoemFoxTalk
revista.Paraumadiscussocompletasobreodesenhoeimplementaodessecontrolever"Agoravoc
v,agoravocnofaz"umartigonaediodejulhode1999doFoxTalk.AsFiguras5.8e5.9mostram
asduasencarnaesdagradedecombinao:

Figura5.8OComboGriddormente

Captulo5:ComboseListas 157

Figura5.9OComboGridativa

NotasdelanamentoparaaClasseComboGrid(Classe:CboGrid.vcx,ExemploForm:
FrmCGrd.scx)
Criadopor:MarciaG.AkinseAndyKramek,ecolocadonodomniopblicoemfevereiro
1999.
EstaclassefoiprojetadaparausarumagradenolugardeumVFPComboboxpadroparaumgrandededados
volumeouinserirdadosemmaisdeumcampotabeladepesquisa,usadoparapreencheralistasuspensa.
Aclasseconsisteemumacaixadetexto,umbotodecomandoeumagradedentrodeumrecipiente.Agradeest
normalmenteinvisveiseaclassepareceesecomportacomoumacaixadecombinaopadroVFP.
Aclassecontroladopor7unidades,comosesegue:

Tabela5.9ComboGridpropriedadespersonalizadas

Propriedade Funo
Calias NomedatabelaaserusadacomoRecordSourceparaagrade
CColSource Vrgulalistadenomesdecamposseparadosparaascolunasnagrelha
CControlSource Fontededadosparaacaixadetexto(senecessrioestarvinculado)
CkeyField Campodeusarparadefinirovalordacaixadetexto
CtagName TagparausaremcAlias
LAddNewEntry Determinasenovasentradassoadicionadastabeladagrade,bemcomo
aocontrolsourcecaixadetexto
NColCount Nmerodecolunasparaexibirnagrade

Ummtododenveldeinstncianicaestdisponvelparaqueosdadospodemserlidosapartirdogridapsum
seleofeita,porexemplo,parapreencheroutroscamposdoformulrio:

Tabela5.10mtodospersonalizadosComboGrid

Mtodo Funo
RefreshControls InstnciaMtodoNvelchamadoporGradeAfterRowColChange()epelo
KeyPressnoTextBoxQuickfill

158 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Existemquatroformasdeusarestecontrole,dependendodaconfiguraodocControlSource
elAddNewEntrypropriedadesdaseguinteforma:

cControlSource:=""elAddNewEntry=.F.Acaixadetextonoestvinculadoe
emboraapesquisaincrementaliroperar,eosnovosdadospodemserinseridosno
caixadetexto,novosregistrosnoseroadicionadostabelasubjacentedogrid.
cControlSource:=""elAddNewEntry=.T.Acaixadetextonoestvinculadoenova
osdadospodemserinseridosnacaixadetexto,novosregistrosseroadicionadosredede
tabelasubjacente.colunasadicionaispodemterdadosinseridospelobotodireitono
clulaadequada.
cControlSource:=<especificado>elAddNewEntry=.F.Acaixadetextoestvinculadae
lerseuvalorinicialdatabelaespecificadaeescreverasalteraesnoqueocampo
devoltamesa.Novosregistrosnoseroadicionadostabelasubjacentedogrid.
cControlSource:=<especificado>elAddNewEntry=.T.Acaixadetextoestvinculadae
lerseuvalorinicialdatabelaespecificadaeescreverasalteraesnoqueocampo
devoltamesa.colunasadicionaispodemterdadosinseridospelobotodireitono
clulaadequada.

Agradecimentos
GraassodevidoaTamarGranorparaametodologiaQuickfillqueelapublicadono
Setembro1998emissodeFoxProAdvisorePaulMaskensqueforneceuainspirao
paraorecipientedeautodimensionamentoedagrade.
SeguindoumasugestoporDickBeebe,oComboGridfoiaprimoradoparaincorporaruma
menudobotodireitonagradesuspensa.Dependendodasconfiguraes,vocpodeclassificarpora
seleccionadocolunaoueditaralinhaatualmenteselecionada.Senemapropriadoomenuno
aparecer.
Paraativaraedio,apropriedadelAddNewEntrydorecipientedeveserdefinido.Paraativaraclassificao
fontededadosdagrade,vocdeveterumamarcadendicechamadoexatamenteomesmoqueocampousadocomo
ocontrolsourceparaacoluna.Seestanoasuaprticanormal,vocprovavelmentedeve
considerlodequalquermaneira.

disclaimerdoautor
Comosempre,temostentadofazerainfalvelComboGrid,masnscolocamosessecontrole
classenodomniopblico"comoest",semgarantiaimplcitaoudado.Nopodemosaceitar
responsabilidadeporqualquerperdaoudanoresultantedesuautilizao(prprioouimprprio).Todoocdigofonte
includosnosubdiretrioCboGriddecdigodeexemplodestecaptulo,entosintaselivreparamodificar,
alteraroumelhorloparaatenderssuasnecessidadesespecficas.
Captulo6:Grids:OscontrolesMisunderstood 159

Captulo6
Grids:TheMisunderstood
controles
"Parasergrandedeveserentendidomal."(Essays,"autosuficincia",deRalphWaldoEmerson)

AgradeocontrolemaiscaluniadonoVisualFoxPro.Muitosespecialistastmpublicamente
expressouaopiniodequeelesnunca,sobquaisquercircunstnciasusarumagradeparadados
entrada.Emborasejadifcildedomar,agradepodeserusadodeformamuitoeficazparaeste
propsitonasituaocerta.Umagradetambmamelhorescolhaquandosetratadeexibir
grandesquantidadesdedadosmuitorapidamente.Nestecaptulo,vamosapresentlocomalguns
etestadastcnicasquevocpodeusarparaobtermaisdesuasgrades.
tentaram

Aotrabalharcomgrades,aprimeiracoisaalembrarqueagradenoumaplanilha,
emborapossaparecerum.Hrealmenteapenasumalinhaemumagrade.Orestofeitocom
fumaaeespelhos.Vocnopodereferirseaclulanaterceiracolunadadcimalinhadagrelha.
MasvocpodesereferiraoterceirocamponodcimoregistrodagrelhaOrigemDosRegistos.Geralmente
falando,sevocprecisaracessarvaloresemumacluladagradeparticular,asuamelhorapostaparaobteresse
ainformaodocampodafontededadossubjacente.
UmagradegeralmenteexibedadosdafontededadosquevocespecificarnoseuOrigemDoRegistro
propriedade.Noentanto,mesmosevocnoespecificarumOrigemDoRegistro,vocaindapodeexibirdadosna
grade.Sehouverumcursorabertonareadetrabalhoselecionado,agradevaipuxarseusdadosde
h!AgradeRecordSourceTypepropriedadeespecificacomoabrirafontededadosque
preencheocontroledegrade.Nsgeralmenteescolheropadro,"2Alias",comoeleomaisgeralmente
til.

Quandoqueoseventosdefogo?(Exemplo:GridEvents.scx)
Sercapazdeusarasredesdeformaeficazdependedecompreensoquandoofogoeventos.Htambm
algumaspegadinhas!notarantesdecomear.Istooqueacontecequandoagradeprimeiraobtmofoco:

dagradeWheneventoacionado
AQuandocasodeoCurrentControlnosprimeirosincndioscoluna
OGotFocuseventodoCurrentControlnasActiveColumnincndios
dagradeAfterRowColChangeeventoacionado

Issoporsistemalgumasimplicaesimportantes.Sevoccolocarocdigonagrade
AfterRowColChangemtododepensarqueelesacionadodepoisquevocmoverparaforadaclulaatual,
pensedenovo!Eleacionadosemprequeagradeobtmfoco.Falandonisso,voctemnotadoqueo
gradeestfaltandoumGotFocusmtodoemboratenhaumSetFocusmtodo?
Tenhaemmentequequandoagradeobtmfoco,asuaActiveColumnvaiseramesma
colunaqueestavaativaquandoagradejperdeuofoco.Aprimeiravezquevocguiaemumagrade,
160 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

oCurrentControlnaprimeiracolunasetornenoActiveCell.Suponhaquevocnavegue
paraaterceiracolunadagradeantesdeclicaremoutroobjetodeformulrio.Aprximavezquearederecebe
focar,aActiveColumn,porpadro,seraterceiracoluna.
Ascoisasacontecemumpoucodiferentequandoagradeperdeofoco.E,apropsito,embora
agradeperdeofoco,notemLostFocusmtodo.Interessante,no?

dagradevlidoseventoacionado
dagradeBeforeRowColChangeeventoacionado
AValidcasodeCurrentControlnasActiveColumnincndios
OLostFocuseventodaclulaativanosfogosdegrade

Umavezqueagrelhatemofocoevocusarotecladoparanavegarentreasclulasnagrade,o
Fogodeeventoscomoeste:

OKeyPresseventodoCurrentControlnasActiveColumnincndios
dagradeBeforeRowColChangeeventoacionado
AValidcasodeCurrentControlnasActiveColumnincndios
OLostFocuseventodosincndioscelularesativos
OQuandocasodeCurrentControlnacolunaquevocsemoveparaincndios
OGotFocuseventodosnovosincndioscelularesativos
dagradeAfterRowColChangeeventoacionado

Quandovocusaomouseparanavegarentreasclulasemumagrade,obviamente,oKeyPress
eventonodispara.Oseventosrestantesdispararexatamentedamesmaformacomoofazemquandoseutiliza
otecladoparanavegar.Noentanto,quandousandoomouse,oClickeventodorecmativa
fogosdeclulasimediatamenteapsagradeAfterRowColChange.Estasequnciaamesma,mesmo
quandooCurrentControlnagradeActiveColumnumacaixadecombinaoemvezdeumacaixadetexto.

Gotcha!Incndiosvlidosdagradeantesdavalidadedocontroleatual
Observequequandosedeslocamdeumagradeparaoutroobjetonoformulrio,dagradevlidosincndios
antesdoValiddaclulaativa.Esteumbug.Normalmentevocesperariaparausaro
docontrolevlidomtodoparadeterminarseessecontrolepodeperderofoco.Noentanto,quandoum
controleestcontidodentrodeumagrelha,existemdoisnveisemqueoperafoco.Emprimeirolugar,entre
ocontroloeoutroscontrolosquetambmestodentrodagrade.Nestecontextoascoisassecomportam
normalmente.
Emsegundolugar,haquestodequalobjetodeformulriotemofoco.Esteerroirmordloquando
focoestsendomovidaentreagradeeoutroobjeto.Tratase,comoseriadeesperar,agrade
Vlidomtodoquedeterminaseagradepodeperderofoco.Noentanto,porqueagradeest
Validchamadoantesdequalquercontidocontrole,umcontrolecontidonopodeimpediragrade
perderofoco,apesardesuaprpriavalidaofalhou.
Issopodeevaipermitirqueosdadosruinsparaserinseridonogrid.Felizmente,existeumfcil
soluoalternativa,quegarantequeagradeValidapelaexplicitamenteeretornaoresultadodequalquer

Captulo6:Grids:OscontrolesMisunderstood 161

continhaavalidaodocontrole.Ento,seacaixadetextonaprimeiracolunadagrelhatemocdigoemseu
Vlida,estalinhanagradevlidamtodocuidadoproblema:
RETURNThis.Column1.Text1.Valid()

OqueadiferenaentreActiveRowe
RelativeRow?(Exemplo:ActiveRow& RelativeRow.scx)
Umagradetemdoisconjuntosdepropriedadesquepodemserusadosparasereferirasualinhacorrenteedacoluna.o
ActiveRoweActiveColumnpropriedadescontmvalores"absolutos".Suponhaqueagradeestsendo
usadoparaexibirtodososcamposdetodososregistrosdeseuOrigemDoRegistrodeformanatural.Nisso
situao,agrelhaActiveRowomesmoqueonmeroderegistoeActiveColumnamesma
comoonmerodocampo.Noentanto,seoOrigemDoRegistronoestnaordemnatural,ActiveRowdetmo
deslocamentodoregistroatualdoprimeiroregistronaordematual.Seumsubconjuntodecampos
apresentadosnagrelha,ActiveColumnprendeodeslocamentodocampocorrentedoprimeiroposicional
camponestesubconjunto.
Poroutrolado,osRelativeRoweRelativeColumnpropriedadesreferemseposiode
alinhacorrenteedacolunacomrespeitoporovisveldagrelha.parecebastante
simples,no?
Bem,noexatamente.Oacimaexpostovlidoapenasenquantoagradeocontroloactivo.Quando
outroobjetodeformulrioocontroleativo,essaspropriedadessozerados.Almdisso,asua
Osvaloressofiveisapenasquandoaclulaactivaestnaporovisveldagrelha.Seumaclulana
gradetemfocoeasbarrasderolagemverticalsousadospararolaragradedemodoaclulaativano
maisvisvel,tantoActiveRoweRelativeRowestodefinidasparazero!Quandoestaclulareapareceno
grade,aRelativeRoweActiveRowsorepostoscomosvalorescorretos.Ovalormantidopela
gradeActiveColumnnomuda,mesmoquandoaclulaativaroladaforadavista.Nisso
situao,agradeRelativeColumncontmosvalorescorretossevocinterpretarestevalorcomo
sendoodeslocamentodaprimeiracolunanaporovisveldagrelha.Emoutraspalavras,oprimeiro
coluna"invisvel"imediatamenteesquerdadaprimeiracolunavisvelnagrelhaemoffset0.
Acolunaimediatamenteesquerdadoumnodeslocamento0,estnodeslocamento1,eassimpordiante.
Ento,oquesignificatudoisso?Nomuito,realmente.Asanomaliassointeressantes,masnovai
temqualquerefeitosobreaformacomousamosessaspropriedades.ActiveRoweRelativeRowpropriedadesso
muitotilquandoqueremosproporcionaranossaredecomocomportamentoespecial.Porexemplo,opadro
comportamentodo TABchaveparamoverofocoparaaprximacolunanalinhaatualdagrade.
Suponhaquevocqueiramoverofocoparaamesmacolunanaprximalinhaemvezdisso.Vocnopodefazer
issospeloincrementodagradeActiveRow.Emvezdisso,vocprecisafazerusodaredede
RelativeRowpropriedadeparadeterminarquandoainvocaroseuDoScrollmtodo.Ocdigodeexemplopara
realizaressatarefaaparecemaistardenestecaptulo.Tambminclumosumacaixadecombinaodegrade
classequepermitequeasteclasdocursorparapercorreragradequandoacombinaoest"fechado".estecomportamento
tambmimplementadopormeiodautilizaodestaspropriedades.

162 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Gotcha!ActiveColumnrealmentenolhedizerqualoativo
coluna
OActiveColumnpropriedadesoacomoseeledevenosdizerqualcolunadegradeanica
sendoacessadopelousurioe,depoisdeumamoda,elefaz.Noentanto,istonomuitotil
porqueapenasnosdizqueaposiodacolunaactualmenteactivonagrelha,noquede
ascolunasestativoatualmente.
Pessoalmente,achoqueseagradeActiveColumn1,seriatilseissosignificava
queGrid.Columns[1]eraacolunaativa.Esta,defato,verdadeirosomenteseascolunasdagradeso
Nomveiseseodesenvolvedornoreorganizarascolunasnodesignerdeformulrioantes
ajustedacolunamvelpropriedadeparafalse.
Tomemos,porexemplo,umagradequecontmcincocolunasmveis.Seascolunassorearranjados
porissoelesso,nestaordem:

.Columns[4] .Columns[5] .Columns[1] .Columns[2] .Columns[3]

easguiasdousurionacaixadetextocontidosno.Columns[5],dagradeActiveColumn2.
EsteomesmovalorqueoOrdemDaColunapropriedadede.Columns[5].Afimdefazerqualquercoisa
significativacomagrelhaActiveColumn,devemosescrevercdigoparadescobrirqualoativo
coluna:

PARACADAloColumnINThis.Columns
IFloColumn.ColumnOrder=This.ActiveColumn

***Estaacolunaativa
***Obterumarefernciaoufazeroqueprecisaserfeitocomeleaqui
SADA
FIMSE
ENDFOR

Comofaoparadestacaralinhadegradeatual?(Exemplo:
CH06.VCX::grdBase)
Quandovocolhaparafolhadepropriedadesdagrade,vocverumapropriedadechamadaHighlightRowsoba
guiadelayout.Aprimeiravezqueviisso,vocprovavelmentepensouquedeixarestapropriedadeemseu
configuraopadrogostariadedestacaralinhadegradeatual.Errado!primeiravista,pareceque
Definindoessapropriedadecomoverdadeirooufalsonofaznada.Issotambmincorreto.Sevocdefinir
HighlightRowaverdade,vocvainotarabordadalinhadegradeatualdestacado.Nomuito
til,no?Sugerimosquevocdefiniressapropriedadeparafalseemsuaclassedegrelhadebase,porquedeixandoo
definidocomoverdadeirodesempenhodegrada.

Captulo6:Grids:OscontrolesMisunderstood 163

Figura6.1Realcealinhadegradeatual

Felizmente,umaquestobastantesimplesparaadicionaressafuncionalidadeparasuagradedeclassebase.o
gradeexigeduaspropriedadespersonalizadasparaalcanaresteobjetivo.Aprimeira,inicializadoparazero,nRecNo.
EleirarmazenaronmerodoregistroatualmentenagradeActiveRow.Asegunda,inicializado
comofalsa,lAbout2LeaveGrid.Eleusadoparareporodestaquecorretamentequandoestamosanavegar
nagradeeparagarantirquearedepermanecerealadoquandoofocosemoveparaumaoutraforma
objeto.Estecdigo,nagradeInitmtodo,irdestacaralinhadegradeatualemciano:

lcForeColorLOCAL,lcBackColor

lcForeColor='IIF(RECNO(This.RecordSource)=This.nRecNo'
lcForeColorlcForeColor=+'RGB(0,0,128),RGB(0,0,0))'
lcBackColor='IIF(RECNO(This.RecordSource)=This.nRecNo'
lcBackColor=lcBackColor+'RGB(0,255,255),RGB(255,255,255))'

Comisso
.nRecNo=RECNO(.RecordSource)
.SetAll('DynamicForeColor',lcForeColor,'COLUMN')
.SetAll('DynamicBackColor',lcBackColor,'COLUMN')

Paraalterarodestaquequandoosactuaisalteraesdelinhadegrade,essecdigonecessriono
Quandoomtododecadacontroleemcadacolunadagrade:

COMThis.Parent.Parent
.nRecNo=RECNO(.RecordSource)
ENDWITH
164 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

TambmprecisamosdefinirlAbout2LeaveGridpropriedadedagradedeverdadeemsuaValidmtodoe
afalsanasuaQuando.OnicooutrocdigonecessrioestnagradeBeforeRowColChange
Mtodo:

SE!This.lAbout2LeaveGrid
This.nRecNo=0
FIMSE

Comofaoparamanterminhagradederolagemquandoasguiasde
foradaltimacoluna?
usurios
Sevocotipodepaciente,possvelfazerissovisualmentenodesignerdeformulrio.Vocpodemuito
cuidadosamenteseesqueadedeixarumpixelentreabordadireitadaltimacolunadegradeeo
bordadireitadasuagrade.Noentanto,amaioriadenstemcoisasmaisimportantesparaenotma
pacinciaparaestetipodeabsurdo.
NsadicionamosummtodopersonalizadochamadoSetGridparaanossagradedeclassebaseparaconfigurlo
eleinstanciado.Temoscertezadequeostamanhosdegradessecorretamente,adicionandoumpoucodecdigoparaonosso
corretamentequando
gradeclassebaseSetGridmtodo.Estecdigosexecutadoquandoagradenotem
barrasderolagemhorizontal,poisbaseiasedeterminarqualaltimacolunanovisvel
porodagrelha.Claramente,quandoagradepodeserdeslocadohorizontalmente,nohfixo"ltima
coluna."
Issotrazoutroponto.Gradesquerolarhorizontalmentedemonstrarinterfacedebad
design.Nsacreditamosquetodasasinformaesapresentadasemumagradedeveserimediatamentevisvelaofim
doutilizador.Istoespecialmenteimportantecomgrelhasdeentradadedados.Emcabeasabaixadassituaesdeentradade
difcilparaosusuriosfinaisparamanteroseulugaresedistrairquandoainformaodesdobramentoem
dados,que
eforadatela.Tambmrequerbrincarparaverainformaorelevantequando
escondidodavistaemumagradequerolanahorizontal:

***Seagradenorolarhorizontalmente,certifiqueseascolunassodimensionadas
***Adequadamenteparaagradenorolarquandovocguiaparaforadaltimacoluna
Comisso
IFINLIST(.ScrollBars,0,2)

***Calcularalarguratotaldetodasascolunas
lnTotColWidth=0
PARAlnCnt=1a.ColumnCount
***Addonalarguradestacoluna
lnTotColWidth=lnTotColWidth+.Columns[lnCnt].Width+1

***Descobrirseestaaltimacoluna
IF.Columns[lnCnt].ColumnOrder=.ColumnCount
lnLastColumn=lnCnt
FIMSE
ENDFOR

***Addonalarguradabarraderolagem(senecessrio)
lnTotColWidth=lnTotColWidth+IIF(.ScrollBars=2,
SYSMETRIC(5),0)+2

***Addondamarcadeexcluso(senecessrio)

Captulo6:Grids:OscontrolesMisunderstood 165

lnTotColWidth=lnTotColWidth+IIF(.DeleteMark,8,0)

***Addonamarcarecorde(senecessrio)
lnTotColWidth=lnTotColWidth+IIF(.RecordMark,10,0)

***Redimensionarltimacolunaparagarantirgradecompletamentepreenchido
.Columns[LnLastColumn].Width=.Columns[lnLastColumn].Width+
(.WidthLnTotColWidth)
FIMSE
ENDWITH
Comofaoparacriarcabealhosdevriaslinhas?(Exemplo:
CH06.VCX::grdBigHeadersegrdMLHeaders)
Pessoalmente,pensamoscabealhosdevriaslinhassodemaisesomuitorestritivas.Tendo
ditoisto,nscriamosumaclassedegradequeusalos.Afimdeusaressaclasse,todasascolunasdegrade
devemterseusredimensionveisemveispropriedadesdefinidacomofalsa.Istoporqueaclassedefineo
gradeHeaderHeightpropriedadeparazeroesubstituiocabealhocomrtulosquesesenteacimada
grade.Porqueessesrtulosnoredimensionaroumover,aclassedegradenopermitehorizontal
rolagem.

Figura6.2cabealhosdegradedevriaslinhasemumagradeesttica

Nossaclassegradedecabealhodevriaslinhastemdoisnovosmtodos:ReplaceHeaders,quecriao
rtulosacimadagrade,eWhiteShadow,quecriaosefeitosvisuaisparatornaressesrtulos

166 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

olharmaiscomocabealhosdoVisualFoxPronativos.NstambmadicionamosalgumcdigoparaonossoSetGridmtodo
paragarantirascolunasnestaclassedegradenopodemsermovidosouredimensionados:

lnCntLOCAL

DODEFAULT()

Comisso
PARAlnCnt=1a.ColumnCount
.Columns[LnCnt].Movable=.F.
.Columns[LnCnt].Resizable=.F.
ENDFOR

***Configureoscabealhosdevriaslinhas
.ReplaceHeaders()
ENDWITH

OReplaceHeadersmtodo,comoonomeindica,substituicabealhodacolunadagradecom
rtulos.TenhaemmentequeagrelhaHeaderHeightdeveseraltaosuficientenodesignerdeformulrio
paraacomodaralegendadevriaslinhas.Estevalorutilizadoparadefiniraalturadortulono
ReplaceHeadersmtodo:

LOCALlnLeft,li,lnVSBWidth,lcName,lnDelRecBlobWidth,
lnTop,lnHeaderHeight,lnOrdinal

Comisso
LnLeft =IIF(.DeleteMark,8,0) &&Deslocadapormarcadeexcluso
LnLeft =LnLeft+IIF(.RecordMark,10,0)&&Deslocadapormarcarecorde

lnDelRecBlobWidth=lnLeft
lnHeaderHeight =.HeaderHeight

lnTop=+1.Top &&Salvarposiosuperiordagrade

***Reporalturacabealhodagrelhaparazero,paraimpedilodeinterferir
.HeaderHeight=0
***ColoqueagrelhaparabaixoporheaderHeight
.Top=.Top+LnHeaderHeight

***AjusteaalturadagradeporheaderHeight
.Height=.HeightLnHeaderHeight

lnVSBWidth=SYSMETRIC(5)+1 &&Obterlarguradabarraderolagemvertical

***Verificaorpidaatravsdecolunasparaencontraraordemdascolunas
ArraylocallaSequence[.ColumnCount]
PARAli=1TO.ColumnCount
laSequence[li]=This.Columns[li].ColumnOrder
ENDFOR

PARAli=1TO.ColumnCount
***Encontrararefernciacolunaordinaldonmerodesequnciadeordemdecoluna
lnOrdinal=ASCAN(laSequence,li)
lcName="dHeader"+LTRIM(STR(lnOrdinal))

Captulo6:Grids:OscontrolesMisunderstood 167

This.Parent.Addobject(lcName,"label")

COMEVAL("This.Parent."+LcName)
.BackStyle 1=
.BorderStyle=1
.WordWrap =.T.
.Visvel =.T.
.Alinhamento 2= alinhamento&&Centroficamelhor
.Rubrica =This.Columns[lnOrdinal].Controls[1].Caption
.Cordefundo=This.Columns[lnOrdinal].Controls[1].BackColor
.FontName =This.Columns[lnOrdinal].Controls[1].Fontname
.Tamanhodafonte
=This.Columns[lnOrdinal].Controls[1].FontSize
.FontBold =This.Columns[lnOrdinal].Controls[1].FontBold
.Altura =lnHeaderHeight
.Largura =This.Columns[lnOrdinal]+2.Width
.Esquerda =This.Left+lnLeft
.Topo =lnTop

This.Columns[lnOrdinal].Controls[1].Caption=ESPAO(0)
This.WhiteShadow(.Left,.Top,.Height,.Width)

lnLeft=lnLeft+This.Columns[lnOrdinal]+1.Width
ENDWITH
ENDFOR

***Adicionarblobacimadegravao/excluirmarca
IFlnDelRecBlobWidth>0
COM.parent
.Addobject('ShpDelRecBlob","Forma")
.shpDelRecBlob.Backcolor =RGB(192,192,192)
.shpDelRecBlob.Height =lnHeaderHeight
.shpDelRecBlob.Width =+1lnDelRecBlobWidth
.shpDelRecBlob.Left =This.Left
.shpDelRecBlob.Top =lnTop
.shpDelRecBlob.Visible =.T.

COM.shpDelRecBlob
This.WhiteShadow(.Left,.Top,.Height,.Width)
ENDWITH
ENDWITH
FIMSE

***Adicionarblobacimabarraderolagemvertical
IF.Scrollbars=2
COM.parent
.Addobject('CmdScrollBlob',"CommandButton")
COM.cmdScrollBlob
.Enabled=.F.
.Altura =lnHeaderHeight
.Largura =lnVSBWidth
.Esquerda=This.Left+this.widthlnVSBWidth
.Topo =lnTop
.Caption=ESPAO(0)
.Visible=.T.
ENDWITH
ENDWITH
FIMSE
ENDWITH
168 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Estaclassereutilizvelenorequerumagrandequantidadedecdigoespecficoinstncia.,noentanto,
limitadaaredesestticos.Estamoscientesdeque,umavezemumaluaazulvocpodeprecisardeumagradecomvrias
cabealhosquetambmsuportarolagemhorizontalecolunasquesoredimensionveise
linhas
mvel,porissocriamosumaclasseparafazerisso.Afunoquetornaissopossvel
OBJTOCLIENT().EstafunoretornaoTop,Left,alturaoulargurapropriedadedeumobjeto
emrelaosuaforma.Umavezquenemcolunasdegrade,nemcabealhosdegradetmumaEsquerdapropriedade,este
posiooudevesercalculadoadicionandoalarguradecadacolunaparaumacumulador,comona
oexemploanterior,ouusandoo OBJTOCLIENTfuno.
Oresultadoparecemuitolegalevaiimpressionartodososseusamigosdotot.Noentanto,nohnenhuma
talcoisacomoumalmoogrtis.Opreoparaestafuncionalidadeumgrandeaumentonaquantidadede
cdigoespecficoinstncianecessriaparaapoilo.
EmvezdeoReplaceHeadersmtodoutilizadonoexemploanterior,estaclassedegrelhatemuma
SetHeadersmtodoporqueoscabealhosnosorealmentesubstitudos.OSetHeadersmtodo
criartulostransparentesqueflutuamacimacabealhosexistentesnagradecomumamargemsuficientepara
permitirqueousuriofinalclicarnocabealhoabaixo,afimdemoverouredimensionaracoluna.
Estaclassegradetemduasnovaspropriedadespersonalizadas:

nHdrMargin:especificaonmerodepixelsparadeixarentreasbordasdaetiqueta
eocabealhodagradeopadrocincopixels
Nright:armazenaacoordenadaxdaposiomaisdireitanaporovisveldo
gradeparasetemoscolunasquenosovisveis,nofazemososrtulosparaoseu
cabealhosvisveis

NstambmadicionamosoRefreshHeadersmtodoparareposicionarosrtuloscadavezqueo
graderoladaouascolunassomovidosouredimensionados.RefreshHeaderschamadoapartirdarede
daclasseSetHeaderseroladasmtodos.EletambmdeveserchamadoapartirdecadacolunaMovede
Redimensionarmtodos.Asltimasduaschamadasdevemsercolocadosemcadainstnciadestaclassedegrelha,umatarefa
quepodesertornadamenostediosoatravsdacriaodeumconstrutorparaestaclasse.Vamosdiscutirtalconstrutor
maistarde,nocaptulosobreferramentasdeprodutividadedodesenvolvedor.

Captulo6:Grids:OscontrolesMisunderstood 169
Figura6.3gradecomcabealhosdevriaslinhasdeapoiorolagemhorizontalemvel
colunas

Gotcha!eventoroladanodisparaquandoasteclasdecursorpercorrera
grade
Podemosbemestaratergiversaessobreasemnticaaqui,masoarquivodeajudadoVisualFoxProdizo
Roladaeventoocorreemumcontroledegradeouseformamquandoasbarrasderolagemhorizontalouverticalso
clicadoouumacaixaderolagemmovido.OparmetronDirectionespecificacomoousuriorolado
seocontedodeumcontrolodegrelhaouforma.Emseguida,elepassaalistaroseguintepossvel
valoresparanDirection:

Tabela6.1OsvalorespossveisparaoparmetronDirectionnomtodoroladadagrade

Valor Usurioroladautilizandose...
0 Setaparacima
1 Baixochavedeseta
2 barraderolagemverticalnareaacimadacaixaderolagem
3 barraderolagemverticalnareaabaixodacaixaderolagem
4 chaveSETAPARAAESQUERDA
5 SETAPARAADIREITA
6 barraderolagemhorizontalnareaesquerdadabarraderolagem
7 barraderolagemhorizontalnareadireitadopergaminho
Barra

Nspensamosquearefernciaa SETAPARAAESQUERDAe SETAPARAADIREITAchavesimplicaqueautilizao


teclasdocursorpararolaragradedisparahorizontalmenteoScrolledmtodoepassaumvalordequalquer
destes

170 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

4ou5paranDirection.Issono.Mesmoqueagradepodedeslocarcomoumresultadodousodestes
chaves,oseuenroladoeventonuncaacionado.OqueoarquivodeAjudaquisdizerquandoelefalousobre SETAPARAA
e SETAPARAADIREITAchavesfoi,defato,assetasesquerdaedireitanabarraderolagemhorizontal.
ESQUERDA
EstaarazoqueoAfterRowColChangemtododaclassegrdMLHeadercontm
asseguinteslinhasdecdigo:

Grade::AfterRowColChange(nColIndex)
This.RefreshHeaders()
NODEFAULT

AchaveparaafuncionalidadedestaclassedegrelhapodemserencontradasnasuaRefreshHeadersmtodo.
Estemtodoasseguraquecadacolunanapartevisveldagrelhatemoadequado
etiquetaposicionadacorretamenteacimaseucabealho:
lnColLOCAL,lcName,lnHdrLeft,lnHdrWidth

Thisform.LockScreen=.T.
Comisso

***PercorrercadacolunaecertifiquesedequeaesquerdadortuloeLargura
***Propriedadesestodefinidascorretamente
PARAlnCol=1a.ColumnCount
lcName="dHeader"+LTRIM(STR(lnCol))
COMEVAL("This.Parent."+LcName)
lnHdrWidth=This.Columns[lnCol].Width(2*This.nHdrMargin)
.Width=IIF(lnHdrWidth>0,lnHdrWidth,0)
lnHdrLeft=OBJTOCLIENT(This.Columns[lnCol].Controls[1],2)
***Seestamosemumrecipiente,descobrirodeslocamentodoformulrio
***Eajusteovalordeixado
IFUPPER(This.Parent.BaseClass)#"forma"
lnHdrLeft=lnHdrLeftOBJTOCLIENT(This.Parent,2)
FIMSE

Seacolunanoestnaporovisveldagrelha,aprimeirachamadapara OBJTOCLIENTretornos
zero.Seagradeestiveremumapginaouemoutrorecipiente,lnHdrLeftirconterumvalornegativo
apsasegundachamada.Portanto,selnHdrLeftmaiordoquezero,acolunacorrentedeveestarna
porovisveldagrelha:

***DefinirApenasaspropriedadesesquerdaevisveisseestacolunana
***Porovisveldagrelha.
IFlnHdrLeft>0
.Left=LnHdrLeft+This.nHdrMargin
.Visible=.T.

***Certificarsedequealarguranotransbordeovisvel
***Porodagrelha
IF.Left+.Width>This.nRight
lnHdrWidth=This.nRight.Left(2*This.nHdrMargin)
.Width=IIF(lnHdrWidth>0,lnHdrWidth,0)
FIMSE
OUTRO
.Visible=.F.

Captulo6:Grids:OscontrolesMisunderstood 171

FIMSE
ENDWITH
ENDFOR
ENDWITH
Thisform.LockScreen=.F.

AclassedegradecontmumoutromtodochamadoKeepHeadersVisible.Estemtodo,talcomoasua
nomeimplica,mantmasetiquetasqueflutuamacimadagrelhadecabealhosvisveisquandoagradeperde
foco.Semprequeagradeperdeofoco,oscabealhosdevriaslinhasdesaparecemporcausadagrade
cabealhosdepassarparaafrentedaordemzeocultarosrtulos.Anicamaneiraqueencontramosparamanter
queissoaconteafoiinvocandodagradeKeepHeadersVisiblemtodonoGotFocus
mtododecadaobjetonoformulrio,bemcomonaformadoLostFocus.Comodissemosanteriormente,o
maiorfuncionalidadedessaclassegradecarregaumpreoelevado.

Usandoaferramentadetextodedicaemvezdecabealhosdevriaslinhas
Umasoluosimplesparafornecerdescriesverbosoparacabealhosdecolunagradefornecerferramentas
dicasparaousurio.Istopodeserfeitorapidamente,emboracabealhosnotmum
ToolTipTextpropriedade.OcabealhopodefazerusodagradeToolTipText.Anicalinhade
cdigo,nocabealhoMouseMovemtodo,defineagradeToolTipTextadequadamente.Somente
lembresededefiniraformadoShowTipspropriedadecomoverdadeira,umavezquedefinidocomofalsoporpadro:

This.Parent.Parent.ToolTipText='Estaumadescriodocabealhomuitotempoparao
coluna'

Naturalmente,hsempreapossibilidadedequeumavezqueseuusuriosfinaisveressasdicasdeferramentabacana,
elesvoclamorparatlosemcadagradenaaplicao.Nessecaso,vocprovavelmente
quercriarumaclassedecabealhopersonalizadoquecontmocdigoparadefiniragradeToolTipTextpropriedade
nasuaMoverRatomtodo.fcildefinircabealhosdemercadorias,masquenopodeserfeitovisualmente.isto
temdeserdefinidacomocdigo:

DEFINECLASSHdrBaseASHeader

MouseMoveFUNO
LPARAMETERSnButton,nShift,nXCoord,nYCoord
Comisso
.Parent.Parent.ToolTipText=.Tag
ENDWITH
ENDFUNC

ENDDEFINE

Oltimorequisitoumconstrutordegradepersonalizadaque,entreoutrascoisas,automaticamente
substituioscabealhosclassebaseVisualFoxProcomseuscabealhospersonalizadosemtempodedesign.Depoisde
executaroconstrutor,vocpodecolocaroToolTipTextempropriedadetagdocabealhopersonalizado.Para
onossoconstrutordegradedeforaindustrial,verocaptulosobreferramentasdeprodutividadedodesenvolvedor.
172 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comopossoalteraraordemdeexibiodagrade?(Exemplo:
Ch06.VCX::grdSetOrder)
Comodecostume,aresposta"depende".OComboGridnoltimocaptuloutilizadoummenudeatalho
selecoparaalcanaresteobjetivo.Amesmafuncionalidadepodeserobtidaligandoumagradepersonalizado
mtodoapartirdocabealhoClick.Comonoexemploanterior,setodasassuasredesprecisameste
funcionalidadequevocdevemelhorarsuaclassedecabealhopersonalizado,adicionandoalgumcdigoparaseuClick
Mtodo.

Figura6.4Gradeitensexibidosemordempelopasapsclicarnocabealho

AquiestocdigoquevainocabealhoCliquemtodo:

COMThis.Parent
.Parent.SetOrder(JUSTEXT(.ControlSource))
ENDWITH

Humasuposioescondidaaquique,comons,seguemaconvenodedar
ndicenicocampodetagsomesmonomequeoscamposemquesebaseiam.oSetOrder
mtododestaclassedegrelha,quechamadoapartirdocabealhodeInstruesmtodo,dependedesta
serverdadeiro:

LPARAMETERStcTag

***Certifiquesedeumnomedemarcavlidafoiaprovada
ESE!VAZIO(tcTag)

***Certifiquesedequetemosoarquivoprocedimentocarregadoparaquepossamosacessaro
Captulo6:Grids:OscontrolesMisunderstood 173

funo***ISTAG()
SETPROCEDIMENTOPARACH06ADITIVO
Comisso
***CertifiquesedequerealmenteumamarcaparaRecordSourcedagrade
IFISTAG(tcTag,.RecordSource)

***Vemfrenteedefiniraordemparaatabela
SELECT(.RecordSource)
SETORDERTO(tcTag)
.SetFocus()
FIMSE
ENDWITH
FIMSE

Comofaoparacontrolarocursor?(Exemplo:NxtGridRow.scx)
Quandoousuriopressionao TABou ENTERparanavegarparaaprximaclula,opadrodagrade
comportamentoparapassarparaaprximacolunanamesmalinha.Vocpodeexigirsuagradesecomportar
umpoucodiferente,especialmenteseeleestsendousadoparaexibirclculosmatemticos.emboraum
gradenoumaplanilha,osusuriosfinaispodemacharmaisfcilparasabersesuascombinaesdeteclassecomportar
maneirafamiliar,talvezcomoMicrosoftExcel.umatarefasimplesdeconstruirredesquenavegam
deuma
verticalmenteemvezdehorizontalmentequandoousuriopressiona TABou ENTEReporquevocpode
crilacomoumaclasse,elestemqueserfeitoumavez.OtxtGrdNextRowclassedecaixadetextofornecida
comocdigodeexemploparaestecaptuloforneceessafuncionalidade.Eletemumnicomtodopersonalizado
chamadoMove2NextRowechamadoapartirdacaixadetextoKeyPressmtodoquandoo ENTERou
TABchavedetectado:

lnMaxRowsLOCAIS

lnMaxRows=INT((.Height.HeaderHeight
IIF(INLIST(.ScrollBars,1,3),SYSMETRIC(8),0))/.RowHeight)

COMThis.Parent.Parent
IFRelativeRow>=lnMaxRows

***Istosignificaqueestamosnaltimalinhanapartevisveldagrelha
***Entotemosquerolaragradedeumalinhaparabaixo

.DoScroll(1)
FIMSE
.ActivateCell(.RelativeRow+1,.RelativeColumn)
ENDWITH

Comofaoparaexibiraltimapginainteiradeumagrelha?(Exemplo:
EndofGrid.scx)
Deummodogeral,quandoumformulrioquecontmumagradeinstanciado,oprimeiroregistroexibidono
agradeoprimeiroregistroemseuOrigemDoRegistro.Obviamente,sevoctiverocdigonagradeInit
mtodoquemoveoponteirodoregistro,issonovaiserverdade.Mashsituaesem

174 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

qualdesejaexibirumagradetotalmentepreenchida,ondeoltimoregistrodisponvelexibidocomo
altimalinhadagrelha.Istopodeserfeito,masnoumexercciotrivial.
Naprimeiravocpodepensar"Oh,esteumpedaodeboloTudooquetenhoafazeralgocomoisto:"

Comisso
GOBOTTOMIN(.RecordSource)
SKIP<Nmerodelinhas1>EM(.RecordSource)
.SetFocus()
ENDWITH

Massevocrealmentetestarestaabordagem,vocvaidescobrirrapidamentequeelenoexecuta
corretamente.Mesmoqueagrelhaposicionadosobreafichacorrecta,estafichanomeio
dapginaevocdeveusaro PAGEDOWNteclaparaveroltimoregistro.Seesteumcomum
exignciadesuasgrades,estecdigodeexemplonaInitmtododeEndOfGrid.scxgenrico
epodeserfacilmentecolocadoemummtodopersonalizadodesuaclassedegrade:

lnKeyLOCAL,lnMaxRows,lcKeyField

***Certifiquesedearquivodeprocedimentocarregada
SETPROCEDIMENTOPARACh06.prgADITIVO
***Mostraraltimapginadagradequandooformulrioinstancia
IFDODEFAULT()
COMThisform.GrdCustomer

***Calculeonmeromximodelinhasporpginadegrade
lnMaxRows=INT((.Height.HeaderHeight
IIF(INLIST(.ScrollBars,1,3),SYSMETRIC(8),0))/.RowHeight)

***ObteronomedocampodechaveprimriaemRecordSourcedagrade
***GetPKFieldNameumafunodefinidanoarquivodeprocedimentoparaesta
***Captulo(Ch06.prg)
lcKeyField=GetPKFieldName(.RecordSource)

***Seachaveprimriaoucandidatodoprimeiroregistroaserexibido
***Naltimapginadagrelhadesdequeoobjetivoteragradepreenchida
***Quandooformulrioaberto
GOBOTTOMIN(.RecordSource)
Ignorar(lnMaxRows1)IN(.RecordSource)

***Salveachaveprimriaoucandidatodesteregistro,setiverum
ESE!VAZIO(lcKeyField)
lnKey=eval(.RecordSource+'.'+lcKeyField)
GOBOTTOMIN(.RecordSource)
.Refresh()

***Roleseumregistroatqueestamosnoquequeremos
DoWhile.T.
.ActivateCell(1,1)
IFEVAL(.RecordSource+'.'+LcKeyField)=lnKey
SADA
OUTRO
.DoScroll(0)
FIMSE
ENDDO

Captulo6:Grids:OscontrolesMisunderstood 175

FIMSE
ENDWITH
FIMSE

Comofaoparausarumagradeparaselecionarumaoumaislinhas?
(Exemplo:
SelGrid.scx)
Umagrademultiselectasoluoperfeitaquandovocdeveapresentaraousurioumalistagrandede
itensapartirdoqualpodemserfeitasvriasselees.Onicorequisitoqueatabelausada
comoagrelhaOrigemDosRegistosdeveterumcampolgicoquepodeserdefinidocomoverdadeiroquandoessalinha
selecionado.Seatabelabasenotemumcampolgico,umasimplesquestodefornecerumpor
quercriarumavisolocaldamesaouusandooparaconstruirumcursoratualizvel.Vejo
Captulo9paraobterdetalhessobrecomoconstruirumRecordSourceparaagradequecontmessaseleo
bandeira.

Figura6.5Multiselectgradeusandocaixasestilogrfico

Configurandoestagradetofcilquenorequernemmesmoumaclassedegradepersonalizada.Noexemplo
acima,nssimplesmentedeixoucairumadasnossasredesdeclassebase(CH06::grdBase)paraonossoformulrioe
acrescentoutrslinhasdecdigoaoseuSetGridmtodo:
DODEFAULT()

***Configurarparadestacarlinhastodososselecionados
This.SetAll('DynamicBackColor',
"IIF(lSelected,RGB(0,0,128),RGB(0,0,0))','COLUMN')
This.SetAll('DynamicBackColor',
"IIF(lSelected,RGB(0,255,255),RGB(255,255,255))','COLUMN')

176 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tudooquerestaadicionarumacaixadeseleoestilogrficoparaaprimeiracolunadagradeecolocardois
linhasdecdigoemseuClickmtodo:

DODEFAULT()
TECLADO'{DNARROW}'

Estecdigomoveocursorparaaprximalinhanagrade.Maisimportante,elecorrectamente
destacaalinhaatual,dependendoounoousurioselecionou.Istoporqueo
SETALLmtodoqueusadopararealaraslinhasselecionadas,nomudaaaparnciadagrade
atqueumaGrid.SetFocus()ouumGrid.Refresh()emitido.Constantementeatualizaragradeser
degradarodesempenhoemovendoseparaaprximalinharealizaomesmoobjetivoemarcas
agrelhamaisconvenienteparaoutilizadorfinal.

Comopossodaraminhagradecapacidadedepesquisamultiselectincrementais?
(Exemplo:Ch06.VCX::txtSearchGrid)
Tecnicamentefalando,issorealizadopelaquedadeumacaixadetextocompesquisaincremental
capacidadeemumaoumaiscolunasdagrade.Obviamente,qualquercolunacomestafuncionalidade
deve,pordefinio,sersdeleitura.Casocontrrio,outilizadorteriadeserconstantementemudarosdadoscomo
eleestavaprocurando!
Achaveparacriarumacaixadetextodepesquisaincrementalparausoemumagradeaadiodo
cSearchStringpropriedadeparamanteracadeiadepesquisaatual.Istoimplicaquetodasasteclasso
interceptadoepassadoparaummanipuladorpersonalizadokeystrokequeouusaachaveparaconstruiro
PesquisacordaoupassaloatocontroleKeyPressmtodoasertratadoporpadro.
(Teclasdenavegao,como TAB, ENTERe DNARROWpodesertratadocomoVisualFoxPronormalmente
lidacomessasteclas.)
Omanipuladordeteclastambmrequeralgunsmeiosdeimplementaodeum"timeout"condiesde
redefiniraseqnciadepesquisa.Apropriedadepersonalizada,nTimeOut,mantmonmeromximodesegundos
quepodedecorrerentreasteclasdigitadasantesdostemposdecontroleparaforaesuacSearchStringpropriedade
reposto.NstambmadicionamosotLastPresspropriedadepararealizaraltimavezqueumateclafoipressionada
Formatodedataehora.EssasduaspropriedadessousadospornossocostumeHandlekeymtodopara
realizaressatarefa.
NsdemosacaixadetextodeumsetTagmtodoqueincluiocdigoparaotimizarabuscausando
ndiceetiquetasseelesestiveremdisponveis.Eleexecutadoquandoocontroleinstanciado.Assumimos,comosempre,
quetodasasnicasmarcasdendicedecampotemomesmonomequeocampoemquesebaseiam.Isto
comoosetTagmtodoinicializapersonalizadadacaixadetextoCTAGpropriedade:

COMThis.Parent

***Seacolunaestligada,versehumamarcanoRecordSourcedagrade
***Quetemomesmonomequeocampodacolunaestligadaa
ESE!VAZIO(.ControlSource)

***Verifiqueseoarquivoprocedimentocarregada
SETPROCEDIMENTOPARACh06.PrgADITIVO
IFISTAG(JUSTEXT(.ControlSource),.Parent.RecordSource)
This.cTag=JUSTEXT(.ControlSource)
FIMSE
FIMSE
Captulo6:Grids:OscontrolesMisunderstood 177

ENDWITH

AmaiorpartedotrabalhofeitoemadocontroloHandleKeymtodo,quechamadoapartirdasua
PremirATeclamtodo.Seabatidadeteclatratadacomsucessoporestemtodo, .T.devolvidoao
oPremirATeclamtodo,quedepoisemiteum NODEFAULT.Seacombinaodeteclasnotratadoporeste
mtodo, ..FdevolvidoeopadroVisualFoxProKeyPresscomportamentoocorre:

LPARAMETERStnKeyCode

***Primeirodeverificaoparaversetemosumachavequepodemoslidarcom
***A'impresso'carter,backspaceou<DEL>sobonscandidatos
SEENTRE(tnKeyCode,32,128)outnKeyCode=7
Comisso

***Primeiroverifiquesetivermosesgotado
***Eredefiniraseqnciadepesquisa,setivermos
IFDATETIME().tLastPress>.nTimeOut
.cSearchString=''
FIMSE

***Entoagoralidarcomachave
DOCASO
CASEtnKeyCode=7

***Seatecladeletefoipressionado,redefiniraseqnciadepesquisa
***Eestgiosadaesquerda
.cSearchString=''
RETURN.T.
CASEtnKeyCode=127
***Backspace:Removeoltimocaracteredaseqnciadepesquisa
IFLEN(.cSearchString).1
.cSearchString=LEFT(.cSearchString,LEN(.cSearchString)1)
OUTRO
.cSearchString=''
RETURN.T.
FIMSE
DEOUTRAFORMA

***Umcarcterdeimpressovariedadedejardim
***Adicionlocadeiadepesquisa
.cSearchString=.cSearchString+CHR(tnKeyCode)
ENDCASE

***PesquisaparaovalormaisprximonaOrigemDoRegistrodagrade
.Pesquisa()

***ValordeAtualizaoparaKeyPresstemporizadordeintervalo
.tLastPress=DATETIME()
ENDWITH
OUTRO

***Noumachavequepodemanipular.VamosVFPlidarcomissoporpadro
This.cSearchString=''
RETURN.F.
FIMSE

178 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

APesquisamtodotentaencontraracorrespondnciamaisprximaparaacadeiadepesquisanagrade
OrigemDoRegistro.Senenhumacorrespondnciaforencontrada,elerestauraoponteirodoregistrodesuaposioatual:

LOCAISlnSelect,lnCurRec,lcAlias

***Guardarreadetrabalhoatual
lnSelect=SELECIONAR()

***ObterRecordSourcedagrade
lcAlias
=This.Parent.Parent.RecordSource

Thisform.LockScreen=.T.

***Pesquisaparaofechacorresponderstringdepesquisa
Comisso
***Salveoregistroatual
lnCurRec=RECNO(lcAlias)
ESE!VAZIO(.cTag)
***Useumamarcadendiceseexistir
SeSEEK(UPPER(.cSearchString),lcAlias,.cTag)
***Nofazernada...encontramosumregistro
OUTRO

***Restauraroponteirodoregistro
GOlnCurRecIN(lcAlias)
FIMSE
OUTRO

***SemTag...temqueusarLOCALIZAR
Seleccione(lcAlias)
LOCALIZARPARAUPPER(EVAL(JUSTEXT(.Parent.ControlSource)))=
UPPER(.cSearchString)
ESE!Encontrado()
GOlnCurRec
FIMSE
SELECT(lnSelect)
FIMSE
ENDWITH

Thisform.LockScreen=.F.

ComofaoparausarDynamicCurrentControl?(Exemplo:DCCGrid.scx)
Useessapropriedadeparaescolherqualdosvrioscontrolespossveisnaredenicacoluna
apresentadaaqualquermomento.Comooutraspropriedadesdinmicas,taiscomoDynamicBackColore
DynamicForeColor,vocpodeespecificarumacondioqueavaliadacadavezquearede
revigorado.

Captulo6:Grids:OscontrolesMisunderstood 179

Figura6.6UsandoDynamicCurrentControlparaexibirdiferentescontroles

EsteexemplousaDynamicCurrentControlparaativarseletivamenteaverificaodeestilogrfico
caixanaprimeiracolunadagrade.Estaanicamaneiradeconseguirissocomoutilizaro
colunaSetAllmtodoparaativarseletivamenteascaixasdeseleonofunciona.Estecdigo,na
gradeSetGridmtodo,fazcomquequalquercaixadeseleonacolunaparasetornardesativadoquandoum
tentativadedefinirofocoparaele:

This.collSelected.setall("Enabled",
IIF(UPPER(ALLTRIM(lv_Customer.Title))="proprietrio",.F,.T.).,
"Caixa")

ParaaproveitardacolunaDynamicCurrentControl,verifiqueseacoluna
contmtodososcontrolesparaserexibido.Paraqueissofuncione,acolunaDispersapropriedadedeve
tambmserdefinidocomofalso.Aprimeiracolunanagrelhaacimacontmdoiscontroles.Aprimeiraumabasede
caixadeseleoestilogrficoclasse.Osegundoumcostume"caixadedeficientesseleo"classe.Depoisde
adicionandooscontrolesparaacoluna,anicaexignciaestalinhadecdigonagradede
SetGridmtodo:

This.collSelected.DynamicCurrentControl=
"IIF(UPPER(ALLTRIM(lv_Customer.Title))="proprietrio",
'ChkDisabled','chkSelected')"

Quandovocexecutaroexemplo,vocvaiverquevocnopodeselecionarqualquerlinhaondeocontato
ttulo"proprietrio".

180 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comofaoparafiltrarocontedodeumagrelha?(Exemplo:FilterGrid.scx)
Hojeemdia,raroparaumaplicativoparaapresentarousuriocomtodososregistroscontidosemum
mesa.Namaioriadasvezes,umsubconjuntodosdadosdisponveisseleccionadocombaseemalgunscritrios.o
mtodotradicionalnoFoxProtemsidoautilizaodeumfiltro.Noentanto,umamidiaparafiltrardados
queestsendoexibidonagradeporqueasredesnopodeusarotimizaoRushmore.Defacto,adefiniodeumfiltro
naRecordSourcedesuagradeamaneiramaisrpidasabemosparatrazerasuacandidaturasua
joelhos.Almdisso,assimquevoccomearatrabalharcomdadosdeumbancodedadosbackend,estabelecendoum
filtronosequerumaopo.Vocdeveselecionarumsubconjuntodosdadosemumavisoouuma
cursoratualizvel.

Figura6.7filtradagradesusandocursoratualizvelevistacomparmetros

OcdigodepreencherosRecordSourcesparaasgradesfotoacimapodeserencontradoemsua
respectivosfiltrosmtodos.Areposiomtodoummtodomodeloquefoiadicionadonossabase
gradedeclasseparaestafinalidade.Umavezqueocontedodagradededetalhesdependedequallinhaa
ActiveRownagrelhadecategorias,eocontedodagradecategoriasdependedoque
seleccionadonacaixadecombinao,aResetGridsmtodofoiadicionadoaoformulrio.Omtodochamado
apartirdacaixadecombinaoVlidomtodoesimplesmentechamadecadagradeRedefinirmtodo.
ORecordSourcedagradedecategoriasumcursoratualizvel.Estecursor,csrCategory,
definidonoformulriodecargamtodousandoo CRIARCURSORcomando.Ocursor
preenchidanagradeRestaurarmtodopelo ZAPpinguecsrCategory, SELECIONEingoapropriado
registrosemumcursortemporrioe,emseguida,acrescentarosregistrosdocursortemporriaem
csrCategory.Restaurarummtodopersonalizadoqueestemnossaclassedegrelhaparapreencherdeformaconsistenteou
repreenchertodasasgradesusandoummtodocomum.AquiestocdigoapartirdagradecategoriasRepor
Mtodo:
Captulo6:Grids:OscontrolesMisunderstood 181

csrCategorySELECIONAR
ZAP
SELECT*apartirdecategorias
ONDECategories.Cat_No=This.Parent.cboSections.Value
INTOCURSORTempNOFILTER
csrCategorySELECIONAR
APPENDFROMDBF('Temp')
USOEMTemp
GOTOPINcsrCategory
This.nRecNo=1
This.Refresh()

Existemalgumasrazesparafazlocomoeste.Primeiro,podemosdefiniracategoriasgradeup
visualmentenodesignerformadesdeasuaRecordSourceexisteantesinstanciao.Mais
importanteofatodequeumagradenogostadeterseuOrigemDoRegistroarrancadodedebaixodela.
SeagrelhaOrigemDosRegistosforamactualizadospelo SELECIONARingparaelediretamente,eleapareceriacomoum
blankblobcinzanatela.Istoporqueo SELECCIONARfechaocursoreeficazmente
saidagradependuradonomeiodoar,porassimdizer. ZAPdepinglo,poroutrolado,noofaz.
UmamaneiradeevitarqueasuavezdegradeemumblobcinzaembrancoparadefiniroOrigemDoRegistropara
umacadeiavaziaantesdeexecutaro Selecte,emseguida,redefinilodepois.Emboraessavontade
trabalhonomaissimplesdoscasos,issonoumasoluorecomendamos.Enquantoelevaimantersuagrade
deperderasuamente,ascolunasdagradeaindaperderseusControlSourcesequalquerincorporado
controlos.Ento,issofuncionasesuagradeusacabealhosdeclassebase,caixasdetextoclassebase,eexibe
oscamposdocursorexactamentedamesmaordemqueelesso SELECCIONARed.Casocontrrio,voctem
paraescreverumcdigomuitomaispararestaurartodasascoisasqueseperdemquandoagradereinicializado.
Outramaneiradeindicarumsubconjuntofiltradoemumagradeusarumavistaparametrizadocomoseu
OrigemDoRegistro.Estaaformacomorealizadanagradededetalhes.Repormtodoutilizao
seguintecdigoparaalteraroqueexibido.Estemtodochamadoapartirdo
AfterRowColChangemtododagrelhacategoriasparamanterosdoisemsincronia:

vp_Cat_KeyLOCAL

vp_Cat_Key=csrCategory.Cat_Key
Requery('lv_Details')
GOTOPEMlv_Details
This.nRecNo=1
This.Refresh()

Opontodevistaaoqualestligadoestemambientededadosdoformulrioetemasua
NoDataOnLoadpropriedadedefinidaparatrue.Fazemosissoporquenosabemosquaisdetalhessero
exibidasnagradeinicialmenteenoqueremosqueVisualFoxProparasolicitaraousurioparaumaviso
parmetroquandooformulrioaberto.Paraobterinformaesmaisdetalhadassobrevistasparametrizadas,consulte
Captulo9.

182 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Assimquesobregrelhasdeentradadedados?(Exemplo:Ch06.VCX::grdDataEntry
eDataEntryGrid.scx)
Assimquesobreeles?Elesnosodefinitivamenteparaotmido.Sevoctentarforlosafazerascoisas
elesnosegurarbem,elesvoseroseupiorpesadelo!Porexemplo,emalgunscontabilidade
aplicaes,fazsentidoparafornecerumagradeparaentradadedados.Nestecaso,outilizadorfinal
provavelmentevaisermaisconfortvelusandoestetipodeinterfacedesdeamaioriadoscontabilistasparecem
amarplanilhas.Temossidocapazesdeusargrelhasdeentradadedadossemrasgaranossacabelo
oprocesso.Istoporquetemostidotempoparaentendercomoasredesfuncionametmencontrado
algumastcnicasquefuncionamdeformaconsistenteeconfivel.Estamoscompartilhandooscomvocparaoseu
experinciacomgrelhasdeentradadedadospodesermenosdolorosodoquepareceseramais.
Umapalavradecautelaaordemaqui.Sevocexaminarocdigoemnossaamostragradedeentradadedados
forma,vocvaificarimpressionadocomonmerodesoluesalternativas(kludges,sevocquiserserfranco
sobreele)necessriaparaimplementarafuncionalidadedentrodaprpriagrade.Samosnaamostraa
mostrarlhequeelepodeserfeito.Noentanto,vocpagaumpreoaltosevoctentarficarmuitobonitocom
suasgradesdeentradadedados.Omaisfuncionalidadetentarincluirnagrade,omais
problemasquevocterporcausadacomplexainteraoentreoseventosdegradeeosde
oscontrolescontidos.Porexemplo,sevoctiverocdigonaLostFocusmtododeumacaixadetexto
umacolunadegradequefazcomqueagradeBeforeRowColChangeeventoaofogo,enohcdigo
essemtodoquenodeveexecutarnestasituao,vocdeveusarumsinalizadorparadeterminarquando
deveserexecutado.Issopodeficarfeiomuitorapidamente.Mantenhaosimples,evocirmanteroseu
doresdecabeaaummnimo.

Comofaoparaadicionarnovosregistrosminharede?
OAllowAddNewpropriedadefoiadicionadaparaaredenoVisualFoxProverso5.0.quandoesta
propriedadedefinidacomotrue,umnovoregistroadicionadoredeautomaticamenteseousuriopressionaa
SETAPARABAIXOteclaenquantoocursorposicionadosobrealtimalinhadagrelha.Adefiniodessapropriedadepara
trueparaadicionarnovosregistrosparaagradenooideal,porquevocnotemcontrolesobrequandoecomo
registrossoadicionados.
Humpardemaneirasdiferentesdeadicionarnovosregistrosparaagrade.Nspreferimosusarum NOVO
botoaoladodagrade.Umbotodecomandoexibidaaoladodagradecomosubttulo"Nova
<Umacoisaououtra>"inequvoca.Mesmoumusuriofinalprincipiantepodedescobrirque,aoclicarem
umboto"Novo"acrescentaumnovorecordeparaarede(emboransfezmaravilhasealgumfaria
enganopensarquesignificava"NewGrid").VoctambmpodesimularoqueVisualFoxProfazquando
AllowAddNewdefinidocomoverdadeiro.Porexemplo,verificarparaverseousuriopressionara ENTER,TAB,ou
SETAPARABAIXOchavenaltimacolunadagradeeadicionarumregistroseocursorestiverposicionadonaltima
linhadagrelha.
Amaioriadosusuriosparecempreferiradicionarnovosregistrosparaofundodarede.Esteopadro
comportamentoquandodagradeOrigemDoRegistroexibidonaordemnatural.Noentanto,seagrade
RecordSourcetemumatagdendicedecontroleemvigor,oregistrorecmanexadoapareceno
partesuperiordagrade.porissoquenossocostumeAddNewRecordmtododaclassegradedeentradadedados
salvaaordematualedesligaosndicesantesdeadicionaronovoregistro.Depoisqueonovo
registrotemofoco,aordemoriginalrestaurado,deixandooregistrorecmanexadocomooltimo
umanagrade:

Captulo6:Grids:OscontrolesMisunderstood 183

lcOrderLOCAL,loColumn
Comisso

***Primeiroverificaoparaversetemosumaordemdendicedefinidonatabela
***Porquequeremosadicionaronovoregistroparaofundodarede
***Enonaordemdondice
lcOrder=ORDER(.RecordSource)
Thisform.LockScreen=.T.
SELECT(.RecordSource)
ORDERSETTO
AcrescentarnoBRANCO(.RecordSource)

***Descubraqualcolunaaprimeiracoluna
PARACADAloColumnEM.Columns
IFloColumn.ColumnOrder=1
loColumn.SetFocus()
SADA
FIMSE
ENDFOR

***Reporaordemanterior
ESE!VAZIO(lcOrder)
SETORDERTO(lcOrder)IN(.RecordSource)
FIMSE
.RefreshControls()
Thisform.Lockscreen=.F.
ENDWITH

EstemtodopodeserchamadoapartirdocostumeOnClickmtododeumbotodecomando,ouele
podeserchamadoapartirdacondicionalmentePremirATeclamtododecontrolocontidosnumacolunadegrade.
EstecdigonoLostFocusmtododacaixadetextonaltimacolunadagradepodeserusadopara
adicionarautomaticamenteumnovoregistonagrelhaquandoocursorposicionadosobreasualtimalinha.Levar
notadocdigoquedefineexplicitamenteofocoparaumobjetodiferentenoformulrio.Atentativadeadicionaruma
registroparaagrelhaOrigemDosRegistosquandoagradeoActiveControl,fazcomqueVisualFoxPropara
levantardeerro109("Recordemusoporoutro").

***VerifiqueparaverseTAB,ENTERouDNARROWfoipressionado
IFINLIST(LASTKEY(),9,13,24)
COMThis.Parent.Parent

***VerifiqueparaEOFporisso,seestamosnofinaldoarquivo,podemosadicionarumnovo
***TAB,EnterouDownArrowfoiatingido
registrose
SKIPIN(.RecordSource)
ESE!EOF(.RecordSource)
SKIP1IN(.RecordSource)
OUTRO

***Definirofocoemoutraparteparaevitarerro109'Recordemusoporoutro"
***Podemosassimdefinirofocoparaapginatemporariamente
***Almdisso,senodefinirofocoemoutrolugar,mesmoqueoAddNewRecord
***Mtodo,defato,adicionarumnovoregistro,ocursormoveseparaoprimeiro
***Colunadaltimalinhaenosemoverparaaprimeiracolunado
***Registrorecmadicionado.NstambmdevedefinirosinalizadorlAddingtovalidao
***Noocorrenoregistroantesqueelesejaexibidonagrade
.lAdding=.T.
.Parent.SetFocus()

184 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

.AddNewRecord()
.lAdding=.F.
NODEFAULT
FIMSE
ENDWITH
FIMSE

Umavezqueonovoregistrofoiadicionadoeousuriocomeaaedio,oquedeveacontecer?Ese
agradeexibidaemordemindexada,oregistrorecmadicionadodevesemoverparaoseucorrecto
posiologoqueocamporelevantepreenchida.Afimdeexibiroregistroemsuaadequada
posio,vocpodesimplesmentemoveroponteirodoregistro,movlodevolta,eatualizaragrade.Issofunciona
maspodeteralgunsefeitoscolateraisvisuaisdesagradveis.Umamelhorsoluopodeserencontradana
txtOrderGridclassedecaixadetexto.Elepodeserusadoemcolunasdegradequeestovinculadosaocampodechavede
tagdendicedecontroledagrade,afimdealteraraordemdeexibiodagrade,logoqueotexto
caixadeperdeofoco:

lnrecnoLOCAL

***SeRecordSourcedagradetemasuaordemdefinidaparaamarcadendice
***Nestecampo,nsqueremostercertezadequeassimquealteraroseucontedo,
***Ordemdeexibiodagraderefleteessamudana.
***Emprimeirolugar,verificarparaversensmudamosestecampo
IFINLIST(GETFLDSTATE(JUSTEXT(This.ControlSource),
This.Parent.Parent.RecordSource),2,4)
Thisform.LockScreen=.T.
COMThis.Parent.Parent
lnRecno=RECNO(.RecordSource)

***Vumapginaparacima
GOTOPIN(.RecordSource)
.DoScroll(2)

***Vparatrsumapginaparabaixo
GOBOTTOMIN(.RecordSource)
.DoScroll(3)

***Finalmente,volteparaoregistrooriginal
GOlnRecnoIN(.RecordSource)
ENDWITH
Thisform.LockScreen=.F.
FIMSE

Comopossolidarcomvalidaodenveldelinhanaminhagradedeentradadedados?
Comodecostume,hvriasmaneirasdelidarcomavalidaonvelrecorde.Seagradedeentradadedados
ligadoaumatabelaVisualFoxPro,umaregrapodeserdefinidonoDBC(vejaoCaptulo7paraobtermais
informaessobreasregrasdatabela).SeagrelhaOrigemDosRegistosumavista, DBSETPROP()podeserusadopara
definirumaregradenveldelinha.Qualquervezqueousuriotentamoverparaumalinhadiferentenagrade,o
regradisparaevalidaralinhaatual.Parecemuitosimples,no?Bem,noexatamente.
regrasdemesanofornecemumavalidaocompletadonveldelinhaemtodasassituaesecdigoaindaest
necessrioparaassegurarestavalidaorealizadasemprequenecessrio.Porexemplo,outilizadorpodesair
agradeefecheoformulrio,deixandoumregistroinvlidonogrelhaOrigemDosRegistos.Nestecaso,
Captulo6:Grids:OscontrolesMisunderstood 185

aregradatabelanodisparaporqueoponteirodoregistronosemoveu.Esevocdecidir
usarumcursoratualizvelcomooOrigemDosRegistosparaasuarede?Tecnicamentefalando,vocest
emseguida,cientificamenteforadesorte.
Nossaclassegradedeentradadedadoscontmcdigogenricoparalidarcomavalidaonvelrecorde.o
validaorealtratadonomtodomodelochamadoValidateCurrentRowqueadicionamos
anossaclassegradedeentradadedadosapenasparaestefim.Ocdigonestemtodoinstnciaespecfica
epodeserutilizadoparavalidaralinhacorrentenagradedeOrigemDoRegistromesmoquesejaum
cursoratualizvel.Sevocoptoupordefinirumaregradenvelderegistroparasuatabelaouexibio,o
mtodopodeserdeixadoembrancosemnenhumproblema.Oresultadoumaclassegenricadegradedeentradade
serusadocomqualquertipodeRecordSourceeexecutaravalidaodenveldelinhaquandonecessrio.o
dadosquepode
nicaexignciaqueagrelhaOrigemDosRegistosseratabelatamponada.
Ametodologiabsicautilizadaaquiparasalvaronmerodoregistrocorrentenarede
BeforeRowColChangemtodo.Ento,nasuaAfterRowColChangemtodo,estevalorguardado
emcomparaocomonmerodoregistroatual.Seforemdiferentes,ousuriofoimovidoparaumdiferente
linhanagrade.Nestecaso,oponteirodoregistromovidonovamenteparaoregistoqueoutilizadorapenas
esquerda,eocontedodesseregistrosovalidados.Seoregistroforvlido,omovimentopretendido
paraonovoregistodeixadaprosseguir.
Onicoproblemaquemoveroponteirodoregistrodeprogramaonagrade
RecordSourcefazcomqueasuaBeforeRowColChangeeventoparadisparar.porissoqueverificarparaversens
estnomeiodoprocessodevalidaonestemtodo:

Comisso
IF.lValidatingRow
NODEFAULT
OUTRO

***Salvenmerorecordeatualparaapropriedadegrade
.nRec2Validate=RECNO(.RecordSource)

***Estecdigotratacomdestaqueparaalinhaatual
SE!.lAbout2LeaveGrid
.nRecNo=0
FIMSE
FIMSE
ENDWITH

AgradelValidatingRowpropriedadedefinidacomoverdadeiraemsuaAfterRowColChangemtodoquando
comeaoprocessodevalidao.Aquiestocdigoqueiniciaoprocessoelidacoma
movimentoentrelinhasdegrade:

lnRec2GoToLOCAL
Comisso

***Senohnenhumregistroparavalidar,fasesadaesquerda
IF.nRec2Validate=0
RETORNA
FIMSE

***linhassalvaronmerodoregistroatual,casonsmudamos
lnRec2GoTo=RECNO(.RecordSource)

186 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
***Verifiqueparaversealinhafoialterado
IF.nRec2Validate#lnRec2GoTo

***Estamosvalidandoalinhaqueestamostentandosair...definirosinalizador
.lValidatingRow=.T.

***Retornoparaoregistro,apenasesquerda
GOTO.nRec2ValidateIN(.RecordSource)

***Seeleverificaparafora,deixeomovimentodousurioparaanovalinha
IF.ValidateCurrentRow()
GOTOlnRec2GoToIN(.RecordSource)
.RefreshControls()
FIMSE

***Terminoucomvalidao...redefinirbandeira
.lValidatingRow=.F.
FIMSE
ENDWITH

Porfim,adicioneumpoucodecdigoparaaclassegradedeentradadedadosVlidomtodo.Issoimpedequeo
usuriodedeixaragradesealinhaatualcontminformaesinvlidas:

***Certifiquesealinhaatualpermanecerealadoquandoofocodeixaagrade
This.LAbout2LeaveGrid=.T.

***Verifiquesealinhadegradeatualvlidaantesdesairdagrelha
ESE!This.ValidateCurrentRow()
RETURN0
FIMSE

OcdigonagradeValidateCurrentRowmtodoinstnciaespecfica.Umavezquechamado
semprequeoutilizadortentamoverparaforadalinhaatual,asalteraesaesteregistopodeser
comprometidaseelespassamvalidao.Noentanto,humpequenoproblemaquandoestemtodo
chamadoapartirdagradeValidmtodo.PorcausadagradevlidosincndiosantesdaValidda
CurrentControlnagrade,estemtodotambmdevegarantirqueaorigemdocontroledoativo
cluladagradefoiatualizadodeseuvalorantesdeeletentavalidaroregistroatual.
Tentarexplicaresteraciocniodifcil,porissoestamosindoparatentaresclarecerestausandoum
exemplo.
Suponhaqueumnovoregistrofoiadicionadoredeeasinformaesestosendoinseridos.
Depoisdeintroduzironmerodetelefone,ousurioclicanobotoFechardoformulrioparasair.Nisso
caso,dagradevlidosincndios,chamandoasuaValidateCurrentRowmtodo.Nesteponto,aValid
eventodacaixadetexto,vinculadoaocamponmerodetelefone,aindanofoiacionado.Portanto,otexto
caixanagradecontmovalorqueacaboudeserintroduzidopeloutilizador,masasuaorigemdocontrole(isto
onmerodetelefonenobufferderegistro)aindaestvazio.Atentativadeexecutaronvelrecorde
validao,nesteponto,antesdeforaraValiddacaixadetextoaofogo,produziria
resultadoserrados.Avalidaopoderapresentarcorrectamenteumamensageminformandoaousurioqueo
campodenmerodetelefonenopodeestarembrancomesmoqueousuriopodeverumnmerodetelefone
natela!
Paracuidardesseproblema,nsadicionamoscdigoparaaValidateCurrentRowmtodo,forando
aValidmtododeclulaativadagradeparadispararantesdetentarvalidaralinhaatual.

Captulo6:Grids:OscontrolesMisunderstood 187

Ocdigoaseguir,apartirdoformulriodeexemploValidateCurrentRowmtodo,ilustraa
tcnica:

lnRelativeColumnLOCAL

***Sneakyformadeatualizarfontededadosdobuffer
***Casocontrrio,seissochamadoapartirdarededevlidaquandoousurio
***Tentafecharoformulrioclicandonobotoprximooutentativas
***Paraativarapgina2,amensagemdeerroirdispararmesmosetivermosapenas
***Adicionouumnmerodetelefone,masnoporabasparaforadaclulaainda
Comisso
lnRelativeColumn=.RelativeColumn
Thisform.LockScreen=.T.
IFlnRelativeColumn=1
.ActivateCell(.RelativeRow,2)
OUTRO
.ActivateCell(.RelativeRow,1)
FIMSE
.ActivateCell(.RelativeRow,LnRelativeColumn)
Thisform.LockScreen=.F.
SELECT(.RecordSource)

***camposEmpresa,contatoetelefonesonecessrios
IFEMPTY(Company)ouvazio(Contato)ouvazio(Phone)
MESSAGEBOX('empresa,contatoetelefonesoobrigatrios.',48,
"Porfavor,corrijaaentrada')
RETURN.F.
OUTRO

***Tudovlido...vemfrenteeatualizarfontederegistrodagrade
SE!TABLEUPDATE(0,.F.,.RecordSource)
MESSAGEBOX('Problemaatualizaratabeladocliente',64,'SoSorry')
FIMSE
FIMSE
ENDWITH

Comofaoparaexcluirregistrosemminhagradedeentradadedados?
AgradeDeleteMarkpropriedadedeterminaseosinalizadordeexclusoexibidoparacadalinha
dagrelha.Quandoeleexibido,ousuriopodealternarostatusexcludodeumregistroclicandoem
oDeleteMark.Noentanto,permitindoqueosusuriosexcluirregistrosdestaformanoumaboaidia
porquenopermitirocontrolesobrequandoecomoosregistrossoexcludos.Umasoluomelhor
apresentaraousurioumbotodecomandoqueforneceessafuncionalidade.Umavezquenoexiste
resposta"certa",apresentamosduasabordagensnocdigodeexemplo.
Comoafirmadoanteriormente,ovolumedecdigoedoresdecabeasodirectamenteproporcionaisquantidadede
funcionalidadetentarimplementardentrodesuagradedeentradadedados.Istoespecialmenteverdadeiroquandovoc
permitirqueosusuriosparaexcluirerecuperarregistrosnagradeclicandoemseuDeleteMark.Issoporque
oDeleteRecordmtodoquetemosacrescentadoclassegrdDataEntryassumequeestsendo
chamadoapartirdeumobjectonoexteriordagrade.
Omaiorproblemaaoexcluirregistrosdegradeestfazendooregistrodesaparecerda
grade.Esteproblemaresolvidomuitofacilmente,movendooponteirodoregistronasgrades
RecordSourceeatualizaragrade,querchamandoexplicitamenteasuaActualizarmtodooupor

188 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

definindofocoparaele.Obviamente,paraqueissofuncione, DELETEDdeveserdefinido ON.Lembrar,


SETDELETEDumdeumalongalistadedefiniesquetemcomoescopoasessodedadosatual!este
cdigodaDeleteRecordmtododenossaclassegradedeentradadedadosilustracomofazera
suprimidoregistrodesaparecerdagrelhadepoisdeserexcludo:

loColumnLOCAL

***Verifiqueseousuriorealmentequerapagaroregistroatual
***ExibiobotesSimeNo,oconedopontodeexclamao
***Efazerosegundoboto(NO)obotopadro
IFMESSAGEBOX("VocestabsolutamentePOSITIVAMENTEsemdvidaCERTO'+
CHR(13)+'Vocdesejaexcluiresteregistro?',4+48+256,
"Voctemcerteza?")=6
Comisso

***Seestamosnoprocessodeadiodeumregistroedecidireliminlo
***Apenasrevertlo,emvez
IF'3'$GETFLDSTATE(1,.RecordSource)OR
'4'$GETFLDSTATE(1,.RecordSource)
TABLEREVERT(.F.,.RecordSource)
GOTOPIN(.RecordSource)
OUTRO
APAGARIN(.RecordSource)
SKIPIN(.RecordSource)
IFEOF()
GOBOTTOMIN(.RecordSource)
FIMSE
FIMSE

***Descubraqualcolunaaprimeiracoluna
PARACADAloColumnEM.Columns
IFloColumn.ColumnOrder=1
loColumn.SetFocus()
SADA
FIMSE
ENDFOR
ENDWITH
FIMSE

VocpodeobterumafuncionalidademelhoradaatravsdadefiniodagradeDeleteMarkpropriedadecomotrue
echamandoDeleteRecordapartirdagradeDeletedmtodo.muitomaisfcilparapermitirqueousurio
cancelarforadeumaoperaodeadio,semterquepassarportodaavalidaoqueocorre
quandoeletentacliquenobotoexcluir.Eletambmpermitequeousuriopararecuperarumregistroseeleexcludo
umporacidente.OK,entoqualadesvantagem?caroporquemaiscdigonecessrio.
IssotambmnoumaboasoluosedagradeRecordSourceestenvolvidoempersistente
relacionamentos.Recordandoeexclusoderegistrosnestasituaopoderiateralguminteressante
consequnciassevocestiverusandoogatilhosparamanteraintegridadereferencial.Aquiocdigodechamada
apartirdagradeDeletedmtodoqueexcluierecordaregistros:
LPARAMETERSnRecNo

llOK2ContinueLOCAL,loColumn
llOK2Continue=.T.
Comisso

Captulo6:Grids:OscontrolesMisunderstood 189

Antesdeagir,temosdeverificarquesoposicionadosnoregistroaserexcludo.Isto
possvelclicarnamarcadeexclusoemqualquerlinhadagrelha.Oponteirodoregistronagrade
RecordSourcenosemoveatqueoExcludosmtodofoiconcludo.Istosignificaque,neste
pontonotempo,possvelquenRecNo,oparmetropassadoparaoExcludosmtodo,noo
mesmoqueoRECNO()doregistroatual.Noentanto,moveroponteirodoregistro
incondicionalmenteanRecNoprovocaAfterRowColChangedagradeparadisparar.Definirofocoparao
gradeposteriormenteparaatualizlafazcomqueagradedaValidaofogo.Ambosesteseventoscausaronveldelinha
validaoaterlugar.Seousurioesttentandoexcluirumregistrodequeeleapenasadicionadoporengano,ns
Noqueroessavalidaoparaocorrer.Nsapenasqueremosreverteroregistro.Esparatornarascoisas
interessante,onmeroderegistrodoregistrorecmanexadoumnmeronegativo,enquanto
nRecNopositivo:

SELECIONECust_IDdoClienteONDEnRecNo=RECNO()INTOCURSORTemp
IF_TALLY>0

***Noomesmoregistro...assimquemovaoponteirodoregistro.
IFTemp.Cust_ID#customer.cust_id

***Certifiquesedequenoestamosnomeiodaadiodeumregistroetentar
***Apagarourecordarumemumdiferente
IF.ValidateCurrentRow()
.Parent.SetFocus()
GOnRecNoIN(.RecordSource)
.SetFocus()
OUTRO
llOK2Continue=.F.
FIMSE
FIMSE
FIMSE

***Umavezqueoregistronaverdadenoaindaexcluda
***Istoirfuncionarparadecidirseestamosrealmenterecordandoumregistro
IFllOK2Continue
IFDELETED(.RecordSource)
RECALLIN(.RecordSource)

***Moverponteirodoregistroparaatualizargrade
SKIPIN(.RecordSource)
SKIP1IN(.RecordSource)
OUTRO

***Verifiqueaquiparaverseestvamosnomeiodeadicionaresteregistro

***Quandosevirouedecidiuexcluloemseulugar.
***Nestecaso,bastareverterosuplementoparaevitarviolaesdePKmaistarde
***Sedecidirrecuperlo
IF'3'$GETFLDSTATE(1,.RecordSource)OR
'4'$GETFLDSTATE(1,.RecordSource)
TABLEREVERT(.F.,.RecordSource)
GOTOPIN(.RecordSource)
OUTRO
APAGARIN(.RecordSource)

***DevefazerumTableUpdateassimqueoregistroexcludo.
***Casocontrrio,quando,recordese,vocvaiterumaviolaoPK
190 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ESE!TABLEUPDATE(0,.F.,.RecordSource)
MESSAGEBOX('NofoipossvelatualizaratabelaCliente',48,'SoSorry!')
FIMSE

***Necessidadedemoveroponteirodoregistroparaatualizarexibio
SKIPIN(.RecordSource)
IFEOF(.RecordSource)
GOBOTTOMIN(.RecordSource)
FIMSE
FIMSE
FIMSE

***Actualizaragrelha,definindofocoparaele
***Descubraqualcolunaaprimeiracoluna
PARACADAloColumnEM.Columns
IFloColumn.ColumnOrder=1
loColumn.SetFocus()
SADA
FIMSE
ENDFOR
FIMSE
ENDWITH

Comofaoparaadicionarumacaixadecombinaominhagrade?(Exemplo:cboGrid::
cboInGrid.scx)
Ch06.vcxe
Amecnicadeadicionarumacaixadecombinaoparaumagradesoexatamenteomesmoquequalqueroutrocontrole.
Noentanto,umacaixadecombinaobastantecomplexaemseuprpriodireito(verCaptulo5paraobterdetalhesdecaixa
eintegrarasuafuncionalidadenativacomumagradepodesercomplicado.Omaiorproblemaenvolve
decombinao)
ligaodacolunadegradeparaumachaveestrangeiraemseuOrigemDoRegistroaoexibirodescritivo
textoassociadoaele.questessecundriasincluemcontrolaraaparnciadagradee
proporcionandonavegaopeloteclado.Estaseoapresentaumasoluoeleganteaestasquestes.o
cdigodeexemploincludonestecaptuloilustraessasoluousandoumdropdowndecombinao
(TipodeNegcio),bemcomoumalistasuspensa(Locais).

Captulo6:Grids:OscontrolesMisunderstood 191
Figura6.8Caixadecombinaoemumagrade

Aabordagemmaiscomumusadoparaadicionarumacaixadecombinaoaumagradedefiniro
colunaDispersapropriedadeparafalse.Enquantoissocuidadoproblemadeexibir
textodescritivoquandoacolunaestvinculadaaumvalordechaveestrangeira,noumaboasoluo.
Quandocaixasdecombinaosoexibidosemcadalinha,aredeparececonfuso.Apesarde
aparnciadesagradvel(verFigura6.9abaixo),humaGotcha!associadasaousodesse
tcnicaparagerenciarcombosdentrogrades.DacombinaoDisplayValuepodesertruncado
porqueopadroMscaraDeIntroduoparaacolunadagradecalculadacombasenalarguradasua
ControlSource.Felizmente,asoluosimples.BastaespecificarumInputMaskparao
colunalargaosuficienteparaacomodarocomboDisplayValue.Infelizmente,noh
maneirafcildecolocaressafuncionalidadeemumaclasse,porissomaisumatarefaquedeveserrealizadaem
onveldeinstncia.

192 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura6.9Combosemcadalinhaaparecemdesordenado

Quandoumacaixadecombinaonecessriaemumagrade,queseligamagradeparaumaexibiolocalouum
cursor.Temoscertezadeotextodescritivoassociadocomachaveestrangeiraestpresentenavista
atualizvel
ouocursorparaquepossamosvincularacolunaparaque,emvez.Vocpodeseperguntarcomonsatualizamoso
valordechaveestrangeiranagradeOrigemDoRegistro.Nsusamosumaclassecaixadecombinaoespecialdestinadaa
abordarestaquesto.Ocdigogenrico,demodoquepodeserimplementadacompoucosobrecargaadicional.
Hapenasalgumaspropriedadesodesenvolvedordevedefinir.
DacombinaocFkFieldpropriedadecontmonomedocampodechaveestrangeiranagradede
OrigemDosRegistosqueestassociadacomotextodescritivoligadocoluna.suanFkColumn
propriedadeespecificaonmerodacolunaquecontmovalordachave.OopcionallAllowAddNew
propriedade,quandodefinidocomoverdadeiro,permiteaousurioadicionarentradasdacombinaoOrigemDaLinhana
mosca.
Nsadicionamosquatromtodospersonalizadosparaanossarededeclassedecaixadecombinao:ProcessSelection,
UpdateGridRecordSource,AddNewEntryeHandleKey.AcombinaodeProcessSelection
mtodo,chamadodeseuValidmtodo,chamaseuUpdateGridRecordSourcemtodoquandoousurio
seleccionaumnovovalorapartirdacombinao.Seovalordacombinaonofoialterada,nohnecessidadede
atualizardagradeRecordSourceesujaosbuffers.Estemtodotambminvocao
AddNewEntrymtodoquandoapropriado.AddNewEntryummtododemodeloecdigoparainserir
umregistronatabeladepesquisadeveseradicionadoaonvelexemplo,quandoousurioestautorizadoa
adicionarnovasentradasnamosca.TodaessaatividadecoordenadanoseguinteProcessSelection
Mtodo:

Comisso

***Verifiqueparaversensselecionamosumaentradavlidanocombo

Captulo6:Grids:OscontrolesMisunderstood 193

IF.ListIndex>0

***Sensnomudaramosvalores,noatualizarOrigemDoRegistrodagrade
***Nsnoqueremossujarosbufferssenadamudou
IF.uOriginalValue#.Value
.UpdateGridRecordSource()
FIMSE
OUTRO

***Seno,vejasedigitoualgonacaixadecombinao
***Quenoestnalista
ESE!VAZIO(.DisplayValue)

***AdicionaranovaentradaparaOrigemDaLinhadocombinao
***Seestamospermitindoqueousurioadicionarnovasentradasnamosca
IF.lAllowAddNew
.AddNewEntry()
OUTRO
MESSAGEBOX('Porfavor,selecioneumaentradavlidanalista',48,
"Seleoinvlida')
.Value=.uOriginalValue
FIMSE
FIMSE
FIMSE
ENDWITH

OUpdateGridRecordSourcemtodosubstituiachaveestrangeiranagrelhade
OrigemDoRegistrocomachaveprimrianadecombinaoOrigemDaLinha.Porqueitensnacombinaode
listainternasempresoarmazenadoscomodadosdecaracteres,precisoprimeiroconverteroitemdalistaparao
tipodedadosusandooStr2ExpfunointroduzidanoCaptulo2:
correcto
LOCALlcField,lcTable

IF!EMPTY(.cFKField)E!VAZIO(.nFKColumn)
lcTable=IIF(VAZIO(.cPrimaryTable),
.Parent.Parent.RecordSource,.cPrimaryTable)
IFEMPTY(lcTable)
CAIXADEMENSAGEM
("VocdevedefinirtantoThis.cPrimaryTableOURecordSourcedagrade!",
16,'Errodesenvolvedor!')
OUTRO
lcField=lcTable+"."+.cFKField
REPLACE(.cFKField)COM
Str2Exp(.List[.ListIndex,.nFKColumn],
TYPE(lcField))IN(lcTable)
FIMSE
FIMSE

Queoutrasfuncionalidadesespeciaisumacaixadecombinaodeveterquandodentrodeumagrade?Nspensamos
os SETAPARACIMAe SETAPARABAIXOteclasdevepermitiraousurionavegarnagradequandoo
combofechado,masdevetambmpermitiraoutilizadorpercorreralistaquandoeledescartado.o
personalizadodecombinaoHandleKeymtodochamadoapartirdoseuKeyPressmtodoparaforneceressa
funcionalidade:
194 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

LPARAMETERSnKeyCode
lnMaxRowsLOCAIS,llRetVal

Comisso

***SeEscapeouEnterpressionado,alistanocaiumais
IFnKeyCode=27ORnKeyCode=13
.lDroppedDown=.F.
FIMSE

***Sealistanodescartadoparabaixo,atravessaragradecomasteclasdocursor
SE!.lDroppedDown
COM.Parent.Parent

***Calcularonmeromximodelinhasnaporovisveldagrelha
lnMaxRows=INT((.Height.HeaderHeight
IIF(INLIST(.ScrollBars,1,3),SYSMETRIC(8),0))/.RowHeight)

***Movaseumalinhanagrade
IFnKeyCode=5THEN

***Seestamosnalinhasuperiornapartevisveldagrade,
***Roleagradeatumalinhanocasodehaverumregistroanterior

IF.RelativeRow=1
.DoScroll(0)
FIMSE
.ActivateCell(.RelativeRow1,.RelativeColumn)
FIMSE
***VamosKeyPresssabemosquetmtratadoopressionamentodeteclas
llRetVal=.T.
OUTRO

***Seestamosnalinhadebaixonapartevisveldagrade,
***Roleagradeparabaixoumalinhaemcasodehaverumprximodisco

IFnKeyCode=24THEN
IF.RelativeRow>=lnMaxRows
.DoScroll(1)
FIMSE
.ActivateCell(.RelativeRow+1,.RelativeColumn)
llRetVal=.T.
FIMSE
FIMSE
ENDWITH
FIMSE
ENDWITH

RETURNllRetVal

Existealgumacoisaquepodemosquererumacaixadecombinaoemumagradedefazer?umabvia
melhoriafazercomquecadalinhadegradeexibirumconjuntodiferentedevalores.Tomemos,porexemplo,o
graderetratadonaFigura6.8.possvelparacadaclientetervrioslocais.Seatela
imobilirioestemumprmio,esseslocaispodemserexibidosemumacaixadecombinao.Bastacriaruma
vistalocalparametrizadodelocaisdecliente.AjustedacaixadecombinaoRowSourceTypea6
CamposeselecionaroscamposnecessriosparadacaixadecombinaoOrigemDaLinha.Umcdigopouconocombo

Captulo6:Grids:OscontrolesMisunderstood 195

dacaixadeGotFocusmtodoalteraocontedodasuaOrigemDaLinhaparaexibiracorreta
informaesparacadalinhadegrade:

lcGridAlias
LOCAIS,vp_cl_key

DODEFAULT()
Comisso
***RepetirConsultaoslocaisvisualizarparaobtertodososlocaispara
***Oclienteexibidosnalinhadegradeatual
COM.Parent.Parent
.nRecNo=RECNO(.RecordSource)
lcGridAlias
=.RecordSource

ENDWITH
vp_cl_Key=&lcGridAlias..Cl_Key
REQUERY('lv_location')

***Atualizeacombinao
.Requery()
.Refresh()
ENDWITH

Concluso
gradesesperoqueagorasoumpoucomenosmalentendidoquequandovoccomeounestecaptulo.Ns
nopodeesperarparafornecertodasasrespostas,mastentaramofereceromaiornmerodeindicaesesugestescomo
posso.
ns

196 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo7:Trabalhandocomdados 197

Captulo7
Trabalhandocomdados
"umerrocapitalteorizarantesumtemdados."
("TheAdventuresofSherlockHolmes",deSirArthurConanDoyle)

VisualFoxPro,emprimeirolugar,umsistemadegerenciamentodebancodedadosrelacional(RDBMS).
sempreteveomotordedadosmaisrpidoemaispoderosodisponvelemumaplataformaPC.
isto
Noentanto,comotodasaspoderosasferramentasdedesenvolvimento,VisualFoxProaindapoderevelar
vocnofizerascoisasdamaneiraqueespera.Nestecaptulovamosabordaralgunsdos
sedifcilse
tcnicasedicasqueaprendemosaotrabalharcomdadosemVisualFoxPro.

TabelasnoVisualFoxPro

algunsprincpios
AunidadebsicadearmazenamentodedadosnoVisualFoxProaindao'DBFarquivo',eseuassociado'FPT'
arquivo(campomemo).EssesarquivostmassuasrazesnahistriadalinguagemxBaseesua
formatoaindareconhecidacomoumadasestruturaspadroemmuitasaplicaes.OarquivoDBF
formatodefineumrecordeemtermosdeumasriedecamposdecomprimentofixocujotipodedadostambm
definiram.Nanomenclaturapadroqueagoraconsiderado,oscampossoreferidoscomoo
'Colunas'eregistroscomoas'linhas',enquantooarquivoDBFemsia"mesa.'
TabelasnoVisualFoxPrososemprearmazenadoscomoarquivosindividuais(aocontrriodoMicrosoftAccess,
exemplo,ondeexistemastabelassomentedentrodobancodedados[.MDBarquivo])epodeexistirquercomo
para
"Livretabelas"ouser"ligada"aumcontinerbancodedados.Umatabelaspodeserligadoaumanica
continerbancodedadosaqualquermomentoe,aomesmotempoqueestvinculadoaumcontinerbancodedados,
atributosefuncionalidadesadicionaisquenoestodisponveisquandolivre(vejaaseosobre
ganhaacessoa
orecipientedebancodedadosnestecaptulo,paramaisdetalhes).Noentanto,unvinculativoumatabeladeum
continerbancodedadosfazcomqueaperdadefinitivadessesatributosepoderesultaremgrande
problemasseissoaconteceemumambientedeaplicao.
AlinguagemVisualFoxProtemmuitoscomandosefunes,queestopreocupados
comacriao,modificaoegestodetabelas(eseusprimosprximos,cursorese
Visualizaes).Parte2doGuiadoProgramadorVisualFoxPro(captulos5a8)dedicado
trabalharcomdadoseabrangeosconceitosbsicosmuitobem.Informaesadicionaissobreomodocomoo
gestodedadosindividualcomandosrealmentetrabalhopodeserencontradoem'TheHackersGuideto
VisualFoxPro6.0'(GranoreRoche,HentzenwerkePublishing,1998).

Comoabriratabelaespecficaquedesejausar
Aotrabalharcomodesignerdeformulriovisual,nohnenhumproblemarealsobreaidentificaodeuma
mesa.Bastaselecionaramesaatravsdodilogo'Adicionar'chamadoapartirdedadosdoformulrio
meioAmbiente.Noentanto,quandovocprecisaparasereferiraumatabelaprogramaticamente,ascoisassomais
difcil.
198 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Obsico USE<table>comandoirabriraprimeiratabelacomonomeespecificadoque
encontra,deacordocomasseguintesregras:

Seumbancodedadosestaberto,edefinidocomoobancodedadosatual,eleprocuradoemprimeirolugar.
Senenhumbancodedadosestiveraberto,ounenhumadefinidacomoatual,oFoxProcaminhodepesquisanormal
usava

Istotemalgumasimplicaesparaoprogramador.Seumatabelacomomesmonomeexisteno
maisdeumbancodedados,vocdeveincluirumarefernciaaobancodedadosaoabriressatabela.
Ocdigoaseguirmostracomoissofunciona:

FECHETUDO
AbrirbancodedadosC:\VFP60\CH03\CH03
?SET('bancodedados')
&&Retorna"CH03'
AbrirbancodedadosC:\VFP60\TIPSBOOK\DATA\tipsbook
?SET('bancodedados')
&&Retorna"TIPSBOOK'
Osclientesusam &&Erroarquivonoexiste!
CH03usar!clientes &&Abreatabelacorreta

Bytheway,notarqueabrirumbancodedadostambmestabelececomoobancodedadosatual!Observetambm
queaaberturadevriosbancosdedadosfazcomquealtimapessoaaserabertoatual.Issoprecisaassistir
aoacessarprocedimentosarmazenadosouutilizarfunesqueoperamsobreomomentodebancodedadosdefinida
(porexemploDBGETPROP())
Noentanto,seobancodedadosnoestiveraberto,enoestnocaminhodeprocuracorrente,emseguida,
aindaespecificarabasededadosnoirsersuficiente.Vocvaiprecisardocaminhocompletotambm.Assim,a
estarcertodeabriro'clientestabela'nonosso"CH03bancodedados",precisamosusarumcomando
comoisso:

FECHETUDO
AbrirbancodedadosC:\VFP60\TIPSBOOK\DATA\tipsbook
?SET('bancodedados') &&Retorna"Tipsbook'
Osclientesusam &&Erroarquivonoexiste!
CH03usar!clientes &&Erroarquivonoexiste
USOC:VFP60\CH03\CH03clientes&&Abreatabelacorreta

Estasregrasdebuscatambmsignificaque,seumnomedetabelausadaduasvezes,umavezparaumamesaemum
continerbancodedadosenovamenteparaumamesalivre,emseguida,abriratabelalivreapresentaumproblema
aberto
amenosquevocespecifiqueumcaminhohardcodedcomoparteda USEcomando.Bytheway,notemos
recomendaessaprtica,realmentemconcepo.Simplesmentenohnenhummecanismo,comexcepo
usandoumcaminhoexplcito,paradizerVisualFoxProqueatabelaqueestsendosolicitadoumamesalivree
VisualFoxProirsempreprocurarorecipientedebancodedadosabertopelaprimeiravez.Anicasoluoquens
encontreiparaesteproblemaparasalvaraconfiguraodebancodedadosatual,emseguida,fecheobancodedados,aberta
atabelalivree,finalmente,restauraraconfiguraodebancodedados,comoeste:

lcDBC=SET('bancodedados')
SETDATABASETO
USE<nomedatabelalivre>
SETDATABASETO(lcDBC)

Captulo7:Trabalhandocomdados 199

Comoparaobteraestruturadeumatabela
Aintroduodocontinerbancodedados,finalmente,permitiunosautilizarnomesdecampolongasemVisual
FoxPro(at128caracteres,emboraaidadede10limitedecaracterescontinuaaseraplicvellivre
tabelas).Enquantoissononecessariamenteumacoisaboa(afinaldecontas,nstambmtemostantoumapropriedade
eumComentrioparacamposemtabelasencadernados!)ousodenomesdecamposlongosprovoupopular
legenda
commuitaspessoas.OgrandeproblemaqueovelhoFoxProcomandosqueaestruturadelistadatabelatm
Nopegomesmonaverso6.0a.Ambosos LISTe EXIBIOESTRUTURAcomandosso
limitadoa12desadapersonagemparalevandoaexibeirritantescomooseguinte:

Estruturaparaatabela:
C:\VFP60\CH07\JUNK.DBF
Nmeroderegistrosdedados:0
Datadaltimaatualizao:
1999/02/10
Pginadecdigo: 1252
NomedocampoCampo Digitar Largura dezembro
ndice AgruparNulos
1THISISALONGF..Character 10 No
2THISISALONGF..Character 10 No
**Total** 21

Vocpodeusaro ESTRUTURACOPYESTENDIDAPARA<table>comandoparaobteraplena
estruturadatabela,masissocriaproblemas.Primeiro,vocdeveenviarosresultadosparaumatabela
oquesignificaquevoctemqueselembrardeapagaratabelaquandoterminar.Emsegundolugar,aproduo
tabelausacamposdememorandoparamuitosdosdadosparaquevoctambmtemumFPTarquivoparalidarcom,e
fazaanlisedasinformaesmaisdifcil.Avantagemquefcildemodificaro
este
estruturarevocpodeusaratabelaasadadiretamenteparacriarumanovatabela.
Noentanto,paraobterumalistagemsimples,amelhorsoluousarosAFIELDSfunction()
(Queteronomedecampocompleto)eparaescreverumapequenafunoparasubstituiroantigo,eagora
,listagemdaestruturacomandosinadequados.Umexemplodeumatalfunoestincludana
cdigodeexemploparaestecaptulo(vejagetStru1.prg)queproduz,paraamesmatabela,asada
abaixo,escrevendoumarquivodetextoe,emseguida,abriroarquivoemum MODIFYFILEjanela.(Claro
agoravoctemumarquivodetextoparaselivrardemasisso,emnossaopinio,menosdeumincmododoqueuma
menosprovveldecausarpreocupaodoqueaexclusodeDBFeFPTarquivosdeseudiretriodedados):
mesae

EstruturaPara:C:\VFP60\CH07\JUNK.DBF
=====================================
Nomelongo:umnomedetabelalongospodemserusados
aqui

Comente: Estaumatabeladelixoparailustrarousodelongosnomesdecampo

Definiesdecampo
=================
THISISALONGFIELDNAME C(10,0)NOTNULL
Padro:"algumacoisa"
(Mensagemdeerro:VFPPadro)
Valid:.NOT.EMPTY(thisisalongfieldname)
(Mensagemdeerro:"Estecamponopodeserdeixadoembranco")
THISISALONGFIELDNAMETHATISDIFFERENTC(10,0)NOTNULL

Noentanto,hmuitomaisinformaesqueseriamteisemumperfil.Porexemplo,
onomedoDBCapartirdoqualamesavemseriatil,comoseriaonomedealgum

200 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

arquivosassociados.Maisimportanteaindaseriamuitobomsaberoquendicesforamdefinidospara
atabelatambm.Asegundavariante(GetStru2.prg)produzoseguinteresultado:

EstruturaPara:C:\VFP60\CH07\JUNK.DBF
=====================================
DBC :CH07.DBC
CDX :JUNK.CDX
Memo:NoFileMemo

ndicesassociados
==================
F02REG:THISISALONGFIELDNAMETHATISDIFFERENT
ISDEL:DELETED()
(Candidato):F03CAN:THISISALONGFIELDNAME+THISISALONGFIELDNAMETHATISDIFFERENT
***PRIMRIACHAVE:F01PRIME:THISISALONGFIELDNAME

Informaesdatabela
=================
Nomelongo:umnomedetabelalongospodemserusados
aqui

Comentrio:Estaumatabeladelixoparailustrarousodelongosnomesdecampo
NenhumaregraTabela
EmInserir:on_insert()
EmUpdate:on_update()
EmExcluir:on_delete()

campoDetalhes
=============
THISISALONGFIELDNAME
Padro:"algumacoisa" C(10,0) NONULO
(Mensagemdeerro:VFPPadro)
Valid:.NOT.EMPTY(thisisalongfieldname)
(Mensagemdeerro:"Estecamponopodeserdeixadoembranco")
THISISALONGFIELDNAMETHATISDIFFERENTC(10,0) NONULO

Estafunopodeserchamadoemumpardeformas.Emprimeirolugarsemparmetros,emcujocaso
tabelaselecionadanomomento(sehouver)assumido.Estemtodoirtrabalharcomambos
cursoresepontosdevista,almdemesas!Emsegundolugar,vocpodepassarumARQUIVOnome(incluiro
extenso,senosimplesmenteo'defaultDBF')eelevaitentarencontraroarquivo,abraseno
jaberta,volteaestruturae,emseguida,fecharqualquertabelaqueseabriu.Finalmente,vocpode
chamlodeformainterativausando:
GetStru2(GETFILE())

Queirabrirodilogolocaldoarquivoparavoctambm.

Comoparacompararasestruturasdeduastabelas?
svezesnecessriosaberseduastabelassorealmenteidnticoemestrutura
especialmentequandovocestcopiandoosdadosusandoo APPENDFROMcomandoquefuncionaem
camposquesonomeadosomesmoindependentementedoseutipodedadosoutamanho.Talvezestranhamenteparaum
sistemadebancodedados,VisualFoxPronotemnenhumamaneiradiretadecompararaestruturado
duasmesas,porissotemosdecriaranossaprpria.Oprogramaaseguir(CompStru.prg)fazexatamente
Istoenaformaaquiapresentadaretornaumvalorlgicosimplesindicandoseounoa

Captulo7:Trabalhandocomdados 201

duastabelassorealmenteidnticos.Noentanto,seriaumaquestosimplesparafazerestafuno
exibirumalistadoscamposincompatveisseissofossenecessrio.
EstafunodeveserchamadocomdoisARQUIVOnomes.ApenasdepassagemnoALIASnomesno
suficiente,porquevamosquererusaro ARQUIVO()funoparadeterminarseofsico
arquivoexisteepodeserencontrado.Nopodemosassumirquetodososarquivosrealmenteterum"DBF"
extenso.(Paraumexemplodeforarumaextensovero"programaGetStru2"neste
Cdigodocaptulo).:

**********************************************************************
*Programa :CompStru
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Comparaaestruturadeduastabelas
**********************************************************************
LPARAMETERStcFile1,tcFile2
laFieldsarraylocal[1]
LOCALlnSelect,lnCnt,lcFile,llRetVal

***Serquetemosdoisparmetros
SENO((VARTYPE(tcFile1)="C"EVAZIO(tcFile1)!)
E(VARTYPE(tcFile2)="C"E!VAZIO(tcFile2)))
ERROR"9000:DevepassarpordoisnomesdearquivosvlidosparaCompStru()"
RETURN.F.
FIMSE

***Verifiqueosparmetrosparaverseexistemarquivosespecificados
SENO(FILE(tcFile1)efile(tcFile2))
ERROR"9000:DevepassarpordoisnomesdearquivosvlidosparaCompStru()"
RETURN.F.
FIMSE

***Agora,verifiqueseelessoambasastabelasutilizveis
***(ISDBF()umafunonesteprograma)
ESE!ISDBF(tcFile1)
ERROR"9000:File"+tcFile1+"noumatabelaFoxProutilizvel"
RETURN.F.
FIMSE
ESE!ISDBF(tcFile2)
ERROR"9000:File"+tcFile2+"noumatabelaFoxProutilizvel"
RETURN.F.
FIMSE

***Guardarreadetrabalhoatual
lnSelect=SELECIONAR()
Selecionar0

***Criarumcursortemporrioparacompararestruturas
CRIARCURSORtmpstru(
arqC(10),ftypeC(1),FlenN(3,0),FDeCN(3,0),fnulL(1))

***Abraosarquivosparacomparareobterassuasestruturasparaocursor
PARAlnCnt=1a2
lcFile=("tcFile"+PADL(lnCnt,1))
USE(&lcFile)novamenteIN0SHAREDALIASTestFile
AFIELDS(laFields,'TestFile')
APPENDFROMARRAYlaFields
USOEMTestFile

202 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

PRXIMO

***Agoravejaseoscampossoidnticos
SELECT*,COUNT(*)cnt
DEtmpstru
GROUPBYfname,ftype,Flen,FDeC,fnul
TENDOcnt#2
INTOARRAYlixo

***RetornoTLogical/Fseestruturaidntica
SELECT(lnSelect)
USOEMtmpstru
llRetVal=(_TALLY=0)
RETURNllRetVal

********************************************************************
***Verifiqueparaverseumarquivopodeserabertocomoumatabela
********************************************************************
FUNOISDBF(tcFile)
lcErrWasLOCAIS,llRetVal
***DisableTratamentodeerrostemporariamente
lcErrWas=ON("ERROR")
ERRORON*
***AbraoarquivoespecificadocomoumDBF
USE(tcFile)IN0NOVAMENTEALIAStestopen
***Sebemsucedida,haviaumamesavlida
Seutilizados('TestOpen')
llRetVal=.T.
USOEMTestOpen
FIMSE
***RestauraramanipulaodeerroeTrabalho
ONERROR&lcErrWas
RETURNllRetVal

Aqui,porsinal,outro"estranheza".VisualFoxPronoincluirumafunopara
determinarseumarquivonaverdadeumatabelautilizvel.Ento,novamente,tivemosdecriarum(a
ISDBF()funo).Issodependededesactivarqualquertratamentodeerrosetentarabriroarquivose
bemsucedido,entopodemosassumirqueoarquivoutilizvelcomoumatabela.

Comoparatestarquantopresenadeumcampodeumatabela
Esteumassuntodelicado!Maisumavezpareceestranhonohnenhumafunonativaparafazerissoporns,mash
so(comodecostumeemVisualFoxPro)vriassoluespossveis.Noentanto,todossofremdepotencial
problemas.Aquiestoalgumassugestes:

TesteparaFSIZE()
AteoriaaquiquesevocperguntarVisualFoxProparaotamanhodeumcamponoexistente,ser
retornar0.Ocdigomuitosimples,naverdade:

IFFSIZE('MyField')>0
***Ocampoexistenatabela,fazeralgo
FIMSE

Noentanto,notequeo FSIZE()funo(deacordocomoarquivodeAjuda):
Captulo7:Trabalhandocomdados 203

"Retornaotamanhoembytesdeumcampoouarquivoespecificado."

Observeo"OR"nofinaldafrase.Nsnormalmentepensamos FSIZE()comoretornandoocampo
largura,masnemsemprefazlo!AconfiguraodeSETCOMPATVELdeterminaqualotamanho
retornado(campoouarquivo)ese COMPATVEL ON,entovocquerobterotamanhodoarquivo
ouumerrosenenhumarquivoexistecomonomeespecificado.

UseTYPE()
Estafunoirretornarumvalorde"U"seocampoespecificadonoexiste.Noentanto,voc
precisaadicionaronomedoaliasparagarantirqueVFPrealmenteolhaparaocamponatabela,enoa
umavarivelchamadaomesmoqueocamposeocamponoexiste.

IFTYPE("junk.myfield")#"U"
***Ocampoexistenatabela,fazeralgo
FIMSE

No,noentanto,umperigorealaqui.Amesmasintaxede<alias.field>usadapara
referncia<object.property>eo TYPE()funoirlidarcomamboscomigualfacilidadee
podemuitobemdarlheumarespostatotalmenteerrado.No,portanto,umaboasoluo!

Alis,ofactodeomesmoestilodesintaxeutilizadotantopara
<Object.property>e<table.field>podesermuitotil.asfunes
JUSTSTEM()eJUSTEXT()foramconcebidosparaextrairamesa
nomeeextensodeumnomedearquivo,masotrabalhotobemcomobject.property
stringsoumesmoqualquercadeiaquecontmum"."Separador.(Ofactodeo
arquivodeajudaafirmaqueJUSTEXT()retornauma"extensodetrsletras"simplesmente
imprecisa,elerealmenteretornatodososcaracteresdireitadoperodomaisdireitaemum
corda,independentementedotempo.DamesmaformaJUSTSTEM()retornatodososcaracteres
esquerdadoperodomaisdireitaemumastring).

UseVARTYPE()
Quetalusar VARTYPE()emvezdisso?Estanovafunofoiintroduzidanaverso6.0,masem
Nestecaso,elenovaifazernada.Sevocespecificaronomedocampo,semumaliasnoomesmo
possibilidadedeumfalsopositivoseumavarivelexisteeocamponomesmoqueVisual
FoxProsempreretornarotipodecampo,seambosexistem.Noentanto,sevoctambmespecificaroalias(para
foraVFPignorarvariveis)vocteruma'Variable<name>noforencontrado'erroporque
VARTYPE()noavaliaascoisasdamesmaformaque TYPE().

UsoAFIELDS()eASCAN()
Estaabordagemfazusodo AFIELDS()funoparaobterumalistadetodososnomesdecampo(mais,como
jvimos,muitomaisinformao)emumatabela.Ento ASCAN()usadoparalocalizarocampo
quevocestprocurando.Sevocreceberumacorrespondncia,ocampoexiste:

lnFieldCnt=AFIELDS(laFields,'MyAlias')
IFASCAN(laFields,'MyField')>0

204 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Ocampoexistenatabela,fazeralgo
FIMSE

Istotemavantagemdasimplicidademassofrededuaspossvelapanhado!'.Primeirocertifiquesedeque
Conjuntoexato ON,etambmformataracadeiaqueestprocurandoparamaisculas,casocontrrioVFP
podeachar"clnica"quandovocestrealmenteprocurandopor"CLINIC ."Tambmporque
ASCAN()procuratodasascolunas,certifiqueseoitemquevocencontrounaprimeira(ouseja,onomedocampo)
coluna.Casocontrrio,vocpodeterencontradoapenasumapartedocdigodevalidao,comentarouumerro
mensagem.Vocpode,obviamente,fazerestetrabalhoabordagemsemessasfalhaspotenciais,maselefaz
requeremmaiscdigodoqueprimeiroparecemnecessrias.
Porexemplo,ummtodomaisseguro,emboramaislentaseriausar AFIELDS()e,emseguida,ciclo
atravsdamatrizcomparandoaprimeiracolunaemcadalinhacomonomedocampoquevocestprocurando
paraautilizaodeum"=="paracomparao.Assim,

lnFieldCnt=AFIELDS(laFields,'MyAlias')
PARAlnCnt=1alnFieldCnt
IFlaFields[lnCnt,1]=='MyField'
***Ocampoexistenatabela,fazeralgo
SADA
FIMSE
PRXIMO

Asoluoinequv oca
Asoluomaisconfivelusar funoFCOUNT()paracontrolarumloopeverificaronomedecada
campocomoretornadopelo campo()funo,usandooduplo"="paraforarumacomparaoexata,
doseguintemodo:

PARAlnCnt=1afunoFCOUNT()
IFUPPER(CAMPO(lnCnt))=='MyField'
***Ocampoexistenatabela,fazeralgo
SADA
FIMSE
PRXIMO

Enquantoistopodenoseromtodomaisrpido,ouomnimodecdigo,elesusa
funes,quesereferemespecificamenteaoscamposemumatabelaeirretornardeformaconfivelounoo
campoespecificadorealmenteexiste.

Comoverificarseatabelaestsendousadoporoutrousurio
VisualFoxPronoforneceressafuncionalidadenativaporissotemosderecorreraartifciosparagarantir
amesaqueescolhemosnojemusoporoutrapessoa.Porqueissoimportantesaber?
Normalmente,issonecessrioaoescreverrotinasdemanutenoquevaiexigirousoexclusivodeum
mesa.Asoluobaseiasenaobtenodeusoexclusivodatabelaespecificada,combasenoquese
vocpodeobtertal,entoatabelanoestemusoporoutrapessoa.Onicoproblemapossvelquese
vocjtematabelaabertacomalteraesnopendentevocvaiperdlos,e
dependendodomododebuffer,voctambmpodeobterumerro.Noentanto,nssentimosqueestedeveseroseu

Captulo7:Trabalhandocomdados 205

prpriaresponsabilidadeeque,paraadicionarverificaesparaestasituaoquecomplicadesnecessariamenteo
funo.AquianossaIsInUsefuno:

**********************************************************************
*Programa :IsInUse.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:tentaobterusoexclusivodeumatabelaparaverseatabela
* :usadoporoutrapessoa
**********************************************************************
LPARAMETERStcTable
lcTableLOCAL,lcOldError,llRetVal,lnWasUsedIn,lnWasOrder
***Verifiqueparmetrosegarantirumamesaestdisponvel
IFEMPTY(tcTable)ORVARTYPE(tcTable)#'C'
MESSAGEBOX('NenhumatabelapassadaparaIsInUse()',16',abortando...')
RETORNA
OUTRO
lcTable=UPPER(ALLTRIM(tcTable))
FIMSE
***Setivermosatabelaemusoj,fechloeobservarofato!
llWasUsedHere=USADO(lcTable)
IFllWasUsedHere
***Estvamosusandoisso,entodescobrirondeesalvlo
lnWasUsedIn=SELECIONAR(lcTable)
lnWasOrder=ORDER(lcTable)
lnWasRec=IIF(RECNO(lcTable)>RECCOUNT(lcTable),
RECCOUNT(lcTable),RECNO(lcTable))
USOEM(lcTable)
OUTRO
lnWasUsedIn=0
lnWasOrder=0
lnWasRec=0
FIMSE
***Salveotratamentodeerrosatualedesativlotemporariamente
lcOldError=ON("ERROR")
ONERRORllRetVal=.T.
***Experimenteeutilizeatabelaexlusively
USE(lcTable)IN0EXCLUSIVE
***Seconseguimos,fechlanovamente
ESE!llRetVal
USOEM(lcTable)
FIMSE
***Restauraromanipuladordeerro
ONERROR&lcOldError
***Seelefoiaberto,emseguida,redefinilaadequadamente
IFllWasUsedHere
USE(lcTable)novamenteIN(lnWasUsedIn)ORDER(lnWasOrder)
IFlnWasRec#0
***Eleestavaemumregistroespecfico
GOTO(lnWasRec)IN(lcTable)
OUTRO
***Bastairparaoprimeiroregistrodisponvel
GOTOPIN(lcTable)
FIMSE
FIMSE
***Retornaoresultado
RETURNllRetVal

206 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Observeque,sejtemosatabelaabertaemnossaprpriasesso,restaurloem
concluso.Istopodenoserrealmentevlidoporque,presumivelmente,ousodestafuno
seriaimediatamenteantesdeuma USOEXCLUSIVOcomando,queteriaentofalhardequalquermaneira
porqueaindatemosatabelaaberta.Noentanto,eleforneceumaoportunidadeadequadaparamostrarcomo
pararestaurarumamesaportanto,nodeixaramessafuncionalidadenolugar.Sevocnoquiser,bastaremover
isto!
Umproblemasurgequandoatabelanecessriojestabertoemoutrareadetrabalhonombitodeum
diferentedealias,ouquandoumcursorgeradoSQLexistequerealmenteumaexibiofiltradadeum
tabelaabertacomumaliasdiferentenaestaodetrabalhoatual.Afunodependedeonativo
VisualFoxProUSADO()funoquestestao"apelido"especificado.Emqualquersituao,a
funoretornarFalse(corretamenteindicandoqueatabelajestemuso),massubsequente
tentaencontraroaliasirfalharcomum'Aliasnoencontrado"errocomoosseguintestrechosdecdigo
ilustrar:

***OpenTablesobdiferentesAlias
OsclientesusamALIASfred
?ISINUSE("clientes")&&retorna.
clientesdeSELECT &&ERROR:'CLIENTESaliasnoforencontrado'

***Criarexibiofiltradadatabelacomaliasdiferente
OsclientesusamALIASfred
SELECT*deFredONDECLISID=96INTOjoeCURSOR&&Criaumfiltrado
Viso
USOEMfred &&'clientes'fecha
?ISINUSE("clientes")&&retorna.
clientesdeSELECT &&ERROR:'CLIENTESaliasnoforencontrado'

Estepoderiaserumproblemaemalgumascircunstncias,mastemosdeolharparaousopretendidopara
estafunooquedeterminarseatabelaespecificadaestemusoporoutrousurio.o
cenriodescritoacimapoderiaserresolvidoemumanicaestaodetrabalhousandooAUSED()funo
paraobterumamatrizdetodososaliasesemusonoDataSessionatual.Cadanomealternativopoderiaentosertestado
usandooDBF()funoparaobteronomedatabelasubjacente,etodaaoperaofechadaem
umloopparatestartodasassessesdedadosabertos.Masissonopoderiaseraplicadaaestaodetrabalhodeoutro
assimmesmoassimvemospoucovaloremcrescentecomplexidadedafuno.Afinal,noimporta
utilizador
comoatabelaforusada,estafunodestinaseanosdizerqueestemusoemalgumlugar.

Oqueexatamenteumcursor?
Otermo"cursor"umacrnimoderivadodafrase"conjuntoatualderegistros."EmVisual
FoxProumcursorimplementadocomoumarquivotemporrioquecriadonodiretrioemque
apontadopelo TMPFILESvariveldesistema(senohouver TMPFILESconfiguraofoiespecificado,oVFP
diretriodeinicializaousadoporpadro).Cursoresso,portanto,muitoteisparaarealizaode
dadostemporriosporqueoVisualFoxProirlimplosparavoc.
UmcursorpodemsercriadosdeduasmaneiraspelaprimeiravezporexecutarumainstruoSQLSelect,que
incluio INTOCURSOR<name>clusula.EmtodasasversesdeFoxProateincluindo
Verso6.0issosemprecriaumcursorsomenteleitura,evamostermaisadizersobreSQL
cursoresgeradosnocaptulodedicadoaoSQL.Poragora,vamossimplesmentenotarqueacriaodeum
cursordestaformatambmabreatabeladeorigememumareadetrabalholivre,senojemuso.
Captulo7:Trabalhandocomdados 207

Emsegundolugar,usandoumadasvariantesdo CRIARCURSORcomando.Istoproduzum
leiacursor/gravaoqueparatodososefeitosprticos,indistinguveldeumatabelapadro.isto
nestetipodecursorquedeveconcentrarsenestaseo.(Noteseque,independentementedecomoum
cursorcriado,elesemprecriadaexplicitamentenosistemalocaldousurioesempre
exclusivaparaesseusurio.)

Comocriarumcursorcombaseemumatabelaexistente
Provavelmente,amaneiramaissimplesdecriarumcursorbaseloemumatabelaexistente.Nsjtemos
usouos AFIELDS()funovriasvezesnestecaptulo(e,semdvida,vaiuslo
novamente!)paraobterosdetalhesdaestruturadeumatabelaemumamatriz.Amatrizqueproduzpodeserutilizada
diretamenteparacriarumcursor(esim,emboraumcursornaverdadeumatabela"livre",elepode
acomodarnomesdecampolongas)usandoocomando:
CRIARCURSOR<aliasname>FROMARRAY<arrayname>

Noentanto,humapegadinha!nisso!Seatabelaaserutilizadacomoafonteparao
AFIELDS()funovinculadoaumbancodedados,emseguida,ALLinformaesrecolhidassobreestatabela
transferidoparaocursoralvoincluindodetalhescomoonomedatabelalonga,triggersepadro
valores.Issocausarproblemasassimcriamosumapequenafunoparafazerumcursorcombaseem
umatabelaquesrecebeainformaoestruturalrealnecessrio(CreCur.prg).estafuno
requerqueumnomedetabelavlidoparaafontedeserpassado,masirgerarumnomedecursorpadro
('Cur_"nome+tabela)sevocnoespecificarumnomedecursor:
**********************************************************************
*Programa :CreCur.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Sumrio...:Criaumcursorcombasenaestruturadatabeladenominada
* :Removequalquercoisa,masainformaoestruturalbsica
**********************************************************************
LPARAMETERStcSceTable,tcCursorName
laFieldslocal[1]
LOCAISlcTable,lcTgtCur,lnSelect,llWasOpen,llRetVal,lnFields
lnRowLOCAL,lnCol
STORE.T.AllWasOpen,llRetVal

***parmetroslimpasegarantirumamesaestdisponvel
IFEMPTY(tcSceTable)ORVARTYPE(tcSceTable)#'C'
lcTable=ALIAS()
OUTRO
lcTable=UPPER(ALLTRIM(tcSceTable))
FIMSE
IFEMPTY(lcTable)
MESSAGEBOX('NenhumatabelapassadaouAbrir',16',abortando...')
RETORNA
FIMSE
***Guardarreadetrabalhoatual(ocomandocursorcriarirmudlo!)
lnSelect=SELECIONAR()
***Abraatabelasenecessrio,enotarofato!
ESE!USADO(lcTable)
USE(lcTable)IN0
llWasOpen=.F.
FIMSE

208 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Padro,onomedocursorsenenhumpassado
IFEMPTY(tcCursorName)ORVARTYPE(tcCursorName)#'C'
lcTgtCur="CUR_"+UPPER(ALLTRIM(lcTable))
OUTRO
lcTgtCur=UPPER(ALLTRIM(tcCursorName))
FIMSE
***Obteraestruturadoquadro
lnFields=AFIELDS(laFields,lcTable)
***AgoraembrancoparaforatudoapsColuna6damatriz
PARAlnRow=1alnFields
PARAlnCol=7PARAAlen(laFields,2)
laFields[lnRow,lnCol]=""
PRXIMO
PRXIMO
***CriaroCursor
CRIARCURSOR(lcTgtCur)FROMlaFieldsARRAY
***Obterovalorderetorno
llRetVal=USADO(lcTgtCur)
***Arrumar
ESE!llWasOpen
USOEM(tcSceTable)
FIMSE
SELECT(lnSelect)
RETURNllRetVal

Quandoqueumcursorserusado?
Umavezqueocursorfoicriado,vocpodeuslocomosefosserealmenteumamesa.Podeser
indexados,usadocomofonteparaum SelectSQL,oRecordSourcedeumagradeouoRowSource
paraumalistaoucaixadecombinao.Anicacoisaalembrarquecertasoperaesexigemoreal
onomedoarquivoemvezdoapelidoe,nessescasos,vocprecisarusaro DBF()funoparagarantir
VisualFoxProlocursorcorretamente.Porexemplo,paraanexarapartirdeumcursoremumafsica
tabelaquevocprecisausarasintaxe:

APPENDFROMDBF('<CursorName>')emvezde APPENDFROM<CursorName>

Ousomaiscomumparaumcursoremsituaesondevocdeoutromodoexigiriaum
tabelatemporria.Avantagemdeumcursorqueelenopermanecernoseusistemaumavez
VisualFoxProtemfechadoevocnoprecisasepreocuparemexcluloouterseu
diretriodedadospreenchidocomtabelastemporrias.AnicaexceoaissoquandoVisual
FoxProterminadeformaanormal(outroeufemismopara"falhas").Sobessascircunstncias
oscursoresnoseroeliminadosautomaticamente.fcildeencontrarlosnoentanto,atravsdaverificaoda
dataehoradacriao,edepoissimplesmenteexclulosmanualmente.
Porexemplo,sevoctemqueimportardadosdeumafonteexterna,validloe,emseguida,
acrescentarapenasosregistrosvlidosparaumatabelafsica,umcursorointermedirioidealprecisamente
porquepodesertratadacomosefosseatabela"real".

ndicesemVisualFoxPro
DizerqueosndicessoimportantesquandosetrabalhacomdadosemVisualFoxProuma"leve
subavaliao".Avelocidadeeflexibilidadedetrabalharcomdadosregulada,emgrandemedida,

Captulo7:Trabalhandocomdados 209

pelamaneiraquevocconfigurareusarseusndices.precisamenteporqueosndicessotoimportantes
quehmuitasvezesumndicetentaodetudodeumamesa.Talcomoacontececomamaioriadascoisas,noentanto,
demaistoruimquantomuitopouco.Estamosconfinandoasnossasobservaesaquiespecificamenteutilizaode
ndicesestruturaleincluemumaobservaosobrealgunsdosproblemasassociadoscomstand
sozinhondicesmaisadiantenestecaptulo.
Primeiro,precisamosnoslembrardealgumasregrasbsicasqueregemndices.

Tiposdendices
VisualFoxProprevquatrotiposbsicosdendicescomoilustradopelatabelaaseguir:

Tabela7.1tiposdendicedoVisualFoxPro

Digitar Caractersticas Comentrios


primrio Sseaplicaatabelasligadas UsadoporVisualFoxProparalidarcom
Apenasumndiceprimriaportabela relacionamentospermanentesentretabelas
ndiceimpesingularidadedechaves Identificara'uma'finaldeumparamuitos
relao
Candidato Aplicaseaambasastabelaslivreseligadas Assimchamadoporqueessesndicesso
Podedefinirvriosndicescandidatos "candidatos"aserfeitaemchavesprimrias
ndiceimpesingularidadedechaves Identificara'uma'finaldeumparamuitos
relao
Regular Aplicamseaambasastabelaslivreseligadas OndicedoVisualFoxPropadro
Podedefinirvriosndicesregulares Identificarofinal"muitos"deumonetomany
Qualquervalordechavepodeserindexadose relao
nicoouno
nico Aplicamseaambasastabelaslivreseligadas Essencialmenteum"legado"dexBasetem
Podedefinirvriosndicesexclusivos nenhumafunorealnoVisualFoxProe
Apenasaprimeiraocorrnciadeumvalordechave
Deveriaserevitado
indexados,quersejanicoouno

Existemalgumasregrasqueseaplicamcriaodetodosostiposdendices,comosegue:

Onmeromximodebytesemumachavedendiceparaosndicescompactosde240,porno
ndicescompactosolimitereduzidopara100bytesporchave.
Osndicesfiltrados(ouseja,aquelescujaschavesincluemexpressescom PARAou NOclusulas)
nopodeserusadoparaotimizarasoperaesqueutilizamatecnologiaRushmore.
Seatabelasuporta NULLvalores,umbyteadicionalporvalordechavenecessria,
reduzindoocomprimentomximodacadeiachave.
DefinaAgruparafetaaformacomoaschavesdendicesoarmazenados.Seopadro(" MQUINAconfigurao")
utilizado,cadacaracterenachaverequerumbyte.Todasasoutrasdefiniesrequeremdoisbytes
porpersonagem.
Aconfiguraode SETCOLLATEdeterminaaordemdeclassificaoVisualFoxProusos.

Comoobterinformaessobreumndice
VisualFoxProforneceumasriedefunesqueretornaminformaessobreosndices
associadocomumatabela,talcomoilustradonatabelaaseguir:

210 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela7.2Funesqueretornaminformaessobrendices

Funo retorna
CHAVE() Aexpressochavedondiceparaumamarcaespecificada,oucontrolaratagatualsenenhum
Especificadas
TAG() Onomedamarcaquecorrespondeaonmeroespecificado,oucorrente
controlartagsenadaforespecificado
TAGNO() Onmerodaetiquetacujonomefoiespecificado,oucontrolaracorrente
tagsenadaforespecificado
TAGCOUNT() Onmerodecdigosdendicenondicecompostorelacionadocomamesa
CANDIDATO() Retornaovalorlgicoqueindicaseonmerodaetiquetaespecificadoum
chavecandidata
PRIMRIA() Retornaovalorlgicoqueindicaseonmerodaetiquetaespecificadoumprimrio
chave
ORDEM() Onomedamarcadendicecontrolandoatualmente
SYS(14) Onomeparaonmerodaetiquetaespecificado(equivalenteaKEY())
SYS(21) Onmerodaetiquetadendiceatualmentecontrolando(equivalenteaTAGNO())
SYS(22) Onomedamarcadendicecontrolandoatualmente(equivalenteaordem())
SYS(2021) Aexpressodefiltroparaonmerodaetiquetaespecificado(sehouver)

Comovocpodever,anicainformaoquevocnopodeobterseumndicefoi
criadoemascendenteoudescendenteordem,eissorealmentenoimportadequalquermaneiradesdequalquer
ndicepodeserinvertidapelaadioespecificamenteo ASCENDINGou DESCEpalavrachaveparao SET
ORDEMcomando.Considereoseguinte:

OsclientesusamordemdemarcaCLISIDASCENDING
SEJAOMELHOR
LISTAprximos3CLISID &&Retorna96,97,98
OsclientesusamordemdemarcaCLISIDDESCENDENTE
SEJAOMELHOR
LISTAprximos3CLISID &&Retorna186,185,184

Comoparatestaraexistnciadeumamarcadendice
Asituaomaissimplesaquiquandovocsabeonomedamarcaquevocprecisaparatestar.em
Nestecaso,vocpodesimplesmenteusaro TAGNO()funopararetornaronmerodendicedonome.Ese
ovalorderetornomaiorque0,existeatagcasocontrrio,no.Assim:

IFTAGNO('mytag','mytable')>0
***Atagexisteparaatabelaespecificada
FIMSE

Ascoisasficammaiscomplexosevocnosabeonomedamarca,masprecisadesaberseumndiceem
Existeumaexpressoespecfica.Nestecaso,vocprecisafazerumloopportodasastags,everificara
()Expressodechaveusandocdigocomoeste:

lcTagName=""
PARAlnCnt=1aTAGCOUNT()
IFUPPER(ALLTRIM(KEY(lnCnt)))==<expressoparaencontrar>
Captulo7:Trabalhandocomdados 211

lcTagName=TAG(lnCnt)
SADA
FIMSE
PRXIMO
RETURNlcTagName

Usandocandidato(eprincipal)Teclas
Acaractersticaessencialdetodososndicesqueforamdefinidoscomocandidato(incluindoa
chavecandidataquepodeserdefinido,paraumatabelaligada,como"primrio")quearesponsabilidadepela
asseguraraunicidadedeteclasprocessadapeloprprioprocessodeindexao.Issosoamaravilhoso
nomaiscdigoparaverificarqueachavejnoexistir.No,evidentemente,umproblemaafinal,
oquepodefazerVisualFoxPro,severificarqueachavedondiceumaduplicataenquantoaadiodeumnovo
registro?Arespostafazerexatamenteoqueelefazaumentarumerroerejeitaraadio.o
consequnciaque,comodesenvolvedores,precisogarantirqueachavequeoferecemosaosVFPnica
quandoutilizarndicescandidatos.Istolevantaduasquestes,emprimeirolugarcomolidarcomchavesquesodo
gerado(geralmentecomo"substituto"teclas)eemsegundolugarcomolidarcomchavesquesoinseridos
sistema
directamenteporumutilizador.

Oqueuma"chavesubstituta"?
Umachavesubstitutanotemqualquersignificadoequalquertipodenegciosimplesmenteumvalorarmazenado
domnioespecficoparaonicopropsitodeidentificar,unicamente,essalinhanatabela.Geralmente
numa
simplesmenteumvalorinteirogeradoautomaticamentepeloprpriosistemaquandoumnovoregistro
adicionadoaumatabela.Vocpodeestarseperguntando,nesteponto,porquenosimplesmenteusaroregistro
nmero,umavezqueidentificajexclusivamenteumregistro.(Ns,obviamente,nopodeterdoisregistros
comomesmonmeroderegistronamesmatabela).
ArazoqueonmeroderegistronoVisualFoxPro"posicional"(ouseja,identificao
localizaofsicanoarquivo)enoestrelacionadacomoteorderegistroreal.Algunscomandos
noVisualFoxProalteraralocalizaofsicaderegistrosdentrodeumatabela(porexemplo PACKe SORT),
enquantosevocextrairdadosdoarquivoemumcursorouvisualizaronmeroderegistrogeradoparao
conjuntoderesultadosnoircoincidircomonmerodoregistronatabelaoriginal.Estasquestessoevitadasseo
chave,naverdade,partedosdadoscontidospeloregistro.
chavessubstitutastmduasfunes,ambosrelacionadoscomofatodequeelesseidentificamcomexclusividade
registros.Primeiro,elespodemserusadoscomoachaveparaondiceprimrioparatabelasqueactuamcomoo
painasrelaespersistentesecomochavesestrangeirasemtabelasrelacionadas.Emsegundolugar,podeser
usadoparaunirtabelasnaconstruodeinstruesSQL.

Comodev oimplementarchav essubstitutas?


Emprimeirolugarassuasestruturasdetabeladeveincluircamposparaaschaves.Omaissimples(emaisusual)
implementaousaumIntegertipodedados.Estetipodedadosrequerapenas4bytesdearmazenamentopor
ficha,epermitequeosvaloresnointervalode21474836472147483647(umintervalodeapenas
cercade4bilhesde)quedevesersuficienteparafinsmaisprticos.
Aocriartabelasqueirusarchavessubstitutasparamanterrelacionamentosquevocvaiprecisar
pelomenos,doiscamposadicionais.UmnatabelapaiparaarmazenaraIDderegistroatual(o"primrio
key')eumemcadatabelafilhoparaocorrespondenteregistrodatabelapaiID(o"Foreign

212 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

key').Vriaspropostasforamapresentadasparanomeartaiscampos,enoh"certo"
responda.Oquegostamosusa"xxxSID"paraumachaveprimria(onde"xxx"oidentificadorparao
mesa,e"SID"significa"SistemaID')e,emcadatabelarelacionadaincluiumcampochamado
"XxxKey"(ondeo"xxx"maisumavezremeteparaoquadroquepossuioIDdosistema,eda"CHAVE"
indicaqueestaumachaveestrangeiraparaqueatabela).Outrasconvenessugeremaadiodosufixo"PK"
ou"FK"aonomedocampo,conformeapropriado.Realmentenoimportacomovocnomearsuaschavesmas
importanteadotarumaconvenoeserconsistentenasuautilizao.Figura7.1mostraumtpico
estruturarelacionalusandochavesprimrias/Estrangeirosnomeadosnanossamaneirapreferida:

Figura7.1estruturarelacionalusandochavessubstitutas

VocpodeverapartirdodiagramaqueparaobterumalistadetodasasordensparaumdeterminadoclienteumSQL
declaraocomoestapodeserconstrudo:

SELECT<fieldList>
DECUclienteJunteseordensou
ONOR.cuskey=CU.cussid
ONDECU.cussid=<valor>
INTOCURSORcur_OrdList

Nosissofazunirastabelasbastantesimples,masaoincluiroSID
camposdecadatabelanoconjuntoderesultados,voctemumarotaimediataeseguradevoltapara
osdadosdeorigememtodososnveis,emtodososmomentos.Istoextremamentetilemsituaesondevoc
forneceraousuriocomlistasdedadosparaselecionarumitemespecficoparaotrabalhofuturo.Achavesubstituta
apontadiretamenteparaosregistrosnecessrios.
Finalmente,voctambmdevedefinirumndiceemsuachavesubstitutacomoa principalchaveparacada
mesa.Istotemvriasvantagens:

Eleevitaanecessidadedechavescompostas.Achavesubstitutasempreidentificaum,
eapenasum,ficha
Vocpodeusarumachaveautogerada,oquesersemprenicoeassimevitaro
precisaverificarsehchavesduplicadasquandoaadiodeumregistro.
Ocampodechavenoprecisaservistopelousurioecertamentenuncaprecisaser
editvel,simplificandoocdigonecessrioparamanteraintegridadereferencialentretabelas.

Comogerarchav essubstitutas?
Nspensamosqueamelhorsoluousarchavesinteiraseusaronveldecampopadroparaachave
campoparachamarumprocedimentoparageraroprximonmeronaseqncia.Oprocedimentopodesertanto
umprocedimentodestandalone,includosemumarquivodeprocedimento,ouumprocedimentoarmazenadoemumbanco
dedados

Captulo7:Trabalhandocomdados 213

recipiente.Nspreferimosmantendooprocedimentotalcomoumprocedimentoarmazenadoemumrecipientedebanco
sporqueseumatabelaabertoforadoaplicativo,eumnovoregistroinserido,o
dedados(se
presenadaDBCirgarantirqueonovovalordechavecorretainserida).Ento,oquedeveeste
procedimentosemelhante,ecomoeledeveserchamado?
Aconfiguraoparaovalorpadronodesignertabelarealmentemuitosimples.Tudooque
necessrioumachamadaparaumafunoqueirretornarovaloraserinserido.Nsinclumosum
tabelachamada"Clientes"nobancodedadosCH07quetemumcampodechavesubstituta"CLISID,"que
usadocomochaveprimriaparaatabela.(Nssempretentamosnomearnossosmarcasdendiceparaqueelesindicam
ocamponoqualsebaseiam.Tornasemaisfcildelembraronomedachave!)Este
campotemumpadrodefinidoquechamaaNEWID()procedimentoarmazenadopararetornaroprximodisponvel
chavequandoumnovoregistroinserido.Notesequeafunodechamadaincluionomedatabela
paraoqualnecessriaachave:
Figura7.2Comoconfigurarumvalorpadroparaumachaveprimriaseqencial

Oprocedimentobaseiasenapresenadeumatabelaquemantmumalistadetodasastabelasem
bancodedadoseoltimovalordachaveprimriaquefoiatribudoacadaum.Chamamosestatabela
"SYSTABLE"etemaseguinteestrutura(Naverdade,nsgeralmenteincluemmuitomaismesa
informaesrelacionadasnossasystable,masissotudoquenecessrioparaageraodechavesprimrias).:

214 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

EstruturaPara:C:\VFP60\CH07\SYSTABLE.DBF
=========================================
DBC :CH07.DBC
CDX :SYSTABLE.CDX
Memo:NoFileMemo

ndicesassociados
==================
***Chaveprimria:CTable:CTable

Informaesdatabela
=================
Nomelongo:SYSTABLE
Comentrio:Tabelasistemaderegistodeusodechaveprimria

campoDetalhes
=============
CTable C( 8,0)NOTNULL
ILASTKEY EU( 4,0)NOTNULL

ONewID()funobastantesimpleseestlistadoabaixo.Pontosaseremobservadossodeque
systableabertasemtamponamento(evitandodestemodoanecessidadedeutilizarum TableUpdate())e
explicitamentebloqueadaantesqueonovovalordechaveobtido(demodoqueelevaitrabalhardeformaconfivelemum
ambientemultiusurio).Almdisso,afunoautocorreo.Sevocesquecerdeadicionarumanovatabela
lista,aprimeiravezqueumregistroinseridonatabela,umnovoregistroserinserido
automaticamenteemsystable.Noentanto,emboratilemdesenvolvimento,fazendocomqueestafunodeauto
correononecessariamenteumacoisaboaemumambientedeaplicao.Oprprioatode
corrigindosepodeesconderofatodequeumproblemagraveocorreunobancodedadosdosistema!
Oexemploaquimostraaversododesenvolvedor:

FUNOnewid(tcTable)
lcTableLOCAL,lnNextVal,lnOldRepro
***VerifiqueParameconverteremmaisculas
IFEMPTY(tcTable)outipo("tcTable")#"C"
RETURN0
FIMSE
lcTable=UPPER(ALLTRIM(tcTable))
***SalvarconfiguraeseabertoSystablesejnoestiveraberta
lnOldRepro=SET('REPROCESS')
ESE!USADO('systable')
systableUSOEM0
***Certifiquesedequeatabelanotamponado
=CURSORSETPROP('Buffering',1,'systable')
FIMSE
***Agora,encontraratabelanecessria
SeSEEK(lcTable,'systable','CTable')
***Encontradotabelanecessria
***Obterumfechamentonosystable
SETREPROCESSparaAutomtico
SERLOCK('systable')
***Obterprximovaloreatualizaosystable
lnNextVal=+1systable.iLastKey
SUBSTITUIRiLastKeycomlnNextValINsystable
DESBLOQUEARINsystable

Captulo7:Trabalhandocomdados 215

OUTRO
***Estenuncadeveacontecer!
lnNextVal=0
FIMSE
OUTRO
***Tabelanoencontrado!
***Precisadeumanovaentradanosystable
lnNextVal=1
INSERTINTOsystable(CTable,iLastKey)VALUES(lcTable,lnNextVal)
FIMSE
***RetornoNewID
SETREPROCESSTO(lnOldRepro)
RETURNlnNextVal
ENDFUNC

Issotudoqueexisteparaela.EstafunopodeserencontradocomoumprocedimentoarmazenadonoCH07
bancodedados.SemprequeumregistroanexadoaoClientetabelaseratribudoautomaticamente
oprximoIDnaseqncia.

Oqueeufaoseumusuriorev erteumaadio?
Arespostacurta"Absolutamentenada!"VocvaiterpercebidoestaabordagemsignificaqueumnovoID
adicionadosaumregistroassimqueesseregistroanexadomesa.Sevocnocometeressenovo
registro,aID"desperdiado"nohnenhumafuncionalidadepararecuperaroIDusado,nemtal
funcionalidadedesejvel.EmumambientemultiusurioqueesttentandorecuperarumaIDperdidoaprpriamatria
dosquaispesadelossofeitose,secomosugerimos,vocusaumachavedeinteirovoctem
quase2bilhesdevaloresdejogarcom(mesmosevocignorarosvaloresinferioresa0).
MaisimportanteporqueoIDestiveraatribuirumsubstitutoIDelesimplesmentenofaz
importaseosnmerosestoforadeseqncia,ouseexistemlacunasnaseqncia.Lembrese,a
nicafunoachaveparaidentificaroseurecorde!

Gerenciamentodechavesintroduzidospeloutilizador
Comojfoiindicado,nsdefendemosfortementeusandochavessubstitutasparaagestoreferencial
integridadeecomobaseparareferenciardadosemconsultasSQLeinstrues.Noentanto,existem
aindahsituaesemqueosusuriosprecisamsercapazesdeentrarvaloresnicos(ordemefatura
nmerosvmmente).Paraestes,ondicecandidatoidealsenspodemosgarantirquetaisvalores
so,naverdadenicaquandotentamosconfirmarasalteraesparaastabelas.
Claro,nohnenhumamaneiraabsolutadeimpedindoqueosusuriosnuncaentrarvaloresduplicados
porqueestamosalidarcomdadosqueperfeitamentevlidoapenasnessecontexto,passaaser
errado.axiomticoquenohsoftwaresoluoparaoproblemadavlidos,maserradasdados!
Vocaindavai,portanto,precisamlidarcomoserrosinevitveisquesurgiroaotentar
confirmarasalteraes,masvocpodetomarmedidasparaminimizaraocorrnciade'accionadorfalhou','Atualizao
Conflito'ou'Unicidadede"errosVulneradoschave,fazendoumpoucodeprsalvarvalidao.

AsoluoSQL
AsoluomaissimplesusarumaconsultaSQLparaverificaratabelasubjacenteeverseorecm
valorintroduzidojexiste.Hdoispontosaseremobservadosaqui.Primeiro,umaconsultaSQLsempre
refereseaobancodedadosfsico,demodoquenopodeser"confundido"peloqueemqualquerdasentradas
tamponada.
216 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Emsegundolugar,porqueoSQLsempreserefereaosdadosnodiscoqueirdetectarasalteraesfeitas(e
salvos)poroutrosusurios.(Naverdadenohnenhumamaneiradedetectaralteraesnoconfirmadasdeoutrosusurios
dequalquermaneiraelesspodemjexistirnosbuffersnamquinadeumusurio).
UmgrandebenefciodousodeSQLqueelenosemoveroponteirodoregistronatabelaeassim
podeserusadomesmoquandoumatabelatamponadolinha.Aquiestumexemplosimplesqueirverificarparaver
seum"nmerodafactura'jexistenatabela'pagamentos':

lcInvNum=ThisForm.txtInvNum.Value
invoice_numberSELECIONAR
DEpagamentos
ONDEinvoice_number=lcInvNum
EmresultadosARRAY
IF_TALLY>0
***Nmerodafaturajexiste
***Ento,tomarasmedidasadequadas
FIMSE

Anicadesvantagemdestaabordagemquepodeserbastantelentoquandoastabelassomuito
grandeamenosquevoctenhatodososcamposnecessriosindexados.Noentanto,comojdissemos
parafora,muitosndicespodemcausaroutrosproblemas,especialmenteemtabelasgrandes..

outrassolues
HumpardealternativasquenousamSQLequepodesermelhoremalguma
situaes.Seatabelatemosndicesrelevantesquevocpodeusaro INDEXSEEK()funo
(IntroduzidonoVFP6.0).Estafunodevolveumvalorlgico,dependendoseo
valorespecificadojexistenondiceparaatabela.Aocontrrio SEEK()ocomportamentopadro
INDEXSEEK()noparamoveroponteiroregistroparaoregistrocorrespondente,emborapossademorarum
parmetroadicional(nasegundaposio)paraforaroponteiroderegistoasermovidoquando
necessrio.Istosignificaquenoirinterferircomastabelastamponadacomfileira,emboraaindaexige
queatabelasejaindexadonocamporelevante.Osmesmosresultadoscomoacimadescritapodeser
conseguidausando INDEXSEEK()comoeste:

lcInvNum=ThisForm.txtInvNum.Value
IFINDEXSEEK('lcInvNum",.F.,'Pagamentos','invoice_number')
***Nmerodafaturajexiste
***Ento,tomarasmedidasadequadas
FIMSE

Humproblemacomouso INDEXSEEK()commesasdebuffer.Logoqueaficha
ponteiromovidoparaforadalinharecmadicionado,ondiceatualizadoparaincluironovovalormesmo
seatabelabufferestemvigor.Assim,o INDEXSEEK()soluosvlidaseforaplicado
imediatamenteapsaadiodeumnovorecorde.
UmaoutraalternativafazerusodacapacidadevisualdeFoxProparautilizaramesmatabela
vriasvezesesimplesmenteverificaratabelainteira.Surpreendentemente,VisualFoxPromuitobomnisso
tipodemanipulao,quenonecessitadequaisquerndicesemuitasvezesmaisrpidadoqueaexecuo
instruoSQLequivalentemesmoquandoatabelatemosndicesrelevantes.Ocdigomuito
simpleseosmesmosresultadosparaonossoexemplopodeserconseguidocomasseguinteslinhas
(Quepoderiaatmesmoserparametrizadoechamadoemummtododeformulrio):

Captulo7:Trabalhandocomdados 217

lcInvNum=ThisForm.txtInvNum.Value
lnSelect=SELECIONAR()
pagamentosusonovamentecompartilhadosem0ALIASschfileNOUPDATE
schfileSELECIONAR
llRetVal=.F.
SCAN
IFinvoice_number=lcInvnum
llRetVal=.T.
SADA
FIMSE
ENDSCAN
USOEMschfile
SELECT(lnSelect)
RETURNllRetVal

Ousodendicescommesasencadernados
ParacriarouexcluirumatagnaestruturalndiceparaumatabelaqueumapartedeumDBC(ouseja,um
queobrigado)vocdeveprimeiroteratabelaabertoexclusivamente.Istopodeparecerrestritivo,
masfazsentidonocontextodemanteraintegridadedasinformaesdaDBCsobre
suastabelas.(Estarestrionoseaplicaalivretabelasoucursores,nemcriaoe
modificaodeCDXarquivosquenosoestruturaisparaastabelasligadas.)Assim,primeiravista,queseria
parecequeamelhorabordagemindexartudooquepoderiaexigirumndicequando
acriaodetabelasquefazempartedeumDBC.
Noentanto,umdosprincipaisproblemascomamanutenodeumgrandenmerodecdigosdendiceem
ndicesqueaactualizaodatabelapodelevarumlongotempoporcausadanecessidadedemantertodos
estrutural
astags.(Nsdissequeoexcessotomaucomomuitopouconocontextodendices.)Ns
altamenterecomendvel,portanto,quevocmantenhaonmerodemarcasdendiceemsuastabelasparao
mnimaabsolutanecessriaemtodososmomentos.
H,evidentemente,umagotchaaqui!Paraotimizarasconsultas(eoutroscomandosquefazem
usodendices),vocpodeprecisardevriosndicesquesoutilizadoscompoucafrequnciaemumaplicativo.
Sevocestiverusandotabelaslivresvocpoderiasimplesmentecriarndicestemporrioseexclulosdepois
usar,masparaastabelasligadasvocprecisaadotarumaestratgiadiferente.
UmaopousararquivosCDXnoestruturais,porquevocnoprecisaterexclusiva
usardamesa,afimdecrilos.Enquantoissovaifuncionar,nsgeralmentenorecomendar
porquetaisndicesdevesermantidoatdata.VisualFoxProsempremantmumaestrutural
ndice,masnoestruturaisndicessomantidossomenteenquantoelesestoabertas.Anoserquetu
especificamentereindexao(ourecriarostags)emcadautilizao,hsempreoperigodeondice
ficandoforadesincronizaocomasuatabelapai.
Umaalternativapreferidaautilizaodeumcursorposicionadoemvezdeacederamesaligado
diretamente.Emboraissopossaenvolvermaispensamentoquandosetratadecriarepreenchero
cursorouactualizarosdadossubjacentes,quegaranteondiceestruturalnatabelabasepodeser
mantidopequeno.Istoajudaareduzirasobrecarga,quandoaactualizaodatabelaeevitaterde
manteroureconstruirndicesnoestruturais,oquepodeserdemoradoparagrandesmesas.

218 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comotiposdedadosmistosndiceaocriarumachavecomposta
Temosdedizernafrentequensnogostamosdechavescompostasespecialmentequandoelesestoincludosno
ondiceestruturaldeumatabela.Noentanto,tambmreconhecemosquepodehavercircunstnciasespeciais
quandoumachavecompostaabsolutamenteanicacoisaquelhepermitiratingiroseu
requisitos.Istolevantaduasquestesimediatas.
Emprimeirolugar,comopodemoscriarumndiceusandoumamisturadetiposdedados?Arespostasimplesmente
criarumanicachaveconcatenadaemquecadacomponentedomesmotipodedados.Normalmente
esterequeraconversodecadacomponenteparaoseucarcterequivalente.Portanto,paracriarumndiceem
umcampodecaractereseumcamponumricodaexpressodendiceseria:

INDEXON<CharField>+STR(<NumField>)tag<name>

Enquantooequivalenteenvolvendoumadataseria:
INDEXONDTOS(<datefield>)+<CharField>tag<name>

Emsegundolugar,comoquepodemoscriarumndiceenvolvendoumelementoclassificadosemordemcrescente,com
outroelementoclassificadosemordemdecrescente?As crescente/decrescenteclusulasseaplicamao
expressocomoumtodo,eapenasumpodeseraplicadoemqualquerexpressodendice,emqualquercaso.o
soluocriarumaexpressoqueinverteaordemnaturalparaoelementoquedeveser
invertido.Porexemplo:

INDEXONacctref+STR(10000000VAL(SYS(11,InvoiceDate)))TAG
lastinvoice

gerariaumndiceemqueo""acctref""campoestemordemcrescente,enquantoo
"InvoiceDatecampo"emordemdecrescente,colocandoassimaltimafaturarecebidaparacada
clientenotopodaordemdeclassificao.O SYS(11)funoestaserutilizadoaquiparaconvertero
campodedataemJulianDay(emformatonumrico),queentosubtradoapartirdeummuitogrande
nmeroinverteraordemantesdeserconvertidoparaumacadeia.Comovocpodeimaginar,issoseria
noserumbomndiceparacriaroumanter,sobreumagrandemesaquetemumaltonveldeatualizao
actividadeeumcasoemqueumadassoluesdescritasnasecoanteriorseria
maisaplicvel!

Comoindexarumatabelatamponada
Arespostacurtaquevocnopodeindexarumatabelaparaaqualtabelabufferestativado,
VisualFoxProgerarumerrosevoctentar.Noentanto,sevocnotemobuffer,ouRow
tamponante,umndicepodesercriadodamaneirausual.Ento,tudooquenecessrioparagarantirquetodos
mesassoforadosaumbaixonveldebufferantesdeindexao,oureindexao.
Onicoproblemaquevoctambmdevegarantirquequaisqueralteraespendentesousocomprometidos
ourevertidaantesdealteraromododebufferdatabela.Vocpodeusaro CURSORGETPROP(
"tamponamento")paradevolveradefinioactualdetamponamentoparaumatabelae,seoresultadofor
4ou5(ouseja,atabelabuffer)verificarsehalteraespendentes,equercometerourevertlos
comoapropriado.Cdigocomoesteseronecessrios:

Captulo7:Trabalhandocomdados 219

lnOldBuffMode=CURSORGETPROP('buffer')
IFlnOldBuffMode>3
***Voctembufferdetabela
IFGETNEXTMODIFIED(0)>0
***Halteraesnoconfirmadas
***Pegalosaqui
FIMSE
OUTRO
IFlnOldBuffMode>1
***Voctemmemriaintermdiadelinha
lcStatusGETFIELDSTATE=(1)
SE'2'$lcStatusOR'4'$lcStatus
***Alinhaatualtemalteraesnoconfirmadas
***Pegalosaqui
FIMSE
FIMSE
FIMSE
***Foraparamemriaintermdiadelinha,senecessrio
IFlnOldBuffMode>1
CURSORSETPROP('Buffering',3)
FIMSE
***Agoraconstruirndices
INDEXON<whatever>tag<newtag>
***RestaurarBuffer
CURSORSETPROP('Buffering',lnOldBuffMode)
RETORNA

Algumaspalav rasdeexplicaosobrendicesdestandalone
Naintroduoaestaseo,queafirmouqueousodendicesdestandalonenoseencaixa
confortavelmentecomomodeloVisualFoxProdousodetabelasedadossessestamponadosmasfez
noexplicammais.Naverdadeusandostandalonearquivos(IDX)(paracriarumndicetemporriopara
exemplo)podecausaralgumascoisasmuitoestranhasaacontecer.
IssoocorreporqueumarquivoIDXestdisponvelemtodasassessesdedados,independentementedolocalonde
criado.Essecomportamentolevaaalgunsresultadosmuitopeculiares,sevoctentarusarondiceemumdados
foi
sessoenquantoamesaaqueserefereabertonomododetabelatamponadaemoutro.o
boanotciaqueVisualFoxProirarmadilhaparaestasituao,masamnotciaqueelerelata
comonmerodeerro1579queafirmaque:

"Ocomandonopodeseremitidoemumatabelacomcursoresnomododebufferdetabela"

Istopodeserdesconcertantequandoocomando Definaondice<file>eamesapara
quevocesttentandodefinirondicedefinitivamente NOusandobufferdetabela!Almdisso,se
vocestiverusandovriassessesdedadoseumatabelaabertausandobufferdetabelaemqualquerumdeles,
vocnopodemesmocriarumndicestandalonenessatabela.Vocvaiobteromesmoerro!
Sevocpercebeoqueestacontecendoeenganar,forandoobufferparaomodolinhanenhumou
nasessodedadosofensivo,criarondiceeconfigurloe,emseguida,redefinirobufferquevocvai
acharquevocnopode,emseguida,fecharoarquivodendicesemficarError#1579.
Nemsequertentarefazeramesmacoisa,enquantovoctemumatransaoemvigor.Sevocconseguir
paracriarondice(porbrincarcomosmodosdebuffer)VisualFoxPronopermitir
loafecharatransao,enquantoessendiceestemuso.Noentanto,entovocvaiacharquevocnopode
220 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

fecharondiceenquantoatransaoestaberto!TivemosdereinicializaoVisualFoxProparasair
este!Alinhainferior,portanto,ficarlongedendicesindependentesquandoseutiliza
mesastamponado.

Trabalhandocomocontinerbancodedados
OadventodorecipientedebancodedadosnoVisualFoxPro3.0forneceualgumaslongoatraso
funcionalidade.ApesardemanteroclssicoDBFformatoparatabelas,oDBCacrescentoumuitos
caractersticasquesopadroemsistemasdegerenciamentodebancodedadosrelacionalmodernos,masquetevede
serdesenvolvidoindividualmenteemversesanterioresdoFoxPro.ADBCfornecesuportepara:

Dicionriodedados
relaespersistentes
Builtindeintegridadereferencial(RI)
Insero,UPDATEeDELETEgatilhosparatabelas
Osnomeslongostabelaeregrasdevalidaorecorde
Osnomeslongoscampoeregrasdevalidaodecampo
OvalorpadroeComentriosparacampos
Campo InputMaske Formatopropriedades
MapeamentodasclassesdecontroleUIparacamposdetabela
Conexescomfontesdedadosremotas
Visualizaeslocaleremoto

OpreoparaestefoiumamodificaoparaocabealhodaDBFarquivoparaincluirum'backlink'
paraindicarqueorecipientebasededadosemquetodaestainformaofoiarmazenada.Aconsequncia
queosquadrosVFPencadernadosnopodeserlidoporversesmaisantigasdoFoxPro.Noentanto,amenosque
absolutamente devetersuastabelaslegveldiretamentetantoemVFPeFP2.xnohabsolutamente
nenhumarazoparanousarorecipientedebancodedados.
Alimitaoqueatabelapodesempreapenaspertencemaumrecipientedebancodedadosdecadavez.
EnquantoVisualFoxPropodelidarcomvriosrecipientesdebancodedadosqueestsendoaberto,ocdigoparafazer
porissopodeficarconfuso.Assim,aindahumlugarparatabelas"livre"noVisualFoxProespecialmentepara
Dadosdepesquisa,quecompartilhadoentrevriosaplicativosemboraumamesalivrenopodecompartilhar
nosbenefciosqueestodisponveisparaseusprimosencadernados.

Usandonomesdetabelalongos
Aocriarumatabelaqueestligadaaumrecipientedebancodedados,vocpodeespecificarumnomedetabelaque
diferentedonomedoarquivoepodeconterat128caracteres(devecomearcomumaletraou
umsublinhado!)epodeincluirespaos.
OcomportamentopadrodoFoxProsemprefoiodeabrirumatabelacomomesmonomedealias
comoonomedoarquivo,amenosqueumaliasfoiexplicitamentefornecido.Quandoastabelasvinculadassoabertas,uma
feitarefernciadevoltaparaorecipientedebancodedadose,seumnomedetabelafoiespecificado,
usadocomoaliasemvezdonomedoarquivo(emboraseonomedatabelaespecificadocontm
espaoshorror!Soinseridossublinhados).Oresultadoquevocpodedefinirpadro
"Aliases"parasuastabelas.

Captulo7:Trabalhandocomdados 221

Noentanto,porqueonomedatabelatempoarmazenadonabasededadosdorecipiente,libertandoumamesa
apartirdorecipientedebancodedadossignificaqueoseunomelongoserperdido.Notesequeopadro COPY
TOcomandoir,porpadro,criarumatabelalivree,portanto,noirpreservarqualquertabelalonga
nomes(ouqualqueroutrainformaorelacionadacomaDBC).Paraevitarisso,vocdevesempreusaro
DATABASEclusulaecopiaratabelaparaoutrorecipientedebancodedados(que deveexistir,
VisualFoxPronoircriarumnovoDBC"onthefly"),assim:

mytableSELECIONAR
COPYTOnewtable &&Criaumamesalivre,masperdeDBCrelacionada
emformao
COPYTOnewdbcDATABASEnewtable &&cpiasAtabelaetodososdadosparao
novoDBC
Usandonomesdecampolongosno!!!
ODBCtambmpermitequevocusenomesdecampolongasemsuastabelas(novamente,at128caracteres).
Noentanto,emnossaopinio,este noumacoisaboa!Humperigorealepresentenouso
denomesdecampodecomprimento,paraalmdadificuldadedesimplesmentedigitandocorrectamenteosemcontrolos
eemcdigo.Talcomoacontececomonomedatabelalongo,osdadosreaisparaosnomesdecampodecomprimento
recipientedebancodedados.Olimiteparanomesdecampoemumamesalivreexatamenteomesmocomosemprefoi
armazenadono
estadoemFoxPro10caracteres.Aconsequnciaquesevocliberarumatabelavinculadaqueusa
nomesdecamposlongos,onomelongoperdidaeVisualFoxProsubstituiumcampode10caracteres
nome.Seosnomesdoscamposmaiscurtosnosoexclusivos,FoxProtornatotomandooprimeiro
<N>caractereseacrescentandoumsufixonumricoassim:

Tabela7.3Truncandocamponomeslongos

Nomelongo Nomecurto
THISISALONGFIELDNAME THISISALON
THISISALONGFIELDNAMETHATISDIFFERENT THISISALO2

Issovaiquebrarocdigoemuitodesagradvel,naverdadeemborasejadifcilveroquemaisVisual
FoxPropodefazer,dadaestasituao.Assim,vocpodedizer,nssnovailiberartabelasqueusamalongo
nomes...problemaresolvido.
Infelizmente,estanoanicasituaoemquenomesdecampotruncadas.Cursores FAZERapoio
nomesdecamposlongos,assimqueumSQLselecionarapartirdeumatabelaqueusalosirpreservaronomedo
intacta.Noentanto,sevoc,emseguida,desejapreservarocursor(fazemosissomuitoquandotestarcdigo
campo
queatuaemtabelasgrandes)etentarcopiaroconjuntoderesultadosparaumatabelatemporriavocacabarcomum
mesalivre,comnomesdecamporeduzidoecdigoquenoseroexecutados.Claroquevocpodecriar
outraDBC,oucriaratabelacomumnovonomenaDBCexistentemasnemsoluo
permitirqueseucdigoexistenteparaexecutarsemmodificao!
Entonsachamosqueaperguntaquevocdeveseperguntarporquevocprecisadenomesdecampolongos
detodo?
CadacampodeumatabelaligadatemumCaptionpropriedadequeusada,porpadro,emvezdo
nomedocampoemcadalugarqueumnomedecampo,normalmente,seriaexibidopeloVisualFoxPro.
Istoincluinocabealhodeumagrade,comoalegendadortuloqueVisualFoxProadicionaa

222 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ocontrolecaixadetextoaoarrastarumcampodaDEemumformulrioenosPesquisar
janela.Naverdade,osnicoslugaresquevocnopodemostrarpropriedadelegendadeumcampodiretamenteestoem
umaestruturadelistaouaousar AFIELDS()(porqueainformaoestnoDBC,enoem
aprpriatabela).
EmqualquerambientealegendadocampopodesersemprerecuperadadoDBC(quedeve
estardisponveis,mesmosenoestiverjdefinidocomoatual,seatabelaestemuso),utilizandoo DBGETPROP()
funoporissoparecenosque,emboralongosnomesdecampososuportados,nohrealmenteuma
bomcasoparauslos.

Usandorecipientesdebancodedados
QuandoseutilizaorecipientebasededadosFoxPro,importantereconhecerqueoVisual
FoxProdiferenciaentreumDBCquemeramenteabertoeoDBCqueatual.
AmaioriadoscomandosefunesrelacionadascomobancodedadossfuncionamnaatualDBC( eg
DBGETPROP(),DBSETPROP(),ADBOBJECTS()e INDBC()).A CRIARcomandotambm
secomportadeformadiferentequandoumDBCdefinidacomoatual.Atabelacriadaserautomaticamente
somadoaoDBC,casocontrrio,umamesalivrecriado.
AbrindoumatabelaqueestvinculadaaumDBCtambmabre(masque nofazematual)a
AssociatedDBCaoabrirumDBCexplicitamente( OPENDATABASE<nome>)tambmfazqueo
continerbancodedadosatual,masnoabrequalquerdesuastabelas.
ParafazerumaDBCabertocomoobancodedadosatual,vocdeveusaro DATABASESETTO<name>
comando.Obancodedadosqueatualpermaneceatualatqueoutra OPENDATABASE,ou
DATABASESETTO,ocomandoencontrado.IssopermitequeVisualFoxProparalidarcommltiplos
recipientesdebancodedadossimultaneamente,masusandovriosdbcspodetambmtornaravidadifcilparao
desenvolvedor,particularmentequandoamboscontmprocedimentosarmazenadoscomooprogramaShoStPro.prg
ilustra:

**********************************************************************
*Programa :ShoStPro.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Ilustreosproblemasaousarvriosdbcs
**********************************************************************
***Abradoisrecipientesdebancodedados
CLARO
bCH07dadosabertos
DadosAbertosaCH07
***LigueparaalojaProcs
?"CurrentDBC="+SET("DATABASE")
DOCheckStProc
***AgorafaaatualaCH07
ConjuntodedadosparaaCH07
?"CurrentDBC="+SET("DATABASE")
DOCheckStProc
***AgorafaaatualbCH07
CONJUNTODEDADOSPARAbCH07
?"CurrentDBC="+SET("DATABASE")
DOCheckStProc
***AgorafaaatualNODBC
SETDATABASETO
?"CurrentDBC="+SET("DATABASE")
DOCheckStProc

Captulo7:Trabalhandocomdados 223

FECHETUDO
RETORNA

PROCEDIMENTOCheckStProc
FAZERmanequim
DOOnlyaCH07
DOOnlybCH07

Sevocexecutaresteprogramaapartirdalinhadecomando,vocverquecomvriosdbcs
aberta,chamandoumprocedimentoarmazenadoqueexisteapenasem umDBCquefine.Itnoimportaqual
DBCatual,oprocedimentocorretolocalizado.Noentanto,se ambososDbcsconterumarmazenado
procedimentoquetemomesmonome,aconfiguraodoDBCdevitalimportncia,umavezVisual
FoxProirsempreprocurarobancodedadosatualprimeiroesentoeleirprocurarqualqueroutraaberta
bancosdedados.
Finalmente,senenhumDBCdefinidacomoatual,emseguida,VisualFoxProexecutaoprimeiroprocedimento,
encontranesteexemplosempreo"manequim"procedimentonorecipientedebancodedadosaCH07.
InvertendoaordememqueosdoisDBCSsoabertosnoShoStProprogramaalterao
Resultadodoltimoteste.IstosugerequeVisualFoxPromanterumacoleointernade
bancosdedadosabertos,emqueoltimobancodedadosparaserabertoestnotopodalista,e
procurouemprimeirolugar,quandonohbancodedadosdefinidocomoatual.

Comovalidarumrecipientedebancodedados
VisualFoxProforneceuma VALIDATEDATABASEcomandoqueirexecutarumaconsistnciainterna
verificarobancodedadosabertonomomento.Atualmente(6.0aVersion)estecomandopodeapenasser
emitidoapartirdejaneladecomandoe,porpadroseusresultadossoenviadosparaoprincipalFoxPro
tela.Atentativadeuslodentrodeumaaplicaoprovocaumerro.
Vocpodevalidarumbancodedadossemprimeiroobterusoexclusivo,masondiceDBCvai
noserreconstruda,nemvocvaisercapazdecorrigirtodososerrosqueoprocessopodeencontrar.comexclusivo
usarvocpodeescolherparareconstruirondice(umaplancie DATABASEVALIDATEcomandofar
apenasisso)ouparainvocaromecanismodereparoadicionando" RECUPERARclusula'paraocomando.
Apesardenosermuitosofisticado,aopoderecuperao,pelomenos,destacaqualquercoisaqueVFP
senteerradocomseuDBCeofereceopesparaqualquerlocalizarouexcluirumitememfalta
eeliminarourebuildfaltandondices(desdequeainformaonecessriaestdisponvel
noprprioDBC).AmelhormaneiradeevitarproblemasnaDBCgarantirquevocsemprefazer
alteraesemsuastabelas(ouvises)atravsdemecanismosprpriosdaDBC.Eviteaescomo
construodendicestemporriosforadoDBCouprogramaticamentealterarexibiooutabela
definiessemprimeiroobterusoexclusivodaDBC.
Emresumo,emboranoexatamentefrgil,oDBCdependefortementedesuaprpriacoernciainterna
eerros(reaisouimaginrios)irinevitavelmentecausarlheproblemasmaiscedooumaistarde.

Comoembalarumcontinerbancodedados
OrecipientedebancodedadosVisualFoxPro,emsi,umatabeladoVisualFoxPronormalemquecada
linhacontmainformaoarmazenadaparaumobjectonabasededados.ComotodososVisualFoxPro
tabelas,excluirumregistrosmarcaqueoregistroparaexclusoeoregistrofsicono
224 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

removidodoDBC.Istosignificaque,aolongodotempo,umabasededadosquepodeobtergrandes,embora
naverdade,contmmuitopoucosartigosatuais.
O PACKDATABASEcomandoonicomtodoquevocdeveusarparalimparumDBC.
BastaabriroDBCcomoumatabelaeemitirumpadro PACKcomandonosuficiente
porqueoDBCmantmumsistemadenumeraointernaparaosseusobjetosquenoser
atualizadosamenosqueo PACKDATABASEcomandousado.Usandoestecomandorequerquevoc
ganharusoexclusivoaobancodedados.

Moverumcontinerbancodedados
Mencionamosanteriormentenestaseoqueonicopreoparaaobtenodetodasasfuncionalidadesqueum
basededadosfornecerecipienteumapequenamodificaoparaocabealhodatabelaparaincluirum
backlinkparaoDBC.Este,naverdade,umacoisatrivialATtentarmoverumbancodedados
recipiente.Emseguida,seusignificadopodeassumirproporesmonstruosas.ArazoqueVisual
FoxProarmazenaocaminhorelativodatabeladevoltaparaoDBCpossuirdiretamentenatabela
cabealho.DesdequevocsempremanteroDBCetodasassuastabelasdedadosnomesmodiretrio,
tudoficarbem,porquetudooqueficaarmazenadoonomedorecipientedebancodedados.
Noentanto,quandovoctemumrecipientedebancodedadosquenoestnomesmodiretrioqueasua
tabelasquevocestcolocandoseabertoapossveisproblemas.Criamosumatabelaemnossotrabalho
diretrio(C:\VFP60\CH07)eanexadoloparaumbancodedadosqueresidianoC:\TEMP
diretrio.Obacklinkadicionadatabelafoi:
..\..\Temp\TESTDBC.DBC

DepoisdesemudaressecontinerbancodedadosparaoC:\Windows\Tempdiretrio,qualquertentativade
abriratabelaresultouemum"nopoderesolverbacklinkerro'eaopodelocalizaro
DBCfalta,eliminaraligaoelibertaratabela(comtodasasconsequnciasnefastasparaocampodecomprimento
nomesqueissoimplica)ouparacancelar.Sendootimistasqueescolhemosparalocalizarocontinerbancodedados
efoidadaumacaixadedilogoparaencontrlo.InfelizmenteterencontradoonossoDBCeselecionados,ns
foramimediatamenteconfrontadocomoerro110informandonosqueo"arquivodeveseraberto
exclusivamente"Nomuitotil!

Fixaodobacklinkparaumamesa
Ento,oquepodeserfeito?FelizmenteaestruturadocabealhoDBFestlistadonoarquivodeAjuda(ver
a"TabelaEstruturadoarquivotpico"paramaisdetalhes)eVisualFoxProfornecenoscomalguma
purasfunesdemanipulaodebaixonveldeficheirosquenospermitemabrirumarquivoelereescreverparaeleem
onveldebyte.Assim,podemosescreverapenasnonovolocalparaoDBCetudoficarbem.o
nicaquestoondeaescrevlo?
Vocvaiverapartirdoarquivodeajudaqueotamanhodocabealhodatabelarealmentedeterminadopela
afrmula:

32+(nFields*32)+264bytes

OndenFieldsonmerodecamposnatabela,quepoderiacomearusando funoFCOUNT()se
nsspoderiaabriramesa!(Htambmum header()umafunopoucotilque,naverdade,

Captulo7:Trabalhandocomdados 225

nosdizquograndeocabealhodatabela.Infelizmente,eletambmexigequesejamoscapazesdeabriro
mesa.)Massepudssemosabriratabela,noteramosnecessidadedecorrigirobacklinktambm.
Obacklinkemsirealizadacomoosltimos263bytesdocabealhodatabela.Noentanto,anica
certamaneiradeobteressasvitais263bytestentareleromaiornmeropossvelde
bytesquejpoderiaestaremumcabealhodatabela.(Tentandoleralmdofimdoarquivono
gerarumerroemumaleituradebaixonvel,elesimplesmentepranofinaldomarcadordearquivo.)VisualFoxPro
limitadaa255camposporregistrodemodoqueprecisamos,usandoafrmulaacima,alerem8.456bytes.
Istoestbemdentrodonovolimitesuperiorde16,777,184caracteresporcadeiadecaracteresou
variveldememriaparaquetudoestbem.
Felizmente,aseoderegistrosdecampodocabealhosempreterminacomumasriede13" NULL"
caracteres(caracteresASCII0)seguidoporum" CarriageReturn"(caracteresASCII13).Entose
podemoslocalizaressaseqnciadentrodoblocoquetemoslidodatabela,teremosoincioda
backlink.Afunoaseguirusaessatcnicaparalerasinformaesapartirdeumbacklink
mesa(quandoapenasonomedoarquivodatabelapassado)ouescreverumanovacadeiabacklink(passetantoo
nomedoarquivoeonovobacklink):

**********************************************************************
*Programa :BackLink.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Abstract...:Define/RetornaInformaoBacklinkdeumatabela
* :PassartantonomedearquivoDBF(incluindoextenso)spara
* :Pararetornarbacklink,tambmpassamnovacadeiabacklinkpara
* :Escreverumanovabacklink
**********************************************************************
LPARAMETERStcTable,tcDBCPath
lnParmsLOCAIS,lnHnd,lnHdrStart,lnHdrSize,lcBackLink,lcNewLink
lnParmsPCOUNT=()
***Verifiqueseoarquivoexiste
ESE!ARQUIVO(tcTable)
ERROR"9000:Nopossvellocalizaroarquivo"+tcTable
RETURN.F.
FIMSE
***Abraoarquivoemnvelbaixosomenteleituraseapenasaleituradeinformaes
lnHnd=fopen(tcTable,IIF(lnParms>1,2,0))
***Verifiquearquivoestaberto
IFlnHnd>0
***Linkltimos263bytesdocabealhoassimcalcularaposio
***Maxtamanhodocabealho(32+(255*32)+264)=8456Bytes
lcStr=FREAD(lnHnd,8456)
***Registrosdecampoterminamcom13NULLS+"CR"
lcFieldEnd=REPLICATE(CHR(0),13)+CHR(13)
lnHeaderStart=AT(lcFieldEnd,lcStr)+13
***PonteirodearquivoMoverparacabealhoposiocomear
Fseek(lnHnd,lnHeaderStart)
***Leiabacklink
lcBackLink=UPPER(ALLTRIM(STRTRAN(FGETS(lnHnd,263),CHR(0))))
***Seestamosescrevendoumanovabacklink
IFlnParms>1
***Obterocaminho(nomximo263caracteres!)
tcDBCPath=LEFT(tcDBCPath,263)
***PadloparaocorpointeirocomNULLS
lcNewLink=APRD(ALLTRIM(LOWER(tcDBCPath)),263,CHR(0))
***IrparaoinciodaBacklink
Fseek(lnHnd,lnHeaderStart)

226 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Escrevaasnovasinformaesbacklink
Fwrite(lnHnd,lcNewLink)
***Definironovobacklinkcomoovalorderetorno
lcBackLink=tcDbcPath
FIMSE
***Fecheoarquivo
FCLOSE(lnHnd)
OUTRO
ERROR"9000:Nopossvelabrirarquivodetabela"
lcBackLink=""
FIMSE
***Retornodobacklink
RETURNlcBackLink

Oqueacontececomv istasquandoeumov erocontinerbancodedados?


Aboanotciaque,movendoumcontinerbancodedadosnotemefeitosobrepontosdevista.Visualizaesso
instruesSQLdentrodocontinerbancodedadose,emboraelesfazemrefernciaaDBCpelonome,
armazenadoscomo
elesnopossuemnenhumainformaodecaminho.Portanto,nohnecessidadedesepreocuparcomeles,sevocmover
DBCdeumlocalparaoutro(ufa!).
uma

Mudaronomedeumrecipientedebancodedados
Mudaronomedeumrecipientedebancodedadosapresentaumconjuntodiferentedeproblemas.Destavez,ambasastabelas
eAsvisualizaessoafetados.Mesasseroafetadosporcausadobacklinkquepossuemquevaiacabar
seapontandoparaalgoquenoexistemais.Noentanto,issorelativamentefcildecorrigir,comons
jvimos,epodeserfacilmenteautomatizada.Nestecaso,noentanto,vistasirserafectada
porqueoVisualFoxPromuitoutilmenteincluionomedaDBC,comopartedaconsultaque
armazenado.Aquiestpartedasadaparaumaconsulta(geradapeloGENDBC.PRGutilitriofornecido
comoVisualFoxPro,equepodeserencontradonoVFP\Toolssubdiretrio):
MakeView_TESTVIEWFUNO
*****************VerconfiguraoparaTestView***************
CRIARSQLVIEW"TestView"
ASSELECTOptutil.config,Optutil.type,Optutil.classnameDE
testdbc!optutil

DBSetProp('TestView','View','Tabelas','testdbc!Optutil')

*PropsparaocampoTESTVIEW.config.
DBSetProp('TESTVIEW.config','campo','KeyField',.T.)
DBSetProp('TESTVIEW.config','campo','atualizvel",f.)
DBSetProp('TESTVIEW.config','campo','UpdateName','testdbc!Optutil.config')
DBSetProp('TESTVIEW.config','campo','Tipodedados","C(20)")
*PropsparaocampoTESTVIEW.type.
DBSetProp('TESTVIEW.type','campo','UpdateName','testdbc!Optutil.type')
*PropsparaocampoTESTVIEW.classname.
DBSetProp('TESTVIEW.classname','campo','UpdateName',
'Testdbc!Optutil.classname')
ENDFUNC

Observequeocontinerbancodedadosanexadoaonomedatabelaemtodasasocasiesno
snoactual SELECIONARlinha,mastambmcomopartede"decadacampoUpdateNamepropriedade".Isto,no

Captulo7:Trabalhandocomdados 227

dvida,muitotilquandosetrabalhacomvriosrecipientesdebancodedados,masumadorrealquando
vocprecisamudaronomedoprimeiroenicoDBC.Infelizmente,notemossidocapazesdeencontrarum
boasoluoparaesteproblema.AnicacoisaquepossosugerirquesevocusarViews,voc
deveevitarmudaronomeaoDBC,sepossvel.
SevocabsolutamentedevemudaronomedaDBC,entoasoluomaisseguraexecutadoGENDBC.PRG
antesderenomeloeextrairtodasasdefiniesdeexibioemumarquivodeprogramaseparadoquevoc
podeentoeditarparaatualizartodasasocorrnciasdonomeantigocomonovo.Depoisdeterrenomeado
oDBCsimplesmenteeliminartodosospontosdevistaeexecutaroseuprogramaeditadopararecrilasna
bancodedadosrecmrenomeado.
Nota:OcdigoSQLparagerarumavisoarmazenadoem"Propriedades"campodecada"Ver"
registronocontinerbancodedados.Emborasejaarmazenadocomocdigoobjecto,osnomesdecampose
mesassovisveiscomotextosimples.Vimossugestesqueenvolvemapiratariaestapropriedades
diretamentecampoparasubstituironomedaDBC,masnopodedefenderestaprtica!Emnossatestlo
provouserummtodototalmentenoconfivelquemaisfrequentementedoquenorendeuopontodevistatanto
inutilizveleincapazdesereditado.UsandoGENDBCpodesermenosglamouroso,masmuitomaisseguro!

GerenciandoaintegridadereferencialnoVisualFoxPro
Otermo"integridadereferencial",geralmenteapenasabreviadopara"RI",significagarantirqueo
registroscontidosemtabelasrelacionadassoconsistentes.Emoutraspalavrasquecadafichacriana(emqualquer
nvel)temumpaicorrespondente,equequalqueraoquemudaovalordachaveusadapara
identificarumpairefletidoemtodososseusfilhos.Oobjectivogarantirque"rfo"
registrosnuncapodeentrar,ouserdeixadonolugaremumatabela.
VisualFoxProintroduziubuiltinregrasdoRInaVerso3.0.Elessoimplementadosusando
asrelaespersistentesentretabelasdefinidasnorecipientedebancodedadosedisparana
tabelasparagarantirqueasmudanasnosvaloresdechaveemtabelassotratadosdeacordocomasregrasquevoc
definir.OconstrutorRInormapermitetrstiposderegradaseguinteforma:

Ignorar:Aconfiguraopadroparatodasasaes,noRIforadaequalqueratualizaoaqualquer
tabelapermitidoprocederexatamentecomoemversesanterioresdoFoxPro
Cascade:Alteraesnovalordechavenatabelapaisoautomaticamenterefletidasno
aschavesestrangeirascorrespondentesemtodasasmesasdecrianaparamanterasrelaes
Restrio:AlteraesoqueresultariaemumaviolaodeRIsoproibidos

CriaodeRInoVisualFoxProbastantesimpleseoconstrutorRIlidacomtodos
otrabalhoparavoc.Figura7.3,abaixo,mostraosetupemandamentoparaumrelacionalsimples
estruturaqueenvolvequatromesas(NsusamosastabelasdasamostrasVFP"TestData"
bancodedadosparailustrarestaseo).Atagora,asseguintesregrasforamestabelecidas:
228 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela7.4RegraRItpicasetup

Tabelapai Tabelacriana Aao Regra


Cliente encomendas Inserir Ignorar
Cliente encomendas Atualizar Cascata
Cliente encomendas Excluir Restringir
encomendas OrdItems Inserir Restringir
encomendas OrdItems Atualizar Cascata
encomendas OrdItems Excluir Restringir

Asconsequnciasdestasregrassoqueumusuriopodesempreadicionarumnovocliente(Ignorar
InserirCliente),masnopodeexcluirumclientequetemordensemarquivo(Restringiraocliente
Excluir)equalqueralteraochavedeumclienteiratualizaraschavesdeordemcorrespondente(Cascade
Atualizaodocliente).Paratabeladepedidossoasregrasqueumitemdaordemspodeserinserido
contraumaordemvlida(Restringirordemdeinsero),quenenhumaordempodeserexcludoenquantoeletemitens
associadoaele(RestringirOrdemExcluir)equequaisqueralteraesaovalordechavedeumpedidoser
refletidoemtodosositensaqueserefere(CascadeOrdemdeatualizao).

Figura7.3UsandooconstrutorVFPRI

LimitaesdoCdigoRIgerado
Infelizmente,aimplementaonoVisualFoxPronomuitoeficientegerandoregrasRI
paraummontedetabelasresultadoemumaquantidadeenormedeclssico"deestiloxBase'cdigodeprocedimento

Captulo7:Trabalhandocomdados 229
sendoadicionadosaosprocedimentosarmazenadosemseurecipientedebancodedados.Asregrasdefinidasno
exemploacimaresultouem636linhasdecdigoem12procedimentosseparados.Cadamesatemasuaprpria
procedimentonomeadoparacadadisparogeradosportanto,noexemploacima,soprocedimentos
geradocomonome:
PROCEDIMENTO__RI_DELETE_customer
__RI_DELETE_ordersPROCEDIMENTO
__RI_INSERT_orditemsPROCEDIMENTO
procedimento__RI_UPDATE_customer
__RI_UPDATE_ordersprocedimento
__RI_UPDATE_orditemsprocedimento

(Noteseainconsistncianacapitalizaodo' PROCESSOpalavrachave'!)Adicionandomais
mesasemaisregrasaumentaaquantidadedecdigo.Almdisso,estecdigonobemcomentado,
eemversesanteriores,continhavrioserrosquepoderiamcausarcomqueelefalheemcertas
condiespelomenosumdosquaistempersistidoatravsdeparaamaisrecenteversodoVisual
FoxPro.
OcdigoaseguirlevadodiretamenteapartirdosprocedimentosarmazenadosgeradospeloVFPV6.0
(Build8492)paraoexemploacima:
procedimentoRIDELETE
llRetVallocais
llRetVal=.t.
IF(ISRLOCKED()e!Excludo())OR!RLOCK()
llRetVal=.F.
OUTRO
SE!Excludo()
EXCLUIR
IFCURSORGETPROP('BUFFERING')>1
=TABLEUPDATE()
FIMSE
llRetVal=0=pnerror
ENDIFnojeliminada
FIMSE
DESBLOQUEARRECORD(RECNO())
RETURNllRetVal

Vocvainotarquealinhaemitlicodecdigocolocadoincorretamente,edeveestarfora
da SE!DELETED()bloco.Talcomoest,ovalorderetornoapartirdestecdigopodeestarincorreto
(dependendodovalorde'pnerror'nomomento)seafichaasertestadajestmarcadopara
eliminao.
Paraalmdestebugespecfico,eapesardascrticasdirigidasaomecanismode
gerarocdigodoRI,ocdigoefectivamentefuncionabemquandoutilizadoemmesasquesoestruturados
damaneiraqueeraesperado.certamentemaisfcildeusaroconstrutorRIdoquetentareescrever
oseuprpriocdigo!H,noentanto,umaprecauoadicionalateremcontaquandoutilizaroRI
construtor.

Usandochavescompostasemrelacionamentos
AogerarocdigoRIparaastabelasnoexemplo,esteavisofoiexibido:

230 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura7.4Aviso!

Quediabosissosignifica?claroqueumsrioavisoouVisualFoxProno
gerlo!Arespostaqueondiceregularusadacomoalvoparaarelaopersistente
entreatabelaPedidoseOrdItemsrealmentebaseadoemumachavecompostaquecompreendeo
chaveexternaparaatabelaEncomendasmaisonmerodoitem.Aexpressodendiceemquestoo
aqueleusadonatabelafilhoorditems,quenaverdade" order_id+STR(line_no,5,0)".(Este
foicriadodemodoquequandoositenssoexibidoselesapareceronaordemdonmerodalinha.Naverdadeno
umacoisarazovelafazer!)Noentanto,qualquertentativadeinseriroumodificarumregistronacriana
mesa(orditems),ircausarumerro'accionadorfalhou'.
Oproblemaquequalquerregracriadanessatabelaqueprecisaparasereferiratabelapai
vaiusar,comoumachaveparao SEEK(),osvaloresdoscamposconcatenadosdetabelafilho.Issovai,
Obviamente,semprefalhamumavezqueachaveparaatabelapai('ordens')apenasaprimeirapartedo
chaveconcatenadanacriana.Comodizoaviso,vocpode(facilmente)editarogerado
cdigodemodoaqueovalordachavecorrectautilizadonestassituaes.
Oextratoaseguirmostraoproblema:
__RI_UPDATE_orditemsPROCEDIMENTO
***Outrocdigoaqui***
***Ento,temososvaloresantigosenovosparaatabeladecriana
SELECIONAR(lcChildWkArea)
***Aquiondesurgeoerro!!!
lcChildID=ORDER_ID+STR(LINE_NO,5,0)
lcOldChildID=OLDVAL("ORDER_ID+STR(LINE_NO,5,0)")
***Outrocdigoaqui***
***Seosvaloresmudaram,temosumproblema!!!
IFlcChildID<>lcOldChildID
pcParentDBF=DBF(lcParentWkArea)
***Eaquiondetudoderrado
llRetVal=SEEK(lcChildID,lcParentWkArea)

***Eaquiondeoerrorealgerado
SENOllRetVal
FAZERrierrorcom1,"Inserirrestringirregraviolada.","",
IF_triggerlevel=1
FAZERCOMriendllRetVal
ENDIFnofinaldonvelmaisaltodedisparo
ENDIFestevalorfoimudado

Captulo7:Trabalhandocomdados 231

UmavezqueachaveparaaidentificaodecrianascodificadoquandoocdigoRIgerado,aedioreal
requeridamuitosimplesbastaapagaraconcatenao.Infelizmenteasalteraess
mantenhabom,desdequevocnovoltaragerarocdigoRI.
Averdadeirarespostaaesteproblema,noentanto,muitosimples.Apenasnofazlo!Comonstemos
jfoisugerido,chavessubstitutasdevesempreserusadopararelacionartabelasparaquevoctenhauma
mtodoinequvocodejuntarduasmesasjuntos.Emadiossuasvirtudesoutros,elestambm
garantirquevocnuncaprecisarusarchavescompostas,afimdefazercumprirRI.

OquesobreoutrasopesdeRI?
Oconstrutornativolidacomapenastrsalternativaspossveisnomomentodeexecuo,peloRICascade,
RestringireExcluirefazasuposiodequeosregistros"rfos"sosempreuma"coisaruim".
Naprtica,issononecessariamenteocaso(desdequevocprojetaparaessacontingncia!)E
existepelomenosumcasoemqueuma"adoptar"oposeriatil.Considereasituao
quandoumvendedor,queresponsvelporumgrupodeclientese,consequentemente,paraassuasencomendas,
deixaaempresa.NaturalmenteprecisoindicarqueIDdessevendedorjnovlidacomo
ovendedorresponsvelpelosclienteseprecisoatribuirumanovapessoa.Masoque
sobreasordensdovendedorrealmentetomouenquantotrabalhavaparaaempresa?
Senssimplesmenteexcluirovendedor,umRI"Restringir"regraserianopermitiraeliminar,porque
hregistros"filho"paraessachave.Oquerealmentenecessrioumavariantedaregraexclusoque
diz:
"Seoregistropaiestsendoexcludoeumachavevlidafornecidoatribuirqualquercrianaexistente
registrosparaachaveespecificada."
IssoaindanoestdisponvelnoVisualFoxPro,masumgatilhoqueimpeumatalregraseria
fcilosuficienteparacriar,ocdigopseudosimplesmente:

Verifiquesetodososregistrosexistemreferenciandoachaveaserexcluda
Senenhuma,permitirqueaexclusoedesada
Seumnovo,vlidochavefoiespecificado
Alterartodososregistrosfilhoexistentesparaanovachave
Excluiroregistropaioriginal
Sada

QuermaisdetalhessobreRI?
ParamaisdetalhessobreoassuntodeRInoVisualFoxProeumexemplodeumacompletaSQL
alternativabaseadanocdigoRInativa,nopodemosfazermelhordoqueencaminhloparaoCaptulo6da
excelente"TcnicaseficazesparadesenvolvimentodeaplicaescomVisualFoxPro6.0,"porJim
BootheSteveSawyer(HentzenwerkePublishing,1998).

UsandodisparadoreseregrasnoVisualFoxPro
Primeiroprecisamosdealgumasdefinies.Disparadoreseregrasspodemserimplementadasparatabelasqueso
partedeumrecipientedebancodedadosparapermitirqueodesenvolvedorparalidarcomquestesrelacionadascoma
Acionasomenteofogoquandoosdadossogravadosnatabelafsicaparaqueelesnopodemserusados
integridadedosdados.
paraaverificaodevalorescomoelessoinseridosemumatabelatamponada.Naverdade,existemdoisconjuntosde
regrasdisponveisRegrasdecampoetabeladeregras.Tantoanveldecampoenveldetabela(oumais

232 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

compreciso,"nveldelinha")regraspodemfazerrefernciaoumodificarqualquercampoindividualoucombinaode
nalinhaatual.Regrassoacionadossemprequeoobjetoaoqualelessereferemperdeofoco
campos
seatabelatamponadoounoeporissopodeserusadoparaavalidaodedadoscomoeleinserido.

Ento,qualadiferenaprticaentreum'gatilho'euma'regra'?
Umgatilho,conformeimplementadonoVisualFoxPro,umtestequeaplicadosemprequeobancodedados
detectaumaalteraoaserescritoparaumadesuastabelas.H,portanto,trstiposdegatilhos
umparacadaumdostiposdealteraesquepodemocorrer(Insert,UpdateeDelete).Aessncia
umgatilhoqueaexpressoquechamaeledeveretornarumvalorlgicoqueindicaseo
mudanadeveserautorizadoaprosseguirouno.Istomaissimplesseogatilhosisempreretorna
umvalorlgico,portanto,seumgatilhoretornaumvalorde .F.ocorrerumerro(Error#1539'Gatilho
Falha')eaalteraonoestcomprometidocomatabelasubjacente.Osdisparadoresnopodeserusadopara
alterarosvaloresnoregistroquecausoulosaofogo,maselespodemserusadosparafazermudanas
emoutrastabelas.Umusomuitocomumdegatilhos,portanto,paraacriaodelogsdeauditoria!(De
Apropsito,sevocestseperguntandoporqueexisteestarestrio,bastaconsideraroqueaconteceriase
vocpoderiamudaralinhaatualnocdigoquefoichamadosemprequemudanasnalinhaatual
foramdetectados!).
Comogatilhos,aschamadaspararegrastambmdeveretornarumvalorlgicomasaocontrriodegatilhos,elespodem
fazeralteraesaosdadosnalinhaaquesereferem.Almdisso,umavezqueelesfazemfogoparatamponada
tabelas,asregraspodemserutilizadasparaefectuaravalidaodiretamentenoUIdeumaplicativo,assim,
evitandoanecessidadedeescreverocdigodirectamentenainterface.Umaregratambmpodeserusadopara
modificarcamposquenofazempartedainterfacedousurio(porexemplo,uma"ltimaalterao"dataouumcampoiddo
Naprtica,anicadiferenaentreocampoeasregrasdatabelaquandoelessodisparados.
usurio).
Ambososdisparadoreseregrasaplicveis(comoqualqueroutroprocedimentoarmazenado)seatabelaem
perguntaabertanumaaplicaoouapenasemumajanelaProcurar.Asdiferenasentre
Disparadoreseregraspodemserresumidasassim:

Tabela7.5Diferenasentredisparadoreseregras

Item Incndios Capacidade


Regracampo Quandoocampoperdeofoco Podemfazerrefernciaoumodificarqualquercamponoregistro
Regratabela Quandooregistroponteirosemove Podemfazerrefernciaoumodificarqualquercamponoregistro
Gatilho QuandoosdadossosalvosemdiscoNopossvelmodificardadosnoregistroquedisparouo
gatilho

Porque,aoadicionarumdisparadorparaumatabela,noVFPvezesrejeitam
isto?
Normalmente,issoindicaqueosdadosquevoctememsuamesajestemconflitocomaregra
vocesttentandoaplicar.(svezesvocvaiverumproblemasemelhanteaotentaradicionarum
ndicecandidatoaumamesapovoada.)Quandovocalterarumatabelaparaadicionarumdisparadorouregra,Visual
FoxProaplicaessetesteparatodososregistrosexistentesseosdadosemumregistroexistentenoaregra,
entovocirobteresteerro.Anicasoluocorrigirosdadosantesdevoltaraaplicararegra.
Captulo7:Trabalhandocomdados 233

Verifiquealgicaemsuasregrascuidadosamente
Outrarazopossvelparaerrosquandoaplicaoderegrasoudisparadoreslgicadefeituosaporpartedo
odesenvolvedor.Vocprecisatercuidadoaodefinirregrasparagarantirquevocnoinadvertidamente
jogueVisualFoxProemumloopinfinito.Issopodefacilmenteacontecerquandoseusaumaregraparaalterar
osdadosporqueamudanafazcomquea mesmaregraparadispararnovamente.Porexemplo,oseguintecampo
regrafarcomqueuma"DoAssentamentoNveldeerro":

IF!EMPTY(ALLTRIM(clicmpy))ENOALLTRIM(Proper(clicmpy))==ALLTRIM(clicmpy)
***Foraroformatoparamaisculas!(Estaumaregraabsurdo!)
SUBSTITUIRclicmpyCOMUPPER(clicmpy)
FIMSE

Arazoqueelepodesimplesmentenuncatersucesso!Otesteindicarealmenteque,seocampo
noem PROPER()formato,alterlopara UPPER().Portanto,aprimeiravezqueestaregraincndios,Visual
FoxProestbloqueadoemumloopinfinitoondeseencontraocampoestnoformatoerrado.Issoento
alteraoformatoparaoutroformatoquedisparaaregradenovo,masocampoaindaesterrado
formato,assimquemudalonovamente...eassimpordianteadinfinitum!Aregraaseguirvaitrabalharcomo
esperado:
IF!EMPTY(ALLTRIM(clicmpy))ENOALLTRIM(Proper(clicmpy))==ALLTRIM(clicmpy)
***Foraroformatodemaisculaseminsculasadequado
SUBSTITUIRclicmpycomadevida(clicmpy)
FIMSE

Possodesativartemporariamenteumgatilhoougovernarento?
Certamente.Amaneiramaisfcildefazerissoincluirumtesteparaumabandeiranveldeaplicao,(ouseja,quer
umavarivelque"pblico"paraaaplicao,ouumapropriedadeemumobjetodeaplicao)nocdigo
queodisparadorouregraimplementos.Gostaramosdesugerirousodeumavarivelporquevoctambmpode
querofazerissoforadeumaplicativoemaisfcilparacriarumavarivelpblicado
linhadecomandodoqueterqueinstanciaroaplicativoobjetocadavezquevocquiserusarum
mesa.Ocdigoaseguir,colocadonoprocedimentoarmazenadoechamadoporumgatilhosimplesmente
devolverumvalorde .T.,quandoavarivelespecificadanoforencontrada:

IFVARTYPE(glDisableRules)="L"E!Vazio(glDisableRules)
RETURN.T.
FIMSE

Umaperguntaquevocpodeestarseperguntandoporquealgumiriaquererdesativarosgatilhosou
regrasdepoisdeteridoparatodootrabalhodeconfigurlos?Podeserquesevocestfazendoum
carregamentoemmassadedados,ouumblocode REPLACE,apenadevalidarcadalinhaindividualmenteretardaria
coisasparabaixodemaisespecialmentequandoasmudanasjforamprvalidadosantes
sendoaplicado.Seestaumacaractersticadesuaaplicaopoderealmentesermelhorparaadicionarumseparada
procedimentoarmazenadoparatestarseasregrasdevemseraplicadasouno,echamlodetodososgatilhosou
regra.Assim:

234 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ApplyRulesFUNO
llRetValLOCAL
STORE.T.AllRetVal
***Testeparaapresenadavarivelincapacitante
IFVARTYPE(glDisableRules)="L"E!Vazio(glDisableRules)
llRetVal=.F.
FIMSE
RETURNllRetVal

Cadafunodegatilhoouregra,ento,comear:

SomeTriggerFUNO
ESE!ApplyRules()
RETURN.T.
FIMSE
***Cdigodegatilhorealaqui
imperativoqueseusgatilhoseregrasretornarumalgica.T.,quandoseucdigo
noestaserexecutado,casocontrrio,umerro'accionadorfalhou'sergerado.

Comofaopararealmentecriarmeusprocedimentosdegatilhoedaregra?
Ocdigoreal,supondoquevocprecisamaisdoqueumaregradeumalinhasimples,pordisparadoreseregras
melhorarmazenadonorecipientedebancodedadoscomoumprocedimentoarmazenado.Istonoumrequisitoabsoluto,
desdeVisualFoxProiriaencontrarumprocedimentomesmoquenoestavamnocontinerbancodedados
(desdequeoarquivonecessriotinhasidoestabelecidocomum" ProcedimentoSetTo"decomando).
Noentanto,umavezqueoprocedimentopodesernecessrio,emqualquermomentoatabelaquechamausado,ele
fazmaissentidoparadeixlonocontinerbancodedadosparaqueeleestejadisponvelsempre,e
Noentanto,oquadroutilizado.
Portanto,aquestopermanececomoquesecrieocdigoreal?H(comodecostumeemVisual
FoxPro)duasopes.VocpodefazlodeformainterativautilizandooEditarStoredProcedures
opoquandomodificarobancodedadosousimplesmenteemitindo alterarosprocedimentosdo
janeladecomando.Voctambmpodeescrever(etestar!)Seucdigoemumarquivodeprogramastandalonee
adicionloaosprocedimentosarmazenadospormeiodeprogramaousando PROCEDIMENTOSAPPENDFROM
<filename>.Dequalquerforma,vocdeveprimeiroteraberto,efezatual,obancodedadosrelevante.

GotchacomocomandoAnexarProcedimentos
HumacoisaateremmenteaousarocomandoAnexarProcedimentos.OarquivodeAjuda
comentriossobreestecomandosoliteralmenteexactanoquedizrespeitodaquiloqueo OVERWRITEclusulade
estecomandorealmentefaz.OarquivodeAjudaafirmaqueo OVERWRITEclusula:

Especificaqueosprocedimentosarmazenadosatuaisnobancodedadossosubstitudospor
aquelasnoarquivodetexto.

Issonosignificaque"qualquerprocedimentocomomesmonomeserosubstitudos",ele
significaexatamenteoquediz.TODASprocedimentosatualmenteemseucontinerbancodedadossoeliminados

Captulo7:Trabalhandocomdados 235

esubstitudoportudooqueestnoarquivodeorigemquevocespecificar.altamenterecomendvelque
vocconsignaraclusulasobrescreverdestecomandoparaalixeiraagora.

Masseeuestouatualizandoaumprocessosem"substituir",issonosignificaqueeuacabar
comduas?
Naverdadeelefaz.Sevocjtemumprocedimentonorecipientedebancodedadoschamado' mytestproc'
eemseguida,acrescentarumanovaversodomesmoprocedimento,vocterdoisprocedimentosdenominados
' Mytestproc'nabasededadosdorecipiente.Felizmente,oprocedimentorecmacrescentadairserpelo
ofimdoficheiroe,portanto,sersempreaversoqueVFPcompilarealmente,eutilizaes.
Enquantoissopodeparecerconfuso,eleirfuncionarcorretamente.Noentanto,vocnodeverealmentedeixaro
continerbancodedadosnesseestadoe,logoquepossvel,vocdeveteracessoaelaeexcluir
quaisquerprocedimentosredundantes.
Umaabordagemalternativaadesempremanterprocedimentosarmazenadoscomoumcompletoconjuntode
procedimentosdesubstituioemumarquivoexternoe,emseguida,usaraclusulaOVERWRITEde APPEND
PROCEDIMENTOSparaforarasubstituiototaldetodososprocedimentos.Sevocpraticarversoestanque
controlarvocpodesesentirconfianteosuficienteparafazerissoemumaplicativodetrabalho.(Nocasoemque,a
ParafraseandoRudyardKipling,"Vocumhomemcorajosodoqueeu,GungaDin".)

Comofaoparaadicionarumdisparadorparaumatabela?
Talcomoacontececomocdigonoprocedimentodegatilho,estepodeserfeitodeformainteractivanatabela
desenhador,inserindoaexpressoapropriadana"Tabelaguia"dacaixadedilogo,ou
programaticamenteusandoo comandoCREATETRIGGERcomando.Lembresequeaexpressochamando
deveseravaliadacomoumvalorlgico,eprefervelqueumachamadaparaumprocedimentoarmazenadodeve
retornarumvalorlgico.Dequalquermaneiravocvaiexigiracessoexclusivotabela.

Ento,quandoeudeveriausarumgatilho?
Aresposta,comosempre,queeledependedesuasnecessidades.Triggerssonormalmenteutilizadospara
ou(e,porvezesambos)dosdoismotivos.Emprimeirolugar,paramanteraintegridadereferencial(RI)e
istocomoVisualFoxProimplementaocdigogeradopeloconstrutorRI.Emsegundolugar,paracriar
trilhasdeauditoriadecontroledealteraesaumatabela.Lembresequeumgatilhosacionadoquandomudanas
umatabelafsicasofeitaseporissonotmqualquerrelevnciaquandosetrabalhacomdadosembuffer.
Valeapenanotarque,dentrodeumgatilho,arestriodequea GetFldState()e
OLDVAL()funespodemunicamenteserutilizadoemtabelasquetmtamponamentoativadonoseaplica.
Ambasasfunesfuncionarosemerro,mesmoemtabelastampodaONU,queextremamentetil
aocriartrilhasdeauditoriadentrodispara.

Umexemplodetrabalhousandodisparadores
Ocdigodeexemploparaestecaptuloincluiumpequenobancodedados('Auditlog')eumaformasimples
('FrmAudit''),queilustracomogatilhospodeserusadoparaconstruirumlogdeauditoria.Oformulriopodeser
executarautnomodiretamentedalinhadecomandousandoo FORMULRIODOcomando.Asmesastm
foiconstrudocomosesegue(oscamposprefixadoscomum'#'soaschavesprimrias):

236 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura7.5Tabelaslogdea uditoria

Gatilhosnatabelade"da"adicionardadosstabelasdeauditoriasemprequeumamudanaestcomprometida,
noentantoapenasositensquesorealmentemudouobterescritosduranteumaatualizao(todosositensso,
pordefinio,mudouquandofazerqualquerumainseroouexcluir).Outrosprocedimentosarmazenadossousados
paraimplementarumpadro"newidfuno"paragerarchavesprimrias,etambmparaimplementarum
regracampoparaoclculodovalordeumstockartigoquandotantoumaquantidadeeumcustosofornecidos.
Afuncionalidadedelogdeauditoriatratadopelo"BildLogfuno"consisteemtrs
peas.Emprimeirolugar,porqueafunousarumatransao,elegarantequetodooapoio
mesas(incluindogeraodetabeladoPK)estodisponveiseembomestado.Nsnopodemos
alteraromododebufferdeumatabeladentrodeumatransao,assimquearotinanormalgeraoPK
(QuevaiabriratabelaedefinirBufferMode=1)porcausarumerro,amenosqueoquadroest
jestaberto.
Aprximapartedogatilhoiniciaumatransaoeinsereonomedatabelaeao
(Quesopassadoscomoparmetrosparaogatilho),maisadataatual,tempoeIDdeusurioparao
logdatabeladecabealho.Estainseroentocometidosantesdequalqueroutraaotomada.
Porltimo,masaindadentrodatransao,ainseroparaatabeladedetalhesdeauditoriatratado.UMA
grandeproblemacomologdeauditoriaparaevitarqueastabelasdelogdeficarmuitograndequepodeser
umproblemarealcommesasdealtaatividade.Ocdigoaquiapenasgravaoscamposquetm
realmentemudouquandoumaatualizaoestocorrendoemboratodooregistrodeveserescritopara
Todasasinsereseexcluiqueajudaaminimizaradimensodastabelas.
Oformulriodeexemplo,apesardesimples,completamentefuncionalepermiteaadio,exclusoe
ediodatabela"da"naprimeirapginaeusaumpontodevista,construdoapartirdastabelasdelogdeauditoria,
aavaliarohistricodealteraesparaatabelanapginadois.Figura7.6mostraasduaspginasde
aforma.
Captulo7:Trabalhandocomdados 237

Figura7.6formaLogDemonstraodeAuditoria

Equandodevousarumaregra?
Asregrassomaiscomumenteutilizadoparavalidaodosdadose,umavezqueelesfogosobredadosembuffer,
podeserusadoparamanipular"prsalvar"validao.Aoprsavevalidaoqueremosdizerverificarqueo
dadosqueforaminseridosoumodificadosnovai,porsis,causarumainseroouatualizaofalhar.
SevocusaumaregradecampoouumaregraTabelavaidependerdequandovocdesejaquearegraparadisparar
(verTabela7.5paramaisdetalhes).
Outrousocomumderegrasparaamanutenodecamposcalculados(oudependentes)dentrodeum
registro.Apesardofatodequeasregrasparanormalizarosdadosparaoterceiroestadoformanormalqueumalinha
nodeveriacontercamposquesoderivadosunicamentedeoutroscamposnamesmalinha,existem
muitasocasiesemqueainclusodetaiscamposbenfica.Normalmente,isto,quandoastabelasso
susceptveisdeobtergrandeseasobrecargadevaloresdependentesclculorecadavezqueumformulrio,
relatrioououtraconsultaexecutadatornaseinaceitvel.(Emoutraspalavras,"denormalizaopara
desempenho").Taldenormalizaocarregacomeleoproblemadegarantirqueocalculado
campossomantidascorretamente,masumaregrasimples,inseridocomoumaregradecampo,irgarantirque
coisasnopodemficarforadesincronizao.
Porexemplo,considereasituaoemqueumamesausadopararegistrardetalhesdaslinhasde
umafatura.Normalmentevocvaitercamposparavendapreoequantidadeencomendada.Paraexibircada
ovalordalinha,semrealmentearmazenarosdadoscalculado,requercdigonainterfacedousuriodocontroleda
VlidasouLostFocusmtodosparavoltaracalcularovalor.Aoincluirumcampodevalornatabela,
vocpodeusarumaregraemvezesimplesmenteligarum(ReadOnly)controleaessecampo.Aquiestum

238 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

exemplodetalregraqueseriachamadotantopeloPreodevendaedaquantidadeencomendada
Campos:

CheckLineValFUNO
IFNVL(SalePrice,0)#0ENVL(QtyOrdered,0)#0
IFLineValue#SalePrice*QtyOrdered
SUBSTITUIRLineValueCOM(SalePrice*QtyOrdered)
FIMSE
OUTRO
IFNVL(LineValue,0)#0
SUBSTITUIRLineValuecom0
FIMSE
FIMSE
RETURN.T.

Nsprecisamoschamlodeambososcamposparagarantirqueoqueforalterado,ovalor
atualizadocorretamente.Notequenstambmverificarelidarcomvaloresnulos.Umaregramuitosemelhante
usadonatabela"da"noexemplo"AuditLog"paraestecaptuloparacalcularovalorde
aesdetidas.

Deveumdisparadorouregrasempresereferemaumanicafuno?
Anicaexignciaqueaexpressoquevocusaparachamarumdisparadorouregradevesempre
avaliadacomoumvalorlgico.Desdequevocpodeconstruirasuaexpressochamandoparaque
FoxPropodeavaliarloparaumvalorlgico,nohnenhumarestriononmerode
funesquepodemserchamadas.Asseguintesexpressessoperfeitamentevlidotantocomoumgatilho
ouumaregra:
RegraField:SalePrice#0ECheckLineVal()
Mensagem:"PreodevendanopodeserdeUS$0,00Paralevantarumcrdito,insirapreoinferior
$0.00"
a.

RegraField:QtyOrdered>0eCheckLineVal()
Mensagem:"Quantidadenopodeser0.Paralevantarumcrdito,insirapreoinferioraUS$0,00"

Usandodisparadoreseregras,noentanto,imporumasobrecarganoprocessodetomada
mudanasecometendodadosparatabelas.Asmaiscomplexasasregras,quantomaiso
navegaoesalvarrotinasterdeexecutar.Comosemprehumtradeoffentre
maiorfuncionalidadeedesempenho.Onvelqueaceitvelemqualquersituaopoderealmente
spodeserdeterminadoportentativaeerro,nocontextoderequisitosdaaplicao.

Captulo8:OsdadosembuffereTransaes 239

Captulo8
Osdadosembuffere
transaes
"Asprimeirasfalhassodelesqueoscometem,osegundodelesquelhespermitam."(Velho
InglsProvrbio)

TodootemadousodebufferdedadosetransaesnoVisualFoxProum
intrinsecamenteconfusoumquenoajudadopelaescolhadaterminologiaassociada
comafuncionalidade.Estecaptuloprocuradesmistificarasquestesemtornodetamponamento
etransacesemostracomovocpodeusarasferramentasdoVisualFoxProforneceaos
gerenciardadosdeformamaiseficaz.

Usandoobufferdedados
Ondeestamosvindo?
Talcomoreferidonaintroduodestecaptulo,trabalhandocombufferdedadosnoVisualFoxPro
parececausarmuitaconfuso.Nssentimosqueesteemgrandepartedevidoaopoucoconfuso
implementaodetamponamento,eumpoucoestranho(paraospadresaceitos)Nomenclatura
associadocomoassunto.
Porexemplo,paradefinirobufferparaumVisualFoxProDBFarquivo(queumatabela),temosde
usarosobrecarregado CURSORSetProp()funo.Porquenoumseparado,semambiguidades,
' )SetBufferMode('funo?Enquantoparaconfirmarumatransaopendente,ocomando END
maispeculiardesdeostandard'
.TRANSACTION Porqueno' COMMIT 'comoemqualqueroutralinguagemdebancodedadosumaescolhaque
ROLLBACK comando'usadoparadesfazerumatransao?
aindaPoroutrolado,talvezporcausadamaneiraemqueFoxProimplementaficha(como
oposioa"Pgina")debloqueio,aquestodecontrolaracolocaoeliberaodebloqueios
aparentementeinextricavelmenteligadobuffering.Porexemplo,afimdepermitirfileira
tamponamento,quesoperaemumnicoregistro, SETMULTILOCKSdeveser ONmasdeacordo
oarquivodeAjudaestadefinioapenasdeterminaacapacidadedoVisualFoxProparabloquearvriosregistros
namesmamesaequetemcomoescopoasessodedadosatualdequalquermaneira.Issonoparecemuito
lgicaenorealmentesurpreendentequeficarconfusoportudo.

Oquequeremosdizercom'buffer'dequalquermaneira?
Oprincpiorealmentemuitosimples.Oconceitodebufferingquequandovocfazalteraes
aosdados,essasalteraesnosoescritasdiretamenteparaatabeladeorigem,emvezdisso,entraremum
'readeespera'(o'buffer')ataomomentoemquevocinstruirVisualFoxPro,querguardlaspara
armazenamentopermanenteoudescartlas.Figura8.1ilustraoconceito.Estareadeespera
oquevocrealmente"ver"noVisualFoxProaousarumatabelaembuffere,narealidade,um

240 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

cursoratualizvelcombasenatabeladeorigem.Todasasalteraessofeitasparaestecursoresoapenas
escritaparaatabelasubjacentequandoocomando"update"apropriadoemitido.

Figura8.1bufferdedadosconceituada

estratgiasdetamponamento
Astabelaspodemserusadascomtrsdiferentes"EstratgiasBuffer".Aprimeiraoponousar
tamponantedetodo.
EstafoianicaopoemtodasasversesdoFoxProantesdoVisualFoxProVerso3.0e
aindaocomportamentopadroparatabelasdoVisualFoxProhoje.Estemodopodeserdefinidaexplicitamente
usando CURSORSETPROP("buffer")comumparmetrode"1".Todasasalteraesfeitassoescritos
diretaeimediatamentetabelasubjacente.Noh'undocapacidade"amenosqueseja
programadoexplicitamenteusando SCATTERe REUNIRporexemplo.
Asegundaopopara"Rowbuffer",quedefinidoutilizando
CURSORSETPROP("buffer")comumparmetrodequalquer"2"ou"3".Asalteraesnosoenviadaspara
atabelasubjacente,amenosqueumadasduascoisasacontece.OuumexplcitaTableUpdate()ou
TableRevert()comandoemitidonocdigo,ouoponteirodoregistromovidonasubjacente
mesa.Qualquermovimentodoponteirodoregistro,noentanto,iniciadaporumamesaqueestnalinha
mododebuffer,sempreprovocaum'implcita'TableUpdate().
Aterceiraopopara"Tabelabuffer",quedefinidoutilizando CURSORSETPROP('Buffering')
comumparmetrodequalquer"4"ou"5".Nestemodoasmudanasnuncasoenviados"automaticamente"
tabelasubjacente,umaexplcitaTableUpdate()decomandosempredeveserusadoparaenviarmudanasno
obufferparaatabelasubjacente,ouTableRevert()paracancelarasalteraes.Atentativadefecharuma
mesa,enquantoeleaindatemalteraesnoconfirmadascausadoVisualFoxProparagerartamponadatable
umerronaverso3.0,masessecomportamentofoialteradoemversesposterioresparaqueasalteraespendentes
Captulo8:OsdadosembuffereTransaes 241

sosimplesmenteperdido.Nohnenhumerro,enenhumavisodequemudanasestoprestesaserperdida,o
tabeladebufferapenasfechado.

Bloqueandoestratgias
Intimamentecomtamponamentoaquestodo"bloqueio".VisualFoxProsempreprecisabloquear
oregistrofsicoemumatabelaenquantoasalteraesestosendofeitasparaoseucontedo,ehdois
possveisestratgias.
Emprimeirolugar,umregistopodesertrancada,logoqueumutilizadorcomeaafazermudanas.(Obloqueio
efectivamentecolocado,logoqueumateclavlidadetectado.)EstaaLockingpessimista'e
impedequalqueroutrousuriodefazerousalvarasalteraesparaesseregistroatqueousurioatualtem
concluremasalteraeselanouodiscodeconfirmaroureverterasua
alterar.
EmsegundolugarVisualFoxPropodetentarbloquearumregistroapenasquandomudanassoenviadosparao
mesa.Estaabloqueiootimista"esignificaquemesmoqueumusurioestfazendoalteraesaosdados,
oregistropermanecedisponvelparaoutrosusuriosquetambmpoderiafazer,e,possivelmente,salvar,asalteraes
omesmoregistoenquantooutilizadoraindaesttrabalhandonele.

modosdetamponamento
O"tampodemodo"paraumatabela,porconseguinte,acombinaoespecficadamemriaintermdiae
Bloqueandoestratgias.HumtotaldecincomodosdetamponamentoparaumamesacomoilustradopelaTabela
8.1.

Tabela8.1ModosVisualFoxProBuffering

Modo BloqueandoBuffer Comente


1 Pessimista Nenhum AnicaopoparaFP2.x,padroparaVFP,tabelas
2 Pessimista Linha BloquearcolocadopeloKeyPressevento.movimentoponteirodoregistro
forassalvar
3 Otimista Linha BloqueiocolocadopelaTableUpdate().movimentoponteirodoregistro
forassalvar
4 Pessimista Mesa BloquearcolocadopeloKeyPressevento.Guardardeveseriniciado
explicitamente
5 Otimista Mesa BloqueiocolocadopelaTableUpdate().Guardardevemseriniciadasexplicitamente

AotrabalharcomVisualFoxPro,devemosterocuidadodedistinguirentreo
individuaisestratgiasqueestamosestabelecendoparaobuffereLockingeomododebuffer
queresultadacombinaodosmesmos.Infelizmente,comoveremos,VisualFoxPro
emsimenoscuidadososobreestadistino.

Oquesignificatudoissoaocriarformasdeligaodedados?
Istoondeascoisascomeamaficarumpoucomaiscomplexa(enosporcausada
nomenclatura).Vamosconsiderarasituao"normal"ondeasmesassoadicionadosparaformarpela
DataEnvironmentnativa.Oformulriotemumapropriedadechamada'Buffermode",quetemtrspossveis
configuraes:

242 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
0Nenhum(padro)
1Pessimista
2Optimistic

Observequeestesrealmentesereferemsopesparaobloqueioestratgiaenotemnadaa
fazercomtamponamentoemtudo!Defacto,aformadedeterminarseomemriaintermdiaestratgiaparatodasassuas
porsi,combasenasuautilizao.
tabelas
Ocdigodeexemploincluiduasformas"Demone'(Figura8.2)e'DemTwo'(Figura8.3)
que,quandoinicializado,exibirosvaloresparaapropriedadeeoBuffermodedoformulrio
mododebufferdecadatabelanascaixasdetextomarcados.(BuffermodeOformulriospodeserdefinida
naconcepodotempo,entoabriroformulrioealteraraBufferMode,emseguida,executloparaverosresultadospara
asdiferentesconfiguraes.)Ambasasformasusarasmesmasduastabelas,asquaistmumnmerodeumpara
relao,masindicamolado"muitos"darelaodemaneirasdiferentes.Osprimeirosusos
umagrade,enquantoosegundosimplesmentemostracamposindividuaisdirectamentenoformulrio.

Figura8.2mododebufferAutoset,quandoumagradeestpresentenoformulrio

Observequequandoatabela"muitos"exibidoemumagradequeaberto,pelaforma,natabela
mododebuffer.Noentanto,seatabela"muitos"estapenasexibindocamposindividuais,emseguida,o
tamponanteparaatabelaseramesmacomoparaatabela"um"paratodasasconfiguraesdaFormade
BufferModepropriedade.

Captulo8:OsdadosembuffereTransaes 243

Figura8.3mododebufferAutosetsemgrade
SevocexecutaratravsdetodasasopesparaoformulrioBuffermodepropriedade,vocter
notadoque,mesmocomaformadoBufferModepropriedadedefinidacomo0(Nenhum)ocursorcriadopor
VisualFoxProaindaestabertoemlinhatamponadamodoquandoastabelassoabertaspelaformade
DataEnvironment."Nobuffer"aparentementesignifica"bufferdelinha"paraumaforma!
Noentanto,issonoocasoquandoastabelassoabertosdiretamentecomumcomandoUSE.
Form'DemThree'idnticoao'Demone',excetoqueemvezdeusaraformade
DataEnvironmentparaabrirastabelassoabertasdeformaexplcitanacargamtodo.Nisso
asituaodaformaBuffermodepropriedadetemqualquerimpacto,easmesasestoabertas
deacordocomasconfiguraesno'BloqueioeBufferseo'noseparador'Dados'dasOpes
dilogo.Estedilogorealmentenodefiniromododebuffer.Temcincoopesquecorrespondemao
cincomodosdefinidosnaTabela8.1acima,equeutilizarosmesmosidentificadoresnumricoscomoo
CursorSetProp()funo.
Noentanto,asdefiniesespecificadasnajaneladeopessseaplicamaopadro
datasession.Seoformulrioestiverexecutandoumdatasessionprivado,entomesasabertocoma USE
comandoserdefinidoparaomodotudooqueespecificadoparaquedatasessioneeste,porpadro,
serparaamemriaintermdianoemtodos.

Vocestconfusoainda?
Certamente!Tantoquantonspodemosdizer,asituao,naverdade,comosegue:

244 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ParatabelasabertasporDataEnvironmentdeumformulrio,noimportaseoformulrio
emexecuonopadroouprivadadatasession.Astabelassosempretamponadaapelomenos
Rowotimistanvel.
OformulrioBufferModepropriedaderealmentedeterminaaestratgiadebloqueio,noo
mododebuffer,masunicamenteparaastabelasquesoabertospeloDataEnvironmentdessaforma.
Nodatasessionpadro,astabelasquesoabertosdeformaexplcitatemtantoasuatamponamento
eestratgiasdefinidasparaaopoescolhidanodilogoglobaldeOpesdebloqueio.
EmumDataSessionprivada,mesasquesoabertosexplicitamentetmoseutamponamentoe
asestratgiasdebloqueiodefinidodeacordocomasconfiguraesqueseaplicamparaessedatasession(Padro
="Nenhumbuffer").

Estesresultadospodemserverificados,definindoasvriasopesnademonstraotrs
formas.

Ento,comofaoparaconfigurarobufferemumformulrio?
Arespostacurta,comosempre,'depende'.SevocusarDataEnvironmentdoformulrioparaabrir
tabelas,emseguida,normalmentevocpodedeixaraescolhadebufferparaVisualFoxPro.Casocontrrio,voc
podesimplesmenteusaro CursorSetProp()funonocdigoparaconfigurarcadatabelaconformenecessrio.
Dequalquerforma,vocprecisaestarcientedasconsequnciasdemodoquevocpodecodificarasuaactualizao
rotinasdeformaadequada.

usandoBufferModeOv erride
AclasseDataEnvironmentforneceumapropriedadeparacadatabela(ou,maisprecisamente,'cursor')
chamado"BufferModeOverride".Istoirdefiniromododebufferparaatabela(enicaqueatabela)
aumdosseusseisopessim,issomesmo, SEISopes,nocincocomosesegue:

0Nenhum
1(Padro)UseAmbienteformulrio
2bufferdelinhapessimista
3bufferdelinhaoptimista
4bufferdetabelapessimista
5bufferdetabelaotimista

Emprimeirolugarnotarque,emboraosnmerosde2a5jogo,osparmetrospara
CursorSetProp()esoosmesmoscomoaquelesdisponveisatravsdodilogoOpes,ovalor
necessriosparaacriao"sembuffering"agoraa0emvezde1.Estamaisumainconsistnciano
osetupparaobuffer!
Emsegundolugarnotarqueovalorpadroparaessapropriedade"1Useformulriodedefinio".o
forma"ajuste"referido,naturalmente,o"BufferModepropriedade",que,comovimos,
naverdade,paraaescolhadaestratgiadebloqueioparaseraplicada.Nohnenhumadefiniodeformulrio
controlarobuffer!

Captulo8:OsdadosembuffereTransaes 245

Tendoditoisso,definindooBufferModeOverridepropriedadeirgarantirqueatabela
abertousandoomododebufferquevocespecificar.Pelomenosestapropriedadenomeadocorretamente,ele
substituitudoorestoeforaatabelanomododebufferespecificadoemtodasassituaes.

UsandoCursorSetProp()
Independentementedaformacomoatabelaaberta,vocsemprepodeusaro CursorSetProp()funopara
alteraromododetampodeumamesa.Noentanto,sevocnoestiverusandoDataEnvironmentdoformulriopara
abrirsuastabelas,entovoctemduasopes,dependendoseosformulriosdeusaropadro
DataSessionouumDataSessionprivada.Noprimeirocaso,vocpodesimplesmenteajustaromododesejadono
caixadedilogoOpeseesquecla.Todasastabelasserosempreabertocomaquelaconfiguraoe
vocsempresaberondevocest.
SevocusaumDataSessionprivada,entovocprecisafazerduascoisas.Emprimeirolugarvocdevegarantir
queoambienteestconfiguradoparasuportarbuffering.Umasriedeconfiguraesdeambienteso
comoescopoodatasessionevocpodeprecisardemudarocomportamentopadrodealguns,outodos
oseguinte(veraSETDATASESSIONtpiconoarquivodeajudaparaobterumalistacompletadeajustes
afectadas):

MULTILOCKSSET DeveserdefinidocomoONparaativarobuffer,opadroOFF
SETDELETED OpadroOFF
DATABASESET "Nenhumbancodedados"definidoporpadroemumDataSessionprivada
SETEXCLUSIVE OpadroOFFparaumDataSessionprivada
BLOQUEIOSET OpadroOFF
COLLATESET Opadro'mquina'
conjuntoexato OpadroOFF

Emsegundolugar,necessriodefinirexplicitamenteomododebufferdecadatabelausandoo
CursorSetProp()funocomoparmetroapropriado,porqueasconfiguraesnasOpes
DedilogonoseaplicamaDataSessionsprivadas.

Ento,omododebuffereudeveriausaremmeusformulrios?
Parans,arespostasimples.Vocdevesempreusarobufferdetabelacomumbloqueiootimista
estratgia(ousejaTampoModo5).Arazosimplesmenteque,comaexcepodaconstruodeum
ndice,nohnadaquevocpodefazeremqualqueroutromodoquenopodeserfeitonestemodo.Enquanto
linhabufferpodesertilnodesenvolvimento,noacreditamosqueeletemalgumlugaremumtrabalho
application.ThereapenasmuitasmaneirasemqueoimplcitoTableUpdate()(causadaspor
moveroponteirodoregistro)podeserdesencadeada,enemtodoselesestosobnossocontroledireto.
Porexemplo,o KeyMatch()funodefinidanoarquivodeajudacomo

Pesquisasumamarcadendiceouarquivodendiceparaumachavedendice

Parecebastanteinofensivacertamenteprocuraumarquivodendicenopodecausarquaisquerproblemas.masum
nota(nasecoObservaesdireitanofinaldotema)tambmafirmaque:
246 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

KEYMATCH()retornaoponteiroderegistoparaoregistoemquefoioriginalmente
posicionadoantesKEYMATCH()foiemitido.

Seguremsebemali!Certamente'retornaoponteirodoregistro"implicaquesemoveoregistro
ponteirooquedefatoelefaz.Aconsequnciaque,sevocestiverusandoobufferdelinhaequer
paraverificarsehumachaveduplicadausando KeyMatch(),vocvaicometerimediatamentequalquerpendentes
alterar.(claroquenaverso6.0ouposteriorvocpodesempreusarINDEXSEEK()emvezdisso.)Noentanto,
omesmoproblemasurgecommuitosdoscomandosefunesqueoperamsobreumamesa
especialmenteosmaisantigos,queforamintroduzidasemFoxProantesdosdiasdebuffer(porexemplo,
CALCULAR, SUMe AVERAGE).
Ofatodequevoctemumamesaparabufferdetabelanoimpedilodetratamento
amesacomosefosserealmentefileiratamponada.TantooTableUpdate()eTableRevert()
funestmacapacidadedeagirapenasnalinhaatual.Anicadiferenaprtica,
portanto,quequenenhumaatualizaovaiaconteceramenosquevocchamarexplicitamenteTableUpdate().Issopode
significaquevoctemqueescreverumpoucomaisdecdigo,masnoevitarumasriedeproblemas.

Alteraromododebufferdeumatabela
Nsdissemos,noinciodaltimaseo,quevocsemprepodeusar CursorSetProp()paradefinirou
alteraromododetamponamentodeumamesa.Issoverdade,masseatabelajatabelatamponada,ele
podenosertosimples,porquealterandooestadodebufferirforarVisualFoxProparaverificar
oestadodequaisquerbuffersexistentes.
SeatabelaforRowBufferedetemalteraesnoconfirmadas,VisualFoxProsimplesmentecomete
asmudanasepermiteamudanademodo.Noentanto,seoalvoatabelatamponada,evoc
tentarmudaroseumododebufferenquantohalteraesnoconfirmadas,VisualFoxProreclama
elevantaErro1545("tampodatabelaparaopseudnimode"nome"contmalteraesnoconfirmadas").Isto
umproblemaporquevocnopodeindexarumatabelaenquantoeleestivertabelatamponada,entoanicamaneiradecriar
umndiceemtaltabelamudar,temporariamente,paraalinhabuffering.Claro,asoluo
bastantesimplesapenasgarantirquenohajaalteraespendentesantesdetentarmudarotampo
modo.Mascomovocpodefazerisso?

IsChanged()umaoutrafunoqueFoxProesqueceu?
VisualFoxProforneceduasfunesnativasquepodemserusadosparaverificarostatusdosbuffers
GetFldState()e GETNEXTMODIFIED().Noentanto,oprimeirodestestrabalhosapenasna
linhaatualdeumatabelaeosegundospodeserusadoquandoatabelabufferestemvigor.isto
Parecenosqueoqueestfaltandoumafunonicaqueirfuncionaremtodasassituaesedeixlo
saberseexistemalteraespendentesemumbufferdetabela.Aquianossatentativadeescreverumtal
funo:

**********************************************************************
*Programa :IsChanged.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:retornaumvalorlgicoqueindicaseumatabelatem
* :Asalteraespendentes,sejaqualforomododebufferempregados
**********************************************************************
LPARAMETERStcTable
lcTableLOCAL,lnBuffMode,lnRecNo,llRetVal,lcFldState

Captulo8:OsdadosembuffereTransaes 247

***Verifiqueoparmetro,assumeapelidoatualsenadapassado
lcTable=IIF(VARTYPE(tcTable)#"C"ouvazio(tcTable),
ALIAS(),ALLTRIM(UPPER(tcTable)))

***Verifiqueseonomedatabelaespecificadousadocomoumalias
IFEMPTY(lcTable)OR!USADO(JUSTSTEM(lcTable))

***Temosumerroprovavelmenteumerrodedesenvolvedor,portanto,useumerro
denuncilo!
ERROR"9000:IsChanged()exigequeoaliasdeumatabelaabertaser"+
CHR(13)
+"Passou,ouqueareadetrabalhoatualdeveconteruma"+
CHR(13)
+"Tabelaaberta"
RETURN.F.
FIMSE

***Verifiqueostatusdetamponamento
lnBuffMode=CURSORGETPROP('buffer',lcTable)
***Senenhumbuffer,bastaretornar.F.
IFlnBuffMode=1
RETURN.F.
FIMSE

***Agoralidarcomosdoismodosdetampo
SEINLIST(lnBuffMode,2,3)

***SeRowBuffered,useGetFldState()
lcFldState=NVL(GETFLDSTATE(1,lcTable),"")

***SelcFldStatecontmnadaalmde1deentoalgomudou
***Todosos3deindicaumregistrovazio,anexado,masqueaindaum
alterar!
***UseCHRTRANpararetirar1doeapenasversealgumacoisaestesquerda.
llRetVal=!VAZIO(CHRTRAN(lcFldState,"1",""))
OUTRO

***Encontreonmeroderegistrodoprimeiroregistroalterado.
***Registrosanexadosterumnmerorecordequenegativo
***Porissotemosdeprocurarumvalorderetornode"noiguala0",
***Emvezdesimplesmente"maiorque0"
llRetVal=(GETNEXTMODIFIED(0,lcTable)#0)
FIMSE
RETURNllRetVal

Essencialmentetudooqueestafunonodeterminarotipodetampoutilizadoedautilizao
afunonativoapropriadoparaversehalgumamudana.Existem,noentanto,umparde
suposiesaqui.Emprimeirolugar,afunodevumrecmanexado,mastotalmentenoeditada,fileiracomoum"
mudana".Estarazovel,jqueonicoobjetivodeterminarseatabelatem
mudado,noseamudanadevesersalvoouno.Emsegundolugar,paratabelasusandoobuffer
modosde4ou5,nohnenhumaindicaodecomomuitasalteraespodemexistirouseo
"Linhaatual"mudourealmente.Maisumavez,dadooobjectivodestarazovel.
Seriaperfeitamentepossvelalterarocdigoparaabordarestasquestes(talvez
retornarumvalornumricoqueindicadiferentescondies,emvezdeumsimples"sim/no").Nanossa

248 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

pontodevista,noentanto,quepodefazerafunomuitoespecficaparasequalificarcomoumcandidatoparaumgenrico
arquivodeprocedimentoqueondensgostariadecolocarafuno.

Gotcha!Quandoacrescentandoregistroscomv alorespadro
H,noentanto,umproblemapotencialparaestaratentoaousarumarotinacomoesta
um.Sevocestadicionandoumnovoregistroaumatabelaqueforneceumvalorpadroparaumoumais
campos,vocvaiterum"falsopositivoretorno"aotestarumregistrodeoutraformainalterada.este
porqueVisualFoxProinsereumvalorpadroapsoregistroanexadoe,portanto,
vistopelasfunesquetestamcamposcomo'mudou'.Felizmente,humasoluoo
SETFLDSTATE()funopodeserusadaparalimparostatusalteradodeumcampoespecfico.
Humalimitao! SETFLDSTATE()usaosmesmosvaloresnumricoscomosodevolvidospelo
o GetFldState()funo,demodoqueosvaloresde1ou2sereferemaregistroseditados,enquanto3e4
referemsearegistrosanexados.Vocnopodeusar SETFLDSTATE()paraalterarostatusdoregistro,
apenasemcamposindividuais.Assim,vocnopodedizerVFPqueumregistroqueestsendoeditadoderepenteuma
registrorecmanexadoaoalteraroestadodetodososseuscamposa"3",ouqueumanexado
registrorealmenteestsendoeditado,alterandoseuscamposdeafirmar"2".Ocdigoaseguirmostraoque
acontece:

***OpenTable,adicionarumregistroeverificaroestado
demoneUSE
CURSORSETPROP('Buffering',5)
APPENDBLANK
?GETFLDSTATE(1) &&retorna"3433"

Lembrese, GetFldState(1)sempreincluioestadododoregistroexcludomarcarcomo
oprimeiroitemnasuaseqnciaderetorno.Assim,ovalorderetornoaqui,naverdade,indicaqueoprimeirocampoem
atabelafoialterado(comoseriadeesperar,umavezqueoSIDcampoetemumvalorpadroespecificado).

***AgoratentealteraroestadocampoparaocampoKey
***Para'noeditada"
?SETFLDSTATE(1,1)

IssogeraimediatamenteErro11,"valordeargumentodefuno,tipooucontageminvlida"
porqueoregistronosendoeditado,umregistroacrescentado.Noentanto,aseguinte:

***AlteraroestadocampoparaocampoKey
***Para'inalterado'
?SETFLDSTATE(1,3)&&retorna.
?GETFLDSTATE(1) &&Agoraretorna"3333"
perfeitamenteaceitvel,eIsChanged()agoravairetornarapenasasconsequnciasdeusurio
iniciouaesenoverasalteraesdecorrentesdousodevalorespadro.o
lugarbvioparacolocaressecdigoestemummtododeganchochamadoapartirdeumquerealmenteadicionao
novorecorde.TalmtodopoderiausarIsChanged()paradeterminarsequaisquervalorespordefeitoeram
fornecidaseusSETFLDSTATE()pararedefinirestadodocampodoregistro.

Captulo8:OsdadosembuffereTransaes 249

Gotcha!UsandoGetFldState()quandoumatabelaestemEOF()
Umapalavradecautelasobreouso GetFldState()(quenomencionadonaAjudaVFP
Arquivos).SeatabelaqueestatestarpassaasernoEOF(),afunoretornarumNULL
valoremvezdotipodedadosesperado.Vocdevegarantirquevoclidarcomestasituaocorretamente
sempreusandoafunoNVL()paraconverterqualquerretornonulodevoltaparaumacadeiavaziaquando
usandooparmetro"1"comoeste:

lcFldState=NVL(GetFldState(1),"")

ou,setestarumcampoespecfico,aconversodevoltaparaotipodedadosnumricosesperado:

lcFldState=NVL(GetFldState("nome"),0)

Sevocnoconseguirfazerisso,entoqualquercdigoquetestaovalorderetornoirfalharporcausadamaneira
emquenulossopropagadas.

Interpretandovaloresnulos:Nsachamosqueamelhormaneiradepensaremum
valornulotraduzilocomo"Eunosei."Quandovistoaestaluz
ocomportamentodosvaloresnulosclaraarespostaaqualquerpergunta
sobreostatusdealgocujovalor"nosei"semprevaiser
"Eunosei!"Assim:

llTestVal=NULL.
***llTestValvazio?
?VAZIO(llTestVal)& & Resposta:.F.('Eunosei'noumvalordefinidocomo'vazio')
***llTestValmaiorque0
?llTestVal>0 & & Resposta:.NULL.('Eunosei')
***onomeDaveouFred?
?INLIST(llTestVal,"Dave","Fred")& & Resposta:.NULL.('Eunosei')

UsandoTableUpdate()eTableRevert()
Aotrabalharcomdadosembuffer,duasfunessoabsolutamentevitalousejaTableUpdate()
eTableRevert().Estessoosmeiosbsicospelosquaisvoccontrolaatransfernciadedados
entreostampesVisualFoxProeafontededadossubjacente.TableUpdate()leva
alteraespendentesdosbuffersecometelosparaotempotabelasubjacente
TableRevert()atualizaosbuffersporreleituradosdadosdafontededadossubjacente.
Aconclusobemsucedidadeambososresultadosdefunoemuma"limpasignificadotampo"que,namedidado
VisualFoxProestemcausa,ostampesefontededadossubjacentesosincronizados.

Gerenciamentodoescopodasalteraes
DesdeVisualFoxProsuportatantoRoweTabeladetamponamento,tantodatransfernciadedados
funespodemoperartantona'nicoregistroatual'ouem'todososregistrosalterados.'Oprimeiro
parmetroquepassadoparaqualquerfunodeterminaoalcancee,infelizmente,nstemosumoutro
250 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

fontedepossveisconfusesaqui.Asfunesoperamdeformaligeiramentediferentee
usardiferentesvaloresderetorno.
Naverso3.0doVisualFoxPro,tantoTableUpdate()eTableRevert()iriaaceitarapenas
umparmetrodelgicaparadeterminaroalcancedamudanaqueelesconseguiram.Passarumvalorde
.T.Significavaquetodasasalteraespendentesdeveriamseracionadas,enquanto .F.Restritooperaesao
nicalinhaatual,independentementedomododebufferemvigor.
TableRevert()retornaonmerodelinhasqueforamrevertidasenopoderealmente'falha'
amenosquehajaumproblemafsico,comoaperdadeumaconexoderede.Emumatabeladelinhatamponada,ou
aoespecificaroescopocomo .F.,ovalorderetornoser,portanto,estarsempre 1.
TableUpdate()sempreretornaumvalorlgicoqueindicaseaatualizaoespecificada
sucedeu,independentementedombito.Emoutraspalavrasumvalorderetornode.T.indicaquetodos
registrosnombitoforamatualizadoscomsucesso.Noentanto,quandovocusaumalgica
parmetroparadeterminaroalcanceeaatualizaofalharporqualquermotivo,nenhumerrogeradoe
afunoretornaumvalorde .F.deixandooponteirodoregistronoregistroquefalhou.
Sevocestiveratualizandoumnicoregistrobastantesimples,massevocestiveratualizando
vriosregistrosemumatabela,eumregistronopodeseratualizado,issosignificaquequaisqueralteraes
noforamtestados.Ento,depoisderesolveroconflitoparaoregistroquefalhou,noexiste
garantirquevoltaraapresentaraatualizaonoirfalharnamuitoprximoregistro.Estepodeserum
problema!
OcomportamentodoTableUpdate()foi,portanto,mudounaverso5aaceitarqualquerum
lgicoouumparmetronumricoparaoescopo,onde 0equivalenteausar f.e 1para
usando .T.Onovocomportamento,oquespodeserespecificadoporpassagem" 2"comooescopo
parmetro,abordaespecificamenteasquestesdeatualizarvriosregistros.
Aousarobufferdetabela,chamandoTableUpdate()comumparmetrodeescopo"2"
tentaatualizartodososregistrosquepossuemalteraespendentes.Noentanto,seumregistronopodeser
atualizado,emvezdepararafunoregistraonmerodoregistroquefalhouemumarray
(Quevocpodeespecificarcomooquartoparmetro)econtinuatentandoatualizarqualqueroutro
alteradosregistros.Afunoaindaretornar.F.Sequalquerregistrodenoatualizar,masquetambmir
ter,pelomenos,tentouatualizartodososregistrosdisponveis.Amatrizdesadacontmumalistadoregistro
nmerosquefalhouaactualizao.

segundoparmetroTableUpdate()'s(fora)
UmadiferenaimportanteentreasintaxeparaTableUpdate()eTableRevert()queo
expodeterumextra,lgico,parmetronasegundaposionalistadeparmetros.este
controlaamaneiranaqualaactualizaocomportasesemprequeumconflitoencontrado.
Porpadro,VisualFoxProirrejeitarumaatualizaosemprequeumconflitoentreotamponada
osdadoseosdadossubjacentesfordetectado(consulteaprximaseoparaumadiscussocompletadeconflito
detecoeresoluo).Especificandoumalgica".T."comoosegundoparmetropodeforar
umaactualizaoparaseraceitemesmoemsituaesemqueseriadeoutromodofalhar.Naturalmente,esteno
algoquevocgostariadefazer,porpadro,mash,comoveremosmaistarde,situaes
ondeestecomportamentonosdesejvel,mastambmessencial.

Captulo8:OsdadosembuffereTransaes 251

Especificandoatabelaaseratualizadaourevertido
AmbosTableUpdate()eTableRevert()operamemumamesaaomesmotempo.Seucomportamentopadro
que,amenosqueespecificamentedirigidodeoutramaneira,elesvoagiremcimadamesanaselecionadonomomento
readetrabalho.Senenhumatabelaestabertanestareadetrabalho,vocreceberumerro(Error#13:Aliasn o
encontrado).Ambos,noentanto,podeactuaremqualquertabelaabertodisponvelnadatasessionactualepode
aceitartantoumaALIASnome(terceiroparmetroparaTableUpdate(),segundoparaTableRevert())ou
umnmerodereadetrabalho.
Nsnorecomendamosousodenmerosdereadetrabalhoneste,ouemqualquer,
situaoemquevocestespecificandoumatabelaquenosejaomomento
seleccionadoum.Tantoquantopodemosverestafuncionalidadesincludo
paracompatibilidadecomversesanterioresenotemlugarnoambienteVFP.tem
duasrazesparaevitarousodenmerosdereadetrabalho.Emprimeirolugar,elesfazemoseu
dependentedetabelasespecficasdocdigoqueestsendoabertoemreasdetrabalho
umagrandelimitaoseascoisasmudam!Emsegundolugarvocrealmentenotemqualquer
especficasque
controlesobreondeVFPabretabelas,cursoresouvistasquandovocusaumformulrio
Dataenvironmentdequalquermaneira.Assim,baseandosenonmerodereadetrabalho,emvez
alis,umaestratgiamuitoarriscadaedesnecessrio.
dea

Anicavezquerecomendamosautilizaodonmerodereadetrabalhoquandosalvaro
readetrabalhoatual,armazenandoovalorderetornodafunoSELECIONAR().usandoo
nmerodereadetrabalho,nestecasoasseguraquecasoareadetrabalhoatual,naverdade,
estarvazio,ouatabelaquecontmserfechadodurantequalquerquesejaaoperaoquevoc
fazendo,vocaindapodevoltaraelesemerros.
est

Concluso
HummontedefuncionalidadeeflexibilidadeescondidodentroTableUpdate()e
TableRevert().Aousarobuffer,vocprecisaestarcientedoqueexatamenteosvrios
combinaesdeseusparmetrospodemforneceregarantirquevocestusandoacorreta
combinaoparaatenderssuasnecessidades.EnquantoTableRevert()bastantesimples,TableUpdate()
maiscomplexoe,portantoTabela8.2abaixoforneceumresumodoqueosvrios"prtico"
combinaesdeparmetrosparaTableUpdate()vaifazer.

252 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela8.2(TABLEUPDATE)opes

parmetros
Escopo Fora Mesa Sada Aao
0ou.F. .F. Tentativadeatualizaralinhaatualsapelidoatual.
0ou.F. .T. Foraratualizaodalinhaatualsapelidoatual.
0ou.F. .F./.T. alis Tentativadeatualizao/Forcedalinhaatualapenasespecificado
alias.
1ou.T. .F. Tentativadeatualizaodetodasaslinhasdisponveisdeapelidoatual.
Pararemcasodefalha.
1ou.T. .T. Foraratualizaodetodasaslinhasdisponveisdeapelidoatual.
1ou.T. .F./.T. alis Tentativadeatualizao/Foradetodasaslinhasdisponveisdeespecificada
alias.Pararemcasodefalha.
2 .F. alis ordem Tentativatudoparaatualizartodasaslinhasdisponveisdeespecificada
alias.Notafalhas,masnopare.
2 .T. Foraatualizartodasaslinhasdisponveisdaatual/especificado
alias.
2 .F./.T. alis ordem Tentativadeatualizao/Foradetodasaslinhasdisponveisdeespecificada
alias.Notafalhas,masnopare.

Comopossolidarcom'salvar'efuncionalidade'desfazer'
genericamente?
Parecenosquemuitosdesenvolvedoresescreveressafuncionalidadediretamentenainterfacedeobjetosmais
eoutravez.Algica,geralmente,que'cadaformulriotemexignciasdiferentes'masisso
realmenteverdade?Nsnotmtantacerteza.Oprocessorealdeatualizaroureverterumamesasempre
omesmo.Asnicasquestessoquandovocfazlo,quedeterminadapelosprocessosdevalidao,
eoquevocfazquandoalgodererrado.Estassoasduasquestessriasesodefato
dependedasituao,masnoafetamoprocessoderealmenteatualizarourevertera
mesa!
Reduzidaaobsico,portanto,onicoverdadeiroproblemasurgequandovocprecisalidarcom
vriasmesasaomesmotempo,porqueTableUpdate()eTableRevert()ambosesperamserpassadoum
nomedetabelanicanaqualoperar.Ocdigopseudoparaomtododeumgenrico'Save',portanto,
algocomoisto:

RecebaAlias
detodasastabelasparaatualizarcomoumalistaseparadaporvrgulas

Paracadatabelanalista
Verifiqueostatusdobuffer
EmitiravarianteadequadadeTableUpdate()
Criarumalistadeeventuaiserros
Retornaroresultado

Enquantoqueparaummtodogenrico'Undo'ocdigomuitosemelhante,defato:
RecebaAlias
detodasastabelaspararevertercomoumalistaseparadaporvrgulas

Paracadatabelanalista
Verifiqueostatusdobuffer
EmitiravarianteadequadadeTableRevert()

Captulo8:OsdadosembuffereTransaes 253

Retornaroresultado

Nsjdiscutimosumafunopararecuperarumitemdeumalistaseparadaporvrgulas
(vejaGetItem()noCaptulo2)entoanicaquestorealondedeveocdigoir?Hdois
opesbsicas.Emprimeirolugar,ocdigopoderiaserimplementadocomopartedeumaclassede"dados
poderiasimplesmenteseradicionadosaformasqueexigemafuncionalidade.Emsegundolugar,osmtodosnecessrios
manipulao",que
podeserincludocomopartedeumaclasseForm"DataAware".Temosescolhidoparailustraraforma
abordagemdeclasseporqueagrandemaioriadosaplicativosdoVisualFoxProsoessencialmenteformar
Sediada.Osocasiesemqueumobjectodedadosseparadoserianecessriase,porconseguinte,
exceesenoaregra.

Oprojetodaclassedeformulrio
AfimdeimplementarSalvareDesfazerfuncionalidadeparaumformulrio,primeiroprecisamosconfiguraronosso
classeparafornecerosmtodosnecessrios.Temosescolhidaparafornecerumconjuntodemtodosdemodelo
formulrio
nanossaclassedeformulrio'Root'(xfrmemRootClas.vcx)quevaigeriroprocessopeloSalvar
aimplementaodeumpadrodeHook.
OSaveFormmtodoocontroladorparaoprocessoeomtodoqueocdigoemuma
instnciadeumformulriocombasenessaclassechamariapararealmentetentar"salvar".oSaveForm
mtodoprimeirofazumachamadaparaoBeforeSavemtodo.Qualquercdigoespecficodainstnciaqueprecisa
serchamadoimediatamenteantesdorealsalvar(porexemplo,prsavevalidao)serocolocadosaqui.Ese
estemtodoretorna.,oDataSavemtodoentochamado,queondeorealSAVE
sertentada,e,dependendodoresultado,queroafterSaveouoAfterFailSavemtodo
chamadoparalidarcomqualquerprocessamentopssaveespecficodainstncia.
Umconjuntosemelhantedemtodoslidacomoprocessodereverter,masumavezqueumTableRevert()nopode
realmente"falha"precisamosdeapenasumnicoAfterRevertmtodo.

OmtodoSav eForm
OcdigorealusadonasSaveFormeRevertFormmtodosdefactoidntica,coma
exceodosnomesdosmtodosparaserchamado.Seria,porconseguinte,serpossvelchamarum
manipuladormtodocomum,'sobrecarregado',comumparmetroindicandose"Save"ou"Reverter"
necessriaumaaco.Noentanto,nsrealmentenogostodessaabordagem,poistornaamanuteno
maisdifcilerealmentenofornecerqualquerbenefciotangvel.Afinaldecontas,apenasumtipode
aonuncavaiserchamadoaqualquermomento!

***EstemtodoenvolveachamadaparaomtodoDataSave
***EincluichamadasparaoantesedepoisHooks
LPARAMETERStcTables
lcTablesLOCAIS,llok
COMThisForm

***Senadaforaprovada,assumirtodasasmesas!
lcTables=IIF(VARTYPE(tcTables)#"C"ouvazio(tcTables),.GetAllUsed(),
tcTables)
ESE!Vazio(lcTables)

***Chamadainstnciadenvel"Antes"Gancho
llok=.BeforeSave(lcTables)
254 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***SeBeforeSavefalhar,ocdigoparalidarcomafalhadevesercolocadol
IFllok

***AnteseraOK,assimchamadapginaSave
llok=.DataSave(lcTables)
IFllok

***Todosossalvos,assimchamadaainstnciadenvel"Depoisde"gancho
.AfterSave(LcTables)
OUTRO

***Agravaofalhou,assimchamadainstnciadenvelalternativo"Depoisde"gancho
.AfterFailSave(LcTables)
FIMSE
FIMSE
OUTRO

***Nohmesasemuso,bastaretornar.T.
llok=.T.
FIMSE
ENDWITH
RETURNllok

OresultadodestaabordagemqueagorapodemoscodificaroDataSavemtodoespecificamentepara
lidarcomachamadarealparaTableUpdate(),porquetemosdesdelocaisalternativosparaqualquer
cdigoespecficoinstnciaemqualquerAntesouDepoisdemtodoseporquetambmtemcodificadoo
Reverterfuncionalidadeemseuprprioconjuntodemtodos.
Umpontodiscutvelseessesmtodos"wrapper"tambmdeveemitirumaatualizaodenveldeformulrio.
Noseuconjunto,preferenoterquefazlo,umavezqueotipodeatualizaonecessriapodedepender
osresultadosdocdigoguardareassimdevemsermanipuladosporexemploespecficoquerna
AfterSaveouAfterFailSaveconformeapropriado.Vocpode,claro,optarporfazlodeformadiferente.

OmtodoDataSav e
OcdigorealnestemtodoidnticoaoqueemDataRevertcomaexcepodequeo
chamadasltimaTableRevert().Maisumavezestesdoismtodospoderiatersidocombinadasnumanica
mtodo,masasrazesparanofazlosoosmesmos.
Emboraaindanodiscutidonestecaptulo,vocvainotarqueestamosusandoumatransao
Aqui.Teremosmaisadizersobretodaaquestodastransaesmaistarde,masporagoraapenas
aceitarqueestamosusandoumparagarantirquevriasatualizaesdatabelaourevertequertersucesso,ou
falhar,comoumblococomosensestvamosrealmentelidandocomumanicatabela:

LPARAMETERStcTables
LOCALllRetVal,lnCnt,lcToDo,lnBuffMode

COMThisForm

***InicializarValorderetornopara.T.
llRetVal=.T.

***Inicieumatransao
BEGINTRANSACTION

***Loopatravsdetodasastabelas

Captulo8:OsdadosembuffereTransaes 255

lnCnt=0
DoWhile.T.

***Recuperarnomedatabela
lnCnt=+1lnCnt
lcToDo=.GetItem(tcTables,lnCnt)

***RetornoNULLindicafimdacadeia
IFISNULL(lcToDo)
SADA
FIMSE

***Verifiqueomododebufferdecada
lnBuffMode=.GetBufferMode(lcToDo)

***Emitaocomandoatualizaocorretae"E"oresultado
DOCASO
PROCESSOINLIST(lnBuffMode,2,3)

***EstamosRowBuffered
llRetVal=llRetValETABLEUPDATE(0,.F.,lcToDo)
CASEINLIST(lnBuffMode,4,5)

***EstamostabelaBuffered
llRetVal=llRetValETABLEUPDATE(1,f.,lcToDo)
DEOUTRAFORMA

***SemBufferemtudoentonofazernada
ENDCASE
ENDDO

***Commitoureverteratransao
IFllRetVal

***Tudoestavamuitobem
ENDTRANSACTION
OUTRO

***Algodeuerrado
ROLLBACK
FIMSE
ENDWITH

***StatusdeRetorno
RETURNllRetVal

Usandoanovaclassedeformulrio
ODemSave.scxformulriodeexemploilustracomoaclassedeformulriodescritopodeserusado.Nstemos
criadasduasnovasclassesdeboto(xCmdStdDisableSaveexCmdStdDisableUndo)combaseem
nossaclassebotodeautodesativaoqueapenaschamaraformadoSaveFormouRevertFormpersonalizado
mtodosdeseusOnClickmtodos.Umavezqueestasaulassodestinadasexclusivamenteparausocomum
formulrioquetemestesmtodos,nohcdigoparaverificarqueomtodorealmenteexiste!defato
poderamosteradicionadoestesbotesdiretamenteparaaprpriaclasseformulrio,masnoofizeram
porquensnuncapodetercertezaquevamossemprequerosdoisbotes.(Lembresevocnopode

256 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

excluirumobjetoquedefinidopelaclassepaiemqualquerumasubclasseouumainstncia).Este
Decorrenossaafirmao(verCaptulo3)que,seafuncionalidadenoestno" MUST"
categoria,elenopertencenaclasse!

Figura8.4UmformulriousandoosmtodosgenricosSave/Undo
Nesteexemplo,osafterSave,AfterFailSaveeAfterRevertmtodossimplesmenteexibiruma
mensagemapropriadaantesdechamarumaatualizaodenveldeformulrio.Paratestaresteformulriosimplesmente
instnciasdeVFPeabraademonemesanasegundainstncia.Depoisdeexecutaroformulriono
comearadois
primeirainstncia,fazeresalvarumaalteraotabelanosegundoe,emseguida,fazereguardarum
mudarparaomesmoregistronoformulrio.

Detecoeresoluodeconflitos
Nasseesanteriores,vimoscomodetectaralteraesemumatabelaecomotentar
atualizarumatabelaembuffer,demodoqueaprximaediogarantirqueaalteraopropostanovai
causarumconflitodeatualizaoquandosalvo.Umdosproblemasinerentesassociadosaoptimista
bloqueioemumambientemultiusurioquepossvelquemaisdeumusurioparafazer
alteraesparaomesmoregistroaomesmotempo.
Vocpodeseperguntarporquetalcoisajamaisseriapossvelcertamentedoisusuriosnopoderiaser
atualizaromesmoregistronomomento?Naprtica,existemmuitassituaesemqueissopode
legitimamenteacontecer.Considereasituaoemumsistemadeprocessamentodepedidodevendas.Quandoumaordem
colocadoparaumitem,oatual"estoquedisponvel"deveserajustadoparareflectirareduo.Ese
doisclientes,sendomanipuladopordoisoperadoresemsimultneo,incluemomesmoitememsua
ordens,humaboachancedequeumconflitosurgiro.Obviamente,issonopodeacontecerseo
sistemausabloqueiopessimista,masquetemoutras,geralmenteindesejveis,consequncias.Nisso
cenrio,osegundooperadorquetentouacessaroitememquestoiriareceberumamensagem
queoregistrofoiemusoporoutrapessoaenoseriacapazdefazermudanasnomuito

Captulo8:OsdadosembuffereTransaes 257

Socorro!AlmdissobloqueiopessimistaspodeserusadaquandoumatabelaVisualFoxProusado
diretamentecomofontededadosvocpodenopessimistabloquearumavistadequalquerespcie.
Aousartampo,VisualFoxProfazumacpiadetodososdados,umavezquerecuperadodo
tabelafsicae,quandoumaatualizaosolicitado,comparaessacpiacomoestadoatualda
osdados.Senohouvermudanas,aatualizaopermitido,casocontrrio,aatualizaoapropriada
errodeconflito(#1585paraViews,#1595paraosquadros)gerado.Figura8.5ilustra,
esquematicamente,comoissofuncionaecomoumconflitodeatualizaodetectado.

Figura8.5Actualizaresquemticadeumamesatamponada

OpapeldeOLDVAL()eCURVAL()
Abasedetodaadetecodeconflitosresideemduasfunesnativas",OLDVAL()"e"CURVAL()",
queacessaroscursoresintermedirioscriadospeloVisualFoxProaousardadosembuffer.Como
seusnomesimplicam, OLDVAL()recuperaovalordeumcampoemqueestavaquandoousurioleraltima
dadosdafonte,enquanto CURVAL()Recuperaoestadoatualdosdadosnatabeladeorigem.
Ambasasfunesoperamnonveldecampoe,emboraambospossamaceitarumaexpresso
queavaliadacomoumalistadoscampos,elessomaisutilizadospararecuperarvaloresdecampoisoladamentepara
problemaderesolverdiferentestiposdedados.
evitaro
Humapegadinha!Comouso CURVAL()paraverificarostatusdeumpontodevista.VisualFoxPro
realmentemantmumnveladicionaldebufferparaumpontodevistaque,amenosqueavista
atualizadosimediatamenteantesdeverificarovalordeumcampo,podecausar CURVAL()pararetornaroerrado
responda.Teremosmaisadizersobreo Refresh()funo,eseuuso,naseosobre
Pontosdevista.
258 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Ento,comopossorealmentedetectarconflitos?
Antesdeentrarnadiscussodecomodetectarumconflito,vamosserclarossobreoqueVisual
definiodeumconflitodeFoxPro.Comoaentenderanteriormente,VisualFoxProfazduascpiasdeum
recordesemprequeumusurioacessadados.Umacpiadisponibilizadacomoocursoreditvele
ondeumusuriofazalteraes.Aoutramantidanoseuestadooriginal.Antesdepermitiruma
atualizaoparaprosseguir,VisualFoxProcomparaestecursororiginalcomosdadosarmazenados
nodisco.Umconflitoocorrequandoestasduasversesdosdadosnocorrespondemexatamente,eh
duasmaneiraspelasquaisissopodeacontecer.Aprimeira,emaisbvia,porqueousurioatual
fazalteraesemumregistroetentasalvaressasalteraesapsalgumjtem
alteradoeguardadoomesmoregistro.Asegundaumpoucomenosbviaesurgequandoumutilizador
se noefectuarquaisqueralteraes,mastenta"salvar"umregistroqueoutrousurio TEMmudado.Visual
FoxProaindavaiverissocomoumconflitoporqueo OLDVAL()e CURVAL()valoressodefato
diferente.Istomelhortratadopornorealmentefazendoum TableUpdate()amenosqueousurioatual
realmentetemalteraesfeitasqueprecisamenteporissoqueoIsChanged()funototil.isto
permitedeterminarseuma TableUpdate()necessrioeusarocdigocomoesteem
suaseconomiasrotinas:

llRetVal=.T.
IFIsChanged()
llRetVal=TABLEUPDATE()
FIMSE
RETURNllRetVal

Ento,depoisdeterevitadoapossibilidadedeconflitosquandoousurioatualnofezqualquer
alteraesporsimplesmentenotentarconfirmaroregistro,existembasicamenteduasestratgiasquevocpode
adoptarparadetectarconflitos.Oprimeirochamamosde"SuckItandSeeabordagem".Istosignificasimplesmente
quenotenteedetectarpotenciaisconflitos,masapenasarmadilhaoresultadodeuma TableUpdate()
decomandoe,quandoelefalhar,tomarmedidasparadescobriroporqu.
Osegundoo"cintoesuspensriosabordagem'emquevocverificarcadacampoalteradoe
resolverosconflitosantesdetentaratualizaratabelasubjacente.Enquantoistoparecemais
defensiva,e,portanto,"melhor",norealmenteumproblemaescondidocomele.Naquantiade
tempoqueleva(emboramuitopequena)paraverificartodososcamposalteradoscontraseusvaloresatuais,
outrousuriopodetersucessoemmudaroprprioregistroquevocestverificando.Ento,amenosquevoctambm
trancarexplicitamenteoregistroantesdecomearaverificarvalores,aactualizaorealaindapodefalhar.
Desderealmentequerevitarexplicitamentecolocandotravas,vocprecisaincorporarexatamentea
mesmaverificaodoresultadoda TableUpdate()decomando,eproporcionaromesmotratamentopara
falhaquevocprecisanomuitomaissimplesapenas"SuckItAndSee"estratgia!
Portanto,amenosquetenhaumarazoimperiosadealteraesprvalidao,altamente
RecomendamosquevocdeixeVisualFoxProdetectarconflitoseapenasarmadilhaparaelidarcomesseserros
quepossamsurgir.Noentantoqualquerestratgiaquevocescolher,vocaindavaiprecisardealgunsmeiosde
constataodequecamposemumdeterminadoregistromudaram,demodoquevocpodeobterosvaloresapropriados
de CURVAL()e OLDVAL().Afunoaseguir,GetUserChanges(),retornaumavrgula
listaseparadadecamposqueforamalteradospelousurioatual:
Captulo8:OsdadosembuffereTransaes 259

**********************************************************************
*Programa :GetUserChanges.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Retornaumalistaseparadaporvrgulasdecamposqueforamalterados
* :Pelousurionalinhaatualdatabelaespecificada
**********************************************************************
LPARAMETERStcTable
lcTableLOCAL,lcRetVal,lnBuffMode,lcFldState,lnCnt,lcStatus
***Verifiqueoparmetro,assumeapelidoatualsenadapassado
lcTable=IIF(VARTYPE(tcTable)#"C"ouvazio(tcTable),
ALIAS(),ALLTRIM(UPPER(tcTable)))
***Verifiqueseonomedatabelaespecificadousadocomoumalias
IFEMPTY(lcTable)OR!USADO(JUSTSTEM(lcTable))
***Erroprovavelmenteumerrodedesenvolvedor,portanto,useumerroparadenuncilo!
ERROR"9000:GetUserChanges()requeroaliasdeumatabelaaberta"
+CHR(13)+"serpassado,ouqueareadetrabalhoatualdeve"
+"Contmum"+CHR(13)+"tabelaaberta"
RETURN.F.
FIMSE
lcRetVal=''
***Verifiqueostatusdetamponamento
lnBuffMode=CURSORGETPROP('buffer',lcTable)
IFlnBuffMode=1
***Notamponada,porisso,podehaver"alteraespendentes'
RETURNlcRetVal
FIMSE
***Sechegarmosataqui,temosumregistrotamponadaquepodeteralteraes
***Entoconfiraparacamposqueforamalteradososvalores
lcFldState=NVL(GETFLDSTATE(1,lcTable),"")
IFEMPTY(CHRTRAN(lcFldState,'1',''))
***Nadaalmde'1',portanto,nadamudou
RETURNlcRetVal
FIMSE
***Assim,temospelomenosumcampoalterado!Mastemosdelidarcomo
***ELIMINADOindicadordebandeiraemprimeirolugar.Podemosusar"DELETED()"comoonomedo
Aqui!
campo
ESE!INLIST(ESQUERDA(lcFldState,1)"1","3",)
lcRetVal="DELETED()"
FIMSE
***Agora,selivrardoindicadorBandeiraDeleted
lcFldState=SUBSTR(lcFldState,2)
***Obterosnomesdecampoparacamposalterados
PARAlnCnt=1afunoFCOUNT()
***Loopatravsdoscampos
lcStatus=SUBSTR(lcFldState,lnCnt,1)
SEINLIST(lcStatus,"2","4")
lcRetVal=lcRetVal+IIF(!empty(lcRetVal),"","")+CAMPO(lnCnt)
FIMSE
PRXIMO
***Retornoalistadoscamposalterados
RETURNlcRetVal

Observequeusamosonativo DELETED()funocomoumnomedecamponestafuno.Ambos
Curval()e OLDVAL()vaiaceitarissocomoum"nomedecampo"vlido(retornandoumvalorlgico
indicandoseocampofoieliminadanatabelasubjacente)paraquepossamosrealmenteverificarseh
excluses,bemcomoalteraes.

260 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tendoobtidoumalistadecamposqueforamalterados,podemosusarumafunocomoGetItem()(umadas
nossosprocedimentosgenricos,descritosnoCaptulo2)pararecuperarosnomesdoscamposindividuais,se
necessrio.Osvaloresoriginaiseatuaisparacadacampoalteradopodeentoserrecuperadose
comparadasparadeterminarondeocorremconflitos.OprogramadeexemploListFields.prgilustra
comoissofunciona,elistasnatelaovalorreal, Curval()e OLDVAL()paramudanas
feitaparaumadasmesasdedemonstrao.Aquiestocdigo:

**********************************************************************
*Programa :ListFields.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:IlustreusodeGetUserChanges(),GetItem(),Curval()e
OLDVAL()
**********************************************************************
lcChgFldsLOCAIS,lnCnt,lcCurFld

***AbraoarquivoProcedimento
SETPROCTOCH08ADITIVO

***Abrirumatabelaebufferlo
demoneUSE
CURSORSETPROP("Buffering",5",demone')
***Faaalgumasalteraes
SUBSTITUIRd1NameCOM"William",d1CityCOM"Wallhouse"

***Vejalistadoscamposalterados
lcChgFlds=GetUserChanges('demone')

***Exibirresultados
lnCnt=0
DoWhile.T.

***Recuperarnomedocampo
lnCnt=+1lnCnt
lcCurFld=getitem(lcChgFlds,lnCnt)

***RetornoNULLindicafimdacadeia
IFISNULL(lcCurFld)
SADA
FIMSE

***NomedocampoMostrar
?"Nomedecampo:"+CHR(9)
??lcCurFld

***Mostrarvaloratual
?"CampoValorActual "+CHR(9)
??&lcCurFld

***AtualDiskValor
?"CURVAL()Valor "+CHR(9)
??CURVAL(lcCurFld,'demone')

***ValorOriginal
?"OLDVAL()Valor "+CHR(9)
??OLDVAL(lcCurFld,'demone')
ENDDO

Captulo8:OsdadosembuffereTransaes 261

***Perderalteraes
TABLEREVERT(.T.,'Demone')
TABELASfechartodas

OK,ento,tendodetectadoumconflitodeatualizao,oquepossofazersobre
isto?
Hquatroestratgiasbsicasparalidarcomconflitosdeatualizao.Vocpodeescolherum,oucombinar
maisdoqueumemumaaplicao,dependendodasituaoreal:
[1]OusurioatualGanhaSempre:Essaestratgiaapropriadasomentenaquelassituaesem
queousurioqueestrealmentetentandosalvaraquelecujosdadosassumidocomosendoomais
preciso.Tipicamente,istoseriaimplementadonabasedaidentificaodoutilizadorque
realmentefazendoosalvareiriaimplementarumaregradenegcioqueasinformaescertaspessoas
demaisvalordoqueoutros.
Umexemplopodeseremumaplicativodetelevendas,ondeumoperadorfalarcomocliente
poderiaterdireitosdesubstituioparainformaesdecontatoparaocliente(combaseemqueapessoa
realmentefalarparaoclientemaisprovvelquesejacapazdeobterosdetalhescorretos).conflitos
poderiasurgirnestasituaoquandoumadministradorestaactualizardetalhesdeumclienteapartirdedadossobre
arquivooualtimaordem,enquantoumoperadorestrecebendonovosdetalhesdiretamentedocliente.
AimplementaodestaestratgianoVisualFoxProrealmentemuitosimples.Bastadefiniro
"FORCE(segundo)parmetro"na TableUpdate()funopara".T."ereenviaraatualizao.

[2]Ousurioatualperdesempre:Esteexatamenteocontrriodasituaoacima.o
usurioatualspermitidoparasalvarasalteraesqueprevemquenenhumoutrousuriotiverfeitoalteraes.
Novamente,istonormalmenteseriaimplementadocombasenoIDdeumutilizadorequerefletema
probabilidadedequeesseusurioespecficosusceptveldeserotrabalhode"histrico",aoinvsde
"informaesatuais.
AimplementaonoVisualFoxProtambmmuitosimples.alteraesdousurioatualso
revertida,afontededadosreconsultado,eousuriotemquefazerquaisquermudanasaindanecessriastudo
denovo.Estaprovavelmenteaestratgiaquemaisfrequentementeadotada,masgeralmenteemumaacross
baseabordo!

[3]Ousurioatualvencesvezes:Estaestratgiaomaiscomplexodosquatroa
implementar,masrealmentemuitocomum.Oprincpiosubjacenteque,quandoumaatualizao
conflitoocorre,vocdeterminarsequalquerumdoscamposqueousurioatualfoialteradovai
afectarasalteraesqueforamfeitaspelooutrousurio.Seno,oregistrodousurioatualatualizado
automaticamente(usandoo CURVAL()valores)demodoqueacausadoconflitonegadaeo
atualizaoentoreapresentado.Noentanto,porquenopossvelalterarosvaloresdevolvidospela
OLDVAL(),vocprecisaforarestasegundaatualizao.
Alis,estaestratgiatambmabordaaquestodecomolidarcomumaatualizaode"falsopositivo"
conflito.Issoocorrequandohumadiscrepnciaentreosvaloresemdiscoeosdo
tampodousurioatual,masasmudanasdousurioatualrealmentenoentraremconflitocomqualquerumdos
alteraesfeitas.evidentequeestasituaonorealmenteumconflito,masnoprecisasertratada.

262 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Emboranosejatrivial,aimplementaonoVisualFoxProrelativamentefcil.Emprimeirolugar,o
CURVAL()funousadaparadeterminarcomoatualizarobufferdousurioatualparaqueeleir
nosubstituiroasalteraesfeitasporoutrousurio.Emseguida,aatualizaoaplicadausandoo FORCE
(Segundo)parmetrono TableUpdate()paradizerVisualFoxProparaignoraroconflitoquevai
surgemporque OLDVAL()e Curval()nocorrespondem.

[4]OusurioatualDecide:Esteocenriode"CatchAll".Oconflitonocai
sobqualquerregradenegcioreconhecvelpeloqueanicasoluoperguntaraousuriocujasalvarao
desencadeouoconflitoqueelespretendemfazersobreisso.Aideiasubjacentequevoc
apresentarousurioqueprovocouoconflitocomumalistadevaloresoqueacaboudeentrar,
ovalorqueestavanatabela(ouseja,queelesacabaramdemudar)eovalorqueagora
natabela(isto,queaquealgumtenhaalteradoovalororiginal).Ousuriopode,ento,
decidirseaforarourevertersuasprpriasmudanas.
Asferramentasbsicasparaaimplementaodestaestratgiajforamdiscutidasna
secoanterior.Tudoquenecessriodeterminarquaisoscamposnaverdadeconflitoe
apresentlasaoutilizador,detalmaneiraqueoutilizadorpodedecidirsobreumcampodebaseparaocampo
fazersobreosconflitos.Naprtica,estaestratgianormalmentecombinadacomaestratgia[3]acimademodo
queousuriosapresentadocomumalistadecamposondehrealmenteumconflitonoscampos
tmsealterado.

resoluodeconflitossoabememteoria,comoquefuncionaem
prtica?
Hmuitasmaneirasdeimplementararesoluodeconflitos.Omtodomaisapropriadoser
dependerderequisitosdesuaaplicao.Noentanto,afimdeilustrarcomosepode
implementlo,criamosumaclassechamada"UpdRes"(noUpdRes.vcxbiblioteca).este
consisteemumformulrio,quetemmtodosparacriarepreencherumcursorlocalcomostrs
valoresnecessriosparatodososcamposquecausamumconflito.Eleimplementaumacombinaode"Current
Usuriosvezesganha"ea"CurrentUserDecide"estratgias(Figura8.6).

Figura8.6Umaclassesimplesexibioderesoluodeconflitos
Captulo8:OsdadosembuffereTransaes 263

Oformulriomostraaousurioquantosconflitosforamdetectadoseexibe,paracada
campodeconflito,osvaloresde OLDVAL(), CURVAL()eobufferatual.Porpadro,todas
conflitossomarcadospararesoluoporreverteramudanadousurioatualeumaoposimples
grupopermitequeousuriosubstituaamudanaexistenteemumcampoporcampobase.Umadicional
refinamentoaopo"forartodos",quedefinetodososconflitosaseremresolvidosusandoacorrente
valoresdousurio.Quandoousurioestsatisfeito,clicandonobotodesadairaplicarasalteraescomo
especificadoparaamesa.

OmtodoInit
AclasseestconfiguradacomoumaformamodaleesperareceberdoisparmetrosoDataSession
nmerodoformulrioquesechamava,eonomedatabelanoquedatasessionquetem
causouoconflito.Ocdigoaquisimplesmentedefineoformulrioparaodatasessioncorretoe,emseguida,
chamaosSetUpFormeCheckUpdatesmtodos:

LPARAMETERStnDSID,tcTable
llRetValLOCAL
COMThisForm

***DefiniresteformulrioparaopassadonaDataSession
.DataSessionID=TnDSID

***ceatecursorevincularcamposaele
.SetUpForm()

***ExecuteosCheckUpdates()paraatabelaespecificada
llRetVal=.CheckUpdates(tcTable)
RETURNllRetVal
ENDWITH

OCheckUpdatesmtodoretornaumvalorlgicoqueindicaserealmenteexistem
quaisquerconflitosquerequeraintervenodousurioe,porqueestevalorretornadodaClasseInit
mtodo,irimpedirqueaclassesejainstanciadoquandonohconflitosquenopode
serresolvidopormeiodeprogramao.Ocdigodechamadaparaestaclassedeve,portanto,tomareste
possibilidadeemconta.

OmtodoSetUpForm
Issoextremamentesimpleseapenascriaocursorlocaledefineoscontrolesdeformulrioparausar
estecursorcomosuacontrolsource.Istoprecisadeserfeito,quernadeinicializao,ounummtodochamado
doInit,porqueprecisamosparaobteroformulrioparaodatasessioncorretaantesdecriaro
cursor.UmavezqueoIDDataSessionnecessriopassadocomoumparmetro,nopodemosacessloemqualquer
mtodoantesdoprprioformulrioInit:

COMThisForm

***Criarumcursorlocalparaarmazenarconflitos
CRIARCURSORcurcflix(
cfxRecNumC( 8), &&NmerodeConflitos
cfxFldNamC(200), Nome&&campo
cfxOldValC(200), &&Valororiginal
cfxCurValC(200), &&Valoratualnodisco

264 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

cfxUsrValC(200), &&Alterarnobuffer
cfxForcitN( 1)) &&Definidopelousurioaco

***Vincularcontrolesaele
.TxtRecNum.ControlSource="Curcflix.cfxRecNum"
.txtFldNam.ControlSource="curcflix.cfxFldNam"
.txtOrgVal.ControlSource="curcflix.cfxOldVal"
.txtCurVal.ControlSource="curcflix.cfxCurVal"
.txtNewVal.ControlSource="curcflix.cfxUsrVal"
.OptUsrChoice.ControlSource="Curcflix.cfxforcit"
.Refresh()
ENDWITH
RETURN.T.
OmtodoCheckUpdates
Esteolugarondealgunsdostrabalhosrealdaclassefeito.Aprimeirapartedocdigoestemcausa
comagarantiadequeatabelacorretaestdisponvel,selecionadoe,emseguida,determinaoarmazenamentoembuffer
estausando:
LPARAMETERStuTable
LOCAISllRetVal,lnBuffMode,lcTable,lnOldArea,lnNextRec,lnRows

***VerifiqueParmetros
IFEMPTY(tuTable)
***Nadapassou,useatabelaatual
lcTable=ALLTRIM(ALIAS())
IFEMPTY(lcTable)

***Nenhumatabela
RETURN.F.
FIMSE
OUTRO
DOCASO
TYPECASE("tuTable")="C"

***SuponhaCadeiadecaracteresoAlias
Obrigatrio

lcTable=ALLTRIM(tuTable)
TYPECASE("tuTable")="N"

***ObteroAlias
paraareadetrabalhoespecificado

lcTable=ALIAS(tuTable)
DEOUTRAFORMA

***Parmetroinvlidosadacomoerro
RETURN.F.
ENDCASE
FIMSE

***VerifiqueBufferMode
llRetVal=.T.
lnBuffMode=CURSORGETPROP('buffer',lcTable)
IFlnBuffMode<2

***Setabelanotamponadoapenasretorno
RETURN.F.
OUTRO

Captulo8:OsdadosembuffereTransaes 265

***Guardarreadetrabalhoatualeselecioneatabelanecessria
lnOldArea=SELECIONAR()
SELECT(lcTable)
FIMSE

Aparteseguintedomtododependedomododetamponamentoqueestaserutilizado.Ese
TabelaBufferestemvigor,oCheckRecmtodochamadoumavezparacadalinhaquemuda
tersidodetectado,afimdepreencherocursorconflitosenecessrio.SeRowbuffer
usado,apenasumanicachamadanecessrio.
***Precisalidarcommemriaintermdiadelinhaebufferdetabeladiferente
COMThisForm

***FormulrioSetCaptionemesadearmazenamentodedestinoaumapropriedadeForm
***ParausonasDoUpdates()Mtodo
.Caption="AtualizarConflitosnatabela:"+lcTable
.cTarget=ALIAS()

***MododebufferVerifique
IFlnBuffMode<4

***Bufferdelinha
llRetVal=.ChkRec(RECNO(),lcTable)
OUTRO

***TabelaBuffernecessidadedeencontrartodososregistrosmodificados
lnNextRec=0
DoWhile.T.
lnNextRec=GETNEXTMODIFIED(lnNextRec)
IFlnNextRec=0
SADA
FIMSE

***Experimenteeatualizaroregistro
llRetVal=.ChkRec(lnNextRec,lcTable)
ESE!llRetVal

***Seno,saia
SADA
FIMSE
ENDDO
FIMSE

Aseofinaldocdigoapenasverificaacontagemderegistrodocursorconflitoparaverse
nadaprecisaserfeitopeloutilizador.Seno,umforado TableUpdate()feitoemtodososregistospara
limparobuffer:

***VerifiqueoCursorConflito
IFRECCOUNT("curcflix")=0

***Nohconflitosinsolveisassimapenasforaraatualizao
***Aoretornar.F.aoInit()podemosevitaroobjetoinstantiating
***Eousuriovaivernada!
llRetVal=!TableUpdate(.T.,.T.)

266 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OUTRO
GOTOPINcurcflix
FIMSE
ENDWITH

***Arrumar
SELECIONAR(lnOldArea)
RETURNllRetVal

OmtodoChkRec
Estemtodochamadoumavezparacadalinhaqueprecisaservalidadoeondeadeciso
feitaparasaberseaintervenodousurionecessriaouno.Paraaslinhasemqueumconflitonopodeser
resolvidaspormeiodeprogramao,umregistroparacadacampoquerequeraintervenodousurioinserido
nocursorconflito:

LPARAMETERStnRecNum,tcTable
lnCntLOCAL,luCurVal,luOldVal,lnRows,llRetVal,lcFldList,lcFldName,
luUsrVal

***Foraroregistrocorretodeseratual
SELECT(tcTable)
IFRECNO()#tnRecNum
GOTOtnRecNum
FIMSE

***Sealistadoscamposalteradospelousurioatual
lcFldList=""
lcFldList=ThisForm.GetUserChanges(tcTable)

***Scanatravsdoscampos
PARAlnCnt=1afunoFCOUNT()
lcFldNamecampo=(lnCnt)
luCurVal=CURVAL(CAMPO(lnCnt))
luOldVal=OLDVAL(CAMPO(lnCnt))
luUsrVal=eval(CAMPO(lnCnt))

***Serqueestecampodecausarumconflito?
IFluCurVal==luOldVal

***Nenhumaalteraofoifeitaparaocampo
***Entonenhumproblemasurgir
LOOP
FIMSE

***Asalteraesforamfeitasparaocampo
ESE!CAMPO(lnCnt)$lcFldList

***Masousuriocurentnomodificouocampo
***Assim,podemosapenasatualizlodoCurval()
REPLACE(CAMPO(lnCnt))COMluCurVal
OUTRO

***Algomudou!Aquestooqu?
IFEVAL(CAMPO(lnCnt))==luCurval
Captulo8:OsdadosembuffereTransaes 267

***Ousurionomudourealmentenada
LOOP
OUTRO

***Esteumconflitoquenopodemosresolverprogramaticamente
***Ento,adicionloaoCursorConflito
COMThisForm
INSERTINTOcurcflix
(CfxRecNum,
cfxFldNam,
cfxOldVal,
cfxCurVal,
cfxUsrVal,
cfxForcit)
VALORES
(.ExpToStr(RECNO()),
lcFldName,
.ExpToStr(LuOldVal),
.ExpToStr(LuCurVal),
.ExpToStr(LuUsrVal),
2)
ENDWITH
FIMSE
FIMSE
PRXIMO

Paracadacamponoregistro,estemtodolvalortamponadadousurioatual,o
OLDVAL()e Curval()valoresepassalosatravsdeumaverificaolgicadaseguinteforma:

Seousurionomudounestecampo,eosvaloresantigoseatuaisso
idntico,
ignorarestecampo
OUTRO
Seousurionomudouocampo,masosvaloresantigoseatuaisso
diferente,
actualizaramemriaintermdiadirectamentecomovaloractual
OUTRO
Seousurioalterouocampo,masovalornobufferjest
idntico
paraovaloratual,ignoreestamudana
OUTRO
Esterealmenteumconflito,entoinserirumalinhaparaocursorconflitos

NotequeestemtodousaoGetUserChangesfunodiscutidoacima,embora,
porqueestaumaclasse,ocdigofoiadicionado(inalterado)comoummtodo.Amesmalgica
aplicaseaparenteduplicaodosExpToStreStrToExpfunes(quens
introduzidonoCaptulo2)comomtodos.Estaclassedependedosdadosqueestosendotratadosemum
formaespecficaenodeveconfiaremqualquercoisaforadesimesmo.Setivssemosderecorreraestas
queestodisponveisemumarquivodeprocedimentodefunes,estaramosquebrandooencapsulamentodo
classeedeixandonosabertosapossveisproblemasseosprocedimentosexternosdeveriamser
modificada.
ParaverestaclasseemaobastaexecutaroShowConf.prgprogramaincludosnaamostra
cdigoparaestecaptulo.Esteprogramacriaduasinstnciasdeumformulriodedadossimples(verFigura
8.7).Fazeralgumasalteraesparaumainstnciadoformulrio,emseguida,semclicaremSALVAR,mudepara

268 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

aoutrainstnciaefazerepouparmaisalgumasalteraes.ClicaremSalvarnaprimeiraforma
agorairchamarateladeresoluodeconflitossempreassumindoqueasalteraesfeitasno
aoutrainstnciatercausadoumoumaisconflitos.
Figura8.7Forarconflitosdeatualizao

Ocdigoinvocandoateladeresoluodeconflitosestcontido(paraefeitosdopresente
demonstrao)nomtodocliquedoSalvarobotodoformulrio.Muitoexigidopoucocdigo,
doseguintemodo:

***Selecioneatabelaprincipal
SELECT(Thisform.PrimaryTable)

***Experimenteeatualizao
llok=TABLEUPDATE()

***Seaatualizaofalhar,criaroobjetoderesoluodeconflitos
ESE!llok

Captulo8:OsdadosembuffereTransaes 269

oUpd=CREATEOBJECT('updres',ThisForm.DataSessionID,ALIAS())

***Seoobjetoexistehumverdadeiroconflito,mostraraforma
IFTYPE('oUpd')="O"E!ISNULL(oUpd)
oUpd.Show()
FIMSE
FIMSE

Lembreseaformacomoaclassederesoluodeconflitosconstrudogarantequeoobjeto
persistesomentequandoumconflitoquenopodemserresolvidospormeiodeprogramaodetectado.este
abordagemgarantequeousuriosvumconflitoquandohrealmenteumqueprecisapositiva
intervenotudoorestotratadodeformatransparente.

usandotransaes
UmatransaonoVisualFoxProforneceumacamadaextradebufferquepodeseestenderpormudanaspara
vriastabelas(emoposiocapacidadetampo"normal",queespecficodatabela).Existem,noentanto,
hopesparacontrolarestacamadaadicional.Paraqualquertransaoou"tudoou
nada",emboravocpodeaninhartransaesatcinconveisdeprofundidadeetaistransaesaninhadas
sodesenroladoemum"ltimoaentrar,primeiroasair"base.Afunoprimriadeumatransacoconsisteem
que,quandomudaparavriasmesassodependentessucessoumdooutro,nosofeitasalteraes
assegurar
aqualquertabela,amenosquetodasasatualizaesdetabelaassociadostambmpodemserfeitas.
Umatransaoiniciadacomuma" BeginTransactioncomando"eterminadapor
queruma" TransaoEnd"("Commit")ou" RollBackcomando".Noentanto,estessoseparados
comandosenoconstituemuma"EstruturadeControle"(como if...else...ENDIFou FAZER
CASO...ENDCASE).Nohnenhumaexignciaparaocomandodefechoparaestarnomesmomtodo(ou
atmesmoomesmoprograma)queocomandoiniciar,anicaregraquecada Begin
Transaodecomandoestdevidamenteencerradoemalgumlugar.Noentanto,certamentemaisfcildeler
emanterseucdigoquandoocdigodegerenciamentodetransaomantidoemumslugar.
Restrieselimitaes
controlesdoVisualFoxProegerenciatransaesatravsdaDBC,mesas,portanto,livres
nopodeparticipardeumatransao,emboraumanicatransaopodeincluirtabelasde
vriosbancosdedados.
Enquantoumatransaoestativa,todososregistros(detodasastabelas)queestoparticipandodo
operaoestototalmentebloqueadosvocnopodelerouescrever,essesregistros!Poresta
razo,imperativoque,emaplicaesmultiusurio,astransaessoapenasativoparaomaiscurto
umespaodetempopossvel.
Finalmente,oscomandosquealteramoestadodeumatabela(emoposiosuadados)nopodeserutilizada
dentrodeumatransao.Alistacompletadeestespodemserencontradosnoficheirodeajudanombitodo"Begin
Transao"tpico.NoteseespecialmentequeoCURSORSETPROP()eTABLEREVERT()funesso
nosuportadoenquantoumatransaoestativa.

Quandoeuprecisodeumatransao?
Anicavezquevocrealmenteprecisausarumatransaonomanuseiodedadosque,embora
armazenadasemtabelasdiferentes,interdependente.Porexemplo,emumagestodeinventrio
aplicativoquevocnoiriarealmentedesejaatualizarolivresdeumitemsealinhaparaque

270 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

esseitemnopdesersalvoporalgummotivo.Emborabastantedistinta,essasduasaesso
claramenteinterrelacionadosedevemsermanuseadoscomoserealmentefossemumanicaoperao.Assim,seo
ordempodesercolocado,oestoquedeveseratualizado,masseaordemnopodesercolocado,entooestoque
nodeveseratualizado.
perfeitamentepossvelescrevercdigoqueatingeoresultadonecessrio(emuitossistemas
escritaemversesanterioresdoFoxProtertalcdigo),maselenoumexercciotrivial.UMA
transaonosdacapacidadedelidarcomtodososproblemascomalgumcdigomuitosimplescomoisto:

BEGINTRANSACTION
llokLOCAL
llok=TABLEUPDATE(2,.F.,"OrderLines",laFailed)
IFllok

***LinesforamatualizadosOK,agorafazeroestoque
llok=TABLEUPDATE(2,.F.,"FreeStock",laFailed)
OUTRO

***errosdeatualizaoHandleOrderartigoaqui
FIMSE
IFllok

***TudoOK,entoconfirmarasalteraes
ENDTRANSACTION
OUTRO

***Algofalhou,entodesfazertudo
ROLLBACK
FIMSE

Qualoefeitoqueareversoteremmeusdados?
Arespostacurtaaquinenhum!Oobjectivodeumatransacoconsisteemassegurarquetodosos
alteraesobtercomprometido,ounenhumfazer.Seguese,portanto,que,nocasodeumatransacofalhada,
Astabelasdevemserexatamenteomesmoestadoemqueestavamantesdaoperaofoide
iniciado.ReversonoomesmoqueumTableRevert()equenomudaoestadoinicial
quaisquerdados.Noentanto,sevoctiverfeitoalteraesnosdadosdentrodatransao,entoqualquer
alteraesserodesfeitascomopartedorollback.Ocdigoaseguirpodeserexecutadoapartirda
linhadecomandoparavercomoissofunciona:

demoneUSE
CURSORSETPROP('Buffering',5)
BEGINTRANSACTION
Pesquisar
REPLACEALLd1cityCOM"London"

Notesequeestano,defacto,alterartodososdados.Nohrestriessobreatrocadedados
dentrodeumatransao,emboravocnopodealteraroestadodeumatabela(oseumododebuffer,
ndiceseassimpordiante).VocaindapodeusarTableUpdate()para"confirmar"asalteraes:

?TABLEUPDATE(2,.F.,'Demone')
Captulo8:OsdadosembuffereTransaes 271

aparentementevaiconfirmarasalteraes,comomostradopelofatodequeumSelectSQLagorapodem"ver"
otroco:

SELECIONEd1CityDISTINCTFROMdemoneINTOcur_cityCURSORNOFILTER

dlheagoraumanicalinhacom'London'comoanicacidade.Noentanto,emboraactualizado,o
mudanasaindanoesto"comprometidos"eaindapodeserrevertidaporreverteratransao:
ROLLBACK
SELECIONEd1CityDISTINCTFROMdemoneINTOcur_cityCURSORNOFILTER

Reexecutaraconsultaretornaalistaoriginaldecidadescomosenadativesseacontecido.

Hey,issosignificaqueeupossousarumatransaoparapermitirSQLparav er"pendentes"
alterar?
Arespostacurtasim!UmaconsultaSQLnormalmenteobtmseusdadosapartirdatabelasubjacente,demodo
vocnopodeusarSQLparaverificaralgoqueumusurioentrou,oualterado,emumatabelatamponada
atqueamudanatenhasidosalvousandoumTableUpdate().Noentanto,VisualFoxProsempre
Dadosverificaqueestemcachenobufferdetransaoantesderecorreraessearmazenadosemdiscopara
consultasemtabelasenvolvidasnastransaes.Assim,envolvendoaTableUpdate()emumatransao,
vocpode"temporariamente"atualizarumatabela,executeoSQL,eemseguida,reverterasalteraes.
No,evidentemente,umcustoaqui(afinalnadarealmentelivre!).Vocdevesempre
lembresequeumatransaobloqueiaoutrosusuriosforadosregistrosenvolvidosparaquearegradeouro
quandoseutilizaumatransaosempreparamantloativoporumtempotocurtoquantopossvel.Gostaramos
Norecomendamosousodessatcnicaparagrandesquantidadesdedadosouconsultascomplexas,maspodeser
muitoeficazquandousadoparaoperaesdetabelaindividuais(comosomadeumconjuntodevaloresexibidosno
umagradedeedio).

ComoqueumimpactotransaoemmecanismosdebloqueiodoFoxPro?
Nonvelmaissimples,arespostaqueumatransaotempoucoefeitosobreamaneiraqueVisual
FoxProlidacomacolocaodefechaduras.Emoutraspalavras,qualquermomentoqueumbloqueiochamadotanto
implcitaouexplicitamente,elesercolocado.MuitosVisualFoxProcomandoschamadaparaum"implcito"
para
bloquear.(Umalistacompletadestescomandos,emconjuntocomotipodebloqueioquecolocam,podeserencontrado
GuiadoProgramador,Captulo17"Programandoparaacessocompartilhado.")Semprequeumde
em
estescomandosusadodentrodeumatransao,VisualFoxProliberaobloqueioquecolocasobre
terminaodatransaco.
Fechadurasquesocolocadosexplicitamente(usando RLOCK()ou FLOCK())sejamrespeitadospor
transaesedevem,portanto,tambmserliberadoexplicitamentepeloapropriada DESBLOQUEAR
comando.Noentanto,devemosdizerquensgeralmenteencontramospoucautilidadeparabloqueiosexplcitosno
FoxPro.Sevocestiverusandotabelasetransaesembuffer(eporquevocnoser?),O
Visual
melhoremaisseguramaneiradelidarcombloqueiodentrodeumatransaopermitirqueVisualFoxProfazerissopor
voc.
Gotcha!bloqueiosautomticosnemsemprediv ulgadosnoVisualFoxProVerso5.0
Umapalavradecautela,sevocestiverutilizandoaVerso5.0humbugquepodecausarproblemasse
vocusarcomandosquecolocambloqueiosdearquivoautomticosdentrodeumatransao.Essesbloqueiosso
NOliberadoquandoatransaotermina.Ocdigoaseguirmostraoproblema:

272 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
***Abraumatabela
USE<table>

***Definirbufferdetabela
CURSORSETPROP('Buffering',5)

***Iniciarumatransao
BEGINTRANSACTION

***Useumcomandoqueexigeumbloqueiodearquivo
REPLACEALL<field>com<testVal>FOR<condio>

***VerifiqueLockingEstado
?ISFLOCKED() &&.F.

***Atualizaratabela
?TABLEUPDATE(.T.) &&.T.

***VerifiqueLockingEstado
?ISFLOCKED() &&.T.

***Completaratransao
ENDTRANSACTION

***VerifiqueLockingStatusarquivoaindaestbloqueado
?ISFLOCKED() &&.T.

Issopode,emumambientemultiusurio,serumgrandeproblemaquandovocprecisafazerbloco
atualizaesemtabelasenvolvidasemrelacionamentosumparamuitos.Felizmente,humadetrabalhosimples
emtornousandoum SCAN...ENDSCANcomumaexplcitasubstituirparaaslinhasapropriadasemvezdeum
REPLACEALL.Aindamais,felizmente,esteproblematemsidocorrigidoemversesposterioresdoVisual
FoxPro.

Possousarvriastransaesaomesmotempo?
Sim,atualmenteastransaespodemseraninhadasatcinconveisdeprofundidadeea TXNLEVEL()funo
podeserusadoparadeterminaronmerodetransacesabertas.Noentanto,astransaesaninhadasso
semprelibertadonumabaseltimainfirstoutdemodoquealgicadeveserconstrudocomcuidadopara
evitarinadvertidamentefechandooerradoespecialmenteseocdigodecontroleestcontido
maisdoqueummtodo(ouprocesso).Desdequeosequenciamentotratadocorretamente,
nomaisdifcildeusarvriastransaesdoqueusarumnico.
Vriastransaessoutilizadosquandoatualizartabelasqueformamgruposlgicos,masque
noprecisadesertratadascomoumanicaunidade.Comonopodemoscontrolarosacontecimentosdentrodeumatransao
qualquernvelmaiordegranularidadedoqueaprpriaoperao,anicamaneiradelidarcomessescasos
em
aninhandoastransaessubgrupodentrodeumatransaoprincipalou"wrapper".Porexemplo,
consideraraadiodeumnovoclienteeprimeiropedidodesseclienteparaumconjuntotpicodetabelas.
evidentequenodesejaadicionarregistrosparaatabelaOrderHeaderamenosquetenhamos
adicionadocomsucessodonovoclienteemprimeirolugar.Estaasituaoclssicaemqueusaramos
umatransao.Noentanto,nsnogostariadeadicionarosdetalhesdopedido,seocabealhodaordempodia
nosersalvo.Issotambmimplicaumatransao,masdevemosrejeitartantooclientecomoo
ordemdocabealhosporquenopodeatualizarumalinhadedetalhe?Emalgumassituaes,arespostapode
bemserquesim,masnamaioriadoscasosnsrealmentegostariaqueaadiodoclientea'vara',mesmo

Captulo8:OsdadosembuffereTransaes 273

senopodeseradicionadoaordem.Anicatransaonosuficiente,masumpardeaninhados
transaesiratenderoprojetodeleimuitobemcomoilustradoabaixo:

***Comeceoexterior("Wrapper')operao
BEGINTRANSACTION

***Atualizaratabeladeclienteemprimeirolugar
llTx1=TableUpdate(1,f.,'cliente')
IFllTx1

***Tabeladeclienteatualizadocomsucesso
***Comeceasegunda,transao'interior'paraordens
BEGINTRANSACTION
llTx2=TableUpdate(1,f.,'OrderHeader')
IFllTx2

***PedidosAtualizado,tentaagoradetalhes
llTx2=TABLEUPDATE(2,.F.,'OrderDetails')
IFllTx2

***Asduastabelasdepedidosatualizadacomsucesso
***Entoconfirmaratransaoordens
ENDTRANSACTION
OUTRO
***AtualizaoEncomendafalhou
***RollBackordensinteirastransao
ROLLBACK
FIMSE
OUTRO

atualizao***OrderHeaderfalhounenhumpontonatentativadetalhes
ROLLBACK
FIMSE

***Masaatualizaoclientejtinhaconseguido,entocometer
ENDTRANSACTION
OUTRO

***Atualizaodoclientefalhounenhumpontoemprocesso
ROLLBACK

FIMSE

Estecdigopodeparecerumpoucoestranhoprimeiravista,masnoenfatizaropontoque
BEGIN...ENDTRANSACTIONnoconstituiumaestruturadecontrole.Notesequeexistemdois
comeandocomandos,umparacadatransacoeduas'Commit'comandos,umparao
tabeladeclienteseumparaopardetabelasdeordem.Noentanto,existemtrsrollback
comandos.Umparaatransaoexterna,masdoisparaatransaointernaparaatenderaofacto
queoutabelaenvolvidapodefalhar.
Algicaficaumpoucomaiscomplicado,maistabelasestoenvolvidos,masosprincpiospermanecemos
mesmo.Noentanto,quandomuitasmesasestoenvolvidos,ousevocestescrevendorotinasgenricaspara
lidarcomumnmeroindeterminadodemesasemcadanvel,eleprovavelmentesernecessrioquebrar
asoperaesacimaemmtodosseparadosparalidarcomUpdate,Commitefunesdereverso

274 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

eusaroTXNLEVEL()funoparamanterocontroledonmerodetransaes.(Lembrar
queVisualFoxProlimitadoacincooperaessimultneas.)

Algumascoisasparaassistiraousartampoem
aplicaes
NopossvelusarOLDVAL()parareverterumcamposobobufferdetabela
Vocpodeterseperguntado,aoleradiscussodaresoluodeconflitosanteriormenteneste
captulo,porquenofazerusodoOLDVAL()funoparacancelarasalteraesdeumusuriono
mesmaformaqueusamosovalorretornadopeloCURVAL()paralimparosconflitosemdiferentescampos.
Arespostasimplesmentequenopodemosfazlodestamaneiraquandoseusaqualquerformadebufferdetabelase
ocampoutilizadoemqualquerumndiceprimriooucandidatosemobteruma"exclusividadedondice
erro<nome>violada".EsteumbugreconhecidoemtodasasversesdoVisualFoxProe,
umavezqueotrabalhoemtornooferecidopelaMicrosoftusaroTableRevert()funoemvezdisso,ele
pareceimprovvelparansqueelenuncavaisercorrigido.
Noentanto,issonopareceserumasoluocompletamentesatisfatriaporqueTableRevert()
nopodeoperaremqualquercoisadiferentede"Row"nveleassimdesfazerumaalteraoemumcampodechave
semperderquaisqueroutrasalteraesnomesmoregistrorequerumpoucomaispensamento.Aomelhor
soluoqueencontramosfazerusoda SCATTERNOMEcomandoparacriarumobjeto
cujaspropriedadessonomeadososmesmosqueoscamposnatabela.Osvaloresatribudosao
aspropriedadesdoobjetosoosvaloresatuaisdobufferderegistroepodemosmudaro
valoresdepropriedadeusandoumaatribuiosimples.Oprogramaaseguirilustraoproblema
easoluode:

**********************************************************************
*Programa :ShoOVal.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:IlustraproblemacomousoOLDVAL()pararevertercampo
* :QueusadoemumachaveCandidate
* :Ref:MSKnowledgebasePSSNmeroID:Q157405
**********************************************************************
***Criarepreencherumatabeladeexemplo
CriaroexemploTABLE(Field1C(5)UNIQUE,Field2N(2))
INSERTINTOamostra(Field1,Field2)VALUES("um",1)
INSERTINTOamostra(Field1,Field2)VALUES("dois",2)
INSERTINTOamostra(Field1,Field2)VALUES("trs",3)

***ForaemmododetabelaBuffered
SETMultiLockON
CURSORSETPROP("Buffering",5)

***PRIMEIRODOPROBLEMA
***CampodechaveMudana
SEJAOMELHOR
REPLACEfield1WITH"quatro",field2COM4
PULAR
SKIP1

***ValorReverterusandoOLDVAL()
REPLACEfield1COMOLDVAL("Field1")

Captulo8:OsdadosembuffereTransaes 275

PULAR
SKIP1

***Vocagorareceberumamensagemdeerro"exclusividadedondiceFIELD1violada"
***CliqueemIgnorarereverteramesaperdealteraesemtodososcampos!
TableRevert(.T.)

***NOWASOLUO
***RepetiroSubstituir
SEJAOMELHOR
REPLACEfield1WITH"quatro",field2COM4
PULAR
SKIP1

***Dissipaoscamposparaumobjeto
SCATTERNOMEloReverter

***ReverterovalorKeyField
loReverter.Field1=OLDVAL('campo1')

***Reverteralinhanatabela
TableRevert(f.)

***Reunirvaloresdevolta
REUNIRNOMEloReverter
PULAR
SKIP1

***NOTA:Nenhumerro,eamudananocampo2retido
***Confirmeareverso
TableUpdate(1)
TESTANOWAIT

Nomomentodaescrita,ocomportamentodescritoacimafoibastanteerrtico
quandoumacadeiadecaracteresfoiusadocomochavecandidata.Porexemplo,
sevocREPLACEfield1WITH"sete"vocnoreceberumerroemtudo!
Noentanto,nohnadademgicosobreacadeia"sete"comovriosoutrosvalores
foramencontradosquenocausouumerro,masnopodamosdiscernirumpadrodentro,ou
formularqualquerexplicaolgicaparaocomportamentoobservado.

Gotcha!bufferdelinhaeoscomandosquemovemoregistro
apontador
Observamosanteriormentequemudaparaumregistroemumatabelalinhatamponadasoautomaticamente
peloVisualFoxProsemprequeoponteirodoregistroparaessatabelamovido.Issoestimplcitona
comprometida
desenhodememriaintermdiadelinhaetotalmentedesejvel.Oquenotodesejvelqueeleno
semprebvioqueumcomandoespecficoestrealmenteindoparamoveroponteiroderegistoeeste
podelevararesultadosinesperados.Porexemplo,previsvelqueaemissodeuma SEEKou SKIP
comandoestindoparamoveroponteirodoregistroe,portanto,noserianormalmentepermitirquetais
umcomandoaserexecutadosemprimeiroverificaromododebuffere,sefileirabufferestem
vigor,averificaodealteraesnoconfirmadas.
276 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Damesmaformaqueseriadeesperarqueautilizaodeum GOTOcomandotambmiriamoveroregistro
ponteiroseoregistroespecificadonofoijseleccionada.Noentanto, GOTOsempremoveo
ponteirodoregistro,mesmosevocusaro GOTORECNO()formadocomando(quemantmo
ponteirodoregistronomesmoregistro)eassimsersempretentarconfirmarasalteraespendentes
sobbufferdelinha.
Naverdade,qualquercomandoquepodepegarouumnmerorecordeexplcitooutemumescopo( PARA
ou ENQUANTO)Clusulavaifazercomqueoponteirodoregistroparamovere,portanto,umacausaprovvelde
problemasquandousadosemconjuntocommemriaintermdiadelinha.Existemmuitosdessescomandos
VisualFoxProincluindoobvio,como SUM, AVERAGEe CALCULAR,bemcomoalgunsmenos
bvioscomo cpiaparaARRAYe desbloquear.
Estaltimaparticularmentesorrateira.Oqueistosignificaquesevocestiverusandobloqueiosexplcitoscom
umalinhatamponadamesa,emseguida,desbloquearumregistrodirectamenteequivalenteaemissodeumTableUpdate()
evocimediatamenteperdemacapacidadededesfazerasalteraes.Notemoscertezaseissoerarealmente
ocomportamentodesejado(emborapossamosadivinhar!),massimsublinharospontosfeitosnoincio
ocaptulo.Emprimeirolugar,nohlugarrealparabufferdelinhaemumaplicativo,esegundo,a
melhormaneiradelidarcombloqueioaousarobufferpermitirqueVisualFoxProparafazlo.

Captulo9:Vistasemparticular,SQLemGeral 277

Captulo9
Visualizaesemparticular,SQL
em Geral
"Hmuitoscaminhosparaotopodamontanha,masavistasempreamesma."
(Provrbiochins)

Osdoiscaptulosanteriorestmseconcentradoprincipalmentenagestoeutilizaode
tabelasnoVisualFoxPro,mashmuito,muitomaisquepodeserfeitoatravsdaentrada
nomundodoSQLemgeral,evistasemparticular.Umavezqueestamosconcentrandoseem
VisualFoxPro,estecaptulotrataprincipalmentecomvistaslocaisenoabordao
objectodeofflineoupontosdevistaremotoemqualquerdetalhe.Esperamosquevocaindavai
pepitasaquiparamantlointeressado.
encontrarosuficiente

AsvisualizaesdoVisualFoxPro
Ocdigodeexemploparaestecaptuloincluiumbancodedadosseparado(CH09.DBC)quecontmo
tabelaseexibieslocaisutilizadosnosexemplosparaestaseo.Noinclumosqualquerespecfica
exemplosqueusamvistasremotos(seapenasporquenopodemosgarantirquevocvaiterum
fontededadosapropriadoconfiguradoemsuamquina),masseforcasodissojindicouqualquer
diferenassignificativasentrepontosdevistalocaiseremotos.

Oqueexatamenteumaviso?
OarquivodeajudadoVisualFoxProdefineumavisonosseguintestermos:

"Adefiniodatabelavirtualpersonalizadoquepodeserlocal,remotoouparametrizado.Visualizaes
refernciaaumoumaistabelasououtrospontosdevista.Elespodemseratualizados,eelespodemfazerreferncia
tabelasremotas".

Apalavrachaveaqui"definio",porqueoobjectivorealmenteumaconsultaSQLquearmazenado
dentrodeumrecipientedebancodedados,mas,aocontrriodeumasimplesconsulta(.QPRarquivo),umaviso
visualmentenorecipientebasededadoscomoseelerealmenteestavaumamesa.Elapode,paratodososefeitosprticos,
representado
sertratadocomosefosserealmenteumatabela(ouseja,paraabrirumavista,vocsimplesmente USElo,eeletambm
adicionadoaoDataEnvironmentdeumformulrioemtempodedesign).Existempelomenostrsvantagensprincipais
podeser
aganharcomousodevistas.
Primeiro,porqueumavisorealmentenoarmazenarquaisquerdadospersistentemente,elenorequerpermanente
armazenamentoemdiscoespao.Noentanto,porqueadefinioarmazenada,avisopodeserrecriadoqualquer
vezquenecessrio,semanecessidadederedefiniroSQL.Emsegundolugar,aocontrriodeumcursorcriado
diretamenteporumaconsultaSQL,avistasempreactualizvelepode,senecessrio,tambmserdefinidospara
atualizaratabelaoutabelas,sobreosquaissebaseia.Emterceirolugar,umavisopodeserbaseadalocal(VFP)

278 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

tabelas,oupodeusartabelasapartirdeumafontededadosremota(usandoODBCeum"Connection")epode
atmesmousaroutrospontosdevistacomoafonteparaseusdadosouqualquercombinaodosanteriores.

Comofaoparacriarumpontodevista?
VisualFoxPropermiteumavistaasercriadodeduasformas,quervisualmente(usandooVista
Designer)ouprogramaticamentecomo SQLCREATEVISTAcomando.Paraobterdetalhescompletossobrecomousar
Criadordevisualizaes,consulteCaptulo8:CriandovisualizaesnoGuiadoprogramador.(Contudo,
lembreseque,comotodososdesigners,oViewDesignertemalgumaslimitaese
certostiposdepontosdevistarealmenteprecisasercriadonocdigo.)Qualquerquesejaomtodoutilizado,o
processoenvolvequatropassos:
Definaoscamposqueopontodevistaircontereamesa(s)apartirdoqualessescampos
devemserseleccionados
especificarquaisquercondiesdejuno,filtrosouparmetrosnecessrios
Definiromecanismoecritriosdeatualizao(seavistaparaserusadoparaatualizaroseu
tabelasdeorigem)
Nomeesalvarofimdeumrecipientedebancodedados

Umagrandevantagemdeusarodesignervistaacriarpontosdevistaqueeleescondeacomplexidadeda
ocdigonecessrioe,enquantoocdigonorealmentedifcil,nopodehaverumaenormequantidadedele
(Mesmoparaumavisosimples),comomostraoseguinteexemplo.AquiestoSQLparaumsimples,mas
actualizvel,vistadeumatabelaquelistanomesdaempresapelacidadeparaumdeterminadopas,comomostradona
ViewDesigner:

SELECIONEClients.clisidDISTINCT,Clients.clicmpy,Clients.clicity
DECH09clientes!
ONDEClients.clictry=cCountry?
ORDERBYClients.clicity,Clients.clicmpy

Enquantoaquiocdigonecessrioparacriaramesmavisoprogramtica:
CRIARSQLVIEW"CPYBYCITY"
ASSELECTDISTINCTClients.clisid,Clients.clicmpy,Clients.clicity
DECH09clientes!
ONDEClients.clictry=cCountry?
ORDERBYClients.clicity,Clients.clicmpy

DBSetProp('CPYBYCITY','View','UpdateType',1)
DBSetProp('CPYBYCITY','View','WhereType',3)
DBSetProp('CPYBYCITY','View','FetchMemo',.T.)
DBSetProp('CPYBYCITY','View','SendUpdates',.T.)
DBSetProp('CPYBYCITY','View','UseMemoSize',255)
DBSetProp('CPYBYCITY','View','FetchSize',100)
DBSetProp('CPYBYCITY','View','MaxRecords',1)
DBSetProp('CPYBYCITY','View','Tabelas','CH09!Clientes')
DBSetProp('CPYBYCITY','View','Preparado',f.)
DBSetProp('CPYBYCITY','View','CompareMemo',.T.)
DBSetProp('CPYBYCITY','View','FetchAsNeeded',f.)

Captulo9:Vistasemparticular,SQLemGeral 279

DBSetProp('CPYBYCITY','View','FetchSize',100)
DBSetProp('CPYBYCITY','View','deParmetros","cCountry,'C'")
DBSetProp('CPYBYCITY','View','Comment","")
DBSetProp('CPYBYCITY','View','BatchUpdateCount',1)
DBSetProp('CPYBYCITY','View','ShareConnection',f.)
DBSetProp('CPYBYCITY.clisid','campo','KeyField',.T.)
DBSetProp('CPYBYCITY.clisid','campo','atualizvel",f.)
DBSetProp('CPYBYCITY.clisid','campo','UpdateName','CH09!Clients.clisid')
DBSetProp('CPYBYCITY.clisid','campo','Tipodedados","I")
DBSetProp('CPYBYCITY.clicmpy','campo','KeyField',f.)
DBSetProp('CPYBYCITY.clicmpy','campo','atualizvel',.T.)
DBSetProp('CPYBYCITY.clicmpy','campo','UpdateName','CH09!Clients.clicmpy')
DBSetProp('CPYBYCITY.clicmpy','campo','Tipodedados","C(40)")
DBSetProp('CPYBYCITY.clicity','campo','KeyField',f.)
DBSetProp('CPYBYCITY.clicity','campo','atualizvel',.T.)
DBSetProp('CPYBYCITY.clicity','campo','UpdateName','CH09!Clients.clicity')
DBSetProp('CPYBYCITY.clicity','campo','tipodedados'"C"(15),)

Emprimeirolugar,devesedizerquenorealmentetoruimquantoparece!MuitosdosVerasdefiniesdenvel
definidoaquisoosvalorespadroesprecisaserespecificadoquandovocprecisadealgodefinido
sedeformadiferente.Ditoisto,continuaaserumexercciodenotrivial(apenascomeandotudodo
declaraesdigitadocorretamentedifcilosuficiente!).Ento,comopodemossimplificarascoisasumpouco?Bem,
VisualFoxProincluiumapequenaferramentamuitotilchamadoGENDBC.PRGquecriaumprogramapara
regerarumrecipientedebancodedados(Vocvaiencontrlono ..\VFP60\TOOLS\GENDBC\sub
diretrio).Asvistasso,comoindicadoacima,armazenadoemumrecipientedebasededados.Ento,porqueno
FoxProfazertodootrabalhoduro?
deixarVisual
Bastacriarumrecipiente(Vazio)basededadostemporriaedefinirseupontodevistanele.Corre
GENDBCevoctemumarquivodeprogramaquenoapenasosdocumentosasuaviso,maspodeserexecutadopara
recriaromododeexibioemseurecipientebancodedadosreal.Maisimportanteaindaexistem,comodissemos,
algumaslimitaesparaoqueodesignerpodesegurar.Umadessaslimitaesenvolvevistascriando
quesejuntarvriastabelasrelacionadascomumprogenitorcomum,masnoumassoutras.Ajuntarseclusulas
produzidopelodesignernoconseguemlidarcomestasituaoeanicamaneiradegarantira
resultadoscorretoscriaressespontosdevistaemcdigo.Usandoodesignerparafazeramaiorpartedotrabalho,e
simplesmenteeditandoascondiesdejunoemumPRGarquivo,amaneiramaisfcildecriarvisescomplexas.
Umapalavradecautela!Sevoccriarvistasprogramaticamente,certifiquesedequevocnofaz
emseguida,inadvertidamentetentarmodificlosnodesignerdevista,porquevocpodeacabarcomum
vistaquejnofazoqueelepretende.Recomendamosfortementenomeartaispontosdevista
deformadiferenteparadistinguilosdospontosdevistaquepodemsermodificadosdeformaseguranodesigner.Para
modificarumaexibioprogramaticamentecriado,bastaeditaroprogramaquecrialoereexecutlo.

Quandodevousarvista,emvezdeumatabela?
Naverdade,vocnuncaprecisarusarumatabeladenovo!Vocpodesempreusarumpontodevista,mesmoqueessa
simplesmenteumacpiaexatadeumanicatabela.Vamoscobrirestepontomaisadiantenestecaptulo(vera
viso
seosobreescalabilidade).Noentanto,hcertamentealgumasocasies,quandopensamosqueumaviso
deveserusadoemvezdeutilizartabelasdirectamente.
Aprimeira,eprovavelmenteomaisbvio,quandoacriaoderelatriosquerequeremdadosde
tabelasrelacionadas.EnquantooVisualFoxProReportWriterumaferramentabastanteflexvel,eleno(nanossa
opinio)fcildeusaraotentartrabalharcomvriastabelas.Umavisonicapodereduzira
280 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

estruturarelacionalcomplexaaum"arquivosimples"quefacilmentemanipuladopeloescritorderelatrio,tornando
atarefadecriaoderelatriosqueusamdadosagrupadosmuitomaisfcil.
Outro,ousotalvezmenosbvioquealgunscontroles,comogradeselistaoucaixasdecombinao,
muitasvezesprecisausartabelasdeconsultaparaexibirasdescriesassociadascomcamposdecdigo.Criaodeum
vistaactualizvelparacombinarasdescriesjuntamentecomosdados"real"forneceumasimplese
formaeficientedelidarcomtaistarefas.Captulo6(Grids:oscontrolesMisunderstood)inclui
umexemploqueutilizaumavistaprecisamenteparaesseefeitoumaviso,usadocomooOrigemDosRegistospara
agrade,incluiumcampodedescriodeumatabeladepesquisa,etodososcampos,excetoadescrio
soatualizveis.
ExibiestambmproporcionamummecanismoparaacessardadosemversesmaisantigasdoFoxProsem
anecessidadedeconverterosdadosdeorigem.Sevoctentaradicionarumatabelade2.xFoxProaumVisualFoxPro
continerbancodedados,astabelassetornarinutilizvelpelaaplicao2.x.Noscasosemquevocprecisa
paraacessaramesmatabelaemambos2.xFoxProeVisualFoxPro,umavisoforneceasoluo.
EmboraopontodevistadeveserarmazenadodentrodeumDBC,astabelasqueeleusanotemqueser.
Estacapacidade,claro,noselimitandoaFoxProtabelas.Umaexibiopodeserdefinidopararecuperar
dadosdequalquerfontededadosemVisualFoxPro,desdequeumaconexoODBCparaqueosdados
fontepodeserestabelecida.Umavezqueosdadostenhamsidopuxadoparadentrodeumpontodevista,podeser
exactamentedamesmamaneiracomosesetratassededadosnativosFoxPro.Aofazertal"remotovista"
manipuladaem
actualizvel,todasasmudanasfeitasnoVisualFoxPropodeserenviadoparaafontededadosoriginal.
Aocasiofinalparausarumpontodevistaquandovocprecisaparaobterumsubconjuntodedados.Nisso
situao,criandoumavisualizaocomparmetrosmuitasvezesmelhordoquesimplesmentedefinirumfiltro.Naverdade,
lidarcomgradessempremelhorporqueasredesnopodemfazerusodeRushmoreparaotimizar
quando
filtros.Paramaisdetalhessobreousodepontosdevistaemgrades,consulteoCaptulo6.

Espere!Oqueumavistacomparmetros?
Ah!Serquensnomencionarisso?Umavisonemsempretemdeincluirtodososdadosdeumatabela,nem
quevocsempretemqueespecificaracondiodefiltroexatonomomentodaconcepo.Emvezdissovocpodedefiniruma
Verqueincluiumacondiodefiltroquevaiserbaseadaemumparmetrofornecidoemtempodeexecuo
Daotermo"parametrizadaVer'.
Umavistaparametrizadadefinidaatravsdainclusodeumacondiodefiltroqueserefereaumavarivel
nome,propriedadeoucampoemumatabelaabertaquefoiprefixadocomum"?"doseguintemodo:

ONDEClients.clicity=city_to_view?

Quandoaexibioabertaoureconsultado,VisualFoxProirprocuraravarivelchamada
e,seoconsiderarsimplesmenteaplicaracondioconformeespecificadoparaainstruoSQLque
preencheavista.Umavistacomparmetrossimplesestincludonasamostrasparaestecaptulo
(vejalv_CpyByCityemCH09.dbc).Seoparmetronomeadonoencontradoquandoavista
aberto,ouconsultadore,umacaixadedilogoquesolicitaumvalorparaoparmetroexibidocomo
esta:

Captulo9:Vistasemparticular,SQLemGeral 281
Figura9.1VerParmetrodedilogo

Definindoparmetrosdev isualizao
Observequeopromptcomea'Enterumvalordecaractere...'.ComooVisualFoxProsabeque
City_To_Viewumacadeiadecaracteres?Arespostaqueno!Estavisoparticularfoi
criadonodesignerdevistae,quandousandoodesigner,humaopono'Consulta'
paddomenudosistema('Visualizaodeparmetros"),quepermitequevocdefinaosnomesedados
tiposdequaisquerparmetrosquevocespecificarnadefinioparaavista.

Figura9.2VerParmetroDefinio

Sevocestiverindoparafazerusododilogodeparmetrosdevisualizaoemumaplicativo,evoc
definirospontosdevistanodesigner,sempredefinirseusparmetrosexplicitamentenestedilogo.(Ns
gostariadesugerirquevocusenomesmuitodescritivostambm!)Sevocnodefiniroparmetro,
emseguida,acaixadedilogoexibidaparaousurionoincluemotipodevaloresperadoevontade
simplesmenteafirmar"InsiraumvalorparaCity_To_View".(Parafazeramesmacoisaaodefiniroobjectivo,
cdigoexigeapenas(maisuma)chamadaparaoDBSETPROP()funo).
Noentanto,emnossaopinio,simplesmenteutilizandoodilogopadronoumaboacoisaafazeremum
aplicaoportrsrazes.Primeiro,VisualFoxPronovalidaaentradaqueousuriodigita
nacaixadedilogo(mesmoquandovocprdefiniroparmetroeseutipodedados),evocnopode
validarqueaentradaantesdeseraplicadoquer.Ento,seoparmetroforinvlido,vocvaisimplesmenteficar
umerro.Emsegundolugar,oprpriodilogonorealmentemuitofcildeusar.Afinal,oqueamdia

282 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

uservaifazerdealgoqueestpedindoum'ViewParameter'?Finalmente,sevocestiverusando
vriosparmetros,emseguida,porqueoVisualFoxPropodeaceitarapenasumparmetrodecadavez,o
usurioserapresentadocomumasriededilogosumapsooutro(muitofeio).

Usandov isualizaesparametrizadasemumformulrio
Asoluorealmentemuitosimplesapenasgarantirqueoparmetroapropriadotenhasidodefinido,
estnoescopoefoipovoadaantesdeabriroureconsultandoaviso.Hmuitos
maneirasdefazerisso,masonossomtodopreferidoodecriarpropriedadesparaosparmetrosdevistano
nveldeformulrioe,emseguida,paratransferirosvaloresdetaispropriedadesparaasvariveisapropriadas
emqualquermtodoqueestconsultandoavista.Istotemduasvantagens.Primeiro,elegarantequeo
valoresatuaisutilizadospeloviewestodisponveisparatodaaforma.Emsegundolugar,permitenosvalidar
osparmetrosantesdeserempassadosparaavista.
Parapermitirqueumusurioespecifiqueosparmetrosnecessrios,devemosforneceraousuriouma
meiosadequadosparaaintroduodeparmetros.Estapoderiaserumaformadepopupoualgumtipode
controledeseleonoprprioformulrio.Maisimportante,nstambmpodeobtervriosparmetrosem
umaoperao,senecessrio.Umaformaquedumexemplodeumtalmecanismoincludono
ocdigodeexemploparaestecaptulo(VuParams.scx).
Figura9.3Usandoumavistacomparmetrosdeumaforma

Estaformausaummododeexibio(lv_adcampanes)queunetrstabelas,queestorelacionadoscomomostrado
naFigura9.4eaceitadoisparmetros,umparao"Nomedocliente"eoutroparaum"Start
Encontro."

Captulo9:Vistasemparticular,SQLemGeral 283

Figura9.4MesasparaVisualizaolv_AdCampanes

AvisofoiadicionadoaoDataEnvironmentdaformacomasua NoDataOnLoad
propriedadedefinidacomo.T.Umavezqueo"Clientesmesa"usadotantonopontodevistaecomoa
caixadecombinao,queteveasua
OrigemDaLinha para BufferModeOverridepropriedadedefinidacomonenhumparadesativarobufferem
queatabela(embora,nesteexemplo,avistanoatualizvel).Oformulriotemdoispersonalizado
Propriedadesparaarmazenarosresultadosdasselecesdoutilizador.O"ReQueryboto"temocdigoemseu
Cliquemtodoparagarantirqueessaspropriedadescontmvaloresetransferilosparaodefinido
parmetrosparaavistaantesdechamaro REQUERY()funo.

Comofaoparacontrolarocontedodeumpontodevistaquandoeleaberto?
Ocomportamentopadrodequalquerpontodevista(localouremoto)quesemprequeaexibioabertapelaprimeira
preencheseporexecutaroSQLqueodefine.Issoseaplicasevocabriravista
vez,ele
explicitamentecomum USEcomandonocdigo(oudajaneladecomando)ouimplicitamente,adicionando
loparaoDataEnvironmentdeumaforma.Noentanto,issopodenosersempreocomportamentoquevoc
quer,especialmentequandoselidacomvistasparametrizadasoucomqualquerpontodevista,localouremoto,que
acessatabelasgrandes.
Paraevitarumavisodecarregartodososseusdados,vocdeveespecificaro NODATAopoquando
abrilo.Nocdigo,apalavrachaveadicionadoaofinaldonormal, USEcomandocomoeste:

USOlv_CpyByCityNODATA

Noentanto,emDataEnvironmentdeumformulrioocursorparaopontodevistatemumNoDataOnLoad
propriedadequedefinida,porpadro,para .F.Definiressapropriedadecomo .T.garantequevocnocomea
o"Entervalorparaxxx'dilogoquandovocinicializaroformulrio.
Independentementedaformacomovocabriroseupontodevista,oresultadoomesmo:vocterumaviso
oscamposdefinidos,massemregistros.Emumaforma,issopermitequecontrolesacopladosparaserinicializado
consistindodetodos
correctamente,mesmoquandonohdadosreaisparaqueelessejamexibidos.Noentanto,amenosquevoc
posteriormente(tipicamentenaInitmtodoouummtodochamadodoInit)preencheravista,
quaisquercontrolesvinculadosaeleserdesativadoquandooformulrioexibido.VisualFoxProfornece
duasfunesqueoperamcomvistaacontrolaramaneiraemqueelesobterosseusdados,
REQUERY()e REFRESH().

QualadiferenaentreREQUERY()eREFRESH()
O REQUERY()funousadaparapreencherumavisoquefoiabertosemdados.Isto
tambmutilizadoparaactualizarocontedodeumavistacomparmetrossemprequeoparmetrofoialterado.
Quandoumpontodevistaconsultada,oSQLquedefineavistaexecutadoeosdadosapropriadosdefinir
recuperado.Afunoretornaou1(indicandoqueaconsultaconseguido)ou0(seo
consultafalhou).Noentanto,notequeovalorderetornoquenolhedizerseosregistrosforam
284 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

recuperado,apenasseoSQLfoiexecutadacorrectamente.Paraobteronmeroderegistroscorrespondentes
vocaindaprecisausar _TALLYcomomostraoseguintecdigo:

NODATAUSOlv_cpybycity
City_to_view='London'
?REQUERY() &&Retorna1
?_TALLY &&Retorna6
City_to_view='Peterborough'
?REQUERY() &&Retorna1
?_TALLY &&Retorna0

O Refresh()funotemumpropsitocompletamentediferente.Eleatualizaocontedodeum
vistaexistentepararefletirquaisqueralteraesaosdadossubjacentesdesdeopontodevistafoipassadorequeried.
Porpadro,somenteoregistroatualatualizada,emboraafunopermitequevocespecifiqueo
nmeroderegistros,eointervaloparaosregistros(combaseemumdeslocamentodoregistroatual)
queseractualizada.Noentanto, Refresh()noreconsultarosdados,mesmoemumparametrizado
exibioparaaqualoparmetromudou,comoilustradoaqui:

NODATAUSOlv_cpybycity
City_to_view='London'
?REQUERY() &&Retorna1
?_TALLY &&Retorna6
?clicity &&Retorna"London'
City_to_view='Peterborough'
?Refresh() &&Retorna1
?clicity &&Retorna"London'

Se REFRESH()simplesmenteignoraoparmetroalterado,oqueousodele?Aresposta
issoporqueoobjectivosemprecriadalocalmentenamquinadocliente,eexclusivoparao
usurioatual,asalteraestabelasubjacentepodemserfeitasquenoestoreflectidosnavista.
Issofacilmentevistosevocabrirumpontodevistae,emseguida,irparaatabelasubjacenteefazerumamudana
diretamente.Avistaemsinovaimudar,massevoc,emseguida,tentarfazerumaalteraoparaavistae
guardlovocterumconflitodeatualizao.Piorainda,reverteramudananomododeexibioaindaser
nodarlheovaloratualdatabelaapenasaquiloqueeraoriginalmenteavista.
Anicamaneiradeobteravisoatualizadachamarum refresh().
Istoporqueavisualizaotemoseuprpriotampo,independentedeque,paraamesasubjacente.isto
norealmenteumproblemasevocconsultarnovamenteumavisocadavezqueousurioqueracessarumnovoconjunto
A REQUERY()semprepreencheopontodevistanovo.Noentanto,sevoctemumasituaoondevrios
dedados.
registrossorecuperadosemumavisoeumusuriopodefazeralteraesemqualquerumdeles,melhor
garantirque,comocadaregistroselecionado,avisualizaoatualizada.Istoasseguraqueoqueoutilizador
vrealmenterefleteoestadoatualdatabelasubjacente.

Porqueasalteraesfeitasemumavisosvezesnoentrarno
tabelasubjacente?
Issopodeacontecerquandovocesttrabalhandocomumavisolocalatualizvelquebaseadoemum
mesaquefoijabertoetamponadaquandoaexibiofoiaberta.Oproblemaocorre
porqueentovoctemduas"camadas"debufferemvigor,masavistassabesobreum
deles.OcomportamentopadrodoVisualFoxProquandosetrabalhacomumavisolocalabrir

Captulo9:Vistasemparticular,SQLemGeral 285

atabelasubjacentesembufferquandoavistaprimeiroconsultado.Noimportaa
VisualFoxProseaexibioabertaapartirdalinhadecomando,emumprogramaouatravsdo
DataEnvironmentdeumformulrio.
Essecomportamentogaranteque,quandoumTableUpdate()chamadoparaavista(quesempreusa
bufferotimista),asalteraesparaatabelasubjacentesoimediatamentecomprometida.
Noentanto,seatabelaemsitamponada,tudooqueatualizadotampodamesaeoutra
TableUpdate()necessriaparagarantirqueasalteraessosalvas.Paraevitaresseproblema,no
abrirexplicitamenteatabela(outabelas)emqueavisobaseada.Emoutraspalavras,quandoseutilizaum
visualizaremumformulrio,quenoadicionarastabelasdeorigemparaofimdeDataEnvironmentdoformulrio.(Se
absolutamentenecessriofazlo,emseguida,definiroBufferModeOverridepropriedadeparaessastabelasparagarantir
vocs
elessoabertossembuffering.)
que
H,evidentemente,umaoutrasituaoemqueoproblemapodesurgir.Isto,quandovocest
usandoopadrodatasessionetermaisdeumaformaaberta.Obviamente,umavezquediferentes
formaspodemutilizartabelasemformasdiferentes,nohnenhumamaneiradeconfianadesaberqueastabelasusadas
umavistadeumaformaaindanotenhasidoabertaemoutraforma,semexplicitamentetestando
pela
cadatabela.Seumatabelativersidoaberto,etamponado,poroutraformaquevocpodefazersobreisso?
Vocnopodesimplesmentemudaromododebufferdatabela.(Issoafetariaaoutraformatambm.)
VocpodemodificarasuaactualizaodecomandosparaforarumaexplcitaTableUpdate()nasubjacente
mesa,masqueparece(paransqualquerforma)paraderrotarumdosprincipaisbenefciosdousodeumavisoque
queelepermitequevocuseosdadosdevriastabelasetratlocomosehouvesserealmenteapenasuma
nicatabelaenvolvida.
AsoluoparaestedilemaparagarantirquevocuseDataSessionsprivadosparaasformas
queusarexibiesatualizveis.UsandoumdatasessionprivadaquevocefetivamenteforarVisualFoxPro
paraabrirastabelassubjacentesdenovo(anlogoaofazerum USE...denovosobreamesa)edepois
nopodehaverqualquerambiguidadesobreoestadodebuffer.Defacto,iriamaislongeedizerque,como
Emregrageral,vocrealmentenodevemisturarvistasactualizveiseastabelasemqueesto
combasenomesmodatasession.Ouusarvistasparatudo(lembrese,vocpodecriarum
vistaquesimplesmenteuma"cpia"diretadatabela)ouuseastabelasdiretamente!

Porqueeuiriaquerercriarumavistaquesimplesmenteumacpiadeum
tabelaexistente?
Htrsrazesparafazerisso.Oprimeiro,talcomodiscutidonasecoanterior,a
evitarterdemisturartabelasevistasdamesmaforma.Asegundaquandoosdadosreais
contidaemumaversoanteriordoFoxProeusadoporoutroaplicativoescritoemque
verso,queiriaimpedilodesimplesmenteatualizarastabelasparaoformatoVisualFoxPro.
Aterceira,eemnossaopinioomaisimportante,quandovocestcriandoumaescalonvel
aplicao.

Oquev ocquerdizercomumaaplicao'escalv el'?


Umaaplicaoescalvelumqueescritoparapermitirqueafontedosdadosasermudado
apartirdoVisualFoxProtabelasparaalgumaoutrafontededadosnormalmenteumservidorbackendcomooSQL
ServerouOracle.Umadasmaioresvantagensdautilizaodepontosdevistaqueamesmadefiniodeexibio
podeserusadoparaacessarqualquerum(ouseja,VisualFoxPro)tabelaslocaisouremotosdedados(ouseja,voltar
nicadiferenaprticaentreumlocaleumremotoexibioqueoltimorequerum
finais).o

286 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

"Conexo"aserdefinida,afimdepermitirqueafontededadosaserconsultado.Emtodososoutrosaspectos
ocomportamentodeumlocaleumremotoexibioidnticoeoscomandosparamanipullos
soosmesmos.
Issosignificaquevocpodeconstruir,testareexecutarumaaplicaointeiramenteemVisualFoxPro.Voc
tambmpode,emdataposterior,redefinirospontosdevistade"locais"para"remota"eterseuaplicativo
executadoapartirdeumafontededadosdiferentesemalterarqualquercdigo.(Issopressupe,naturalmente,
queosnomesdetabelasesuasestruturassoasmesmasemambososVisualFoxProeobackend
bancodedados.)

Soalegal!Comofaoisso?
Emprincpio,muitosimplesusarvistasemvezdetabelas.Noentanto,noapenasumaquestode
substituindovistasparaastabelas.Hmuitasquestesaconsiderar,porque,quandosetrabalhacom
pontosdevista,vocrealmenteesttrabalhandocomumafontededadosremota.Umaplicativobaseadoemvistadeve,
portanto,sermodeladoemumaarquiteturacliente/servidoradequada.Ento,depoisdetercriadoseu
aplicativoparausarvisualizaesquesobaseadasemtabelasdoVisualFoxProlocais,vocnoprecisamais
utilizartabelasdirectamentenaaplicao.Istodlheumaaplicaodetrabalho,quepodemposteriormenteser
comutadaparautilizarumafontededadosdiferente,semquesejanecessriaqualquermodificaodocdigoporque
umavezqueumpontodevistatemsidopreenchida,noimportaparaVisualFoxProsebaseiaseemlocais
oudadosremotos.Entocomoquevocrealmenteconverterumpedidodevistalocalpararemoto
pontosdevista?Hduassoluespossveis,assumindoqueosnomesdetabelaseestruturassoidnticas
emambososVisualFoxProeafontededadosremota.
Umamaneiracriartrsrecipientesdebancodedados.Aprimeiracontmolocal,VisualFoxPro
mesaseosegundocontmapenasospontosdevistalocaiscombasenastabelasnoprimeiro.Oterceiro
contmosmodosdeexibioremotosequivalentes(easinformaesdeconexorelevante).Issopermite
lhemanterosnomesdeambosospontosdevistalocaiseremotosomesmo.Dentrodoaplicativo,
vocforneceummecanismoparaespecificarquaisdosrecipientesdebancodedadosbasedevistaparaser
usava.(IstopoderiaserfeitoatravsdaleituradeumINIarquivoouumadefinioderegisto.)Simplesmentemudando
esteponteirodebancodedados,aaplicaomudadelocalparausarmodosdeexibioremotosenorequernenhum
cdigoadicionalalgum.
Estaaabordagemmaisflexvel,poiselemantmapossibilidadedecorrercontra
oudadoslocaisouremotos.tambmexigemaismanutenoeconfiguradoparaassegurarqueo
vistaslocaiseremotossosempresincronizadoscomastabelas.Talcomoacontececomtudo,h
umtradeoffaqui.
Asegundamaneirarealmenteparaconvertervistaslocaisemvistasremotos.Esteomelhorfeitopor
criando,comoantes,vrioscontentoresdebancodedadosembora,nestecaso,precisamosdeapenasdois
(Umparaoslocaisetabelasparaumavista).Paraconverterospontosdevistadolocalparaoremoto,
primeirogerarocdigoparaospontosdevistalocais(usandoGendbc.prg)comoumprograma.Esteprogramapode
emseguida,sermodificadopararedefinirospontosdevistacomovistasremotos.Oprogramamodificadoentocorrerpara
gerarumnovorecipientedebancodedados,incluindoapenasvistasremotos.
Emboramaissimplesdemanter,esteessencialmenteumaoperaounidirecional,porquevocperdeo
capacidadedeexecutaremrelaoaosdadoslocalquandoasvistassoredefinida.Aabordagemser,comosempre,
dependerdasnecessidadesespecficasdaaplicao.

Captulo9:Vistasemparticular,SQLemGeral 287

Conv ertendov istaslocaisemv istasremotosprogramaticamente


Ocdigoaseguirmostraoquopoucoadefiniodeumavisolocalprecisasermodificadopara
transformloemumavisualizaoremota.Comovocpodever,almdeespecificaraconexoeonome
dobancodedados,nohrealmentenenhumadiferena:
LOCAL:CREATESQLVIEW"clientes"
*ASSELECTFROMVfpdata!Clientes

REMOTO:criar"CLIENTES"VistadeSQL
REMOTOCONNECT"SQL7"
*ASSELECTFROMdbo.CustomersClientes

Naverdade,orestodocdigonecessrioparacriarquerolocalouavistaremota,novamente
comaexcepodeonomedobanco,idnticoAssim,porexemplooKeyField
("Customerid")definiesparecidocomeste:

LOCAL
*PropsparaocampoCustomers.CustomerID.
DBSetProp('Customers.CustomerID','campo','KeyField',.T.)
DBSetProp('Customers.CustomerID','campo','atualizvel",f.)
DBSetProp('Customers.CustomerID','campo','UpdateName',
'Vfpdata!Customers.CustomerID')
DBSetProp('Customers.CustomerID','campo','Tipodedados","C(5)")

CONTROLOREMOTO
*PropsparaocampoCustomers.CustomerID.
DBSetProp('Customers.CustomerID','campo','KeyField',.T.)
DBSetProp('Customers.CustomerID','campo','atualizvel",f.)
DBSetProp('Customers.CustomerID','campo','UpdateName',
'Dbo.customers.customerid')
DBSetProp('Customers.CustomerID','campo','Tipodedados","C(5)")

Enquantoocdigoparacriaraconexotambmmuitosimplesnaverdade,eseparececomisso:

CriarumaligaoSQL7
DATASOURCE"SQL7Adamastor"
USERID"xxxxxx"
SENHA"YYYYYY"

****Aspropriedadesdeconexo
DBSetProp('SQL7','Conexo','Asynchronous',f.)
DBSetProp('SQL7','Conexo','BATCHMODE',.T.)
DBSetProp('SQL7','Conexo','Comment','')
DBSetProp('SQL7','Conexo','DispLogin',1)
DBSetProp('SQL7','Conexo','ConnectTimeOut',15)
DBSetProp('SQL7','Conexo','DispWarnings',f.)
DBSetProp('SQL7','Conexo','IdleTimeOut',0)
DBSetProp('SQL7','Conexo','QueryTimeOut',0)
DBSetProp('SQL7','Conexo','Transaces',1)
DBSetProp('SQL7','Conexo','bancodedados','')
poucoprovvelqueemumambientedeproduovocdeixariatodasessasconfiguraesemseu
defaults(queoquevemosaqui),masaquantidadedemodificaonecessriamuitolimitado.

288 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

claro,htodaumasriedeproblemasassociadosaverdadeconcepoeconstruodeumaverdadeira
aplicaoescalvel.Enquantoquedefinitivamenteforadombitodestelivro,osmecnicosde
dimensionamentodeumaplicativobaseadoemvistaso,comovimos,realmentemuitosimples.

Qualamelhormaneiradeindexarumpontodevista?
Desdeumpontodevista,naverdade,criadoporumainstruoSQL,elenotemnenhumndicedasuaprpria.
Noentanto,umavezqueoobjectivosemprecriadolocalmenteeexclusivoparaousurioatual,criando
ndicesparapontosdevistano,porsis,problemtica(desdequevoclembresededesligartabela
bufferaocriarondice).Consulte"Comoindexarumatabelatamponada"noCaptulo7paraobtermais
informaessobreestetpico.Anicaquestosemelhorparacriarondiceantes,ou
depois,preencheravista.
Atcertoponto,issodependedaquantidadededadosquevocesperaparatrazerparadentrodo
vereondeosdadosestsendorecuperado.Porexemplo,parabaixarcercade90registrosdeuma
instalaolocaldoSQLServeremumavisoeconstruirndicesemdoiscampos,obtivemosa
seguintesresultados:

OpenViewepreencher=0,042segundos
ndiceVerPovoada =0,003segundos
Tempototal =0,045seg

OpenViewendice =0,033seg
Preenchervistaindexada
=0,016seg
Tempototal =0,049seg

Comovocpodever,hpoucadiferenaprticaaqui.Osmesmosprocessosexactos,apartirda
equivalentelocaltabeladoVisualFoxPro,produziuosseguintesresultados:

OpenViewepreencher=0,011segundos
ndiceVerPovoada =0,003segundos
Tempototal =0,014segundos

OpenViewendice =0,006seg
Preenchervistaindexada
=0,008seg
Tempototal =0,014segundos

Osresultadosaquimostramaindamenosdiferena.Usandotabelasmaiores,correndoatravsdeumaredeou
terumamquinacomhardwarediferenteeconfiguraoestotodosindoparainfluenciaroreal
cronometragem.Noentanto,emgeral,parecerazovelsuporquevocdeveconstruirndicesaps
avistafoipreenchida.Afinal,indexaodeumpontodevistasempreumafunopuramentelocal,que
nopodeserditoparaapopulaorealdavista.Nonossopequenoexemplo,claroque
recuperarosdadosdemoramaisdoquecriarosndices.Aousarvistaquesosubconjuntos
dedados,estegeralmentevaiserocaso,demodoqueomaisrpidoosdadosnecessriospodemserrecuperados,
omelhor.Aadiodendicesantesdepreencheravisoimpeumasobrecargasobreesteprocessoe
geralmentepodeserdeixadaatmaistarde.
Captulo9:Vistasemparticular,SQLemGeral 289

Maissobreousodepontosdevista
Asvistassoextremamentetil,sevocestconstruindoumaaplicaoqueestaserexecutadointeiramente
noVisualFoxPro,ouparaserescalvel,ouapenasparaserexecutadoemumafontededadosremota.
Noentanto,elesexigemumpoucomaispensamentoealgunscuidadosadicionaisemuso.estaseo
listaalgumascoisasadicionaisquetemosencontradoquandosetrabalhacomvistasemgeral.

Usandoumv alorpadroparaabrirumav istaparametrizada


Noinciodestecaptulo,dissemosquequandoseutilizaumavistacomparmetros,melhorparagarantirque
avistaabertocomqualquerumexplcita NODATAclusulaoudefinindoa NoDataOnLoad
propriedadepara .T.Noentanto,estaabordagemsignificaqueaaberturadeumavisorealmenterequerdois
consultasparaserenviadoparaafontededados.Aprimeiraconsultarecuperaaestruturadavista,eo
segundaconsultapreenchelo.Issoimprovvelquecausaratrasossignificativosquandosetrabalhacomum
vistalocal,mesmoemumarederelativamentelenta.Noentanto,assimquecomearapensarem
visualizaesremotas,outrofatorentraemjogo.Afimdemaximizarodesempenho,noofazemos
desejaenviarvriasconsultasparaobackend.Aquestocomopodemosevitarterde
recuperartodososdadosdisponveis(quepodeserumaenormequantidade!)etambmevitarotemido'Introduzaum
valorparaxxxdedilogo'quandoumformulriousandoumaexibioparametrizadoinicializado?
Naverdade,FoxProrequerapenasoparmetroemduasocasies.Emprimeirolugar,quandoumavista
abertopelaprimeiravezesegundosemprequeumpontodevistareconsultado.Emqualquermomento,o
parmetroirrelevante,porquevocjtemopontodevistapovoada.Portanto,nohnenhuma
precisaparafazeroparmetrodisponvelglobalmente,desdequeeleinicializadoemqualquer
mtodorealmentevaichamara REQUERY()funo.Asoluo,porconseguinte,paraexplicitamente
definirumparmetrovalorpadronasOpenTables()mtododeDataEnvironment.
Noentanto,issonotosimplescomopodeparecerprimeiravista.Oformulriodeexemplo,DefParam.SCX,em
ocdigoqueacompanhaestecaptulo,utilizaumavistacomparmetros(lv_cpybycity)e
inicializalopararecuperardadospara'London',incluindooseguintenosOpenTables()
mtododoDataEnvironment:

City_to_view="London"
DODEFAULT()
NODEFAULT

Notesequetantoo DoDefault()eo NoDefaultsonecessriosaquiporcausadamaneira


ainteraoentreoOpenTablesmtodoeseuassociadosBeforeOpenTablesevento
implementadoemVisualFoxPropareceumpoucoestranho,masfunciona!

Usandoumav istanov amente


Jmencionamosque,paratodososefeitosprticos,vocpodeconsiderarumaexibiocomoumatabela.
Issodevesignificarquevocpodeemitirum USE<nome>novamenteocomandoparaumavista,edefato
vocpodefazlo.Noentanto,humadiferenaentreareutilizandovistaseusandotabelasou
cursorescomo NOVAMENTEpalavrachave.Quandoumaexibiousado novamente,VisualFoxProcriaumponteiro
vistaoriginalemvezdecriarumcompletamentenovo,ou"desconectadocursor',porisso.o
consequnciaque,sevocalterarocontedodaexibiooriginal,ocontedodosuplente
alistambmmuda.Paraserhonesto,notemoscertezaseissoumacoisaboaouumacoisam,mas
dequalquerforma,nopareceserumalimitaoparaautilidadeda USE<vista>novamenteopo.

290 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Valeapenanotarque,apenasparavisualizaesremotas,htambmum NOREQUERYopoquepode
serusadocomo USE<vista>novamenteocomandoparaevitarVisualFoxProapartirderecarregamentodo
dadosparaavistaapartirdoservidorbackend.

Usandodatascomoparmetrosdev isualizao
Infelizmente,nomomentodaescrita,humerronoVisualFoxProVerso6.0(SP3),
associadoconfiguraode STRICTDATE,oqueafetaousodedatascomoparmetrospara
pontosdevista.Quandoumaconfiguraopara STRICTDATEdiferentede0especificado,nohnenhumamaneirasimples
umparmetrodedataatravsdodilogopadro.Onicoformatoqueseroaceitasa
paraintroduzir
inequvoca: 1999,01,01masemboraesteseraceitosemerro,eleaindanovaidar
oresultadocorretoquandoaconsultaexecutada.
Estamaisumarazoparanousaracaixadedilogopadroparareunirparmetrosparavistas.
Noentanto,asoluobastantesimplesapenasdefinir STRICTDATEa0antesdeabriroure
consultandoumaexibiousandoparmetrosdedataeavista,ento,aceitarparmetrosnaposionormal
Formatodedata.Ocdigodeexemploparaestecaptuloincluiumavistacomparmetros(lv_campanelist)
querequerumadata.Osseguintestrechosmostramoresultadodevriasformasdefornecero
parmetro:

SETSTRICTDATETO1
lv_campanelistUSE
***Digitenacaixadedilogo:{1999/12/12}
***Resultado:Errodesintaxe!
***Digitenacaixadedilogo:1999/12/12
***Resultado:Erro2032:AmbguoData/constanteDateTime
***Digitenacaixadedilogo:1999,12,12
***Resultado:Viewpreenchidocomtodososdados,independentementedovalor
entrou

SETSTRICTDATETO0
lv_campanelistUSE
***Digitenacaixadedilogo:12/12/99
***Resultado:Viewestcorretamentepreenchidocomdados

Claro,sevocestinicializandoosparmetrosnocdigo,nohnecessidadedealterar
STRICTDATEemtudo.Emboravocaindadevegarantirqueasdataspassadascomoparmetrosso
inequvoca,quefacilmentefeitousandoaDATE(aaaa,ddmm)funoouo{^AAAA
mmdd}formulrioparaespecificarovalor.

Criandov isesenv olv endomltiplastabelasdeconsulta(exemplo:LkUpQry.prg)


MencionamosanteriormentenestecaptuloqueoViewDesignertemalgumaslimitaesquandose
tratadeconstruirpontosdevista.Talvezamaisgravedelasqueodesignersempre
geraconsultasusandoo'aninhado'sintaxequesimplesmentenopodelidarcomconsultas
envolvendocertostiposderelacionamento.Issoclaramentevistoquandovoctentaconstruirumavisodeque
incluitabelasligadasmesmatabelaprincipal,masnorelacionadadirectamenteumaooutro.Tipicamente
taisligaessurgemnocontextodetabelasdeconsulta.Considereoseguinteesquema:

Captulo9:Vistasemparticular,SQLemGeral 291

Figura9.5VerParmetrodedilogo

Nesteprojeto,atabelapai(Cliente)temumatabelafilhonico(Endereo),queusado
paraarmazenarosvrioslocaisemqueumdeterminadoclienteexerceasuaactividade.cadaendereo
registrocontmduaschavesestrangeiras,almdequedeseupai,queapontamparatabelasdepesquisa
de'Regio'e'TipodeNegcio'.Claramente,nohumarelaodirectaentreestasduaspesquisas,
masfcilverporqueserianecessrioparasercapazdeincluirasdescriesrelevantes
umavistaquefornecedetalhesdeumcliente.
Figura9.6mostraomododeexibiodesignersetupparaacriaodeumavisodessastabelasutilizandoo
juntarseascondiesoferecidaspelodesignercomopadro.
Figura9.6Verdesignerparaumavisoenvolvendotabelasdepesquisa

292 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Issoproduzaseguinteconsulta:

SELECIONECustomer.cusname,Address.address,Address.city,
Bustype.busdesc,Region.regdesc
DECH09clienteINNERJOINCH09endereo!!
INNERJOINCH09BusType!
INNERJOINCH09regio!
ONRegion.regsid=Address.regkey
ONBustype.bussid=Address.buskey
ONCustomer.cussid=Address.cuskey
ORDERBYCustomer.cusname,Address.city

EstaprimeirajuntaEndereoparaoCliente,emseguida,juntaseotipodenegcioe,finalmenteregio.looks
bastanterazovel,no?Noentanto,osresultadosdaexecuodestaconsultaolharumpoucopeculiar
(Figura9.7):

Figura9.7Osresultadosdaconsulta

Comovocpodever,todososclientesso,aparentemente,namesmaregio.Piorainda,quando
tentarsalvarestepontodevista,umamensagemde"Erro1806"apareceafirmandoque:

"SQL:Colunaregkeynofoiencontrado"

Talvezprecisemosaschavesnoconjuntoderesultadosparafazerestetrabalho?Masno,adicionandooscamposchave
tambmnoajuda.TalvezprecisamosespecificarassociaesexternasemvezdeInnerjuntaseparao
tabeladepesquisa?Maisumavezarespostano.Finalmente,emdesespero,vamostentaradicionarastabelasemum
ordemdiferente.Primeiroadicioneoendereoeasduastabelasdepesquisa.Criaraconsultaeexecutlo.
Tudoparecemuitobem!Agoraadicionenatabeladeclienteseintegrlo.Reexecutaraconsultae
Agora,emvezdeapenasumaregio,temosapenasumcliente(eoerroquandotentarsalvar
avistaque"Colunacuskeynoforencontrado").
Oproblemaqueessetipodeconsultasimplesmentenopodeserresolvidoemumanicapassagemusandoo
"aninhado"sintaxegeradapelodesignervisual.Parafazerisso,precisamosconstruirdois
perguntaseporissoqueoViewDesignernopodefazerissoporns.
Asoluo'visual'aprimeiraauniratabeladeendereosparasuastabelasdepesquisa(incluindoo
chavedocliente)esalvaradefiniodavisoresultante.Emseguida,juntarseatabeladeclientescomestaviso.
(Lembresedeumavisopodeincluiroutrospontosdevistaemsuadefinio.)Ospontosdevistalv_AddLkupe
lv_CustAddressnocdigodeexemploparaestecaptulomostramosresultadosintermediriosefinais
estaabordagem(Figura9.8):
Captulo9:Vistasemparticular,SQLemGeral 293

Figura9.8Oresultadocorreto,finalmente!

Istolhedarosresultadoscorretose,emborasejaumaabordagembastanteprolixo,anica
maneiraqueseconhecepararesolvercorretamenteoproblemausandoodesignerdevista.claroqueo
soluofacilmentemanipuladosevoccriaradefiniodavistanocdigo.Vocpodeusaro
sintaxeSQLpadrocomosegue:

***PadroSintaxedeConsulta
SELECIONECU.cusname,AD.address,AD.city,BU.busdesc,RG.regdesc
DECUcliente,endereoAD,BusTypeBU,RGregio
ONDEAD.cuskey=CU.cussid
EBU.bussid=AD.buskey
ERG.regsid=AD.regkey
ORDERBYcusname,cidade

ou,sevocpreferirusaroformatoANSI92,vocpodeusar'sequencial'juntase,assim:
SELECIONECU.cusname,AD.address,AD.city,BU.busdesc,RG.regdesc
DECUclienteJunteendereoADONAD.cuskey=CU.cussid
CadastreBusTypeBUONBU.bussid=AD.buskey
CadastreRGregioONRG.regsid=AD.regkey
ORDERBYcusname,cidade

EssasconsultasestoincludasnaLkUpQry.prgnocdigodeexemplo,massevocquiserusaro
aninhadosintaxe,estamoscommedoquevocestnoseuprprio!Emborapossaserpossvel,emcertos
situaes,paraobterconsultasdestetipoatrabalharusandoasintaxesejuntaraninhada,novaleapenao
esforo(amenosquevocrealmentegostadepalavrascruzadas).Existemformasmaissimples,maisconfiveisde
lidarcomoproblema.Qualquerabordagemquevoctoma,vocprovavelmentevaiacabardecodificao,tais
vasimesmoaoinvsdeusaroViewDesigner.

Acriaodepontosdev istacomparmetrosquenecessitamdelistasdeparmetros
Outragrandelimitaododesignerdevistaqueelenopodecriarumavistacomparmetrosque
aceitarcorretamenteumalistadeparmetros.Naverdade,asituaoaindapior,porqueembora
vocpodecodificarumavisotoparametrizada,nopossvelespecificarosparmetrosatravsdodilogo
deumamaneiraquesignificativaparaomotorSQL.Anicasoluoquetemossidocapazesde
encontrar(atdata)ocdigoladoavistaeusarsubstituiodemacroparaoparmetro.oSQL
separececomisso:

294 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

CRIARSQLVISTAlvCityListAS
clicmpySELECT,clicity,cliphon
DEclientes
ONDEINLIST(clicity,&?CITY_LIST)

Quandovocabre( USE)aopiniodequeestecdigocria,ascoisasparecempromissoresopadro
dedilogoaparecepedindoumvalorpara'CITY_LIST'.Ento,insiraumalista,mascomo?Bem,aINLIST()
funoesperaqueosvaloresdevemserseparadosporvrgulas,ecadavalortemquesernacotao
marcas,assimquealgocomoissodevesermuitobem:
'London','Berlin','Stuttgart'

Clicandonoboto"OK"dacaixadedilogodepoisdeentraremnacadeia,imediatamentelevantaErro1231
("Faltandooperando").NaverdadeQUALQUERvalorquevocinserircausasdesteerroe(obviamente)a
fazconsultanopreencheravista.Noentanto,sevocespecificaramesmalistadevaloreseloja
losparaoparmetrodevistaemprimeirolugar,comoeste:

CITY_LIST="'London','Berlin','Stuttgart'"

avistavaifuncionarcomorequerido.Paraserperfeitamentehonesto,notemoscertezaporqueodilogo
nopodeserutilizadoparapreencheroparmetronestecenrio,masevidentequehumproblemacom
amaneiraemqueaentradaapartirdopadrodedilogointerpretadoquandooSQLexecutada.
Asoluo,sevocprecisardessafuncionalidade,simplesmenteparaevitaroViewDesignere
absterse(maisumavez)acaixadedilogopadroparaarecolhadeparmetrosparaaconsulta.

Umapalav rafinalsobreodesignerv ista


Vamosrepetiraadvertnciaquedeianteriormentesobrecomousarodesignerdevista.Sevocestiverusandovisualizaes
criounocdigo,nsrecomendamosfortementequevocnomelosdeformadiferentedaquelesque
criarnodesigner,afimdeevitarinadvertidamentemodificaressepontodevistavisual.Ese
voctentarefazlo,aschancessoquevocvaidestruirasuavisocompletamenteporqueo
designervaireescreveradefiniousandooaninhadosintaxe,que,comojtemos
visto,podenoseradequado.
Assimodesignerrealmentedealgumautilidade?Sim,claroque.Porumladomuitomaisfcil,
mesmoparaumavisoquevocsabequerealmenteterdecdigomo,parausarodesignerpara
recolherastabelasrelevantes,obteralistacamposelecionado,bsicocondiesdejuno,filtroseatualizao
critrio.Useodesignerparacriaravista,mascopiaroSQLqueproduzemseuprprio
arquivodeprogramaaomesmotempo.Emseguida,useGenDBC.prgparaobtertodoocdigosetupassociadopara
avistaeacrescentarqueparaoseuprogramadecriaotambm.Finalmente,editaroSQLrealpararemovero
aninhadojuntaseeregeraravista"corretamente."

SQLnoVisualFoxPro
Sevocestconstruindoaplicaesdebancodedadosoucomponentesdecamadaintermediria,ouestoprocuradeum
frontendparaumbancodedadosremoto,talvezarazomaisimportanteparausarVisualFoxPro
seumotorSQLintegrado.MuitasferramentaspodemusarSQL,maspoucostmacombinaodeumnativo
bancodedados,SQLEngineincorporadoeprogramaoGUIquefazcomqueVisualFoxProdemodo

Captulo9:Vistasemparticular,SQLemGeral 295

flexvelepoderosa.Nestaseo,vamoscobriralgumasdascoisasqueaprendemos
(Muitasvezesdamaneiramaisdifcil)sobreousodeSQL.Ocdigodeexemploparaestecaptuloincluiumaseparado
bancodedados(SQLSAMP.DBC)quecontmastabelasusadasnosexemplosparaestaseco.

Tabelasdejunta(ExemploExJoins.prg)
UmadasmudanasmaisbemvindosemVisualFoxProfoiaintroduo,noVisualFoxPro
5.0,deapoioaumconjuntocompletodejunta.Issoefetivamenteremovido,paraamaioriadosdesenvolvedores,o
necessidadedelutarcomobastantecomplicado(paranodizerfrancamentepersnickety) UNIO
comandoqueanteriormentetinhasidoanicamaneiradegerenciarqualquercoisadiferentedeumsimples'Inner
Juntese'.Vamos,portanto,comearanossadiscussosobreousodoSQLcomumabreverevisodosvrios
tiposdejunoqueestodisponveiseasintaxeparaimplementlasantesdepassarparaoutras
assuntos.
Tabela9.1(abaixo)listaosquatrotiposdeassociaoquepodemserespecificadoseminstruesSQLem
VisualFoxPro.Asintaxebsicaquedeveserutilizadaemtodososcasos:
Seleccione<campos>from<table1><CadastreTYPE><table2>ON<condio>

Onde <CadastreTYPE>podeserqualquerumdoslistadosnaprimeiracolunadatabela:

Tabela9.1SQLtiposdejunoemVisualFoxPro

JunteseTipo Incluinoconjuntoderesultados
Junointerna Apenasosregistroscujaschavescorresponderemambasastabelas
Esquerdaassociaoexterior
Todososregistrosdaprimeiratabela,maisregistroscorrespondentesapartirdosegundo
Junoexternadireita Combinandoosregistrosdaprimeiratabelaetodososregistrosapartirdosegundo
Junteseacompleta Todososregistrosdeambasastabelasindependentementedofactodeexistirquaisquerpartidas

OprogramaExJoins.prgexecutaamesmaconsultasimplescontraomesmopardemesasdequatro
vezes,usandoumadiferentecondiodejunodecadavez.OsresultadosreaissoapresentadosnaFigura9.9,
eonmerodelinhasretornadosporcadatipodeconsultaera:
CompletaJunte(cantosuperioresquerdo):
14linhas
INNERJOIN(cantoinferioresquerdo):
9linhas
Junoexternadireita(cantosuperiordireito):
10linhas
Junoexternaesquerda(cantoinferiordireito):13Fileiras

296 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura9.9Diferentesjuntaseproduzirresultadosdiferentesdosmesmosdados

Noteseque,comtodasascondies,exceptoaassociaointerior,existepelomenosumalinhaque
contmumvalorNULLem,pelomenos,umacoluna.Issoalgoqueprecisasercontabilizados
emcdigo(ouformas)quedependemdecadaOuterouFulljunta.Comojmencionado,
valoresnulossepropagamnoVisualFoxProepodecausarresultadosinesperadosseasua
ocorrncianotratadocorretamente.

ConstruodeconsultasSQL
EmborageralmentehpelomenosduasmaneirasdefazerascoisasemVisualFoxPro,nestecasono
sotrs!VocpodeusarasintaxeSQL'standard'queutilizauma ONDEclusulaparaespecificar
junesecondiesdefiltro,ouvocpodeusarasintaxemaisrecente"ANSI92",queimplementajunta
usandoo JUNTESE...ONclusulaeusaum ONDEclusulaparaespecificarfiltrosadicionais.OANSI92
sintaxetemduasmaneirasdeespecificarsejunta,ou"sequencial"ou"aninhados"ecadaumdelestem
suasvantagensedesvantagens.
AconsultaaseguirusaasintaxeSQLpadroparaexecutarumajunointernaemtrstabelas
ondeonomedoclientecomeacomaletra"D"eencomendaroresultado:
SELECIONECL.cliname,CO.consname,CO.confname,PH.phnnum,CO.conemail
DEsqlcliCL,sqlconCO,PHsqlpho
ONDECL.clisid=CO.clikey
ECO.consid=PH.conkey
ECL.cliname="D"
ORDERBYcliname,consname

Observequenohnenhumadistinoclaraentre"juntarse"econdies"filtro".o
consultaequivalenteusando"sequencialjuntarse"sintaxeumpoucomaisclarodesdeajuntaeasua
condiessoseparadosdacondiodofiltro:
Captulo9:Vistasemparticular,SQLemGeral 297

SELECIONECL.cliname,CO.consname,CO.confname,PH.phnnum,CO.conemail
DECLsqlcli
INNERJOINsqlconCOONCL.clisid=CO.clikey
INNERJOINPHsqlphoONCO.consid=PH.conkey
ONDECL.cliname="D"
ORDERBYcliname,consname

O"aninhadoformato"tornaaindamaisfcilparasepararajuntadesuascondies.isto
importantenotarquenestasintaxe,ajuntaeassuascondiessoprocessadasapartirde
foraparadentro.Assim,naconsultaaseguir,juntaroprimeiroaserprocessadoadicionaa'sqlcontabela'
utilizandoaltima' ON'condiooprximoaserprocessadoadiciona'sqlpho'usandoosegundoaoltimo' ON'
condio.Qualqueradicionaljuntairiaserprocessadosdamesmamaneira:

SELECIONECL.cliname,CO.consname,CO.confname,PH.phnnum,CO.conemail
DECLsqlcli
INNERJOINsqlconCO
INNERJOINsqlphoPH
ONCO.consid=PH.conkey
ONCL.clisid=CO.clikey
ONDECL.cliname="D"
ORDERBYcliname,consname

Lembresequetodosostrsdestasconsultasrealmenteproduzirosmesmosresultadosaescolhade
estilo,nestecaso,pelomenos,apenasumadeprefernciapessoal.Noentanto,enquantooestilopode
Noimporta,aordememquevocespecificarajuntadefinitivamentenoimporta,logoquevocusa
ouoaninhados,ousequencialjuntarformato.Alterandoaordememqueasjunesso
especificadopodealteraroresultado,eatmesmoimpediraconsultadecorreremtudo.(Invertera
seqncianasegundailustraoprovocaum'AliasCOnoforencontradoerro'porqueosqlcon'
tabelaaindanofoiunidaconsulta.)Asintaxepadrotemavantagemneste
respeito,porquetodasastabelasnecessriassoespecificadosemprimeirolugar.Aordememqueasuniesesto
noafetaoresultado,evocpodeatmesmomisturarjuntaefiltrossemafectaradversamentea
listados
resultado.
EnquantooestiloaninhadoutilizadoparageraroSQLproduzidopeloFoxProVer
edesignersdeconsulta,jvimosqueexistemalgunstiposderelaesque
nopodeserfacilmentemanipuladoporesteformato.Tantoquantosabemos,noexistemcondiesqueos
estiloaninhadopodelidarcomissooestilosequencialnopodeeisso,portanto,onossopreferido
estilo.
No,noentanto,umalimitaoaplicaodasintaxeANSI92emVisual
FoxPro.Eleestrestritoaummximodenoveassociaes.AgorapodeserapenascoincidnciaqueVisual
FoxProtambmtemumlimitedenove UNIOsemumnico SELECIONARcomunicado.Oupoderiaserqueamaneira
asintaxeefectivamenteaplicadofazendoumaunio'nosbastidores'?Dequalquermaneira,este
limitaonmeromximodetabelasquepodemserabordadosadez,masumalimitaoque,como
Atondepodemosdeterminar,seaplicasomentesevocusarasintaxebaseadaemparticipar.

Comoverificarosresultadosdeumaconsulta(ExemploChkQry.prg)
ComopodemosdizerseumaconsultaSQLtemrealmentedevolvidoalgumacoisa?Afinal,aconsulta
declaraoemsinogeraumvalorderetorno.Arespostaqueexistemvriasmaneirase

298 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Cadaumtemsuasvantagensedesvantagens.Qualdelesvocrealmenteusarvaidependerdotipo
deconsultaqueestsendoexecutadaeodestinoparaoqualasadadirecionada.
UsandoRECCOUNT()
Talvezacoisamaisbviaaverificaracontagemderegistrodatabeladesadaoucursor.
VisualFoxProtemumafunopadro,RECCOUNT('AliasName'),queretornaonmerode
registrosnoconjuntoderegistroespecificado,mesmosemterparaselecionarareadetrabalho(emborao
resultadonormaldeexecuodeumaconsultaSQLmudarasreasdetrabalhodequalquermaneira).Noentanto,esteno
guiainfalvelparaumcertonmeroderazes:
um
RECCOUNT()sempreretornaonmeroderegistrosfsicosemumatabela,cursorouexibio.
Emoutraspalavras,eleignoraaconfiguraodosinalizadorapagadoemumregistro.Onicomomentoemque
RECCOUNT()mudaquandoumnovoregistroadicionadotabelaouquandoatabela
embaladapararemoverregistrosexcludos.
Seoresultadodeumaconsultaumaexibiofiltradadosdadosoriginais, RECCOUNT()retornao
nmeroderegistrosnatabelasubjacente(oucursorouvista)quetenhasidoconsultados.
EsteproblemaparticularpodeserevitadaporforandoFoxProparacriarumasempre
cursorfsicaparaumaconsulta,incluindoo NOFILTERclusula.
RECCOUNT()obtmsuasinformaesapartirdocabealhodatabelaenofazrealmente
executarumacontagemdonmeroderegistrosnoconjuntoderesultados.Enquantoissopoucoprovvelqueseja
errado,nopodedarlheainformaoquevocprecisaemcadasituao.Para
exemplo,sevoctemregistrosquecontmapenas NULLvaloresesterealmenteumvlido
resultardeumaconsulta?
RECCOUNT()saplicvelseodestinodesadaparaaconsultaumcursorou
mesa.Sevocestivercriandoumamatrizqueintil.

usando_TALLY
Osegundomtodoparadeterminarseumaconsultavoltounadausarosistema
varivel _TALLY.Noentanto,emborasejacertamenteverdadeque _TALLYirdizerlhequantosregistros
foramdevolvidosporumaconsulta,importantelembrarque _TALLYtambmdefinidaporumnmerode
outroscomandos.Estamos,maisumavez,emdbitocomoincansvelTamarGranoreTedRoche,
eo'HackersGuide,"paradeterminaralistadefinitivadetaiscomandos:

AnexarDe Mdia Calcularembranco Copiarpara


Copiarparamatriz Contagem ExcluirExcluiSQL Exportar
ndice Pacote LembreseReindex Substituir
Substituirapartirdoarray SelectSQL Ordenar Soma UpdateSQL

_TALLYFazcomunicaronmerodelinhasretornadas,independentementedodestinodesada,
masdevemossalientarquesrealmenteconfivel,setestadoimediatamenteapsaconsultaSQLtem

Captulo9:Vistasemparticular,SQLemGeral 299

sidoexecutado.Baseandosequemantendooseuvalornoseguroeassim,sevocachaquevaiprecisarpara
sabermaistardequeumadeterminadaconsultaretornou,semprearmazenarovaloraumavarivelimediatamente.
Duasoutrasprecauessobreouso _TALLY.Emprimeirolugar,elesirdizerlheonmeroderegistros
queestqualificadoparainclusonoconjuntoderesultados.Issonosignificaquetodososregistroscontmvlido
valores.Emsegundolugar,sevocestiverexecutandoumaconsultaqueincluium COUNT(),lembresequetais
consultassemprevoltarpelomenosumregistromesmoquandooresultadozero.

UsandoSELECTCOUNT()
Estadefinitivamenteamaneiramaisconfiveldeobteronmeroderegistrosemumatabelaoucursor.
Almdisso,existemduasformasdistintasdecontagemdosregistos.Usando SELECTCOUNT(*),voc
obteronmeroderegistrosindependentementedeseucontedo(ouseja,eleidnticoao _TALLY)maspor
especificandoumcampoparticularparacontar,voclimitaoresultadoparaincluirapenasosregistrosonde
ocampoespecificadono NULL.
Noentanto,como RECCOUNT(),istospodeserusadoquandoumaconsultadirigeasuasadaparaum
cursorfsicaoumesa.Seoresultadoumaexibiofiltrada,anicamaneiradeusar SELECTCOUNT()
contraatabelasubjacenteeoresultado,portanto,intil.
Oprogramadeteste(ChkQry.prg)mostraoresultadodouso RECCOUNT(), _TALLYe SELECIONE
COUNT()emdiferentessituaes.Emprimeirolugar,paraumaconsultaqueenvolveumaassociaoexternaqueretorna
registroscom
alguns NULLvalores.Emsegundolugar,executandoamesmaconsultaduasvezesumavezquandoelecriaum
filtradavistaenovamenteparaproduzirumcursorfsico.

Tabela9.2RECCOUNT(),_TALLYeSELECTCOUNT()podemdiferir!
pergunta
OuterJoin13registros,4comvaloresnulos Reccount()
13 _tally
13 Contagem(*)
13 Contagem(<field>)
9
ConsultaproduzumFilteredView(2registros 9 2 9 9
Qualificar)
Repitaltimaconsultaparaumcursorfsica(2 2 2 2 2
Records)

ComoestenderumcursorSQLgerado
EnquantoSQLnormalmenteconsideradocomoproporcionandoummtodoparaextrairdadosapartirdeumj
tabelaouconjuntodetabelas,perfeitamentepossvelparamudaronome,ouatmesmocriarepreencher,colunas
existente
umcursorgerado.Omtodoparafazerissodependedoquevocquercomoresultado.o
secesqueseseguemilustramalgumasdastcnicasquepodemserutilizadaspararesolverproblemasdiferentes.

Definirnov ascolunas
Omtodopadroparaadefiniodeumanovacolunaparaincluirumvalorconstantedo
tipodedadosapropriadonaclusulacamposdeumainstruoSELECTeutilizaro'AS'palavrachavepara
definirumnomeparaacoluna.

300 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Nota:NaverdadeVisualFoxPronoexigeainclusodo'AS'
palavrachaveemtudo,nemamaioriadosservidoresdebackend.Naverdade,algunsmais
versesdeservidoresnosuportamapalavrachave'AS'emtudoeinclusive
velhos
loemumaconsultaenviadaparaumfimtovoltaprovocaumerro"invlidoNomedacoluna'.
Felizmente,opadroagorapareceserque,mesmoquandononecessria,incluindo
'AS'nocausarumerro.Nohdvidadequeelefazmelhoraralegibilidade
deumaconsultaeseuuso,sentimos,amplamentejustificadaporessemotivosozinho.

AnicapossvelGotcha!Aquiquequandovocespecificarasconstantesparaasnovascolunas
vocdevegarantirquevocdefinirvaloresgrandesosuficienteparaelesparaarmazenarosdados.Porexemplo,
definiodeumanovacolunadecaracterescomo" ESPAO(1)"vaifazerexatamenteissocriarumacolunadotipo
personagemcomumalarguradeumpersonagem.Damesmaformaumacolunadefinidacomo" 0.0"ircriarum
colunanumricocujadefinioN(3,1),enquantosimplesmenteespecificando" 0",emvezdecriar
umtipodedadosinteiro,criaumacolunanumricadasdimenses(1,0).claro,paraaquelesdados
tipos(moeda,data,DateTimeelgica),quesoprdefinidos,nohnenhumproblema.Umcheio
listadostiposdedadospadroesuasconstantesInicializaradequadosdadanaTabela9.3
abaixo.

Tabela9.3Constantesparainicializarnovascolunas

Tipodedados InicializarCom...
Requeridos
Personagem ESPAO(n)
Numrico Comomuitoszeros,conformenecessrio,incluiropontodecimal,senecessrio
Moeda OuUS$0ouNTOM(0)
Lgico .T.ou.F.comoapropriado
Encontro {}Ouumadata
Datahora {/:}OuDTOT({})ouumDateTime()
Outrostiposdedados Incondicionalmenteparticipardeumcursor(outabela)comocampoapenasexigido(s)eumanica
registroembranco

Adicionandoumtipodedadosnopadro
EnquantovocpodedefinirumvalorconstanteparatodosostiposdedadosbsicossuportadospeloVisualFoxPro,
nohvalores"constante"paraalgunsdosoutrostiposdedados(porexemplo,memorando,integer,float,
duplaetc).Amelhorsoluoquenssabemoscriarumcursorfictcioqueconsisteemum
campo(oucampos)dotipodesejadoetemumanicafichanela.Estecursorpode,emseguida,serunidas
soutrastabelasusadasemumaconsultaeoconjuntoderesultadosincluirumcampovaziodo
tipoapropriadocomoilustradoabaixoparacamposdememorandoeinteiro:

CRIARmemodummyCURSOR(memofieldM(4),intfieldI(4))
APPENDBLANKINmemodummy

SqlcliSELECT.*,MEMODUMMY.memofieldASCliNotes,MEMODUMMY.intfieldASCliint

DEsqlcli
CadastrememodummyON1=1
INTOCURSORCurMemTest

Captulo9:Vistasemparticular,SQLemGeral 301

Observeque,porqueestamosusandoo JUNTESE...ONsintaxe,devemosespecificarum ONcondio.Dentro


Nestecasodesejamoscadaregistronasadadefinidoparateroscamposextras,porisso,terespecificadoum
condiodequesempreavaliadacomo VERDADEIRO.(Porquenousar" =.T."?Emcasodeprecisarmos
comunicarcomumservidorbackendquenosuportacamposlgicos.QualquermotordeSQLvai
interpretar" onde1=1",como VERDADEIROe" onde0=1"como FALSE).UsandoasintaxeSQLpadro,
estetipodetrapaanecessrioeoSELECTequivalentesimplesmente:
nenhuma
SqlcliSELECT.*,MEMODUMMY.memofieldASCliNotes,MEMODUMMY.intfieldASCliint

DEsqlcli,memodummy
INTOCURSORmemtest

FazendoumSQLgeradoatualizv elcursor
SevocestadicionandocamposvaziosparaumcursorSQLgerado,provavelmenteporquevocquer
inseriralgunsvaloresparaeles.Noentanto,ocursorgeradocomoresultadodeumaconsultaSQL
sempresomenteleitura.Amaneiramaissimplesdefazertalatualizvelcursoraemissodeum DBFUSE(
'aliascursor')novamente.Masissosvaifuncionarenquantoocursornomeramenteumfiltrado
Diantedosdadossubjacentes.Adicionandoum NOFILTERclusulaparaumSQLgarantequeVisualFoxPro
devecriarumcursorfsicoparaoconjuntoderesultadosenoapenasgerarumaexibiofiltrada.o
exemploaseguircriaumcursoratualizvelquecontmambososcamposdatabeladeorigem
eumanovacoluna:

SELECIONEsqlcli*,espao(12)ASNewField.
DEsqlcli
INTOCURSORjunkNOFILTER

USODBF("lixo")novamenteIN0ALIASUpdCur
USOEMlixo
SELECIONARupdCur

Concatenandocamposdecaracteres(Exemplo:concat.prg)
Infelizmente,nohnenhumamaneirafcildeconcatenarcamposdecaracteresemumaconsultaSQL.Emrelatrios,
vocpodeusarvrgulasparacortarcamposqueprecisamserconcatenados(edoispontossemiparaadicionarlinha
breaks),masissonovaifuncionaremumaconsulta.OmaisprximoqueoVisualFoxProtemde"operador"
paraconcatenarduasstringsosinaldemenos("").Noentanto,issoapenasaparaespaosdireita
apartirdoprimeirocampoeanexatodoosegundocampo(nocortado)paraoresultado.Assim,dada
doiscamposdefinidoscomoCharacter(10),oresultadoseroseguinte:

F1=>"Fred "
F2=>"Smith "
(F1F2)=>"FredSmith "

quenoexatamenteoquenormalmenteiriaquerer.Anicaalternativarealistausar
funesdecorteexplcitasemtornodoscamposdeserconcatenadoseparaincluirqualquernecessria
pontuaoouespaosexplicitamenteno SELECIONAR.Assim,paragerarumcampodenomedeaspectonormal
apartirdosdoiscamposacimaseriaprecisofazerumdosseguintesprocedimentos:
302 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SELECIONAR(ALLTRIM(F1)+""+ALLTRIM(F2))ASFullName
SELECIONAR(ALLTRIM(F2)+","+ALLTRIM(F1))ASSortName

Nomuitoelegante,maseficaz.H,noentanto,umapegadinha!Espreitaaqui.Seum
doscampos NULL,oresultadoconcatenadotambm NULL.Nsestamosemumaperdaparaexplicaresta
comportamento.Afinal,tentandoconcatenarumcampodecaracterescomum NULLnormalmentelevantauma"dados
digiteerrodeincompatibilidade".Nopodemosverporqueasimplesinclusodeum ALLTRIM()devealteraresta
comportamento,maselefaz,eissopodesermuitocomplicadoparadepuraoquandoissoacontece.Osseguintes
programacriaumconjuntoderesultadosquedeveconterumastringformatadaqueconsisteemnomedaempresa
eumnomedecontato:

**********************************************************************
*Programa :ConCat.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:ilustraroproblemadeconcatenarcadeiasdecaracteres
* :QuandoumououtrocontmvaloresNULL
**********************************************************************

***Gerarumcursorquecontmvaloresnulosparaconsname
SELECIONECL.cliname,CO.consname
DECLsqlcli
LEFTOUTERJOINsqlconCO
ONCO.clikey=CL.clisid
ORDERBYcliname,consname
INTOCURSORlojoin

***Crieumasadaformatada
SELECIONAR(ALLTRIM(cliname)+"CONTATO:"+ALLTRIM(consname))
DElojoin
INTOCURSORformatadoNOFILTER

Oconjuntoderesultadosapartirdaprimeiraconsultaseparececomisso:

Figura9.10Intermediateconjuntoderesultados

Masasegundaparececomisso:

Captulo9:Vistasemparticular,SQLemGeral 303

Figura9.11finalconjuntoderesultadoscompletacomvaloresNULL

Observequeos NULLvaloresforampropagadasatravsparaoconjuntoderesultadosfinal!Estemais
outroexemplodequoimportantetornouse,noVisualFoxPro,paraestarcientedo
possibilidadede NULLvaloresqueaparecemcomoresultadodousodeassociaesexternas.Felizmente,asoluo
bastantesimples.Nssprecisamosdemodificarasegundaseleoparasubstituirumcaracterevazia
stringsequalquervalor NULL,eo NVL()funofazissoparans:

***Crieumasadaformatada
SELECIONAR(ALLTRIM(NVL(cliname,""))+"CONTATO:"
+ALLTRIM(NVL(consname,"")))
DElojoin
INTOCURSORformatadoNOFILTER

Estaversomodificadaser,pelomenos,garantirquevemostodososnomesdeempresas,oque
precisamenteporissousamosumaassociaoexternaesquerdaemprimeirolugar.

Execuodeclculos(exemplo:SQLCalc.prg)
Muitasvezesprecisamosparaexecutarclculosemdadosqueextramosusandoconsultas,entoaquesto
sabersemelhorfazeressesclculos,comopartedaconsultaouparapsprocesso
oconjuntoderesultadosefazerosclculosdefora.Nohumarespostaduraerpida,mas,seo
clculorelativamentesimples,eoconjuntodedadosaserprocessadonomuitogrande,asobrecarga
naconsultanodevesersignificativo.Oproblemacompsprocessamentodeumaconsultaquevoc
sernecessriofazeroconjuntoderesultadosdeleitura/gravao,deformaquehrealmentetrsetapasenvolvidasa
consulta,criandoocursordeleitura/gravaoeoprprioprocesso.Anicasoluorealexperimentlo
inicial
emambosossentidosemcadacasoeveroquefuncionamelhoremsuasituaoparticular.
Realizaodeclculosnaconsultanodifcil,masvocprecisaselembrardeuma
parderegrasbsicas.Emprimeirolugar,ocampoquevaiarmazenaroresultadodoclculodeveser
nomeadoeformatadosapropriadamente.Emsegundolugar,vocnopodesereferiraumcampocalculado,querem
listadecamposoucondiesdefiltro.Talrefernciairgerarumerro.Aseguir SELECIONAR
clusula,portanto,invlida:

304 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SELECTSUM(invamt)AStotalinv,
SUM(invpaid)AStotalpaid,
(Totalinvtotalpaid)ASinvbal

Condicionalmenteincluindocamposemumconj untoderesultados
OVisualFoxProimediataseafuno( IIF())podeserusadoemumaconsultaparacondicionalmente
extrairdadosapartirdequalquerumdosdoisdomniosnumnicocampo.Noentanto,humasobrecarga
associadaaesteeosignificadodequeasobrecargairdependerdanaturezado
condioeonmerodefichasaserprocessadoporqueotestevaiseraplicadoacada
registro.Talcomoacontececomosclculosdoespectculo,anicamaneiradesaberseissovaiserumproblema
paratestarexaustivamenteemvolumesrealistasdedados.
Asintaxeparausloexatamentecomoseriadeesperar.Aseguir SELECIONARrecebeo
ocontedodeumououtrodedoiscampos,dependendodovalordeumtero:

SELECIONARIIF(type="Residencial",ResidenceCode,BusinessCode)comotipo

Conv ertendocamposdeumtipodedadosparaoutro(Exemplo:SQLConv.prg)
Umrequisitomuitocomumadeextrairdadosapartirdeumbancodedadosemqualqueroutroformato,comogeralmente
textoparatransferirparaoutraaplicao.VisualFoxProsempreproporcionouumasriede
funesquepodemlidarcomaconversodevriostiposdedadosparaasuacadeiadecaracteres
equivalentes( STR(), DTOC()eassimpordiante).Estespodemserutilizadosempesquisasparaconverterosdadosa
Tipodeoriginalparaacadeiadecaracteresapropriado.
partirdasua
VisualFoxProVerso6.0adicionounovasfuncionalidadesparaafunoTRANSFORM()para
que,seusadoemumaexpresso, SEMespecificarquaisquercdigosdeformatao,umaconversopadrode
osdadosparaoseuequivalentecadeiarealizada.Issosimplificamuitoatarefadedadosconvertendo
emcadeiasdecaractereseumamudanabemvinda,defato.Paramaioresdetalhessobreestafunode
capacidades(elimitaes)consulteoarquivodeAjudaonline,masafuncionalidadebsicaparaacriaodeum
cursorquecontmapenasdadosdecaracteresdeumatabelaagorapodeserfornecidacommuitafacilidade,
segue:

***ExtratobrutodeInformaesdoCliente/Fatura
SelecioneTransformar(CL.cliname)AScliname,
TRANSFORM(IN.invdate)ASinvdate,
TRANSFORM(IN.invamt )ASinvamt,
TRANSFORM(IN.invpaid)comoformadepagamento,
TRANSFORM(invamtinvpaid)ASinvbal
DECLsqlcli
CadastresqlinvINONIN.clikey=CL.clisid
ORDERBYcliname
INTOCURSORcurNumeric
Observequeo TRANSFORM()temconvertidoosvaloresparainteiroseformatadoocampo
Tamanhosdeconformidade,oqueproduzumcursorcomaseguinteestrutura:

CLINAME Personagem 40
INVDATE Personagem 8
INVAMT Personagem 3
PAGAMENTO Personagem 3

Captulo9:Vistasemparticular,SQLemGeral 305

INVBAL Personagem 1

Infelizmente,ERRADO!EsteumcomumGotcha!Quepodemteenganarsemprequevoc
permitirqueVisualFoxProparadeterminarotamanhodeumcampoquecriadoemumconjuntoderesultados.Visual
FoxProsemprebaseiaocampodedimensionamentonoprimeirovalorquerecuperae,emseguida,despejatodosos
nomesmocamponestecaso,truncarosdadosparatornloapto.Portanto,temos,naverdade,osdadosperdidos
outrosdados
aqui,porqueaprimeirafaturaprocessadospassouaterumsaldode0,00,que,depoisdetersido
transformado,resultaemumnicocaractere"0",porsuavez,determinaralarguradagerado
coluna.Oprximoregistrodeveterumsaldode622,00,masagoramostrasecomo"6."
Damesmaforma,sequeramosparaconverterosdadosem,digamos,formatodemoedaquepodamossimplesmente
englobaruma NTOM()funoemtornodecadaexpresso.Masistoproduziriaumcursorcomo
seguinteestrutura:

CLINAME Personagem 40
INVDATE Personagem 8
INVAMT Personagem 7
PAGAMENTO Personagem 7
INVBAL Personagem 5

Destavez,ocampo"invbal"ficadimensionadopara5caracteresporqueesseocomprimentonecessriopara
armazenaroprimeirovalorquecalculado(agoraumvalordemoedatransformada"0.00")e,umavez
maisumavez,perderdadosemqualqueroutroregistroondeosaldoultrapassar"9,99."
Asoluobviaadeproporcionaraformataoapropriadosparaa TRANSFORM()
funomas,naverdade,emumSQL,consultaro PADL()funoamelhoropoporduasrazes.
Como TRANSFORM(),queirconverterqualquerumdostiposdedadospadroparaseusequivalentesdecaracteres.
Maisimportante,elepermitequevocdefinaotamanhodacadeiaresultanteeforaVisual
FoxProparaoseutamanhoemcolunageradaemconformidade.Ento,sensreescreveroSQLacimadaseguinte
forma:
***UsePADL()emvezdetransformarparaobterosresultados'certas'
SELECIONEPADL(CL.cliname,40)AScliname,
PADL(IN.invdate,10)ASinvdate,
PADL(IN.invamt, 10)ASinvamt,
PADL(IN.invpaid,10)comoformadepagamento,
PADL(invamtinvpaid,10)ASinvbal
DECLsqlcli
CadastresqlinvINONIN.clikey=CL.clisid
ORDERBYcliname
INTOCURSORcurCorrect

Nsobterumcursorcujaestruturaadequadaparaatarefaemmos:

CLINAME Personagem 40
INVDATE Personagem 10
INVAMT Personagem 10
PAGAMENTO Personagem 10
INVBAL Personagem 10
306 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Claro,existemmuitasoutrasmaneirasdeconverterdadosemumarquivodetexto.
Oqueeurealmentegosto(emborastilparaarquivosquesonecessrias
emformatoSDF)fazerusodonovoSTRTOFILE()funoem
conjuntocomoobjetodoaplicativoVFPDataToClipmtododaseguinteforma:

***Abraumatabela
USE<table>
***Copiarcontedoparaoclipboard
_CLIPTEXT=_VFP.DataToClip()
***Criarumarquivodetexto
STRTOFILE(_CLIPTEXT,'<arquivodesadaname>')

Comoverificaraotimizaodasuaconsulta(exemplo:SQLShow.prg)
OVisualFoxPro SYS(3054)funopermitequeoequivalentemaisprximoquetemosdeum
"Showplan"ferramentaparaverificaraotimizaodeumaconsulta.Enquantoeleumpoucolimitada(por
exemplo,asuanicaopodeexibiodiretoparaajaneladesadadecorrente),podeforneclocom
ummontedeinformaesmuitoteissobreaformaVisualFoxProvsuasconsultas.Omaisrpido
maneiradeobterasadadoSYS(3054)emumaformautilizvelusar SETALTERNATIVASecoartudo
sadadetelaparaumarquivodesuaescolha,comosegue:

SETALTERNATIVASPARAshowplan.txt
SETONALTERNATIVAS

Sevocestiverexecutandoumprograma,voctambmpodesuprimirasadanatelausando SET
CONSOLEOFF(masissonotemnenhumefeitosevocestapenasexecutandoocdigodajaneladecomando).
Quandoterminar,cancelaroecodasadausando:

SETOFFALTERNATIVAS
ALTERNATIVASPARASET

O SYS(3054)funotemdoisnveisdeexibiodedeterminadospeloparmetropassado
achamadadefuno.Oprimeironvel(parmetro=1)mostraautilizaodendicesemtabelase
indicaoOptimizationRushmoreparacadatabelaenvolvidanaconsultacomoNenhuma,
Parcialoutotal.Oprogramaaseguir(SQLShow.prg)mostracomofunciona:

**********************************************************************
*Programa :SQLShow.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:IlustrarousodeVFPShowPlanrelatando

***Habilitarorelatriodeplanodeexecuo
SYS(3054,1) &&Realmenteretorna"1"indicandoNvel1relatoesthabilitado

***TelaDesativaresadadiretaparaoarquivo
SETCONSOLEOFF
SETALTERNATIVASPARAshowplan.txt
SETONALTERNATIVAS
***PrecisamosexcludoONparaverosresultados

Captulo9:Vistasemparticular,SQLemGeral 307

lcOldDel=SET('excludos')
SETDELETEDON

***Executaraconsulta
SELECIONECL.cliname,CO.consname
DECLsqlcli
CadastresqlconCOONCO.clikey=CL.clisid
ORDERBYcliname,consname
INTOCURSORijoin

***Restaurarconfiguraes
SETCONSOLEON
SETOFFALTERNATIVAS
ALTERNATIVASPARASET
SETDELETED&lcOldDel
***Desliguerelatriosshowplan
SYS(3054,0)

Issoproduzaseguintesada(noformatado)emshowplan.txt:

UsandoondicedetagIsdelparaRushmoreclOPTIMIZETABLE
nveldeotimizaoRushmoredecltabela:full

UsandoondicedetagIsdelparaRushmoreOPTIMIZETABLEco
nveldeotimizaoRushmoreparaatabelaco:full

Osegundonvel(parmetro=11)mostratantoautilizaodendiceparaatabelaetambm
paraqualquerjuntaenvolvidanaconsulta.Usandoestaopo,aconsultaacimaproduzaseguinte
sada:
UsandoondicedetagIsdelparaRushmoreclOPTIMIZETABLE
nveldeotimizaoRushmoredecltabela:full

UsandoondicedetagIsdelparaRushmoreOPTIMIZETABLEco
nveldeotimizaoRushmoreparaatabelaco:full

Juntandocldemesaecotabelausandondicetagclikey

Issonosdizquetemosumaconsulta"totalmenteotimizado".Ambasastabelastmumndiceem
DELETED()eestamoscorrendocom DELETED=ON(vejaaprximaseoparaobtermaisdetalhessobre
opapelda DELETED),paraqueastabelasindividuaissoambosotimizvelRushmore.Almdisso,h
umndiceexistentenocampoutilizadanacondiodejuno.Noentanto,setivssemosdeadicionarumfiltro
condioparaaconsulta(porexemplo: ONDEconsname="a"eCONFNAME="B"),a
resultadosseriaagoraparecidocomeste:

UsandoondicedetagIsdelparaRushmoreclOPTIMIZETABLE
nveldeotimizaoRushmorede cldemesa:completo

UsandoondicedetagConsnameparaRushmoreOPTIMIZETABLEco
UsandoondicedetagIsdelparaRushmoreOPTIMIZETABLEco
nveldeotimizaoRushmorede mesaco:parcial

JuntandocomesaecldemesausandoondicedetagCLISID

308 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Observequeatabela'co'estagoraapenasparcialmenteotimizado,porque,emborahajauma
ndiceem'consname'quepodeserusadoparaaprimeirapartedacondiodofiltro,noh
ndicecorrespondentequepodeserutilizadoparaosegundo.
Ascoisasficamumpoucomaiscomplexoquandomaisdeduastabelasestoenvolvidos,masa
informaoaindamuitorevelador.Considereaseguinteconsulta(osresultadosreaisnoimportam
paraagora):

SELECIONECL.cliname,CO.consname,PH.phnnum,SI.Invdate
DECLsqlcli
CadastresqlconCOONCO.clikey=CL.clisid
CadastrePHsqlphoONPH.conkey=CO.consid
CadastresqlinvSIONSI.clikey=CL.clisid
ORDERBYcliname,consname
INTOCURSORijoin

Quandoesteexecutado,showplannosdoseguinterelatrio:

UsandoondicedetagIsdelparaRushmoreclOPTIMIZETABLE
nveldeotimizaoRushmoredecltabela:full

UsandoondicedetagIsdelparaRushmoreOPTIMIZETABLEco
nveldeotimizaoRushmoreparaatabelaco:full

UsandoondicedetagIsdelparaRushmorephOPTIMIZETABLE
nveldeotimizaoRushmoredephdemesa:completo

UsandoondicedetagIsdelparaRushmoresiOPTIMIZETABLE
nveldeotimizaoRushmoreparasimesa:completo

JuntandocldemesaemesadesiusandondicetagClikey
JuntandoresultadointermedirioemesadecousandoondicedetagClikey
JuntandoresultadointermedirioephtabelausandondicetagConkey

Asprimeiraslinhassosemelhantesaoquetemossidojvisto,masajuno
informaesquesorealmenteinteressado.PodemosveragoraasequnciaqueVisualFoxPro
realmenteusandoparaunirastabelas.Nestecaso,eleprimeirosejunta'SI'(facturas)para'CL'(clientes)e
emseguida,adiciona'CO'(contatos)efinalmente"PH(nmerosdetelefone)'.Normalmente,vocpodepermitircom
segurana
VisualFoxProparadeterminaramelhorformadeunirastabelas,masapenasocasionalmenteelevaiobtlo
errado(ou,pelomenos,juntlosdeumamaneiraquenolhedosresultadosquevocqueria).em
Nestassituaes,podemosusarapalavrachaveadicional"fora"naclusulaFROMparagarantir
queVisualFoxProexecutaaconsultaexatamentecomonsdefinimos.Porexemplo,quealteraa
exemplodeconsultaparaforarasequnciadejuntarse:

SELECIONECL.cliname,CO.consname,PH.phnnum,SI.Invdate
DEFORAsqlcliCL
CadastresqlconCOONCO.clikey=CL.clisid
CadastrePHsqlphoONPH.conkey=CO.consid
CadastresqlinvSIONSI.clikey=CL.clisid
ORDERBYcliname,consname
INTOCURSORijoin

Captulo9:Vistasemparticular,SQLemGeral 309

produzosseguintesresultadosdeshowplan,econfirmaqueVisualFoxProtem
fatofeitooquefoisolicitado:

UsandoondicedetagIsdelparaRushmoreclOPTIMIZETABLE
nveldeotimizaoRushmoredecltabela:full
UsandoondicedetagIsdelparaRushmoreOPTIMIZETABLEco
nveldeotimizaoRushmoreparaatabelaco:full
JuntandocldemesaecotabelausandondicetagClikey

nveldeotimizaoRushmorederesultadointermedirio:nenhum
UsandoondicedetagIsdelparaRushmorephOPTIMIZETABLE
nveldeotimizaoRushmoredephdemesa:completo
JuntandoresultadointermedirioephtabelausandondicetagConkey

nveldeotimizaoRushmorederesultadointermedirio:nenhum
UsandoondicedetagIsdelparaRushmoresiOPTIMIZETABLE
nveldeotimizaoRushmoreparasimesa:completo
JuntandoresultadointermedirioeSItabelausandondicetagClikey

Ento,quandodevemosrealmenteusarshowplan?Arespostasuperficial,claro,sempre!
Noentanto,naprtica,deveseraprimeiracoisaquevocverifiqueemduassituaes:
Quandovocencontrarseperguntandoporqueumaconsultaestlevandomaistempodoqueoesperado
Quandoumaconsultaretornaresultadosinesperados

OefeitodaDELETED()noSQL
EstetalvezumdosaspectosmenoscompreendidosdemotordeSQLdoVisualFoxPro.Enquantoo
detalhesdamaneiraemqueaotimizaoRushmorerealmentefuncionaaindasoumbemguardado
segredo,ofactoessencialqueRushmoredependedendices,afimdeaceleraraselecode
dados.Ofatormaisimportanteaformacomoelelidacomregistrosmarcadosparaexcluso.
QuandovocexecutarVisualFoxProcomoconjuntodeexcludospara ON,vocestdizendoaeleparaignorar
queestmarcadoparaexcluso,mascomoparadescobrirquaisregistrossomarcadosparaexcluso?
qualquerregistro
Arespostaque,amenosquetenhaumndicequeincluiespecificamenteaessesregistros,temque
verificarcadaregistroindividualmesmosevocnotemregistrosmarcadosparaexcluso.
Estaumaoperaorelativamentelentoeprovavelmenteacausamaiscomumdepobres
desempenhoSQLemaplicaes.Asoluosimples,incluemumndiceespecficona
DELETED().
Correndocomapagadodefinir OFFevitaanecessidadedeumndiceem DELETED(),massignificaque
vocpodeterqueincluirexplicitamenteumfiltroadicionalemsuasconsultas(ouseja, onde!
DELETED())seassuastabelaspodemconterregistrosexcludos.Noentanto,istoirresultaremapenas
otimizao"parcial"desuasconsultasepodedarlheumdesempenhopiordoqueusandoum
ndiceem DELETED()edefinir DELETED=ON,mesmoquevocnuncatemqualquerexcludo
registros.
Noentanto,acriaodeumndiceem DELETED()no,emsi,apanaceiauniversalespecialmente
quandograndesmesasestoenvolvidos.Istoporquesemprequevocacessarumatabela,(quercomum
explcitacomandoUSE,ouatravsdeumaconsulta)VisualFoxProprocura,ecarreganamemria,
ondiceem DELETED().Sevocestiverexecutandoemumaredeissopodeserumlongotrabalhoparamuitogrande
310 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

tabelase,emtaiscircunstncias,geralmentemelhornoterumndiceem DELETED().
Infelizmente,noexistemregrasrgidaserpidassobreisso,eonicoconselhorealquepodeoferecer
tentarascoisasemseuprprioambienteparadeterminaramelhorcombinaodendices
eafixaode DELETED.

Ento,oquendicesdev ocriar?
Infelizmente,noexistemrespostas"fcil"aestapergunta.Comovocvaiterpercebidoapartirda
secesanteriores,opapeldosndicesemtabelascrucialquandoestamosconsiderandoSQLem
VisualFoxPro.Emborasejaimpossveldeserabsolutamenteprescritivosobreesta,halguns
diretrizesbsicas,masestarpreparadoparaalterlascomoresultadodetestarascoisascomseuprprio
dadosemseuprprioambienteoperacional.
Aprimeiraquevocdevesemprecriarumndicenocampodechaveprimriadoseu
mesasmesmoqueissonodefinidocomouma"chaveprimria"emseubancodedados.Sevocaindanoestiver
usandochavessubstitutas(eporqueno?),vocaindadevecriarumndiceemqualquercampo,ou
combinaesdecampos,identificarexclusivamenteumregistro.Senadamaisvocvaiprecisardeste,afimde
sercapazdesejuntarmesacomeficinciaemconsultas.
Emsegundolugar,consideraracriaodeumndiceem DELETED().Enquantoisso,semdvida,acelerar
consultasquandovocexecutarVisualFoxProcom DELETED=ON,podeterumimpactoindesejvelsobre
desempenhoemoutrasreas(porexemplo,formulriosdecarregamento),especialmentesesuastabelassomuitograndes.
sempre,testaremseuprprioambiente.
Como
Emterceirolugar,criarndicesparatodososcamposemquenormalmentevocvaiestarpesquisascondutores,
ouacriaodefiltros.IssopermitirqueRushmoreparaotimizartantojunesdetabelaecondiesdefiltro
corretamenteeirmelhorarmuitoodesempenhodesuasconsultas.Lembresequeondice
expressodevecorresponderexatamenteoquevocvaiusarnaespecificaodepesquisaoufiltro
condio.Ento,sevocestiveradicionandoumndiceem'sobrenome',massernormalmentefiltragempara
" UPPER(sobrenome),"emseguida,criarondiceem" UPPER(sobrenome)"tambm.

Apresenadendicescujaschavesnosodefinidasexatamenteno
mesmostermosquesousadosa oconsultarastabelasprovavelmenteo
segundacausamaiscomumdemaudesempenhoemSQL,masum
quefacilmenteapanhadaporusandoshowplan.Vocsaberquevoctemcadofalta
destequandovocvumresultadoquemostraotimizaoparcialparaumaconsultaquedeve
voltarotimizaocompleta,porquevocsabequenoumndicenocampo
questo.

Emquartolugar,evitaracriaodendicescondicionais(ouseja,aquelesqueusam' FOR<condio>')ou
ndicesbaseadosnadesigualdade(ouseja,aquelesqueutilizamum' NO<condio>').Rushmorenopodeusar
ndicesdequalquertipoesimplesmenteignoralos.Sevocprecisardelesporoutrasrazes,emseguida,criar
tantoondicerequeridoeumsimplesndicenocampo.(Istotambmfacilmentedetectadausando
showplan.)
Finalmente,eviteinvertendosuastabelas.Suareaoinicialaestaperguntapodeserqueela
seriamaisseguroparasimplesmentecriarumndiceemtodososcamposnatabelaafinalnuncasesabe
oquevocpodequererprocuraremvoc?Esta,noentanto,geralmenteummovimentomau,especialmentenas
tabelasquetmaltosnveisdeatividade(querinseres,atualizaesouexcluses),porquevoc
estoforandoVisualFoxProparamanterumgrandenmerodendicescomqualquertransacono

Captulo9:Vistasemparticular,SQLemGeral 311

mesa.Issopodeafetarsignificativamenteodesempenhoe,comosempre,humtradeoffentre
desempenhoemumareaedesempenhoemoutro.

Qualmelhorparaatualizartabelas,SQLouFoxPronativos
Estaumaquestocomplexaearespostadependedotipodeatualizaoedanaturezado
comandos?
mesa.Amelhorsoluotambmvaria,dependendosevocestadicionandonovosregistrosou
atualizaodedadosexistentes.

SQLINSERTv sAPPEND
Deummodogeral SQLINSERTdarummelhordesempenhoporquerequerapenasumanica
actualizaodequalquerndiceassociadocomatabela.Aoadicionarregistrosaumatabela,VisualFoxPro
temqueatualizarocabealhodatabelaeatualizarosndicescomosnovosvalorescombasenoquefoi
adicionado.Usando INSERIRmaiseficienteporquerequerapenasumaoperao.Onovorecorde
eosseusvaloressoadicionadosemsimultneoeosndicesactualizado.
Noentanto,afimdealcanaresteobjectivonecessriotertodaainformaodisponvelquandooinserto
realizadaeistonemsemprepossvel(porexemplo,aoadicionarregistosembrancoatravsdeumconjuntodedados
formulriodeinscrio).Nestasituao,especialmentesemesassotamponados,fazpoucadiferenaprtica
comovocrealmenteadicionaroregistro.

SQLupdate/deletev sSUBSTITUIR/DELETE
Arespostaaquidependedequantosregistrosprecisamseratualizados.Paraatualizaesderegistroindividuais,
especialmenteondeoregistrojestselecionadoeimediatamentedisponvel,quetenderiaa
ficarcomas substituir/APAGARcomandos.Naverdade,mesmoquandooregistronecessriono
imediatamentedisponveis,geralmentemelhorusarum SEEKe REPLACE/DELETEestratgiavez
doqueoequivalenteSQL.ArazosimplesmentequeoscomandosSQLrequeremuma ONDEclusula
edeveprocuraratabelainteira(ou,pelomenos,osndices)paragarantirquenohmaisdoque
umregistroqueestsendoespecificado.PoroutroladooescopopadroparaonativoVisualFoxPro
comandossempreoregistroatual(ouseja, prximo1)eassim,paraatualizaesderegistroindividuaisou
delees,geralmentemaisrpida.
Quandotemosqueatualizarvriosregistros,asituaodiferente.Ambos REPLACEe
APAGARpodetomarumescopocondicional(ouseja, PARA<condio>).Issooscolocanamesma
categoriaqueoscomandosSQLcomoseu ONDEclusulaeasmesmasregrasseaplicam.
Desdequeacondiootimizvel,VisualFoxProusarRushmore,tanto
situaeseadiferenaserinsignificante.Noentanto,quandoacondiono
otimizvel,oscomandosSQLnormalmenteirdarumdesempenhoumpoucomelhor.Aresposta,
comosempre,paratestarcasosindividuaisedecidirsobreosseusmritos.

Concluso
TodaaquestodautilizaodeSQLnoVisualFoxPro,querdirectamente,queremvista,dependente
apstantosfatoresquemuitodifcildeserprescritivosobrequalqueraspectodomesmo.o
regradeouroparaplanejarsuasestruturasdetabelasendicescorretamenteetestar,testarereteste
suassoluesemtantasmaneirasdiferentesquantopossvel.Use SYS(3054)paraconfirmarqueoquevoc
esperaroquerealmenteestacontecendo,eestarpreparadoparaalgumassurpresasquandovocfaz.

312 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo10:ClassesNonVisual 313

Captulo10
Classesnovisuais
"Prazeremterentendidoumsistemamuitoabstrataeobscuralevaamaioriadaspessoasa
acreditamnaverdadedoqueeledemonstra."(Aforismos"NotebookJ"porGCLichtenberg)

AcapacidadededefinirnossasprpriasclassesnoVisualFoxProumdosmaispoderosos
caractersticasdalinguagem.Elanospermitecriarferramentasquepodemserreutilizadosemumaampla
decircunstnciase,porqueelessocriadoscomoclasses,tambmnospermiteampliarou
variedade
modificarseuscomportamentospadroquandoosrequisitosmudamemaplicaesespecficas.
Quetambmpodemoscriarclassesnocdigoabreumnovomundodepossibilidadespara
desenvolverabordagenspadroparaproblemascomuns.Nestecaptulo,exploraralguns
dasclassesnovisuaisquetemosdesenvolvidoparatornarnossavidamaisfcilquando
escreveraplicativosdoVisualFoxPro.Emboranosejaprojetadoespecificamentecomoo"quadro"
classes,muitasdasfuncionalidadesdescritasnestasclassesquenormalmentecaemna
mbitodeumaestruturadeaplicativo.

ComopossofazerusodearquivosINI?(Exemplo:INIMAINT.SCX)
EmborahajaumatendnciacrescenteparausaroRegistrodoWindowsparaarmazenardadosque
refereseaumaplicativo,omaisvelhoINIarquivoaindaoferecevriasvantagensparaaaplicao
desenvolvedor.Primeiro,simplesmenteumarquivodetextoquepodemserarmazenadoslocalmenteemumamquina
informaesespecficasdousurio.Estaumavantagemimportante,porquetornamaisfcildemanipular
clienteparasegurar
sevocfazlopormeiodeprogramaooucomqualquereditordetextodisponvel.Emsegundolugar,porquepode
estarlocalizadonodiretriohomedeumaplicativo,fcilderemover,seaaplicaotemdeser
removidoapartirdeumamquina,efcildesubstituiremcasodeque,inadvertidamente,excludo.Terceiro,
possvelinstruirmesmoumusurioinicianteemcomocorrigiroserroseacrescentarnovositensemumarquivoINI
senecessrioatmesmoportelefone,senecessrio.
Enquantooregistroforneceumbomlarparainformaesquenecessrio'widesistemade'
porqueeleestdisponvelautomaticamenteparaosaplicativosdoWindows,nonemdesenvolvedor,nempelousurio
amigveis.complicado,paranodizerperigoso,manipularprogramaticamenteedesinstalaodeum
aplicaocompletamentemuitomaisdifcilquandoasentradastmdeserlocalizado,eexcludos
de,noregistro.Almdisso,nsseriamuitonervososobreadoaodeumusurioexperiente
(Emuitomenosumnovato)oacessoaoregistrodesuamquinaeaperspectivadetreinarumusurio,por
telefone,editaroregistroaqueleque,francamente,nsachamosterrvel!Finalmente,seo
informaosejaarmazenadapuramenteaplicaoespecfica,eacessadopornada,excetoo
aplicao,podemosvernenhumarazoparanoarmazenlocomoaplicativo.

Visogeral
OINIGestordeficheirosumaclassequeprojetadoparafornecerumtratamentocontnuode.iniarquivos(ou
qualqueroutroarquivobaseadoemtextoquerespeiteoINIformatodearquivo).UmINIarquivoumarquivodetexto
("STF"),queconsistedeumasriedeTtulosdeSees(devehaversemprepelomenosumdos
estruturado
estes)delimitadocom"[]"e,emseguida,itemeovalorparesqueincluemum"=".Todososdadosso
314 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

realizadacomosequnciasdecaracteresnoINIarquivose,emborahajaumalimitaode64Knotamanhodeum
INIarquivo,amaioriadosaplicativosnososusceptveisdechegarpertodisso.Umarquivotpicopodeolhar
algocomo:

Nome:SYSTEM.INI

[SISTEMA]
Name=SOMESYSTEM
COPYRIGHT=TightlineComputersLtd

[CONSTANTS]
STANDARDRATE=17.50
CONCESSIONRATE=15,00
=8,50UTILITYRATE

OobjetivofundamentaldeumINIarquivofornecerummeiodearmazenarinformaonecessriaparauma
aplicaosemterquerecorreraousodeumatabeladedados.UmavezqueumINIarquivoumarquivodetextosimples,
informaesnelecontidaspodemseratualizadosoualteradosporumusuriofinalusandoqualquereditordetexto.
OWindowsforneceumnmerodefunesAPIquepodeacessaregravarINIarquivos,mas
comotodasessasfunes,elessorelativamentecomplexos.Ogerenteumexemplodeum"Wrapper
Classe",quefornecefunesbsicasdegestoparaINIarquivos,almdeoferecerumaformamais
interfaceamigveldesenvolvedorparaestasfunesdaAPI.
OINIgerenciadordearquivosexpeseismtodosemsuainterfacepblica,quesodescritosem
detalheabaixo.Foiconcebidoparaserinstanciadacomoumobjectodenveldesistemaemborapossaser
criadocomoumobjetotransiente,senecessrio,oucomoumcomponentedeum"objectodeaplicao".Quase
todasasfuncionalidadesdoINIFileManagerinterno,asexcepessodequeelerequeralgum
funesdoVisualFoxProque,antesdaVerso6.0sestavamdisponveisnasFoxTools
biblioteca.SeestaclasseparaserusadocomumaversoanteriordeFoxPro,umamodificaovai
sernecessriaparaa"ChkFileName()mtodo"paracarregarabibliotecaseelejnoestpresenteno
memria.

Inicializarogerente
Existemduasmaneirasdecriaroobjetogerente.Vocpodecarregaradefiniodeclassecomoum
arquivodeprocedimento(oqueseriaamelhorabordagemseogestorestasercriadocomoumtransiente
Object),ouvocpodeexecutaroprogramadiretamenteecriarogerentecomoumobjetoglobal.(Este
ircriararefernciaaogerentecomoumavarivelpblica,masnocarregaroarquivono
memriacomoumprocedimento).
Independentementedaformacomoutilizado,oprocessodeinicializaolevaumparmetroopcionalquea
nomedoINIarquivoparaserusadocomooarquivopadropelogerente.Processosdeverificaointerna
formataressenomeemumnomedearquivototalmentequalificadocomaextensodefault"INI"eo
caminhopadrodaunidadeepastaatuais.Noentanto,caminhosespecficosououtrasextensessero
serrespeitado,sefornecido.

Captulo10:ClassesNonVisual 315
Tabela10.1CriandooobjetogerenciadordearquivosINI

CriandooManagercomoumobjetoglobal CriandooManagercomoumtransiente
objeto
LIBERTAOgoIniMgr FAZERCOMiniproc<inifile>
goIniMgrPBLICO LIBERTAOgoIniMgr
PROCEDIMENTOPARAiniprocaditivoconstante
GoIniMgr=CREATEOBJECT('iniproc',<inifile>)

Seoarquivopassadocomooarquivopadronopodeserlocalizadonocaminhoespecificadoouno
caminhopadro,elasercriadacomumanicaseoquetemomesmonomecomooarquivo.Assim,o
comandodeconfigurao:

goIniMgr=CREATEOBJECT('inimgr','c:\teste\nosuch.txt')

resultar(dadoaspermissesadequadasedireitosdecriaodearquivo)nacriaodeum
arquivochamado"NOSUCH.TXT"no"C:\TESTE"diretrioquecontmsimplesmenteaseco
header"[NoSuch]",porque,comofoiobservadonaintroduo,umaINIarquivosemprerequerpelomenos
umaseodecabealho.

AopoNoCreate
Aclassepodeaceitarumasegundalgica,parmetro,queusadoparadeterminarseumnovoINI
arquivodevesercriadoseumarquivoespecificadonofoiencontrado.Ocenrio,inicializadanoarranque,realizada
emumapropriedadeprotegidaequandoexplicitamentedefinidocomo .T.,impedequeoINIFileManager
tentarcriarumarquivoquandooarquivosolicitadonofoiencontrado.Assim:

goIniMgr=CREATEOBJECT('inimgr','c:\teste\nosuch.txt',.T.)

aindavaiinstanciaroobjetogerenteedefinirapropriedadedearquivopadro,maseleno
criaroarquivosolicitadoseeleaindanoexistir.

Oarquivopadro
OINIManagermantmumacoleointernadenomesdearquivoreconhecidasporeleetambm
mantmumdessesarquivosregistradoscomooarquivopadro.Quandoqualquermtododeleituraougravao
dadosserolidosougravadosparaoarquivopadro,amenosqueumarquivoespecficotransmitidocomopartedo
chamado,
instruo.Afinalidadedoarquivopadrosimplesmenteparaevitaranecessidadedeterquemanter
passandoevalidaronomedomesmoarquivoINIarquivoumavezque,normalmente,asaplicaesirousar
apenasumnicoINIarquivo.
Noentanto,oINIManagertemacapacidadeparaconsultarumarquivoespecficosemrealmente
alterandoaconfiguraopadro(porexemplo,paralerumvalorespecficoapartirdeumSistemadeINIouSTF
arquivo)eparaalterarqualquerarquivoregistradocomopadroaqualquermomento.

316 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

registrodearquivo
OINIManagerutilizaumprocedimentoderegistointernoparagarantirquetodososnomesdearquivopassadopara
quesejamdevidamentequalificadoscomocaminhocompletoeextenso.Senenhumcaminhopassado,otrabalhoatual
unidadeediretriosoassumidos,esenenhumaextensoestincludooarquivosupostoparaterum
' Iniextenso'.Emboraospadressodesignadosparasubstituirositensemfaltadedados,oINI
gerentevairespeitarqualquerinformaocaminhoouextensoquepassadoparaele.

Ainterfacepblica
OINIinterfacepblicaManagerextremamentesimples.Existemapenasseismtodosquepodemser
acessadoseogerentetempropriedadesnoexpostosemtudo.Osmtodosindividuais,e
exemplosdecomoelespodemserutilizados,sodiscutidosnassecesseguintes.

GetIniFile()
OGetIniFile()mtodolevasemparmetrosesimplesmenteretornaonomedequalquerarquivodo
INIManagerestactualmenteadefinircomooarquivopadro.Senenhumarquivoforregistrado,GetIniFile()retorna
umacadeiadecaracteresvazia.

Exemplos:
Estemtodopodeserchamadocomopartedeumtesteparagarantirqueumarquivoregistrado:
IFEMPTY(goIniMgr.GetIniFile())
***NoINIarquivodefinido
FIMSE

Emalternativa,onomedoarquivopadroatualdoarquivocompletopodeserrecuperadoemum
varivel,ouovalorderetornopodeserutilizadanum SUBSTITUIRou ACTUALIZAOdeclarao.Osseguintes
comandosimplesmenteexibeonomedoregistradoatualmenteINIarquivonatela:

?goIniMgr.GetIniFile()

SetIniFile()
OSetIniFile()mtodousadoparadefinirumespecficoINIarquivocomoodestinopadroparaleitura/gravao
operaesouparacriarumnovoINIarquivoedefinaocomopadroparausofuturo.Omtodolevaum
nicoparmetroonomedeumarquivoedefineessearquivocomoonovoarquivopadroparausodo
objetoManager.Ovalorderetornonumricocomoeterumdostrsvalorespossveis:
Erro1nosparmetrosdeentrada
0Nopossvelregistraroarquivo
1ficheiroespecificadodefinidacomopadro
Seoarquivocujonomefornecidonoexistenocaminhoespecificado(oupadro),oINI
Managerircriaroarquivoeatribuirlheumanicaseochamadaomesmoqueonomedoarquivoe
tornaronovoarquivodoarquivopadro.

Captulo10:ClassesNonVisual 317

Exemplos:
ParadefinirarquivopadrodoWindows"WIN.INI",comooarquivopadro:

lnSuccess=goIniMgr.SetIniFile('C:\WINDOWS\WIN.INI')

ParadefinirumINIarquivonodiretriodetrabalhoatualcomooarquivopadro:

lnSuccess=goIniMgr.SetIniFile('eusys')

ParacriarumnovoarquivousandoINIformatodearquivoemumlocalespecficoedefinilocomopadro:
lnSuccess=goIniMgr.SetIniFile('G:\DEV\SYSTEM\WORK.STF')

GetValue(<Section>,<Item>[,<file>])
OGetValue()mtodoretornaovalorarmazenadoparaumitemespecificadodasecoespecificada
deumarquivoqueobservaopadroINIformatodearquivo.Omtodolevadoisobrigatria
parmetros(onomedaseo,eonomedoitem)eumterceiroopcional(oarquivopara
usar).Seoterceiroparmetroforomitido,oarquivopadroatual.
Ovalorderetornosersempredecarctertipoeouserovalorespecificadoou
umacadeiavazia.Estemtodonoretornaumvalordeerroemqualquercircunstncia.Assim,se
queraseoouonomedoitemnoexistem,ouseacombinaodesecoeitemest
invlida,umacadeiavaziatudoqueretornado.Damesmaforma,seumparmetroforomitidoouinvlido,
umacadeiavaziaretornada.

Exemplos:
Pararecuperarovalordoarquivopadroatualdoitem'Nome'naseo'Sistema':

lcName=goIniMgr.GetValue('sistema','name')

PararecuperaronomedodriverODBCconfiguradoparalerastabelasdoFoxProparaareadetransferncia:

_ClipText=Goinimgr.getvalue('FOXPROFILES','Driver32',
'C:\windows\odbc.ini')

Nota:Recuperandoumvalorapartirdeumarquivodiferentedoarquivopadrono
alteraraconfiguraodearquivopadro.Anicaformadealteraroarquivopadro
cenrioatravsdomtodoSetIniFile().

SetValue(<Section>,<Item>,<Valor>[,<file>])
OSetValue()mtodogravaovalorespecificadoparaoitemeSeoespecificado.Sequero
SeoouItemaindanoexistenoarquivoespecificado,asentradasapropriadassocriadas
valoresdeoutraformaexistentessosimplesmentesubstitudos.Todososparmetros,incluindoovalor,
deveserpassadocomocadeiasdecaracteres,masparmetrosnosomaisculasdeminsculas.Asregrashabituais

318 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

regemascadeiasdecaracteresaplicarefunesdeconversodeFoxPropodemserincorporadosna
chamadademtodocomonormal.
SetValue()retornaumvalornumricocomoumdosseguintes:
Erro1nosparmetrosdeentrada
0Nopossvelgravaroarquivoespecificado
1valorescritocomsucesso
Exemplos:
ParadefinirovalordoitemdatanaseodeSistemadoarquivopadro:

lnSuccess=goIniMgr.SetValue('sistema','date',DMY(DATE()))

Paracriarumnovoitemnaseosistemadoarquivopadro:

lnSuccess=goIniMgr.SetValue('SYSTEM','newitem','newvalue')

Paracriarumanovaseoeitemnoarquivopadro:

IFgoIniMgr.SetValue('NewSection','NewItem','somevalue')>0
***Asinscriesescritascomsucesso
FIMSE

Nota:SetValue()noircriarumnovoarquivoseoarquivoespecificadofaz
noexistirousehouverregistradonenhumarquivopadro.Nesses
situaes,ovalorderetornosersempre0.

ReadIniFile(<@ArrayName>[,<file>])
OReadIniFile()mtodoltodoumINIarquivoemumamatrizdeduascolunas(quedeveser
criadonarotinadechamadaepassadaporreferncia).Amatrizsersemprecorretamente
dimensionadoparaosvaloresqueseencontramnoINIarquivo.Aprimeiracolunadamatrizcontm
osnomesdoscabealhosdasseces(incluindoassuas'[]'delimitadores)ouitens,enquantoosegundo
colunacontmossmbolosdedelimitao'[]'parattulosdeseoouosvaloresreaisparaositens.
ReadIniFile()retornaumvalornumricoqueindicaonmerodelinhasvlidasqueforamlidas
namatrizdedestino.Senenhumnomedearquivopassadocomoumparmetro,oarquivopadroassumido.

Exemplo:
Paralertodoocontedodoarquivopadroparaamatriz laData:

ArraylocallaData[1]
IFgoIniMgr.ReadIniFile(@laData)>0
***Pelomenosumalinhaencontrada
OUTRO
***Nohdadosretornados
FIMSE
Captulo10:ClassesNonVisual 319

Ocontedodo laDataseralgoparecidocomisto:

laData[1,1] [SISTEMA]
laData[1,2] []
laData[2,1] NOME
laData[2,2] Sistemadeteste
laData[3,1] ENCONTRO
laData[3,2] 1998/01/10

WriteIniFile(<@ArrayName>[,<file>])
OWriteIniFile()mtodogravaocontedodeumamatrizdeduascolunas(quedevemsercriadosem
ochamadorotinaepassadoporreferncia)paraoespecificadoINIArquivo.Aprimeiracolunada
matrizdeveconterosnomesdasrubricasdaseco(no'[]'delimitadoresdeveserusado)oudo
Itens,enquantoasegundacolunadeveconterossmbolosdelimitadores'[]'paracabealhosSeo
eosvaloresreaisparaositens.
Amatrizdeveserordenadodemodoaqueoprimeiroelementosempreumaseconome(isto,tema
segundoelementodefinidocomo"[]").LinhassubsequentesdamatrizsotratadoscomoparesItem/Valorque
pertencemaessaseoatqueumanovalinhaSeodeCabealhoencontrado.
Seumnomedeseonoforencontrado,umanovaseocriadaautomaticamentenoINIarquivoe
Seumnomedeitemnoforencontrado,oitemseradicionadoseopai.
WriteIniFile()retornaumvalornumricoqueindicaonmerodelinhasqueeramvlidos
escritoparaoarquivodedestino.Senenhumnomedearquivopassadocomoumparmetro,oarquivopadro
eseoarquivoespecificadonopodeserencontradoouescrito,umvalorde0retornado.
assumido,

Exemplo:
ParaescreverumINIarquivodeumarray:

ArraylocallaData[4,2]
laData[1,1]="SYSTEM"
laData[1,2]="[]"
laData[2,1]="NAME"
laData[2,2]="SistemadeTeste"
laData[3,1]="NewSection"
laData[3,2]="[]"
laData[4,1]="Version"
laData[4,2]=" 1.0G"
IFgoIniMgr.WriteIniFile(@laData)>0
***Osdadosforamgravadoscomxito
FIMSE

OINIarquivoserentoparecidocom:

[SISTEMA]
NAME=SistemadeTeste
[NEWSECTION]
Version=1.0G

320 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

UtilizandoogerenciadordearquivosINI
OusomaisbvioparaoINIgerenciadordearquivospararecuperaoeatualizaoconstantesdosistema,
armazenadasemumarquivodetextoexternodentrodeumaaplicao.Todaaestruturadogerente
desenhadoespecificamenteparasimplificaresteprocessoemumambientedeaplicaotpica,ondeum
nicoINIarquivousadoparaarmazenartodososdadosrelevantes,fazendoqueoarquivopadroparatodasasoperaes.
Noentanto,tantooGetValue()eSetValue()mtodosproporcionamacapacidadedetratarficheiros
quenosejaoarquivopadroquandonecessrio.
OsegundousoprincipalparaoINIgerenciadordearquivoscontribuirparaamanutenodaaplicao
INIarquivos.OsReadIniFile()eWriteIniFile()mtodossoprojetadosparatransferirumblocode
informaesentreumamatrizFoxProeumINIarquivo.Provavelmente,amaneiramaissimplesdemanipulao
istocriarumatabela(oucursor)comduascolunasquecorrespondemmatrizrequerida
estruturaedeusardoFoxProSQLSELECT...INTOARRAYeSQLINSERTINTO....APARTIRDE
ARRAYparaobterdadosemalgoquepodeserutilizadonumaforma.Ocdigodeexemplo
queacompanhaestecaptulocontmumformulrio("INIMAINT.SCX")queusaumcursorpara
manterasentradasparaumINIarquivo.

Figura10.1formulriodemanutenosimplesparaarquivosINI

Apesardenoserabrangenteemseutratamentodeerros,esteexemplomostracomousar
oINIFileManagerparaleregravarumINIarquivo.Oformulrioforneceparaaleituraapartirdequalquer
umjexistenteINIarquivo,criandoumcompletamentenovoouleituradedadosdeumatabelaVisualFoxPro.
Nesteexemplo,ogerentecriadocomoumobjetoglobal(goIniMgr)noformulriodecarga
Mtodo.

Captulo10:ClassesNonVisual 321

Lendoosdadosdafonteespecificadanocursordoformulriotratadopelocostume
ReadFile()mtodocomosesegue:

ArraylocallaTfer[1,2]
lcSceFileLOCAL,lcOldFile
COMThisForm
***Verifiqueoarquivodeorigem,cursorclaroseumnovoarquivoestsendocriado
IF.chkSource()>0
IFEMPTY(ALLTRIM(.txtFName.Value))
***Acriaodeumnovoarquivobastaretornar
ZAPINcurIniFile
.RefreshForm()
RETORNA
FIMSE
OUTRO
***VerificaodearquivosFontefalhou!
RETORNA
FIMSE

***OrigemespecificadaOK,entoserenemcaminhocompletoeonomedoarquivo
lcSceFile=ALLTRIM(ADDBS(.txtDir.Value))+ALLTRIM(.txtFName.Value)
IFJUSTEXT(lcSceFile)="DBF"
***umamesa,ento,bastalloemumamatriz
ttuloSELECT,item(lcSceFile)ORDERBYsortorderINTOARRAYlaTfer
OUTRO
***umarquivoINI(talvez).Entollo
goIniMgr.ReadIniFile(@laTfer,lcSceFile)
FIMSE
***Limparcursorecopiarosresultadosem
ZAPINcurIniFile
INSERTINTOcurIniFiledamatrizdelaTfer
***Tiraoffttulo"[]"elesvoserreescritadequalquermaneira
SUBSTITUIRtodoottuloCOMCHRTRAN(ttulo,'[]','')NOcurIniFile
.RefreshForm()
ENDWITH

EscreverosdadosparaforadocursortratadonocostumeWriteFile()mtodocomo
segue:
ArraylocallaTfer[1,2]
lcOldFileLOCAL,lcDestFile
COMThisForm
***Deveterumdestino
IFEMPTY(.txtDestFName.Value)
MESSAGEBOX('Umarquivodesadadeveserespecificado!',16',incapazdecontinuar')
.txtDestFName.SetFocus()
RETORNA
FIMSE
***Temosumdestino
lcDestFile=ALLTRIM(ADDBS(.txtDestDir.Value))+ALLTRIM(.txtDestFName.Value)
***Excluiroarquivoseelejexistir
ESE!ARQUIVO(lcDestFile)
DELETEFILE(lcDestFile)
FIMSE
***Agoracriarumnovoarquivo,vazioprontoparagravar
***Nsprecisamosfazerissoparagarantirqueassupressessefeitacorretamente
lnHnd=FCREATE(lcDestFile)

322 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

IFlnHnd<0
MESSAGEBOX('Nopossvelcriarnovoarquivo'+CHR(13)
+LcDestFile,16,'NopossvelContuinue')
RETORNA
OUTRO
FCLOSE(lnHnd)
FIMSE
***Agoraescrevaonovoarquivoignorevazia"heading"campos
*SELECTFROMcurinifileonde!VAZIO(posio)INTOARRAYlaTfer
COMgoIniMgr
***contedodoarquivoWrite
.WriteIniFile(@laTfer,LcDestFile)
ENDWITH
***LimparCursor
ZAPINcurIniFile
.RefreshForm()
ENDWITH

Comoselecionarumareadetrabalhodiferente,estiloOOP!( Exemplo:
ChgArea.prg )
Umdostrechosmaisfrequentementeescritadecdigo,empraticamentequalqueraplicao,parece
algoassim:

***Guardarreadetrabalhoatual
lnSelect=SELECIONAR()

***Selectreanecessria
ESE!USADO(<Alias>)
USE<table>IN0NOVAMENTEALIAS<Alias>
FIMSE
Selecione<novareadetrabalho>

***Fazeralgumacoisal
...
<comandos>
...
***Voltarreadetrabalhooriginal
SELECT(lnSelect)

Agora,naverdade,issonorealmentemuitodifcil,masoualgumavarianterepetidomuitas
vezesemumaplicativo.Nsrealmentedevesercapazdefazermelhordoqueisso,agoraquetemostodoo
poderdeOrientaoaObjetosatrsdense,naverdadenspodemos.

Visogeral
OSelAliasclassefoiprojetadaparaaceitaronomedealiasdeumatabelacomoumparmetroemudarpara
readetrabalhodessamesa.Seatabelanoabriloirabriramesaparans.Maisimportanteque
vai"lembrar"queabriuamesae,porpadro,fechloquandoeledestrudo.o
classefornecesuporteparaumparmetroadicionalquepodeserusadoparaespecificarumnomealternativo
quandonecessrioabrirumatabelacomumaliasdiferentedonomerealdatabela.
Captulo10:ClassesNonVisual 323

AclassetempropriedadesoumtodosnoexpostoefaztodooseutrabalhoemseuInite
Destruirmtodos.Aocriarumobjetocombasenessaclasse,eescopolocomo LOCAL,precisamos
nuncaescrevercdigocomoomostradoacimanovamente.

Umapalavrasobreacriaodoobjetoselector
Umobjectodeselectorpodesercriadodamaneirausualporprimeirocarregaroficheiroprocedimentoem
memriae,emseguida,usandooCreateObject()funosemprequenecessriaumainstncia.Contudo,
Verso6.0doVisualFoxProintroduziuummtodoalternativo,usandooNewObject()
funo,quepermitequevocespecifiqueabibliotecadeclassesapartirdoqualumaclassedeveser
instanciadocomoumparmetro.Emborasejaligeiramentemaislento,issonosignificaquevocnoprecisa
carregaremanterarquivosdeprocedimentonamemriaetilquandovocprecisacriarumobjeto'on
thefly",comoeste.Asintaxeparaambososmtodosdadaabaixo.(Notesequecom
NewObject(),seaclassenoumabibliotecadeclassesvisual,VisualFoxProesperatantoum"mduloou
programadenome'comoosegundoparmetroequerumnomedeaplicativoouumstringvaziaouum
NULLvalorcomooterceiro).

***UsandoCreateObject()
PROCEDIMENTOPARAselaliasaditivoconstante
Losel=CREATEOBJECT('xSelAlias',<Alias>,[|<NomedaTabela>])

***UsandoNewObject()
Losel=NEWOBJECT('xSelAlias','selalias.prg',NULL,<Alias>,[|<NomedaTabela>])

Umapalavradecautelaseutilizarvriasinstnciasdestaclassenomesmoprocedimentoou
mtodoparaabrirtabelas,querassegurarquetodososobjectossocriadosapartirdamesmareadetrabalhoouque
elessolibertadosnaordeminversaquelaemqueforaminstanciado.Sevocnofizer
isso,vocpodeacabaremumareadetrabalhoquefoiselecionadocomoresultadodaaberturadeumamesa,masque
agoraestvazio.

Comoaclasseselectorconstrudo
Comomencionadonavisogeraldestaclassetempropriedadesoumtodosnoexpostoefaztudo
seutrabalhoemsuasInitoudestruirmtodos.Internamenteeleusatrspropriedadesprotegidaspararegistro:
readetrabalhoemquefoiinstanciado
oaliasdatabelagere
seatabelajestavaabertanainstanciao

AclasseselectorInitmtodo
OInitmtodofazquatrocoisas.Primeiroeleverificaosparmetros.Umnomedealiaso
mnimaquedevesertransmitido,enaausnciadosegundoparmetroopcionalamesa
nome,elepresumequeatabelatemomesmonomecomooalias.Seaprovado,onomedatabelapode
incluemumaextensoetambmpodemincluirumcaminho.(Observeousoda ASSERTnestapartedo
Mtodo.Oobjetivoaquiparaavisarosdesenvolvedoresdeerrosquepossamsurgirnasintaxechamando
semafetarocdigodetempodeexecuo.)

324 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Procedimentodeinicializao(tcAlias,tcTable)
llRetValLOCAL
***NoAliasPassouBailOut

ESE!VARTYPE(tcAlias)="C"

ASSERT.F.MENSAGEM"devepassarporumNomeAlias
toWorkAreaSelector"

RETURN.F.
FIMSE
tcAlias
=UPPER(ALLTRIM(tcAlias))

IFVARTYPE(tcTable)#"C"ouvazio(tcTable)
tcTable=tcAlias
OUTRO
tcTable=UPPER(ALLTRIM(tcTable))
FIMSE

Emseguida,eleverificaoaliasatualmenteselecionados.Seissojoaliasnecessrios,elesimplesmente
retornaumvalorde f.eoobjetonoinstanciado.Arazosimplesmentequeseatabela
jestabertoeselecionados,nohnadaparaoobjetoparafazerdequalquermaneira:

***Sejnareadetrabalhocorretanofazernada
IFsuperior(ALLTRIM(alias()))==tcAlias
RETURN.F.
FIMSE

Emseguida,eledeterminaseoaliasnecessriojestemusoe,seno,tentaabriro
mesasoboaliasespecificado.Seforbemsucedidoeledefinesua"lWasOpenpropriedade'para .F.Istopermite
amesmatabelaaserabertomaisdeumavezemdiferentesaliases.Seatabelanopodeser
aberta,umvalorde .F.irserdevolvidoeoobjectonoirserinstanciada.(NOTA:A
"Produo"versodestaclassetambmdeveverificarseoarquivoexiste,equeumavlida
TabeladoVisualFoxPro,antesdetentarabrilocomum USEcomando.Talcdigoj
foicobertoemoutroslugaresefoideliberadamenteomitidoapartirdestaclasseparamantlotosimples
quepossvel.VejaaISDBF()funonoCaptulo7,"Comocompararasestruturasdedois
"tabelasparaumasoluo.)

***SeespecificadoAliasnoabertoAbrao

ESE!Utilizado(tcAlias)
USE(tcTable)novamenteIN0ALIAS(tcAlias)COMPARTILHADA
***EConfira!
llRetVal=USADO(tcAlias)
***Seforadoaabrir,Notaofato
IFllRetVal
This.lWasOpen=.F.
FIMSE
OUTRO
llRetVal=.T.
FIMSE

Finalmenteelearmazenaonmerodereadetrabalhoselecionadoeonomedoaliasaoseu
'NOldarea'e'Caliaspropriedadeseparmetros'paraareadetrabalhonecessrio.Oobjetivo,
portanto,apenasinstanciadoquandotudofuncionouconformeoesperado:

***SeOK,salvarreadetrabalhoatuale
***AgoraMoverparaareadetrabalhoespecificado

Captulo10:ClassesNonVisual 325

IFllRetVal
This.nOldArea=SELECIONAR()
SELECIONAR(tcAlias)
This.cAlias
=tcAlias

FIMSE
***StatusdeRetorno
RETURNllRetVal
ENDPROC

AclasseselectorDestruirmtodo
OmtodoDestruirlidacomaarrumaodoambiente.Seoseletorabriuamesa,
fechadocasocontrrio,deixadaemaberto.Areadetrabalhoemqueoobjetofoiinstanciado
emseguida,selecionadoeoobjetoliberado:
PROCEDIMENTODEDESTRUIR
Comisso
***Seatabelaabertaporesteobjeto,fechlo
ESE!.lWasOpen
USOEM(This.cAlias)
FIMSE
***Restaurarreadetrabalhoanterior
ESE!VAZIO(.nOldArea)
SELECT(.nOldArea)
FIMSE
ENDWITH
ENDPROC

Usandoaclasseselector
Aclassedestinaseaserusadaparainstanciarumobjectolocalnumprocessooumtodosempre
necessrioparamudardereasdetrabalho.Oprogramadeexemplo(ChgArea.prg)mostracomoelepode
serusado:
**********************************************************************
*Programa :ChgArea.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:ilustrarousodaclasseSELALIASparacontrolar
* :Emudandoreasdetrabalho.resultadosdesadaparaoecr
**********************************************************************
***Certifiquesedequeestamostodosfechado
CLARO
TABELASfechartodas
***TabelaabertaClients
UtilizarORDERsqlcli1IN0
?'UsandoSelectorcomapenasumAlias'
?'================================='
?
?"UtilizarORDERsqlcli1IN0"
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS
?
()
***CriarumobjetodeSeleoCliente
loSelCli=NEWOBJECT('xSelAlias','SelAlias.prg',null,'sqlcli')
?"loSelCli=NewObject('xSelAlias','SelAlias.prg',null,'sqlcli')"

326 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
***AbrirFacturasTable(temporariamente)
loSelInv=NEWOBJECT('xSelAlias','SelAlias.prg',null,'SqlInv')
?"LoSelInv=NEWOBJECT('xSelAlias','SelAlias.prg',null,'SqlInv')"
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
***AgorafecheatabelaFacturasporliberaroobjeto
LIBERTAOloSelInv
?"LIBERTAOloSelInv"
?"USADO('SqlInv')=>"+IIF(USADA('SqlInv')",aindaemuso","NoAbra")
?
***AgorareleasweoobjetodatabelaCliente
LIBERTAOloSelCli
?"LoSelCliLIBERTAO"
?"USADO('sqlcli')=>"+IIF(USADA('sqlcli')",aindaemuso","NoAbra")
?
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
?"Pressioneumateclaparalimparatelaecontinuar..."
INKEY(0,'hm')
CLARO

?'UsandoSelectorparacriarumAlias'
?'================================='
?
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
***AbertasClientsnovamentesobnovaAlias
loSelCli=NEWOBJECT('xSelAlias','SelAlias.prg',NULL,'Clientes','sqlcli')
?"LoSelCli=NewObject('xSelAlias','SelAlias.prg',NULL,'Clientes',
'Sqlcli')"
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
***AbrirFacturasTable(temporariamente)
loSelInv=NEWOBJECT('xSelAlias','SelAlias.prg',NULL,facturas,'SqlInv')
?"LoSelInv=NEWOBJECT('xSelAlias','SelAlias.prg',NULL,facturas,
'SqlInv')"
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
***AgorafecheatabelaFacturasporliberaroobjeto
LIBERTAOloSelInv
?"LIBERTAOloSelInv"
?"utilizado(facturas)=>"+IIF(USADA(facturas),"aindaemuso","Nopossvelabrir"
)
?
***Agora,solteoobjetodatabelaCliente
LIBERTAOloSelCli
?"LoSelCliLIBERTAO"
?"utilizado("clientes")=>"+IIF(USADA("clientes"),"aindaemuso","Nopossvelabrir")
?
?"Area:"+PADL(SELECT(),2)+"UsandoaTabela"+JUSTSTEM(DBF())+",comoAlias"+ALIAS()
?
?"Pressioneumateclaparalimparatelaeterminar..."
INKEY(0,'hm')
CLARO
Captulo10:ClassesNonVisual 327

ComopossogerircaminhosnaDataEnvironmentdeumformulrio?
DataEnvironmentdoformulriofornecemuitosbenefcios,incluindoapossibilidadedeautoabertoe
mesasprximas,paradefinirobufferdetabelasindividuaise,nomomentodaconcepo,parausararrastaresoltarpara
criardadoscontrolesacopladosemumformulrio.Noentanto,existeumproblemapermanentecomousodo
DataEnvironmentdoformulrioaformacomoelelidacomaquestodecaminhosparaasmesaslo
contm,paradizeromnimo,complicado.
CadacursorcriadonoDataEnvironmenttemduaspropriedadesqueestoenvolvidoscomo
nomedatabelaeinformaesdecaminho,ouseja,'basededados'e'CursorSource'.Noentanto,elesso
usadodeformadiferente,dependendoseatabelaemquestolivreouligadoaumbancodedados
recipiente.Amaneirarealemqueainformaoarmazenadadependedalocalizaodo
tabelasemtempodedesigndeacordocomasseguintesregras:

Tabela10.2Propriedadesdecursorquedeterminamalocalizaodosdadosdeorigem

TipodemesaeLocalizaoBancodedados CursorSource
TabelaBound,DBCnaatual Caminhorelativoeonomedoarquivo OnomedatabelanaDBC
dirigir DBC
Tabelaligado,DBCemdiferentes CaminhoabsolutoenomedoarquivodeOnomedatabelanaDBC
dirigir DBC
Tabelalivrenaunidadeatual Caminhorelativoeonomedoarquivo
Vazio DBF
Tabelalivrenaunidadediferente Caminhoabsolutoenomedoarquivode
Vazio DBF

OsexemplosqueseseguemmostramosresultadosdaadiodeumatabelaparaoDEdeumaforma,enquanto
executandoumasessoVFPcomdrive"G:"definidocomoaunidadepadroe"\VFP60\"comooatual
diretrio:
[1]Tabelalivreemumaunidadediferente
alis ="Messageb"
Bancodedados=""
CursorSource=e:\v f p50\common\libs\messageb.dbf
[2]mesalivrenosubdiretriododiretriodetrabalhoatual(G:\VFP60\)
alis ="Cliente"
Bancodedados=""
CursorSource=data\customer.dbf
[3]TabeladeumDBCemumaunidadediferente
alis ="Demone"
BancodeDados=c:\v f p60\CH08\ch08.dbc
CursorSource="demone"
[4]TabeladeumDBCnamesmaunidade,masnoumsubdiretriododiretriodetrabalho
(G:\VFP60\)
alis ="clientes"

328 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

BancodeDados=..\samples\data\testdata.dbc
CursorSource="clientes"
[5]TabeladeumDBCnosubdiretriododiretriodetrabalhoatual(G:\VFP60\)
alis ="clientes"
BancodeDados=data\testdata.dbc
CursorSource="clientes"

EmtempodeexecuoVisualFoxProsempretentareutilizarasinformaessalvascomocursoremprimeirolugar,
masseoarquivonopodeserencontradonolocalespecificado,elecontinuaraprocurartodososdisponveis
caminhos.

O"semcdigo"soluo!
Arespostafcilparaestaquesto,portanto,paramantertodasastabelas(livreouconjugada)ebancodedados
recipientesnomesmodiretrioeparatercertezaquedefinidocomoumsubdiretriodoseu
diretriodedesenvolvimento.IssogarantequeoVisualFoxProsempreapenasarmazenaocaminhorelativopara
tabelas.(Vejaexemplos2e5acima).
Quandovocdistribuirseuaplicativo,certifiquesedequeumsubdiretrio(nomeadoomesmoqueo
utilizadoduranteodesenvolvimento)criadonodiretrioinicialdoaplicativoequetodos
arquivosdedadossoinstaladosl.Noentanto,hmuitasocasiesemqueestasoluonoapenas
possvel,maisobviamentequandooaplicativoestsendoexecutadoemmquinasclientes,masusandocompartilhada
osdadosarmazenadosnoservidor.Ento,oquenspodemosfazersobreisso?

Asoluoembutida!
DataEnvironmentnativadeumformulrionopodesersubclassificados(emboranspodemos,claro,criaronosso
aulasDataEnvironmentprpriosnocdigo).Istosignificaquenohnenhumamaneiradeescreverocdigoparauma
formulriodeclasseemtempodedesignparalidarcomaresoluodecaminhos,porqueessecdigoteriadeser
colocadoemDataEnvironmentBeforeOpenTablesmtodo.(PorqueBeforeOpenTables?
PorqueoOpenTablesmtodocriaosobjetosdecursoreemseguida,chamaBeforeOpenTables
depoisosobjectossocriados,masantesainformaonelescontidausadapararealmenteabrira
mesas.)Assim,umaabordagemadicionaralgumcdigoparaaBeforeOpenTablesmtododetodasasformasde
definiroscaminhosparaastabelasconstantescomonecessrio.Istoirfuncionar,maspareceumpoucoum"old
formadomaneira"defazlo.Almdequalqueroutracoisaquefariaamanutenodeumaaplicao
comummontedeformasumagrandeempresa.Devehaverumamaneiramelhor!

Asoluoobj etodatadriv en!


SenopodemossubclasseDataEnvironmentnativa,talvezpudssemoscriaranossaprpriaclassepara
lidarcomotrabalho,esimplesmentelimitarocdigoquetemdeseradicionadaacadainstnciadeumaclassedeformulrio
aumanicalinha?Naverdade,podemosfazerexatamenteisso,eseusarumatabelaparaarmazenarinformaescaminhoque
Tambmpodesimplificarmuitoatarefademanteraaplicao.Umatalsoluoapresentadana
aprximaseodestecaptulo.

Aclassegerentedecaminhodedados
Aclassedegestodocaminhodedadosconcebidaparaserinstanciadacomoumobjetotransientena
BeforeOpenTablesmtododeumDataEnvironmentdoformulrio.Suafunofazeravarreduraatravsdetodas

Captulo10:ClassesNonVisual 329

osobjetosmembrodoDataEnvironmente,paracadaobjetocursorqueeleencontra,realizaruma
olharparacimaemumatabelaseparada"sistema"quedefineoscaminhosaseremutilizadasparasuastabelasemtempo
EnquantonsaindaprecisaadicionarcdigoparaaBeforeOpenTablesmtododeDataEnvironmentem
deexecuo.
todasasformasquecriamos,nssprecisaadicionarumalinha.Ocdigoexecutadoestcontidonuma
classenicaeutilizaumanicatabeladeestruturaprdefinida.Amanuteno,porconseguinte,ummenor
importaquandovocadotarestaestratgia.

Atabeladegerenciamentodecaminhos
Oprimeirocomponentequeprecisamosafimdeimplementaraestratgiadelineadaacimao
tabeladepesquisaqueirarmazenarainformaoquedesejamosVisualFoxProparausaremtempodeexecuo.este
mesatemsido(imaginao)comonome'datapath.dbf'eemboranstloincludona
continerbancodedadosdoprojetoquensnormalmenterecomendamosquesejausadocomoumamesalivre.o
estruturaaseguinte:
EstruturaPara:C:\VFP60\CH10\DATAPATH.DBF
=========================================
DBC :CH10.DBC
CDX :DATAPATH.CDX

ndicesassociados
==================
***Chaveprimria:CTable:UPPER(CTable)
ISDEL:DELETED()
campoDetalhes
=============
CTable C(20,0)NOTNULL&&NomedatabelaouDBCNomeouarquivoDBF
nome
SET_PATH C(60,0)NOTNULL&&unidadeecaminho
SET_DBC (Somentequadrosvinculados)C(20,0)NONomeNULL&&DBC
SET_TABLE C(20,0)NOTNULL&&NomedatabelanaDBC(quadrosvinculados)
&&Onomedoarquivoeextenso(TabelasFree)

Paravelocidadedeprocuranatabelaindexadanocamponomedatabelaetemumndiceem
DELETED().Desdeestatabelaprovavelmenteserconfiguradolocalmenteemumamquinacliente(paralidarcom
mapeamentosindividuaisdecarro),aquestodederrubargrandesndicesemDELETED()sobreo
redenoprovvelquesurja.NstemosnossatabeladeexemplopovoadacomoilustradonaFigura
10,2abaixo:

Figura10.2tabelademapeamentodecaminhodedados

330 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Aclassedegerenciamentodecaminhos(Exemplo:chgpaths.scx )
Aclassereal,comooselectordereadetrabalho,fazoseutrabalhodiretamentenoInitmtodoou
mtodoschamadosapartirInit,enotemmtodosexpostosoupropriedades.Istosignificaque,quando
instanciado,oobjetorealizaautomaticamenteasuafunoepode,ento,serliberado.o
classedefineduaspropriedadesprotegidasparaseuusointerno,umamatrizparaarmazenarrefernciasdeobjeto
oscursoresDataEnvironmenteumapropriedadeparaarmazenararefernciaaochamado
Dataenvironmentprprioobjeto.
Oprincpioportrsdasuaoperaoqueelerecebeumarefernciachamada
DataEnvironment(comoparmetro)evalidaquearefernciaaomesmotempoumobjetovlidoe
naverdade,refereseaumobjetocujaclassebase"DataEnvironment.ODEchamando,ento,
analisadoparaobterumarefernciaparacadaobjetocursor,quearmazenadoparaamatrizinterna.Tendo
abriuatabeladeconsultaaetapafinalpararecuperarderefernciadecadacursor,porsuaveze
determinaronomedatabelanaqualsebaseia(usaJUSTSTEM()pararetornaronome
doCursorSourcepropriedade).
Onomedatabela,ento,olhouparacimanatabelademapeamentoe,dependendodosdadosencontrados(se
houver)dobancodedadosepropriedadesCursorSourcesoactualizados.Ocdigorealutilizado:

**********************************************************************
*Programa :DPathMgr.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Usatabeladepesquisaparaobtercaminhoscorretosparaosquadros
* :Emtempodeexecuo,definaoscaminhosDECursorObjeto
* :ChamadadeMtodoBeforeOpenTablesdeumaDEForm
* :EsperaumarefernciaparaoDEaserempassadospodeusar

NEWOBJECT():
* :LoPathSet=NEWOBJECT('dPathMgr','dpathmgr.prg',NULL,ESTA)
**********************************************************************

DEFINECLASSDPathMgrASrelao
***DefinirPropriedadesProtegidas***

***Arrayparalistadecursores
aCursorsPROTEGIDAS[1]
aCursors[1]=NULL

***ObjectReferenceaoDE
OdePROTEGIDA
Ode=NULL

OInitmtodousadoparacontrolaroprocessamentoeprimeiroverificaoparmetropassadospara
assegurarqueumarefernciaaumobjectoDataEnvironment.Emseguida,elechamaoGetTablesmtodo
e,setodasastabelassoencontrados,chamaOpenRefTableparaabriratabeladepesquisa.Finalmente,chamaa
SetPathsmtodopararealmenteverificarcadacursoreverseumnovocaminhofoidefinidoparaele:

PROCEDIMENTOInit(Tode)
lnCursorsLOCAIS

***Verifiqueoparmetro
IFVARTYPE(Tode)="O"
***Temumarefernciadeobjetovlido

Captulo10:ClassesNonVisual 331

This.oDe=Tode
Seforinferior(This.oDE.BaseClass)#"DataEnvironment"

***MasnoumaDE!
ASSERT.F.MENSAGEM"DPathMgrclasserequerumareferncia"
+CHR(13)+"DataEnvironmentobjetoquechama."
RETURN.F.
FIMSE
OUTRO

***WhoopsNemmesmoumobjeto
RETURN.F.
FIMSE

***Quantoscursoresestol?
lnCursorsThis.GetTables=()
IFlnCursors<1

***NadaaverassimaapenasvoltarOK
RETORNA
FIMSE

***VerifiqueparaDataPathTabelaeabrilo,senecessrio
ESE!This.OpenRefTable()
***Nopossvelencontraratabeladereferncia
RETURN.F.
FIMSE

***Definiroscaminhosparaoscursores
This.SetPaths(lnCursors)
RETORNA
ENDPROC

OOpenRefTableexplicitamentetentaabriratabeladeDataPath.Issopoderia,senecessrio,ser
parametrizadomasnopodemosverqualquergrandebenefcioimediatoparafazlo(simocontrrio
defato).Nopodeconcebivelmenteexistirsituaesemquevriastabelasdemapeamentoseria
requeridoporumaplicativoeeleseria,ento,totalmenteadequadoparapassarumparmetroparao
tabelaaserusada.Noentanto,aofazlovocperdeumdosprincipaisbenefciosdestaabordagem,que
queocdigoaserinseridonosBeforeOpenTablesdeformasjnoseriaamesma
paracadaforma:

PROTEGIDOopenreftablePROCEDIMENTO

***Abraatabeladereferncia
ESE!Utilizado('DataPath')
datapathusarnovamentenas0SHAREDNOUPDATE
FIMSE
RETURNUSADO('DataPath')
ENDPROC

OGetTablesmtodousaarefernciadeobjetoarmazenadoparaoDataEnvironmentdechamadapara
preencherumamatrizcomtodososobjetosmembro.Esteentodigitalizadoerefernciasaocursor
objetossoarmazenadosparaapropriedadedematriz.Omtodoretornaonmerodecursoresque
encontrado:
332 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

GetTablesprotegidoprocedimento
ArraylocallaObj[1]
lnObjCntLOCAL,lnCnt,loObj,lnRows,lcObjName

***ObterumalistadetodososobjetosdoDE
lnObjCnt=AMEMBERS(laObj,This.oDe,2)

***Procurenalista
lnRows=0
PARAlnCnt=1alnObjCnt

***VerifiqueseesteobjetorealmenteumCursor
loObj=EVAL("This.oDe."+laObj[lnCnt])
IFloObj.BaseClass="cursor"

***,parasalvarsuarefernciaparaamatrizinterna
***Adicionarumanovalinhaparaamatrizcursores
lnRows=+1lnRows
This.aCursorsDIMENSO[lnRows,1]
This.aCursors[lnRows]=loObj
FIMSE
PRXIMO

***Retornonmerodecursores
RETORNOlnRows
ENDPROC

OSetPathsmtodoondeapesquisanatabelademapeamentofeitoeosresultados
sousadospararedefinirdecadacursordebancodedadoseCursorSourcepropriedadesemconformidade.Sehouver
nenhumaentradanatabeladepesquisa,aspropriedadesdocursornosoalteradosdeformaalguma:

SetPathsprotegidoprocedimento(tnCursors)
lnCntLOCAL,loObj,lcTable

***Procurenalista
PARAlnCnt=1atnCursors

***Recuperararefernciadoobjetodamatriz
loObj=This.aCursors[lnCnt]

***Encontreonomedatabela
lcTable=UPPER(JUSTSTEM(loObj.CursorSource))

***Procureonomenatabeladerefernciaquelista
***Ondeosdadosdevemsertomadasapartir
SeSEEK(lcTable,"caminhodedados","CTable")

***Temosumarefernciaparaestatabela!
ESE!VAZIO(set_dbc)

***Temosumamesadelimite
loObj.Database =ALLTRIM(datapath.set_path)
+ALLTRIM(DataPath.set_dbc)
loObj.CursorSource=ALLTRIM(DataPath.set_table)
OUTRO

***Deveserumamesalivre

Captulo10:ClassesNonVisual 333

loObj.Database=""
loObj.CursorSource =ALLTRIM(datapath.set_path)
+ALLTRIM(DataPath.set_table)
FIMSE
FIMSE
PRXIMO
ENDPROC

ENDDEFINE

Utilizandoogerenciadordecaminhodedados
AamostraformaChgPaths.SCXusaogerenciadordecaminhodedadosparaalteraroscaminhosdastabelas
queforamadicionadossuaDataEnvironment.Paraexperimentarcomisso,simplesmentecopieo
CH10.DBC(etodasasmesas)paraumlocalalternativoemudaro SET_PATHcampono
cpiadoDataPathtabelaquepermanecenolocaloriginal.Onicocdigoquetenhasido
adicionadoaoDataEnvironmentdoformulrioanicalinhanaBeforeOpenTablesmtodo,como
segue:
NEWOBJECT('dpathmgr','dpathmgr.prg',NULL,ESTA)

queinstanciaoobjetogerentedecaminhodedadosepassaumarefernciaparao
DataEnvironment.
ComomostradonaFigura10.3,aconfiguraooriginalparacadatabelanaformaDataEnvironment
derivadadastabelaslocaisemC:.directrio\VFP60\CH10Figura10.4mostraoresultadode
executaroformulrioe,comoesperado,astabelasnoformulrioestosendoretiradosdeumcompletamente
diferenteunidadeeodiretrio.

334 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura10.3ConfiguraoparaastabelassqlclinoexemploformaDE
Figura10.4Oformulriodeexemplorunningnotequeastabelassoagoraretiradosdeum
origemdiferente

Captulo10:ClassesNonVisual 335

Comopossogerenciarformulriosebarrasdeferramentasnomeu
aplicativo?
Hprovavelmentetantasrespostasparaessapergunta,poishdesenvolvedoresqueescrevem
aplicativosusandooVisualFoxPro.Umapartefundamentaldequalquerestruturadeaplicativoomecanismo
paraogerenciamentodeformulriosetodososquadrosincluemum"FormulrioManager"dealgumtipo.o
mecanismoparaimplementarissovaidependerdoseuquadro,mashcertasbsica
tarefasquequalquerobjetodogerenciadordeveexecutar:
instanciaodeformas(sejaSCXouVCXcombase)
Acompanhamentodequeforma(equeinstnciadeumformulrio)atualmenteativo
Assegurarqueabarradeferramentasapropriadoestdisponvel
Adicionareremoverformulriosasuaprprialistadeformasactivascomoelessoinicializadosou
liberado

Claroqueexistemmuitasoutrasfunesquepodemserexecutadaspelogerenciadordeforma
(Porexemplo,adicionar/removeritenslistaJanelaou'cascata'formascomoelasso
inicializado),masosquatrolistadosacimaconstituemafuncionalidadebsicaqueaclassedeve
fornecer.
Afimdeimplementarumgestordeformulrio,necessriocriaruma"gestosubclasse',por
Ambasasformasebarrasdeferramentasparaqueocdigoadicionalparainteragircomogerentepodeser
isolado.Assecesseguintesapresentamocdigoparaestasclasseseparaumaclassegerentedeformulrio
queirlidarcomtodasastarefasbsicasdescritasacima.Estaclassefoiprojetadaparaser
instanciadocomoumobjeto"global",quenoanicamaneiradefazerisso,masamaissimplesde
ilustrar.Nstambmpoderiaterimplementadoosmtodosnecessrioscomopartedeumamaisampla
classe'applicationmanager'ouatmesmolidoucomainstanciaoereferenciamentodaforma
gerenteindirectamenteatravsdeumobjetodeaplicao.

Aclassedeformulriogerenciado
Formulriosdestinadosatrabalharcomogerentedeformulriopertencemaumaclasseespecial('xFrmStdManaged'em
GenForms.vcx).AlmdealgumcdigonecessrionoInit,Activaedestruirmtodos,
trspropriedadespersonalizadasedoismtodossonecessriosparaainteraocomoFormulriodeGestor
doseguintemodo:

Tabela10.3Propriedadespersonalizadasemtodosparaaclassedeformulriogerenciado

Nome PEM propsito


cInsName Propriedade nomedainstncia,atribudopelogerentedeformulrioquandoformulrio
inicializado
cTbrName Propriedade Nomedabarradeferramentasusadaporaforma(sehouver)
lOneInstance Propriedade Quando.T.impedeFormMgrdecriarvriasinstncias
aforma
ReportAction Mtodo MtodoFormActiondogerentedechamada
CheckFrmMgr Mtodo Retornaumarefernciadeobjetoparaogerentedeformulrio
336 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Aspropriedadespersonalizadas
OcInsNamepropriedadeusadaparaarmazenaronomedeinstnciaatribudopelaforma
gerente,aumaformaquandoinicializado.Aslojasmanagerformaambosonomedoformulrio
eonomedainstnciaatribudoemsuacoleointerna.Istoserveparamltiplos
instnciasdeumformulriofornecendoogerenteformamummeioparaidentificarinequivocamente
cadainstnciadeumaformaparticular.
OcTbrNamepreenchidaemtempodedesigncomonomedaclassedebarradeferramentas
associadocomoformulrio.Estapropriedadeserlidopelogestordeformulrioemtempodeexecuo
paradeterminarqual,sehouver,sonecessriasbarrasdeferramentaseparagarantirque,quandoumadeterminada
formulrioativado,abarradeferramentascorretoexibido.
OlOneInstancepropriedadepodeserdefinidaparaindicarparaogerenciadordeformaqueoformulrio
nicainstncianica.Quandoogerenteformulrioinstrudoparainstanciarumaformaque
jexisteemsuacoleo,elevaisimplesmenterestaurareativaroformulrioexistentese
essapropriedadedefinida.

ClassedeformulrioReportActionmtodo
Estemtodoforneceo"nicopontodecontato"entreaformaeogerenteformulrio.isto
podeserchamadoporqualquermtodoformulrioquepassaumparmetroqueindicaotipodeao
exigidoapartirdogerenciadordeformulrio(nonossoexemplo,issoseriatanto" ATIVAR"ou" destruir"):

LPARAMETERStcAction
loFrmMgrLOCAL

***ParmetroVerificar
IFVARTYPE(tcAction)#"C"
ASSERT.F.MENSAGEM"mtodoReportActiondoformulriodeveserchamadocomum
aonecessria"
RETORNA
FIMSE
***AgoralidarcomachamadaparaoformulrioGestor
COMThisForm
***ObterumarefernciaparaaformaGerente
loFrmMgr.CheckFrmMgr=()
IFVARTYPE(loFrmMgr)="O"
***DigaGestorformulrioparafazerestaaformaativa
loFrmMgr.FormAction(tcAction,.cInsName)
OUTRO
***NenhumaformaManager,paraquenadaespecialnecessrio
FIMSE
ENDWITH

Aresponsabilidadepelaverificaodaexistnciadogestorformapassadoparao
CheckFrmMgrmtodo,queretornaouarefernciadoobjetoapropriadoouum NULLvalor.Ese
umarefernciavlidadevolvida,omtodochamaogerenteFormActionmtodoe
passatantoaaonecessriaenomedainstnciadoformulrioparafornecerumainequvoca
derefernciaparaogerentedeformulrio.

Captulo10:ClassesNonVisual 337

ClassedeformulrioInitmtodo
AclassedeformulrioInitmtodoesperaparareceberumobjetodeparmetrocontendoumapropriedade
chamadocInsNameouumacadeiadecaracteresqueonomeaserarmazenadosuacInsNamepropriedade:

LPARAMETERStuParam
***Mtododeclasseesperaqueonomedainstnciaaserpassado
***Quercomo'cInsName'emumobjetodeparmetrooucomoumastring.
***Poderiarealmentetestaraqui,masoquediabos!Viverperigosamente!
***(Naverdade,otestedeveserfeitoemqualquerinstnciaousubclasse)
IFVARTYPE(tuParam)="O"
***LojapropriedadecInsNameparaformarpropriedade
ThisForm.cInsName=tuParam.cInsName
RETURN.T.
FIMSE
***Senoumobjeto,umastring?
IFVARTYPE(tuParam)="C"
***Lojaquepassadoparaformarpropriedade
ThisForm.cInsName=tuParam
RETURN.T.
OUTRO
***Temosalgomuitoerradoaqui!
ASSERT.F.
MENSAGEM"Aclassedeformulrioutilizadorequerqueumnomedeinstncia"+CHR(13)
+"Sergeradopelogerenteformulrioepassadoparaoformulrio."
+CHR(13)

+"FormaAbortarinicializao"
RETURN.T.
FIMSE

Istosignificaquequalquerinstnciadoformulrioquerequerparmetrosadicionaisdevem
extrair,apartirdesuaprprialistadeparmetros,ogerentedeformulriogeradonomedainstnciaepasse
quevoltaparaaclassedaseguinteforma:

LPARAMETERStoParams
***ExtraironomeInstnciadoobjetodeparmetro
IFVARTYPE(toParams)='O'EPEMSTATUS(toParams,'cInsName',5)
***NomedaInstnciapassarparaomtododaclassepai
DODEFAULT(toParams.cInsName)
IFtoParams.nParamCount>0
***Extraiaparmetrosadicionaisnomeadoscomo"tuParm1"atravsde"tuParmn"
FIMSE
OUTRO
***NoNameInstnciaespecificado
***Tomaroasmedidasapropriadasnomomento
FIMSE
***Faaoquemaisnecessrioaqui

Umdosprincipaisbenefciosdousodeumobjetodeparmetrocomoeste,comovimosnocaptulo2,
quepermiteautilizaodeparmetros'nomeados'quesimplificaocdigonecessrioparalera
passadosemvalores.

338 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ClassedeformulrioActivate,lanamentoeQueryUnloadmtodos
Almdisso,aclasseincluiduaslinhasdecdigoemambososActivateeSoltemtodospara
iniciaracomunicaocomogerentedeformulrio.Ocdigo,emcadacaso,chamaaReportAction
mtodoepassaonomedomtodoqueestemexecuo:
ThisForm.ReportAction(JUSTEXT(PROGRAM()))
DODEFAULT()

Finalmente,oQueryUnloadmtododestaclasseincluiumachamadaexplcitaparaolanamento
mtodoparagarantirquenoentantoousuriosaidoformulrio,oGerenciadordeformulrionotificado.
(IssoocorreporqueQueryUnloadnormalmenteignoraomtodoRelease.Oprximoevento
comumaamboslanamentoeQueryUnloaddestruir,eissomuitotardeparaoFormulrio
Gerente.)

Aclassebarradeferramentasgesto
Ousodebarrasdeferramentasemumaplicativodifcildeabordargenericamente.Sevocusa
barrasdeferramentasdiferentesparadiferentesformas,ouusarumanicabarradeferramentaseativar/desativaropescomo
necessrioafetarosdetalhesdoprojeto.Noentanto,qualquerabordagemquevoctoma,abarradeferramentas
terdeinteragircomseusformulrios.DesdeoFormulrioManagercontrolaasformas,parece
inteiramenterazovelqueelatambmdevecuidardasbarrasdeferramentas,quedeve,portanto,ser
concebidoemconformidade.Nossaclassebarradeferramentasabstratogesto("xTbrStdManaged"em
GenClass.vcx)foicriadocomosesegue.
Primeiro,abarradeferramentasControlBoxpropriedadefoidefinidacomo .F.Assegurandoassimqueumusurio
nopodeinadvertidamentefecharumabarradeferramentas(agoraaresponsabilidadedamanjedouraforma)eo
barradeferramentastemsidodadoumDataSessionprivada.Trsmtodospersonalizadosforamadicionadose
algumcdigoadicionadoaonativaActivatemtododaclassecomosesegue.

AbarradeferramentasclasseActivatemtodo
Aquestoabordadaaquigarantirquesemprequeumabarradeferramentasativado,eleirsincronizar
secomqualquerformaatualmenteativonatela.AbarradeferramentasActivatemtodochamado
semprequeabarradeferramentasmostrada,eumavezqueogestordeformairlidarcombarrasdeferramentaschamando
suasMostrareocultarmtodosquepodemosusarissoparachamaromtodoqueirsincronizaro
configuraesdabarradeferramentascomaformaatual:

***Sincronizarbarradeferramentasparaaformaativanomomento
***ActivatechamadodeShow(),demodosemprefogo
***QuandoFormManagerchamaoToolbar.Show()
This.SetDataSession()

AbarradeferramentasclasseSetDataSessionmtodo
Quandochamado,essemtodoirdefinaabarradeferramentasparaomesmodatasessioncomoomomento
formaativae,emseguida,chamarpersonalizadodabarradeferramentasSynchWithFormmtodo.Senenhumformulrioest
simplesmentechamaocostumesetDisabledmtodo:
ativo,ele

Captulo10:ClassesNonVisual 339

loFormLOCAL
***Obterrefernciaformaativa
IFTYPE("_SCREEN.ACTIVEFORM")="O"E!ISNULL(_SCREEN.ACTIVEFORM)
***ObterrefernciaparaActiveForm
loForm=_SCREEN.ACTIVEFORM
***ForaDatasessionmesmauma
This.DataSessionID=loForm.DataSessionID
***Mtododesincronizaodechamadasparalidarcomconfiguraesdabarradeferramentas
This.SynchWithForm(loForm)
OUTRO
***Noformulrio,paradesativarabarradeferramentas!
***Nota:Issonuncadeveacontecer,porqueogerentedeformulriodeve
***Sersemprelidarcomavisibilidadedabarradeferramentas
This.SetDisAbled()
FIMSE

AbarradeferramentasclasseSynchWithFormmtodo
Estesimplesmenteummtododemodeloparaserconcludaemumaclasseconcreta.Elechamadopelocostume
SetDataSessionmtodoquandoumaformaativaencontradoeondevocirialidarcomqualquer
detalhesdesincronizao(quepermitembotes/incapacitanteseassimpordiante).Elarecebe,comoparmetro,um
refernciaformaativanomomento.

AclassebarradeferramentassetDisabledmtodo
Estemtodoforneceocomportamentopadroparadesabilitartodososcontrolesnabarradeferramentasquandonenhum
formulrioencontrado.Istodevenuncamaisacontecerquandorodandosobcontrolegerentedeformulrio,maso
ativo
comportamentoprevistaqualquermaneira.

Aclassegerentedeformulrio
Aclassegerentedeformailustradaaquitemumainterfacepblicamuitosimples.Hapenastrs
mtodospersonalizados('DoForm','FormAction'e'ReleaseAll').ODoFormmtododestinasea
serchamadoexplicitamentenocdigoeresponsvelpelacriaodeformasesuasbarrasdeferramentasassociadas.
OFormActionmtodochamadoautomaticamenteapartirdoActivateedestruirmtodosna
gerenciadoclassedeformulriomaspoderiafacilmenteserestendidoparalidarcomoutrasaes,senecessrio.o
ReleaseAllmtodoprojetadoparaserchamadoapartirdoprocessodedesligamento,mastambmpoderiaserchamado
apartirdeumitemdemenu"FecharTodasasFormas'.Estaclassefoiprojetadaparafuncionaremconjuntocomo
Formaeaulasbarradeferramentasgerenciadosdescritosnasseesanteriores.Ocdigoreal
Managed
discutidosnasseesseguintes.

DefiniogerentedeformulrioeInitmtodo
Aclassedefineduasmatrizesequatropropriedades,osquaissoprotegidoscomosesegue:
340 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela10.4Propriedadespersonalizadasemtodosparaogerenteclassedeformulrioformulrio

Nome PEM propsito


aFmList matrizdepropriedade
AcoleoForms
aTbList matrizdepropriedade
Acoleodebarrasdeferramentas
nFmCount Propriedade NmerodeformascontidasnoCollectionForms
nTbCount Propriedade NmerodebarrasdeferramentascontidasnoCollectionbarrasdeferramentas
nFmIndex Propriedade ndiceparaoformulrioativonomomentonacoleoForms
nTbIndex Propriedade ndiceparaabarradeferramentasativanomomentonacoleoToolbar

OInitmtodosimplesmenteinicializaessaspropriedades:

DEFINECLASSxFrmMgrcomorelao
ARRAYPROTEGIDOaFmList[1,4],aTbList[1,3]
PROTEGIDOnFmIndex,nFmCount,nTbCount,nTbIndex

funoinit
Comisso
***Propriedadesinicializar
.aFmList="" FormulriodeRecolhade&&
.nFmCount=0 &&ManagedCondeForm
.nFmIndex=0 &&ndicenaColeodeformaatual
.aTbList="" &&ColeoToolbar
.nTbCount=0 &&ContagemToolbar
.nTBIndex=0 &&ndicenaColeodebarradeferramentasatual
ENDWITH
ENDFUNC

OgerenteformulrioDoFormmtodo
Estemtodopersonalizadoondeogerentedeformulriocriaformaseasbarrasdeferramentasassociadas.Isto
omaiormtodoniconaclasse,masrealmentenoseprestaapromoveradecomposio.
Omtodopermitequeattrsparmetrosaserempassados,masquenormalmenteesperam
passarumnicoobjetodeparmetro.Anicarazoparaestaestruturasimplificarchamandoo
mtododiretamenteapartirdeumitemdemenu.
Osprimeirosdoisparmetrossoutilizadosparaonomeeomtodoaserutilizadoparaainstanciao
Formato.AochamarumSCXapenasonomedoformulrioprecisaseraprovada,amenosquehajaadicional
parmetros,porqueovalorpadroparaosegundoser .F.queirinvocaro DO
FORMULRIOmecanismo.Seoformulrioestiveraserinstanciadoapartirdeumaclasse,osegundoparmetrodeve
sempresertransmitidoexplicitamentecomo .T.
Aprimeiracoisaqueestemtodofazverificarosparmetrosegerar(usando
SYS(2015))umacadeiadecaracteresvlidaqueserutilizadotantoparaarefernciadeobjetoparaaforma
esua"instncia"name:

****************************************************************
***XFrmMgr::DoForm(tcFmName,tlIsClass,tuParm1,tuParm2,tuParm3)
***Exposedmtodoparaexecutarumformulrio
***Provisopara3params,masnormalmenteseriadeesperarapenas1(como
***Umobjetodeparmetro)
****************************************************************

Captulo10:ClassesNonVisual 341

FUNODoForm(tcFmName,tlIsClass,tuParm1,tuParm2,tuParm3)
lnFormParamsLOCAIS,lcFmName,loFmRef,lnFmIdx,llRetVal,lnCnt
Comisso
***VerifiqueParmetros
IFVARTYPE(tcFmName)#"C"
***Nomedoformulrionofornecido!
ASSERT.F.MENSAGEM
"Nomedeumformulrio,ouumaclassedeformulrio,"+CHR(13)
+"DeveserpassadoaoformulrioGestorDoForm()"
RETURN.F.
FIMSE
***DefinirBandeiraderetorno
llRetVal=.T.
***Formnomeetipodevemestarpresentes,quantosformulrioparams?
lnFormParams=PCOUNT()2

Oprximopassoverificarseoformulriojfoiinstanciadoe,emcasoafirmativo,
seoformulriofoidefinidocomo"instncianica".Aformacomoogestorlidacomtais
formassimplesmentereativarainstnciaexistente,definaabarradeferramentas(sehouver)edesada:

***Verifiqueparaversetemosesteformulrioj?
.nFmIndex=.FmIdx(tcFmName)

***Setivermosisso,nonicainstncia
IF.nFmIndex>0

***Obterumarefernciaparaaformaeversepodemos
***Tervriasinstnciasdomesmo.
loFmRef=.aFmList[.nFmIndex,1]
COMloFmRef

***Verifiqueparaverseoformulriodeinstncianica
IF.lOneInstance
***Restaurarformulrioseminimizado
IF.WindowState>0
.WindowState =0
FIMSE

***Foraparaoincio
.AlwaysOnTop=.T.

***Ativaroformulrio
.Ativar()

***CancelarForaSubir
.AlwaysOnTop=.F.

***Classificarparaforabarrasdeferramentas,passeonomedabarradeferramentas
.SetToolBar(.aFmList[.nFmIndex,4])
(sehouver)
***ESairagora
RETURNllRetVal
FIMSE
ENDWITH
FIMSE

342 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Seoformulrionoestiverinstanciado,ouse,masnonicainstncia,emseguida,umanovaforma
necessrio.Primeirovamosgeraronomedoobjetoderefernciaeexemplo,eentoconstruirum
objetodeparmetroparaoformulrio:

***necessriaqualquerprimeiraexecuodoformulrio,ouumanovainstncia
***Criaroobjetodeparmetro
***Gerarumnomedeinstnciaerefernciadeobjeto
STORESYS(2015)PARAlcFmName,loFmRef

***Criaroobjetodeparmetro
oParams=NEWOBJECT("xParam","genclass.vcx")
COMoParams

***PrimeiroNomedaInstncia
.AddProperty('CInsName',lcFmName)

***Adicionarumacontagempropriedade
.AddProperty('NParamCount',lnFormParams)

***Adicionequaisquerparmetrosadicionaisaserempassados
paraaforma

IFlnFormParams>0
PARAlnCnt=1alnFormParams
lcPName="tuParm"+ALLTRIM(STR(lnCnt))
.AddProperty(LcPName,&lcPName)
PRXIMO

FIMSE
ENDWITH
Finalmente,podemoscriaroprprioformulrio.OtlIsClassparmetrousadoparadecidirseo
formulrionecessrioumSCXarquivoouumaclasseeparainstanciaraformaadequada:

***Instancieaforma
IFtlIsClass

***Criarcomoumaclasse
loFmRef=CREATEOBJECT(tcFmName,oParams)
OUTRO

***executadocomoumformulriousandoonomeeligadosclusulas
DOFORM(tcFmName)loFmRefNOMECOMoParamsLIGADOS
FIMSE

***Atualizaracoleocomosnovosdetalhesdoformulrio
IFVARTYPE(loFmRef)="O"

***YEPconseguiuumformulrio,paraincrementaracontagemformulrioepreencheracoleo
.nFmCount=+1.nFmCount
DIMENSO.aFmList[.nFmCount,4]
.aFmList[.nFmCount,1]=loFmRef &&ObjectReference
.aFmList[.nFmCount,2]=lcFmName &&NomedaInstncia
.aFmList[.nFmCount,3]=tcFmName &&NomedoFormulrio
.aFmList[.nFmCount,4]=UPPER(ALLTRIM(loFmRef.cTbrName))&&Toolbar
usar

***Faadestaaformaativa

Captulo10:ClassesNonVisual 343

.nFmIndex=.nFmCount

***Mostraronovoformulrio
loFmRef.Show()
OUTRO
***FormulriodeInicializaofalhouporalgummotivo
llRetVal=.F.
FIMSE

Depoisdecriaraformaqueverificarparagarantirqueoformulriorealmentefezsecriou,edepois
quepreencheracolecodeformulrioscomasinformaesrelevantes.Altimacoisaafazer
lidarcomexibiodasbarrasdeferramentas,oquefeitochamandooDoToolBarmtodo:

***Finalmenteresolveraexignciabarradeferramentas
IFllRetVal
.DoToolBar(.aFmList[.nFmCount,4])
FIMSE
RETURNllRetVal
ENDWITH
ENDFUNC

OgerenteformulrioDoToolbarmtodo
Estemtodochamadosomentequandoumnovoformulrio,ouumanovainstnciadeumformulrio,criado.Est
funoadeatualizaracoleoToolbarseonovoformulriorequerumabarradeferramentas.Issopode
envolvemincrementandoacontagemdeumabarradeferramentasexistenteoucriarumanovabarradeferramentas.O
mtodomanipulaambasascontingncias:
mesmo
****************************************************************
***XFrmMgr::DoToolBar(tcTbName)
***Mtodoparacriarprotegidooudefinirabarradeferramentaschamadaativa
***Chamadoquandoacriaodeumformulrio
****************************************************************
FunoprotegidaDoToolBar(tcTbName)
Comisso
lnTbIdxLOCAL

***Serqueprecisamosdeumabarradeferramentasemtudo?
IFEMPTY(tcTbName)
***NenhumabarradeferramentasObrigatrio,escondertudo
.SetToolBar("")
RETORNA
FIMSE

***Verifiqueparaversetemosabarradeferramentasj
lnTbIdx=.TbIdx(tcTbName)
IFlnTbIdx>0

***Nsjtemosumpresente,entoativlo
***Eincrementarasuacontraporum
.aTbList[lnTbIdx,2]=.aTbList[lnTbIdx,2]+1

OUTRO
***Nsprecisamoscriloeadicionlocoleo

344 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

.nTbCount=+1.nTbCount
DIMENSO.aTbList[.nTBCount,3]
.aTbList[.nTbCount,1]=CREATEOBJECT(tcTbName) &&ObjetoRef
.aTbList[.nTbCount,2]=1 &&ToolbarContador
.aTbList[.nTbCount,3]=UPPER(ALLTRIM(tcTbName))&&NomeToolbar
FIMSE

***Verifiqueabarradeferramentasaativa
.nTbIndex=.nTbCount
.SetToolBar(.aTbList[.nTbCount,3])
ENDWITH
ENDFUNC

EstemtodochamaoSetToolBarmtodoparaclassificaraexibiodebarrasdeferramentasepasses
onomedabarradeferramentasnecessrias(sehouverum)ouumacadeiavazia.Esteltimofazcomqueo
SetToolBarmtodoparaocultartodasasbarrasdeferramentasexistentes.

OgerenteformulrioFormActionmtodo
Estemtodochamadoapartirdeumformulrioparasolicitaraoapartirdogerenciadordeformulrio.doisparmetros
soesperados,aprimeiraaaonecessria,easegundaonomedainstnciadoformulrio
queestsolicitandoaao.Aclassedeformulriogerenciadochamaestemtodosemprequeumformulrio
ativadoouliberadoparanotificarogerentedeumamudananoestatuto,passandoonomedo
Mtodocomooprimeiroparmetrodechamada.Aaotomadadependedachamadaeadicional
aespoderiamserfacilmenteprevistaaqui:

****************************************************************
***XFrmMgr::FormAction(tcAction,tcInsName)
***MtodoExposeddetratamentodospedidosdeformulrio
****************************************************************
FUNOFormAction(tcAction,tcInsName)
Comisso
lnFmIndexLOCAL
***Serquetemosestaforma?
lnFmIndex =0
lnFmIndex =.FmIdx(TcInsName)

***Senstlo
IFlnFmIndex>0
DOCASO

MAISCULAS(tcAction)="ativar"
***Faadestaaformaativa
.nFmIndex=lnFmIndex
.SetToolBar(.aFmList[.nFmIndex,4])

MAISCULAS(tcAction)="Release"
***Limparoformulriodacoleo
.nFmIndex=lnFmIndex
.ClearForm(.aFmList[.nFmIndex,1])

DEOUTRAFORMA
ASSERT.F.
MENSAGEM"Ao:"+tcAction+"passouparaFormulrioDom"
+CHR(13)+"Masnoreconhecido"
RETURN.F.
Captulo10:ClassesNonVisual 345

ENDCASE
OUTRO
***FormulrionofoiiniciadoporFormaGestor
***Nohnadaafazersobreisso
FIMSE
RETORNA
ENDWITH
ENDFUNC

OgerenteformulrioReleaseAllmtodo
Comosugereonome,oltimodosprincipaismtodossimplesmenteliberatodasasformasebarrasdeferramentas
queogerentedeformulriotememsuascolees.Issonormalmentechamadoapartirdoprocessodedesligamento
mastambmpodeserutilizadoparaproporcionarumaopo"Limpartodos"nummenu:
****************************************************************
***XFrmMgr::ReleaseAll
***MtodoExposedparaliberarTODASasformasnapossedoformulrioGestor
***Usadoaofecharumaplicativocomformasaindaemaberto
****************************************************************
ReleaseAllFUNO
COMISSO
LOCALloFmRef,loTbRef
.nFmIndex=.nFmCount
***Liberartodasasformas
Fazerenquanto.nFmIndex>0
***Verifiqueaindatemosumobjetodeformulrio
loFmRef=.aFmList[.nFmIndex,1]

IFVARTYPE(loFmRef)="O"
***Liberlo
loFmRef.Release()
FIMSE
.nFmIndex=.nFmIndex1
ENDDO

***PrximainicializaocoleoForms
DIMENSO.aFmList[1,4]
.nFmCount=0
.nFmIndex=0
.aFmList=""

***Soltetodasasbarras
.nTbIndex=.nTbCount
Fazerenquanto.nTbIndex>0
***Verifiqueaindatemosumobjetobarradeferramentas
loTbRef=.aTbList[.nTbIndex,1]
IFVARTYPE(loTbRef)="O"
***Liberlo
loTbRef.Release()
FIMSE
.nTbIndex=.nTbIndex1
ENDDO
***ToolbarColeoprximainicializao
DIMENSO.aTbList[1,3]
.nTbCount=0
.nTbIndex=0

346 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

.aTbList=""
RETURN.T.
ENDWITH
ENDFUNC

OgerentedeformaShowFormseHideFormsmtodos
Estesdoismtodospersonalizadosadicionaisestoexpostosnogerenciadordeformaaforneceruma
mecanismoparaesconderereexibirtodasasformasvisveis.Issotilsevocestiverexecutandoum
relatriodeprvisualizaoenodesejaquaisquerformasexistentesparainterferircomavisibilidadedo
relatrio.Osmtodossoessencialmenteosmesmoseloopatravsdadefiniodacoleodeformulrio
propriedadevisveldetodasasformas.OhidemtodoacabachamandoSetToolBarcomumvazio
cadeiapararemoverasbarrasdeferramentasexistentes.OmtodomostrachamaoMostrarmtododaltima
formarqueestavaativopararestaurloesuabarradeferramentasassociada:

****************************************************************
***XFrmMgr::HideForms
***MtodoExposedparaescondertodasasformasdetidospeloFormulrioGestor
***Utilizadoduranteaexecuovisualizaodeimpressocommltiplasformasabertas
****************************************************************
HideFormsFUNO
Comisso
LOCALnndice,loFmRef
nIndex=.nFmCount

***EsconderTodasasformas
Fazerenquantonndice>0
***Verifiqueaindatemosumobjetodeformulrio
loFmRef=.aFmList[nndice,1]
IFVARTYPE(loFmRef)="O"
***Esconde
loFmRef.Visible=.F.
FIMSE
nIndex=nIndex1
ENDDO
***Escondertodosbarrasdeferramentas
.SetToolBar("")
ENDWITH
ENDFUNC

****************************************************************
***XFrmMgr::ShowForms
***MtodoexpostoparamostrartodasasformasdetidospeloFormulrioGestor
***Usadoaofecharvisualizaodeimpressocommltiplasformasabertas
****************************************************************
ShowFormsFUNO
Comisso
LOCALnndice,loFmRef
nIndex=0
***Mostrartodasasformas
Fazerenquantonndice<.nFmCount
nIndex=nIndex+1
***Verifiqueaindatemosumobjetodeformulrio
loFmRef=.aFmList[nndice,1]
IFVARTYPE(loFmRef)="O"

Captulo10:ClassesNonVisual 347

***Mostre
loFmRef.Visible=.T.
FIMSE
ENDDO

***Restauraraltimaformaativa
.aFmList[.nFmIndex,1].Show()
ENDWITH
ENDFUNC

OgerenteformulrioClearFormmtodo
Estemtodopersonalizadoprotegidaremoveumaformaesuabarradeferramentasassociadaapartirdasformase
barrasdeferramentascolees.ElechamadoapartirdoFormActionmtodoquandoumformulrionotificao
gerentequeeleestsendoliberado:
****************************************************************
***XFrmMgr::ClearForm(toFmRef)
***Mtodoprotegidoremoverumformulriodacoleo
****************************************************************
PROTEGIDOClearFormFUNO(toFmRef)
Comisso

***Cancelarsenoumobjeto
Seotipo('toFmRef')#"O"ouISNULL(toFmRef)
RETURN.F.
FIMSE

***VerifiqueParaumabarradeferramentasassociada
lcTbName=.aFmList[.nFmIndex,4]
ESE!VAZIO(lcTbName)
.ClearToolBar(LcTbName)
FIMSE

***Limparoformulriodecoletadeentrada
.nFmCount=.nFmCount1
IF.nFmCount<1

***ReInicializaramatrizseestefoioltimoformulrio
DIMENSO.aFmList[1,4]
.nFmCount=0
.nFmIndex=0
.aFmList =""
OUTRO

***ApenasReDimensionlo
=ADEL(.aFmList,.nFmIndex)
FIMSE
DIMENSO.aFmList[.nFmCount,4]

***Redefinirondice=contagemdeforma
***(Aactivaoseguinteformulrioirreconfigurlodequalquermaneira)
.nFmIndex=.nFmCount
ENDWITH
ENDFUNC

348 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OgerenteformulrioFmIdxmtodo
Estemtodopersonalizadoprotegidochamadocomqualquerumarefernciadeobjetoaumaformaouainstncia
nomedeumformulrioeprocuraacoleoformadeencontraredevolverondicecorretoparaa
coletaparaaquelaforma:
****************************************************************
***XFrmMgr::FmIdx(tuFmRef)
***Digitalizaracolecodeformulriosparaarefernciaquepode
***Serumarefernciadeobjetoaumformulrioouumnomedeinstncia
***Retornaonmerodalinha,seforencontrado
****************************************************************
FunoprotegidaFmIdx(tuFmRef)
Comisso
LOCALlnElem,lnIdx
lnIdx=0
ESE!ISNULL(tuFmRef)E.nFmCount>0
ConjuntoexatoON
***Digitalizaramatriz
IFTYPE("tuFmRef")="O"
lnElem=ASCAN(.aFmList,tuFmRef.cInsName)
OUTRO
lnElem=ASCAN(.aFmList,tuFmRef)
FIMSE
***Calculeonmerodalinha
IFlnElem>0
lnIdx=ASUBSCRIPT(.aFmList,lnElem,1)
FIMSE
ConjuntoexatoOFF
FIMSE
RETURNlnIdx
ENDWITH
ENDFUNC

OgerenteformulrioTbIdxmtodo
EstemtodopersonalizadoprotegidaexecutaamesmafunoparabarrasdeferramentascomoofmIdxmtodo
fazparaformulrios.Eleretornaonmerodendicedeumabarradeferramentasnacoleobarradeferramentas.Contudo,
porqueestemtodochamadosemprenocontextodeumaformaconhecida,semprequeaespera
nomedabarradeferramentasparaserpassadocomoumparmetro.(Onomedabarraarmazenadonaquarta
colunadacoleoformulrio.)

****************************************************************
***XFrmMgr::TbIdx(tcTbName)
***Digitalizaodacoleodebarradeferramentasparaarefernciaqueir
***Seronomedabarradeferramentasnecessrias
***Retornaonmerodalinha,seforencontrado
****************************************************************
FunoprotegidaTbIdx(tcTbName)
Comisso
LOCALlnElem,lnIdx
lnIdx=0
***Verifiquetemosumnome,epelomenosumabarradeferramentasregistrado
ESE!VAZIO(tcTbName)E.nTbCount>0
ConjuntoexatoON
Captulo10:ClassesNonVisual 349

***Digitalizaramatriz
lnElem=ASCAN(.aTbList,tcTbName)
***Calculeonmerodalinha
IFlnElem>0
lnIdx=ASUBSCRIPT(.aTbList,lnElem,1)
FIMSE
ConjuntoexatoOFF
FIMSE
***RetornaronmeroRowrelevante
RETURNlnIdx
ENDWITH
ENDFUNC

OgerenteformulrioSetToolbarmtodo
Estemtodopersonalizadoprotegidoresponsvelporcontrolaraexibiodebarrasdeferramentasno
tela.Eleesperaparareceberonomedeumabarradeferramentasouumacadeiavazia,comoumparmetro.o
mtodosimplesmentecirculaacoleobarradeferramentaseescondetodasasbarrasdeferramentas,excetoo
Especificadas.Senadaforespecificado,todasasbarrasdeferramentasestoescondidos:

****************************************************************
***XFrmMgr::SetToolBar(tcTbrName)
***Mtodoprotegidoparafazerabarradeferramentaschamadaativa
***Passandoumacadeiavaziaescondetodasasbarrasdeferramentas
***Chamadoquandoaativaodeumformulrio
****************************************************************
PROTEGIDOSetToolBarFUNO(tcTbName)
Comisso
lnCntLOCAL
***Loopatravsdacoleobarradeferramentaseescondertudo,masonecessrio
PARAlnCnt=1a.nTBCount
DOCASO

CASOVAZIO(.aTbList[lnCnt,3])
***NohbarrasdeferramentasdefinidoNofazernada
***Necessriasparaevitarcomparandoparaumacadeiavazia!

CASOVAZIO(tcTbName)
***NoToolbarnecessria,paraescondlo
.aTbList[lnCnt,1].hide()

CASEtcTbName==.aTbList[lnCnt,3]
***Queremosumpresente,entomostrlo
.aTbList[lnCnt,1].Show()

DEOUTRAFORMA
***Noqueroumpresente,entoescondlo
.aTbList[lnCnt,1].hide()
ENDCASE
PRXIMO
ENDWITH
ENDFUNC

350 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OgerenteformulrioClearToolbarmtodo
EstemtodopersonalizadoprotegidocorrespondeaoClearFormmtodoeremoveumabarradeferramentas
dacoleodabarradeferramentasdogerenteformulrio.Noentanto,porqueasbarrasdeferramentassoapenasinstanciado
umavez,aremoodeumformulrioquetemumabarradeferramentasassociadanosignificanecessariamentequeabarrade
deveserliberado.Outrasformaspodemaindaexigir.Estemtodolidacomambasassituaes,
ferramentas
apenasdiminuindoocontador(realizadanacolunadoisdacoleobarradeferramentas),amenosquecai
abaixo1.Nessasituao,abarradeferramentasliberadoetodaalinhaexcludado
coleo:

****************************************************************
***XFrmMgr::ClearToolBar(tcTbrName)
***Mtodoprotegidoparafazerabarradeferramentaschamadaativa
***Passandoumacadeiavaziaescondetodasasbarrasdeferramentas
***Chamadoquandoaativaodeumformulrio
****************************************************************
FunoprotegidaClearToolBar(tcTbName)
Comisso
lnIdxLOCAL
***EncontrealinhanacoleoToolbar
lnIdx=0
lnIdx=.TbIdx(tcTbName)

IFlnIdx=0
***Estabarradeferramentasnoestregistadoqualquermaneira
RETORNA
FIMSE

***Diminuirocontador
.aTbList[lnIdx,2]=.aTbList[lnIdx,2]1
SE.aTbList[lnIdx,2]=0
***Nenhumaoutrareferncia,assimliberarabarradeferramentas
.aTbList[lnIdx,1].Release()
.nTbCount=.nTbCount1

IF.nTbCount<1
***ReInicializaramatrizseestefoioltimo
DIMENSO.aTbList[1,3]
.nTbCount=0
.nTbIndex=0
.aTbList =""
OUTRO
***ApenasReDimensionlo
=ADEL(.aTbList,lnIdx)
DIMENSO.aTbList[.nTbCount,3]
FIMSE
FIMSE
ENDWITH
ENDFUNC

Utilizandoogerenciadordeforma(Exemplo:FmgrTest.prg )
Talcomoreferidonaintroduodestaseo,aclassegerentedeformulriofoiconcebidoparaser
instanciadocomoumobjetoglobal.Istofoifeitoparaevitaranecessidadedeogestor
passandoumarefernciaasimesmoacadaformulriocriadocomtodasasarmadilhaspotenciaisparaolixo

Captulo10:ClassesNonVisual 351

coleoqueissoimplicaria.Oresultadoqueaclassedeformulriogerenciadotemquesabercomo
verificarapresenadogerenciadordeformaeestatratadapelofactodeclassepela
CheckFrmMgrmtodo.Nsaceitamosqueissopodeservistocomoocaminho"errado"defazerascoisas,mas
consideramque"maissimplesmelhor"nestecaso.nicaadoptarummtododiferenteseria
exigirumaalteraoparaumnicomtodonaclassedeformulrioenssentimosqueosbenefciosdasimplicidade
compensamaperdadeflexibilidadeparaestetipodeobjetogerente.
Oprogramadeexemploinstanciaumobjetodogerenciadordeformaeusaoparacriartrsparesde
formas.CadaparconsistenamesmaformadefinidatantocomoumSCXecomosendodeclasse.Umpartem
nenhumabarradeferramentas,umparrequerumabarradeferramentas'boto'eoterceirousaumabarradeferramentas
cdigodebaseaseguinte:
'caixadecombinao".o

SETCLASSLIBTOgenclass,fmgrtestADITIVO
LIBERTAOgoFrmMgr
goFrmMgrPBLICO

***CriaroobjetodeformulrioGestor
goFrmMgr=NewObject("xFrmMgr','formmgr.prg',NULL)

***AgoraexecutealgumasformastantocomoclasseeSCX
***ComeSembarrasdeferramentas.
***NotesequeasformasbaseadasemclasseexigemumT.lgico.comoparmetrodois
goFrmMgr.Doform('btnbarfm')
goFrmMgr.Doform('btnbarfm',.t.)

goFrmMgr.Doform('cbobarfm')
goFrmMgr.Doform('cbobarfm',.t.)

goFrmMgr.Doform('notbarfm')
goFrmMgr.Doform('notbarfm',.t.)

Ocdigorealtambmcambaleiaasformasnateladeformaaapresentaraaparncia
ilustradonaFigura10.5abaixo:
Figura10.5executandomltiplasformassoboFormulrioGestor

Comodiferentesformasobterofocoelessotrazidosparaotopoesuabarradeferramentasassociado
ativado,comomostramasseguintesilustraes:

352 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura10.6formaSCXcombarradeferramentasassociada

Figura10.7formaVCXcombarradeferramentasassociada

OcomportamentodoformulriotambmpodesertestadopelotelefonedogerenteformulrioHideFormse
ShowFormsmtodosdiretamente:

GoFrmMgr.HideForms()e goFrmMgr.ShowForms()

Osformulriostambmpodemserliberados,clicandoemseubotodefecharereinstanciadocomonecessrio.
Paraliberartodasasformas,chameomtodoReleaseAll()dogestordeformulrio:

goFrmMgr.ReleaseAll()

Comopossocontrolaremanipularerros?
ProvavelmenteotratamentomaisabrangentedaestratgiademanipulaodeerrosnoVisualFoxPro
ExcelenteartigodeDougHenning,"TratamentodeerrosnoVisualFoxPro,"queestdisponvelpara
baixar,completocomcdigodeexemplo,apartirdeseuwebsiteemwww.stonefield.com.Hpouca
apontaraquiemreiterandooqueDougdiz,eomelhorconselhoquepodemosoferecerquesevocprecisadeum
completosistemadetratamentodeerros,irbuscaressepapeleestudla.
Entooquepodemosofereceraquiemvezdisso?Bem,nssuspeitamosque,naprtica,amaioriadasaplicaes
(aocontrriodeferramentasouutilitrios)naverdade,notentar,oumesmonecessidade,paralidarcomerros.Isto
porqueamaiorpartedoserrosquesurjamemumaaplicaosoprovavelmenteerrosdecdigo(isto,
deerrodelgica),comerrosdeconsistnciadedadosexecutandoumsegundoprximo.Asprioridadesnestes
situaesso,portanto,paraprotegeraintegridadedosdados,informarousurioquealgosaiu
erradoefecharoaplicativosegraciosamenteecomsegurana.Oquerealmenteprecisamosparaeste
Captulo10:ClassesNonVisual 353

situaoalgoquevaigravaroqueaconteceueforneceromximodeinformaes
possvelsobreoestadodosistemaquandooerroocorreu.
DesdeVisualFoxProumbancodedados,noparecerazovelpensarqueestetipode
informaesdevemserregistradasemumatabela,demodoqueainformaopoderiaserusadaparagerar
relatrios,correesderegistroeassimpordiante.Oqueestamosrealmenteafalar,portanto,'agravaodeerro'
emvezde"manipulaodeerro!'Claro,aindatemosqueconfiaremmanipuladordeerrodoVisualFoxPropara
nosdizerquandoalgoesterrado.NemtodoerroqueVisualFoxProdetectavontade
necessitamdeencerraroaplicativoparaqueaindahalgumamanipulaoelementosobretudo
emboratalveznotantoquantosepoderiapensar.

ClassificandoerrosVisualFoxPro
manipuladordeerropadrodoVisualFoxProforneceparamaisde700errosreconhecidos,maselesnoso
realmentecategorizadosemqualquerformatil.Paratentarefazermelhorusodoserrospadro
desdequetenhamoscriadoumatabela('errmsg.dbf')contendooerropadrotudoVisualFoxPro
nmeroseotextoassociado.Incluemsenestatabelasotrscamposadicionaispara
"Categoria","Tipo"e"Ao"paranosdaraseguinteestrutura:

ErrNum N( 4)
ERRCAT C(20)
ERRTYPE C(20)
ERRACTION C(10)
ERRTEXT C(200)

Classificamososerrosemumadascincocategoriaslistadasabaixo.
errosdeprojetoTime:Estassocoisasquespodemocorrerduranteodesenvolvimentodeum
aplicaoequeseria,portanto,noesperarencontraremqualqueroutromomento.
Estessoprincipalmentequercompilaoou'emuso'erros.Exemplo:Erro1169:"Projecto
arquivosomenteleitura."
ErrosDesenvolvedor:Itensnestacategoriasurgiratravsdeerrosnocdigooulgica.
Muitosdestesserpegoemtesteseelessurgemdedescuido,fadiga,
insuficientementecdigodefensivaousuposiesinvlidasporpartedodesenvolvedor.
Corrigindoesseserrosinvariavelmenteexigiralteraesaocdigofonte.Exemplo:Erro
1127:"VocdeveusarumaexpressolgicacomumFORouclusulaWHILE."
ErrosRunTime:Estacategoriaincluicoisasqueseriamdifceisdeapanharnoprojeto
tempoequenopodemesmoserpegonoteste.Amaioriadestesestorelacionadoscomafalta
ouinvlidoarquivosouaoperaesquepodemtersucessoemumambientededesenvolvimento,mas
quepodefalharemtempodeexecuo.Talcomoacontececomerrosdedesenvolvedor,correesnormalmente
aocdigofonte.Exemplo:Erro109"Gravarestemusoporoutrousurio."
requeremmudanas
Errosdosistema:Estassocoisasquenormalmentenosocausadasdiretamentepeloserrosna
cdigofonte,massurgemdevidoaoambientedosistemaouproblemasderecursos.Amaioria
destesspoderealmentesertratadoporencerraroaplicativo.Exemplo:Erro
1986"memriaGDIestprximodeumoumaisjanelasetentenovamentebaixa,."

354 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

errosdeutilizador:Somente11dos700errospadropoderiarealmenteseratribudaaeste
categoria.Estessoerrosquenormalmenteesperariaparaocorrersomentecomooresultado
dealgumaaodousurio.Amaioriadevesercapazderesoluosemanecessidadedefechar
aaplicaoparabaixo,emborasejaimprovvelqueumasoluogenricapodeserconcebido
paralidarcomeles.Exemplo:Erro1523"execuofoicanceladapelousurio."
Noentanto,oproblemaquealgunserrospodemtambmsurgirporrazesdiferentes.Para
exemploErro1152"Nopossvelacessaratabelaselecionada."Podesercausadopelarede
conexosendoperdido(um"sistemadeerro"),mastambmporqueatabelausadacomoorowsourceparauma
combinaooucaixadelistafoifechadademasiadocedo(um"desenvolvedor"ouum"tempodeexecuoerro').
Paracadaerro,nsadicionamosumaaopadroqueseriaoufecharatoda
aplicao,abortaroprocessoatualoupararesolveroerro.Notesequeestassoluesnoso,
meramenteumaindicaodagravidadeesperadadoerro!
OtextodamensagemdeerronestatabelasimplesmenteamensagempadroqueVisualFoxPro
gera.Estessoraramente'userfriendly'egostaramosdesugerirasubstituiodopadro
mensagenscomalgomaisapropriadoparaasuasituao.(Masistodefinitivamenteuma
"Exerccioparaoleitor.')
Finalmente,semprequepossvel,nsatribumosacadaerro'Tipo'relacionadascomasituaoemquese
maisprovvelquesejaocorrer,porexemplo'SQL,''Print,''Index'ou'Tabela.'Apenascercademetadedo
errospodemseratribudos,destaforma,enemtodasessasatribuiessonecessariamenteexclusivo,
massentimosqueeraumexercciotil,noentanto.

Errosderegistro(Exemplo:TrackErr.prg,ErrorLog.prg )
Htrsquestesaabordarduranteacriaodeumprogramadeerroderegistro.Emprimeirolugar,oquedeveser
logado?Arespostacurta"tantoquantopossvel"!fcildeignorarsuprflua
informaesemumerroderegistro,mas,geralmente,muitodifcil,senoimpossvel,pararecriaro
condiesexactasemqueocorreuumerro.Quantomaisinformaesvocpodereunirsobre
oqueaconteceu,nomomentoemqueissoacontece,omaisfcilserresolveroproblema.
Emsegundolugar,ondedeveologserarmazenado?Nohumarespostagenricaaestapergunta,mas
asoluoquepreferemadeincluirumaentradanoarquivoINIdoaplicativo.Estedevedefinir
onomeeolocaldologdeerroesprecisaserlidoumavezquandoo
aplicaoiniciada(consulteotpicoGerenciadordearquivosINI,nestecaptulo,paramaisdetalhes).Oresultado
podemserarmazenadosemqualquerumavarivelglobalouaumapropriedadedoobjectodeaplicao,parausoposterior.
Umdosprincipaisbenefciosdefazlodestamaneiraqueelepermitequecadausurioconfigurarumlogdeerrolocalse
necessrio.(Especialmentetilparadesenvolvedoresetestadores),semcomprometerasuacapacidadede
manterumregistodeerroscentralizadaparaaaplicaocomoumtodo.
Aterceiraquestoaformacomodevelogdeerrosercriado?Existemduasopesdebasee
cadaumtemalgummrito.Nspoderamosusarumamesaeescreverumregistroparacadaerrodiretamenteaele.o
benefciobviodessaabordagemqueelaprestaseaanliseegeraoderelatriosedetalhesde
soluesecorrecespodemaindaserarmazenadonamesmatabela.Oproblemaque,especialmenteemumgrande
sistema,hsempreoperigodecorreremconflitosaotentaracessaratabela.
Cadaregistroser,necessariamente,envolvemumagrandequantidadededadosealtimacoisaquevocquer
acontecerquandotentargravarumerrolevantarumaoutra!
Alternativamente,poderiasimplesmentegerarumarquivodetextocomosdetalhesdecadaerroe,emum
mesa,gravarumresumodoqueoerro,juntamentecomumarefernciaparaoarquivodesada.Notodo

Captulo10:ClassesNonVisual 355

nsgostamosdestaabordagemmelhorporqueomaisflexvelemantmotamanhodologdeerro
tabelaaummnimo.Umaidiaparticularmentepurovimosfoiquesemprequeumarquivodeerro
foigerado,foiautomaticamenteporemailparaaEquipeLderdeDesenvolvimento.
Nossaclassedelogdeerro,quedefinidacomoumaclassenovisual('ErrorLog.prg'),adotao
segundaabordagemeusaumatabelaparagravarinformaesderesumoeumtextogeradoautomaticamente
arquivoparagravarosdetalhesdoestadodeerroedosistema.Notequensnofizeramnenhumatentativadelidarcom
asituaoemqueumerronasrotinasdetratamentodeerroocorre.Nosestalidarcomtais
umerrodeumproblemacomplexoemsimesmo,muitoalmdombitodestaclasseparticular
cobrir.Asseesseguintesabordamosprincipaiselementosdaclasse.

Atabela"errorlog"
Estatabelausadapelaclassedelogdeerroparagravarinformaesderesumosobrecadaerro
queocorre,etemaseguinteestrutura:

LOGSID nmerointeiro
4 &&ErroNmerodeIdentificao
LOGDTIME Datahora 8 &&Dedata/hora
LOGERRNUM nmerointeiro
4 &&VFPnmerodoerro
LOGERRPROG Character60 Programa&&noqualerroocorreu
LOGERRLINE nmerointeiro
4 &&LineNumbernoqualerroocorreu
LOGERRUSER Character20 &&IDdousurio
LOGERRTXT Character60 &&PathLogdeerros/FileName

Aidentificaonicageradoparacadaerroqueregistradonestatabela.EsteIDentousado
comopartedonomedoarquivodetextoqueregistraosdetalhesdoerroparafornecerummeiofcil
derefernciacruzada.

Usandoaclassedeerrologging(Exemplo:Errorlog.prg)
EstaclassebaseadonoFoxPro"VisualFormsetclassebase"paraqueelepossaserdadaumaparticular
datasession.(OFormCounteVisiblepropriedadesforamprotegidosedefinira 0,e .F.,
respectivamente).Quandoaclasseinstanciado,eleabreastabelasmensagemdelogdeerroeerro
(Semtampo)nasuadatasessionprivadaedeterminaocaminhoparaoqualoarquivodelog
deveserescritoeonomedoaplicativo.Nsnormalmenteinstanciaroregistrodeerros
objetoemaplicaostartupeatribuirlheumarefernciamundial:

LIBERTAOgoErrorLog
goErrorLogPBLICO
goErrorLog=NEWOBJECT('xErrLog','errorlog.prg',NULL)

Aclassetemapenasummtodopersonalizadoexpostos,o"LogErrormtodo"edoisexpostos
propriedadespersonalizadas,cNextActionecUserMsg.
VisualFoxPro ERRORONconfigurao,ento,apontouparaumprogramadeinvlucrosimplesqueir
receberaDataSession,Programaeonmerodalinhaemqueoerroocorreuechamara
LogErrormtodo,passandoosparmetrospormeio,comoeste:

NOERRODOTrackErrCOMSET("DATASESSION"),PROGRAM(),NUM_LINHA()

356 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Oobjetodeerrologginginsereumregistronatabeladelogdeerroeescreveodetalhada
informaesemumarquivodetexto.Emseguida,elepreencheassuaspropriedadesexpostascomamensagemenoprximo
aodatabelamensagemdeerropersonalizada.Oprogramainvlucro,emseguida,lestes
propriedadeseaaoapropriadasejatomada.Avantagemdessaabordagemqueelesepara
oprocessodelogdodecomunicaodiretacomousurioepermitenosutilizaro
classedelogdeerroemsituaesemquesimplesmenteexibirumacaixademensagemdiretamentenoseria
apropriado.
OTrackErr.prgprogramanormalmentealgocomoisto:

**********************************************************************
*Programa :TrackErr.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:programachamadopeloONerronologDetalhesdoerro
* :ONERRORDOTrackErrCOMSET("DATASESSION"),PROGRAM(),
NUM_LINHA()
**********************************************************************
LPARAMETERStnDSID,tcProgram,tnLineNo
lcNextActionLOCAL,lcUserMsg

IFVARTYPE(goErrorLog)="O"
***Mtododeregistrodechamadas
goErrorLog.LogError(tnDSID,tcProgram,tnLineNo)
***Agoraverificarosresultados
lcNextAction=goErrorLog.cNextAction &&PrximaAonecessria
lcUserMsg =goErrorLog.cUserMsg &&Mesagetextodousurio

***Tomaroasmedidasapropriadas
***Normalmente,issoseriaparaexibirumamensagemparaousurio
***EdequalquerReTryoufechar
MESSAGEBOX(lcUserMsg,16,"Errodeaplicativo")
OUTRO
MESSAGEBOX("Registrodeerrosnoestdisponvel",16,"Errodesistema")
FIMSE

Oarquivodetextocriadoconsisteemseesdecabealhoeseisdetalhecomosesegue:

*********NOVOERRO:12/22/9909:50:44*******************
Erro:1925:UnknownTXTOUTPUTmembro.
nalinha29emFRMCHGPATHS.SETFORM
CdigoFonte:ThisForm.txtOutPut.Value=""

Doutilizador
:TLCcasa#andykr
================================================================
Categoria:Desenvolvedor
Digitar:
Aao: endproc
****************************************************************
[1]***despejodememria:amemriaLISTA
[2]***despejodedados
[3]***cadeiadechamada
[4]***contedodareadetransferncia
[5]***despejoObjeto:LISTADEOBJETOS
[6]***sessodedadosstatus:statusdalista
Captulo10:ClassesNonVisual 357

OprogramaTestErr.prg,includonocdigodeamostraparaestecaptulo,configuraodeerros
registrandoobjetoe,emseguida,geraumerro.

Comopossosimplificaraobtenodemensagensparameus
usurios?
VisualFoxProfornecenoscomdoisconstrudoemmecanismosparasecomunicarcomnossosusurios.
Emprimeirolugar,ho WindowWAITcomando,queomaisadequadoparaotratamentodestatuse
mensagensdeinformao.Emsegundolugar,o MESSAGEBOX()funo,queprevvrias
formatosdeumaformaquecontmtextomodalerequeralgumaaodousurio.Ambossobastante
utilizvele,emboraasvriasconfiguraesopcionaisparao Messagebox()funonosofceisde
lembrese,parecedesnecessrioparatentar"reinventararoda"quandosetratademensagem
manipulaoatravsdaelaboraodeumsubstitutoparaessasduasferramentasnativas.
Noentanto,umacoisaquedevemosconsiderar(especialmentenocontextodo COM
componentes,ntierarquiteturaevriosaplicativos'frontend')quensrealmente
gostariadeevitarquecodificachamadasexplcitasparafunescomo MESSAGEBOX()e WAITWINDOW.Depoisdetudo,
ambasasfunesassumemquevocestexecutandoemumambientenoqualoconceitode
uma"janela"significaalgumacoisaeissopodenosersempreocaso.
Nstambmqueremosremoverotextodamensagemrealdenossocdigodeprogramaextraindoo
paraumatabela.Istonosnospermitereutilizarmensagens,mastambmajudaamantermensagensconsistentes
emnossasaplicaesportanto,nopedirqueousurio'Confirmaralteraes"emumlugare'Salvar
Changes'emoutro.Eletambmfazmudarotextodamensagemrealmaisfcile,seprecisar
lidarcomvriosidiomas,anicamaneiraprticadefazlo.Oseguinteesboosees
aconstruoeutilizaodenossaclassemanipulaodemensagensbaseadaemtabelas.

Figura10.8classemanipuladordemensagemsimples

Atabelademensagempadro(exemplo:Msgtable.dbf)
Estatabelausadaparaarmazenartodasasinformaesrelevantesparaasmensagensdeinterfacedeusurioque
nscriamos.definidacomoumatabelalivre,que,umavezquesempresomenteleituraemtempodeexecuo,
parao EXE.NestecasoestamosnegociandoosbenefciosdeteramesacomopartedeumDBCpara
construmos
velocidadedeacessoemtempodeexecuo.Aestruturadatabelamuitosimples:

358 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
MsgnumI( 4,0)NOTNULL &&IDdamensagem(chavecandidata)
MSGTYPC( 1,0)NOTNULL &&DisplayTypeNecessrio
MSGTITC(60,0)NOTNULL &&TtuloparaMessageBox,TextoparaWait
Janela/Estado
MSGBTNN( 1,0)NOTNULL &&Botoparadefinircomopadro(ParaMessageBoxapenas)
MsgTxtH( 4,0)NOTNULL &&Mensagemdetexto(porMessageboxOnly)

Umachavenica(candidato)definidona msgnumcampoparafornecerumrecursodepesquisarpida
pelonmerodamensagem.Notequetemosusadoumcampodememorandoparaarmazenarotextodamensagemreal,
demodoquetantootextoeolayoutdecadamensagempodeserprdefinido.
Nsdefinimosumnmerolimitadodetiposdemensagempadro,queusamosparaprdefinir
amaneirapelaqualumamensagemefectivamenteapresentado,comosesegue:

Tabela10.5Definiestipodemensagempadro

CdigoDigitar Estilo Tipodeexibio


E dilogodeerro Pararconecompadro'OK'botos 16
W dilogodeaviso conedaexclamaocom'OK'e'Cancelar' 49
botes
Eu Dialoginformaes coneInformaescomobotodefault'OK'nica 64
C confirmaodedilogo Perguntaconecom"sim"e"no"Botes 36
X Janelacentrado EsperarJanela,centralizadanatela 99
Y Janelapadro EsperarJanela,cantosuperiordireitodoecr 98
Z Barradestatus Defineotextonabarradestatuspadro 97

Aclassedeprocessamentodemensagens(exemplo:Msgmgr.prg)
Estaclasse,comoaclassederegistrodeerrodescritanaseoanterior,baseadoemum
FormSetporissopodeteroseuprprioDataSessionprivada.Aclasseestconfiguradaparaqueeleprecisaser
instanciadoapenasumavezcomopartedaaplicaodearranque.SuaInitmtodoarmazenaseuprprio
datasessionaumapropriedadeprotegidaeconfiguraatabelademensagememquedatasession(que
ajudaagarantirqueatabelademensagemnoseinadvertidamentefechadapelasaesdeoutra
objetos):

**********************************************************************
*Programa :MsgMgr.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:definiodeclasseparaMessageHandler
**********************************************************************
DEFINECLASSxMsgMgrASFormSet
PROTEGIDOFormCount,Visvel,DataSession,nDSId
FormCount =0 &&Nopermitaquequaisquerformas
Visvel =.F. &&MantenhaoFormsetinvisvel
DataSession=2 Numa&&Datasessionprivada
nDSId 1= &&DSpadropara1

PROCEDIMENTOInit
Comisso
***Abraatabelademensagens
ESE!USADO('msgtable')
msgtableUSOEM0msgtableALIASNOVAMENTECOMPARTILHADA

Captulo10:ClassesNonVisual 359

FIMSE
***DataSessiondoSalvarMessageHandler
.nDSId=.DataSessionID
ENDWITH
ENDPROC

Aclassetambmtemumnicomtodopersonalizadoexposta(ShoMsg),queesperarecebero
IDNmerodeumamensagemnatabelademensagempadrocomoumparmetro.Tendoverificadoque
oparmetronumrico,estemtodosalvaodatasessionatualemudaparao
datasessionprivadademanipuladordemensagem:
PROCEDIMENTOShoMsg(tnMsgNum)
lnOrigDSLOCAIS,lnRetVal
Comisso
***Nmerodemensagensdevesernumrico
IFVARTYPE(tnMsgNum)#"N"
ERROR"9000:UmparmetronumricovlidodeveserpassadoparaShoMsg()"
***Indicadordeerroderetorno
retornar1
FIMSE
***MudarparaMesageDSdeHandler
lnOrigDS=SET("DATASESSION")
SETDATASESSIONTO(.nDSId)
***LocalizeObrigatrioDetalhesMensagem
SeSEEK(tnMsgNum,'msgtable','msgnum')
***ChamadamanipuladorapropriadoparaestamensagemcombasenoTipo
lnRetVal.GetMsgStyle=()
OUTRO
***Nmerodemensagensnovlido
ERROR"9000:MensagemNumber"+ALLTRIM(STR(tnMsgNum))+"No
Reconhecido"
***Indicadordeerroderetorno
lnRetVal=0
FIMSE
***RestauraoDSoriginaleretornar
SETDATASESSIONTO(lnOrigDS)
RETURNlnRetVal
ENDWITH
ENDPROC

Seopassadoemnmerodemensagemnoforencontrado,omanipuladorsimplesmenteretornaumcdigodeerro
casocontrrio,oponteirodoregistrodeixadoapontandoparaamensagemcorretaeprotegida
(0),
GetMsgStylemtodopersonalizadochamadoparapassaraexibiorealdamensagemparaocorrecto
mtodo,comosesegue:

********************************************************************
***MsgMgr::GetMsgStyle()Verifiqueotipodemensagemechamarmanipuladorapropriado
********************************************************************
PROTEGIDOPROCEDIMENTOGetMsgStyle
***Verifiqueotipodemensagematualechamarmanipuladorcorretacom
***quaisquerparmetrosnecessrios
lcMsgTypLOCAL,lnRetVal
lcMsgTyp=msgtable.msgtyp
DOCASO
CASElcMsgTyp="E"

360 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***ErroPadro="Stop"+"OK"
lnRetVal=.DoMsgBox(16)
CASElcMsgTyp="W"
***PadroWarning="exclamao"+boto"OK/Cancelar"
lnRetVal=.DoMsgBox(49)
CASElcMsgTyp="I"
***PadroInformaes="INFO"+BotoOK
lnRetVal=.DoMsgBox(64)
CASElcMsgTyp="C"
***confirmaostandard="pergunta"+Sim/NoOpes
lnRetVal=.DoMsgBox(36)
CASElcMsgTyp="X"
***Janeladeesperacentralizadanatela
lnRetVal=.DoWait(.T.)
CASElcMsgTyp="Y"
***Janeladeesperanocantosuperiordireito
lnRetVal.DoWait=()
PROCESSOlcMsgTyp="Z"
***MensagemStatusBar
lnRetVal.DoStat=()
DEOUTRAFORMA
***SemApresentaoNecessrioRetornoSucesso
lnRetVal=1
ENDCASE
***RetornoTipodeexposio
RETURNlnRetVal
ENDPROC

Amensagemserexibidareaisso,comexcepodeclculoaposioparao
centradobastantesimples"janela,espere':

********************************************************************
***MsgMgr::DoMsgBox(tnParam)Callcaixademensagemparaexibirmensagens
***RetornoBotousadoparafecharacaixademensagens
********************************************************************
PROCEDIMENTOPROTEGIDADoMsgBox(tnParam)
LOCALlnRetVal,lcTxt,lcTit
***Obtermensagemettulodatabela
lcTxt=ALLTRIM(msgtable.msgtxt)
lcTit=ALLTRIM(msgtable.msgtit)
***BotoDefinirpadrolojanaTabelacomo1,2ou3
ESE!VAZIO(msgtable.msgbtn)
lnParamtnParam=+((msgtable.msgbtn1)*256)
OUTRO
lnParam=tnParam
FIMSE
lnRetVal=MESSAGEBOX(lcTxt,lnParam,lcTit)
RETURNlnRetVal
ENDPROC

********************************************************************
***MsgMgr::DoWait(tlCenter)Visordemensagensjaneladeespera
***Nenhumvalorderetornoespecfico
********************************************************************
PROCEDIMENTOPROTEGIDADoWait(tlCenter)
lcTxtLOCAL
***Obtermensagemdatabela

Captulo10:ClassesNonVisual 361

lcTxt=ALLTRIM(msgtable.msgtit)
IFtlCenter
LOCALlnTexLen,lnRows,lnAvgChar,lcDispText,lnCnt,lcLine,lnCol,lnRow
***Calcularotamanhodamensagem
SETMEMOWIDTHa80
_MLINE=0
lnTexLen=0
lnRows=MEMLINES(lcTxt)
***Calcularotamanhodotextoparaoposicionamento
lnAvgChar=FONTMETRIC(6,'Arial',8)/
FONTMETRIC(6,_SCREEN.FONTNAME,_SCREEN.FontSize)
lcDispText=''
***Encontremaislongafileiradetextonamensagem
PARAlnCnt=1alnRows
lcLine=''+MLINE(lcTxt,1,_MLINE)+''
lcDispText=IIF(!empty(lcDispText),CHR(13),"")+lcDispText+
lcLine
lnTexLen=MAX(TXTWIDTH(lcLine,"MSSansSerif",8,'B')+4,lnTexLen)&&4
fronteira
PRXIMO
***Exerciteposioparaajanelacombasenamaislongafileira
lnCol=INT((SCOLS()*lnTexLenlnAvgChar)/2)
lnRow=INT((SROWS()lnRows)/2)
***Mostrarjanelacentrada
WAITWINDOWlcDispTextATlnRow,lnColNOWAIT
OUTRO
***Waitsimplesjanelanapartesuperior/Direita
ESPERANOWAITJANELAlcTxt
FIMSE
***Retorno'Sucesso'
RETURN1
ENDPROC

********************************************************************
***MsgMgr::DoStat()visordemensagensdabarradestatus
***Nenhumvalorderetornoespecfico
********************************************************************
PROCEDIMENTOPROTEGIDADoStat()
lcTxtLOCAL
***Obtermensagemdatabela
lcTxt=ALLTRIM(msgtable.msgtit)
SETMENSAGEMAOSlcTxt
***Retorno'Sucesso'
RETURN1
ENDPROC

Usandoomanipuladordemensagem
Umavezqueoobjetodemensagemdemovimentaocriado,tudoquenecessrioparaexibirumamensagem
oShoMsgmtodoepassaronmerodamensagemrequerida.Ocdigodeexemploparaeste
chamar
captuloincluiumatabelaquedefineumamensagemdecadatipodemensagem.Paratestaromanipulador,
bastacriaroobjetoechamarumamensagem:

goMsgMgr=NEWOBJECT('xMsgMgr','msgmgr.prg',NULL)
lnChoice=goMsgMgr.ShoMsg(1030)
362 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Omanipuladordemensagemsempreretornarocdigodeidentificaoparaobotopressionadoparafecharuma
caixademensagemouumcdigonumrico'1'paratodasasoutrasmensagensexibidas.

Concluso
Esperamosqueosexemplosnestecaptulolhedeialgumasidiasteisetemosacertezadeque
vocsercapazdepensaremmuitasoutrasmaneirasdeusaropodereaflexibilidadedenovisual
classes.

Captulo11:FormaseoutrasclassesVisual 363

Captulo11
FormulrioseoutrosVisual
Classes
"Formaefunosoumaunidade,doisladosdamesmamoeda.Afimdemelhorarafuno,
formaadequadadeveexistirousercriados"("Rolfing:.AIntegraodetruesHumanos"
porIdaP.Rolf).

Oaplicativopodeimplementarumalgicaquemaiscomplexadoqueacinciadefoguetes,masse
ainterfacegrosseiropelousurio,ningumnuncavaisaberoucuidado.Acoisamaisimportanteparao
aspessoasqueestarousandooaplicativoounofazoseutrabalhomaisfcil
Faz.Softwarequefazcomquemaistrabalho,outornaavidadetrabalhodealgummaisdifcil,
softwareruim,noimportacomovocofaria.Nestecaptulo,vamoscompartilharalgumasclassescom
vocquenosirtornaravidamaisfcilparaseususuriosfinais,mastambmirfacilitaravidados
voccomovocdesenvolvlo.

Comopossofazermeusformulriospreencheratelainteira,
independentemente
daresoluodatela?(Exemplo:CH11.VCX::FrmMaximizee
Maximize.scx)
Seoaplicativoquevocestconstruindosoberano,(ouseja,umaaplicaodestinadaaserutilizada
exclusivamenteporumutilizador,poroposiomerapartilharumaporodoecrdoutilizadorcomoutros
aplicativos),vocprovavelmentevaiquererasformasdemaximizarasimesmosquandoinstanciado,
independentementedaresoluodatelaumdeterminadousuriodefiniu.
Parafazerissovocvaiprecisarparacalculararelaopelaqualaresoluodetelaatual
diferedopadro(quedevesersempre640x480dequalquermaneira!)paraqueseusformulrios
soprojetados.Estarelaopodeentoseraplicadaatodasasformaseosseuscomandospararedimensionartudo
semalterarasproporesrelativas.IstomelhorrealizadoatravsdaadiodeumResizeControls
mtodoparaaclassedeformulrioechamloapartirdoformulrioInitmtodo,apsaprimeiraredimensionaro
formarse,assim:

loControlLOCAL
COMThisform
***Determinaraproporonecessriaparamaximizaraforma
***Dependendodaresoluodatelaearmazenloparaformarpropriedades
.WidthRatio=SYSMETRIC(1)/640
.HeightRatio=SYSMETRIC(2)/480
***Searesoluoforsuperiora640x480,reposicione
***Emaximizaraforma
IF.WidthRatio>1
.Top=0
.Left=0
.Width=.Width*.WidthRatio
.Height=.Height*.HeightRatio
***Eredimensionarcadacontrolecontidasnoformulrio

364 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

PARACADAloControlEM.Controls
.ResizeControls(LoControl)
ENDFOR
FIMSE
ENDWITH

NotequeestamosusandoonativoSYSMETRIC()funoparadeterminaratelaatual
resoluoe,emseguida,calcularambososrcioshorizontaiseverticais.Estesrciossosalvoscomo
formarpropriedadeseusadoimediatamentepararesizeoprprioformulrio.entonsloopatravsdecadaumdos
osobjetosdoformulrioControlscoleo,chamandoaResizeControlsmtodoepassaruma
refernciadeobjetoparaocontroleparacadaum.
OResizeControlsmtododeveagirdiferente,dependendoseoobjeto
queelerecebeumcontrolesimplesoudeoutrorecipientecommaiscontroles.Paralidarcomisso
situao,omtodotemdesercapazdeperfurarparabaixoemrecipienteschamandosedeformarecursiva.
Aprimeiratarefa,noentanto,definiroTop,esquerda,alturaelargurapropriedadesparaopassado
controleseeletemessaspropriedades.(Seuprimeiropensamentopodemuitobemserque,certamente,todososcontroles
tmestaspropriedades?Noassim,PageFrames,porexemplo,notmrealmenteAlturae
visuais
Largura,emvezdeteremPageHeightePageWidthpropriedades.)

LPARAMETERStocontrol
LOCAISloPage,loControl,loColumn,lnColumnWidths[1],lnCol

IFPEMSTATUS(tocontrol,'Largura',5)
toControl.Width=toControl.Width*Thisform.WidthRatio
FIMSE
IFPEMSTATUS(tocontrol,altura,5)
toControl.Height=toControl.Height*Thisform.HeightRatio
FIMSE
IFPEMSTATUS(tocontrol,'Top',5)
toControl.Top=toControl.Top*Thisform.HeightRatio
FIMSE
IFPEMSTATUS(tocontrol,'Esquerda',5)
toControl.Left=toControl.Left*Thisform.HeightRatio
FIMSE

Emseguida,precisamosredimensionarafonteparaocontroleatual.Seissoacontecedeserumagrade,uma
casoespecialedevesertratadoseparadamenteporquealterarotipodeletradeumagraderedefineo
largurasdecolunadagrade.Antesdemodificarumagrade,devemossalvartodasaslargurasdascolunasdemodoaque
podemosrestaurlosmaistarde:
IFUPPER(ALLTRIM(toControl.Baseclass))'Grid'=
lnColumnWidthsDIMENSO[toControl.ColumnCount]
PARAlnCol=1atoControl.ColumnCount
lnColumnWidths[lnCol]=toControl.Columns[lnCol].Width
ENDFOR
toControl.Fontsize=INT(toControl.FontSize*Thisform.WidthRatio)
PARAlnCol=1atoControl.ColumnCount
toControl.Columns[lnCol].Width=lnColumnWidths[lnCol]
ENDFOR
OUTRO
IFPEMSTATUS(tocontrol,'Tamanhodafonte',5)
toControl.Fontsize=INT(toControl.FontSize*Thisform.WidthRatio)

Captulo11:FormaseoutrasclassesVisual 365

FIMSE
FIMSE

Emseguida,precisodeterminarsetemosumobjetoquecontmoutrosobjetos.Quandoesteforo
caso,devemoschamaraResizeControlsmtodorecursivamenteepassloumarefernciaparacadaumdos
continhamobjetos.Ocdigoaseguirfazissoquandooobjetoatualumpageframe,pgina,
recipiente,CommandGroup,ouOptionGroup.
DOCASO

MAISCULAS(toControl.BaseClass)='pageframe'
PARACADAloPageINtoControl.Pages
Thisform.ResizeControls(loPage)
ENDFOR

CASEINLIST(UPPER(toControl.BaseClass),'pgina','contentor')
PARACADAloControlINtoControl.Controls
Thisform.ResizeControls(loControl)
ENDFOR

CASEINLIST(UPPER(ALLTRIM(toControl.BaseClass)),
'CommandGroup','OptionGroup')
lnButtonLOCAL
PARAlnButton=1atoControl.ButtonCount
ThisForm.resizeControls(toControl.Buttons[lnButton])
ENDFOR

Finalmente,temosdelidarcomoscasosespeciais.Seoobjetoatualumagrade,devemosdefiniroseu
RowHeighteheaderHeightpropriedades.Tambmdevepercorrersuacoleodecolunas
edefiniralarguradecadacolunacontidanagrade:

MAISCULAS(toControl.BaseClass)='Grid'
COMtocontrol
.Alturadalinha
=.RowHeight*Thisform.HeightRatio
.HeaderHeight =.HeaderHeight*Thisform.HeightRatio
PARACADAloColumnEM.Columns
loColumn.Width=loColumn.Width*Thisform.WidthRatio
ENDFOR
ENDWITH

Masseoobjetoatualouumacaixadecombinaooulista,precisorecalculareredefinirasua
ColumnWidths:

CASEINLIST(UPPER(toControl.BaseClass),'COMBOBOX','LISTBOX')
lnColLOCAL,lnStart,lnEnd,lnLen,lcColumnWidths
COMtocontrol
IF.ColumnCount<2
.ColumnWidths=ALLTRIM(STR(.Width))
OUTRO
lcColumnWidths=''
lnStart=1
PARAlnCol=1a.ColumnCount1
lnEnd=AT(',',.ColumnWidths,lnCol)
lnLen=lnEndlnStart
366 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

lcColumnWidths=lcColumnWidths+
IIF(empty(lcColumnWidths),'','')+
ALLTRIM(STR(Val(substr(.ColumnWidths,lnStart,lnLen))
*Thisform.WidthRatio))
lnStart=+1lnEnd
ENDFOR
lnLen=len(.ColumnWidths)+1lnStart
lcColumnWidths=lcColumnWidths+','+
ALLTRIM(STR(Val(substr(.ColumnWidths,lnStart,lnLen))
*Thisform.WidthRatio))
.ColumnWidths=LcColumnWidths
FIMSE
ENDWITH

DEOUTRAFORMA
***Nohoutramaneira...Achoquetemostodososcasos
ENDCASE

Comofaoparacriarformulriosredimensionveis?(Exemplo:CH11.VCX::
cusResizere
Resize.scx)
Aclassedeformulrioautomaximizandodiscutidoacimaumcasoespecialdeumaformadereconsidervel,namedidaem
umavezsdeoperao,masosprincpiosbsicossoosmesmos.Cadavezqueoformulrioredimensionado,
que
precisamoscalculararelao,emquealturaelarguradoformulriomudaramemrelaoaoseu
dimensesoriginaise,emseguida,aplicaressaproporoparacadacontrolenoformulrioparamanteromesmo
tamanhorelativoeasposiesemtodososmomentos.

Figura11.1formaResizablecomoinstanciadocomdimensesoriginais

Captulo11:FormaseoutrasclassesVisual 367

Amelhormaneiradelidarcomissocriarumaclassequevaifazerosclculosnecessriose
bastaadicionloacadaformulrioqueprecisaserfeitoredimensionvel.Asclassesdafundaoqueacompanham
comoVisualFoxProverso6.0realmenteincluirtalclasseresizer.Noentanto,emborapossaser
adequadoparaformassimples,comalgunscontrolesbsicos,bastantelimitadoenomanipula
maiscontrolescomplexos,comogrades,combosoucaixasdelistacorretamente.Nemsequertentar
redimensionaroureposicionarOptionGroupsouCommandGroups.Comoresultado,emnossaopinio,nofaz
mritomuitaateno.
Figura11.2formaResizablefeitamenor

Paraumaflexibilidademxima,criamosumResizerclassequeirlidarcomtodosestes
requisitoscorretamente.Oobjectobaseadonestaclassedeveseradicionadoclasseformaoudeforma
nasuaInitmtodoporqueeleprecisasalvarasdimensesoriginaisdetodososcontrolosdeformulrioquandoele
instanciado.Claramente,temosdeassegurarquetodososcontrolesdeformulriotersidoinstanciadoantesdo
doresizerInitmtodoexecutadoporissousamosumcdigocomoestenoformulrioInitmtodo:

IFDODEFAULT()
This.AddObject('Resizer','cusResizer')
FIMSE

Comoditoacima,achaveparatornarapropriedadefunodeclasseoprimeiroasalvaratodosos
Propriedadesdeorientaovisuaisrelevantesparacadaobjetonoformulrio.NoVisualFoxPro6.0,nspodemos
fazerusodecadacontrolodeformulrioAddPropertymtodoparaguardarestasinformaesdentrodoobjeto
si.Assim,quandooobjectoinstanciadaredimensionador,asuaSaveOriginalDimensionsmtodo

368 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

processosderecolhadecontrolesdoformulrio,perfuraoparabaixoemtodososrecipientes(semelhanteao
frmMaximizeclasseapresentadaacima).Estemtodocriaaspropriedadesexigidasparaguardar
Altura,Largura,PageHeight,ColumnWidthseassimpordiante.Obviamente,aclassebasedoobjeto
determinaquaispropriedadessoadicionadosviaAddProperty.Estecdigo,naderesizerInitmtodo,
invocaasuapersonalizadosSaveOriginalDimensionsmtodoassim:

loControlLOCAL

COMThisform

***dimensesSalvarformulrioeminstanciao
.AddProperty('NOriginalHeight',.Height)
.AddProperty('NOriginalWidth',.Width)

***Definirumalarguraminimaealturaparaevitarerrosmaistarde
.MinWidth=.Width/2
.MinHeight=.Height/2

***Agorasalveaspropriedadesvisuaisrelevantes(altura,largura,ColumnWidths,
etc)
***Detodososcontrolosnoformulrio
PARACADAloControlEM.Controls
This.SaveOriginalDimensions(loControl)
ENDFOR
ENDWITH

SaveOriginalDimensionsbrocasparabaixoemtodososrecipientes,adicionandoaspropriedadesnecessrias
einicializarloscomosvalorescorretosmedidaquegiraatravsdecoleodecontrolesdoformulrio:

LPARAMETERStocontrol
loPageLOCAL,loControl,loColumn,lnCol

Obviamente,seoobjetonotemumAddPropertymtodo,nopodemosusloparaadicionaro
propriedadesnecessriasparasalvarasdimensesoriginais.Seesteforocaso,nssocorrer.Issopode
causaralgumasanomaliasmaistarde,quandooformulrioredimensionado,mascertamenteprefervelaterum
errofatal:

ESE!PEMSTATUS(tocontrol,'AddProperty',5)
RETORNA
FIMSE

Emseguidansverificaraspropriedadesusuais:Altura,Largura,TopeEsquerda.Seelessovlidos
propriedadesparaoobjetoatual,podemosadicionaraspropriedadesnecessriasparaoobjetoesalvarasua
dimensesoriginais:
IFPEMSTATUS(tocontrol,'Largura',5)
toControl.AddProperty('nOriginalWidth',toControl.Width)
FIMSE
IFPEMSTATUS(tocontrol,altura,5)
toControl.AddProperty('nOriginalHeight',toControl.Height)
FIMSE
IFPEMSTATUS(tocontrol,'Top',5)

Captulo11:FormaseoutrasclassesVisual 369

toControl.AddProperty('nOriginalTop',toControl.Top)
FIMSE
IFPEMSTATUS(tocontrol,'Esquerda',5)
toControl.AddProperty('nOriginalLeft',toControl.Left)
FIMSE
IFPEMSTATUS(tocontrol,'Tamanhodafonte',5)
toControl.AddProperty('nOriginalFontSize',toControl.FontSize)
FIMSE

Emseguidavamosverificarparaverseoobjetoatualumrecipiente.Seeleecontmoutras
objetos,teremosquepasslasparaestemtododeformarecursiva:

DOCASO
MAISCULAS(toControl.BaseClass)='pageframe'
PARACADAloPageINtoControl.Pages
This.SaveOriginalDimensions(loPage)
ENDFOR

CASEINLIST(UPPER(toControl.BaseClass),'pgina','contentor')
PARACADAloControlINtoControl.Controls
This.SaveOriginalDimensions(loControl)
ENDFOR

CASEINLIST(UPPER(ALLTRIM(toControl.BaseClass)),'CommandGroup',
'OptionGroup')
lnButtonLOCAL
PARAlnButton=1atoControl.ButtonCount
This.SaveOriginalDimensions(toControl.Buttons[lnButton])
ENDFOR

Nstambmpodemoslidarcomoscasosespeciaisaqui.Porexemplo,asgrelhasRowHeighte
HeaderHeightpropriedadesqueprecisamsersalvoseprecisamossalvaraslargurasoriginaisdetodos
suascolunascontidas.Combinaoecaixasdelistagemtambmrequeremumtratamentoespecialparasalvarooriginal
ColumnWidths:

MAISCULAS(toControl.BaseClass)='Grid'
COMtocontrol
.AddProperty('NOriginalRowHeight',.RowHeight)
.AddProperty('NOriginalHeaderHeight',.HeaderHeight)
.AddProperty('NOriginalColumnWidths[1]')
.nOriginalColumnWidthsDIMENSO[.ColumnCount]
PARAlnCol=1a.ColumnCount
.nOriginalColumnWidths[lnCol]=.Columns[lnCol].Width
ENDFOR
ENDWITH

CASEINLIST(UPPER(toControl.BaseClass),'COMBOBOX','LISTBOX')
COMtocontrol
.AddProperty('NOriginalColumnWidths',.ColumnWidths)
ENDWITH

DEOUTRAFORMA
***Nohoutramaneira...Achoquetemostodososcasos
ENDCASE
370 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tertodososvaloresoriginaissalvos,precisamosgarantirqueoresizerinvocado
semprequeoformulrioredimensionado.AnicalinhadecdigonoformulrioResizemtodotudooque
necessrio:

Thisform.cusResizer.AdjustControls()

OcostumeAdjustControlsmtodopercorrecoleodecontrolesdoformulrioemgrande
damesmamaneiraqueoSaveOriginalDimensionsmtodo.Nestecaso,noentanto,omtodo
invocaoResizeControlsmtodopararedimensionarereposicionaroscontrolesutilizandooformulriode
larguraatualdivididoporsualarguraoriginalcomoofatorpeloqualseuscontrolescontidosso
fezmaislargooumaisestreito.
OformulriodeexemploResize.SCXmostracomoaclassepodeserusadaparalidarcomoredimensionamentodeum
formarazoavelmentecomplexa.Noentanto,umapalavradecautelaaordemaqui.Estaclassenovailidar
comobjetosquesoadicionadosemtempodeexecuousandoinstanciaoretardada.Istosimplesmenteporqueo
configurarassumequetodososobjetosexistemantesdoresizeremsiinstanciado.Sevocprecisausar
instanciaoatrasadoemumaformaredimensionvel,chamedoresizerSaveOriginalDimensionsmtodo
explicitamentecomumarefernciaaoobjetorecmadicionadoe,emseguida,chamarimediatamentea
ResizeControlsmtodo.
Certasoutrasclassesqueintroduzimosmaiscedonestelivrotambmexigiria
modificaoparafuncionarcorretamenteemumaformaredimensionvel.Porexemplo,quandoutilizadonuma
formaracaixadeediodeexpansoapresentadonoCaptulo4exigequeseusSaveOriginalDimensions
redimensionvel
mtodoserchamadocadavezqueexpandida.Desdeoseutamanhoeposiomudasemprequeo
formulrioredimensionado,nosuficienteparaarmazenaressainformaoumavez,quandoacaixadeedioinstanciado.

Comofaoparaprocurarporregistrosespecficos?(Exemplo:SearchDemo.scx
eSrch.scx)
Acapacidadedeencontrarumregistroespecficocombaseemalgumtipodecritriodepesquisamuitocomum
requerimento.Nscriamosumaformagenrica'popup'(Srch.scx),quepodeserusadoparaprocurar
paraumjogoemqualquercampoemumadeterminadatabela.Vocsprecisatercertezadequequalquerformaqueochama,
flocomosseguintesparmetrosnaordememqueelassolistadas.

Tabela11.1Parmetrospassadosp araoformulriodepesquisa

Nomeparmetro parmetroDescrio
ToParent refernciadeobjetoparaaformadechamada
tcAlias Aliasemquepararealizarapesquisa
TcField Ocampoemqueparaprocurarumacorrespondncia
TcAction Acoatomarquandoforencontradaumacorrespondncia

Captulo11:FormaseoutrasclassesVisual 371
Figura11.3formulriodebuscagenricoemao

Cadaobjetonoformulriodechamadadevesercapazderegistrarsecomestaformacomoo
objetoatual.Issonecessrioporquequandoousurioclicanoboto'pesquisar',oboto
tornaseaformadoActiveControl.Noentanto,queremosprocurarnocampovinculadoao
controlequefoioActiveControlantesdeclicarnobotoPesquisar,porissoprecisamosdealgumamaneira
deidentificlo.Tudooqueprecisamosparaatingiressafuncionalidadeumapropriedadedeformulriopersonalizado
oActiveControleoseguintecdigonoLostFocusmtododenossosdadoscontrolesconscientes:
chamado

IFPEMSTATUS(Thisform,'oActiveControl',5)
Thisform.oActiveControl=Este
FIMSE

OformulriodepesquisainstanciadocomestecdigonocostumedoformulriochamadoPesquisamtodo.
Observequeoformulriodebuscasinstanciadoseoformulriodechamadanotemumarefernciaa
umquejexiste:

***Primeiroversejtemosumformulriodepesquisadisponveis
IFVARTYPE(Thisform.oChild)='O'

***Setivermosum,bastadefinirocampodepesquisa
Thisform.oChild.cField =JUSTEXT(This.oActiveControl.ControlSource)
Thisform.oChild.Activate()
OUTRO
DOFORMSrchComisso,This.cPrimaryTable,
JUSTEXT(This.oActiveControl.ControlSource),
'This.oParent.oActiveControl.SetFocus()'

372 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FIMSE

***Istofuncionaporquetodososcontrolesquesoreferenciadosnocdigo
***Temumprefixodetrscaracteresquedefineoqueso(porexemplo,txt)
***Seguidoporumnomedescritivo
Thisform.oChild.Caption='Pesquisar'+SUBSTR(This.oActiveControl.Name,4)

Oformulriodepesquisaguardaosparmetrosquerecebeparapropriedadesdoformulriopersonalizadoparaqueeles
disponvelparatodaaforma.Eletambmenviaumarefernciaasimesmodevoltaparaaformadechamadaparaque
sejam
aformadechamadacapazdeliberaroformulriodebusca(seeleaindaexiste),quandoforlanado:

LPARAMETERStoParent,tcAlias,tcField,tcAction
IFDODEFAULT(toParent,tcAlias,tcField,tcAction)
COMThisform

***Salvarrefernciaformaquecomeouabusca
.oParent=toParent

***Tambmsalvaratabeladepesquisaeonomedocampodepesquisa
.cAlias
=tcAlias

.cField=tcField

***Porfim,salvaraacoatomarquandoforencontradaumacorrespondncia
.cAction=tcAction

***Salvenmerorecordeatual
.nRecNo=RECNO(.cAlias)
***Dopaiformarumarefernciaparaoformulriodepesquisa
***Porisso,quandofecharoformulriopaitambmfecharoformulriodebusca
.oParent.oChild=Este
ENDWITH
FIMSE

Oformulriodepesquisatemtrsmtodospersonalizados,umaparacadaumdosbotesdecomando.o
Encontrarpesquisasmtodoparaoprimeirojogonocampoespecificadoparaovalordigitadono
caixadetextodaseguinteforma:

LOCALlnSelect,lcField,luValue,lcAction

***Guardarreadetrabalhoatual
lnSelect=SELECIONAR()
COMThisForm

Seocampocontmdadosdecaracteres,queremosforarovalornacaixadetextoparamaisculas.
Istofacilmenteconseguidopelacolocaodeum!emsuapropriedadedeformatonafolhadepropriedades.
Portanto,nohnecessidadedeexecutarestatarefanocdigo:

luValue=IIF(VARTYPE(.txtSearchString.Value)='C',
ALLTRIM(.txtSearchString.Value),.txtSearchString.Value)
Seleccione(.cAlias)

Captulo11:FormaseoutrasclassesVisual 373

Emseguida,verificarsehumamarcadendicenocampoespecificado,usandoonossodandyacessvelISTAG()
funo.Setemosumatag,usaremos SEEKparaencontrarumacorrespondncia.Casocontrrio,temosqueusar
LOCALIZAR:

IFISTAG(.cField)
SEEKluValueTAGORDER(.cField)IN(.cAlias)
OUTRO
lcField=.cField
IfVarType(eval(.cAlias+'.'+LcField))='C'

LOCALIZARPARAUPPER(&lcField)=luValue
OUTRO
LOCATEFOR&lcField =luValue
FIMSE
FIMSE

Seforencontradaumacorrespondncia,realizamosaprximaaoquefoipassadoparadoformulrioInitmtodo
esalvaronmeroderegistrodoregistroatual.Casocontrrio,vamosexibirumamensagemparadeixaro
usuriosaibaquenenhumacorrespondnciafoiencontradaerestauraroponteirodoregistroparaondeestavaantesdens
comeouabusca:

***Seumacorrespondnciafoiencontrada,executeaprximaao
SEACHADO()

***Salvenmerorecordederegistrocorrespondente
.nRecNo=RECNO(.cAlias)
SELECT(lnSelect)
lcAction=.cAction
&lcAction
OUTRO
WAITWINDOW"NoMatchFound!'NOWAIT

***Restaurarponteiroderegistro
GOTO.nRecNoIN(.cAlias)
SELECT(lnSelect)
FIMSE
ENDWITH

OcdigonoFindNextmtodomuitosemelhanteaocdigonaFindmtodo.
Infelizmente,devemosusar LOCALIZARnaFindNextmtodoporque SEEKencontrasempreoprimeiro
correspondersempreecomeaapartirdotopodoficheiro.Aocdigoqueencontraoprximoregistro,se
hum:

***Seestamosnoltimoregistroencontrado,puleparaoprximoregistro
PULAR

***Deveusarlocateparalocalizarseguinteporqueprocuramsemprecomea
***Notopoeencontraoprimeirojogo
lcField=.cField
luValue=IIF(VARTYPE(.txtSearchString.Value)='C',
ALLTRIM(.txtSearchString.Value),.txtSearchString.Value)
IfVarType(eval(.cAlias+'.'+LcField))='C'

LOCALIZARPARAUPPER(&lcField)=RESTOluValue
OUTRO
LOCATEFOR&lcField =LuValueDESCANSO

374 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FIMSE

OcdigonocostumedoformulriodepesquisaAnularmtodocancelaapesquisa,reposicionao
ponteirodoregistro,efechaoformulriodebuscaassim:

COMThisform
GOTO.nRecNoIN(.cAlias)
.Lanamento()
ENDWITH

AlgunsdoscdigosmaisimportanteresidenaDestruirmtododecadaformulrio.Seabusca
formanotenhoessecdigoemsuaDestruirmtodo:
IFTYPE('Thisform.oParent.Name')='C'
Thisform.oParent.oChild=NULL.
FIMSE

queserecusariaairemboraquandoousurioclicouno CANCELARbotoporqueaforma
queochamouaindaestariaapontandoparaele.Nestecaso,areferncianapossedoformulriodechamada
conhecidacomoumarefernciapendente.Arefernciaqueoformulriodebuscatemaformadechamada
(This.oParent)limpaapsseautomaticamente,porissomenosproblemtico.Quandoapesquisa
formulriolanado,arefernciaquedetmparaoformulriodechamadaliberadotambm.Estecdigono
chamandoaformadedestruirmtodogarantequequandomorre,elaassumeaformadebuscacomele:

***Solteoformulriodepesquisaseeleaindaestaberto
IFVARTYPE(Thisform.oChild)#'X'
Thisform.oChild.Release()
FIMSE

ComofaoparaconstruirSQLnamosca?(Exemplo:FilterDemo.scxe
BuildFilter.scx)
Muitosexcelentesferramentasdeterceirosestodisponveiseforneceressafuncionalidade,bemcomoa
capacidadedecriar,modificareimprimirrelatriossobreasadadoSQLgeradopelousurio.Nonossa
intenodereinventararodaaqui.Seosrequisitosdesuaaplicaoparaousuriofinal
SQLgeradosocomplexas,asoluoclaramenteumdestesprodutosmuitofinos.Tendo
disseque,hocasiesemquenecessrioapresentarousuriofinalcomummeiode
aconstruodeumacondiodefiltromuitosimplesquepodeseraplicadaaumanicatabela.Nestecaso,o
ferramentadeterceirospodemfornecerumafuncionalidademuitomaisdoquevocnecessita.umBuildFilter.scx
construtorefiltrosimplesfornecidocomocdigodeexemploparaestecaptulo.Eleconstriofiltro
condioparaumnicoalias.Comligeiramodificaoeaadiodeumpageframe,estaforma
podeserfacilmentemodificadoparajuntarduastabelas(oumais)antesdeconstruirofiltro.
Captulo11:FormaseoutrasclassesVisual 375

Figura11.4formagenricaparaconstruircondiodefiltro

ChamadaBuildFilter.scxusandoestasintaxe:

FAZERBUILDFILTERformulriocom'<ALIAS>'paralcSQLString

VocpodeentousaracondiodefiltrovoltouaexecutarumaconsultaSQLcomoesta:

SELECT*FROM<alias>ONDE&lcSQLstringINTOCURSORTempNOFILTER

ouparadefinirumfiltroparaoaliasespecificadocomoeste:

SELECT<alias>
SETFILTERTO(lcSQLstring)

OBuildFilterformaesperareceberumapelidodetabelacomoumparmetroearmazenaa
personalizadoscAliaspropriedade,afimdetornlodisponvelatodooformulrio.OcostumeSetForm
mtodoentochamadoparapreencherocostumeaFieldNamespropriedadedematrizqueusadocomoo
RowSourceparaaquedalistadenomesdecampofotoacimaparabaixo.Depoisdegarantirquea
aliasespecificadoestdisponvel,oSetFormmtodousao AFIELDS()funoparacriarlaFields,
umamatrizlocalquecontmosnomesdoscamposnoapelidopassou.Umavezquenoquerem
permitirqueousurioincluircamposdememorandoemqualquercondiodefiltro,nsfazemosavarreduradamatriz
removertodososcamposmemoassim:
laFieldspara

lnFieldCntLOCAL,laFields[1],lnCnt,lcCaption,lnArrayLen
COMThisform

***Certifiquesedealiasestdisponvel
SE!Utilizados(.cAlias)
Uso(.cAlias)em0

376 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FIMSE

***Vejatodososnomesdecamponoaliaspassados
lnFieldCnt=AFIELDS(laFields,.cAlias)

***Noincluemcamposdememorandonalistadecampos
lnArrayLen=lnFieldCnt
lnCnt=1
FazerenquantolnCnt<=lnArrayLen
IFlnCnt>lnFieldCnt
SADA
FIMSE
Seotipo(.cAlias+"."+LaFields[lnCnt,1])="M"

=ADEL(laFields,lnCnt)
lnFieldCnt=lnFieldCnt1
OUTRO
lnCnt=+1lnCnt
FIMSE
ENDDO
Apsoscamposdanotatenhamsidoremovidos,amatriz,ThisForm.aFieldNames,construdo
utilizandooselementosremanescentesnamatrizlaFields.Thisform.aFieldNamescontmdois
colunas.Aprimeiracolunacontmalegendadocampo,seoaliaspassadoumatabelaouexibioem
acorrentedepropriedadedbcealegendaparaocamponoestvazio.Seoaliaspassadolivre
mesaouarespectivalegendaestvazio,aprimeiracolunadamatrizcontmonomedocampo.o
segundacolunadamatrizsemprecontmonomedocampo:

.aFieldNamesDIMENSO[lnFieldCnt,2]
PARAlnCnt=1alnFieldCnt
lcCaption=""
Seestivervazio(DBC())e(INDBC(.cAlias,QUADRO!')
ORINDBC(.cAlias,'View'))
lcCaption=APRD(DBGETPROP(.cAlias
++laFields[lnCnt,1],"."

'Campo','caption'),40)
FIMSE
IFEMPTY(lcCaption)
lcCaption=APRD(laFields[lnCnt,1],40)
FIMSE
.aFieldNames[lnCnt,1]=lcCaption
.aFieldNames[lnCnt,2]=APRD(laFields[lnCnt,1],40)
ENDFOR
.cboFieldNames.Requery()
.cboFieldNames.ListIndex=1
ENDWITH

costumedaformaBuildFiltermtodoqueadicionaacondiodecorrenteparaofiltro.Isto
invocadacadavezqueo ESTADOADDbotoclicado:

lcConditionLOCAL
COMThisform
Seotipo(.cAlias
+'.'+ALLTRIM(.cboFieldNames.Value))='C'

lcCondition='UPPER('+ALLTRIM(.cboFieldNames.Value)+')'+
ALLTRIM(Thisform.cboConditions.Value)+''
OUTRO
lcCondition=ALLTRIM(.cboFieldNames.Value)+''+

Captulo11:FormaseoutrasclassesVisual 377

ALLTRIM(Thisform.cboConditions.Value)+''
FIMSE

***Adicioneasaspasseotipodecampoocarter
Seotipo(.cAlias
+'.'+ALLTRIM(.cboFieldNames.Value))='C'

lcCondition=lcCondition+CHR(34)+
UPPER(ALLTRIM(.txtValues.Value))+CHR(34)
OUTRO
lcCondition=lcCondition+ALLTRIM(.txtValues.Value)
FIMSE

***Sehouvervriascondiesejuntos
.cFilter=IIF(VAZIO(.cFilter),lcCondition,.cFilter+
'E'+lcCondition)
ENDWITH
Thisform.edtFilter.Refresh()

Nohvalidaorealizadasobreosvaloresinseridosparaacondiodefiltro.Isto
algoquevoccertamentevaiquereradicionarsevocusarestepequenoformacomoabasedeumSQL
geradoremseuaplicativodeproduo.Istopoderiaserconseguidoatravsdaadiodeum
ValidateConditionmtodoparaoformulrio.EstemtodoseriachamadopeloBuildCondition
mtodoeretornarumverdadeirolgico,seacaixadetextocontmumvalorapropriadoparaotipodedados
ocamposelecionadonalistasuspensa.NossaStr2ExpfunointroduzidanoCaptulo2faria
ajudaraalcanaresteobjetivo.

Comopossosimularajaneladecomandonomeu
?executvel(Exemplo:Command.scx)
Ocasionalmente,vocpodeacharquenecessriocaminharumusuriofinaldoseuaplicativodeproduo
atravsdeumaoperaosimples,comonavegaremumatabelaespecfica.Vocpodepensarqueseususurios
precisadeumacpiadoVisualFoxPro,afimdefazerisso.Noverdade!Comumaformasimples,umparde
linhasdecdigoeumpoucodeexpansomacro,vocpodefacilmentecriarumsimuladordejaneladecomando
paraajudarvocarealizaressatarefa.
378 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura11.5Simuladojaneladecomandoparaoseuexecutvel

Oformulriodejaneladecomandoconsisteemumacaixadeedioeumacaixalista.personalizadadoformulrio
ExecuteCmdmtodochamadosemprequeousuriodigitaumcomandonacaixadeedioe
pressionaa ENTERchave.Ocomandotambmadicionadocaixadelistagemusandoestecdigonaedio
dacaixadeKeyPressmtodo:

***Se<ENTER>teclapressionada,executeocomando
IFnKeyCode=13

***Verifiquesehumcomandoparaexecutar
IF!EMPTY(This.Value)
COMThisform

***Adicioneocomandoparaalistadohistricodecomando
.lstHistory.AddItem(ALLTRIM(This.Value))

***Executeocomando
.ExecuteCmd(ALLTRIM(This.Value))
ENDWITH

***Desmarqueacaixadeedio
This.Value=''
This.SelStart=0
FIMSE
***Nocoloqueumretornodecarronacaixadeedio!
NODEFAULT
FIMSE

Umcomandotambmpodeserselecionadoparaexecuo,destacandoonacaixadelistae
pressionandoENTERouclicandoduasvezessobreele.DacaixadelistagemdblClickmtodotemcdigoparaexibir
Captulo11:FormaseoutrasclassesVisual 379

ocomandoatualnacaixadeedioeinvocaroformulrioExecuteCmdmtodo.Ocomando
executado,atravsdesubstituiodemacro,nestemtodo:

LPARAMETERStcCommand

***Asadadiretapara_Screen
ativaratela

***Executaumcomando
&tcCommand

***Reactivaresteformulrio
AtivarjanelaFrmCommand

Seocomandonovlidoouquetenhasidodigitadoincorretamente,doformulriodeerrodemtodoexibe
amensagemdeerro.Issotudooquenecessrioparaforneceroseuexecutvelcomcomandobsico
funcionalidadejanela.

WrappersparafunescomunsdoVisualFoxPro(Exemplo:
CH11.VCX::cntGetFileeCH11.VCX::cntGetDir)
NsencontramoshcertasfunesdoVisualFoxProqueusamosumaeoutravezemnossa
aplicaes. GetFile()e GetDir()sodoisqueimediatamentevmmente. GetFile()
especialmenteproblemticoporqueaceitatantosparmetros.Nsnuncapodelembrardetodos
elesetemqueirparaoarquivodeajudacadavezquechamarafuno.Criandoumpouco
classewrapperparaeletemduasgrandesvantagens.Primeiro,eleforneceaosnossosusuriosfinaiscomumaconsistente
Interfacesemprequenecessrioselecionarumarquivooupasta.Emsegundolugar,notemosmaisparasereferira
Ajudaarquivocadavezqueprecisarusaro GetFile()funo.Todososseusparmetrossoagora
propriedadesdaclasserecipienteeelesestobemdocumentados.

380 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Figura11.6classesdewrapperparaGetFile()eGetDir()emao

CntGetFileaclasserecipienteusadoparaembrulharo GetFile()funo.constitudapordois
caixasdetextoeumbotodecomando.Aprimeiracaixadetextocontmonomedoarquivoretornadopela
afuno.Asegundacaixadetextocontmcaminho.Obotodecomandousadoparachamaro
GetFile()funocomosparmetrosapropriados.Atabelaaseguirlistaocostume
propriedadesutilizadasparaparmetrosaceitospela GetFile()

Captulo11:FormaseoutrasclassesVisual 381

Tabela11.2cntGetFilepropriedadespersonalizadasutilizadoscomoparmetrosparaGetFile()

Propriedade Explicao
cFileExtensions Especificaasextensesdosarquivosexibidosnacaixadelistaquando'Todososarquivos'
noestmarcada.Quando"Tables"escolhidoapartirdalistaArquivosdotipo,todososarquivos
comumaextenso.dbfsoexibidos.Quando"formas"escolhidoapartirdoArquivos
dalistaTipo,todososarquivoscom.scxe.VCXextensessoexibidos.
cText TextoparaalistadediretrionacaixadedilogoAbrir
cTitleBarCaption TtulobarradelegendaparaacaixadedilogoGetFile()
nButtonType 0:botesOKeCancelar.
1:OK,NeweCancelar
2:OK,NenhumeCancelar
"Untitled"devolvidocomocaminhoespecificadonacaixadedilogoAbrirse
nButtonType1eousurioescolheobotoNovo
cOpenButtonCaption LegendaparaobotoOK

Parausaraclasse,apenassolteonoformulrio,definatodasounenhumadaspropriedadesespecificadasacima,
evocestacabado.Onomecompletodoarquivoretornadodo GetFile()funo
armazenadonocostumedocontinercFileNamepropriedade.
CntGetDirenvolveonativo GetDir()funoeoperadeformamuitosimilar.o
parmetrosaceitospelafunosopropriedadespersonalizadasdorecipienteeafunode
valorderetornoarmazenadoemseucostumecPathpropriedade.

aulasdeapresentao
Umestoquedeaulasdeapresentaopadroirtornarsuavidacomoumdesenvolvedormuitomaisfcil.Estes
aulasdeapresentaosoasclassesgeralmentecompostasquevoc"enlatados"porqueeles
executartarefascomunsquesonecessriosemmuitaspartesdiferentesdoaplicativo.Estes
aulasdeapresentaotendemaseraplicaoespecfica.Porexemplo,umcabealhoouclienteVisual
classecabealhodaordemiracelerarodesenvolvimentodetodasasformasqueexibemclienteouordem
emformao.Nosasclassesdeapresentaocomoestespermitemquevocdesenvolvaaplicativos
maisrapidamente,elestambmdoaaplicaodeumaaparnciaconsistentequeserapreciado
porseususuriosfinais.
Emboraaulasdeapresentaotendemaserespecficosdoaplicativo,temosalgunsqueusamos
emmuitasaplicaes.

Postalclassedepesquisadecdigo(exemplo:CH11.VCX::cntAddresseGetLocation.scx)
Deummodogeral,menosvezesousuriofinaltemquetocaroteclado,oseumelhor
aplicativoserexecutado.Quandovocpodeencontrarmaneirasdereduziraquantidadedeinformaoquedeveser
entrou,vocpodereduzironmerodeerroscometidosduranteoprocessodeentradadedados.Isto
porclassesdepesquisacomooapresentadonestasecosototeis.Aentradadeendereo
informaesseprestaaestetipodeaplicao,poisaslistasdecdigospostaissoprontamente
disponvelapartirdeumavariedadedefontes.

382 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura11.7CdigoPostalformulriodepesquisachamadadeclassedeapresentao

QuandoocdigooulookupCEPmesapostalusadoparapreencherumconjuntodecamposdeendereo,
todasasinformaesrelevantes(cidade,estadoouprovnciaedopas,senecessrio)copiadodo
atabeladeconsulta.Isto,ainformaodeendereononormalizadaparaforadatabelacontendo
isto.Atabeladepesquisadecdigopostalsutilizadoparapreencheroscamposnecessrioscomacorreta
informaesseeleforencontrado.Normalmente,aslistasdecdigospostaissocompradosdeemantidoporuma
terceiro.Alteraressastabelaslocalmentenoumaboaidia,porquenohnenhumagarantiadeque
aprximaatualizaonovaiespancaressasmudanas.
AformadepopupchamadoapartirdocostumeFindCitymtododacntAddressapresentao
classe.Orecipientedeendereoseparececomissoepodeserdescartadoemqualquerformaqueprecisa
exibirumendereo:
Captulo11:FormaseoutrasclassesVisual 383

Figura11.8classecontinerendereoPadro

Nossorecipienteendereoeformulriodepesquisaassociadaesperarparaterumavisualizaocomparmetros
presentechamadolv_PostalCode.Estaexibiocontminformaessobreacidade,estadoepaspelapostal
cdigoetemaseguinteestrutura:

Tabela11.3Estruturadelv_PostalCodevistacomparmetros

Nomedocampo
Tipodedados
D escrio
Cidade Personagem NomedaCidade
sp_name Personagem NomeEstado/Provncia/Regio
Cdigopostal Personagem Cdigopostal
Ctry_Name Personagem Nomedopas
Pc_Key nmerointeiro CdigoPostalchaveprimria

Oparmetrovista,vp_PostalCode,determinacomoavistapreenchida.Ento,sevoc
querusaressaclasserecipienteesuaformadepesquisaassociado,voctemduasescolhas.Vocpode
criaraexibioparametrizadolv_PostalCodedesuamesa(s)depesquisa,comodescritoacima.Ou
vocpodemodificaraclassedecontinereoformulriodepesquisaparausaraestruturadoseuespecial
tabeladepesquisadecdigopostal.Oresultadoumaclassequepodeserusadosemprequevocprecisaparaexibirou
informaessobreoendereodepesquisanasuaaplicao.
AclassedecontinerendereotemumapropriedadepersonalizadachamadalPostalCodeChanged.Este
propriedadedefinidacomofalsaquandotxtPostalCodeseconcentrar.Eledefinidocomotruenotextodacaixade
InterActiveChangemtodo.Issofeitoporissotemosalgumaformadesaber,norecipientede
FindCitymtodo,seousuriorealmentedigitadoalgonacaixadetextodecdigopostal.
FindCityinvocadoquandoacaixadetextodecdigopostalperdeofoco.Claramente,seousurionofeznenhuma
alteraesnocontedodacaixadetexto,noqueremosparaprocurarocdigopostale
preencherascaixasdetextonocontiner:

vp_PostalCodeLOCAL,loLocation,lnTop,lnLeft

***Verifiqueparaverseousurioalterouocdigopostal

384 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

***Senadamudou,nsnoqueremosfazernada
ESE!This.lPostalCodeChanged
RETORNA
FIMSE
***Obtertodososregistrosnatabeladepesquisaparaestecdigopostal
vp_PostalCode=ALLTRIM(This.txtPostalCode.Value)
REQUERY('lv_PostalCode')

Seavistacontivermaisdoqueumnicoregistro,devemosapresentaraousurioumpopup
formulrioapartirdoqualelepodeselecionarumaentrada.Usamoso OBJTOCLIENTfunoparapassarotopoe
deixoucoordenadasparaaformadecontextodemodoquepodeposicionarsebemsobocdigopostal
caixadetexto:

***Semaisdeumacorrespondnciaencontrada,popupteladeseleodecidade/estado
IFRECCOUNT('lv_PostalCode')>1

***Obtercoordenadasemqueparaabriroformulrio
***Tornlabonitaparaqueeleaparecelogoabaixodacaixadetexto
lnTop=OBJTOCLIENT(This.txtAddress,1)+This.txtAddress.Height+
Thisform.Top
lnLeft=OBJTOCLIENT(This.txtAddress,2)+Thisform.Left

Aformadepopupmodal.Deveserseesperamosobterumvalorderetornoapartirdoformulrio
usandoaseguintesintaxe.Passamosaformaqueoparmetrodevistaeascoordenadasemque
eledeveposicionarse.Oformulriomodalretornaumobjetoquecontmosdetalhesdoregistrode
qualitemfoiselecionado,seumfoiselecionadonoformulriodepesquisa:

DOFORMGetLocationCOMvp_PostalCode,lnTop,lnLeftTOloLocation

***AgoravamosverificarloLocationparaveroqueoformulriomodaldevolvido
Comisso

***Umavezqueestamosarmazenandoinformaesendereonoregistrodocliente
***Queremostercertezadequenoespancarqualquercoisaquefoidigitado
***Quenoestnapesquisadecdigopostal
IF!EMPTY(loLocation.PostalCode)
.txtPostalCode.Value=loLocation.PostalCode
FIMSE
IF!EMPTY(loLocation.City)
.txtCity.Value=loLocation.City
FIMSE
IF!EMPTY(loLocation.StateProv)
.txtState.Value=loLocation.StateProv
FIMSE
IF!EMPTY(loLocation.Country)
.txtCountry.Value=loLocation.Country
FIMSE
ENDWITH
OUTRO

Sehouverumououtroregistrocorrespondenteounenhumregistrocorrespondente,noqueraparecer
aformadeselecocidade.Queremosapenasparapreencherascaixasdetextocomasinformaesno

Captulo11:FormaseoutrasclassesVisual 385

tabeladepesquisa.Sevocquiserpermitirqueousurioadicionarumanovaentradaparaatabeladereferncia,voc
chamaroformulriodemanutenoadequadaapartirdaquiseavistanocontmregistros:
poderia

Comisso
IF!EMPTY(lv_PostalCode.PostalCode)
.txtPostalCode.Value=lv_PostalCode.PostalCode
FIMSE
IF!EMPTY(lv_PostalCode.City)
.txtCity.Value=lv_PostalCode.City
FIMSE
IF!EMPTY(lv_PostalCode.Sp_Name)
.txtState.Value=lv_PostalCode.sp_name
FIMSE
IF!EMPTY(lv_PostalCode.Ctry_Name)
.txtCountry.Value=lv_PostalCode.Ctry_name
FIMSE
ENDWITH
FIMSE

AformaLocalizaoSeleousaosparmetrospassadosparaoInitmtodoparaposicionarse
apropriadamenteepreenchersuacaixadelista.Oobjetoqueretornaainformaoseleccionada
povoadaemsuaDescarregarmtodo.

Logingenricoforma(exemplo:LogIn.scx)
Quasetodasasaplicaesexigequeousuriologin,sejacomopartedeummodelodeseguranaou
simplesmentepararegistraronomedousurioatual(porissosabemosqueaculpaquandoascoisasvomal!).
Estaformapoucousaumaexibioquelistatodososnomesdeusuriosatuaisesuassenhasassociadase
verificaseosvaloresintroduzidossovlidos.Setudoestiverbem,oformulrioretornaonomedousurioatual,
casocontrrio,retornaumacadeiavazia.
Notesequenoimportacomovocrealmentearmazenarsuasinformaesdeusurio,desdeque
vocpodecriarumaexibiochamadalv_UserListcomdoiscampos(chamadousernameesenha)
contendoumalistadevlidosLogInNomesesuassenhasassociadasparausoporestaforma.

Figura11.9genricoformalogin

386 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Logindeconstruoforma
Aformalogindefatomuitosimplesetemtrspropriedadespersonalizadasetrspersonalizado
mtodos,comosegue:

Tabela11.4Loginpropriedadesdeformulrioemtodos

PEM Digitar Descrio


cUserName Propriedade nomedousurioLogIn,retornouapslogincomsucesso
nTentativas Propriedade Registrosnmerodetentativasfalhadasdelogem
nMaxAttempts Propriedade Determinaronmerodetentativasdeumusuriopermitidoantesdeshutdown
Cancelar Mtodo FechaLogInFormeretornaumacadeiavazia
ValidateUserName Mtodo VerificaodoNomedeUsurioestnalistaatualdeusuriosvlidos
ValidatePassword Mtodo Verificaodesenhaestcorretaparaonomedeusurio

Quandooformulrioinstanciado,ofocoestdefinidoparaocampodeentradaNomedousurio.AValidmtodo
destecampopermitequeousuriouseoboto"Cancelar"parafecharoformulrio,mascasocontrriovai
nopermitirqueofocoemabandonarocampoamenosqueoformulrioValidateUserNamemtodoretorna .T.Este
formulriofoicriadoparaqueambasnomedeusurioesenhadeentradasosensveiscaixa(embora
vocpodepreferirumaabordagemdiferente).OValidateUserNamemtodomuitosimplese
apenasverificaparaverseoquefoidigitadopelousuriocorrespondeaumaentradanaformade
lv_userlistvistadaseguinteforma:

lv_UserListSELECIONAR
***Obterapenasumacorrespondnciaexata!
LOCALIZARPARAALLTRIM(lv_UserList.UserName)==ALLTRIM(
Thisform.txtUserName.Value )
SEACHADO()
***Onomedeusurionovlido
Thisform.txtUserName.Value=''
MESSAGEBOX('NsnoreconhecloPorfavor,reintroduziroseunome.',
16,'Nomedeusurioinvlido')
RETURN.F.
OUTRO
***Nomedeutilizadorvlidoguardloparaapropriedadedeformulrio
Thisform.cUserName=ALLTRIM(Thisform.txtUserName.Value)
FIMSE

Ocampodeentradadesenhacomportasedeformamuitosemelhante,emboraumavezqueestesacessvel
umavezqueumnomedeusuriovlidofoiinserido,oValidatePasswordmtodosimplesmenteverificao
atualmenteselecionadoregistroparaverseasenhafornecidacorrespondeaonecessrioparaousurio
nome:

lv_UserListSELECIONAR
IFALLTRIM(lv_UserList.Password)==ALLTRIM(Thisform.txtPassword.Value)
***Tudoapenaspeachyafiado
OUTRO
***Senhaestavaerrada!
Thisform.txtPassword.Value=''
***ContadordetentativasIncremento

Captulo11:FormaseoutrasclassesVisual 387

Thisform.nAttempts=+1Thisform.nAttempts
***Verifiquequenotenhamatingidoastentativasmximaspermitidas
IFThisform.nAttempts=Thisform.nMaxAttempts
***Aindanenhumaboalanceusurioparafora!
MESSAGEBOX('VocobviamentenolembradasuasenhaGoodbye.!',
16,'muitastentativasdeloginerrados')
Thisform.Cancel()
OUTRO
***Permitiroutratentativa
MESSAGEBOX('passwordinvlido.Porfavor,reentrar.',16,'senhainvlida')
RETURN.F.
FIMSE
FIMSE

OnmerodetentativasqueumusuriotempermissoparafazercontroladapelosnMaxAttempts
propriedade,queestdefinidopara3porpadro.

Usandoaformalogin
Aformadefinidacomoumaformarestritademodoaqueelapodeserexecutadanarotinadearranquedeum
aplicativousandoo DOFORM<nome>para<varivel>sintaxe.Aaotomadaapsologin
formulrioexecutadovontade,obviamente,dependedoresultadoeumcdigosemelhanteaoseguintepodeserusado
noprogramadearranqueparaaaplicao:

LIMPARTUDO
CLARO
FAZERlogindoformulrioparalcUserId
IFEMPTY(lcUserID)
***Falhanaautenticao
SAIR
FIMSE
***Loginfoibemsucedidacontinuar

Aclassecaixadetextodepesquisa(Exemplo:CH11.VCX::txtlookupeContacts.SCX)
Muitasvezes,possvellidarcomapesquisaeexibiodeinformaesemumformulriosimples,definindo
umarelaoparaatabeladepesquisa.Se,noentanto,atabeladepesquisanotemumadequado
ndicetagparausaremumarelao,vocprecisadeoutramaneiradefazerisso.Isto,quandotilter
umacaixadetextoquepodemexecutarumapesquisae,emseguida,exibiroresultado.Aclassecaixadetextode
usadoparaexibirotipodecontatonaformaContacts.scxfotoabaixo,permitequevocmanipule
pesquisa,
estatarefameramentedefiniralgumaspropriedades.
388 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura11.10Lookupclassecaixadetextoemuso

Acaixadetextoprojetadoparaserusadonoligadoeemvezdissousaatabelaecampoespecificado
nasuacControlSourcepropriedadeparadeterminarovalordevesertomandocomoorigemdocontrole.

Tabela11.5Propriedadespersonalizadasparaaclassedecaixadetextodepesquisa

Propriedade Descrio
cAlias aliasdatabelaaserprocurado
cControlSource Mesaecampoquecontmovalordechaveparausarna
olhoparacima
cRetField Campodatabeladepesquisacujovalordeveserdevolvido
cSchField Campodatabeladepesquisaemqueachaveaserprocurado
cTagToUse Nomedocdigodendiceparausarnapesquisa(Opcional)

Inicializaracaixadetextodepesquisa
Quandoacaixadetextoinicializado,eledefineseuvalorparaocontedodocampoespecificadopor
avaliandosuacControlSourcepropriedadeemseuInitmtododaseguinteforma:

DODEFAULT()
***Copiarinfontedecontrolo
IFEMPTY(This.ControlSource)E!VAZIO(This.cControlSource)
This.Value=eval(This.cControlSource)
FIMSE

Atualizandoolookup
Ummtodopersonalizado(UpdateVal)chamadoapartirdonativoActualizarmtodoparamanipularoreal
pesquisacomosegue:

Captulo11:FormaseoutrasclassesVisual 389

lcRetFldLOCAL,luSchVal,lcSchFld,luRetVal
***Seatabelafoiespecificado,adicionloPesquisaenomesRetornodecampo
SE!Vazia(THIS.cAlias)
lcRetFld=This.cAlias
+'.'+This.cRetField

lcSchFld=This.cAlias
+'.'+This.cSchField

OUTRO
lcRetFld=This.cRetField
lcSchFld=This.cSchField
FIMSE
***Obterovalordechaveatual
luSchVal=eval(This.cControlSource)

ESE!VAZIO(luSchVal)
***DoLookupusandoondice,casotenhasidoespecificado
IFEMPTY(This.cTagToUse)
luRetVal=PROC(&lcRetFld,luSchVal,&lcSchFld)
OUTRO
luRetVal=PROC(&lcRetFld,luSchVal,&lcSchFld,This.cTagToUse)
FIMSE
OUTRO
luRetVal=""
FIMSE
***Atualizarexibio
ESE!VAZIO(luRetVal)
This.Value=luRetVal
OUTRO
This.Value=""
FIMSE

Usandoaclassecaixadetextodepesquisa
Umavezqueabaseemqueaclassefuncionaquesemprenoligado,elespodeserusadocomoum
sdeleituradecontrole"display".Almdisso,nopodeserusadonointeriordeumagradeporquehaveria
nenhumamaneiraparaocontroleparadeterminar,paraqualquercoisaquenosejaalinhaatual,oquedeveser
exibida.Dadasestaslimitaes,aclasseaindatilparaasocasiesemque
necessriaparaapresentaroresultadodeumapesquisanumambienteinteractivo.Tudoquevocprecisafazer
definaseucostumecControlSourceaonomedocampoquecontmachaveestrangeirado
tabeladepesquisa.Emnossoformulriodeexemplo,esteContact.ct_key.Coloqueonomedatabeladepesquisaem
seuspersonalizadoscAliaspropriedade.CSchFieldecRetFieldpropriedadesdeveconterosnomesdos
camposnatabeladepesquisaquecontmovalordechaveeotextodescritivoparaexibir.Seo
tabeladepesquisaindexadasobreestevalordechave,coloqueonomedeumtagnocostumedocontrole
cTagToUsepropriedade.

Concluso
Umestoquedeaulasdeapresentaogenricosvailhedarumgrandeimpulsoaprodutividadeporquevocpode
uslosumaeoutravez.Noselesvoajudaraproduziraplicativosmaisrapidamente,
quetambmirajudarareduzironmerodeerrosquevoctemquecorrigir,porqueelessotestadoscada
vezquevocuslos.Esperamosqueestecaptulotenhalhedadoalgumasclassesquevocpodeusar
imediatamente,bemcomoalgumasideiasparaacriaodenovasclassesquesoaindamaisteis.

390 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo12:Ferramentasdeprodutividadedodesenvolvedor
391

Captulo12
Ferramentasdeprodutividadedo
"Emumasociedadeindustrialqueconfundetrabalhoeprodutividade,anecessidadedeproduzir
desenvolvedor
semprefoiuminimigododesejodecriar."("Arevoluodavidacotidiana"por
RaoulVaneigem)

Asferramentasincludasnestecaptuloforamdesenvolvidosparatornarnossasvidascomo
maissimples.Nenhumdestesestariamnormalmentedisponveis(oumesmotil)emumaplicativo,
desenvolvedores
uttodossomembrospermanentesdosnossoskitsdeferramentasdedesenvolvimento.Ditoisto,
essasferramentasrealmenteterminado.Hsemprealgomaisquepoderiaseradicionadoe
nenhumdos
nsesperamosquevoc,comons,vaiapreciaradicionarseusprpriostoques.

Form/classeeditorbiblioteca(Exemplo:ClasEdit.prg)
Comovocprovavelmentejsabem,osformatosdoVisualFoxProForm(SCXarquivo)eClasse
Library(VCXarquivo)soidnticos.AmbossotabelasrealmenteVisualFoxProeanica
diferenasestonocaminhoquedeterminadoscampossoutilizadosequeumSCXarquivospodecontero
objetodetalhesparaumnicoformulrio,aopassoqueumabibliotecadeclassepodecontermuitasclasses.Desdeque
soambasastabelaspodemos'hack'lossimplesmenteusandooarquivodiretamentecomoumatabelaeabrindoa
eles
mesaemumajaneladenavegao.Noentanto,istonofcildefazerporque,comaexcepodea
primeirostrscampos(Platform,UniqueIDeTimstamp),todaainformaomantidanomemo
Campos.Ento,criamosumformulrioparaexibirasinformaescontidasemqualquerumSCXouum
ArquivoVCXmaisfacilmente(Figura12.1abaixo).

Figura12.1SCXeditor/VCX
392 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Porquensprecisamosdisso?Quantasvezesvocjquissercapazdealteraraclasseemque
algumobjetocontidoemumformulriobaseadoouparasercapazderedefinirabibliotecadeclassespaiparaum
classe?Sevocqualquercoisacomons,algoquemuitasvezesquerfazerenohoutra
maneirasimplesdefazerissodoqueeditandodiretamenteoarquivoSCXouVCXrelevante.Amaioria
camposimportantesnosarquivosestolistadosnaTabela12.1aseguir:

Tabela12.1PrincipaiscamposemumarquivoSCX/VCX

FieldName Usadopara
CLASSE Contmaclasseemqueoobjetobaseado
ClassLoc Seaclassenoumaclassebase,ocampocontmonomedoarquivoquecontmaclasseVCX
definio.Seaclasseumaclassebase,ocampoestvazio.
baseclass Contmonomedaclassebaseparaesteobjeto
objname ContmNomedainstnciadoobjeto
PAI Contmonomedorecipienteprimriodoobjeto
PROPRIEDADES Contmumalistadetodasaspropriedadesdoobjetoeseusvaloresquenosoapenasesquerdana
valorespadro
PROTEGIDO Contmumalistademembrosprotecteddoobjeto
MTODOS Contmmtododecdigodoobjeto/evento
ObjCode Contmaversocompiladadocdigodoeventoemformatobinrio
OLE ContmdadosbinriosusadosporcontrolesOLE
OLE2 ContmdadosbinriosusadosporcontrolesOLE
Reservado1 Contm'Class'seesteregistrooinciodeumadefiniodeclasse,deoutraformavazia
Reserved2 Lgicoverdadeiro(.T.)SeaclasseOLEPUBLIC,casocontrriolgicafalsa(.F.)
Reserved3 Listatodososmembrosdefinidospelousurio.Prefixo"*"ummtodo,"^"umArray,casocontrrio,uma
Propriedade
RESERVED4 caminhorelativoeonomedoarquivodobitmapparaumconedeclassepersonalizada
Reserved5 caminhorelativoeonomedoarquivoparaumgerentedeprojetopersonalizadoouconedeclassenavegadordeclasse
RESERVED6 ScaleModedaclasse,PixelsouFoxels
RESERVED7 Descriodaclasse
RESERVED8 Onomedoarquivo#include

Detodosestescampos,quesomaispropensosaquereralteraraobjname,CLASSe
ClassLoccamposeestessoostrscamposquecolocamosemprimeirolugarnogrid.aedio
regiesabaixodagrelhademostrarocontedodoscamposdepropriedadesemtodosparacadalinhaem
oarquivoe,emboravocpodeeditarasconfiguraesdepropriedade,oumesmocdigodomtodo,diretamentenestes
janelasnspreferimostrabalharcomafolhadepropriedades.(Noforamencontradasquaisquerproblemas
fazlodiretamente,maselenosesenteseguradealgumaforma!)
Umrecursotildaformaquepodemosentrarcomandaumalinhadiretamenteno
caixadee'Run'executlos.Comomostraailustrao,estetilparamanipulaomundial
alteraesnositensdentrodeumabibliotecadeformulrioouclasse.

UsandooeditorSCX/VCX
Paraexecutaroeditorusamosumprogramadeinvlucrosimples,chamadoclasedit.prg(queestincludo
comocdigodeexemploparaestecaptulo).Issosimplesmenteexecutadooformulriodentrodeumloopenquantouma
novoficheiroVCXSCXouseleccionadoapartirdodilogo.Assimquenenhumaseleoforfeita,oloop

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
393

sadaseliberatudo.CadavezqueoeditorfechadooarquivoSCXouVCXre
compiladoparagarantirqueasalteraesqueforamfeitasestodevidamenteguardado.

**********************************************************************
*Programa :ClasEdit.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:ExecutaoeditorSCX/VCXdentrodeumloopatquenenhumarquivo
* :selecionadonoGetFile()Dialog
**********************************************************************
lcSceFileLOCAL
CLARO
LIMPARTUDO
FECHETUDO
***Fechequaisquerbibliotecasabertas
SETCLASSLIBTO
***ESCX/ArquivosVCX
Seutilizados('vcxedit')
USOEMvcxedit
FIMSE
***Inicializaravariveldecontrole
DoWhile.T.
***Obteronomedoarquivodeorigem
lcSceFile=GETFILE('SCXVCX')
IFEMPTY(lcSceFile)
SADA
FIMSE
***AbrirarquivodeorigemedefiniromododebufferparaTabelaOptimistic
USE(lcSceFile)IN0ALIASvcxeditEXCLUSIVE
CURSORSETPROP('Buffering',5)
***Executaroformulrio
DOFORMClasEditCOMlcSceFile
READEVENTS
***Compilaro/VCXarquivoSCX
IFJUSTEXT(lcSceFile)="SCX"
COMPILEFORM(lcSceFile)
OUTRO
COMPILECLASSLIB(lcSceFile)
FIMSE
ENDDO

InspectorForm(Exemplo:InspFprm.scxeShoCode.scx)
Estapequenaferramentasimplesforneceacapacidadedeinspecionarumformulrioetodososseusobjetos,enquantoque
formarealmenteestsendoexecutado.Existemvriasmaneirasdefazerisso,mascomoesteporque
simples,fcildeusarepermitenosterumaviso"rpidaesuja'emqueumformulrioestfazendoquando
estamosaexecutlonomododedesenvolvimento.Eletambmnospermitedefiniroualteraraspropriedadesdo
formar,ouqualquerobjetonoformulrio,deformainterativa.
Oformulriofoiconcebidoparaaceitarumarefernciadeobjetoparaumaformaactivaeparaexibir
informaessobreessaformaemsuapageframe.Normalmenteusamos,definindoumnaetiquetaKey
comandocomoeste:

ONKEYLABELCTRL+F9DOFORMULRIOinspFormCOM_SCREEN.ACTIVEFORM

394 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Apginadeinformaesdatabela
Quandoativado,apgina"InformaesTable"exibidaacaixadelistanestapginamostraqualquer
tabelasquesousadaspelaformaalvo.(Seoformulrionoutilizatabelas,anicaentradana
estacaixadelistaser"Nenhumtabelasusadas.')Selecionarumatabelanalistapreencheoassociado
camposquemostramostatusdessamesaeagradequemostraosdetalhesdoregistoactual.

Figura12.2InspectorFormpginadeinformaesdatabela
Apginadeinformaesdoformulrio
Asegundapginadoformulriocontmumacaixadelistagemquepreenchidoquandooformulrio
inicializado,utilizandoosnativos AMEMBERS()funo,comtodasaspropriedades,eventos,mtodosequalquer
objetosdoformulriodedestino.

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
395

Figura12.3FormulriodeInspectorformarpginadeinformaes

Clicandoduasvezesemummtodooueventonestalistatrazumajanelamodalcontendo
qualquercdigoassociadocomessemtodonaforma(Nota:nicocdigoquetenhasidoadicionada
directamenteparaaformavisveldestaforma,herdadacdigonoservistoaqui):
396 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura12.4InspectorFormexibiodocdigo

Clicandoduasvezesemumapropriedadetrazumacaixadedilogoquelhepermitealterarovalorde
essapropriedade.(Aviso:Nohnenhumaverificaodeerroassociadaaessafunoesevoctentar
paradefinirumapropriedadequesomenteleitura,VisualFoxProirgerarumerro.Esteum"rpidoesujo"
ferramenta!)

Figura12.5FormulriodeInspectordilogodeconfiguraodepropriedade

Finalmente,clicandoduasvezesumobjetopreencheaterceirapginadoformulriocomaspropriedades,
eventos,mtodosequaisquerobjetoscontidosparaesseobjeto.

Apginalistadeobjetos
Aterceirapginausadaparaexibirosdetalhesdequalquerobjetonoformulrio.Talcomoacontececomalistaforma,
duplocliquesobreummtodooueventoexibequalquercdigoassociadoaessemtodoe
duplocliquesobreaPropriedadeantecipaodilogodeconfigurao.Notesequeocdigomtodo
recuperadousandoo GETPEM()funoenopareceserumbugnestafunonaVerso
6,0porissonovairecuperarocdigoqueexisteemmtodosdeuma"pgina".Cdigoemqualquerobjetoemumapgina,

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
397

ouemmtodosdopageframe,recuperadocorretamente,masosmtodosdapginasempremostramcomo
vazia,mesmoquandonotiverocdigononveldeinstncia.
Figura12.6InspectorFormpginadeinformaesdoobjeto

Clicandoduasvezesemumobjetonacaixadelistaderepreenchealistacomosdetalhesdoque
objetoeatualizaalinha'doobjetoatual'napgina.botodireitodoratonasselecionacaixadelista
opaidoobjetoatual(sehouver)etornapossvelsubiredescero
hierarquiadeobjetos.

Construodoformulriodeinspeco
OsIniteSetUpFormmtodos
OInitmtodousadoparareceberearmazenararefernciadeobjetoparaoformulrioaserinspecionadopara
umapropriedadedeformulrio.Emseguida,eleforaoformulriodeinspecoemdatasessioneconjuntosdoformulrio
sualegendaparaincluiralegendadoformulriochamado.FinalmenteelechamaocostumeSetUpForm
dechamada
Mtodo:

LPARAMETERStoSceForm

IFVARTYPE(toSceForm)#"O"
***Nopassouumobjetodeformulrio
RETURN.F.
FIMSE

398 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

COMThisForm
***SalverefernciachamadaForm
.oCallingForm=toSceForm
***SituadoDataSessionamesmaqueoFormulriodechamada
.DataSessionID=.oCallingForm.DataSessionID
***SetUpCaption
This.Caption="InspecionandoForma:"+.oCallingForm.Caption
***Configuraresteformulrio
.SetUpForm()
ENDWITH

OSetUpFormmtodoprimariamenteresponsvelporpreencheracaixadelistagememumapgina
dorelatriodecontrolocomumalistadastabelassendoutilizadopelaformadechamada.Emseguida,chamao
personalizadosUpdFormPropsmtodoparapreencheracaixadelistanapgina"membrosformam"antes
retornandoocontroleparaprocessodeinicializaodoformulrio.OcdigorealnoSetUpFormmtodo
:

latablesarraylocal[1]
lnTablesLOCAIS
***ObterumalistadetabelasemusonoDataSessiondoformulriodechamada
lnTables=AUSED(latables,ThisForm.DataSessionId)
***Construirumcursorparatodasastabelasabertas
CRIARcurAliasCursor(

CTableC(30),
NareaI(4))
IFlnTables>0
INSERTINTOcurAliasDElatablesARRAY

OUTRO
INSERTINTOcurAliasVALUES('Nohtabelasusadas',0)

FIMSE
***Configurarastabelasdecaixadelistagem
COMThisForm.pgfMembers.Page1.lstTables
.RowSourceType=6
.RowSource ="Curalias.cTable,Narea"
.Requery()
.ListIndex 1=
ENDWITH

***Vejaaspropriedadesdoformulrio
ThisForm.UpdFormProps()

OUpdTablemtodo
EstemtodopersonalizadochamadoapartirdaActivatemtododapgina'Tabelas'eresponsvel
parapreencheroscamposdestatus,eagradenessapgina,comosdetalhesparaomomento
tabelaselecionada.OmtodotambmchamadoapartirdoInterActiveChangemtododecaixadelistagem
umapginaparaqueosdetalhessomantidossincronizadoscomatabelaselecionadanomomento.

lcTableLOCAL,lcMode,lnMode,lnSelect,lcSafety,lcField,lcFVal
COMThisForm
***Bloquearoecrduranteaactualizao
.LockScreen=.T.

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
399

COM.pgfMembers.page1
lcTable=ALLTRIM(.lstTables.Value)

***Senomesasusadas
IFlcTable=='Nohtabelasusadas'
Thisform.Lockscreen=.F.
RETORNA
FIMSE

***Contagemderegistros&NmerodoRegistro
.txtRecCount.Value=RECCOUNT(lcTable)
.txtCurRecNo.Value=IIF(EOF(lcTable),"NoEOF()",RECNO(lcTable))

***AtualTagndice&ExpressoKey
.txtCurTag.Value=ORDER(lcTable)

***Modobuffer
lcMode=""
lnMode=CURSORGETPROP('buffer',lcTable)
lcMode=IIF(lnMode=1,"sembuffering',lcMode)
lcMode=IIF(lnMode=2,'Rowpessimista',lcMode)
lcMode=IIF(lnMode=3',linhaotimista',lcMode)
lcMode=IIF(lnMode=4,'Tabelapessimista',lcMode)
lcMode=IIF(lnMode=5",linhaotimista',lcMode)
.txtBufMode.Value=lcMode

***CampoStatus
IFlnMode>1
.txtFldState.Value=NVL(GETFLDSTATE(1,lcTable),"NoEOF()")
OUTRO
.txtFldState.Value=""
FIMSE
ENDWITH

***AtualrecordeDetalhes
lnSelect=SELECIONAR()
Seutilizados('currec')
lcSafety=SET("SAFETY")
OFFSEGURANASET
ZAPINcurrec
SETSAFETY&lcSafety
OUTRO
CRIARCURSORcurRec(
cFieldC(40),
cValueC(60))
FIMSE
SELECT(lcTable)

***Vejaosdetalhesdoregistro
PARAlnCnt=1afunoFCOUNT()
lcFieldcampo=(lnCnt)
lcFVal=TRANSFORM(&lcField)
INSERTINTOVALUEScurrec(lcField,lcFVal)
PRXIMO
SELECT(lnSelect)

***Preenchereatualizaragrade
COMThisForm.pgfMembers.Page1.grdCurRec
.RecordSource="Currec"
400 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

GOTOPINcurrec
.SetFocus()
ENDWITH

***Solteoecr
.LockScreen=.F.
ENDWITH

OUpdFormPropsmtodo
Estemtodopersonalizadosimplesmenteobtmalistademembrosdeformulriousandoosnativos AMEMBERS()
funo.Detalhessoescritosparaumcursorlocal.Osnicositenscomplicadasaquiestoquealguns
propriedadesnosodirectamenterecupervel,ouporqueelessorealmentecolees(porexemplo,
'Comandos)ouporqueelesprpriossorefernciasdeobjetoqueapenastmvaloresdentrodo
chamandoforma(porexemplo,"ActiveControl').Estessoespecificamenteexcludoseapalavrachave
'Referncia'inseridodemodoquenovaicausarproblemasmaistarde:

ArraylocallaObj[1]
LOCALlnObj,lnCnt,lcProp,lcPName,lcPVal
COMThisForm
***Visordateladebloqueioduranteaactualizao
.LockScreen=.T.
***Obterumalistadetodasaspropriedades,mtodosemembrosdeobjeto
lnObj=AMEMBERS(laObj,ThisForm.oCallingForm,1)
***Criarascusorsnecessrias
Seutilizados('curFormProp')
USOEMcurformprop
FIMSE
CRIARCURSORcurFormProp(
cPropC(40),
cValueC(40))

***cursoresPreencherformulriodePropriedadeelistadeobjetos
PARAlnCnt=1alnObj
Seforinferior(laObj[lnCnt,2])="objeto"
VALORESINSERTINTOcurFormProp(laObj[lnCnt,1],"Objeto")
OUTRO
lcProp=LOWER(laObj[lnCnt,2])
IFlcProp="propriedade"
lcPName=LOWER(laObj[lnCnt,1])
***Ignorarpropriedadesqueretornamrefernciasdeobjeto/colees
SE'controles'lcPName=='colunas'OrlcPName=='pginas'ORlcPName==
'Botes'ORlcPName==OU'objetos'lcPName==
ORlcPName=='pai'ORlcPName=='ActiveControl'
ORlcPName=='ActiveForm'
VALORESINSERTINTOcurFormProp(laObj[lnCnt,1],'Referncia')
LOOP
FIMSE

***Casocontrrio,obterovaloratual
lcPVal=TRANSFORM(EVAL("ThisForm.oCallingForm."+laObj[lnCnt,1]))
VALORESINSERTINTOcurFormProp(laObj[lnCnt,1],lcPVal)
OUTRO
VALORESINSERTINTOcurFormProp(laObj[lnCnt,1],laObj[lnCnt,2])
FIMSE
FIMSE

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
401
PRXIMO

***Configuraroformulriodepropriedadedecaixadelistagemnapgina2
COMThisForm.pgfMembers.page2.lstFormProps
.RowSourceType=6
.RowSource ="CurFormProp.cProp,cValue"
.Requery()
.ListIndex 1=
ENDWITH

***Desbloquearatela
.LockScreen=.F.
ENDWITH

OUpdObjPropsmtodo
EstemtodopersonalizadoessencialmenteomesmoqueoUpdFormPropsmtodoacima,exceptoqueele
atualizareferncia'atualobjeto'doformulriodeinspecoerecuperaasPEMsporqualquer
objetoestarefernciaestapontando.Asinformaessoexibidasnacaixadelistagemno
pginatrsdoformulriodeinspeco:

LPARAMETERStlSetForm
ArraylocallaObj[1]
LOCALloFormObj,lnObj,lnCnt,lcProp,lcPName,lcPVal

COMThisForm
***Congelamentodeteladuranteaactualizao
.LockScreen=.T.
ESE!tlSetForm
***UpdateaatualObjectReference
loFormObj=eval("This.oCurobj."
+ThisForm.pgfMembers.page3.lstObjProps.Value)
***SalveobjetoatualRef
.oCurObj=loFormObj
OUTRO
loFormObj=.oCurObj
FIMSE
lnObj=AMEMBERS(laObj,loFormObj,1)

***Criarcursorlocal
Seutilizados('curobjlist')
USOEMcurObjList
FIMSE
CRIARCURSORcurObjList(
cPropC(40),
cValueC(40))

***CursorPreencherListadepropriedades
PARAlnCnt=1alnObj
lcProp=LOWER(laObj[lnCnt,2])
IFlcProp="propriedade"
lcPName=LOWER(laObj[lnCnt,1])
***Ignorarpropriedadesqueretornamrefernciasdeobjeto/colees
SE'controles'lcPName=='colunas'OrlcPName=='pginas'ORlcPName==
'Botes'ORlcPName==OU'objetos'lcPName==
ORlcPName=='pai'ORlcPName=='ActiveControl'

402 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ORlcPName=='ActiveForm'
VALORESINSERTINTOcurObjList(laObj[lnCnt,1],'Referncia')
LOOP
FIMSE

***Casocontrrio,obterovaloratual
lcPVal=GETPEM(loFormObj,laObj[lnCnt,1])
VALORESINSERTINTOcurObjList(laObj[lnCnt,1],TRANSFORM(lcPVal))
OUTRO
VALORESINSERTINTOcurObjList(laObj[lnCnt,1],laObj[lnCnt,2])
FIMSE
PRXIMO

***Configureoobjetodepropriedadedecaixadelistagemnapgina3
COM.pgfMembers.page3.lstObjProps
.RowSourceType=6
.RowSource ="CurObjList.cProp,cValue"
.Requery()
.ListIndex 1=
ENDWITH

***AtualizaodeControledeCorrente
.pgfMembers.page3.txtCurObj.Value=SYS(1272,.oCurObj)

***Teladedesbloqueio
.LockScreen=.F.
ENDWITH

Oscomportamentosdecaixadelista
OnicooutrocdigosignificativonoformulriodeinspecoestnoDoubleClickmtododalista
caixasemambasaspginasdoisetrse,adicionalmente,naRightClickmtododecaixadelistagem
pginatrs.ORightClickcdigomuitosimpleseapenasdeterminaseomomento
objetoselecionadotemumpaie,nessecaso,fazcomqueesseobjetooobjetoatualantesdechamaro
deformaUpdObjPropsmtodocomosesegue:

COMThisForm
***VerifiqueparaPais
IFTYPE("ThisForm.oCurObj.Parent")="O"
***FaaatualParent
.oCurObj=.oCurObj.Parent
.updObjProps(.T.)
OUTRO
***Fazernada
MESSAGEBOX("Objetoatualnotempai",16,"nopodevoltaratrs")
FIMSE
ENDWITH

OcdigonoDoubleClickmtodosumpoucomaiscomplexoeusaoregistroatual
nocursorparaqueacaixalistaobrigadoadeterminarqueaonecessria.Ocdigopara
ambasascaixasdelistagemessencialmenteomesmoeseparececomisso:

LOCALlcStr,loCurObj,lcProperty,LCType
COMThisForm

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
403

DOCASO
CASEINLIST(curObjList.cValue,'mtodo','Evento')
***Enstemosumobjeto
IFVARTYPE(ThisForm.oCurObj)="O"
***Obteveocdigonomtodo
lcStr=GETPEM(ThisForm.oCurObj,ALLTRIM(curObjList.cProp))
IFEMPTY(lcStr)
lcStr="NoCode,aestenvel"
FIMSE
***Mostrarajaneladecdigo
FAZERshoCodeformulriocomlcStr,
ThisForm.oCurObj.Name+"::"+ALLTRIM(curObjList.cProp)
FIMSE

CASEcurObjList.cValue="Objeto"
***TernovasPEMSObjeto
.UpdObjProps(F.)

CASEcurObjList.cValue#"Referncia"
***DeveserumapropriedadeGetseuvaloratual
loCurObj=EVAL("ThisForm.oCurObj."+ALLTRIM(curObjList.cProp))
***Eonome
lcProperty=SYS(1272,ThisForm.oCurObj)+"."+ALLTRIM(curObjList.cProp)
***ETipodedados
LCType=TYPE("loCurObj")
***Obternovovalor
DOFORMSetPropCOMlcProperty,LCType,loCurObjTOluNewVal
***Atualizarapropriedade
lcProperty="ThisForm.oCurObj."+ALLTRIM(curObjList.cProp)
&LcProperty=luNewVal
***Atualizeaexibio
.UpdObjProps(.T.)

DEOUTRAFORMA
***Ignoreisto!
ENDCASE
ENDWITH

Nossaforaindustrialgradebuilder(Exemplo:gridbuild.vcx::gridbuild)
Quandovoctomaonossosuperduper,aforaindustrialdagradedoconstrutorparaumtestdrive,vocvai
provavelmenteseratingidoporsuaestreitasemelhanacomoconstrutordegradeVisualFoxPronativa.este
semelhananoporacaso.Microsoftenviaocdigofonteparaosseusassistenteseconstrutorescom
VisualFoxProverso6.0.Ento,sevocprecisardefuncionalidadeespecialdeumconstrutor,vocno
jnotmdereinventararoda.VocpodepersonalizarprpriosconstrutoresdoVisualFoxPro.
EstamosespecialmentegratosaDougHenningporcompartilharconoscoseutrabalhoinicialnogrid
construtor.feitoodesenvolvimentodestavariantedoconstrutormuitomaisfcil.
404 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura12.7construtordegradecomumafuncionalidademelhorada

Parautilizaronossomelhoradoconstrutor,vocprimeiroprecisaregistrlo,executando
GridBuildReg.prgincludocomocdigodeexemploparaestecaptulo.Esteprogramaadicionaumnovo
registroparaBuilder.dbfnoFoxProassistentessubdiretrioVisual.Builder.appusaestatabelapara
determinarqualoprogramaconstrutorparaserexecutado.
AgoravocprecisarreconstruiroGridBuild.pjx,oprojetoquecontmonossoindustrial
construtoregradedeforaestincludocomocdigodeexemploparaestecaptulo.Sevocnotem
feitoisso,vocdevedescompactarocdigofonteparaosconstrutoresquefornecidocomVisual
FoxPro6.0.VocvaiencontrlonaHOME()+'\TOOLS\xSource\XSOURCE.ZIP'.descompactao
oarquivousandoasconfiguraespadrocriaumaestruturadediretriosquecomeano
HOME()+'\TOOLS\vfpsource'eseestendeporvriosnveis.Depoisdeterdescompactouo
cdigofonte,sigaestespassosparainstalaroconstrutordegradedeforaindustrial:
1.CopieosarquivosGridBuild.pjxeGridBuild.pjtdodiretrioquecontmo
cdigodeamostraparaestecaptuloparaHOME()+'\TOOLS\vfpsource\construtores.'

2.CopieosarquivosGridMain.prg,GridBuild.vcxeGridBuild.vctdodiretrio
quecontmocdigodeexemploparaestecaptulo
HOME()+'\TOOLS\vfpsource\CONSTRUTORES\GRIDBLDR'pasta.

3.Agoravocestprontoparareconstruiroprojeto.ConstruirGridBuild.Appequandoest
terminar,movaoappparaolar(+)'\Wizards'diretrio.
Captulo12:Ferramentasdeprodutividadedodesenvolvedor
405

Apartirdeagoraoseuconstrutorgradeterfuncionalidadesnovasemelhoradas.Sevocreinstalar
VisualFoxProouaplicarumservicepackquesubstituiBuilder.dbf,tudoquevocprecisafazerexecutarnovamente
GridBuildReg.prgpararegistrarnovamenteGridBuild.appcomooconstrutordegradepadro.
Ento,porqueprecisamosdeumconstrutordegrademelhorada?OconstrutordegradeVisualFoxPronativotem
asseguintesdeficincias:

Notamanhocolunasligadascorrectamente,ouseja,combasenalarguradasua
ControlSource
Nonomearcolunasligadaseseuscontrolescontidosdeformaadequadaparao
colunaControlSource
Nohnenhumamaneiradesaberseautilizaodeclassespersonalizadas

Estaversodoconstrutorabordatodosostrsdestasquestes,mas,depoisdelutarparachegar
nossamelhoriasdetrabalho,comeamosanosperguntarsenopoderiatersidomaisfcilescreveranossa
prprioconstrutorapartirdozero.FoimuitobomdaMicrosoftparanosdaracessoaocdigofontepara
estesconstrutores.Teriasidoaindamelhorsetivessemcomentadoedepuradolo!Para
exemplo,descobrimosvriosbugsnoconstrutornativa,especialmentequandocomeouaremover
colunasdagrade.
Nsfinalmentedescobriuqueocdigodeconstrutornopoderialidarcomremoesseascolunas
tinhadiferentedopadro"column1","column2",etc.nomesNstambmdescobrimosqueo
construtordegradenativaesperadotodososcabealhosparaterseusnomespadro,afimdelidarcomeles
semexplodir!
Desdequequeriatocartopoucodocdigooriginalpossvel,nsrebatizadode
colunasecabealhosdeseusnomespadronacargamtododenossaclasseGridBuildpersonalizado.
Porestarazo,sevocchamaroconstrutoreusara CANCELARparasair,vocvaiacharque
todososseusnomesdecolunaecabealhoforamredefinidasparaseusnomespadrodoVisualFoxPro.este
fcildecorrigir.Bastachamaroconstrutoredesadapressionandoo OKboto.
AmaiorpartedafuncionalidadedoconstrutordegradenativapodeserencontradanaclassedeGridBldr
GridBldr.vcx.ApenasnocasodenovafuncionalidadefoiadicionadaaestaclasseemfuturasversesdoVisual
FoxPro,decidimossubclasseloemodificaronossosubclasse.Vocvaiencontrarocdigoque
forneceafuncionalidademelhoradanaGridBuild.vcxclass::GridBuild.

Redimensionarcolunasdegradecorretamente
Felizmente,nsnotemquebateracabeacontraotecladoparadescobririsso.
AmaioriadotrabalhojtinhasidofeitoporDougHenningeapresentadonaTerceiraAnual
SouthernCaliforniaVisualFoxProConfernciaemagostode1999.Oqueeledescobriufoique
oconstrutordegradejtinhaummtodochamadoSetColWidthpararealizarosclculosnecessrios
eredimensionarascolunas.Noentanto,oconstrutorestavapassandoovalorerradoparaomtodo!
Depoisdemuitaescavaoeexperimentao,descobrimosqueVisualFoxProfoiacrescentandonovos
colunasparaagradecomumalargurapadrode75pixelsemsuaResetColumnsmtodo.Essemtodo
entorealizadaaseguinteverificaoafimdedecidirsequerounootamanhodanovacoluna
correctamentenoquedizrespeitoaocampodependente:

406 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

*Noredefiniralarguraseousuriojmudou
IFwbaTemp[m.wbi,1]#wbaCols[m.wbi,1],ewbaCols[m.wbi,1]#0
wbaTemp[m.wbi,1]=wbaCols[m.wbi,1]
FIMSE

DesdewbaCols[m.wbi,1]mantmacorrenteColumnWidthdacolunaaserprocessado
peloconstrutordegrade,elenuncafoiigualazeroeoColumnWidthNuncafoiredimensionada
devidamente.TudooquetnhamosafazererainicializaroColumnWidthparacolunasadicionadasrecentementeazero
eelesforamredimensionadasadequadamente.

Mudaronomedecolunaseseuscontrolesdeformaadequada
Nsadicionamosummtodochamado,estranhamente,RenameControlsanossaclasseGridBuildpara
lidarcomessatarefa.EstemtodochamadoapartirdoClickmtododebotoOKdoconstrutore
renomeiaascolunaseseuscontrolescontidoscombasenonomedocampoparaoqualo
colunaestvinculada.Estemtodotambmsubstituioscabealhosdeclassebaseecaixasdetextoclassebasecom
suasclassespersonalizadasseumaclassepersonalizadafoiespecificadadapgina"controlespersonalizados"do
construtor.

lnRowslocal,lnCnt,lcField,loColumn,lcHeader,loHeader,
lnCtl,lnControls,lacontrols[1,2],lnCount,lcCaption

***Senenhumacolunadefinida,afianceparaforaagora
IFwbaControl[1].ColumnCount=1
RETORNA
FIMSE
lnRows=Alen(wbaCols,1)

Emseguida,varremosmatrizwbaColsdoconstrutorpararenomearcadacolunapararefletira
nomedocampoaoqualeleestvinculado.Oconstrutorarmazenaonomedacolunaatualnacoluna
setedesuavariedadewbaCols.Onomedocampoaoqualestligadoarmazenadonacolunadois.
Oconstrutormantmumalinhanamatrizparacadacolunanagrade:

PARAlnCnt=1alnRows
lcField=wbaCols[lnCnt,2]
Senoforvazio(lcField)

***Obteronomepadrodacoluna
loColumn=EVALUATE('wbaControl[1].'+wbaCols[lnCnt,7])

***Renomeieacolunaeocabealhodeacordocomonomedocampo
loColumn.Name="col"+lcField
wbaCols[lnCnt,7]=loColumn.Name

EstecdigoremovecabealhosclassebaseesubstituiloscomosnossoscabealhospersonalizadosSeisso
opofoiespecificadanaquintapginadoconstrutor.Emseguidarenomeiaocabealhodeumamaneira
consistentecomacolunanaqualreside.Noteseque,aoadicionarcabealhospersonalizadosao
colunadegrade,precisoprimeiroremovertodososcontrolescontidosnacolunaporqueacoluna
esperaqueseucabealhoaseroprimeirocontroleemsuacoleodecontroles.Senofor,agrelharesultante
nofuncionarcorretamente.Apsocostumedecabealhoadicionadocoluna,orestodo
controlessoadicionadosnovamente:

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
407

IFThisFormSet.Form1.Pageframe1.Page5.chkCustomHeaders.Value=.T.E
!VAZIO(Thisformset.cHeaderClass)

***Agoraremovertodososcabealhosdeclassebaseeadicionarcabealhospersonalizados
***Temosderemovertodososobjetosnacolunademodoaque
***Ocabealhopersonalizadorecmadicionadocontroles[1]
lnControls=loColumn.ControlCount
lnCount=0
PARAlnCtl=1alnControls
IFsuperior(loColumn.Controls[1].BaseClass)='header'

***Salvaralegendadocabealhoantesderemovlo
lcCaption=loColumn.Controls[1].Caption
loColumn.RemoveObject(loColumn.Controls[1].Name)
OUTRO

***Salveinformaessobreosoutroscontrolesnacoluna
***Antesderemovlos

lnCount=lnCount+1
laControlsDIMENSO[lnCount,2]
laControls[lnCount,1]=loColumn.Controls[1].Name
laControls[lnCount,2]=loColumn.Controls[1].Class
loColumn.RemoveObject(loColumn.Controls[1].Name)
FIMSE
ENDFOR

***Adicioneocabealhopersonalizado
loColumn.AddObject('HDR'+lcField,Thisformset.cHeaderClass)

***Certifiquesededefiniralegenda
loColumn.Controls[1].Caption=lcCaption

***Adicionartrsosoutroscontrolesdecoluna
PARAlnCtl=1alnCount
loColumn.AddObject(laControls[lnCtl,1],[laControlslnCtl,2])
ENDFOR
OUTRO

***Senoestiverusandocabealhospersonalizados,bastarenomelo
loColumn.Controls[1].Name="hdr'+lcField
FIMSE
Omtodotambmsubstituiascaixasdetextonativoserenomeialos.Ocdigoquefazisso
muitosemelhanteaocdigoapresentadoacima.

Controlaapginapersonalizadadoconstrutordegrade
Adicionandoestapginaparaoconstrutordegradefoi,provavelmente,apartemaisfcildemelhorarisso.Issofoi
omaisdivertidoporquetemosdeusarduasfunesmuitolegaisquesonovosparaVisualFoxPro
tambm
6.0: FILETOSTR()e ALINES().Estasfunesnospermitiupreencheracaixadecombinaode
queumaclassedecabealhopersonalizadopodeserselecionado.Desdecabealhospersonalizadosnopodemser
edeveserdefinidaearmazenadanumficheirodeprograma,estasduasfunessimplificadograndementeotrabalho
definidasvisualmente
deanalisarosnomesdasclassesdedentrodoarquivodoprograma.Aquionossocdigolegal
daValidmtododacaixadetextocontendoonomedoarquivodeprocedimentoparausar:

408 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

LOCAISlcProcFile,lcStr,laLines[1],lnLines,lnCnt,lcClass,lnLen

IFEMPTY(ThisformSet.cProcFile)
RETORNA
FIMSE
lcProcFile=Thisformset.cProcFile

***Agorapreencheracombinaocomosnomes
***Dasclassespersonalizadasnoarquivodeprocedimento
This.Parent.cboHeaderClass.Clear()
lcStr=FILETOSTR(lcProcFile)
lnLines=ALINES(laLines,lcStr)
PARAlnCnt=1alnLines
SE'DEFINECLASS'$UPPER(laLines[lnCnt])
lnLen=AT('AS',UPPER(laLines[lnCnt]))13
lcClass=ALLTRIM(substr(laLines[lnCnt],13,lnLen))
This.Parent.cboHeaderClass.AddItem(lcClass)
FIMSE
ENDFOR
This.Parent.cboHeaderClass.ListIndex=1

***Certifiquesedeclassecabealhopersonalizadoestdisponvel
IF!EMPTY(lcProcFile)
IFlcProcFile$SET("Procedimento")
OUTRO
lcProcFile='"'+lcProcFile+'"'
SETPROCEDURETO&lcProcFileADITIVO
FIMSE
FIMSE

Adicionandocdigomtodoparacolunasdegrade
NoCaptulo6,apresentamosumaclassegradecomcabealhosdevriaslinhas.Usandoaclassemuito
caro,porqueummontedecdigotemdeseradicionadoinstncia,afimdequepossafuncionar
devidamente.Afimdetornlomaisfcildeimplementar,nsadicionamosumpoucodecdigoparaonossoconstrutorde
seriaadicionarocdigonecessrioparaascolunasdegradeemtempodedesign.Estecdigo,noconstrutorda
gradedemodo
BotoOK,eliminouanecessidadedeadicionarmanualmenteocdigoparadecadacolunaMovedeResize
Mtodo:

***OK,agoraverseestamosusandoumagradedecabealhodemultilinhadinmica
***Seassimfor,pediraoutilizadorparaverseocdigodeveserescritoparao
***Colunamovidoeredimensionarmtodos
Seforinferior(wbaControl[1].class)='grdmlheaders'
IFMESSAGEBOX('Vocqueradicionarocdigonecessrio'+chr(13)+
'Paraascolunasdegradeparamanter'+chr(13)+
'Oscabealhosdevriaslinhasposicionadocorretamente?'
,4+32,"Adicionarcdigoagora?')=6
PARACADAloColumnINwbaControl[1].Columns
loColumn.WriteMethod('Movido","Coluna::movido()'+CHR(13)+
'This.Parent.RefreshHeaders()'+CHR(13)+
'NODEFAULT')
loColumn.WriteMethod('Resize','Coluna::movido()'+CHR(13)+
'This.Parent.RefreshHeaders()'+CHR(13)+
'NODEFAULT')
ENDFOR
Captulo12:Ferramentasdeprodutividadedodesenvolvedor
409

FIMSE
FIMSE

Seporacasovocsentirquaisquerpeculiaridadespoucoaousaronossoconstrutordegrade,manterem
mentequeelessomaispropensosaserpeculiaridadesdoconstrutorgradeVisualFoxPronativa.Onico
vezquetemosexperimentadonadaforadocomumquandonsadicionamosvriasvezes,
removidoecolunasordenouReumanicasessoconstrutor.possvelquevoctambm.Ese
voccapazderastrearasrazesdetaisanomaliasexaminando
GridBldr.vcx::GridBldr(agradeconstrutornativo),envieumemailcomasoluo.Umaolhada
ocdigofonte,evocvaientenderporquenstivemosnemtemponempacinciapara
investigarmais.

Classecatalogador(Exemplo:vcxlist.scx)
OobjetivodoVCXListlerocontedodeumarquivodeprojetoespecificadoeconstruirumatabela
quecontmosdetalhesdetodasasclassesvisuaisutilizadosnesseprojeto.extremamentesimples
deusar,bastachamaraforma,selecioneoprojetoecliquenoboto'Go'.
Umanovatabelasercriadanodiretriohomedoprojeto,chamado vcxlist.dbfcom
aseguinteestrutura:

CCLASLIBC(60,0)&&Classenomedabiblioteca
CCLASNAMEC(35,0)&&Nomedaclasse
CBASECLASC(25,0)&&VFPBaseClass
CPARENTCbibliotecadeclasse(50,0)&&Paieonome
CDESC C(150,0)&&ClasseDescrio

Estatabelatambmutilizadopelonossoutilitrio"MC.PRG"(verabaixo).

410 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Figura12.8ClasseCatalogervcxlist.scx

Enquantovoctemestaformaaberta,voctambmpodeabrirodesignerdeclasseparaqualquerclassede
bastaselecionaraclassenacaixadelistaeclicandonoboto"Modificarclasseselecionada".

OqueVCXListfaz
EstaformafaztodooseutrabalhonocostumeSetUpmtodo.Emprimeirolugar,omtodolonome
oprojetoselecionadoemudaodiretriopadroparaadoprojeto.Seumatabelachamada
vcxlist.dbfencontrado,eleabertoexclusivamenteeapuradas.Casocontrrio,umanovatabelacriada
nodiretrioinicialdoprojeto.Estatabelaprecisaserlocalizadolporquetodososcaminhosarmazenados
noarquivodeprojetosorelativosaodiretriohomedoprojeto.Seestenotambmopadro
diretrio,emseguida,abrirbibliotecasdeclassespodeserproblemtico.
OarquivodeprojetoentoabertocomoumDBFeumarraylocalpreenchidado NOMEcampo
doprojetoparatodasasentradascujos TYPE="V"(bibliotecadeclassesVisual).Emseguida,paracadaclasse
bibliotecaidentificada,onativo AVCXCLASSES()funousadapararecuperarosdetalhesdo
aulasqueelacontmeparainserirosdadosnatabela.
Finalmenteacaixadelistagempreenchida(pelocostumeUpdlistmtodo)eoformulrioestprontopara
usoimediatoparaforneceracessorpidoaqualquerclasseutilizadanoprojeto.Enquantoistobastante
tilemsuaprpriadireita,overdadeiropropsitodesteutilitriocriarovcxlistmesa.

Umwrapperpara"modificarclasse"(Exemplo:mc.prg)
EstepequenoprogramafoioriginalmenteconcebidoporStevenpretoquandoestvamostodostrabalhandoemum
projetomuitograndenoinciode1999.Oproblemaqueenfrentamosfoiquehaviaumgrandenmerode

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
411

bibliotecasdeclasseselembrarqualbibliotecarealizadaqualclassefoidifcil.Opropsitode
MC.PRGsimplificaratarefadeabrirumaclasseespecficaparamodificaoutilizandoumatabelade
armazenarosdetalhesnecessriosdetodasasclasses.Estaencarnaodoprogramafazusodo
vcxlist.dbfmesa,quefoidescritonasecoanterior.
Paraabrirodesignerdeclasse,bastaligarpara MC,comoumafunocomonomedaclassenecessria:

MC(<nomedaclasse>)

Podeaindaespecificarummtodoparamodificardemodoquequandoseabreodesigner,queomtodode
janeladecdigoserabertoparaedio.

MC(<nomedaclasse>,<nomedomtodo>)

Aquiestocdigoparaoprograma:
**********************************************************************
*Programa :MC.PRG
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:EsteprogramafoioriginalmenteconcebidoeescritoporStevenPreto
* :Enquantoestvamostodostrabalhandojuntosemumgrandeprojetonoinciode
De1999.
* :Nsgostaramosdereconhecerisso,etudooStevende
contribuies,
* :Eagradecerlheporsuadisposiodepartilharasuaengenhosidade
* :Econhecimentocomorestodens.
*Sintaxe :MC(<classname>[,<methodname>])ou
* :DOMCCOM<classname>[,<methodname>]
LPARAMETERStcClass,tcMethod
lcClassLOCAL,lnSelect,lcOrigDir,lcOldError,lcLoc,lcMethod

***Devepassarumnomedeclasse,pelomenos!
IFVARTYPE(tcClass)#"C"ouvazio(tcClass)
RETORNA
OUTRO
***Obteronomedaclasse
lcClass=LOWER(ALLTRIM(tcClass))
FIMSE

***Salvaratualreadetrabalho
lnSelect=SELECIONAR()

***TabelaVCXListAberto
ESE!USADO("VcxList")
***DisableTratamentodeerrostemporariamente
lcOldError=ON("ERROR")
ERRORON*
lcLoc=""
***LocalizaratabelaVCXListdeusar
lcLoc=LOCFILE("VCXList","DBF","Ondeest")
***Restauraramanipulaodeerroeverifiqueresultado
ONERROR&lcOldError
ESE!VAZIO(lcLoc)e"vcxlist'$INFERIOR(lcLoc)
***OKAbraaTabela
USE(lcLoc)novamentecompartilhadosem0

412 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OUTRO
***NolocalizadoAbortar
WAITwindow"NopossvellocalizarVCXList.DBFAbortar"
RETORNA
FIMSE
FIMSE
***SelectVCXList
VCXListSELECIONAR

***FaaVCXListLocalizaoatualpadroporqueo
***classlibssosalvoscomcaminhosquesorelativas
***Paraolocaldoprojeto(e,consequentemente,paraVCXList)!
lcOrigDir=FULLPATH(CURDIR())
SETDEFAULTTOJUSTPATH
(DBF())

***Serquevamosobterumnomedemtodotambm?
IFVARTYPE(tcMethod)="C"E!VAZIO(tcMethod)
lcMethod="Mtodo"+tcMethod
OUTRO
lcMethod=''
FIMSE

***Encontreaclassenecessria
LOCALIZARPARAALLTRIM(cclasname)==lcClass
SEACHADO()
***MostraronomeVCX
WAITWINDOW'OpeningClasseLibray:'+ALLTRIM(cClasLib)NOWAIT
MODICLASSE(ALLTRIM(cClasName))de(ALLTRIM(cClasLib))&lcMethodNOWAIT
OUTRO
WAITwindow"Classe"+lcClass+"NotFound"NOWAIT
FIMSE

***RestaurarLocalizaoOriginalereadeTrabalho
SETDEFAULTTO(lcOrigDir)
SELECT(lnSelect)

Ocdigoemsibastantesimples.Anicacoisaanotarousodo LOCFILE()
funcionarparaencontrara vcxlist.dbfmesa.Tantoquantonspodemosdizer,uminteiramenteemsituaoirregular
caractersticado LOCFILE()que,quandousadoparalocalizarumarquivo,ocaminhodoarquivoautomaticamente
atualVFPcaminhodepesquisa.(IstoverdadeemtodasasversesdoVisualFoxPro.)
adicionadoao
Istosignificaqueumavezquevocidentificouondeatabelaestlocalizada,adicionadoodiretrio
noseucaminhodepesquisaatualetodasaschamadassubsequentesparaMCvaiencontraramesa.Claroque,se
estotrabalhandoemvriosprojetosestepoderiaserumproblema,evocpodepreferirsubstituir
LOCFILE()comumsimples GETFILE()quefaznoalteraroseucaminhodepesquisa.Noentantosentimos
quedesdequeamaioriadenstrabalharemapenasumprojetodecadavez,adicionandoalocalizaode vcxlist.dbfpara
ocaminhodepesquisaumaeconomiadetempotil.

Umutilitriodocumentaobibliotecadeformulrios/aula(exemplo:
genscode.scx)
UmadasmuitascoisasquemudaramcomaintroduodoVisualFoxProVerso3.0foi
quesetornoumaisdifcildevisualizarocdigoparaformulrios.Istoporque,emvezde
produodeumficheirodeprogramaparaumatela,todoocdigofoiarmazenadaemcamposdenotanatabelaque
defineaforma.Umaestratgiasemelhantetambmfoiadotadaparabibliotecasdeclasse.adocumentao
assistenteincludonoVisualFoxPro,eaopo'cdigodeexportao'fornecidocomaclasse
Captulo12:Ferramentasdeprodutividadedodesenvolvedor
413

navegadorsoteis.Noentanto,aindasentiaanecessidadedeumutilitriosimplesparadocumentartudo
propriedadesemtodosdeumaforma,eparadocumentarumanicaclasse,ouumaclasseinteira
biblioteca.Genscode.SCXoresultado.

Figura12.9Genscode.scx:Form/VCXDocumentador

Quandoumformulrio,oubibliotecadeclassesselecionadae,ouoboto"Preview"ou"Imprimir"
clicado,costumedoformulrioWriteCodemtodochamadoparaproduzirasadacomoumarquivodetexto
queouabertoparaavisualizaoemtelaouenviadosdiretamenteparaaimpressora.Oarquivodetextono
salvosporpadro,entosevocprecisacriarumregistropermanente,useaopodevisualizaoeuso
opadroopodemenu"Salvarcomo"parasalvaroarquivocomumnovonome.Aquiestocdigoque
realmenteproduzadocumentao,oqueestcontidonoWriteCodemtodo.
Primeirovamosdefiniralgumasconstanteseabrirosarquivosdeorigemededestino:

******************************************************************************
***Genscode::WriteCode()Mtodo
******************************************************************************
emltexarraylocal[1]
lcSourceLOCAL,lcTarget,lnFno,lnOldMemo,lnNumLine,lnCnt,lcText,
lcClassName

***anunciam
WAITWINDOWNOWAIT"gerarcdigodeorigem...'

***constantesdepropriedadeImprimir
#DEFINECRLFCHR(13)+CHR(10)
#DEFINELOC_USER'*****USURIODEFINIDO*****'+CRLF
#DEFINELOC_PROP'**********PROPRIEDADES'+CRLF
#DEFINELOC_METH'**********MTODOS'+CRLF
#DEFINELOC_LINEREPLICATE('=',SET('MEMOWIDTH'))

***NomedoarquivofonteExtract
lcSource=THISFORM.txtSource.Value
lcTarget=THISFORM.cOutputName

***Certifiquearquivodedestinonoexiste
Seoarquivo(lcTarget)
DELETEFILE(lcTarget)
FIMSE

***Abrirarquivodedestinoparaaescrita
lnFno=FCREATE(lcTarget)

414 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
***InformaoWritecabealho
lcText="Arquivodeorigem:'+UPPER(ALLTRIM(lcSource))
FPUTS(lnFno,lcText)
FPUTS(lnFno,LOC_LINE)
lcText='documentados:'+TTOC(DATETIME())+CRLF
FPUTS(lnFno,lcText)

OsdetalhesreaissorecolhidosusandoafunoALINES()paralerocontedoda
camposdememorandoemumarraylocale,emseguidaescritoslinhaalinhaparaoarquivodetextodedestino.UMA
blocodecabealhopadroescritoemprimeirolugarparacadanovoobjetoouclassequeencontrado.Prximoqualquer
propriedadesdefinidaspelousuriooumtodossoescritos(docampoReserved3),edepoiso
contedodaspropriedadesemtodossocamposdeescrita.Umavezqueofimdoficheirodeorigem
atingido,oficheirodesadafechadodemodoqueelepodeservisualizadoouimpresso,conformenecessrio.

***Escrevadetalhes(porloopingatravsVCX)
vcxSELECIONAR
SCAN
***Ignorarinformaesdefonte/versesantigasetc.
IFEMPTY(timestamp)ouexcludo()
LOOP
FIMSE

***Obternomedeclasse
lcClassName=ALLTRIM(objname)
IFThisform.cboSelectClass.ListIndex>1
***Ignorarasclasses,excetoseexigido
ESE!(UPPER(ALLTRIM(lcClassName))==
UPPER(ALLTRIM(Thisform.cboSelectClass.DisplayValue)))
LOOP
FIMSE
FIMSE

***CabealhoObjeto
FPUTS(lnFno,APRD('Nome',17,'.') +''+UPPER(ALLTRIM(objname)))
FPUTS(lnFno,APRD('Class',17,'.') +''+UPPER(ALLTRIM(classe)))
FPUTS(lnFno,APRD('Pai',17,'.') +''+UPPER(ALLTRIM(pai)))
FPUTS(lnFno,APRD('classebase',17,'.')
+''+UPPER(ALLTRIM(baseclass)))
FPUTS(lnFno,APRD('Descrio',17,'.')+''+UPPER(ALLTRIM(reserved7))+
CRLF)

***itensdefinidospelousurio
IF!EMPTY(Reserved3)
DIMENSOemltex[1]
emltex=""
lnNumLine=ALINES(emltex,Reserved3)
FPUTS(lnFno,LOC_USER)
PARAlnCnt=1alnNumLine
lcText=emltex[lnCnt]
DOCASO
CASEISBLANK(lcText)
lcText=''
CASELEFT(lcText,1)='*'
lcText='Mtodo:'+SUBSTR(lcText,2)
DEOUTRAFORMA
lcText='propriedade:'+lcText

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
415

ENDCASE
IF!EMPTY(lcText)
FPUTS(lnFno,lcText)
FIMSE
PRXIMO
FPUTS(lnFno,LOC_LINE+CRLF)
FIMSE

***Propriedades
SE!Vazia(propriedades)
DIMENSOemltex[1]
emltex=""
lnNumLine=ALINES(emltex,propriedades)
FPUTS(lnFno,LOC_PROP)
PARAlnCnt=1alnNumLine
lcText=emltex[lnCnt]
FPUTS(lnFno,lcText)
PRXIMO
FPUTS(lnFno,LOC_LINE+CRLF)
FIMSE

***Mtodos
SE!Vazia(mtodos)
DIMENSOemltex[1]
emltex=""
lnNumLine=ALINES(emltex,mtodos)
FPUTS(lnFno,LOC_METH)
PARAlnCnt=1alnNumLine
lcText=emltex[lnCnt]
DOCASO
MAISCULAS(LEFT(lcText,9))="Procedimento"
lcText='***'+UPPER(ALLTRIM(SUBSTR(lcText,10)))+"mtodo"
MAISCULAS(LEFT(lcText,7))='ENDPROC'
lcText=LOC_LINE+CRLF
CASEISBLANK(lcText)
lcText=''
ENDCASE
IF!EMPTY(lcText)
FPUTS(lnFno,lcText)
FIMSE
PRXIMO
FIMSE
ENDSCAN

***Tidyuparquivodesadaperto
FCLOSE(lnFno)

***Mensagensclaras
ESPERAAPAGAR

Share.prgumnavegadordeclasseaddin
EstaferramentamuitotilfoicriadoporStevenpretoeestdisponvelparadownloadgratuitoapartirdesua
Websiteemwww.stevenblack.com.Suafunotomarumanicaclasseecopiloparaumnovo
bibliotecadeclasses.Noentanto,nosextrairaclasseespecificada,quetambmirdeterminare
copiartodasasclassesnaclasseespecificada'hierarquiadeheranaparaanovabiblioteca..Oresultado

416 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

queasuanovabibliotecaircontertodasasclassesnecessriasparausaraclasseselecionadosem
anecessidadedefornecerumconjuntocompletodebibliotecasdeclasses.
Figura12.10(abaixo)mostraoresultadodeusaresteutilitrioparaextrairtodasasclasses
necessrioparaumaclassecompostacomplexoemum'appclassbiblioteca".Comovocpodever,onovoVCX
incluiutodaahierarquiadeclassesparatodososcontrolesutilizados,mesmoqueelesso,naverdade,
definidadevriasbibliotecasdiferentes:

Figura12.10resultadosproduzidospeloShare.prgclassebrowseraddIn

Parautilizaresteutilitriovocprimeiroprecisaregistraroprogramacomoumnavegadordeclasseaddin.
Parafazerisso,primeirocopieoshare.prgprogramaparaomesmodiretrionoqual browser.appe
browser.dbfresidem(normalmenteodiretrioVFP).Emseguida,abraonavegadordeclassepara
criararefernciadeobjetodosistemaparaonavegador("_oBrowser")edocomando
janelachamar'donavegadorAddInmtodo"comosesegue:

_oBrowser.AddIn("ClasseExtractor","share.prg")

Issotudoqueexisteparaela.Agoravocpodeabrirqualquerbibliotecadeclassenonavegadore,quando
vocabriromenudobotodireito,a"ClasseExtractor"estardisponvelatravsdo"Add
Ins"opo.(Lembrese,onavegadordeclassetemdoismenusdeatalhodiferentes,dependendo
ondevocclica.AopoAddInsnomenudeatalhodonavegadorprincipaleno
disponvelnomenudeclassequeaparecequandovocclicacomobotodireitoemqualquerumodetalheprincipal
janelas.)difcilsuperestimarautilidadedestaferramentapequenaemesmosevocnousar
onavegadordeclasseparaqualqueroutracoisa,estedeveserdefinitivamentepartedoseukitdeferramentaspadro.

Umlocalizadordekinder(Exemplo:Finder.scx)
Algumavezvocjprecisavasabertodososlugaresdentrodeumaplicativoqueumatabelaespecficafoi
usava?Oucomosobretodasasformasquecontmumainstnciadeumaclasseespecfica?Nossolocalizadordekinder
tornaestaumatarefamuitofcilmesmo.Tudoquevocprecisafazerdigitarotextoaprocurareselecionaro
diretrioparapesquisar.Oformulrio,emseguida,preencheacaixadecombinaodetiposdearquivoscomostiposde
encontradonodiretrioespecificado."ArquivosdePesquisa"e"Nomesdecampoparapesquisar"listasso
arquivosvlidos

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
417

preenchidadeformaadequadaquandoumnovotipodearquivoselecionado.Depoisdeselecionarumoumaisarquivos
especificandopelomenosumcampodepesquisa,pressioneo GOboto,eoformulrioexibeosresultadosem
apginaseguinte.

Figura12.11Finder.scx:Procuratodasasclassesquetmummtododeconfigurao

OsdiretriosparapesquisasocolocadosempersonalizadosdoformulrioaDirectoriespropriedadepeloseu
personalizadosSetDirectoriesmtodo.Eletambmpreencheascaixasdecombinaoelistachamandoo
personalizadosdoformulrioGetFileTypesmtodo:

ESE!VAZIO(.cDirectory)

***Confiraostiposdearquivonodiretrioselecionado
***Adicioneoqueestdisponvelparaacaixadecombinaodetiposdearquivos
.GetFileTypes(.cDirectory)

***Vejaseprecisamosrecurseatravsdodiretrioselecionado
IF.lRecurse
.GetChildDirectories(.cDirectory)
FIMSE
FIMSE

EstecdigonopersonalizadosGetChildDirectoriesmtodopreencheamatrizcomototalmentequalificado
caminhodetodosossubdiretriosnarvore:
418 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

LPARAMETERStcDirectory

LOCAISlnDirCnt,laDirs[1],lnCnt,lnLen
ESE!(TcDirectory==Thisform.cDirectory)

***Adicionarodiretrioatualparaalistasenoaraiz
lnLen=ALEN(Thisform.aDirectories)+1
Thisform.aDirectoriesDIMENSO[lnLen]
Thisform.aDirectories[lnLen]=tcDirectory

***Verseprecisoacrescentarquaisquernovostiposdearquivos
Thisform.GetFileTypes(tcDirectory)
FIMSE

***Agoraversetemostodososdiretriossobodiretrioatual
lnDirCnt=ADIR(laDirs,tcDirectory+'*.*','D')
IFlnDirCnt>1
PARAlnCnt=1alnDirCnt
Sefordeixado(laDirs[lnCnt,1],1)#'.'

***Certifiquesedequetemosumdiretrioenoumarquivo
Seodiretrio(tcDirectory+laDirs[lnCnt,1])
Thisform.GetChildDirectories(tcDirectory+laDirs[lnCnt,1]+'\')
FIMSE
FIMSE
ENDFOR
FIMSE

OGetFileTypesmtodousaasentradasnatabelaFinderTypes.dbfparadeterminarquais
tiposdearquivosdevemserincludosnacaixadecombinao.Eleexaminaaextensodecadaarquivono
diretrioespecificadoeadicionaodaformaaFileTypesmatrizseelepodeserencontradoem
FinderTypes.dbfequeaindanoummembrodamatriz:
lnFileCountLOCAL,lafiles[1],lnFile,lcExtension,lnSelect,lnLen

lnSelect=SELECIONAR()
lnFileCount=ADIR(lafiles,tcDirectory+'*.*')
IFlnFileCount>0
PARAlnFile=1alnFileCount
lcExtension=superior(ALLTRIM(JUSTEXT(lafiles[lnFile,1])))

***Vejaseestaumaextensodearquivo'legal'
FinderTypesSELECIONAR
LOCALIZARPARAALLTRIM(FinderTypes.cExtension)==lcExtension
ESE!Encontrado()
LOOP
FIMSE

***EntensionLegal...versejtemosissonamatriz
IFASCAN(Thisform.aFileTypes,FinderTypes.cAbbr)=0

***Seesteoprimeirotipodearquivoencontrado,
***Substituiro'(nenhum)"entradaqueocombofoiinicializadocom
lnLen=ALEN(Thisform.aFileTypes,1)
IFlnLen=1ANDThisform.aFileTypes[1,1]='(Nenhum)"
OUTRO
lnLen=+1lnLen

Captulo12:Ferramentasdeprodutividadedodesenvolvedor
419

Thisform.aFileTypesDIMENSO[lnLen,2]
FIMSE

***Adicionarestetipodearquivolista
Thisform.aFileTypes[lnLen,1]=FinderTypes.cAbbr
Thisform.aFileTypes[lnLen,2]=FinderTypes.cExtension
FIMSE
ENDFOR
FIMSE

SELECT(lnSelect)

Cadavezquefeitaumaseleonacaixadecombinao,aformadoGetFileNamesmtodo
invocadapararepovoaracaixadelistadearquivosparaprocurar:

lnfileLOCAL,lnFileCnt,lnDirCnt,lnDir,lafiles[1],lnTotalFiles,lcFileType

lnTotalFiles=0
***Sestemos'(nenhum)"comoumtipodearquivo,nofazernada
IFEMPTY(Thisform.cFileType)
RETORNA
OUTRO
lcFileType=UPPER(ALLTRIM(Thisform.cFileType))
FIMSE

lnDirCnt=ALEN(Thisform.aDirectories)
PARAlnDir=1alnDirCnt

***Obtertodososarquivosnodirecotryatual
lnFileCnt=ADIR(lafiles,Thisform.aDirectories[lnDir]+'*.*')

***Percorrerosarquivoseadicionarosdotipocorretoparaamatriz
***Acoluna1onomedoarquivoecoluna2odiretrioqueestlocalizadona
PARAlnFile=1alnFileCnt
IFsuperior(ALLTRIM(JUSTEXT(lafiles[lnFile,1])))==lcFileType
lnTotalFiles=+1lnTotalFiles
Thisform.aFileNamesDIMENSO[lnTotalFiles,2]
Thisform.aFileNames[lnTotalFiles,1]=JUSTSTEM(lafiles[lnFile,1])
Thisform.aFileNames[lnTotalFiles,2]=Thisform.aDirectories[lnDir]
FIMSE
ENDFOR
ENDFOR

***Organizarosnomesdearquivo
ASORT(Thisform.aFileNames,1)

DoformulrioGetFieldNamesmtodoentoutilizadopararepovoaroscamposdecaixadelistagemdepesquisa:

lcExtensionLOCAL,lnSelect,lnFld,lnFldCnt,lcFile,laFields[1]

lnSelect=SELECIONAR()
lcExtension=UPPER(ALLTRIM(Thisform.cFileType))

***Vejaquetipodearquivoquetemos
FinderTypesSELECIONAR
LOCALIZARPARAALLTRIM(FinderTypes.cExtension)==lcExtension

420 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SEACHADO()

***umarquivodetextodemodoquenopodeselecionartodososcampos
IFFinderTypes.lIsText
ThisForm.aFieldNamesDIMENSO[1]
Thisform.aFieldNames[1]=''
OUTRO

***umaestruturapadrocomoumpjx,scx,vcxetc.
***ObtersuaestruturaparaamatrizaFieldNameseatualizaracaixadelistagem
IFFinderTypes.lStatic
lcFile=ALLTRIM(Thisform.aFileNames[1,1])
Selecionar0
Uso(Thisform.aFileNames[1,2]+lcFile++lcExtension'.')
nOVAMENTENOUPDATE
lnFldCnt=AFIELDS(laFields)
USAR
Thisform.aFieldNamesDIMENSO[lnFldCnt]
PARAlnFld=1alnFldCnt
Thisform.aFieldNames[lnFld]=[laFieldslnFld,1]
ENDFOR
OUTRO

***Otipodearquivoselecionadodbf
Thisform.GetDBFFields()
FIMSE
FIMSE
FIMSE

SELECT(lnSelect)

PersonalizadadoformulrioPesquisamtodogiraatravsdecadaarquivoselecionado,procurandoumacorrespondncia
acadeiadepesquisaespecificadonoscamposselecionados.Quandoforencontradaumacorrespondncia,umregistro
em
emumcursordemodoqueosresultadosdapesquisapodemserexibidosnagradenasegundapgina.
inserido
Captulo12:Ferramentasdeprodutividadedodesenvolvedor
421

Figura12.12Resultadosdapesquisa:umalistadetodasasclassesquetmummtodode
configurao
AmaiorpartedotrabalhorealizadonocostumeSearchTextFilemtodoseoficheiroescolhido
umarquivodetextoenocostumeSearchTablemtodoseforumformulrio,classeououtratabelacombase
entidade.Clicandono MODIFICARbotopermiteeditaroformulrio,classe,relatrio,etc.desde
apginaderesultados.

Concluso
Talcomoreferidonaintroduoaestecaptulo,essasferramentassodestinadosadesenvolvedoresdeusare
Nosooferecidoscomo"completoeprontoparaproduo".Porfavor,noseofendasevocdescobrirum
bugesintaselivreparaalterarouampliarqualquerumadessasferramentasparaseadequarasimesmos.Ns
ouvirdetodososproblemasprincipaisquevocencontrar,edequaisquernovasdireesqueestesexemplospodem
gostaramosde
sugeriravoc.
422 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Captulo13:coisasdiversas 423

Captulo13
coisasdiversas
"Htrsestradasparaarruinarmulheres,jogosdeazaretcnicosOmaisagradvel.
comasmulheres,omaisrpidocomojogo,masomaiscertocomostcnicos."(Georges
Pompidou,presidentedaFrana.Citadoem"SundayTelegraph",Londres,26demaio1968).
Estecaptulocontmumavariedadededicasteiseutilitriosquerealmentenopertencem
emqualquerumlugar,masquepodesertilpordireitoprprio,detemposatempos.Apreciar!

UsandoodepuradordoVisualFoxPro
OdepuradorVisualFoxPro,naformaemquefoiintroduzidopelaprimeiraveznaverso5.0,muito
poderosoconjuntodeferramentasquepodemserdeenormevaloraotestarseucdigo.Noentanto,
tambmumaferramentabastantecomplexoepodelevaralgumtempoparaseacostumar.

Caractersticasdasjanelasdodepurador
Cadaumadasjanelasdisponveisnodepuradortemalgumacaractersticainteressantequepodenoser
bvio.Aquiestoalgumasdascoisasquetemosrecolhidassobreeles:

localsj anela

Vocpodealterarovalordeumavarivellocalouestabelecimentoclicandonosvalores
colunadajanelaedigitandoumnovovalor.Taisalteraesseromantidascomo
desdequeavariveloupropriedadepermanecenoescopo
botodireitodoratoabreummenudeatalhoquepermitealternaravisibilidade
estado,e,portanto,aclarezadaexposio,de:
opblicoVariveisdeclaradascomo PBLICOpalavrachave
olocalVariveisdeclaradascoma LOCALpalavrachave
opadroTodasasvariveisnombitodoprocedimentodenominadopor"Localspara"
OObjetosObjetoreferncias
Vocpodeseaprofundaremumobjetooumatrizclicandonosinal"+"najanela
AjanelaLocalspodeserchamadoprogramaticamentecom janelaLocalsACTIVATE

JaneladeInspeo

Vocpodealterarovalordeumavarivellocalouestabelecimentoclicandonosvalores
colunadajanelaedigitandoumnovovalor.Taisalteraesseromantidascomo
desdequeavariveloupropriedadepermanecenoescopo
Vocpodeseaprofundaremumobjetooumatrizclicandonosinal"+"najanela

424 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Vocpodearrastarexpressesdeeparaajaneladecomandoeaentrada"Watch"
linha
Vocpodearrastarexpressesdajaneladerastreamentodiretamentenalinhadeentrada"Watch"
refernciasdeatalhocomoesteeThisFormpodeserusadoemexpressesdeinspeo
Paraveronomedequalquerobjetoestsoboponteirodomouseemqualquermomento,incluem
oseguintenalistadeexpressesWatch:" SYS(1272,SYS(1270))"
Ajaneladerelgiopodeserativadopormeiodeprogramaocom ativarajanelaRELGIO

JaneladeRastreamento

Almdo'Resume'(tringuloverde)e'Cancelar'(crculovermelho)opes,o
depuradoroferecequatroopesdemovimentoquandoorastreamentodecdigodaseguinteforma:
oStepInto:Executarlinhaatualdecdigos
oStepOver:desativarastreamentoduranteaexecuodeumasubrotina,ouligueaummtodo
oufunodefinidapelousurio
oStepOut:Retomaaexecuodoprocedimentoatualoumtodo,mas
suspendenovamentequandooprocedimento/mtodoconcluda
oRuntoCursor:Retomaaexecuodalinhaatualesuspendequando
alinhaquecontmocursoratingido
Aopassarocursordomousesobreumarefernciavariveloupropriedadeexibeumadicadeferramenta
janelamostrandoovaloratualparaesseitem.Vocpodelimitaroqueavaliadopelo
destacandotextonajaneladerastreamento.Umusoparaissoverificarseumobjeto
realmenteumobjetoportirandoumachamadademtodo.Porexemplo,passaromousesobre
"OObj.Init()"novaimostrarnada,massevocdestacarapenas"oObj,"vocvaiterum
dicaexibio"objeto."Outrousoparaobterovalordeitensentreaspas
selecionandoaopo"toObj.Name"de" tipodecaso("toObj.Name")="exibiro
valordapropriedadedenomenadica.
Definirdeclaraoseguinteopo:Quandovocestnomododerastreamento,vocpodesaltarblocosde
cdigo,oureexecutarocdigo,simplesmentemovendoocursordomouseparaalinhanecessriae
escolhendo'Definirprximainstruo"domenu"Debug"(Teclado:" ALTD+N").
Considerandoqueo'RuntoCursor"opotemporariamentedesativaorastreamento,masaindaexecutaocdigo,
'Definirprximainstruo'movesediretamenteparaolocalespecificadosemexecutarqualquer
intervenientecdigodetodo.
Cdigopodesercopiadodejaneladerastreamentoecoladonajaneladecomandoou
paraumprogramatemporriaeexecutadodeformaindependenteoucomoumblocooupela
destacandolinhaseexecutlosdiretamente.
Vocpodedestacarearrastarotextodiretamentedotraonajaneladorelgio.
Ajaneladerastreamentopodeserativadopormeiodeprogramaocom TRACEativarajanela.

Captulo13:coisasdiversas 425

DEBUGOUTJanela

QualquerexpressoFoxProvlidoprecedidocomocomando DEBUGOUTavaliadoe
ecoouparaajaneladesadadedepurao.Todasasseguintessovlidos: DEBUGOUT"Ol
World", DATADEBUGOUT(), DEBUGOUT22/7.
DEBUGOUTsadapodeserhabilitadopormeiodeprogramaousando SETDEBUGOUTTO<file>
[ADDITIVE]edeficientescom SETDEBUGOUTTO.
ASSERTmensagensetodososeventosqueestosendoacompanhadosnorastreadorevento,tambmso
ecoouparaodestinoDEBUGOUT(ouseja,paraarquivooujanelaouambos).
Paracontrolarmtodospersonalizadosoumtodosnativosquenoestodisponveisnorastreadorevento,
incluem PROGRAMADEBUGOUT()declaraes.(Nota:Estasdeclaraesnoprecisamesmode
serremovido.Seajaneladesadanoestdisponvelporquenoabertoouporque
oprogramaestsendoexecutadoemumambientetempodeexecuo,todososcomandosDEBUGOUT
sosimplesmenteignorados.)
AjanelaDEBUGOUTpodeserativadopormeiodeprogramaocom ativarajanela
"Sadadedepurao."

CallStackJanela

Ativao"ShowCallStackOrder"colocaumnmerosequencialaoladodecada
programanajaneladepilhadechamadasqueindicaaordemnaqualelessodeexecuo.
Poralgumarazo,ocontrolodestafunotemsidochamado'posioordinal"no
menupopupqueaparecequandovocclicacomobotodireitonajaneladepilhadechamadas.
Aativaodo'CallStack'Indicatormostraumtringulopretonafronteiradeambosos
Chamadajanelaspilhaerastreamentosemprequevocestvendoumprogramaquenosejao
aquelequeestatualmenteemexecuo.NajaneladeCallStackestetringuloindicaque
programaquevocestvendo,enquantoquenajaneladerastreamentoqueindicaalinha,namedidaemque
programa,queestemexecuo.

Configurandoodepurador
OsetupparaodepuradorcontroladaatravsdodilogoOpes,ondetemsuaprpriaguia.
Asconfiguraessoarmazenados(comoacontececomtodasasoutrasopescontroladosporestedilogo)nasjanelas
registro.

Oquadroquedesej ausar?
Odepuradorpodeserexecutadoemqualquerseuprprio"quadro",oqueotornaumaplicativoseparado,ou
dentro'quadro',oFoxProcasoemquetornaseumconjuntodejanelasindividuaisqueso
disponvelapartirdomenudeferramentasequeflutuamsobreareadetrabalho.Osprincipaisbenefciosdousoda
quadrodedepuraosodequeelenotomaespaodetelapreciosolongedetudooquevoc
emexecuo,todasasjanelasdodepuradorestocontidosemumanicajaneladenvelsuperioreso
facilmenteacessveiseos"consertar"obrasdeopo.Aprincipaldesvantagemdeusaramolduradedepurao
quesevoctiverocdigoemLostFocusouDesativareventos,essecdigoserdemitidoquandovoc
alternardeeparaodepuradorepodeinterferircomoquevocesttentandodepurar.
426 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Configurandoasj anelasdodepurador
opesdeconfiguraopadrododepuradorpodemserencontradosnacaixadedilogoVisualFoxProopes
(AcessvelapartirdoFerramentasalmofadadomenuprincipal),ondeelestmoseuprprioguia.Noentanto,o
interfaceparaestapginanopadroenoimediatamentebvioqueositens
disponvelparaaconfiguraodependerdequalajanelaespecificadopelobotodeopodo
'EspecifiqueJanela'seo,comosegue:

Tabela13.1janelaDebugopesdesetup

Janela opes
CallStack FonteeCores
ChamadaStackOrder
ChamadaStackIndicadordeLinhaatual
ChamadaIndicadordePilha
locals FonteeCores
Sada FonteeCores
Logsadaparaoarquivo(especificararquivopadro)
Vestgio FonteeCores
Mostrarosnmerosdelinha
Traoentrepontosdeinterrupo
Pausaentreaexecuodalinha
Assistir FonteeCores

Osignificadode'traceentrepausas'
Notesequeparaajaneladepilhadechamadasparaestardisponvelnodepurador,vocprecisa"Traoentre
breakpoints"paraserdefinidoON,masestaopo,felizmente,localizadosobo"JanelaTrace"
opes.Noentanto,amenosquevocestinspecionandoactivamenteapilhadechamadas,recomendamos
quemantenhaestajanelafechada.ajaneladepuradormaislentopararefrescarenquantoavana
pormeiodecdigo.
Naverdade,adefiniode"traceentrepausas"oprincipalfatornadeterminaodoimpacto
demanterodepuradorabertaduranteaexecuodecdigo.Nspreferimosdeixlodesligadoporpadro,
definiosapartirdomenudeatalhonodepuradorquandonecessrio.

Fecheasj anelasdedepuraoquev ocnoprecisa!


Quantomaisjanelasdedepuraoquevoctemaberto,maiorseroimpactosobreaexecuodoseucdigo
Tempo.interessantenotarque,aoexecutarodepuradorem"framedebug",vocrealmenteno
precisaterqualquerdasjanelasdodepuradorindividuaisaberta,desdequeoprprioquadro
ativo.Sevoctiverdefinidoeativadoqualquerpontodeinterruponecessrios,(incluindoosdefinidosno
ajanelaWatch)ospontosdeinterrupoaindairdispararconformeoesperado.Issosignificaquevocpodeexecutar
seucdigocomomnimoabsolutodedesacelerao.

Definirpontosdeinterrupo
FoxPropermiteaquatrotiposdepontosdequebra,comomostradonatabelaaseguir.Oprincipal
diferenaqueospontosdeinterrupocombaseemumaexecuolocaldeparadaantesdalinhadecdigo
executa,enquantoqueaquelescombaseemexpressesentramemvigorapsalinhadecdigofoiexecutado.

Captulo13:coisasdiversas 427

Tabela13.2Tiposdepontosdeinterrupo

Tipodepontodeinterrupo
temefeito
Nolocal Imediatamenteantesdalinhadecdigoexecutado
NolocalSeaexpresso Imediatamenteantesdalinhadecdigoexecutadoseacondioforatendida
verdade
Quandoaexpressoverdadeira Imediatamenteapsalinhadecdigoquecausouaexpressoparasetornarverdade
Quandoaexpressoalterada Imediatamenteapsalinhadecdigoquecausouaexpressomudana

Hmuitasmaneirasdedefinirpontosdeinterruponodepurador.Aquiestoalgunsquemaisencontrar
til:

Cliquecomobotodireitodomouseemumalinhadecdigoduranteaediodecdigodomtodonaformaou
ouemumaPRGeescolha"SetBreakpoint"(aplicaseaverso6.0comoServicePack3).
classededesigner
Issodefineum'breaknolocal'pontodeinterrupo.
Najaneladerastreamento,vocpodeselecionarqualquerlinhadecdigo,emseguida,cliquecomobotodireito
Esteumpontodeinterruporapidinhaquemuitotilpara,porexemplo,parandodepoisdeumloop
RunToCursor.
cesseouemalgumoutromomentoimediatosemdefinirumapermanente
pontodeinterrupo.
Najaneladerastreio,cliquenamargemaoladodeumalinhadecdigo.Issodefineuma"pausano
localizaopontodeinterrupo"emostraumpontovermelhonamargemparaindicaropontodeinterrupo.
Dumduplocliquenamesmalinhanovamente,paralimparopontodeinterrupo.
Najanelarelgiocliquenamargemaoladodequalquerexpressoobservou.Issodefineum
'Quandoaexpressomudanas'pontodeinterrupo,eexibeumpontovermelhonamargempara
indicamopontodeinterrupo.
Apartirdomenudeferramentasdodepuradorescolher"Pontosdeinterrupo"paraabrirumacaixadedilogo
podedefinirqualquerumdosdiferentestiposdepontodeinterrupodeformaexplcita.Noentanto,tanto
ondevoc
estatambmanicalugaremquevocpodedefiniro PASSCOUNTopoparaum'at
quantosabemos,
location'pontodeinterrupo.Esteumtilparaselembrarsevocdesejadefinirumpontodeinterrupo
dentrodeumloopmasnotmqueexecutadoatqueumdeterminadonmerodeiteraesdociclo
ocorreu.
Adicionarum"explcito SETSTEPON"emqualquerlugaremqualquercdigo.Istoirincondicionalmente
suspenderaexecuoeexibirodepuradorcomajanelaabertaderastreamento.

Aoexecutarodepuradoremseuprprioquadro,umdilogoadicionalmostratodomomento
breakpointsdefinidosepermiteativar/desativarlosdeformaseletiva.Notequeo'Limpartudo'
botonosdesativatodosospontosdeinterrupo,eletambmlimpalasdahistria.

428 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Figura13.1dilogoBreakPoint

Apesardoficheirodeajudaafirmandoque" CTRL+B"vaiexibirestedilogoemqualquerDebugou
FoxProquadro,estedilogonopareceestardisponvelaoexecutarodepuradoremFoxPro
Frame.

expressesdepontodeinterrupoteis
MuitasvezesadecisomaisdifcilcomoobterVisualFoxProparaquebrarprecisamentenoponto
quevocquer,semterqueadicionarcdigoexplcitoparaoquevocesttestando.Aquiesto
pardesugestesquetemosencontradotil:

Useum"tempocombase"pontodeinterrupo
Muitasvezesqueremosexaminaroestadodosnossosobjetosimediatamenteapsalgumusurio
interaocomoimediatamenteapsumacaixademensagemououtrodilogomodal.Introduzaumrelgio
expressocomoesta:

MINUTO(DATETIME())

edefinirumpontodeinterruposobreele.Emseguida,executeocdigodetesteeesperarnodilogoapropriadaat
asalteraesminutosantesdesairdodilogo.Opontodeinterrupoirpararimediatamente

Captulo13:coisasdiversas 429

execuoepermitirlheparaexaminaroestadodosistema.Omesmotambmpodeserexpresso
usadoparadetergrande(ouinfinitas!)ciclos.

Useafunodeprograma
Paradefinirumpontodeinterrupoquedisparasemprequeumprogramaoumtodoespecificadoexecutadousodeum
expressocomo:

"Checkmethod"$INFERIOR(PROGRAM())

Istoirmudarde.F.a.T.sempre"checkmethod"iniciaaexecuoefixando
'Quandoasmudanasdeexpresso'pontodeinterrupo,vocpodepararaexecuologonoinciodocdigo
quadra.Issopode,edeve,serfeitomuitoespecficaespecialmentequandovocquerquebraremum
chamadaaummtodoVFPnativaquepodemexistiremdiversosobjectos.Porexemplo,aseguir
breakpointsirinterromperquandooClickmtododeumobjetochamado'cmdNext'comeaa
executar:

"CmdNext.Click"$INFERIOR(PROGRAM())

enquantoaseguintelinhavaiquebrarquandoqualquermtododomesmo"cmdNextobjeto'
executa:

"CmdNext"$INFERIOR(PROGRAM())

Limitandopontosdeinterrupoparamudanas
Umdosproblemascomousodeum"quandoasmudanasdeexpresso'pontodeinterrupoqueVisualFoxPro
consideraraexpressoobservoucomomudouquandooqueestsendomonitoradoentraem,
ousaide,escopo.Paraevitaresteelimitebreaksparaaquelasocasiesemqueovalorfoi
realmentemudou,useum IIF()funopararetornarumaconstanteapartirdaexpressorelgioamenosqueo
valorquerealmentemudou.Porexemplo,aseguinteexpressoirinterromperoprograma
execuosemprequeumavarivelchamada'lnCnt'estnoescopoemudanasdeouparaumvalorde"3,"
mascasocontrrio,sertotalmenteignorado:
IIF(TYPE("lnCnt")="N"elncnt=3,.T.,F.)

Demodosemelhanteovalorderetornoapartirdeum SET("DATASESSION")detestepodeserutilizadopara
quandoadepuraocomvriosDataSessionsaberta,apenasocorretoestsendomonitoradopela
assegurarque
depurador.Assim,definirumpontodeinterrupoemumaexpressorelgiocomoeste:

IIF(SET("DATASESSION")#1,ALIAS(),"DSerrado")

vaiquebrarapenasquandooselecionado ALIAS()mudanasemumasessodedados,excetoo
VisualFoxProdatasessionpadro(ouseja,DataSession=1).
430 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Comopossogarantirqueosmeusmtodospersonalizadosdefogoquandoeuesperarqueeles?
Umdosmaioresproblemasquetodosnsencontraraotrabalharcomobjetosqueno
semprebvioquandooseventosdefogo.OobjetivodoControladordeeventos,queestincorporadono
depurador,paraquevocpossaseguirasequnciaemqueoseventosdefogonativodoVisualFoxPro.
AopermitiroacompanhamentodeeventosvocpodedirecionarVisualFoxProparaecoaronomedeeventose
mtodoscomoelesfogo,querparaajaneladesadadedepuraoouparaumarquivodetexto.Noentanto,vocnopode
monitorartodososeventosemtodosnativosdoVisualFoxProenohnenhumadisposioemtudopara
rastreamentodemtodospersonalizados.Ento,sevocprecisacontrolarexatamenteoqueestsendoexecutado,vocdeve
usarologgerdecoberturaouincluirocdigoparacriarumarquivodelogemsuasclasses.
Felizmente,aintroduodoSTRTOFILE()funonaverso6.0tornaissomuito
simples,naverdade.Anicalinhadecdigotudoquenecessrio,comosegue:

STRTOFILE(PROGRAM()+CHR(10)+CHR(13),"<logfilename>',.T.)

Asadaseronomedomtodoactualmenteemexecuoouprocedimentoparaoespecificado
Arquivo.Oparmetrofinalgarantequeotextoadicionadoaoarquivodedestinoseelejexiste,
casocontrrioSTRTOFILE()seriasimplesmentesubstituiroarquivodelog.
Temosutilizadoestatcnicaparamonitorarexatamenteocdigoemumaplicativocompilado
naverdadeexecutadodurantea'testescomusurios.Afimdefazerissodeformaseletiva,nsenvolvemosalinhade
cdigoquegravaoarquivodelogemumtesteparaumavariveldosistema(leiaapartirdoaplicativoINIarquivoem
comece).Depoisdisso,simplesmentealterandoaconfiguraonoarquivoINInospermitetransformartempodeexecuo
logoneoff.

Escrevercdigoparafacilitaradepuraoemanuteno
Houvemuitaspginasdeumbomconselhoescritosparatentarconvencerosprogramadoresqueeles
devemadotarboasprticasdefensivas,use,convenesdenomenclaturapadroadequadoeumplano
seucdigoantesdeescrevlo.Infelizmente,muitasvezesaindavemoscoisasquenosfazempensarse
algunsprogramadoressonemremotamenteincomodadocomapossibilidadedetestar,depurareatmesmo
manteroseucdigo.Aquiestoalgunsdosnossospensamentos,paraoqueelesvalemapena,emescrevermelhor
cdigo.

Usea/conv enopropriedadenomenclaturadev ariv eis


TemhavidomuitodebatenacomunidadeFoxProlongodosanossobretemascomo
seo"m."prefixoumacoisaboaparausarouseaconvenopadroMicrosoft
devemseradoptadasparanomearvariveisemtodasassituaes.Nsnopensamosqueissoimportemuito
bemoqueosdetalhesdesuaconvenodenomenclaturarealmenteso,contantoquevocconsistenteem
suaaplicao.Porqu?
ArazoqueVisualFoxProumalinguagemfracamentetipado.Emoutraspalavras,nofaz
impordigitaodedadosparasuaspropriedadesouvariveis.Istosignificaque,semotesteespecfico,voc
nopodetercertezaquetipodedadosumavarivelrealmentesesustentaporqueumavarivelderivaseutipo
apartirdeseusdadosemudanaspararefletirquaisquerdadosquedado.Isto,paradoxalmente,tantoum
dospontosfortesdoVisualFoxPro,etambmumadesuasgrandesfraquezas.
Captulo13:coisasdiversas 431

umafora,porqueelenospermitedefinirumavarivelemqualquerlugarqueprecisadeum
(Semterquedeclararformalmente)simplesmenteatribuindoumvaloraumareferncia.Istofaz
alinguagemdeprogramaomuitoflexvelefcildeusar.
umafraquezaporduasrazes.Emprimeirolugar,issosignificaquenohnecessidadedehaverumnicolocal
mtodo,procedimentooufunoondetodasasvariveis
numa utilizadassodeclarados.Istopodelevar
mesmonomedevarivelaserredeclaradaemdiferenteslugaresdentrodocdigo.outraconsequncia
quepequenoserrostipogrficoscausarerrosemtempodeexecuoporqueoquerealmenteumagrafada
nomedavarivelaceitopelocompiladorcomoumanovadeclaraodevarivel.Emsegundolugar,istosignificaque
mesmoquandoumavariveltenhasidodeclaradaexplicitamente,comonomeeinicializadocomumadadosespecficos
digita,osimplesatodeatribuiodedadosdeumtipoinadequadonoirgerarumerro.o
varivelsimplesmentemudaparaacomodarosdados.
Paraenfrentaroprimeiroproblema,recomendamosfortementequevoccrieohbitodedeclararqualquer
variveisquevoccriaremumaparteespecficadoprograma(normalmentelogonocomeo).
Nohnenhumamaneirafcildeevitarosegundoproblema,excetoparagarantirquequandoosdadossoatribudos
aumavarivel,onomedessavarivelindicacorretamenteotipodedados.Istopoderesultaremmais
variveisqueestsendocriadoeutilizado,mas,emnossaopinio,esteumpequenopreoapagarparaaclarezae
facilidadedemanuteno.
Enquantoestiverusandoumaconvenodenomenclaturanovairealmenteevitarerros,encontramoseletendea
lomaisfcildemanterascoisasconceitualmenteseparadaeassimminimizaapossibilidadedeintroduodeerro.
fazer
Sevocestendersuaconvenodenomenclaturaparaincluirobjetos,camposearquivosrealmenteat
voc,masessascoisassogeralmentemenosdeimediatosignificativo.Nssentimosquemelhorparagarantir
quenohdocumentaoadequadaparaumbancodedadosesuastabelas,eparaaspropriedadesexpostase
mtodosdeclasses.

Manterprocedimentosemtodostocurtoquantopossv el
Istopodeparecerbvio,masmenoscdigosignificamenosbugs.Maisimportanteaindamaisfciltanto
gerenciarocdigoecompreenderalgicaquandoselidacommtodosclaramentecentradasou
procedimentos.Comoregrageral,ummtododevelidarcomuma,eapenasuma,peaespecficade
funcionalidade.(Adoptandoesteprincpiotambmtornamaisfcilamtodosconhecidos!)Quantomaiora
graupeloqualummtodoestsobrecarregado,omaisdifcilparamanteremaiora
riscodealgodarerrado.

Useafirmaes"retorno"nomtodoeprocedimentodecdigo
ComoamaioriadosprogramadoresdoVisualFoxProquetendemaserumpoucodesleixadoemnossousodeRetorno
declaraes,especialmentequandonoestamosrealmenteretornarumvalorexplicitamente.Amaiorpartedotempo
issonoumproblema.OcompiladorFoxProinteligenteosuficienteparaaceitarquequandoseesgotade
cdigoemumlugar,eledeveretornarparaopedaodecdigoqueiniciouloeelevaiimplementarum
"implcita" RETURNparans.Noentanto,istopodecausarproblemasduranteadepuraodecdigo,especialmenteem
situaesemquealtimalinhaaserexecutadaouumachamadadefunoouumachamadaparaoutromtodo.
Aoadicionaraexplcita RETURNdeclarao,voctemumaoportunidadeparaparardentrodachamada
mtodoquandoorastreamentodecdigonodepurador.

Useafirmaparaaj udaraerrosdecapturaemtempodedesenv olv imento


Afirmasoextremamentevaliososparaodesenvolvedor,porqueelespermitemnosparalidarcomproblemas
diferenteemdesenvolvimentoeemtempodeexecuosemrealmenteterquealterarqualquercdigo.Isto

432 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

porqueoVisualFoxProsirexecutarumalinhadecdigoquecomeacomuma" ASSERTdeclarao"se
ocdigoexecutadonomododedesenvolvimentoe SETASSERTS ON.Emqualqueroutrasituao,alinhade
tratadocomosefosseumcomentrioenointerferecomaexecuodoprograma.
Umusocomumde ASSERTalertarosdesenvolvedores(etestadores)quandoalgonotem
comportadocomoesperado.Oobjetivoaquiparafornecerinformaesadicionaisaotestarem
desenvolvimento.Oseguintetrechodecdigomostracomoissopodeserfeito:

luSomeVarSomeProcessResult=()
IFVARTYPE(luSomeVar)#"C"
ASSERT.F.MENSAGEM'SomeProcessResultnoconseguiuretornarumacadeiadecaracteres'
RETURN.F.
FIMSE

Amensagemdeerrosvaiserexibidoquando SETASSERTSestligadoeoprocesso
noretornarumacadeiadecaracteres.Emtodasasoutrassituaes,seoprocessonoretornaumpersonagem
corda,ocdigoirsimplesmenteretornarumalgica f.econtinuarasuaexecuonormal.
OsegundousocomumdeAssertsverificarlgicadeprogramao.Esteligeiramente
diferentedoprimeiroexemploemqueoteste,nestecaso,sserrealizadaquando
Afirmaestohabilitadoseporissoemtempodeexecuonovaimesmosertentadooteste:
ASSERTPCOUNT()#3MENSAGEM"Esperava3parmetros,recebeu"+
PADL(PCOUNT(),2)

Mantenhaprocessamentoelgicaseparada
Umadasmaneirasmaisfceisdesimplificaroseucdigoparagarantirquevocnosemisturamse
processamentoelgica.Comoumexemplodoquequeremosdizer,considereoseguintecdigoquefoi
feita,comomostradoaqui,apartirdeumaaplicaoreal:
IFcheknam(alltrim(table2.legal_name))==cheknam(alltrim(
thisform.pageframe1.page1.text1.value))ENOcheknam(alltrim(
table2.legal_name))==cheknam(alltrim(Curval('legal_name","comprador"))

Istopodeparecermuitolegalmascomonaterraumsupostointerpretaredepurar
algoassim?Naverdade,sevocverificarestalinhadecdigocomcuidadovocvaidescobrirqueexistem
realmenteumparnteseausente!Comodevemasdeclaraesforamescritas?Bem,talvez
algocomoistoteriasidoumpoucomaisclaro:

***SerquetodosChekNam()funesdeprimeira
lcSceName=ChekNam(ALLTRIM(table2.legal_name))
lcInpName=ChekNam(ALLTRIM(ThisForm.PageFrame1.Page1.Text1.value))
lcLegName=ChekNam(ALLTRIM(CURVAL('legal_name","comprador")))

***Agorafaaoteste!
IFlcSceName==lcInpNameENOlcSceName==lcLegName

Porquenspensamosqueesteomelhor?Htrsrazes:

Captulo13:coisasdiversas 433

AschamadasparaoChekNam()funosotratadasseparadamente.Podemos,portanto,verificar,
(Nodepurador,mesmoquenoqueriacolocarcdigodeverificaonoprograma)que
osvaloresderetornosorealmenteoqueesperamos.
Naverdade,podemosreduzironmerodechamadasquefazemosaoChekNamfuno.
OtesterequerqueovalorquechamamoslcSceNameserusadoduasvezes,demodoqueo
cdigooriginaltemquefazerduaschamadasparaafuno,passandoomesmovalordecadavez.
Temosagoraseparadosalgicadoprogramaapartirdoprocessamentorealizadopelo
ChekNam()funo.Istosignificaque,mesmosemsaberoqueoChekNam()
funofaz,podemospelomenosveroqueo IFdeclaraorealmentetestarepode
validarosresultadosdodepurador.

TrabalhandocomDataSessions
NsnocobrimosousodeDataSessionsespecificamenteemqualqueroutrapartedolivroprincipalmente
porquenopoderiadecidirseotemafoirelacionadoadadosouaformas.Aquiestoalguns
dicasetruquesparausarDataSessions.

ComopossopartilharDataSessionsentreasformas?
realmentemuitofcildeobterumformulrio(ourelatrio)parausarodatasessionprivadadoobjetoque
chamou.BastadefiniroobjetofilhoDataSessionpropriedadecomo"1padroparaasessodedados".este
funcionaporcausadaformaVisualFoxProinterpretaotermo"padro"nestecontextoeno
oquevocpoderazoavelmenteesperar!
QuandovoccomeaaVisualFoxProeabrao"JanelaDataSession",vocvainotar
datasessionqueacorrente"Padro(1)".PropriedadeAmbientedatasessiondeumformulriopara"1Padro
Sessodedados",pareceprovvelparagarantirqueaformausaomesmonmerode1DataSession
queVFPrefereseacomopadro.Infelizmenteissononecessariamenteverdade!Nestecontexto,otermo'Default'
realmentesignificaqueaformasenocriarumdatasessionprivadoparasimesmo,massusa
oquequerquedatasessionatualquandoeleinstanciado.porissoqueumaformacujasdatasession
apropriedadedeixadaem"1defaultsessodedadosaes"asessodedadosdoformulrioquelanalo.
SeumformulriousaseuprprioDataEnvironmentparatabelasAutoOpen/AutoClose,somenteastabelas
queso,naverdade,abertopeloformulriofilhoserfechada.Emoutraspalavras,seoformulriofilho
requerumatabelaquejestabertonodatasessiondoformulriopai,VisualFoxProinteligente
osuficienteparareconheceressefatoenoreabriressastabelasquandooformulriofilho
instanciado,oufechlasquandooformulriofilholiberado.
Umacoisaanotarque,sevocpermitirqueumaformadecompartilharadatasessionprivadadeoutro,
quandovocsoltaracrianaformaronomeVisualFoxProDataSessionatualmudarpara
'Unknown(n)',onde'n'onmerodatasessiondaformaqueoriginalmentecriouo
datasession.Noentanto,issonoparececausarVisualFoxProqualquerproblema,emboraelepode
serumpoucodesconcertantequandovocperceberissoacontecer.Arazopareceserque,embora
VisualFoxProcapazderenomearodatasessionparaoproprietrioatual,quandoacriana
formulrioinstanciado,elenosabecomovoltaranomeloquandoessaformaliberadoeassim
simplesmentedeixalocomo'desconhecido'.

434 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ComofaoparamudarDataSessions?
Apesardainformaoemcontrrionoarquivodeajuda,deumaformaDataSessionIDpropriedade
realmentelerescreveremtempodeexecuo.Vocpode,portanto,forarumformulrioparaserexecutadoemumdatasession
definindosuaDataSessionIDpropriedadediretamentenocdigo.Noentanto,sevoctemqualquerlimite
especfica
controlesemseuformulrio,mudandosessodedadosdoformulriodepoisdeteremsidoobrigadoscausar
lhegravesproblemas.Ograudegravidadevaidependerdocontroloemquesto.Umagrade
simplesmentevaiperderasuaRecordSourceeirirrevogavelmenteembranco.UmacaixadelistacujoOrigemDaLinha
tiradadeumamesafarum"UnabletodeacessoselecionadoTable'erroeirdesaparecer,
enquantoumacaixadecombinaoirsimplesmentepassarembranco.Curiosamente,religaroformulrioparaacorreta
datasessionirrestaurarascoisasaonormalnocasodeambososdalistaedecombinaocaixas,emborano
paraasredes.Amoraldestahistriaque,sevocprecisamudardatasessiondeumformulrio,faaona
CARGAdoformulrioantesdequaisquercontrolesforaminstanciado,enopermitirqueaformade
DataEnvironmentparatabelasAutoOpen.
Podehaver,noentanto,haverocasiesemquevocprecisaparamanipularumobjetode
DataSessionIDpropriedade.Porexemplo,barrasdeferramentassomuitasvezesobrigadosamudarseparao
datasessiondoformulrioativonomomento.(Nossa"administrado"classebarradeferramentasnoCaptulo10temcomo
cdigoeestenoumproblema,porqueessasbarrasdeferramentasgenricasnotemosdadoscontrolesligados.)
ParaosobjetosquenotmumDataSessionIDpropriedade,vocdeveusaro SET
DATASESSIONcomandoparaalterarodatasessionglobal.Istopodesernecessrioparaumaorganizaoglobal
objeto(porexemplo,umobjetodeaplicativo)quecriadonasessodedadospadrodoVisualFoxPro,mas
quepodemprecisardeacessoatabelasabertasporumformulrioemumdatasessionprivado.Desdequevoc
primeirosalveodatasessionatualerestaurlologoemseguida,issonodevecausar
problemas,mesmoquandooutrosobjetoscomdadosligadocontrolesestopresentes.Ocdigoaseguir
trechomostracomo:

***SalvarDSatual
lnDSID=SET("DATASESSION")
***MudanaDatasession
SETDATASESSIONTO<novonmerodesesso>
***Faaoquefornecessrioe,emseguida,reverter
SETDATASESSIONTO(lnDSId)
Captulo13:coisasdiversas 435

ComofaoparaobterumalistadetodosDataSessionsativos?(Exemplo:getallds.prg)
NohnenhumamaneiranativaparaobterumalistadetodososDataSessionsativosdeprogramao,masdesdeque
normalmentesestarinteressadonosDataSessionssendousadoporformulrios,podemosusaro
_SCREEN.FORMSColeoparadeterminarquaisestoativos.Afunoaseguirfazprecisamente
esteepreencheumamatriz(quepassadoporreferncia)comonmerodatasessioneo
possuirnomedoobjeto.AfunoretornaonmerodeDataSessionsativosqueeleencontra:

**********************************************************************
*Programa :GetAllDS.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:PreenchermatrizcomtodososDataSessionsabertas
* :Matrizdedestinopassarporrefernciaaestafuno
* : DIMENSOaDSList[1]
* : lnNumSess=GetAllDs(@aDSList)
**********************************************************************
LPARAMETERStaSessions
taSessionsARRAYEXTERNAS
lnCurDatasessionLOCAL,lnSessions
***InicializarContador
lnSessions=0
***LoopatravsdeformasColeco
PARACADAoFormIN_SCREEN.FORMS
***Temosnscomeamosestasessoj?
IFASCAN(taSessions,oForm.DatasessionID)=0
***Seno,adicionloparaamatriz
lnSessions=+1lnSessions
taSessionsDIMENSO[lnSessions,2]
taSessions[lnSessions,1]=oForm.DatasessionID
taSessions[lnSessions,2]=oForm.Name
FIMSE
PRXIMO
***Retornaonmerodesesses
lnSessionsRETORNO

Itensvariados
Orestantedestecaptuloumacoleodecoisasquensnoinclumosespecificamente
emoutrolugar.Noexisteumaligaoespecialentreeles,maselessodignosdemeno,mesmose
apenascomoumlembrete.

Qualasequnciadeeventosquandoumformulrioinstanciadoou
destrudo?
ComofrequentementeocasocomVisualFoxPro,arespostaque"eledepende.'Nestecaso,depende
deseoformulrioestaserinstanciadoapartirdeumSCXarquivousando" DOFORM'oudeumarquivoVCX
usando CREATEOBJECT()ou NEWOBJECT().Instanciaraformacomoumaclasseomaissimplese
aquiasequnciadeeventos:

Form.Load
INITparacadacontrole

436 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FORM.INIT
FORM.SHOW
FORM.ACTIVATE
FORM.REFRESH
Quando,por1stcontrolenoTabOrder
GotFocuspara1stdecontrolenoTabOrder(setiverum)

Asequnciadestartupdebase,portanto,dadapelasigla"LISAR".Porpadro,
oscontrolosindividuaisnoformulriosoinstanciadonaordememqueforamadicionadosao
classenodesigner.Noentanto,utilizandoo'Trazerparaafrente"e"Enviarparatrs'opes,vocpode
alterarasequnciaemqueoscontrolessoinstanciado.(Emboraelerealmentenodeveimportarem
queordemascoisasestoinstanciado.aulasCriandoquedependemdecontrolessejainstanciadoemum
ordemparticularno,emnossaopinio,umbomdesign!)
Soltarumaclassedeformulrioessencialmenteoinversodoprocessodeinicializao.olanamento
mtodoforneceosmeiosparainiciaroprocessodeprogramao,enquantooQueryUnload
mtodochamadoquandoumusurioclicanoboto"fecharjanela"emumformulrio.Nemachama
outra,amenosqueespecificamenteadicionarcdigoparatornlosfazlo,masamboschamaraformadedestruir
Mtodo:
FORM.RELEASEouFORM.QUERYUNLOAD
FORM.DESTROY
DESTRUIRparacadacontrole(emordeminversa)
FORM.UNLOAD

Istosignificaquesevocprecisardecdigoaserexecutadoindependentementedeousuriofechaa
formulrio,clicandoemumbotodecomando(quechamadelanamento)oua"fecharjanela"boto
(quechamaQueryUnload),emseguida,queocdigodevesercolocadonaformadedestruirmtodo.
NocasodeumaformacriadaapartirdeumaSCX,asequnciadeeventosbsicoformaamesma,
masapresenadeDataEnvironmentnativacomplicaoproblema.Notesequeo
DataEnvironmentOpenTablesmtodochamadooprimeiromtodo(istodisparaBeforeOpenTables)
mesmoantesdoformulrioCargamtodochamado.ApsoformulriodeCargamtodofoiconcluda
comsucesso,oscursoressoinicializados.Issogaranteque,quandooscontrolesdoformulrioso
instanciado,aquelesqueestoligadosaosdadossercapazdefazlocorrectamente:
DATAENVIRONMENT.OPENTABLES
DATAENVIRONMENT.BEFOREOPENTABLES
Form.Load
INITparacadacursornoDataEnvironment
DATAENVIRONMENT.INIT
INITparacadacontrolenaforma
FORM.INIT
FORM.SHOW
FORM.ACTIVATE
FORM.REFRESH
Quando,por1stcontrolenoTabOrder
GotFocuspara1stdecontrolenoTabOrder(setiverum)

Oprocessodelibertao,namedidaemqueaformaemsiestemcausa,idnticoaoqueacima.Avisoprvio
queoDataEnvironmentnorealmentedestrudoatapsoformulriofoidescarregadoda
memria:

Captulo13:coisasdiversas 437

FORM.RELEASEouFORM.QUERYUNLOAD
FORM.DESTROY
DESTRUIRparacadacontrole(emordeminversa)
FORM.UNLOAD
DATAENVIRONMENT.AFTERCLOSETABLES
DATAENVIRONMENT.DESTROY
DESTRUIRparacadaCursornoDE(emordeminversa)

Comofaoparaobterumarefernciaaoformulriopaideumformulrio?
Humpardemaneirasdefazerisso,osermaisbviosimplesmenteparateropai
formulriodepassarumarefernciaasimesmoaochamaroformulriofilhoassim:

DOFORM<formcriana>Comesta

Noentanto,istoexigequeoformulriofilhoInitmtododeveserconfiguradopararecebero
objetoderefernciacomoumparmetroe,emseguida,armazenloparaumapropriedadedeformulrio.Curiosamenteo
apontadopeloVisualFoxPro_SCREEN.ACTIVEFORMpropriedadenoalteradoquandoumanovaforma
objecto
instanciadoatquedoformulrioInitmtodofoiconcludacomxito.(Issofazsentido
quandoselembraquedevolverumalgica f.apartirdequalquercargaouInitmtodosir
impedirqueanovaformadeinstanciar.)
Portanto,paraobterumarefernciaparaaformadechamada,nohnecessidadedepassarnada.
Bastaarmazenar_SCREEN.ACTIVEFORMaumapropriedade,queremcargaouInitmtododacriana
Formato.Normalmente,temosquecolocaressetipodecdigonacargamtodo(paradeixaroInitlivrepara
manipulaodeparmetros)comoeste:

IFTYPE("_Screen.ActiveForm.Name")#"U"
ThisForm.oCalledBy=_SCREEN.ACTIVEFORM
FIMSE

Notequenopodeutilizarcomseguranao VARTYPE()funoaquiporqueeleirfalharsenohouver
nenhumaformaativa.

Comofaoparaobterumalistadetodososobjetosemumformulrio?
OobjetoVisualFoxProFormtemumacoleochamada"Controls"eumcontadorassociado
propriedade("ControlCount")contmumarefernciaparacadaobjetonoformulrio.Noentanto,este
coleosmantmrefernciasaobjetosquesodiretamentecontidospeloformulrio.Assim,por
exemplo,noirincluirobjetosqueestoemumapgina,dentrodeumpageframenoformulrio.tudooque
vaiterarefernciaparaopageframe.Paraobterumalistadetodososobjetos,que,portanto,sernecessrio
"Drilldown"emcadarecipientequeencontrado.
FelizmentecadaclassedecontinerVisualFoxProtemumacoleo(econtadorassociado)
quedetmrefernciasaosobjetosqueorecipientepossui.Infelizmente,estascoleces
nosotodosomesmonomequeoquadroseguinteindica:

438 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela13.3coleesclassedecontiner

BaseClass Coleo Contrapropriedade


_Tela Forms FormCount
_Tela controles ControlCount
formset Forms FormCount
Formato controles ControlCount
Toolbar controles ControlCount
PageFrame Pginas Contagemdepginas
Pgina controles ControlCount
Grade colunas ColumnCount
Coluna controles ControlCount
Recipiente controles ControlCount
personalizadas controles ControlCount
Aocontrole controles ControlCount

Estavariaonanomenclaturafazescreverumarotinaqueirperfurarparabaixoatravsdeumaformaum
poucomaisdifcilporquetemosdetestarosbaseclassdecadarecipientequeencontramosem
afimdeverificarqualasuapropriedadedecoleochamado.OformulriodeexemploLogCtrls.Scxtemum
mtodorecursivopersonalizado(GetControls)eumapropriedadedematrizpersonalizado(aAllControls),que
usadocomoacoleodetodososcontrolesepreenchidopelocostumeAddToCollectionmtodo.
Finalmente,umcostumeRegisterControlsmtodousadoparainicializarapropriedadedematrizeparacomear
oprocessodeperfuraoparabaixo,chamandooGetControlsmtodocomumarefernciaaoprprioformulrio.
AquiestocdigoparaoRegisterControlsmtodo:

***MtodoLogCtrls::RegisterControls
***ColeoFormIniciaechamaoGetControlsrecursiva()
COMThisForm
***Limparalistaatual(sehouver)
.aAllControlsDIMENSO[1,3]
.aAllControls=""
***Comeceodrilldowncomoprprioobjetodeformulrio
.GetControls(Este)
ENDWITH

OGetControlsmtodoumpoucomaiscomplexo.Aprimeiracoisaqueelefazcriarumlocalde
refernciaparaoobjetopassadoparaelecomoumparmetro(notequeeleirusaroprpriosenadaForm
passada).Emseguida,elechamaoAddToCollectionmtodoparaadicionaroobjetoparaacoletae
emseguida,armazenaclassebasedoobjetoemoutravarivellocalparausoposterior:

***MtodoLogCtrls::GetControls
***Brocasparabaixoatravsdeformulrioepreencheamatrizdecoleopersonalizada
LPARAMETERStoStartObj
LOCAISloRef,lnCnt,lnControls,loObj

***Obterrefparaopaiouparaformar,porpadro
loRef=IIF(TYPE('toStartObj')='O',toStartObj,THISFORM)
***AdicionarEsteobjetocoleo
ThisForm.AddToCollection(loRef)
Captulo13:coisasdiversas 439

***Obteraclassebasedoobjetoatual
lcClass=LOWER(ALLTRIM(loRef.BaseClass))

Emseguidaprecisodeterminarquetipodeobjetoqueestamoslidandocomnaiteraoatual.
Primeirovamosverificarparaverseestamosalidarcomumadasclassesqueusamalgodiferente
doqueumacoleo'controles'.SeassimchamamosdeGetControlsmtodorecursivamenteaoloop
atravsdarecolhadesseobjeto:
***AgoraProcessaroobjetoatual
DOCASO
CASElcClass='pageframe'
PARAlnCnt=1aloRef.PageCount
***Chameessemtodoparacadapgina
THISFORM.GetControls(loRef.Pages[lnCnt])
PRXIMO

CASElcClass='grid'
PARAlnCnt=1aloRef.ColumnCount
***Chameessemtodoparacadacoluna
THISFORM.GetControls(loRef.Columns[lnCnt])
PRXIMO

CASElcClass='formset'
PARAlnCnt=1aloRef.FormCount
***Chameessemtodoparacadaforma
THISFORM.GetControls(loRef.Forms[lnCnt])
PRXIMO

Qualqueroutraclassedecontinerestarusandoumacoleo"Controls"paraquepossamosprocesslostodos
emumanicainstruocaso.(Notequensverificamos,usandoumacomparaoexata,paraa'pgina'
classebase.IssoparaevitarcairnasarmadilhasdecordaligeiramenteidiossincrticadoVisualFoxPro
comparaoqueiriaretornar .T.sesimplesmenteincludos'pgina'nalista,masoobjetofoi
um'pageframe'.)
Seoobjetoatualumrecipiente,estecdigopercorreasuacontrolescoleo.Maisumavez
verificamosaclassebasedecadaobjetoqueencontramose,seforumoutrorecipiente,ligueparao
GetControlsmtodorecursivamentepassandoumarefernciaparaoobjeto.Noentanto,senoforum
recipiente,umarefernciaaissopassadoparaoAddToCollectionmtododemodoquepossaserregistrada:

***OK,umobjetoquetemumacoleodecontroles?
CASEINLIST(lcClass,'forma','recipiente','coluna','personalizado','controle')
'Pgina'ORlcClass==
***Seassimfor,loopatravsdesuacoleo
PARAlnCnt=1aloRef.ControlCount
***Obterumarefernciaparaoobjetoatual
loObj=loRef.Controls[lnCnt]
IFINLIST(loObj.BaseClass,'Container','Pageframe','Grid','Custom',
'Aocontrole')
***Chameessemtododeformarecursivaseumrecipientecontido
ThisForm.GetControls(loObj)
OUTRO
***Bastaadicionaroobjetocoleo
ThisForm.AddToCollection(loObj)
FIMSE

440 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

PRXIMO

Seoobjetoatualnodesencadearqualquerumadascondiesnestecomunicadocaso,noum
recipienteejfoiregistadoparaquepossamosignorloesaircomseguranaapartirdestenvelde
recurso:
DEOUTRAFORMA
***Nadamaisafazeraestenvel
ENDCASE

***Apenasretorno
RETORNA

Onicooutrocdigoaquelaquerealmenteadicionaumobjetodoformulrio'aAllControls'
coleo.Istomuitosimples,naverdade,porqueelerecebeumarefernciadiretaaoobjetoqueele
temdeiniciarsessocomoumparmetrodoGetControlsmtodo:

LPARAMETERStoObj
loRefLOCAL
IFVARTYPE(toObj)#"O"
***Senoumobjeto,bastaretornar
RETORNA
OUTRO
***Obterreferncialocal
loRef=toObj
FIMSE

Depoisdeverificarqueoparmetrodefatoumobjeto,aprximatarefadeterminarcomo
muitositensjforamregistradas:

COMThisForm
***Onmerodelinhasjemcoleo
lnControls=Alen(.aAllControls,1)
***Seumalinhapovoada?
IFlnControls=1
lnControls=IIF(vazio(.aAllControls[1,1]),0,1)
FIMSE
***Incrementarocontador
lnControls=+1lnControls

Umanovalinhaentoadicionadorecolhaeoselementosdarecolhapreenchida:

***Adicionarumalinhaparaamatriz
.aAllControlsDIMENSO[lnControls,3]
***Preenchaanovalinha
.aAllControls[lnControls,1]=loRef.Name &&Nomedoobjeto
.aAllControls[lnControls,2]=loRef &&ObjectReference
.aAllControls[lnControls,3]=SYS(1272,loRef)&&HierarquiadeObjetos
ENDWITH
***ApenasRetorno

Captulo13:coisasdiversas 441

RETORNA

Hmuitassituaesemquetilparasercapazdepercorrertodososcontrolesemum
Formato.Emboraessecdigoescritoespecificamenteparapreencherumamatrizdecoleo,comexceo
dasduaschamadasparaoAddToCollectionmtodo,ocdigocompletamentegenricaepodeser
usadoaqualquermomentonecessrioparaperfurarparabaixoatravsdeumformulrio.Almdisso,umavezqueos
mtodochamadocomumarefernciadeobjeto,elenotemquecomearcomoformulrio.Elepodeapenas
GetControls
comearcomoobjetoderefernciapassado.

Comopossodefinirofocoparaoprimeirocontrolenaordemdetabulao?
Umarespostaaestaperguntaquevocpodeusarcdigosemelhanteaoquedadonaanterior
seoparadetalharatravsdeumrecipiente(ouseja,aforma,ouumapginaemumformulrio)paraencontraro
objetocontidoquetemasuaTabIndexpropriedadedefinidacomo1.focoseguida,bastadefiniraesseobjeto
esair.
Comoalternativaaousarformulrioscomvriaspginas,emvezdeexecutarrepetidamenteesse
drilldowncdigo,vocpodepreferirparaconstruirumacoleoespecial(quandooformulrioinstanciado)
paragravarparacadapginaumarefernciaparaoobjetoqueoprimeironaordemdetabulao.Entotudooque
serianecessrioseriafazeravarreduraqueacoletaparaapginadesejadaedefinirofocoparao
objetoespecificado.

Comofaoparadevolverumvalorapartirdeumformulriomodal?
Emoutroslugares,nsjdiscutimosalgumastcnicasparapassarparmetrosentreobjetos
dediferentestipos.Oquensnocobrimosespecificamenteemqualqueroutrolugarsoosvrios
tcnicasparaobtervaloresdevoltaapartirdeumformulriomodal.Oconceitode"retornarumvalor"
sfazsentidoquandoaformaderetornarovalormodalporqueorequisitoimplcito
quealgumprocessopodeserinterrompido,oususpensos,atqueovalordesejadodevolvido.
Susandoumformulriomodalvocpodegarantirque:

Oprocessonopodecontinuaratqueovalorestdisponvel
Ovalorretornadoparaolocalcorretonocdigodechamada.

Existemessencialmentetrsmaneirasdeconseguirumvalordevoltaapartirdeumformulriomodal,masumdos
elessfuncionaparaformasquesoexecutadoscomoarquivosSCX,trabalhasecomformasqueso
instanciadoapartirdearquivosVCXeumfuncionaindependentementedaformacomooformulriocriado.Lembrar
que,apesardequeestamosafalardevoltar"umvalor",este"valor"podeserumobjetodeparmetro
contendovriositens(verCaptulo2"FuneseProcedimentos"paraobtermaisinformaessobre
criaoeutilizaodeobjetosdeparmetro).

Retornandoumv alordeumformulrio
Omecanismorealpararetornarumvalordeumformulriobastantesimples.vocsimplesmente
colocarum RETURN<valor>comandocomoaltimalinhadecdigonaformadoUNLOADmtodo.
Esteoltimomtododeformulrioaserexecutadoantesqueumformulrioliberadoeporissoumperfeitamente
lugarlgicoparaainstruoderetorno.Noentanto,humpoucodecaptura.Seovalorquevoc
desejaretornarprovenientedeumcontrolenoformulrio,nomomentoemqueomtodoUnloaddoformulrio

442 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

corretodososcontrolesforamlibertados,paraosvaloresqueeramtitularesdeixarodeestardisponveis.Para
contornaresteproblemanecessriogarantirquequaisquervaloresdecontrolevocdesejaretornarsosalvos
propriedadesdoformulrio,omaistardarnoFormulriodedestruirmtodo.(Vejaaseoanteriormenteneste
captuloparaobterdetalhessobreaseqnciadeeventosquandoumformulrioinstanciadooudestrudos.)

Ocultandoumformulriomodal
Umamaneiradeobteracessoaosvaloresqueestocontidosdentrodeumformulriomodalsimplesmenteparaesconder
aformaemvezdeliberlo.Quandoumformulriomodalestescondido,oqueformaeraativa
imediatamenteanteriorformamodalsendoinstanciadotornaseaformaactivamaisumavez.em
outraspalavras,aformaquechamouoformulriomodalreativado.Desdequevoctem,
dentrodaformadechamar,umarefernciavlidaparaoformulriomodalpodeacederaqualquerexposta
Propriedadesdoformulrio,oudeseuscontrolescontidos.Estaabordagemirfuncionarindependentementedo
formanaqualaformainstanciado.
Oseguintetrechodecdigomostracomoissopodeserfeitodeumaformainstanciadodiretamente
deumaclasse:
***Instanciarumformulriomodal
OFM=NewObject('modalform','formclasses')
***Mostraraformaegarantirqueelemodal
oFm.Show(1)
***Quandoformulrio'liberado',naverdadeoculta!
***AcesseaspropriedadesdoformulrioModaldiretamente
ThisForm.SomeProperty=oFm.ModalFormProperty
***Solteoformulriomodalquandofeito
oFm.Release()

EnquantoqueparaumformulrioquecriadoapartirdeumarquivodeSCX,ocdigoaseguirequivalente:

***Instanciaroformulriomodal
DOFORMmodalformNOMEOFMLIGADO
***Quandooformulriomodal"liberado",naverdadeoculta!
***Onome'OFM'podeagoraserusadoparaacesslodiretamente:
ThisForm.SomeProperty=oFm.ModalFormProperty
***Solteoformulriomodalquandofeitosoltandoo"nomeligado"
LIBERTAOOFM

Usandofazerformulrio<name>para<v ariv el>


ParaformasmodaisqueforamcriadoscomoarquivosdeSCXequesoexecutadosutilizandoo FORM
comando,humasintaxeespecficaquevocusaparasalvarumvalorquedevolvidoapartirdoformulrio,como
segue:

DOFORMmodalformTOluRetVal

Quandooformulriomodalliberado,oquequerquefoidevolvidoapartirdoformulrioUnloadmtodo
serguardadoparaavarivel'luRetVal'.Notesequeestavarivelnoprecisadetersido
anteriormentedeclaradoesercriadaconformenecessrio.Noentanto,seoformulriochamadono
conteruma RETURNdeclaraoemseuDescarregarmtodo,avarivel nosercriado.Assim,emnossa
Captulo13:coisasdiversas 443

opinio,muitomaisseguroparasempredeclararexplicitamenteavarivelderetorno,einicializeo,emvez
dedependerapenasdaexistnciadeumainstruoderetorno.

Retornandoumv alordeumaformainstanciadodiretamentedeumaclasse
Oproblemanestasituaoquenohnenhumamaneirapararetornararefernciadeobjetoeum
valortantodaretornar CreateObjectou NEWOBJECTfunes.Umavezquetantodeveretornarum
refernciaaonovoobjetotemosqueencontraroutramaneiradeobterumvalordevolta.Asoluo
passarumobjetodeparmetroparaoformulrioquepodeentoserdevolvidopeloformulriomodalquando
liberado.
Aclassedeformulriodeveserconfiguradoparareceberearmazenaraumapropriedade,oobjetoparmetroque
transmitidoaomesmo.(NormalmenteteramostambmaclasseInitmtodochamarseuMostrarmtodo
diretamenteparafazeraformavisvelimediatamentenainstanciao.).Esteobjetodeveserpreenchido
comaspropriedadesrelevantesenquantoqueaformaactivaedevolvidoparaomtododechamada(ou
procedimento)apartirdoformulriomodalDescarregarmtodo.Ocdigoparainstanciaroformulriomodal
ficariaassim:

***CrieoobjetoParameter
oParamObj =CREATEOBJECT('parameterobject')
***Instanciaroformulriomodal
oModalForm=CREATEOBJECT('modalformclass',oParamObj)
***Verifiqueaspropriedadesdoobjetoretornado
IFoParamObj.FormWasOK
***Faaoque
OUTRO
***Fazeroutracoisa
FIMSE

Comofaoparaalteraroponteirodomouseemformaenquantoumprocesso
correndo?
Comodecostume,arespostabsicamuitosimples.TodososcontrolesvisuaistmumMousePointerpropriedade
quedeterminaaformadocursordoratoquandoocursorestposicionadoaolongodeumcontrolo.
Noentanto,porquecadacontroletemsuaprpriaconfiguraoparacontrolaroponteirodomousenoexiste
nicapropriedadeoumtodoparacontrolaroMousePointerpropriedadeparatodososcontrolesemumformulrioem
umavez.
Aformapadroparamudartodososvaloresdeumapropriedadeparatodososobjetosemumformulriousar
doformulrioSETALLmtodo.Ocdigoaseguirdefineoponteirodomouseparatodososcontrolesemum
formarparao'ampulheta':

COMThisForm
***Situadoprprioponteirodomousedoformulrio
.MousePointer=11
***objetosAgoratudocontidos
.SetAll('MousePointer',11)
ENDWITH

Pararestauraraconfiguraopadro,bastarepetiressecdigocomumvalorde0emvezde11.
Noentanto,issonocontarcomtodososcontrolesnoformulriousandoomesmoMousePointerpropriedade
configuraoemtodososmomentos.SevocjtemdiferentesMousePointerconfiguraesdepropriedadeparadiferentes

444 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
classesdecontrole,anicaalternativapercorrertodososcontrolesemumformulrioesalvarcada
atualdocontroleMousePointerpropriedadeedefiniloexplicitamenteparaovalordesejado.(Vocpode
utilizecdigosemelhanteaomostradono"Comofaoparaobterumalistadetodososobjetosemumformulrio?"seo
estecaptulo.).Pararestauraroponteirodomousequevocsimplesmentetemquerepetiroprocessoe
lerovalorsalvo.Nssentimosqueesteumcenriobastanteincomumenormalmenteesperaria
encontrartodososcontrolesusandoseu('default'MousePointer=0)definio.
Porenquanto,tudobem!Infelizmente,noumaexceoatudooquedissemosacima
quandoumagradeestenvolvido.EnquantoumagradetemumMousePointerpropriedade,quenocompletamentecerto
porque.NaVerso6.0,dequalquermaneira,noparececomportarsedamesmaformaqueoutroscontrolese
afetaapenasovisorquandoomouseestsobreumareadagradequenocontmqualquer
dados.NoimportaoqueagrelhaMousePointerpropriedadedefinidacomo,movendoomousesobreo
partepovoadadagradesempreexibeo"I"cursorviga.
AmelhorsoluoquepodemosdarparaadicionarumtransparenteSHAPEobjetoparacobrir
agrade(exceptoparaasbarrasdeposicionamento).Oresultadoque,naverdade,oobjetodeforma
Mousepointerqueousuriovquandoelessemovemsuaponteirodomousesobreagrade.Clarose
agradenosomenteleitura,quedeveforneceralgummecanismoparadetectarumcliquesobreaforma
etransferindoaparaaparterelevantedarede.Felizmentealgumasnovasfunesem
Verso6.0podenosajudaraqui.Ocdigodeexemploincluiumformulrio("ChgMPtr.scx")que
mostracomoissofunciona.Aquiestocdigodomtododecliquedaformaquesesobrepe
grade:

***Nsprecisamossaberonomedarede
COMThisForm.grdVatrates

***UseAMOUSEOBJ()paraobterdetalhessobreaposiodomouse
ArraylocallaList[1]
AMOUSEOBJ(laList,1)

***XeYcoordenadasestoemlinhas3e4
LNX=laList[3]
lnY=laList[4]

***Inicializaralgumasvariveis
lnGObj=0
lnGrow=0
lnGCol
=0

***UseGridHitTest()paraobterGradeLinha/Colunasobomouse
llStat=.GridHitTest(LNX,lnY,@lnGobj,@lnGRow,@lnGCol)

***EnviarFormaatrsdagrelha
This.ZORDER(1)

***Ativeaclulacorretanagrade
.ActivateCell(LnGRow,lnGCol)
.SetFocus()

ENDWITH

Estecdigodeterminaondenaformaocorreuocliqueetraduzessaposio
nalinhacorrespondenteeacolunadagrade.Emseguida,solteaformaatrsdagrade

Captulo13:coisasdiversas 445

eativaraclulacorreta.Onicotruquequetemosderestauraraformaparaasua'OnTop'
posioquandoagradeperdeofoco,masagradenotemLostFocusmtodo!Portanto,temosdeadicionar
cdigoparaagradevlidomtodoemvezdisso,echamarprpriadagradeZOrdermtodoparaenviaragrade
"Parabaixo"restaurandoassimoobjetodeformasuaposiooriginalsobreagrade.

Comopossocriarumapropriedade"global"paraaminhaaplicao?
NoVisualFoxPro,aspropriedadessoescopoparaobjetosporissonorealmentepossvelparaumapropriedadede
ser"global"damesmamaneiraqueumalatavariveldememria.Omelhorquepodemosfazerdefiniro
propriedadecomopertencenteaumobjetocujoescopoglobal.Tendoemcontaestaabordagem,temosuma
pardeopes.
Emprimeirolugar,poderiasimplesmentecriarumobjetodaclassenecessriaeassociarsuarefernciacom
Umavarivelpblica,comoeste:

LIBERTAOgoGlobalObject
goGlobalObjectPBLICO
goGlobalObject=NEWOBJECT(<class>,<ClassLibrary>)

Qualquercoisanopedidoagoratemacessoa'goGlobalObject'e,portanto,atodooseu
propriedadesemtodos.Istocomoum"objetodeaplicativo'(svezesconhecidocomoum'god'
objeto)geralmentecriado.Claro,seoobjetocriadonoprogramadeinicializaodo
aplicao,nohnecessidadededeclararexpressamentearefernciacomo"pblico",desdequenoseja
declaradoexplicitamentecomo'Local'.Qualquervarivelprivadacriadonoprogramadeinicializaoeficaz
"Pblico"paraaaplicaodequalquermaneira.
Comaintroduoparaalngua(naverso6.0)doAddPropertymtodo,um
alternativaintriganteparaacriaodeumobjetoglobalfoiaberto.OVisualFoxPro"_Screen"
objetorealmenteumobjetoglobalreadymadeeumavezquetemumAddPropertymtododesua
prpria,podemossimplesmenteadicionarquaisquerpropriedadesquenecessitamglobalmentediretamenteaoobjetode
segue:
telacomo
_Screen.AddProperty('CCurrentUser','')

Masespere,nsouvilochorar,oqueaconteceu,sevocexecutaroaplicativocomatela
desligado?Naverdade,nofazdiferenaemtudo.O_Screenobjetoaindaestdisponvelmesmose
vocnomostrloevocaindapodeacessarsuaspropriedadesemtodosincluindoqualquerpersonalizado
propriedadesoudosobjetosadicionadosaqualquermomento.

Comoposso'procurar'umarray?(ExemploArToCurs.prg)
UmdosmenoresirritantesVisualFoxProquenohnenhumaboamaneiradeverrealmenteocontedo
deumamatriz.Existem,naturalmente,vriasmaneirasdechegaraumamatriz.Vocpodeusarodepurador
paraexpandireaprofundaratravsdeumconjuntoouvocpodelistloparaatela,ouparaumarquivodetexto,mas
elessointeiramentesatisfatrios.Afinaldecontas,nspodemoscriarumamatrizdeumcursorusandoSQLpor
nenhum
simplesmenteemitirumcomandocomoeste:

Seleccione<campos>from<table>INTOARRAY<name>

446 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Oquenopodemosfazerocontrriotransformarumamatrizdevoltaparaumcursorparaquepossamos
procurloouexibiloemumformulrioouqualqueroutracoisaquepodeprecisarnomomento.osArToCurs
funofazotrabalhoparans,tendoumarefernciaaumamatrize,opcionalmente,umnomedecursor,
econstruodeumcursorapartirdocontedodamatriz.
Humaadvertnciaparaocdigo,talcomoapresentadoaqui.Estafunonoirlidarcommatrizes
contendorefernciasaobjetos.Noseriadifcilalterarocdigoparaqueelefez(talvez
obtendoonomedoobjeto),masestafunonofoiconcebidaparaoefeito,porisso
noestescritodessaforma.Ovalorderetornoonmerodelinhasnocursorquefoicriado.
Aquiestocdigo:

**********************************************************************
*Programa :ArToCurs.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:aceitaumamatrizeconverteloemumcursor
**********************************************************************
LPARAMETERStaSceArray,tcCursorName
ArraylocallaStru[1]
lnRowslocal,lnCols,lnCnt,lcColNum,lnColSize,lcInstr
ARRAYEXTERNALtaSceArray

***Verifiquequetemosumamatrizcomoumparmetro
***NBNopossvelusarVarType()aquinamatrizcasonoexiste!
IFTYPE("taSceArray[1]")="U"
ASSERT.F.MENSAGEM"devepassarporumamatrizvlidaparaArToCurs()"
RETORNA
FIMSE

***PadroCursornomepara"arraycur"senadapassado
lcCursor=IIF(VARTYPE(tcCursorName)="C"EVAZIO(tcCursorName),!
ALLTRIM(LOWER(tcCursorName)),"arraycur")

***Determinarotamanhodamatriz
lnRows=ALEN(taSceArray,1)
lnCols=MAX(ALEN(taSceArray,2),1)
DIMENSOlaStru(lnCols,4)

***Criaramatrizdeestrutura
lcInstr=""
PARAlnCnt=1alnCols
***Colunasnomecomonmerodedadostipode+Zeroalmofadada
lcColNum=PADL(lnCnt,5,"0")
laStru[lnCnt,1]=VARTYPE(taSceArray[1,lnCnt])+lcColNum
laStru[lnCnt,2]="C" &&Tipodedados
***Determinaralarguramximadacolunanecessria
lnColSize=1
PARAlnRowCnt=1alnRows
lnColSize=MAX(lnColSize,LEN(TRANSFORM(taSceArray[lnRowCnt,lnCnt])))
PRXIMO
laStru[lnCnt,3]=lnColSize &&ColLargura
laStru[lnCnt,4]=0 &&Semdecimais
***AdicioneocampoparaaInserodeCordas
ESE!VAZIO(lcInstr)
lcInStr=lcInstr+","
FIMSE
IFlnCols>1
lcInStr=lcInstr+"TRANSFORM(taSceArray[lnCnt,"+ALLTRIM(STR(lnCnt))+"])"

Captulo13:coisasdiversas 447

OUTRO
lcInStr=lcInstr+"TRANSFORM(taSceArray[lnCnt"+"])"
FIMSE
PRXIMO

***Criarocursordamatrizdeestrutura
CRIARCURSOR(lcCursor)FROMARRAYlaStru

***Preencherocursor
PARAlnCnt=1alnRows
INSERTINTO(lcCursor)VALUES(&lcInStr)
PRXIMO
GOTOPIN(lcCursor)

***RetornoNmeroderegistros
RETURNRECCOUNT(lcCursor)

ChamadasAPIdoWindows
Humaenormequantidadedeesteseelesso,infelizmente,nobemdocumentadaparaVisualFoxPro
usurios.AquiestoalgumasfunesdoVisualFoxProqueusamchamadasdeAPIquetemosencontradotil.
Emboraapresentadoaquicomofunesindependentes,normalmenteseriarecolherestetipode
funesemumarquivodeprocedimento,oucomomtodosdeumaclasse.AvantagemdeusarumVisual
classe(porexemplo,um"costume"classe)que,quandosonecessriasestasfunes,umobjetocombasenaclasse
podesersimplesmenteadicionadodirectamenteparaoformulrioquenecessitedela.
UmdosmaioresproblemasparaamaioriadosdesenvolvedoresdoVisualFoxProquandocomearatrabalhar
comoWindowsAPIqueasfunesdependemfortementedeconstantesdefinidas.Masno
semprefcildeterminarondeestasconstantesnaverdadevem,ouatmesmooqueelesso.
GaryDeWitttemrecolhido,emuitogenerosamentedisponibilizadosatodos,aolongode4000
ConstantesdoWindowscomoVisualFoxPro" #definedeclaraes".Umacpiadeseuarquivo("windows.h")
includocomocdigodeexemploparaestecaptulo.

Comofaoparaencontraroarquivoassociadoaumtipodearquivo?(Exemplo:
Estafunopoucotilporquelhedizondeoarquivoexecutvelassociadoaum
findexec.prg)
extensodeterminadoarquivoestlocalizado.Paraqualquerextensodearquivoquetemumaassociaoespecficado
ovalorderetornoconsisteemocaminhocompletoeonomedoarquivoparaoprogramaexecutvel.Istopodeento
Windows,
sermanipuladosusandoasfunesnativasdoVisualFoxPro( JUSTPATH(),JUSTFNAME(),etc.)para
extrairqualquerinformaoquevocrealmenteprecisa.
NotequeafunoAPIqueestamosusandoaqui(FindExecutable())podeaceitarumaespecfica
caminhoenomedoarquivo,masoarquivodeveexistir.Assim,paraserabsolutamentecerto,optouseporcriar
umarquivotemporrio,comaextensonecessria,nodiretriodetrabalhoatualeusaressearquivo
paradeterminaroresultado.Noentanto,istosignificaquequalquerpassagemdoexecutveldoWindows
extenses(ouseja,' COM',' MTD'ou' EXE'),quenoestoassociadosaaplicaesespecficas,avontade
simplesmenteretornaralocalizaodoarquivotemporrio.Istonoumproblema,umavezqueoconjunto
objetivodafunodeterminarondeoprogramaexecutvelqueexecutaumno
tipodearquivoexecutvelestlocalizado:

**********************************************************************
*Programa :FindExec.prg
448 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Retornaocaminhoeonomecompletodoexejanelas
* :Oqueestassociadocomafunoespecificada
**********************************************************************
LPARAMETERStcExt
LOCALlcRetVal,lcFileExt,lcFileName,lnFileHandle,lcDirectory,lcResBuff
STORE""paralcRetVal,lcFileExt,lcFileName,lcDirectory
***Verifiquequeumaextensopassado
IFVARTYPE(tcExt)#"C"ouvazio(tcExt)
ERROR"9000:DevepassarporumaextensodearquivoparaFindExec()"
RETURNlcRetVal
OUTRO
lcFileExt=UPPER(ALLTRIM(tcExt))
FIMSE

***Estafunodeveterumarquivodotiporequisite
***Ento,crieumaqui(apenastemporria)!
lcFileName="MANEQUIM."+lcFileExt
lnFileHandle=FCREATE(lcFileName)
IFlnFileHandle<1
***Noconseguecriararquivo
ERROR".9000:NopossvelcriararquivoFindExec()deveparar"
+CHR(13)+"Verifiquesevoctemosdireitosnecessriosparaacriaodoarquivo"
RETURNlcRetVal
FIMSE
FCLOSE(lnFileHandle)

***CriarobuffervalorderetornoedeclararafunoAPI
lcResBuff=ESPAO(128)
DECLAREINTEGERFindExecutableINSHELL32
STRING@cFileName,
STRING@cDirectory,
STRING@cBuffer

***Agorachamlocomnomedearquivoediretrio
lnRetVal=FindExecutable(@lcFileName,@lcDirectory,@lcResBuff)

***Verifiqueovalorderetorno
lcMsgTxt=""
DOCASO
CASElnRetVal=0
lcMsgTxt="Outofmemriaourecursos"
CASElnRetVal=2
lcMsgTxt="fileespecificadonofoiencontrado"
CASElnRetVal=3
lcMsgTxt="caminhoespecificadonofoiencontrado"
CASElnRetVal=11
lcMsgTxt="formatoEXEinvlido"
CASElnRetVal=31
lcMsgTxt="Nenhumaassociaodetipodearquivo"+lcFileExt
DEOUTRAFORMA
***Temosalgodevolta
***Stringterminadacomnulonobufferresultadoat:
lcRetVal=LEFT(lcResBuff,AT(CHR(0),lcResBuff)1)
ENDCASE

***Excluiroarquivofictcioquecriamos.
DELETEFILE(lcFileName)

Captulo13:coisasdiversas 449

***Osresultadosvisorevoltar
ESE!VAZIO(lcMsgTxt)
MESSAGEBOX(lcMsgTxt,16,"FindExecFalha")
FIMSE
RETURNlcRetVal

ComopossoabrirumarquivousandoassociaesdearquivodoWindows?(Exemplo:
runfile.prg)
IstoextremamentesimplesusandooShellExecute()funo.Estafuno,querabrirou
imprimeoarquivoespecificado(quepodeserumarquivoexecutvelouumdocumento).Aquiesto
cdigo:

**********************************************************************
*Programa :RunFile.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:abrirouimprimirumarquivo/documentochamadousandoassociaojanelas
**********************************************************************
LPARAMETERStcDocName,tlPrint
LOCALlnRetVal,lnShow,lcAction
***VerifiqueParmetros
IFVARTYPE(tcDocName)#"C"ouvazio(tcDocName)
WAITwindow"devepassarporumnomededocumentovlidoeextenso"NOWAIT
RETORNA
FIMSE
***Deveterumaextensomuito
IFEMPTY(JUSTEXT(tcDocName))
WAITwindow"devepassarporumnomededocumentovlidoeextenso"NOWAIT
RETORNA
FIMSE

***Verifiqueao,setlPrint=.T.,"Imprimir"deoutraforma"Open"
lcAction=IIF(tlPrint,"Imprimir","Open")
lnShow =IIF(tlPrint,0,5)

***FunoDeclareAPI
DECLAREINTEGERShellExecuteINShell32.dll
LONGOHWnd,
STRINGcAction,
STRINGcFileName,
cParameterscorda,
STRINGcPath,
INTEIROnShowWindow

***Agoraexecutlo
lnRetValShellExecute=(0,lcAction,tcDocName,"","",lnShow)

RETORNA

Notesequetemosumconjuntoestafunoparaaceitarumcaminhocompletoeonomedoarquivocomoum
parmetronico.Naverdade,vocpoderiausloigualmentebemdividindooparmetroemnomedoarquivo
ecaminhoepasslasseparadamente,comooscFileNameecPathparmetros.

450 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OnShowWindowvalordefinidocomo5(ouseja,'Mostrar'oaplicativo)aoabrirum
documentoea0(ocultaroaplicativo)aoimprimirumdocumento.(Agamacompletadevalores
podeserencontradanaWinUser.harquivosobo"ShowWindow()Comandos"dettulo.)

ComopossoobteroWindowsdousuriologinnome?(Exemplo:getlogin.prg)
HrealmenteumamaneirapuramenteVFPdeobteressasinformaesusandooSYS(0)funo
queretornaonomedamquinaeusurioatualloginnome.Ovalorderetornoumnico
cordaeusaosmbolo"#"parasepararonomedamquinaapartirdonomedeusurio.Assim,uma
possvelsoluousar:

lcCurrentUser=ALLTRIM(SUBSTR(SYS(0),AT('#',SYS(0))+1))

Noentanto,htambmumaGetUserName()afunoqueirretornarasmesmasinformaes
equepodeserenroladacomoumafunodefinidasimples,outilizadordaseguinteforma:

****************************************************
*Programa :GetLogIn.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:ObternomedoWindowsLogIn
****************************************************
lcUserNameLOCAL,lcRetVal

***FunoDeclareAPI
DECLAREGetUserNameINWin32API
STRING@cString,
INTEIRO@nBuffer

***Inicializarosbuffers
lcUserName=ESPAO(50)

***Obteronomedelogin
GetUserName(@lcUserName,LEN(lcUserName))

***Stringterminadacomnulonobufferresultadoat:
lcRetVal=LEFT(lcUserName,AT(CHR(0),lcUserName)1)

***RetornoIDdelogin
RETURNlcRetVal
Comopossoobterinformaesdedirectrio?(Exemplo:windir.prg)
AAPIdoWindowscontmdiversasfunesquepodemserusadasparaobterinformaesdedirectrio.
AlgunstambmestodisponveisapartirdoVisualFoxPro(porexemplo,mudarodiretrioatual)
enquantooutrosnoso(porexemplo,encontrandoosdoWindowsoudosistemadiretrios).Oseguinteprograma
recolhevriasdessasfunesjuntoeusaumndicenumricoparadeterminaraao
requeridacomosegue:

Captulo13:coisasdiversas 451

Tabela13.4funesdediretrioAPI

ndice Aao
1 RetornaocaminhocompletoparaodiretriodosistemaWindows.
2 RetornaocaminhocompletoparaodiretrioinicialdoWindows.
3 Retornaocaminhocompletoparaodiretriodetrabalhoatual.(Equivalentea"CD"noVisualFoxPro).
4 Aceitaparmetroadicionalqueumcaminhorelativoouumcaminhototalmentequalificado,e
fazqueodiretriodetrabalhoatual.Retornaodiretrioatualtotalmentequalificadoou
umamensagemdeerroseodiretrioespecificadonoexiste.
5 Aceitaparmetroadicionalqueumcaminhorelativoouumcaminhototalmentequalificado,e
criaodiretrio.Retornaou"Criado"ou"Falha".
6 Aceitaparmetroadicionalqueumcaminhorelativoouumcaminhototalmentequalificado,e
excluiodiretrio.Retornaou'removido'ou'Falha'.

ValeapenanotarqueestasfunesirlidarcomqualquerUNCouunidadeconvencional
identificadorescomigualfacilidadequepodemtornlosteisemalgumassituaes.Aquiestocdigo:

**********************************************************************
*Programa :WinDir.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:FunesDiretrioAPIdoWindows
* :ChamadaOpes
* :1 >ListaderetornodosistemaWindows
* :2 >ListadeRetornodoWindows
* :3 >Retornodiretriodetrabalhoatual
* :4,<caminho>>DefinirDiretriodetrabalho(Aceitacaminhorelativo)
* :5,<caminho>>Criardiretriochamado(Aceitacaminhorelativo)
* :6,<caminho>>Removerdiretriochamado(Aceitacaminhorelativo)
**********************************************************************
LPARAMETERStnWhich,tcDirName
lcSysDirLOCAL,lnBuffer,lnDirLen,lcRetVal
***Inicializarosbuffers
lcSysDir=REPLICATE(CHR(0),255)
lnBuffer=255
***Executarchamadaapropriada
faaCASE
CASEtnWhich=1
***DiretriodosistemaWindows
DECLAREINTEGERGetSystemDirectoryINWin32API
STRING@cBuffer,
INTEIROnSize
***Chameafuno
lnDirLen=GetSystemDirectory(@lcSysDir,lnBuffer)
lcRetVal=LEFT(lcSysDir,lnDirLen)

CASEtnWhich=2
***DiretriodosistemaWindows
DECLAREINTEGERGetWindowsDirectoryINWin32API
STRING@cBuffer,
INTEIROnSize
***Chameafuno
lnDirLen=GetWindowsDirectory(@lcSysDir,lnBuffer)
lcRetVal=LEFT(lcSysDir,lnDirLen)
452 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

CASEtnWhich=3
***Diretriodetrabalhoatual
DECLAREINTEGERGetCurrentDirectoryINWin32API
INTEIROnSize,
STRING@cBuffer
***Chameafuno
lnDirLen=GetCurrentDirectory(lnBuffer,@lcSysDir)
lcRetVal=LEFT(lcSysDir,lnDirLen)

CASEtnWhich=4
***SetDefaultDirectory
DECLAREINTEGERSetCurrentDirectoryINWIN32API
STRINGcNewDir
***Chameafuno,onomevoltarseOK,stringvaziaseno
lcRetVal=IIF(SetCurrentDirectory(tcDirName)=1,tcDirName,
"Diretrionoexiste")

CASEtnWhich=5
***CriarDiretrio
DECLAREINTEGERCreateDirectoryINWIN32API
STRINGcNewDir,
STRINGcAttrib
***Chameafuno
lnSuccess=CreateDirectory(tcDirName,"")
lcRetVal=IIF(lnSuccess=1,"Criado","Falha")

CASEtnWhich=6
***RemoveDirectory
DECLAREINTEGERRemoveDirectoryINWIN32API
STRINGcKillDir
***Chameafuno
lnSuccess=RemoveDirectory(tcDirName)
lcRetVal=IIF(lnSuccess=1,"removido","Falha")

DEOUTRAFORMA
***UnknownParmetro
lcRetVal=""
ENDCASE
***Retornoalocalizaododiretrio
RETURNlcRetVal

Notesequeaopo"removerodiretrio"sfuncionarseodiretriodedestinoestvaziode
todososarquivos.

Comopossoobteronmerodecoresdisponveis?(Exemplo:wincols.prg)
Onmerodecorespodesercalculadoapartirdonmerodebitsdecoresquesoalocadospara
cadapixel.Esteum(demuitos)valoresquepodemserobtidosusandoosGetDeviceCaps()
funo.Noentanto,afimdedeterminarondearecuperaroseuvalor,estafunodeveestar
passouaidentificaodecontexto(queobtidoapartirdaGetDC()funo)paraobteroqueprecisamosdo
Windows"WHnd"pega.EstapodeserobtidaquerusandoabibliotecaFoxToolscomoeste:
SETLIBRARYTOFoxtools.fllADITIVO

Captulo13:coisasdiversas 453

lnHWND=_WHTOHWND(_WMainWind())

ou,comoaqui,afunoAPIGetActiveWindow()podeserutilizadaparadevolverapegaparaa
janelaprincipaldoFoxPro:

**********************************************************************
*Programa :WinCols.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Retornaonmerodecoresdisponveis
**********************************************************************
lnHWNDLOCAL,lnBitsPixel,lnDeviceContext

***FunesDeclareAPI
DECLAREINTEGERGetActiveWindowINWIN32API

DECLAREINTEGERGetDCINWin32API
INTEIROnWHnd

DECLAREINTEGERGetDeviceCapsEMWin32API
INTEIROnDeviceContext,
INTEIROnValueToGet

***ObteroidentificadordoWindowsparaajanelaativa
lnHWNDGetActiveWindow=()

***Primeiroobtenhaocontextodispositivoparaajanelaatual
lnDeviceContext=GetDC(lnHWND)

***Emseguida,obteronmerodebitsdecorporpixel
lnBitsPixel=GetDeviceCaps(lnDeviceContext,12)

***Resultadoderetorno
RETURN(2^lnBitsPixel)

ComofaoparaobterosvaloresparaasconfiguraesdecoresdoWindows?
getwcol.prg)
(Exemplo:
Existemduaspartesenvolvidasnesteprocesso.Firsprecisamospararecuperaraconfiguraodecorparao
requeridaitemdeWindowsapartirdoprprioWindows.(ExisteumafunoAPIquevaifazerisso.)Emseguida,
queconverteressevalorparaoscomponentesvermelhos,verdeseazuisquepodemosusardentrodoVisual
FoxPro.(Embora,setudoquevocestfazendodefinirumapropriedadedecor,emseguida,VisualFoxPropodeusar
WindowsCorNmerodiretaeaconversononecessrio)Aquiafuno.:

**********************************************************************
*Programa :GetWCol.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:RetornaoVermelho,Verde,evaloresdecorazulparaum
* :DadonumeradoobjetoWindowscor
**********************************************************************
LPARAMETERStnObjectNumber
***VerifiqueParmetro
IFVARTYPE(tnObjectNumber)#"N"OR!ENTRE(tnObjectNumber,0,28)
WAITwindow"Devepassarjanelasnmerodecoresentre0e28"NOWAIT
RETORNA

454 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

FIMSE

***Obteradefiniodecorexigida
DECLAREINTEGERGetSysColorINWin32API
INTEIRONObject
lnWinCol=GetSysColor(tnObjectNumber)

***ConverterparavaloresRGB
lnSq256=256^2
lnRedGrn=MOD(lnWinCol,lnSq256)

***Agoraobteroscomponentesindividuais
lcBlue =TRANSFORM(INT(lnWinCol/lnSq256))
lcGreen =TRANSFORM(INT(lnRedGrn/256))
lcRed =TRANSFORM(MOD(lnRedGrn,256))

***SeqnciaderetornoRGB
RETURN(lcRed+","+lcGreen+","+lcBlue)

EstafunoexigeumaconstantenumricaqueidentificaumelementodoWindows.Estessotodos
definidono"Windows.harquivo"includocomocdigodeexemploparaestecaptulo,masalgunsdos
osprincipaisestolistadosaquiporconvenincia.

Tabela13.5ConstantesparacoresdoelementodoWindows

Constante Janelaselementodecor
1 Background(WindowsDesktop)
2 TtuloBar(Janelaactiva)
3 TtuloBar(janelainativa)
5 Backgroundjanela
9 Ttulobarradelegendadetexto(Janelaactiva)
19 Ttulobarradelegendadetexto(janelainativa)
13 Backgrounditemrealado
14 DestaqueItemdeTexto
17 Botodecomando
18 BotodecomandoTexto

Comofaoparamudarocursor?(Exemplo:ChgCursor.prg)
VocpodefacilmentepersonalizarseuscursoresusandoaAPIdoWindows.Porexemplo,vocpodesubstituir
aampulhetaestticapadrocomumaampulhetaanimadaquegira,apenasaemissodopresente
chamadadefuno:

ChgCursor(FULLPATH('HourGlas.ani'),32514)

NotequeoChgCursor()funotemdoisparmetros.Oprimeiroonomedearquivoque
serusadoparaocursordenoexemploacima,istoumpadrodeWindowsdo"animado"
cursorarquivos.Osegundoparmetroumaconstantequedefinequetipodecursor(ouseja,Ibeam,
mo,ampulheta)sersubstitudopelonovoarquivo.Estasconstantespodemserencontradasem
Windows.heumalistadelestambmestincludonoprprioChgCursor.prg.

Captulo13:coisasdiversas 455

UmbomusoparaestafunoparaalterarocursoremformadeIpadroparaumasetaquando
vocquiserusarumagradequeousomenteleitura,ouseparececomumacaixadelistagem,usandoumanicalinhade
cdigo(emoposiometodologiaquedescrevemosanteriormentenestecaptulo):

ChgCursor(FULLPATH('Arrow_m.cur'),
32513)

Estejacientedequesevocfizerisso,tudodoseucursoremformadeIsersubstitudopelaseta.este
incluitodasascaixasdetextoquepodesernoformulrioparasecertificardequeamudanasseaplica
quandoomouseestsobreagrade.Aquiestoprogramaqueusamosparamudarocursor:

**********************************************************************
*Programa :ChgCursor.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Mudaocursorespecificadoparao.curespecificadoouarquivo.ani
**********************************************************************
LPARAMETERStcCursorFile,tnCursorType
lcNewCursorLOCAL

ASSERTVARTYPE(tcCursorFile)='C'
MENSAGEM"devepassarporumNomedoarquivoparaChgCursor.Prg'
ASSERTVARTYPE(tnCursorType)='N'
MENSAGEM"devepassarporumtiponumricoCursorparaChgCursor.Prg'

IFINLIST(JUSTEXT(tcCursorFile),'CUR","ANI")
Seoarquivo(tcCursorFile)
DECLAREINTEGERLoadCursorFromFileemWin32APICordas
DECLARESetSystemCursoremWin32APIInteger,Integer

lcNewCursor=LoadCursorFromFile(tcCursorFile)
SetSystemCursor(lcNewCursor,tnCursorType)
FIMSE
FIMSE

Comopossopersonalizarmeusbips?(Exemplo:MsgBeep.Prg)
SevocolharparaossonsdosistemanopaineldecontroledoWindows,vocvainotarquediferente
sonssodefinidosparadiferentestiposdeeventos.umaquestomuitosimplesdeusaressasconfiguraes
parareproduzirsonsquesoconsistentescomoutroaplicativodoWindowsquandovocexibirumamensagem
caixaemVisualFoxPro.aindamaisconveniente,porqueos MESSAGEBOXconstantesconeso
idnticosaosutilizadosparaidentificarossonsassociadosnoWindowsAPI.Parareproduziro
somassociadoaparadacrticaconfigurarnopaineldecontroledoWindows,tudoquevocprecisafazer
esta:

MsgBeep(16)

OprogramausadoparaembrulharestafunoAPIrealmentemuitosimples:

**********************************************************************
*Programa :MsgBeep.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Jogueosomdosistemaespecificadocomoumbip
456 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

* NotesequeasconstantesbipcorrespondeaoconeMESSAGEBOX
constantes
**********************************************************************
LPARAMETERStnBeep

DECLAREINTEGERMessageBeepINWin32APIINTEIRO
MessageBeep(tnBeep)

Comofaoparadescobrirseumaaplicaoespecficaestfuncionando?(Exemplo:
IsRunning.prg)
ComovoclidacomajanelaAPIAjuda,vocpodecorrerparao FindWindowfunoe
achoquevocpodeusarissoparadescobrirseumdeterminadoaplicativoestsendoexecutado.Infelizmente,este
funorequerquevocsaibaalegendaexatoexibidonabarradettulodajaneladoaplicativo.
svezes,issoimpossvel.Porexemplo,quandoumdocumentoestsendoeditadonoMicrosoft
Word,legendadajaneladoWordcontmonomedodocumentoqueestsendoeditado.Porqueisso
emgeral,nopossvelparaaaplicaodoVisualFoxProparasaberessesdetalhes,nopodemos
usaroFindWindow()funoparadeterminarseoWordestsendoexecutado.Pararesolveresteproblema,
nossaIsRunning()funofazusodaAPIdoWindows GetWindowTextfuno.
IsRunning()umafunosobrecarregada.Sechamadosemparmetros,eleretornaumparmetro
objetoquecontmumapropriedadedematriz.Estamatrizcontmosnomesdetodoocorredor
aplicaes.Seumaseqnciaparcial,como"MicrosoftWord'passado,eleretornaumaverdadeiralgica,seo
aplicativoestsendoexecutado.Sevocquisesseexpandirsuafuncionalidade,vocpodemodificlopara
retornarumamatrizbidimensionalepreencherasegundacolunadamatrizcomo
identificadordejaneladoaplicativo:
**********************************************************************
*Programa :IsRunning.prg
*Compiler...:VisualFoxPro06.00.8492.00paraWindows
*Resumo...:Quandopassadoumastring(ouseja,'MicrosoftWord'),retornar.T.
* :Seoaplicativoestsendoexecutado.Quandoinvocadosemparmetros,
* :Retornaumobjetodeparmetrocujamatrizlistatodosexecuo
* :aplicaes
*************************************************************************
IsRunningFUNO
LPARAMETERSluApplication

LOCALluRetVal,lnFoxHwnd,lnWindow,lnWhich,lcText,
lnLen,laApps[1],lnAppCnt

***DeclararfunesdaAPIdoWindowsnecessrias

DECLAREINTEGERGetActiveWindowINWin32API

DECLAREINTEGERGetWindowINWin32API
INTEIROlnWindow,
INTEIROlnWhich

DECLAREINTEGERGetWindowTextINWin32API
INTEIROlnWindow,
CORDA @lcText,
INTEIROlnLen

Captulo13:coisasdiversas 457

DECLAREINTEGERIsWindowVisibleINWin32API
INTEIROlnWindow
lnAppCnt=0

***ObteroHWND(identificador)paraajanelaprincipalFoxPro
lnFoxHwndGetActiveWindow=()
IFlnFoxHwnd=0
MESSAGEBOX("valorderetornoinvlidadoGetActiveWindow',16,'errofatal')
RETORNA
FIMSE

***Percorrertodososaplicativosemexecuo
lnWindow=GetWindow(lnFoxHwnd,0)
FazerenquantolnWindow#0

***CertifiquesedequenotemosajanelaVisualFoxPro
IFlnWindow#lnFoxHwnd
IFGetWindow(lnWindow,4)=0eIsWindowVisible(lnWindow)#0
lcText=ESPAO(254)
lnLen =GetWindowText(lnWindow,@lcText,LEN(lcText))

***Seafunofoipassadoumnomedeaplicativo,verifiquesehumacorrespondncia
***Casocontrrio,Adicionaresteparaamatriz
IFlnLen>0
IFVARTYPE(luApplication)='L'
lnAppCnt=+1lnAppCnt
DIMENSOlaApps[lnAppCnt]
laApps[lnAppCnt]=LEFT(lcText,lnLen)
OUTRO
IFUPPER(ALLTRIM(luApplication)) $UPPER(ALLTRIM(lcText))
RETURN.T.
FIMSE
FIMSE
FIMSE
FIMSE
FIMSE

***Vejasehumoutroaplicativoemexecuo
lnWindow=GetWindow(lnWindow,2)
ENDDO

***Ounsnoencontramosumacorrespondnciaparaonomedoaplicativopassado
***Ouestamosretornandoumarraydetodososaplicativosemexecuo
IFVARTYPE(luApplication)='L'
SETCLASSLIBTOCH13ADITIVO
luRetVal=CREATEOBJECT('xParameters',@laApps)
OUTRO
luRetVal=.F.
FIMSE

RETURNluRetVal

ParaverIsRunning()emao,bastadigitar DODemoIsRunningnajaneladecomando(depois
vocbaixouedescompactouocdigodeexemplo,claro!)paraverumcursorquelista
todososaplicativosemexecuo.

458 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

UsandoocomandoDECLARE
VocvaiterpercebidoapartirdasseesanterioresqueachaveparaacessaraAPIdoWindows
oVisualFoxPro DECLAREcomando.Estecomandoregistaumafuno,queestdefinidano
umWindowsdinmicoligadobiblioteca(.DLLarquivos)etornadisponvelparaVisualFoxProcomose
naverdade,eramumafunonativa.VocpodepensaremDLLscomooequivalentedoWindowsdo
familiaresarquivosprocedimentodoVisualFoxPro,mas,aocontrriodeumarquivodeprocedimento,asfunescontidas
DLLdeveserregistradoindividualmenteantesqueelespossamseracessados.
emum
AsintaxebsicaeutilizaodeDECLAREexplicadorazoavelmenteclaramentenalinha
Arquivosdeajuda,eaindamaisclaramenteno"GuiadoHackerparaoVisualFoxPro6.0,"mashuma
algunspontosquevalemapenaenfatizarquandosetrabalhacomfunesAPI:

Onomedafunorealmentemaisculasdeminsculas!EstemaisincomumnoVisualFoxPro
e,portanto,valeapenamencionaraqui.Sevocreceberumerroqueafirma:"Nopossvelencontrar
pontodeentrada...".,emseguida,quasecertamentevoctemocasoparaonomedafunoerrado..
Nosocasonomedafunosensvel,masemalgunscasosafunoreal
nomepodenoseromesmoqueoqueindicado.(Issoocorreporquepodehaver
diferentesfunesparadiferentesconjuntosdecaracteres.Assim,aAPI"MessageBoxfuno"
naverdade,duasfunes"MessageBoxA",quetrabalhacomconjuntosdecaracteresdebytenico
e"MessageBoxW"paraconjuntosdecaracteresUnicode.Noentanto,vocnormalmentenoprecisa
sepreocuparcomisso,pois,seoVisualFoxPronoconsegueencontrarafunoespecificada,ser
anexarum"A"etentenovamente.)
Nohnenhumarquivocomo"WIN32API.DLL"apesardofatodequemuitasvezesvocvaiver
funessendodeclaradonestabiblioteca.realmenteum'atalho'queinstruiVisual
FoxProparaprocurarumalistaprdefinidadearquivos,incluindo:Kernel32.dll,Gdi32.dll,
User32.dll,MPR.dlleAdvapi32.dll.
Quandodeclararumafuno,vocpodeespecificarumaliaslocalparaessafunoatravsdaincluso
o'AS'palavrachavenadeclarao.Istopodesertil,poisenquantoareal
nomedafunosensvelamaisculas,oaliaslocal(sendoconhecidaapenasparaVisualFoxPro)
no.

Comofaoparav erificaroquefunesdeAPIsocarregados?
Onativo Visualdoestadorelatrioinclui,nofinal,umalistadetodososarquivosDLLdeclarada
funesjuntamentecomoarquivorealemqueafunoestlocalizado,comoilustrado:

DLLsdeclarou:
GetActiveWindowC:\WINDOWS\SYSTEM\USER32.DLL
GetSystemDirectoryC:\WINDOWS\SYSTEM\KERNEL32.DLL
GetWindow C:\WINDOWS\SYSTEM\USER32.DLL
GetWindowText C:\WINDOWS\SYSTEM\USER32.DLL
IsWindowVisible C:\WINDOWS\SYSTEM\USER32.DLL

Captulo13:coisasdiversas 459

ComofaoparaliberarumafunoAPI?
Infelizmente,nohnenhumamaneiradeliberarumanicafunoAPI,umavezquefoideclarado.
EmissoquerumCLEARDLLSouLIMPARTUDOvailiberartodasasfunesdeclaradas,masneste
caso,pelomenos,realmente"tudoounada!"
460 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Captulo14:GerenciamentodeProjetos 461

Captulo14
GerenciamentodeProjetos
"Depoisdeumaolhadanesteplanetaqualquervisitantedoespaodiria"EUQUEROVER
OGERENTE.'"("AMquinadeadio",deWilliamBurroughs)

desenvolvedoresFoxProtmvindoautilizaroGestordeProjectoparagerenciararquivosdesdeo
introduodeFoxPro2.0.Estecaptuloirdiscutiralgunstruquesgerentedeprojeto
VisualFoxPro.

OGerentedeProjetotemsidoumaimportanteferramentaparadesenvolvedoresdoVisualFoxProaolongodosanos.
permitequeosdesenvolvedoresparaorganizartodososarquivosqueestoincludosparaumaaplicao.Eleforneceuma
isto
fcilmecanismoparamodificarqualquerumdessesarquivosecompilartodoocdigofonteincludono
projeto,bemcomoAPPconstruirarquivos,EXEseDLLs.OlanamentodoVisualFoxPro6.0Servio
Pack3tambmpermiteaosdesenvolvedorescriarobjetosCOMmultithreaded.
OGerentedeProjetoainterfaceVFPparaoarquivodemetadadosdoprojeto.Oprojeto
arquivodemetadadosumVFPmesalivrequeterminacomaextensoPJXeumarquivodememorandoquetemo
extensodeprojeco.Essesarquivoscombinarinformaessobrecadaarquivoquecontroladonoprojeto.
Osarquivosdemetadadosdoprojetocontmumregistroporarquivoeumponteiroderefernciaparacadaarquivo.
Informaescomoonmerodaverso,nomedoautoreendereo,seocdigofonte
includonoexecutvelpormotivosdedepurao,eseoexecutvelcriptografadotambm
rastreadonoarquivodeprojeto.

Oqueacontecequandoaconstruodeumexecutvel?
Aconstruodeumprojetoenvolvemuitasetapas.Primeiro,todososarquivosreferenciadosnocdigoso
Verificousenoprojecto.Seelesnoestonoprojeto,oprocessodeconstruoprocuralosparafora
emtodasaslistasjreferenciadosnoprojeto(viaarquivosjnoprojeto)eadiciona
eles.Seelesnoforemencontrados,odesenvolvedorsolicitadoalocalizlosmanualmente.Cadaarquivo
compiladoseafontefoiatualizadodesdealtimacompilao,procedimentosarmazenadososbancosdedados'
socompiladasecdigodomenugeradoecompilado.Orestodoprocessodepende
aescolhadotipodecompilaoselecionada.

ExistemvriasopesdeconstruodisponvelnoVisualFoxPro6.0,Servio
Pack3(amaisrecenteatualizaodaMicrosoftcomodaescritadestelivro).
NotamosaversodoVFPdesdeServicePack3introduzidoomaisnovo
construiropo,oDLLmultithreadedservidorCOM.Acaixadedilogocompilaofoialterada
refletiressanovaopoeesclarecerexatamenteoqueasoutrasopesdecompilaoso
para
usados.
AopodecompilaoreconstruirprojetodizVFPparapercorrerodescritoanteriormente
processo.Nohnenhumaoutraaorealizada.Estadelongeamaisrpidadasopesdecompilao.
Aopodecompilaodoaplicativoexecutaasaesquesofeitasparaumareconstruo,eemseguida
mesclatodososarquivosdeorigemmarcadosparainclusoemumestilodeaplicao(.APP)doexecutvel
Arquivo.EsteumarquivoexecutvelcompletonoVisualFoxPro,masrequerVisualFoxProparaser

462 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

executadosdiretamente.ElepodeserchamadodeumoutroexecutvelVFPquejestemexecuodentro
oambientedetempodeexecuo.
OservidorWin32executvel/COM(.exe)construiropoexecutatodasasaesqueso
feitoparaoexecutveldoaplicativo.Emseguida,oarquivoapppassaporumprocessometamrficoque
acrescentaocdigodeinicializaonecessrioparatornloumexecutveldoWindowsquechamaotempodeexecuo
arquivosDLL,acrescentaoconeeasinformaesdaverso.exe.Oexecutvelgeradovontade
necessrio
exigirqueosarquivosdetempodeexecuoVFP(Vfp6r.dlleVfp6rXXX.dll(XXXdenotaoespecfico
versodeidioma))paraserexecutadoforadoambientededesenvolvimentoVisualFoxPro.UmarquivoTypeLibrary
geradoseexistemclassespblicosOLEnoprojeto.
O(.dll)opodecompilaodoservidorCOMsinglethreadedeoservidorCOMmultithreaded
(.dll)OpesdeconstruirobjetosCOMcompletoseosarquivosnecessriostipodebiblioteca(.tlb)depoisdepassar
atravsdoprocessodereconstruo.OarquivoTypeLibrarygeradonomesmodiretrioqueo
DLL.EstesprojectostambmprecisateraulasmarcadascomoOLEPblica.ADLLderoscamulti
requerumarquivoespecialdetempodeexecuochamadoVFP6T.DLL.Todososservidoresquesoconstrudosso
pginadoservidordacaixadedilogoInformaessobreoprojeto.
adicionadosao
Comoutilizarasopesdeprojetoparaasuavantagem
AcaixadedilogoInformaessobreoprojetoapresentadesenvolvedorescomdetalhesimportantessobreoprojetoea
arquivosquefazempartedoprojeto.
AprimeirapginaaguiaProject.Estaformapermitequeodesenvolvedorparaentraremseuendereo
emformao.Estainformaoarmazenadanocdigogeradoparamenus.Foraisso,apenas
documentaoparaoprojeto.Paratrsnosdias2.x,asinformaesdoprojetotambmfoiarmazenadoem
ocdigogeradotela.Maisimportante,estapginadaosdesenvolvedoresacessoaconfiguraesdechave
paraoprocessodecriao.

Comovocusaaconfiguraodeinformaesdedepuraodeum
projeto?
Aconfiguraodeinformaesdedepuraocrticaemduassituaes.Aprimeiraquandodepurarumaplicativo
erastreioatravsdecdigo.Seocdigonofoicompiladocominformaesdedepuraoem(marcada),seguida
vocreceberumamensagem"Fonteestdesatualizado"najaneladerastreamento.Istopodeserverdadeiramenteagravante
quandovocestdeznveisdeprofundidadenapilhadechamadasevocacertarumprogramaquefoicompiladosem
ocdigodedepurao.Nsodeioquandoissoacontece!
importantenotarqueumarquivonocompiladoamenosqueorecompilartudoverificadaquando
fazendoacompilaoouoarquivofoimodificadodesdealtimacompilao.VerificandosenoCdigodedepurao
oponogarantequetodososarquivosterofontecompilado.Onicomomentoquandoo
Reconstruirtudomarcado.Asegundasituaoquecrticoquandovocestconstruindoafinal
versodeenviodopedido.
HumadiferenasignificativanotamanhodoexecutvelentreoCdigodedepuraosendo
ligadoedesligado.Recomendamosverificaressaopoaoconstruirocdigoparaser
fornecidocomorelease.Otamanhopodesermaisde10vezesmaior,comcdigoincludo.Ns
tinhaumcasodeum.exesendo50megabytescomocdigofonteincludoparadepuraoeapenas
maisde4megabytessemele.Enviodecdigocomcdigodedepuraodefinidoemnaviosocdigofonteem
oexecutvel.Istocomoajaneladerastreamentopodeexibircadalinhaqueestsendoexecutado.Observeque
oclienteououtrodesenvolvedorteracessoaestecdigo,seforenviadoparao
Arenaproduo.

Captulo14:GerenciamentodeProjetos 463

Comovocusaaconfiguraocriptografadodeumprojeto?
Istolevanosparaaconfiguraocriptografado.Nobastavocamarcomotudoissofluijuntos?o
configuraocriptografadofazcomqueogeradoexecutvelasercriptografadoparaqueoutrosdesenvolvedoresnopodem
tenhaacessoaocdigofontedentrodoexecutvel.bastanteintilnamentedoautor
umavezqueexistemferramentasdeterceirosqueirdecompileumexecutvel.Naturalmente,estesterceiros
ferramentaspermitemquevocparacarimbarumachaveparaoutracpiadoprodutonopodedecomporlo.Isto
umpoucocomochantageandoloacompraroprodutono?Poroutrolado,aferramentatemalguns
excelenteusoquandoalgumperdeocdigofonteouodesenvolvedororiginalfogedacidadeparaqueele
podevalerapenacomprar.executveiscriptografadostambmnopodesercomprimidoquandofechouozper
combasenoesquemadecriptografiausadointernamente.EsteautoradorariaseaMicrosoftfaria
permitirqueodesenvolvedorafornecerumachaveaocriptografaroexecutvelparacontornardeterceiros
ferramentaserealmentetornloumambientevalioso.
Altimacaixadetextoconstrudaexibeadataehoradaltimacompilaofoiconcludaumtil
lembretedequandovocltimacompiladoaaplicao.AconfiguraoProjectHookabordadoem
Captulo15,objetosdeprojetoeProjectHooks.

Comovocdefinirumconepersonalizadoparaumexecutvel?
Esteumprocessodeduasetapas.Oprimeiroparaatribuiro _screen.Iconpropriedadeparaoarquivodeconeno
oprincipalarranquedoprograma.Asegundausarasinformaesdoprojetodedilogoparaanexaro
coneparaoprojeto.Oqueaconteceduranteacompilaodeprojetocomestecone?Bem,fisicamente
armazenadonoexecutvel.IstodoWindowsacapacidadedeexibirseuaplicativopersonalizado
coneemvezdoconebonitoraposa.Dizemosqueoconebonito,umavezquenaverdade,tivemosumclienteumavez
notequeelesnoqueremquensparasubstituiroFoxhead"cute"comalgumoutroconeparaasua
aplicao<risos>.

Oarquivodecone(.ico)podearmazenarvriascpiasdaimagemdocone.Cada
destasimagensderesoluodiferente.importanteparaeditartanto
imagensdesdeoWindowsusaumaimagemde16x16pixelsparaaplicao
aimagemdepixel32x32paraaexibiodeumavisoampliadaemaplicaesdejanelase
comooWindowsExplorer.

Recomendamoscomoumadasferramentasconedeedioparaquevocpodecriaroseuprprio
conesoumodificarconesquevoccompra.muitoimportanteusarumeditordeconesquepodemeditar
imagensambos.NsusamosoappletMicrosoftImagedit.exefornecidocomVFP5.0.quandoum
coneabertovocestnormalmenteperguntouqualdasimagensquevocdesejaeditar.Vocdeveser
capazdeselecionaraimagempequenocone16coresVGA16imagemEGA/Color(32x32)ou
(16x16).Seumadasimagensestfaltandooarquivodecone,nsfazerum"selecionartudo"sobreaimagem
queexiste,ecopiloparaareadetransferncia.Nsabrimosaoutraimagemnoarquivoconee
colarocontedodareadetransfernciaparaoeditordeimagem.Asegundaimagemouserexpandidoou
encolheram.NsgostamosdaopodeajusteautomticoqueImageEditforneceaoexpandirou
encolhendoogrficoparaseajustaraonovotamanho.
Ousoadequadodeconespodepolonsatumaplicativoedarlheumamaisprofissional
aparncia.Umadasmaneirasmaisfceisdeconstruirumaboacoleodeconesacompra
vriosdeterceirosimagem/conedoCDROMs.HumaabundnciadeconesinteissobreessesCDs,mas

464 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

umbomconefacilmentevaleopreodetodooCDquandovocconsideraquantotempo
vocpodegastarcriandooseuprprio.

ComovocgerenciararquivosnoProjectManager?
AguiaProjetoarquivosdeinformaopermiteclassificaratravsdoListViewquecontmalistade
arquivos.Issosignificaqueosdesenvolvedorespodemclassificaralistadearquivosportipodearquivo,onomedoarquivo,
modificado,sejaincludoeapginadecdigo.Clicandoduasvezessobreos"cabealhos"vontade
ltima
fazercomqueacolunaaserclassificada.Estajanelatambmpermitealternarseoarquivoestincludoou
excludosdaaplicaoouexecutvelconstri.Osficheirosincludosmostramum"X"ea
arquivosexcludosexibirumacaixavazia.Seacaixaestivercinzapreenchido,queindicaoarquivoprincipalparao
projeto.Arquivosquemantmumapginadecdigotambmpodeseratualizadoparaapginadecdigonativo.Isto
importanteparadesenvolvedorescriaraplicativosquesoexecutadosforadasualnguanativae/ou
pginasdecdigo.

ComovocadministraServidoresdoGerentedeProjetos?
OguiaServidoresInformaessobreoprojetolistaasclassesnoprojeto,tantoemVisualClass
Bibliotecasearquivosdeprograma(via DEFINECLASScdigo)quesomarcadosolepublic.cadaclasse
queestdisponvelcomoumservidorestlistadonacaixadelistagemnoladoesquerdodapgina.Conformevocrola
parabaixonalista,onomedaclasse,bibliotecadeclasses,descrio,arquivodeajuda,eajudamudanadecontextoid
paraessaclasseespecfica.Osajustespodemserfeitosparaindicarseoservidordeautomaonico
threaded,multithreaded,ounopodemsercriadosemtodaaopoInstancing.
Estaumaconfiguraoimportantedopontodevistadodesempenho.servidoressinglethreadedprecisa
umainstnciaparacadarefernciaclasse.Apenasumprocessopodeserchamadodeumavez
aessainstncia.EsteeraumproblemaantesdoServicePack3quandodoisprocessosnecessriospara
mtodosdeacessoseparadasemumservidorumavezqueapenasumapodesertratadaaomesmotempo.Seestauma
problemadedesempenho,oservidormultithreadedpodeintervirelidarcomambasaschamadascomum
instncia.TipodeinformaoBibliotecatambmexibidonacaixadedilogo.

Comovocdefinirdescriodoobjetodoprojeto?
Criaodedocumentaotcnicatemsidosempreumaprioridadebaixaparaamaioriadosdesenvolvedoresque
conhecer.Noumadascoisasdivertidasquefazemosemnossotrabalho.Cadaarquivoquecontroladonoprojetotem
umadescrioopcionalquepodeserpreenchido.Estacaractersticaparticulardogestordoprojecto
muitotilemumambientedeequipeparaquetodososdesenvolvedorespossamentenderoqueoarquivorealiza
ouqueapresentaelesuporta.Eletambmpodesertilparaumaspessoalojasparalembraro
desenvolvedorqualopropsitodoarquivo.
Adescriopodeseracessadoatravsdomenudeatalho(cliquecomobotodireitodoGerentedeProjeto
menu)ouoProjetomenuprincipal|Editardescrio...opo.EstaopoexibeoEditar
Descriodedilogo(verFigura14.1).Digiteotextoquedescreveoarquivoesalvlo
premindoobotoOK.Naturalmente,pressionandoobotoCancelarirreverterasalteraesqueacabou
digitada.
Captulo14:GerenciamentodeProjetos 465

Figura14.1Usandoadescriodoarquivoparadescreveropropsitodoarquivonoaplicativo
podeajudarvocesuaequipeaentenderoqueparasemabriroarquivoparacima.

Vriosarquivosdereteradescriodentrodometadadoscdigofontedoarquivo,outrossosalvosem
metadadosdoprojeto.AsdescriesinscritasnoProjectManagersomantidosnaclasse
definies(noomesmoparaasbibliotecasdeclasse),bancosdedadoscontinhatabelaseavista
definies.Seasdescriessoadicionados/alteradosatravsdaclasse,bancodedados,tabelaouVista
Designer,elessoarmazenadosnometadadosdeorigemeexibidanoProjectManager.Oresto
dasdescriessoarmazenadosdiretamentenoarquivodeprojeto.Issoimportanteparasabersevocj
temumarquivodeprojetocorrompido.(Simelefazacontecer,emboracommenosfrequnciadoqueno2.x
dias).Sevocnomanterbackupsslidosdosarquivosdoprojetoeterumcorrompido,vocvai
perderasdescriesduranteareconstruodeumnovoprojeto.

Comoconfigurarasinformaesdaversoexecutvel
OVisualFoxPro6.0ProjectManagerarmazenaasltimasinformaessobreaversoqueestconfigurado
atravsdacompilaodedilogo(verFigura14.2).Estainformaousadapeloprocessodeconstruoe
armazenadonoexecutvelresultante(.EXE).Devenotarsequenoarmazenadono
aplicao(.APP)arquivoseesseotipodeexecutvelquevocgerar.

466 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Figura14.2UsandoacaixadedilogoOpesdeconstruoparaobterodilogodeverso,os
podearmazenarinformaesdiretamenteparaoexecutvelresultante.Algumasdessasinformaes
desenvolvedoresVFP
podeservistoemferramentascomooWindowsExplorer.

Estainformaosobreaversopodeserextradoatravsdanovafunonativa AFILEVERSION.Se,por
algummotivovocestiverusandoVFP5.0,vocprecisarusaro GetFileVersionfunoque
disponvelemFoxtools.fll.Existemalgumasdiferenasnachamadadasfunesedo
informaesnamatrizdecadafuno,porisso,sevocusaVFP5.0,consulteoarquivodeAjuda.
EmVFP6, AFILEVERSIONfunoretornaumzeroseoarquivoespecificadonasegunda
parmetronofoiencontrado.Seoarquivoforencontrado,amatrizcriadacom15elementos.Tabela14.1
contmasinformaesqueseriavistoexecutandoum MEMOLISTnocomando
Janela:

?AGETFILEVERSION(laEXEDetails,"Sample01.exe")

Captulo14:GerenciamentodeProjetos 467

Tabela14.1ExemplodesadadeAGETFILEVERSIONdoSample01.exe

ordem Contedo Valoresdeexemplo


Posio
1 Comente "Desenvolvidopara1001CoisasQueVocQueriaSaberSobre
VFP"
2 Nomedaempresa "KirtlandAssociates"
3 Descriodoarquivo "AplicaoCool"
4 Versodoarquivo "1.0.1"
5 Nomeinterno "Sample01"
6 DireitosdeautorLegal "Janeiro2000"
7 TrademarkLegal "Marcasdeexemplo"
8 Nomedoarquivooriginal "Sample01.exe"
9 Construirprivada ""
10 NomedoProduto "Sample.exe"
11 Versodoproduto "1.0.1"
12 Construirespecial ""
13 RegistroOLEAuto ""
14 Lngua "InglsdosEstadosUnidos)"
15 Cdigodetraduo "040904e4"

O AFILEVERSIONfunopodeserusadaparadeterminarosdetalhesdaversoemmaisdoqueapenas
executveisVFPeletambmpodeserusadoparaobterdetalhessobreoutrasversoWindowsexecutveis.
Portanto,sevocexecutarocdigoaseguir,vocvaiter9.0.2719exibidanatelaparao
versoinicialdoExcel2000:

AGETFILEVERSION(laEXEDetails,
"C:\ProgramFiles\MicrosoftOffice\Office\EXCEL.EXE")
?laExeDetails[4]

Ento,qualousodesterecurso?Vamosutilizloparaexibirasinformaesdeversoemambososnossos
telainicialpadroesobreajaneladoaplicativo.

QuaissoasvantagensdeincluiroConfig.fpwno
oprojeto?
OarquivoConfig.fpwpermiteaosdesenvolvedoresVisualFoxProcontrolesobreoambienteVFP
configuraes.Adicionandooarquivoparaoprojetopermiteafcilediodasconfiguraesparao
aplicao.Marcloincludonoprojetoirincorporaraconfiguraoparao
executvel.VFPusaautomaticamenteessearquivoparafazerquaisqueralteraesdeconfiguraoqueo
aplicaoestcomeando.Seoarquivonoestmarcadocomoincludonoprojeto,eleprecisaser
distribudoseparadamentecomoexecutvel.
EsteumficheiroCONFIG.fpwdeexemploquepodemserincludasnoprojecto.Asconfiguraesdentro
essearquivopoderiacausarVFPparaoarranquesematelaprincipalqueestsendoexibidoeoFoxUser
arquivonodiretriodosistemasobodiretrioraizdoaplicativoparaserusadocomoorecursoaplicativos
Arquivo:

468 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

*AaplicaocomeacomVFPQuadrooff
tela =off
resource=system\foxuser.dbf

Incluindooarquivoexecutvelnovaieliminaranecessidadedeoprocessoterqueinstalar
carregarumarquivodeconfiguraoe,emseguida,atribulaatravsdosmecanismoshabituais.Noquepassado
podeterincludoaumparmetrocnalinhadecomandodentrodeumatalhoparao
aplicao.SeousurioclicarduasvezessobreoexecutvelnoWindowsExplorer,asconfiguraes
Nuncaforamfeitasporqueoarquivodeconfiguraonofoicarregado.Aoutraomecanismo
FOXPROWCFGDOSvariveldeambiente,masissoobrigaopessoaldeapoioouaousurio
certificarseesteestconfiguradoemcadamquinaqueoexecutvelexecutado.Aoutradesvantagem
deusaraconfiguraodoambienteDOSqueeleoarquivodeconfiguraopadroparatodoscarregados
aplicaesVFP.Nsgostamosdetermaiscontroleparacadaaplicao,atribuindoassimumaespecfica
arquivodeconfiguraoparacadasistemaliberado.

ComopodemosincluirobjetosnoVFPnoprojeto?
desenvolvedoresVFPestfamiliarizadocomosdiferentestiposdearquivosquesocontroladosemumVFPpadro
projetocomoformulrios,relatrios,etiquetas,bibliotecasdeclassesvisual,programas,APIs,aplicativos,menus,
arquivosdetexto,bancosdedadosetabelaslivres.Sabiaquevocpodeincluirarquivosdeseu
processadorfavoritodetexto,planilha,pacotedegrficosououtroaplicativo?
HvriosarquivosnoVFPquegostariadeincluirnogerentedeprojetoparatodos
aplicaesquedesenvolvemos.SevoctiveroProjectManagerconfiguradoparaabriroarquivoquando
clicadoduasvezes,elefuncionaexatamentecomooWindowsExplorereiriniciaroprogramaassociado
eabraoarquivo.NsgostamosdeincluiressestiposdearquivosnoVFPnacategoriaOutrosarquivosna
ProjectManager,umavezquemostraaextensodoarquivo.Umdosproblemascomestatcnicaa
tipodearquivopadroparaestacategoriaumbitmap(.bmp.msk)eorestodostiposdearquivona
listasogrfica.Vocprecisaselecionaraopo"Todososarquivos"eescolheroarquivoquevocdesejaadicionar
oprojeto.
Captulo14:GerenciamentodeProjetos 469

Figura14.3GerentedeProjetocomarquivosnoVFPincludonoprojeto

Humpardeitensdignosdenotamencionarcomestafuncionalidade.Sevocno
excluiressesarquivos,elesseroconstrudosparaoexecutvelgeradoduranteoprocessodecriao.
Elessoincludosporpadroquandovocadicionalosdentro.Istopodeserbenficosevocquerqueeles
fornecidocomoprodutofinalenoquerenviloscomoumarquivoseparado.Oladonegativo
damoedaqueessesarquivosiradicionarotamanhobytecompletodoarquivoparaoseuexecutvel.Estes
arquivosinchadaspodelevaraexecutveisdecarregamentomaislentoeanecessidadedemaismemriaparaexecutaro
aplicao.
OprimeirodosarquivosquegostariadetercomopartedoprojetoumarquivoReadMe.txt.Esteficheiro
incluiquaisquerdetalhesqueaequipededesenvolvimentodeveincluirparaosusuriosalerdepoisqueeles
carregararevisomaisrecentedoaplicativo.Estearquivotemumalistadenovosrecursos,correesdebugs,e
questespendentesparaaversonsestamosliberando.Istodaoutilizadorumabasedepontodepartidapara
entenderoqueelesprecisamrevereaequipededesenvolvimentoumaformadeacompanharahistriadoque
foitrabalhadoparaaliberaoeoqueaindaprecisaserconcludaantesdeenviar.
Osegundotipodearquivoqueincluem,tipicamente,soarquivosdeprocessamentodetexto.Existemvrios
documentosutilizadosparaogerenciamentoedesenvolvimentodeprojetosdentrodociclodevidadeumprojeto.
Estesincluempropostas,especificaesfuncionais,ordensdecontroledemudanas,listasprioritriase
documentosOLEAutomation.Adicionandoessesarquivosparaumprojetopodeeconomizarotemponecessriopara
odiretriodentrodoprocessadordetextocadavezqueumdessesdocumentosdeveser
encontrar

470 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

modificada.Tambmseriaprudentemencionarqueessesarquivosdevemsercuidadosamentegerido
foradoprojeto,bemcomo,umavezqueelessoimportantesparaosucessodoprojeto.
arquivosdeajudapodemserincludosseelessooformatoHLPmaisvelhasoumaisrecentecompilado
formatoHTML(CHM).IstodacessodesenvolvedoresdoprojetoparaoarquivodeAjudagerados
semdispararoaplicativo.
ficheirosHTMLpodesermodificadoutilizandooeditorVFPnativa,masexistemferramentasmelhoresque
modificarestetipodearquivo.SevoctiveraextensoHTMatribudaaumaferramentacomooFrontPageouHot
Demetal,ouincumprimentodeumnavegadorcomooNetscapeNavigatorouInternetExplorer,essesarquivossero
serabertoforadoVisualFoxPro.
MesmoqueosarquivosdeprojetosonativosparaVisualFoxPro,elespodemseradicionadosaumprojetocomoum
Outroarquivo.Soaumpoucoestranho,no?Duplocliquesobreessearquivoserabertoo
projetoemsuaprpriainstnciadogestordoprojecto.Seaarquiteturadeterseleccionadotemuma
principaisaplicaesexecutveisevriosquesoexecutadosapartirdoexecutvelprincipalvocpodeconfigurar
oprojetocontroleeterosprojectos"app"disponveisapartirdedentrodele.
Nohpraticamentenenhumlimiteparaonmerodearquivosexternosquefazempartedoarquivodeprojeto,
apenasolimitedetamanhodearquivode2gigabytesnatabelademetadadosdoprojeto.Onicorequisitoque
oarquivoadicionadodeveterumaextensodearquivoregistadoqueestassociadocomumprograma.Ns
Encorajovosaaproveitaressafuncionalidadequandovocacharqueapropriado.

ComoreduziratelaimobiliriotomadapeloProjeto
Gerente
funcionalidadedeencaixegeralmenteassociadacombarrasdeferramentas.MuitosnovosdesenvolvedoresparaVisual
foramintroduzidasparaacapacidadedeencaixedoGestorVFPprojetoporqueelesvemissocomouma
FoxPronotem
formarnareadetrabalho.OGerentedeProjetopodeserumaformadetamanhocompletooupodeserreduzidoaum
barralikeexistncia.Issopodeseralternadaclicandonobotodecomandoseta
direitadasguias.
OGerentedeProjetorecebeapenasancoradoquandoelearrastadoparaareadabarradeferramentassuperior/menu
oambientededesenvolvimentoouclicandoduasvezesoProjectManagerTitleBar(tambmconhecido
comoaformadelegenda).Anicamaneiradefecharumprojetoancoradousandooarquivo|Fecharomenu
opo.Voctambmpodedesencaixaroprojetoparafechlaatravsdobotodefechamento.

Captulo14:GerenciamentodeProjetos 471

Figura14.4IstooqueoGerentedeProjetoparecequandoelaestiverencaixadabarrade
eumadaspginassoacessadasclicandonaguiadapgina
ferramentas
ComoarrancarguiasdoGerentedeProjeto
Guiasdestacveistmnadaavercomasuabebidafriaenlatadofavorito.Bemquepoderiase
teralgumaslatasvelhasdemoda,masquandosetratadeVisualFoxPro,corteguiastemafazer
comoGerentedeProjeto,quefoireduzidoaoseuestadobarralike.Cliquenapginade
suaescolhae,emseguida,arrasteaguiadapginaparaforadabarradeferramentas.Issovaideixaraguianareade
trabalho.
Umavezqueoguiafoiarrancadoabarradeferramentas,vocpodearrastloparaondequisernaVFP
readeTrabalho.VFPlembraondedeixouoprojetoquandoelefechado,masporalgumarazo,
nosalvaoestadodaspginasrasgadasoff.Agarrandonocantoinferiordireitodaguiapermite
loparadimensionloapenascomoumajanelaconsidervelregular.Arrastandoqualquerumdosladosnopodefazer
deveserocanto.Fecharereabriroprojetoreataasabasqueestavamanteriormente
isso
arrancado.Clicandosobreoalfineteiralternaroalfinete.Estedevebloquearquandooguia,porisso,
vocnopodearrastloemqualquerlugaratquesejanovamentealternado"out".NoVFP6.0comoServicePack3
aplicada,oalfinetetemnenhumefeitosobreacapacidadedearrasto.

472 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura14.5AquioprojetodeamostradestecaptulocomosTodoseCdigopginasarrancadas

VocpodeexpandiroGerentedeProjetoparaotamanhomximo,mesmocomasabasarrancadas.aspginas
quesoarrancadassodesativadosepermanecemarrancada.VocpoderetornarasguiasdevoltaparaoProjeto
Managerdeumaexpandidooutamanhoreduzido,arrastandoosparatrs,masvocspoderasgar
losforaquandooGerentedeProjetonoestadoreduzido.

existemQueproblemasaoabrirumbancodedadosno
projeto?
Umacoisaqueaprendemoscedoemuitasvezesqueoprojetoabreautomaticamentequalquerbancodedadosque
tersuahierarquiaexpandidanaDadosouTodososguias,pelaprimeiravez,querguiadadofoco.Ese
oprojetofoifechadoquandooseparadordedadostevefoco,elevaiabrirqualquerbancodedadosqueso
expandidaquandooprojetoforaberto.
Asbasesdedadossoabertosexclusivamenteouemmodocompartilhado,combasenaconfiguraodoambiente
de SETEXCLUSIVE.Istopodesercrticoseodesenvolvimentodeumasituaoemqueequipanoutilizaralguns
formadecontroledecdigofontecomcpiasdomesmoprojetocomnomesdiferentes.esteautor
temlutadoporissocomsuaequipeatqueeleinstituiuumaclasseProjectHookque SET
OFFEXCLUSIVOquandooprojetoaberto.Destaforma,todosnaequipepodemjogarnamesma
sandbox,sembloqueiodeacessoaosbancosdedados.Seumdesenvolvedorrecebeusoexclusivodo
bancodedadoseoutraseabrenaguiadados,oProjectManagertentafazercomqueosdiferentesdetalhes
dobancodedados,masnopodelerobancodedados.Eleentraemmodo"cmeralenta"elentamente

Captulo14:GerenciamentodeProjetos 473

desenhaoTreeViewcomapenasansnativadaVFP.Semtabelas,visualizaes,conexesouarmazenados
procedimentossoexibidos.Outroproblemacomestemodoqueningumpodeconstruirum
aplicaoumavezqueogerentedeprojetoprecisausoexclusivodobancodedadospararecompilaro
procedimentosarmazenados.Notemoscertezadeporqueissonecessrioumavezqueelessocompiladosdecadavez
elessosalvosapsumasessodeedio.
SeobancodedadosabertoatravsdoGerentedeProjeto,elenopodeserfechadocoma FECHAR
DATABASESALLcomando.Ocomandofazefetivamenteum DATABASESETTO,oquetorna
nenhumbancodedadosbancodedadosatual.AnicamaneiradefecharbancosdedadosabertoatravsdoProjeto
GerenteselecionarobancodedadosepressioneobotopertodoGerentedeProjetooufecharo
projeto.

arrastamentoprojetoetruquesquedeixamcair
MuitosdesenvolvedoressesurpreendemaodescobrirqueoGerentedeProjetoumclientedragndrope
servidor.IstosignificaqueosarquivospodemserarrastadosparaoGerentedeProjetodemuitasfontes
incluindooutrosprojetosedeforadoVisualFoxPro.

Oqueacontecequandoarrastaapartirdeumprojetoparaoutro?
Arrastararquivosentredoisprojetosdiferentescriaumareferncianosegundoprojectoparaesse
Arquivo.Sehumadescrioparaoarquivo,estadescriotambmadicionadoaosegundoprojecto,
mesmoparaarquivosquenoarmazenamadescrionoprprioarquivo.Seoarquivoumprogramadefinidocomoo
programaprincipaldoprojetooriginrio,VFPirpedirlhecomumaperguntaqueperguntasevoc
querfazeroarquivodoprogramaprincipalnosegundoprojeto.Vocnoprecisaestarno
mesmapginaemcadaprojeto.Oarquivonaturalmenteadicionadacategoriacorretacombasenoarquivo
extenso.

Comopossoarrastarobjetosdeumprojetoparaumdesigner?
Arrastarosarquivosdoprojetoparaumformulrioouclassedesignerpodeeconomizartempoduranteo
Muitosobjetosdeprojetopodeserarrastadoparaoformulrioouclasse.Osobjetosdescartadosso
desenvolvimento.
instanciadonodesigner.
Arrastandoumcampoapartirdeumbancodedadoscontinhatabela,exibiooutabelalivreaumformulrioou
instanciaraclasseassociadaparaotipodedados.Avantagemdesserecursoqueelecriaum
classeir
objetonaclasseligadossemautilizaodeumDataEnvironment.Muitosdesenvolvedoresquetemos
instruiuaolongodosanossentemqueprecisamprimeiraquedaemumaclassee,emseguida,definiraorigemdo
EnquantoaconfiguraomanualdosOrigemDoControleobras,queexigequeosdesenvolvedorespararealizaruma
controle.
etapaextra.AoutravantagemdestatcnicaqueeleincorporaoIntellidrop
capacidadedevistoquandovocexecutarestaoperaoapartirdoDataEnvironment.Destaforma,o
classesespecificadascomantecednciasousadosemvezdasclassesbaseVFP.
Tabelasarrastadoparaumformulrioouclasseirinstanciarumagrade.Sevocclicarcomobotodireitoearraste,
soapresentadoscomaopodaclassegrade(ououtraclassequevocdefiniuparaoMultiple
voc
configuraonomapeamentodecamponaferramenta|Opes).
Sevocquerumaclasseespecficacaiuemoutraclassedecontiner,vocpodeselecionlona
ProjectManagerearrastloparaaclasserecipiente.Estanovinculaoobjetocomooarrasto
operaodeumcampodetabela.IstopermitelhesubstituirasconfiguraesIntellidropquesopr
mapeada.
474 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Espervamosqueumconecaiuemumformulriopodedefinirapropriedadedeformulrioconeeque
soltandoumgrficoiriagerarumobjetodeimagem.Elesno.Outrosobjectosnomencionados
nestaseonopodeserdescartadoemumaclassedeformulrioourecipiente.

Oqueacontecequandoarrastandodeprojetoparaprogramarcdigo?
Nomesmoespritodescritonaseoanterior,vocpodearrastaresoltarprojetodiferente
objetosparaeditoresdecdigo.Onomedoobjetoexibidonajaneladecdigo.Porexemplo,
sevocdeixarcairumnomedecamponajaneladecomando,vocrecebeonomedocampo.Infelizmentevoc
noobterasintaxetable.fieldname.Issofuncionaparacadatipodeobjetonoprojeto,excetoo
nomesprocedimentoarmazenado.Osnicosobjetosquecarregamsobreaextensodearquivosoosarquivosno
Categoria"outros".

Oqueacontecequandoarrastardenavegadordeclasseoucomponente
Galeriaparaumprojeto?
Testamosumpardeoutrasidiascomestacapacidade,arrastandoosarquivosdaclasseVFP
Navegadoreseuprimoprximo,aGaleriadecomponentes.
Espervamosquearrastandoasclassesapartirdonavegadordeclasseaogestordoprojectoseria
adicionaraclasse.Infelizmente,issonofunciona.Nsarrastadooconenocantosuperioresquerdo
paraoprojeto,assimcomotemosmuitasvezesparaoutrainstnciadobrowserclasse.claro
nofuncionanaversodoVFP6.0quecorremos,queServicePack3.
Aindamaisinteressantequearealizaodosmesmostestesnagaleriadecomponentesprovou
bemsucedido.Escolhaaclassenagaleriadecomponentesearrasteoconenoladosuperioresquerdo
cantoouoconenopaineldadireitaearrasteoparaoGerentedeProjeto.Seoarquivoumaclasse,
humdilogoapresentadaqueestperguntandocomovocdesejaadicionaroarquivoparaoprojecto(ver
Figura14.6).Voctemaopodeadicionarabibliotecadeclassesexistentesouadicionarumacpiadaclassepara
outrabibliotecadeclasses.Oarquivoadicionado.Legal!Qualquerarquivoquepodeseradicionadoaumprojetopodeser
retiradodagaleriadecomponentes.acrescentandorapidamentearquivoscomunsaumprojetoapartirdoseu
Catlogofavoritoumatcnicamuitopoderosa!

Captulo14:GerenciamentodeProjetos 475
Figura14.6AquiestoAddClassparadilogoqueapresentadaprojetoquandocair
arquivosdagaleriadecomponentesemumprojeto

OqueacontecequandoarrastardeumaplicativonoVFPaum
projeto?
OutrorecursolegalqueosarquivospodemserarrastadosparaoGerentedeProjetodefora
VFP.OGerentedeProjetoapenasumadasmuitaspartesdoVFPqueforamhabilitadoparaOLEGota
earrastenaVFP6.0.
Ento,comopossoaproveitaresserecurso?PopabraoWindowsExplorerouoseufavorito
substituio.SearrastaresoltararquivosespecficosVFPdeExplorerparaoGerentedeProjeto,
elessoadicionadoscategoriaapropriada.arquivosnoVFPsoadicionadoscategoria"outros".Ese
quearrastarumatalhodareadetrabalho,temosumarquivodeatalho(LNK)adicionadoao"outro"
categorianoProjectManager.

Comotomarvantagemdeocampodoutilizadorprojecto
CadaumdosarquivosdemetadadosdoVisualFoxProcontmumcampodeusurioquenousadoemtodosospor
si.Eleprojetadoparaserusadopordesenvolvedoresparaqualquerfimqueentenderem.Estecampo
VFP
noexpostospelainterfaceGerentedeProjeto,maspodeseracessadoporabriroprojeto
metadadoscomoumatabelaenavegarporeles.
Nsnonosconhecemosmuitosdesenvolvedoresqueutilizamestafuncionalidadenoarquivodeprojeto.umuso
quetemosvindoapensarultimamenteestarmazenandoumltimobackupdocarimbodedata/horanestecampo

476 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

eenganchandoemumprocessoquefechatodososarquivosnoprojetoparaumarquivocompactadovia
DynaZip.Infelizmente,oobjetodeArquivosatualnoexponhaestecampoparaodesenvolvedorem
esteoprocessodebackuptempoeterde"cortar"oarquivodeprojeto.

Comoprocederparadocumentaroarquivodeprojeto
AtoProjectHooknosfoidadaemVFP6.0,anicamaneiradeacessaroprojeto
informaoeraparaabriroarquivodeprojetocomoumatabelaeprocessoatravsdosregistros.muito
importantelembrarquevocdeveprocessaratravsdeumacpiadoarquivooriginaldoprojeto.este
precauonecessrianocasodevocfazerumamudanaacidentaldeumcampoqueconfundeoProjeto
Manageredesativaacapacidadedeabrilo.
Hackingoarquivodeprojetonotograndeumnegcio,umavezqueinicialmentepodeparecerumavezqueoarquivo
estbemdocumentadaemquemais,umprojeto,queestno
deprojeto HOME()+"Filespec\"diretrio.Vejo
Tabela14.2paraumalistadeprojetosparacadaumdoslanamentos.

Tabela14.2listadasespecificaesdelayoutarquivodeprojetoVFPdisponveis

Projeto Relatrios VFPReleases


60Spec.pjx 60Pjx1.frx VFP6.0
60Pjx2.frx
50Spec.pjx 50Pjx1.frx VFP5.0
50Pjx2.frx
30spec.pjx 30Pjx1.frx VFP3.0
30Pjx2.frx
26spec.pjx 26Pjx1.frx TodosVFPlanamento
26Pjx2.frx

Paratrsnosdias2.x,oautorcriouumaferramentadedesenvolvimentochamadadeListerProject.este
ferramentafoioriginalmentecriadoparagerarumalistadeverificaodetodososarquivosemumprojetopara
todososarquivosdedocumentaoouparafazeralteraesparaumaatualizaoespecfica.estaferramenta
processar
temevoludoaolongodosanoseincludocomoumexemplodoquevocpodefazerquando"hacking"
oprojeto.Eleestdisponvelnosarquivosdedownloaddesenvolvedoremwww.hentzenwerke.com.Oarquivo
chamadopl60.zipeestincludocomosoutrosarquivosassociadosaestecaptulo.
Captulo14:GerenciamentodeProjetos 477

Figura14.7EsteoProjetoListerVFPqueumexemplode"hacking"doVFP
arquivodeprojeto

OutilitrioProjetoListerlistaosdiferentesobjetosdeorigemqueestoemumVFPespecfica
projeto.Comoseobserva,estaferramentafoicriadaparalistarcadaumdosobjetosnoprojetocomoumalistade
umaplicativoestavasendodesenvolvido.Comoopassardotempo,maisemaisrecursosforamadicionadosao
verificaocomo
darmaisdetalhessobrecadaumdosobjetos.Agora,oListerProjetoutilizadoparadocumentara
noesbsicassobreosprojetosdesenvolvidoseparadeterminaroqueexatamenteestemprojetosqueestoolhando
assumirocontrole.Aatualencarnaonosaradosatravsdosdiferentesobjetosdecdigofonte,
para
masfazumtrabalhorudimentardignodedocumentarumrecipientedebancodedadostambm.Observe
quenovaidarlheaprofundidadequealgocomooToolkitStonefieldbancodedadosd
voc,mastil.

Tabela14.3RecursosqueestoincludosnoProjetoLister

Escolhaumprojetoparadocumentarapartirdeumprojetoabertoouumresidentenodisco
relatriosconfigurveispermitemselecionarquaisinformaesaparecem
listaconfigurveldeobjetosdoprojetopermitemselecionarquaistiposdeobjetosaparecememrelatrios
Podeprocurarosobjetosqueseroexibidosnasada
Selecioneapartirdevriosrelatrios(tantodeimpressograndeecompactado)eordensdiferentes
Sadapararelatriodeprvisualizao,relatrioimpresso,arquivodetexto,oWindowsprancheta,ouformatodemesalivre
RequerVFP6porqueincorporaalgumasdasnovaspropriedadesobjetodeprojeto,eventosemtodos

Concluso
GerentedeProjetodoVisualFoxProlhedumnicolocalparagerenciartodasasfacetasdoprojeto
desenvolvimentoecriaodeconstruo.NoentantocomoVisualFoxPro6.0,ogestordoprojectoainda
478 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

apenasmetadedahistria.Peloamordelegibilidade,o"restodahistria"emprojetos,projetodeobjetose
ganchosdoprojetosoabordadosnoprximocaptulo.Leia!

Captulo15:ObjetosdoprojetoeProjectHooks479

Captulo15
Objetosdoprojetoe
ProjectHooks
"Euaindanoviqualquerproblema,noentantocomplicado,que,quandovocolhouparaelena
caminhocerto,nosetornouaindamaiscomplicado."(PaulAndersonescrevendono"NewScientist
(Londres,"25desetembrode1969)
EstecaptuloirapresentarosnovosobjetosProjectHookedeprojectonoVFP6.0e
algumasutilizaesdestasferramentasdedesenvolvimentoimportantes.Nsembrulharsecomum
tantooVFPProjectHookeoobjetodeprojetoemumutilitrioconhecidocomooProjetoRAS
exemplodequeoslaos
Construtor.

aopiniodoautorqueacombinaodoobjetoProjectHookeprojetofoiumdos
asnicascaractersticasmaisinteressantesdolanamentodoVisualFoxPro6.0.Estasduascaractersticas
exporosacontecimentosdoGerentedeProjetoeampliaracapacidadedeumdesenvolvedorparaadicionar
AmbienteInterativodeDesenvolvimento(IDE)doVisualFoxPro.OProjectHookumabaseVFP
classequepermitequeocdigopersonalizadoparaserexecutadoemrespostaaaestomadaspelodesenvolvedor
oGerentedeProjeto.OobjetodoprojetoumobjetoCOMquepermiteaosdesenvolvedoresparaexecutar
quandoseutiliza
aesqueforamreguladospreviamentepara"hackear"osarquivosdoprojeto(.pjx).

ComousarProjectHooksparapegarumpeixegrande
PrimeiroqueremosaproximaranovaclasseProjectHook.OProjectHookpodeserumasubclassee
estendidaassimcomoasoutrasclassesdebaseemVFP.Estaclasse,quandoinstanciado,engancha
diferenteseventosquesodesencadeadospelogerentedeprojeto.OProjectHookfacultativamente
instanciadoquandoumprojetoaberto.importantenotarqueosProjectHooksnoso
automticoelesexigemquevocespecificarumaclasseProjectHookparacadaprojeto.
CriandoumaclasseProjectHooktosimplescomoacriaodequalqueroutraclassenoVisual
FoxPro.Usandoo CREATECLASScomandomostraacaixadedilogoNovaclassemostradonaFigura
15.1.Vocespecificaonomedaclasse,baselonoProjectHookVFP(ououtraclasseProjectHook
voccriouanteriormente)eselecioneabibliotecadeclassequevocdesejasalvaraclasse.

480 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura15.1AnovaclassededilogoVFPquedemonstracomocriarumanova
classeProjectHook

DepoisdeclicarnobotoOKonovoProjectHookestardisponvelnaClasse
Designer.Vocpodelerafolhadepropriedadesparavertodasaspropriedadesemtodosqueso
disponvel.HumalistacompletadosmtodosdeTabela15.1.

Tabela15.1EstaumalistademtodoseseuusoparaaclasseProjectHook.

Mtodo Usar
AfterBuild Permiteaodesenvolvedorverificaronmerodeerrosencontradosduranteaaodecompilao.Isto
tambmumtimolugarpararedefinirambienteparaasconfiguraessalvasantesdeseremdefinidasno
BeforeBuildmtodo.
BeforeBuild Permitequeosdesenvolvedoresapararumacompilaocombaseemcondiesouparmetrosdesejados.Tambmum
lugarparacolocarcdigoparapedirosdesenvolvedoresparapossveisconfiguraeseajustarambiente
paraaconstruo.
Destruir PadroVFPDestruirmtodo.
Erro PadroVFPerromtodo.
Nisso VFPpadroInitmtodo.
OLEDragDrop VFPPadroOLEDragDropmtodo.
OLEDragOver PadroVFPOLEDragOvermtodo.
OLEGiveFeedback VFPPadroOLEGiveFeedbackmtodo.
QueryAddFile acionadoquandoumnovoarquivodequalquertipoadicionadoaoprojeto.Ocdigopodeserincludopara
Certificoqueoarquivopodeseradicionadoaoprojeto.Incluilgicaqueexecutaum
NODEFAULTparaqueoarquivonoadicionadoaoprojeto.
QueryModifyFile acionadoquandoumarquivoexistentedequalquertiposelecionadoparasermodificadoapartirdoprojeto.
Cdigopodeserincludoqueircertificarqueoarquivopodesermodificadoapartirdoprojeto.
IncluialgicaqueexecutaumNODEFAULTparaqueoarquivonomodificadoatravsda
projeto.
QueryRemoveFile acionadoquandoumarquivoexistentedequalquertiposelecionadoparaserremovidodoprojeto.
Opcionalmente,possvelexcluiroarquivododiscotambm.Cdigopodeserincludoqueavontade
Certificoqueoarquivopodeserremovidodoprojeto.Incluilgicaqueexecutaum
NODEFAULTparaqueoarquivonoremovidodoprojeto.
QueryRunFile acionadoquandoumarquivoexistentedequalquertiposelecionadoparaserexecutadoapartirdoprojeto.Cdigo
podeserincludoqueircertificarqueoarquivopodeserexecutadoapartirdoprojeto.inclui
lgicaqueexecutaumNODEFAULTparaqueoarquivonoexecutadoapartirdoprojeto.

UmavezqueoProjectHookcriadosimplesmentedesignadocomoProjectHookdoprojectoatravsdo
InformaesdoProjetodedilogo(verFigura15.2).Aopoestnapginadoprojetoeselecionadapor

Captulo15:ObjetosdoprojetoeProjectHooks481

verificandoacaixadeseleodeclassesdeprojetoedeprosseguiratravsdodilogoProjectReference
(Dilogodeseleodeclasse).VocprecisasaberqueaclasseumProjectHook.Sevocnoselecionarum
ProjectHook,vocserpunidocomumamensagemquedizapenasaquela.

DepoisdeselecionarcomsucessoaclasseProjectHook,importante
lembresequevocprecisaparareabrirumprojetoparaqueoProjectHook
instanciado.OGerentedeProjetonocapazdeinstanciaraclasse
depoisdesignadoamenosquevocexecutarestaao.

Figura15.2OdilogodeseleoProjectHookVFPpareceestranhamentesemelhanteao
dedilogoclassedeseleoapresentadapelafunoVFPAGETCLASS

ComoconfigurarumProjectHookglobalparatodososprojectos
AlmdacriaodeumProjectHookparaumprojetoindividual,osdesenvolvedorespodemterumaProjectHook
comopadroProjectHookparatodososnovosprojetosquesocriadosnofuturo.Istoconfigurado
atravsdasferramentasVFP|caixadedilogoOpesnapginadeProjetos.
Quandoumnovoprojetocriado,eleatribudooProjectHookglobal.Quasesoacomons
estoocupandoumacausaparasalvaroplaneta.Mas,falandosrio,sevoctemumProjectHookdesenvolvido
quedenaturezagenrica,entoesteoseubilhete.

OqueacontecequandoumProjectHookperdidoouexcludo?
EntovocestseperguntandooqueacontecesevoctemumaProjectHookdesignadoparaoprojeto
ealgovaimal.Acontece.AlgumentraeinocentementehacksdoProjectHook
bibliotecaebrindesdoarquivo.Oupioralgumalteraintencionalmentealgumcdigoesperandoparaadicionar
amelhorcoisadesdeopofatiadoetornatoaclassenoinstancia.Ouquese
aclasseexcludodabibliotecadeclasse?Oqueacontececomoprojeto?Simplesoprojeto
482 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

noabre.Euseiquevocestpensandoqueissoumrecursodeseguranaengenhosaparalibertaraparar
osdesenvolvedoresjuniordeentrarnoprojetododiaantesdolanamento.Bem,seelessoto
afiadacomoosdesenvolvedoresquetrabalhamcom,elesvoabriroficheirodeajudaouestelivroeverque
oprojetopodeserabertosemaProjectHook.O MODIFYPROJECTcomandosuportauma
NOPROJECTHOOKclusula.Aquiestumexemplo:

MODIFICARPROJETOd:\devvfp6apps\bookproject\tips.pjxNOPROJECTHOOK

Rats,achoquevamosterdecontinuararestringirologindessesdesenvolvedoresjuniornodiaanterior
olanamento<risos>.

Sevoccriarumnovoprojetoquevocpensarmelhoredecidirdesfazerse,
VFPirpedirlhecomumamensagemperguntandosevocdesejaremover
osarquivosdeprojetoouretlos.SevocconfigurarumProjectHookglobaleir
atravsdestecenrio,vocnosersolicitadodesdeVFPadicionaoProjectHook
refernciadeclasseparaoarquivodeprojetoejnoestvazio.

Ento,oquevocpodefazercomessacapacidadepoderosa?Narealidade,vocpodefazerquasequalquercoisa
seucoraodeseja.Maisadiantenestecaptulo,hvriasseesqueimplementaesdetalhe
denossasprpriasidias,bemcomoideiasdeoutrosdesenvolvedoresquetemosincorporadosemnossa
ProjectHook.

OqueaMicrosoftdeixardeforadaprimeiraversodoProjectHooks?
Oqueestfaltando?Porumlado,umprojetoAtiveeDeactivatemtodoseriamuito
calhar.Nstemosestesemumutilitrioparacontrolarasmudanasnecessriascomoousurioselecionaumnovoprojeto.
Vocvaiverexemplosmaisadiantenestecaptuloquealterarasconfiguraesdemapeamentodecampono
Registroquandooprojetoforaberto.SevocabrirvriosprojetosduranteumasessonoVFP,o
MapeamentosltimocamporegistadossousadosquandovocsoltarnarrastarcamposdoDataEnvironment
paraaforma.Seosprojetosestousandobibliotecasdeclassesseparadas,vocteruma"polinizaocruzada"
debibliotecasdeclassesnosprojetos.Emnossoescritrio,temosumasubclassedabasedequadro
classesparacadaprojetoevriosdenossosdesenvolvedorestrabalhamemprojetosdiferentesacadadia.
DesdequensusamosoProjectHookdescritomaistardenestecaptulo,osprojetosprecisamser
exterminadosdas"classesestrangeiros"deoutrosprojetosemumabaseregulardesdedesenvolvedores
queestointensamentealterarocdigotendemaesquecersesobreomapeamentodecamposconfuses.
HumexemplodeumProjectHookqueacompanhaoVisualFoxPro6.0.Oexemplo
mostracomovocpodeaproveitarosdiferenteseventoseacompanharosdesenvolvedoresdeatividadeexecutar
comoprojeto,escrevendoumaentradacadavezqueumarquivomodificadoouexecutarouoprojeto
abrirouconstrudos.Issotambmpermitequeaatividadeaservistoquandooprojetofechado.nouma
excessivamenteexemplosofisticado,maseficienteemdemonstraropoderdessasclasses.
Essaclasseeaformaexemplopodeserencontradona HOME(5)+"soluo\Tahoe\"diretrio.
Osarquivosincluemoformulriodeexemplochamadaacttrack.scx/scteoProjectHookreal,que
chamadoactivity_trackereresidenoproject_hook.vcx.

Captulo15:ObjetosdoprojetoeProjectHooks483

ComoacessarinformaesnoprojetoeobjetodeArquivos
ObjetoprojetoconstrudoemVisualFoxProenopodeserumasubclasse.umainterfaceCOMpara
oarquivodeprojeto.Nosltimosdesenvolvedorestiveramque"cortar"oarquivodeprojeto,abrindoocomoumVFP
mesalivreatravsda USEcomando.OusodocomandoSQLSELECTeoprojetoaberto
comoumatabelalivreumacombinaopotenteparaextrairainformaoquearmazenadanosmetadados.
Enquantoalgumasdestastcnicasaindasoteis,oobjetodeprojetoreduzanecessidadede"hack"
osmetadadosdoprojeto.
HumadiferenanoacessoaointerfaceCOMparaoprojectodopadro
maneiraquevocpodeestaracostumadoausar.COMobjetossoinstanciadosatravsda CREATEOBJECT(),
CreateObjectEx(),ou NEWOBJECT()funes.Oobjetodoprojetocriadoparavoctodavezqueum
projetoaberto.Oobjetodoprojetocriadoparacadaprojetoabertoeacessadoatravsdo
_VFPObjectodeaplicao.Esteobjetodacessoavriaspropriedadesemtodosparaganhar
informaessobreoprojeto.Aquiestumcdigoqueacessainformaeschavedo
projeto:

COM_vfp.ActiveProject
?.Nmerodaverso&&Exibeonmerodaversoprximacompilao
?.MainFile &&NomeDisplays(ecaminho)doarquivoprincipal
.Limpar() &&Packsosmetadadosdoprojeto
ENDWITH

Acoleodearquivosdoobjetodoprojetocomoseobtmacessoaarquivosindividuais
dentrodoprojeto.Humnmerodepropriedadesqueestoassociadascomcadaficheiro.L
tambmsocomportamentosquepodemserchamadosparamanipularosarquivosnoprojeto.Aquiestumcdigo
queacessainformaesdechaveapartirdeumarquivonoprojeto:
COM_vfp.ActiveProject
?.Files[1].Descrio&&Exibedescriodoprimeiroarquivo
?.Files[1].Modify() &&Modificaoprimeiroarquivodedesignernativa
ENDWITH

AmbasaspropriedadesdoobjetodoprojetoearquivopodeserdefinidocomoqualqueroutroobjetoVFP
propriedadeatravsdeumainstruodeatribuio:

_vfp.ActiveProject.Files[1].Exclude=.T.

AtravsdestesdoisobjetosCOM,nstemosocontrolequasecompletosobretodososarquivosemnosso
projectosVFP.

Comousarobjetosdeprojetoemdesenvolvimento
semprebomtermuitateoriaemurmuraramontoadodecomoascoisasfuncionam,masnoh
nadacomoteralgunsexemplosdavidarealparatrazlotodosjuntos.Issooqueestaseco
vaifazer.Amaioriadosexemplosquea"listaosarquivosemumprojeto"tcnica.Enquantonsencontrlos
exemplosvaliosos,elesnoservemmuitousoemnossoambientededesenvolvimento.

484 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ComoconstruirumAssistentedeaplicaobsica
Iremosdemonstrarprimeiropeasdeumassistentedeondeoobjetodoprojetoearquivosdeaplicao
objetosoaproveitados.Umexemplofoidesenvolvidoqueutilizatantooobjetodoprojetoea
ArquivosdeobjetoumAssistentedeaplicao.Oconceitobastantesimples.Processoatravsdetodaa
passosmecnicosquefizemosparacadanovopontapinicialdedesenvolvimentodoprojeto.Algunsdevocspodemestar
perguntandoporquepassarportodoesseesforoquandoVFPvemcomumAssistentedeaplicao?o
razosimpleselenoapoiaronossoquadroenoatendersnecessidadesdenossa
arquiteturadeimplementao.
Oprocessodeconstruomanualmenteoprojetoinicialteveumdesenvolvedordevriashoraspara
completo.UsandooAssistentedeaplicativo,queagoralevatodososdezminutos.Aquisoobsico
passosenvolvidos:
1.Crieodiretriodoprojetoetodososnecessrios/subdiretriospadro
2.quadrosubclasseaulasparaumnvelaocliente,entoonveldeprojeto
3.Gerarocompiladorprogramade"farsante"programaprincipale
4.GereoarquivoConfig.fpw
5.Copiesobreomodelodemenuiniciar
6.Gerarobancodedadosestruturaetabelasassociadas
7.Adicionepersonalizadostabelasdeextensoquadro
8.Gerartabelaslivresnecessrios
9.ProjectHooksubclassephkDevelopmentparaoprojetoedefinirpropriedadeschave
10.PreenchaatabelaUtilityOpodemapeamentodecampocomregistrosnecessrios
11.Geraroarquivodeprojetoepreenchercomarquivosnecessrios
12.Faaaconstruoinicialdoprojeto
13.Enviarumamensagemparaodesenvolvedorparacomearafazeralgumtrabalhoreal<risos>

OcdigousadoparasubclasseoProjectHookemudarocFieldMappingCategory
propriedadenamoscanaetapanovedemonstradonaListagem15.1.Esteutilizaduastcnicasque
podeprecisardealgumaexplicao.Oprimeiroa qualidade,quecriam...NOWAIT.Estecomandocria
aclasseeexibenoClassDesigner,emseguida,continua.Oprximotrechodecdigousa
algumatecnologia"construtor"como ASELOBJcomando.Issoretornaumamatrizcomumobjeto
refernciaaoProjectHooknoClassDesigner.Umadeclaraoeaatribuiosimples
ProjectHookestprontopararolarpelasnormasemnossaloja.Osegundopoucodeexplicao
requeridasoos TECLADOe DOEVENTScomandos.OdesignertemdeserfechadoeCtrl
Wa"salvarsemmeperguntarseeusourealmentecerto"atalho.Desdeissotudoestacontecendoem
cdigoedesdequeobufferdotecladoumeventodoWindows,os DOEVENTSfoiadicionadoparafazer
OWindowsdizerVFPparafecharoClassDesignernaquelemomentonoesperaratmaistarde,quando
respira.

Captulo15:ObjetosdoprojetoeProjectHooks485

Listagem15.1CdigonecessrioparasubclasseoProjectHookprogramaticamente
LPARAMETERStcProjectHook,tcProjectFieldMappingConfig

#defineccPROJECTHOOKSLIB "k:\vfpaddon\rasprojecthooks\cProjectHooks"
#defineccPROJECTHOOKSBASELIB"k:\vfpaddon\rasprojecthooks\cPhkBase"
#defineccPROJECTHOOKSBASE "PhkDevelopment"

Criarclasse(tcProjectHook)deccPROJECTHOOKSLIB
comoccPROJECTHOOKSBASEdeccPROJECTHOOKSBASELIBnowait

*DefinaapropriedadedeclasseparaoProjectHookcFieldMappingCategorypropriedade
aselobj(laProjectHookRef,1)

seotipo("laProjectHookRef[1]")="O"
laProjectHookRef[1].cFieldMappingCategory=tcProjectFieldMappingConfig
fimse

*CertifiquesearefernciaaoProjectHookliberado
liberaolaProjectHookRef

*LidarcomoVFPJanelasqueseabremsemarquivoderecursos
seWEXIST("Propriedades")
janeladelanamento"Propriedades"
fimse

seWEXIST("controlesdeformulrio")
janeladelanamento"controlesdeformulrio"
fimse

*FecheaclasserecmcriadoabertonoClassDesigner
*Asteclasso"buffer"atquetodasasclassessocriadas
Teclado'{CTRL+W}'

*Adicionadoparafecharosdesignersdeclasseparabaixo
DoEvents()

Passosonzeedozesoosburrosdecargaquandosetratadealavancaroobjetodeprojeto
eoobjetodearquivo.Esteolugarondeoprojetodoaplicativocriado,povoado,e,inicialmente,
construdo.Comodecostume,halgumasquesteschavedeapontar.
Primeirosoalgunsdesaparecidos"caractersticas"oupropriedadesdentrodoobjetodeprojeto.Estessoo
itensautorcomonome,empresaeendereo.Esperemosqueestesiroaparecernaprximaverso
deVFP.Seriabomparaprpreencheressasconfiguraesnoprojetoaocrila.
OsarquivosobjetoAddmtodoexecutatodaamgica.Achaveparaestemtodoconsisteemfazer
sedeincluiraextensodoarquivoquevocestadicionando.IstocomoVFPentendeoque
arquivarcategoriaparaadicionloaoabrigodoGerentedeProjeto.Oprimeiroitemimportantecriaroprojeto
atravsdo Criarprojetodecomando.Notesequeoprojetocriadocomo NOPROJECTHOOK
opo.Istogarantequenenhumganchoestassociadacomoprojectoatquesejaadicionadomaistarde.eleainda
substituiumaconfiguraoganchoglobal.Emseguida,adicionetodososarquivosquesonecessrios.Nsdescobrimos
formaquevocprecisadepelomenosumarquivodecadadiretrioparacadatipodearquivo.Porexemplo,se
odisco
tmbibliotecasdeclassesnodiretrioliberaisdoprojetoeodiretrioliberaisdoquadro,precisamos
paraadicionarumarquivodecadaum.Destaforma,aconstruodoprojetopodeencontrarorestantedosarquivosno
486 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

caminhodepesquisaqueestabeleceapartirdosarquivosadicionadosanteriormente.Quaisquerarquivoschamadosatravsda
tcnicadechamadasindiretas(viasubstituiodemacroou eval())tambmdeveseradicionadocomdirecto
chamadasparaoAddmtodo.

OcdigonaListagem15.2apenasumapequenapartedocdigoqueutilizamosnaproduo.Ese
vocestinteressadoemlertodooprograma,estdisponvelnoDeveloper
Baixararquivosdisponveisemwww.hentzenwerke.comcomoGenProjectFile.prgcom
osoutrosexemplosdestecaptulo.

Listagem15.2Cdigousadoparageraroprojeto,preenchlocomosarquivose,inicialmente,construir
oprojetoparapuxarosarquivosassociados

LPARAMETERStcProjPrefix,tcProjectDir,
tcBusinessGroupDir,tcSystem,tcProjectHook

#DEFINECcPROJECTHOOKSLIB"k:\vfpaddon\rasprojecthooks\cProjectHooks.vcx"

Criarprojeto(lcProjectName)NOWAITSALVARNOSHOWNOPROJECTHOOK

IFTYPE("_vfp.ActiveProject")="O"EISNULL(_vfp.ActiveProject!)
EARQUIVO(lcProjectName)

?"Arquivodeprojetocriado"+lcProjectName+"no"+TTOC(DATETIME())

COM_vfp.ActiveProject
*DefinaalgumasdasinformaesdeconstruoVerso
.HomeDir =tcProjectDir
.Incrementoautomtico
=.T.
.Depurar =.T.
.Nmerodaverso ="1.0.0"
.VersionComments ="FoxProaplicativoVisual"
.VersionCompany ="KirtlandAssociates,Inc"
.VersionDescription=""
.VersionCopyright =ALLTRIM(STR(Year(Date())))
.VersionTrademarks =""
.VersionProduct =ALLTRIM(tcSystem)
.VersionLanguage ="Ingls"

*RAS05Oct1999AdicionadoaconexoProjectHook.
*Devemestarnestaordem,bibliotecadeprimeira,segundaclasse
*Casocontrrio,serexibidoumdilogoeasfalhasdoassistente
.ProjectHookLibrary=CcPROJECTHOOKSLIB
.ProjectHookClass =ALLTRIM(tcProjectHook)

*Oprogramaprincipalprecisaseradicionadoprimeiroatornarse
*Oconjuntoprincipalparaoprojeto
lcFile=tcProjectDir+"programas\"+tcProjPrefix+"Main.prg"
FAZERCOMAddFileToProjectlcFile

*Adicionecontinerbancodedados
lcFile=tcProjectDir+lcDatabaseDir+tcProjPrefix+".dbc"
FAZERCOMAddFileToProjectlcFile

*Adicionealgumasmesaslivres
lcFile=tcProjectDir+"sistema\"+tcProjPrefix+"Config.dbf"

Captulo15:ObjetosdoprojetoeProjectHooks487
FAZERCOMAddFileToProjectlcFile

*AdicioneasclassesdebancodedadosToolkitStonefield
lcFile="K:\VfpAddOn\Stonefield\SDT\Source\DbcxMgr.vcx"
FAZERCOMAddFileToProjectlcFile

lcFile="K:\VfpAddOn\Stonefield\SDT\Source\SDT.vcx"
FAZERCOMAddFileToProjectlcFile

*RAS27Sep1999AdicionadoomodeloConfig.fpw
lcFile=tcProjectDir+"text\"+"Config.fpw"
FAZERCOMAddFileToProjectlcFile

*Certifiqueseoarquivodeconfiguraoestincludo
_vfp.ActiveProject.Files("Config.fpw").Excluir=.F.

*RAS27Sep1999AdicionadoomodeloReadMe.txt
lcFile=tcProjectDir+"text\"+"ReadMe.txt"
FAZERCOMAddFileToProjectlcFile

*Certifiqueseoarquivodeconfiguraoestincludo
_vfp.ActiveProject.Files("ReadMe.txt").Excluir=.T.

*CrieoprojetousandoaopodepuxarReconstruir
*Orestodosarquivosdeprojeto
llBuildResult=.build(1)
?"Oresultadodacompilaofoi:"+TRANSFORM(llBuildResult)+
"At"+TTOC(DATETIME())
ENDWITH
OUTRO
?"Criaodearquivodeprojetofalhoupor"+lcProjectName+
"At"+TTOC(datetime())
FIMSE

PROCEDIMENTOAddFileToProject(tcFileName)

Seoarquivo(tcFileName)
_vfp.ActiveProject.Files.Add(tcFileName)
?"Arquivoadicionado:"+tcFileName+"no"+TTOC(DATETIME())
OUTRO
?"Fileacrescentandoproblema"+tcFileName
FIMSE

RETORNA

*:EOF:*

Oobjetodoprojetodeconstruomtodopermitequevocfaaqualquerumadasopesdecompilao
desenvolvedorviadedilogoOpesdeconstruodoprojeto.Nsescolhemosoprojetodereformademodoqueo
disponveisao
arquivosdeprojetoseriapuxadocomonecessrioecadaarquivocompiladopelaprimeiravez.
restodo
Emgeral,esteprojectofoidivertidoedemonstrouopoderdeterumainterfaceabertapara
oambientededesenvolvimento.Tambmestnossalvandotempoedinheiroemcadaprojetoquetrabalhar.

488 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ProjectHookeProjecttruquesObjeto
Usaremosumavidareal,emProjectHookproduoquetemsidousadopeloautordesdeo
fimdoVFP6.0beta.NstambmirdemonstrarcomooobjetoProjectHookeprojetopode
serutilizadoemconjuntoumcomooutrocomumanovaferramentachamadaRASProjectBuilder.

ComoaumentarabasedeProjectHook
HvriosarquivosquecompemabibliotecadeclassesCPhkBase.PrimeiroaclassephkBase.este
classeumasubclassediretadoProjectHookVFP.sempreumaboaprticaparaconstruirseuprprio
cpiadasclassesVFPparaquevoctenhaumabaseparamelhoriasemumnveldeclasse
hierarquia.TodasasoutrasclassessoumasubclassedaclassephkBase(verFigura15.3).Nsadicionamos
algunsmtodosepropriedadesaestenvelquenssabiaqueseriatilparatodaa
ProjectHooksdesenvolvemos(verTabela15.2eTabela15.3)

Tabela15.2MtodosadicionadoaonossoProjectHookphkBasecomumabrevedescriodo
seuuso

Mtodo Descrio
Usadoparaexibirumamensagemparaodesenvolvedor.SelWaitMessageTrueumaespera
DeveloperMessage Janelaexibida,casocontrrio,amensagemenviadaparaoDEBUGOUT
janela.
GetPProp Retornaovalordapropriedadeenviadocomoumparmetro.Issopermitequeosdesenvolvedores
paraacessaraspropriedadesprotegidascomumainterfacesimples.
Lanamento Liberaoobjetoinstanciado.
SetProjectObjReference UsadoparaconfigurarapropriedadeProjectInfoaoActiveProjectsehouver.sim
humapossibilidadedequeumdesenvolvedoririainstanciarumProjectHooksemum
projeto.
ShellAdditionalInit UsadoparaestenderomtodoInit()semterdesubstituirocdigoInit()in
subclasses.ChamadoapartirdomtodoInit().
zzAbout Contmtodaadocumentaoespecficaparaaclasse.

Tabela15.3PropriedadesadicionadoaonossoProjectHookphkBasecomumabrevedescriodo
seuuso

propriedades Descrio
Construtor Oprograma(PRG)ouvisualclassebiblioteca/classname(VCX)queapontaparao
construtorparaaclassebaseadaemBuilder.dbf.
BuilderX AclassevisualqueapontaparaoBuilderBBuilderparaestaclasse.
cVersion Onmerodaversodaclasseespecfica.
lWaitMessage AlternaamensagensentreomododedesenvolvedorESPERARWindowsou
declaraesDEBUGOUT.
oProjectInfo Contmumarefernciadeobjetoparaasinformaesdoprojeto.

AspropriedadesconstrutoreBuilderXsopropriedadesqueosconstrutoresnativosVFPser
reconhecer.EstesganchosviracalharsevoccriarumconstrutorProjectHookclasse/programa.

Captulo15:ObjetosdoprojetoeProjectHooks489

ExistemduasoutrasclassesProjectHooknabiblioteca.OprimeirophkTestPems.este
classepropsitonavidaeratestaraspropriedades,eventosemtodosfornecidospeloVFP.Ns
utilizadoestaclassecomopartedociclobetaparaverificarqueestvamosrecebendooqueaMicrosoftfoi
propaganda.Noexistemmtodosoupropriedadesadicionais.HcdigoemcadaumdosVFP
Mtodosdeeventosquedisparaumamensagemusandooseguintecdigo:

THIS.DeveloperMessage(PROGRAM())

OlWaitMessagepropriedadedefinidacomotrueporisso,quandovocexecutarestecdigoquevocobterum
qualquermomentoumganchoacionadoquandoalgumaaoexecutadaapartirdoGerentedeProjeto.No
ESPERA
JANELA
realmentetil,masserveoseupropsitodetestarosdiferenteseventos.

Figura15.3CPhkBasebibliotecadeclassequemostraahierarquiadeclasseparao
ProjectHooks

ComocriarumProjectHookdesenvolvimentotil
Altimaclasse,phkDevelopment,averdadeiracarneeasbatatasdabiblioteca.Estaabasepara
tudoprojetarProjectHooksespecficos.EssaclassefornecealgumasfuncionalidadeschavequemuitosVFP
desenvolvedorestmdesejadoparaseradicionadoaoIDEnativo.Estaaverdadeirabelezada
extensoProjectHook.Elanospermiteadicionarfuncionalidadeparaoambientededesenvolvimento
semterqueesperarparaaMicrosoftparamoveronossopedidoparaotopodalistadeprioridades.este
conceitodemelhoriadodesenvolvimentodbrilhoaoVFPsobreoutrasferramentasdedesenvolvimento.Algunsdos
caractersticasqueimplementadasemphkDevelopment:

490 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

MapeamentoUtilitycampo
Limpezadeinformaesdaimpressoracodificadoemrelatrios
AuditoriadeProjetos(acompanhamentodeatividade)
capacidadedebackupdearquivos
Resultadosdocompilador/construirmensagensabarradestatusou WAITWINDOW
InstanciandobarradeferramentascomobotoparachamarRASProjectBuilder
Alterarodiretriopadroparaodiretriodoprojeto
Ajustarocostumecaminhoparaumcaminhodoprojeto

Cadaumadessascaractersticasprincipaisserodiscutidosnasseesaseguir.
Captulo15:ObjetosdoprojetoeProjectHooks491

Tabela15.4MtodosadicionadoaonossoProjectHookdedesenvolvimentocomumabrevedescrio
seuuso
do

Mtodo Descrio
cBuildMessageSetting_assign CertificaqueasatribuiesprpriasdocBuildMessageSetting
propriedadesofeitas.
cCleanReportPrinters_assign CertificaqueasatribuiesprpriasdoscCleanReportPrinters
propriedadesofeitas.
ChangeToProjectDirectory Alteraodiretriopadroparaodiretriohomedoprojeto.
ChangeToProjectPath AdicionaosdiretriosparaoPATHSETquesonecessriosparaoprojeto.
CleanReportPrinter IreliminarasinformaesdaimpressoracodificadonosmetadadosRelatrio
arquivo(.FRX).
FieldMappingDo Chamadoparaprocessartodasasverificaesdemapeamentodecampo,emseguida,executaoprocesso.
FieldMappingPropertyCheck Utilizadoparaverificartodasasconfiguraesdedesenvolvimentoparaaspropriedadesdemapeamentode
desteProjectHook.
campo
FieldMappingSet Usadoparadefinirasconfiguraesdemapeamentodecampoparaoregistro.
FieldMappingTableClose Usadoparafecharatabeladeopesmapeamentodecampo.
FieldMappingTableOpen Usadoparaabriratabeladeopesmapeamentodecampo.
ModifyFileBackup Usadoparacriarumtipodearquivobakdosarquivosdecdigofontequenotmessa
comportamentonativo.
ProcessReportFiles Chamadoapartirdomtododeconstruoparapercorrerosarquivoseprocessodequalquer
relatriosnecessriosantesdeconstruir.
ProjectActivate DisparadopeloaulasInit()mtodoparaprocessaritensquandooprojeto
abriuouactivado.
ProjectAuditDo Chamadoparafazercontrolosadequados,emseguida,chamaraaberturadoProjeto
tabeladeauditoria.
ProjectAuditSetSessionId InicializaapropriedadecSessionIdparaacapacidadedeauditoriaProject.
ProjectAuditTableClose Usadoparafecharatabeladeauditoriadeprojectos.
ProjectAuditTableCreate Utilizadoparageraratabelausadapelafuncionalidadedeauditoriaprojecto.
ProjectAuditTableOpen Usadoparaabrirtabeladeauditoriadoprojeto.
ProjectAuditTableReindex Usadoparareconstruirosndicesparaatabeladeauditoriaprojeto.
ProjectAuditUpdate Atualizaatabeladeauditoriaprojeto.
ProjectBuilderToolBarinit InstanciaabarradeferramentasRASProjectBuilderseeleoprimeiroprojetoaberto
eapropriedadelUseProjectBuilderTbdefinidocomoverdadeiro.
ProjectBuilderToolBarinit LiberaabarradeferramentasRASProjectBuilderseeleoltimoprojetodep
eexisteabarradeferramentas.

492 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Tabela15.5PropriedadesadicionadoaonossoProjectHookdesenvolvimentocomumabrevedescrio
dasuautilizao

propriedades Descrio
aErrorDetail[1,0] Umacoleodedetalhessobreoltimoerroparaocorrerduranteoprocessamento.
cBuildMessageSetting Contmadefiniotipodemensagem,"S"deestado(padro)e"W"esperar
janela.
cCaption ContmalegendaparaoMessageBox().
cCleanReportPrinters Contmoindicadorseosrelatriosnoprojetodeveteraimpressora
informaesesfregouapartirdosmetadados(.FRX).Asconfiguraesincluem"C"lean,
iew"V",ou"S"Kip(padro).
cDeveloper usadocomoumidentificadorparaoProjectHook.Istoparaousointernopela
rotinaRASProjectBuilder.
cFieldMappingCategory usadoparadefinirostiposdedadosdemapeamentodecampoparaasconfiguraesparaestacategoria
naTabeladeOpodemapeamentodecampo.
cFieldMappingTableAlias ContmoALIAS()utilizadoparaatabeladeopesmapeamentodecampo.
cFieldMappingTableDirectory Contmodiretrioparaatabelamapeamentodecampo.
cFieldMappingTableName ContmonomedatabeladatabelaOpomapeamentodecampo.
cFieldMappingVfpCategory Contmacategoriapadroparadefinirtodosostiposdedadosdemapeamentodecampopara
classesbaseVFP.
cOldNotify ContmoantigoSET('Notificar')pararesetdepois.
cOldStatusBar ContmoantigoSET("STATUSBAR")pararesetdepois.
cOldTalk ContmoantigoSET("falar")pararesetdepois.
cOldTalkWin ContmoantigoSET("falar,1')pararesetdepois.
cPathDirectories ContmosdiretriosadicionaisqueprecisamestarnoSETPATH.
cPathDirectories ContmosdiretriosadicionaisqueprecisamestarnoSETPATH.
cProjectAuditAlias Contmatabeladeauditoriaconjuntodealiasprojetoquandoatabelaaberta.
cProjectAuditDirectory ContmocaminhododiretrioparaatabeladeauditoriaProject.
cProjectAuditTable Contmonomedatabelausadapararastreareventosdoprojeto.
cProjectBuilderGlobalVariable onomedavarivelqueabarradeferramentasdoProjectBuilderinstanciadocomo.
cProjectBuilderTbClass ContmonomedaclassequeabarradeferramentasRASProjectBuilder.
cProjectBuilderTbClassLib ArmazenaonomedabibliotecadeclassesqueabarradeferramentasRASProjectBuilder
reside.
cSessionId ContmaIDdesessoexclusivaparaoprojeto.Estearmazenadona
TabeladeAuditoriadoprojetoparadeterminartodososeventosqueaconteceramemum
sesso.
lCreateBackupFile Quandoocdigofontemodificado,determinaseotipodearquivobakcriado
quenotemestecomportamentonativo.
lFieldMappingActive usadoparaterorecursodemapeamentodecampoativoparaoProjectHook.
lUseProjectAudit Determinaseascapacidadesdeauditoriadeprojectossoutilizadosparaestacorrente
projeto.
lUseProjectBuilderTb DeterminaseabarradeferramentasRASProjectBuilderinstanciadoquandoisso
classeinstanciado.
oRegistry EstapropriedadecontmumarefernciadeobjetomanipulaodoRegistro
objeto.

ComoteroProjectHookdefinirodiretrioatualecaminho
AntesdoProjectHook,cadavezqueabrimosumnovoprojeto,fomosforadosamanualmente
alterarodiretrioVFPpadroparaodiretriodoprojeto.Issofeitodemodoformasindividuais

Captulo15:ObjetosdoprojetoeProjectHooks493

podeserexecutadodeformaindependenteeaSETPATHencontrarcorretamentetodososarquivosnecessriospara
caractersticasqueestamosdesenvolvendo.Oautorgeralmenteatingeumameiadziadeprojetosacadadiaeisso
executaro
podesetornarbastantetedioso.
Muitosdesenvolvedorescriaramumprogramaparadefinirocaminho,odiretrioatualeoutros
configuraesambientaisantesdeabriroprojetocomuma PROJECTModificar...NOWAIT.Issono
maisnecessriodesdeoProjectHookpodeexecutaromesmotipodecdigodecadavezqueoprojeto
aberto.Ento,quaissoasvantagensentreumprogramaquefazissoeoProjectHook
instanciar?Humnmerodevantagens.Emprimeirolugar,noprecisadeumprogramapersonalizado
duplicadosparacadaprojetoumavezqueocdigoescritoumaveznaclasseProjectHookdemaisaltonvel.
Manutenominimizadopelodesignorientadoaobjetodaclasse.Emseguida,noh
hardcodingcaminhosnoprograma.OProjectHookusaodiretriodoprojetoqueestarmazenado
Jnoprojeto.Emterceirolugar,eupossousaroVFPIDEparaabrirprojectosenosepreocuparcomo
AlistacompletadeprogramasdeaberturadoprojetoestarnocaminhoVFPexistenteeparagarantirquens
abraoprojetocorreto.Esteumproblema,jqueamaioriadosdesenvolvedoresnomearoprojetodeabertura
programadeformaidnticaemprojetos.Ento,odiretrioestamos?Qualprojetovai
abrirquandoeucorroSetPath.prg?ComoProjectHookdesignadoparaoprojeto,sapertaro
menuArquivoeescolherumdosltimosprojectosemquetrabalheiousaltarparaajaneladecomandoe
executaro MODIFYPROJECTlinhadecdigoquejestl.Simples.
Ento,ocdigonecessrioparateressavantagem?Aquiestodoismtodosextradosforado
classephkDevelopmentquesochamadosapartirdoProjectActivatemtodo:

*PhkDevelopment.ChangeToProjectDirectory()
*Definaodiretriopadroparaacasadoprojeto
*Directoryparaasobraspathinggenricos
*OusejaSETPATHTOdados,formulrios,classes,grficos
IFTYPE("THIS.oProjectInfo")="O"E!ISNULL(THIS.oProjectInfo)
IF!EMPTY(THIS.oProjectInfo.HomeDir)
CD(THIS.oProjectInfo.HomeDir)
OUTRO
THIS.DeveloperMessage("configuraoDiretriodoprojetoestvazio...",.T.)
FIMSE
OUTRO
*Issonuncadeveriaacontecer,amenosquevocmanualmente
*CREATEOBJECT()daclassesemumprojeto.
THIS.DeveloperMessage("Refernciadoprojectonoestdisponvel",.T.)
FIMSE
*PhkDevelopment.ChangeToProjectPath()
lcOldPathLOCAL &&ReterantigaSETPATH

SE!ISNULL(THIS.cPathDirectories)E!Vazia(THIS.cPathDirectories)
IFVARTYPE(THIS.cPathDirectories)="C"
lcOldPath=SET("PATH")
lcNewPath=THIS.cPathDirectories

SETPATHTO&lcOldPath,&lcNewPath
OUTRO
THIS.DeveloperMessage("propriedadeDiretrioCaminhonoocarter")
FIMSE
OUTRO

494 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

*Noexistemrequisitosespeciaispathingparaesteprojecto
FIMSE

Humadesvantagemparaestemtodo.UmavezquenoexisteummtodoparaoprojectoActivar
quepodemosligarpara,estecdigosexecutadoquandoabriroprojeto.OProjetoRAS
ferramentaBuilderdiscutidomaisadiantenestecaptulotemumasoluoparaesteproblema.

ComocontrolarprogramaticamenteasdefiniesVFPIntellidrop
VisualFoxPro5.0introduziuoIntellidroprecursonativoparaoambientededesenvolvimento.
Quandoaconstruodeformaseclasses,vocpodearrastaresoltaritensdeDataEnvironment,um
projetoouDesignerdebancodedadosequandovocsoltlonodesigner,aclasseespecificadautilizada
aocriaroobjeto.Agrandevantagemdissoquevoccomeaaespecificarasclassesemvezde
usandoasclassesbasepadrodoVFP.AcapacidadeIntellidropgeridoatravsdaferramenta|Opes
dedilogonapginademapeamentodecampo.EstasdefiniessomantidasnoRegistrodoWindows.Voc
verimediatamenteosbenefciosdestafuncionalidade.maisumamaneiradepersonalizara
ambientededesenvolvimento.
Existemduasgrandesdesvantagensdestaaplicao.Aprimeiraaquelaqueimediatamente
percebiquesevocusarclassesdiferentesemdiferentesprojetos.Istopodeserdevidoaofactodequevoc
tmaulasquadrosubclasseparacadaprojeto,oupodeserquediferentesclientestm
cdigofontedequadrosdiferentes.
OsegundoofatodequeessasconfiguraessoarmazenadasnoRegistro,quemquina
especfico.Sevoctivervriosdesenvolvedorestrabalhandonomesmoprojeto,cadaumtemquepassarpor
otediosoprocessodedefinirasconfiguraesdemapeamentodecampoparaoprojeto.Istocomplicadopela
ofatodequeamaioriadosdesenvolvedoresestotrabalhandoemvriosprojetos.Sevocesttendoproblemascom
umamquinaequerpularparaoutramquinanarede,voctemquepassarpor
eredefiniressasconfiguraesparaqueamquina.
Issopodesermaisdoqueumagravamento.Felizmente,existeumasoluoquepodeser
desenvolvidacomumprogramaouumProjectHook.VFPguruJohnPetersencompartilhouumaferramentaque
desenvolvidachamadoOptUtility.Estaumaformasimplesedacombinaotabelaquearmazenadiferente
configuraesparatodasasclassesdebaseVFP.Eleexecutatodasasoperaesdemanutenoe
escrevediretamenteparaeapartirdoregistoparamapearessasconfiguraes.Vocexecutaroformulrio,selecioneo
agrupamentodeprojeto,eapertarumbotoparaatualizaroregistro.Estaumaferramentalegalqueeuusootempotodo.
Anicaquestoqueeuprecisolembrarparairapertaroboto.Estaocasionalmenteesquecido
eeurecebopolinizaocruzadadebibliotecasdeclassesemmeusprojetosdiferentes.
Captulo15:ObjetosdoprojetoeProjectHooks495

Tabela15.6OptUtil.dbfmesalivrequearmazenaasinformaesdemapeamentodecampousadoem
aporoIntellidropGestordoProjectHookphkDevelopment

Campo Nome Digitar TamanhoDescrio


1 configurao C 20,0 Esteonomedaconfigurao.Nspreencheristocomum
derefernciaqueestligadaarepresentaroprojeto.
2 Digitar C 20,0 EsteonomedoobjetoclassebaseVFP.
3 NomedaclasseC 50,0 EsteonomedaclassequeestdefinidonoRegistroparaa
classebaseVFPnaseodemapeamentodecampo.
4 ClassLoc C 254,0 Estaabibliotecadeclasses(comfullpath)ondeaclasse
designadoemqueresideacolunaClassName.

AprimeiravezqueviVFP6.0eosProjectHooks,viimediatamenteousoda
ProjectHookparaatualizaroregistrocomasinformaesmapeadasnatabeladeOptUtility.Desde
oProjectHookinstanciadoquandooprojetoforaberto,poderamosligarparaainicializao
processoeexecutarcdigoparamapearclassesparaoregistro.OcdigoparaissoencontradoemListagem15.3.
IssoeliminouanecessidadedeselembrardeexecutaroOptUtilitycadavez.Adesvantagemdisto
quenohnenhumprojetoActivatemtododisponvel,porisso,sevocpularprojectosouabriroutra
projeto,vocvaiteronovomapeamentoetmosmesmosproblemaspotenciaiscomoesquecerde
executaroutilitriodemapeamento.

Listagem15,3EstecdigoencontrasenomtododaFieldMappingSet
phkDevelopmentProjectHook.EstecdigomapeiaasconfiguraesIntellidropparaWindows'
Deregistocombasenoagrupamentoseleccionado.

*RazesRegistro(rasgadaforadoVFP98\FFC\Registry.h)
#DEFINEHKEY_CLASSES_ROOT 2147483648&&BitSet(0,31)
#DEFINEHKEY_CURRENT_USER 2147483647&&BitSet(0,31)+1
#DEFINEHKEY_LOCAL_MACHINE 2147483646&&BitSet(0,31)+2
#DEFINEHKEY_USERS 2147483645&&BitSet(0,31)+3

lcIntellidropKeyLOCAL &&VFPOpesdoRegistroChaveparaIntellidrop
lnOldSelectLOCAL &&Salveovelhoworkarea

*ApenasprocessarasentradasderegistroseoobjetoRegistryinstanciado
SE!ISNULL(THIS.oRegistry)
*ConstruiraprimeirapartedachavederegistoparaIntellidrop
lcIntellidropKey="Software\Microsoft\VisualFoxPro\"+
_VFP.VERSION+
"\Options\Intellidrop\FieldTypes\"

lnOldSelect =SELECIONAR()
lcFieldMapAlias
=THIS.cFieldMappingTableAlias

*Obtertodasasdefiniesdeclasseparaoprojeto
SELECT*
De(lcFieldMapAlias)
ONDEconfig=ALLTRIM(THIS.cFieldMappingCategory)
INTOCURSORcurSetReg

lnRecords=_TALLY

496 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

IF_TALLY=0
THIS.DeveloperMessage("Nohregistrosdeclassecampomapppingcom"+
Processoparaa"+
ALLTRIM(THIS.cFieldMappingCategory))
OUTRO
*Atualizaroregistro
SCAN
*EstaaconfiguraoVisualClassLibrary
THIS.oRegistry.SetRegKey("ClassLocation",
ALLTRIM(curSetReg.ClassLoc),
lcIntellidropKey+ALLTRIM(curSetReg.Type),
HKEY_CURRENT_USER)
*Esteoconjuntodeclasserealparaaclassebase
THIS.oRegistry.SetRegKey("ClassName",ALLTRIM(curSetReg.ClassName),
lcIntellidropKey+ALLTRIM(curSetReg.Type),
HKEY_CURRENT_USER)
THIS.DeveloperMessage(ALLTRIM(curSetReg.Type)+
"Definidocomo"+
ALLTRIM(curSetReg.ClassLoc)+"::"+
ALLTRIM(curSetReg.ClassName),
.T.)
ENDSCAN
FIMSE

*Fecheocursortemporrio
USOEMcurSetReg

SELECT(lnOldSelect)
OUTRO
THIS.DeveloperMessage("objetodeRegistronoinstanciado")
FIMSE

*NocasodeasmensagenssoenviadasparaoWindowWAIT
ESPERAAPAGAR

Francamenteesterecursopodesalvarumaquantidadeenormedetempo,sevocestconstantementeamudar
projetoscomooquefazemos.Sevoctrabalhanomesmoprojetootempotodoouusarapenasumconjuntodebasede
aulasparatodososseusprojetos,estapartedoProjectHookserpraticamenteintil.Vocpode
desativaresserecurso,definindoolFieldMappingActivepropriedadepara .F..

ComoremoverasinformaesdaimpressoraapartirderelatriosVFP
HouveumaabundnciadeescritosnosvriosfrunsonlineepublicaesFoxProsobre
orelatriodemetadadosreterinformaesdaimpressoradedesenvolvimento.Istopodecausarumnmerode
apoiarproblemasemumaplicativodeproduo,seoclientenotemasmesmasimpressoras.
Houvevriassoluesparaodesenvolvedorparaesteproblema.Amaioriasoescritascomoum
programaqueverificaoarquivodeprojeto(.pjx),abreosmetadadosderelatrioe,emseguida,limpaa
TageTag2colunasdoprimeiroregistro.SteveSawyerpassouaolongodeumamelhor
programasqueexecutaesteservio.Euincorporeiessecdigo,juntamentecomSteve
melhorias,paramodificarseletivamentecertasinformaesnacolunaExprdoprimeiroregistro
nosmetadadosdorelatrio.
OcdigoparaexecutaralavagemestlocalizadonoCleanReportPrintermtodono
ProjectHook,quechamadopelosProcessReportFiles.OCleanReportPrintercdigolimpa

Captulo15:ObjetosdoprojetoeProjectHooks497

asespecificidadesdaimpressoraemumarquivoderelatrio.Talcomoacontececomtodasascaractersticasdo
Orecursopodeserligadoedesligado.IstoconseguidocomocCleanReportPrinterspropriedade.
phkDevelopment,o
Hvriasconfiguraesdisponveis."Clean"farcomqueodepuradorparafazerotrabalho,"View"
executaras WindowWAITmensagensseo ELSElgicauncommented(atumamelhor
implementaofeita),e"Passar"irignoraroprocessotodosjuntos.

Listagem15,4EstecdigoencontrasenomtododaCleanReportPrinter
phkDevelopmentProjectHook.EstecdigoapagaatageTag2camposdoprimeiro
registronoarquivoderelatriodemetadados.detalhesselectivosdacolunaExprdoprimeiro
registrotambmsoremovidos.
*Osrelatriostmomauhbitodeguardarinformaesdaimpressorana
*Primeiroregistrodemetadadosrelatrio.Estarotinaseletivamente
*Removealgumasdasinformaesdeimpressoracodificadodemodoqueosusurios
*Podeusarimpressorasdiferentesdoqueaequipededesenvolvimento,semproblemas.
LPARAMETERStcFrx2Chk,tcAction

*?AindaprecisadechegaraalternativaparaainformaoVerrelatrio

*ParmetroVerifique
IFVARTYPE(tcAction)!="C"ouvazio(tcAction)
This.DeveloperMessage("parmetroderelatrioestavavaziadotipodedadosincorreto")
RETORNA
FIMSE

IFVARTYPE(tcAction)!="C"
tcAction="VIEW"
FIMSE

*Passeparaonegciodomtodo
This.DeveloperMessage(Proper(tcAction)+"ingReport:"+tcFrx2Chk,.T.)
*Verifiqueseorelatriodeexistir
Seoarquivo(tcFrx2Chk)
USE(tcFrx2Chk)ALIAScurFrx2ChkEXCLUSIVE
OUTRO
This.DeveloperMessage(tcFrx2Chk+"noexiste.")
RETORNA
FIMSE

*Verifiqueseorelatrioabriumanipuladorbem(casocontrrioerroapenas
*Exibidaumamensagemeavidaseguiuemfrente).
SE!USADO("curFrx2Chk")
RETORNA
FIMSE

LOCALIZAR

*Lidarcomocampodeexpresso
IF!EMPTY(curFrx2Chk.Expr)
IFUPPER(tcAction)=="limpa"
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[DEVICE],[*DEVICE])
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[motorista],[*DRIVER])

498 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[OUTPUT],[*OUTPUT])
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[default],[*DEFAULT])
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[PrintQuality],[*PrintQuality])
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[yresolution],[*yresolution])
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[TTOPTION],[*TTOPTION])
SUBSTITUIRcurFrx2Chk.ExprCOM
STRTRAN(curFrx2Chk.Expr,[DUPLEX],[*DUPLEX])
This.DeveloperMessage(tcFrx2Chk+"colunaExpr:limpo",.T.)
OUTRO
*This.DeveloperMessage(tcFrx2Chk+"colunaExpr:"+curFrx2Chk.Expr)
FIMSE
FIMSE

*LidarcomoTagcampo
IF!EMPTY(curFrx2Chk.TAG)
IFUPPER(tcAction)=="limpa"
SUBSTITUIRcurFrx2Chk.TAGCOMESPAO(0)
This.DeveloperMessage(tcFrx2Chk+"Tagcoluna:limpo",.T.)
OUTRO
*This.DeveloperMessage(tcFrx2Chk+"Tagcoluna:"+curFrx2Chk.Tag)
FIMSE
FIMSE

*PegaocampoTag2
IF!EMPTY(curFrx2Chk.Tag2)
IFUPPER(tcAction)=="limpa"
SUBSTITUIRcurFrx2Chk.Tag2COMESPAO(0)
This.DeveloperMessage(tcFrx2Chk+"Tag2coluna:limpo",.T.)
OUTRO
*This.DeveloperMessage(tcFrx2Chk+"Tag2coluna:"+curFrx2Chk.Tag2)
FIMSE
FIMSE

*Agoraembalarparatercertezadequevocnoficarmemoinchao
IFUPPER(tcAction)="limpa"
PACOTE
FIMSE

*Fecheorelatrio(FRx)
Seutilizados([curFrx2Chk])
USOEMcurFrx2Chk
FIMSE

ESPERAAPAGAR

RETORNA

EstarotinachamadaapartirdoProjectBuilderRASquediscutidomaisadiantenestecaptulo.
Norecomendvelexecutaresteparacadacompilao,umavezquenonecessrioparaodesenvolvimento
ambiente,amenosquevocimprimiremmaisdeumaimpressoranoescritrio.Estateoriapodenoseaplicar
seorelatriofoidesenvolvidocomumaimpressoraquediferedeimpressorapadrodoWindows.Em
Captulo15:ObjetosdoprojetoeProjectHooks499

Poroutrolado,altamenterecomendvelparaexecutarestarotinanociclodeacumulaodeproduo
antesdeenviloparaumsitedocliente.

ComocontrolaroquefeitodentrodoGerentedeProjeto
Vocjseperguntouquantasvezesvocalterouumarquivoespecficoouquemfoialtimapessoa
quetocouabibliotecadeclassescrtica?HumaabundnciadeopesquandosetratadeFonte
Controlequelhedarestasestatsticas.VFPfuncionacomprovedoresdecontroledeorigemque
emconformidadecomaFonteApplicationControlProgrammerInterface(API).Masoquesenoofizer
teressescontrolesimplementadosemseuescritrio?Esevocqueriasaberquantasvezes
vocabriuumprojetoouconstruiuocdigo?Oquevocpodefazer?Umaopoimplementaroqueeu
chamamde"trilhadeauditoriadoprojetopobredesenvolvedor".
HumasriedemtodosquesoexecutadosquandooseventosProjectManagersoacionados.
CadaumdestesmtodostemdeeventodeumachamadanamesmaparaoProjectAuditUpdatemtodo.Aquiesto
nadeProjectHookQueryModifyFilemtodo:
cdigo
THIS.ProjectAuditUpdate("arquivomodificado",toFile.Name+
IIF(VAZIO(tcClassName),"","("+tcClassName+")"))

importantenotarque,seesserecursonodesejada(comose<g>),vocpodealternara
lUseProjectAuditpropriedadepara .F..

Listagem15,5EstecdigoencontrasenomtododaProjectAuditUpdate
phkDevelopmentProjectHookeinsereumalinhaemumaVFPlivretabelaespecificadapelo
propriedadecProjectAuditTable

LPARAMETERtcActivity,tcParameter

IFTHIS.lUseProjectAudit
IFPCOUNT()<2OUVARTYPE(tcParameter)!="C"
tcParameter=""
FIMSE

*Sempreverifiqueseatabelaabertaporcausadapossiblility
*DeeleserfechadoatravsdeumprximomesasoudadosFecharapartirdo
*JaneladeComando
SE!Utilizados(THIS.cProjectAuditAlias)
THIS.ProjectAuditTableOpen()
FIMSE

*VejaoProjectAuditTableCreate()mtodoparaalistadecampos
INSERTINTO(THIS.cProjectAuditAlias)
VALUES(LOWER(JUSTPATH
(THIS.oProjectInfo.Name)),

JUSTFNAME(THIS.oProjectInfo.Name),
tcActivity,
tcParameter,
THIS.cSessionId,
DATAHORA())
FIMSE

500 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Agoraquetodososganchosdeeventosestoenchendoamesa,oquevocpodefazercomeles?Mesmose
nohcontroledecdigofontenolugar,nsgostamosdeverquandooarquivofoimodificadomaisrecentemente
noservidor:

SELECIONEcProjFileAScName,
APRD(mFileName,60)ASCFILE,
cSessionId,
MAX(tUpdated)
DEprojectaudit
ONDEcActivity="Modificado"
E"Program1.prg"$mFileName
GROUPBYcProjFile,CFILE
INTOCURSORcurTemp

Nstambmpodemosverquantasvezesumprojetofoiaberto:
SELECIONEcProjFileAScName,
COUNT(*)ASnCount
DEprojectaudit
ONDEcActivity="aberto"
GROUPBYcProjFile
INTOCURSORcurTemp

Estessoexemplostriviais,claro,masosdetalhesestolnatabelaparaoseuarquivo
edesenvolvimentodecdigoSQLoquefazemosparaganharavida,entoaproveite.

Comogerarcpiasdeseguranaautomticasdemetadados
VisualFoxProgeraumarquivodebackupquandoumdesenvolvedormodificaumarquivodeprograma.Oarquivo.bak
geradoquandooprogramamodificadoguardado.NemtodosVFPobjetosobteresserecursodesegurana
quandomodificado.Ento,umdesenvolvedordeixadopendurado?Obviamentequeno,umavezqueestamosescrevendo
tpiconestecaptulo<risos>.OphkDevelopmentProjectHookexemploaproveitao
sobreisso
QueryModifyFilemtodoparachamarocostumeModifyFileBackupmtodo.Essecdigocopiaos
arquivosdemetadadosantesdeprosseguirparaodesignerdeescolha.Devenotarsequeoficheiroest
copiado,mesmoseodesenvolvedorsalvanenhumaalteraododesigner.
OcdigonaListagem15.6foiagarradoforadaFoxWiki,queestlocalizadona
www.Fox.Wikis.com.VFPguruJimBoothpostounestabasedeconhecimentoincrvel.este
cpiasderotinatodososdiferentesarquivosdemetadadosparaumarquivoseparadochamadoomesmo,mascomuma
extensodiferente.Assimcomoalimitaodoarquivodebackupprograma,apenasumnveldeapoio
retida.

Listagem15,6EstecdigoencontrasenomtododaModifyFileBackup
phkDevelopmentProjectHook.Estecdigocopiaosdiferentesarquivosdemetadadosaum
arquivodebackupquandoelessomodificados.

LPARAMETERSTOFILE

*Apenasprocesso,seoprojetorequeressafuncionalidade
IFTHIS.lCreateBackupFile
*Continueeprocessarobackup

Captulo15:ObjetosdoprojetoeProjectHooks501

OUTRO
RETORNA
FIMSE

lcFileLOCAL &&Tabelademetadadosdoarquivo
lcFptLOCAL &&Arquivodememorandometadadosassociados
lcBakLOCAL &&Nomedacpiadeseguranaparaatabela
lcFptBakLOCAL &&Nomedobackuoparaomemo
lcOldSafetyLOCAL &&SalveaconfiguraopararedefinirSegurana

lcOldSafety=SET("SAFETY")
lcFile =UPPER(toFile.Name)
lcBak =SUBSTR(lcFile,1,LEN(lcFile)3)+"SCT"

OFFSEGURANASET

*NohnecessidadedelidarcomasPRGs,DBFsdesdequeobtenham
*Backupnativamente
DOCASO
CASODIREITO(lcFile,3)="SCX"
lcFpt =SUBSTR(lcFile,1,LEN(lcFile)3)+"SCT"
lcBak =SUBSTR(lcFile,1,LEN(lcFile)3)+"SXK"
lcFptBak=SUBSTR(lcFile,1,LEN(lcFile)3)+"STK"

CASODIREITO(lcFile,3)="VCX"
lcFpt =SUBSTR(lcFile,1,LEN(lcFile)3)+"VCT"
lcBak =SUBSTR(lcFile,1,LEN(lcFile)3)+"VXK"
lcFptBak=SUBSTR(lcFile,1,LEN(lcFile)3)+"VTK"
CASODIREITO(lcFile,3)="FRX"
lcFpt =SUBSTR(lcFile,1,LEN(lcFile)3)+"FRT"
lcBak =SUBSTR(lcFile,1,LEN(lcFile)3)+"FXK"
lcFptBak=SUBSTR(lcFile,1,LEN(lcFile)3)+"FTK"

CASODIREITO(lcFile,3)="MNX"
lcFpt =SUBSTR(lcFile,1,LEN(lcFile)3)+"MNT"
lcBak =SUBSTR(lcFile,1,LEN(lcFile)3)+"MXK"
lcFptBak=SUBSTR(lcFile,1,LEN(lcFile)3)+"MTK"

CASODIREITO(lcFile,3)="LBX"
lcFpt =SUBSTR(lcFile,1,LEN(lcFile)3)+"LBT"
lcBak =SUBSTR(lcFile,1,LEN(lcFile)3)+"LXK"
lcFptBak=SUBSTR(lcFile,1,LEN(lcFile)3)+"LTK"

DEOUTRAFORMA
SETSAFETY&lcOldSafety
RETORNA
ENDCASE

Seoarquivo(lcBak)
APAGARARQUIVO&lcBak
FIMSE

Cpiadearquivo(lcFile)a(lcBak)

Senoforvazio(lcFpt)
Seoarquivo(lcFptBak)
APAGARARQUIVO&lcFptBak
FIMSE

502 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Cpiadearquivo(lcFpt)a(lcFptBak)
FIMSE

SETSAFETY&lcOldSafety

RETORNA

RASProjectBuilder
ORASProjectBuilder(frmProjectBuilderemCPhkBase)umacombinaodoVFP
dedilogoCriarprojeto,odilogoCriarVersoeacaixadedilogoInformaessobreoprojeto.Quantos
vezesvocfezessaltimacompilaoproduodeouroedescobrirquevocseesqueceudedefinirDebug
CdigooffnacaixadedilogoInformaessobreoprojeto,resultandoemumexecutvelde50megabytena500
CDsqueforamapenascortar?Estedilogotraztodasasconfiguraesdocompiladorjuntosparaquevocpodeconstruir
oexecutvelcomtodasasinformaesnafrentedevocaomesmotempo.
importantenotarquehvriosrecursosdoRASProjectBuilder(veja
Figure15.4)quefuncionamemconjuntocomoProjectHookRAS,masnonecessrio.Defato,
noexistequalquerrequisitoparaqualquerProjectHookemtudo.Anicaexignciaqueumprojeto(ou
mais)devemestarabertas.
RecursosquenoestodisponveissemoProjectHookRASsodeAuditoriadoProjetoProcesso
checkboxTrail,oInformaesdaimpressoraLimpeacaixadeseleoRelatriosecaixadetexto,oProjeto
Ativecommandbutton,aredefiniocommandbuttonmapeamentodecampoemapeamentodecampo
pginanopageframe.Orestodasopesestodisponveisparatodososprojetos.
Ento,oqueesteprodutotemavercomaseoProjectHookdestelivro?tem
vriosexemplosdecdigodentrodessaferramentaquedemonstramoobjetodeprojeto,osProjectHooks,
easpropriedadesdevrioseventos,mtodosequelhesestoassociados.
Captulo15:ObjetosdoprojetoeProjectHooks503

Figura15.4ORASProjectBuilderemao.Noteseatecla"PB"adicionado
barradeferramentasnapartesuperiordatela.EstebotoinstanciadoquandoophkDevelopment
(Ousubclasse)ProjectHookinstanciado.

Existemmuitopoucosmtodosdoobjectodoprojecto,masaproveitaestautilidadetantodo
maisimportantes.Oprimeirooobjetodoprojetodeconstruomtodo.Noprimeiro,utilizoua BUILD
comando,masexistemalgunsrecursosnosuportadospelocomandoquesosuportadospela
Mtodo.Omtododeconstruosuportamostrandooserrosdecompilaoquandoaconstruoestconcludae
eletambmlidacomsuporteparaaregeneraodeIDsdecomponentesparaasdiferentesopesdeservidorCOM.
OsegundomtodoutilizadooLimpomtodo.Estemtodoembalaoarquivodemetadadosdoprojeto.
EstaopopodeseracessadanomenuVFPProjetotambm.
Vriaspropriedadesdoobjetodoprojetosoacessadosedemonstradoatravsdesteutilitrio.Todos
informaessobreaversoqueestsentadonapginaversoacessadoatravsdoVersionComment,
VersionCompany,VersionCopyright,VersionDescription,VersionLanguage,VersionNumber,
VersionProducteVersionTrademarkspropriedades.AcapacidadededefinirnoincrementoAuto
VersoestvinculadoaoAutoIncrementpropriedade,ocriptografadosexecutvelaocriptografados
propriedade,eoCdigodedepuraodefinindoaoDebugpropriedade.OnomeProjectHookeclasse
soexibidasnapginaSobreesoacessadasatravsdoProjectHookClasse
ProjectHookLibrarypropriedades.OmesmovaleparaoProvedordeCdigoFonteatravsdoSCCProvider
propriedade.
504 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OgrupodeopodealternnciadeDesenvolvimento/Produoimportantefalarsobretambm.
opodeproduopadroparaaconstruoderecompilartodososarquivos,errosdeexibio,econfigurao
relatriosparaserlimpodepossveisinformaesdaimpressoradedesenvolvimento.Nsdeterminamosqueestas
configuraessomelhoresparaonossoambientededesenvolvimento.AdefiniodeProduotambmfazum SET
STRICTDATETO1paraquenohajamensagensambguasdeentradadedatadousurionaproduo
aplicao.AconfiguraodeDesenvolvimentofazoinversoefazum STRICTDATEdefinidopara2porisso,
soalertadosparaosproblemasY2Kquenossocdigopodeterintroduzidoinadvertidamente.o
configuraesdeDesenvolvimento/alternnciadeproduopodesersubstituda,definindoasatravsdo
interfaceapsescolherotipodeconstruoquevocdesejaexecutar.Porexemplo,sevocdesejodeno
mostrarerrosenolimparosrelatosdepossveisinformaesdaimpressoradedesenvolvimentoparaa
construoproduo,apenascliquenascaixasdemodoareflectirosseusdesejos.
Temossidosucessousandoessaferramentadesdeofinalde1999.Eletem,naturalmente,ido
atravsdealgumasmelhoriasatravsdesugestesdotestadorbeta.Estamoscolocandoono
domniopblicoparaqueoutrospossambeneficiardesteutilitrioprtico.Notemnenhumagarantia,emqualquer
caminhoefoioriginalmentedesenvolvidocomoumaferramentadeaprendizagem,mascomotempoeletomouumavida
comomuitasferramentasparadesenvolvedores.AfonteestincludonoDeveloperbaixararquivosdisponveisem
prpria
www.hentzenwerke.com.

Concluso
AsferramentasdegerenciamentodeprojetossobastanteinclusivenoVisualFoxPro.Quandovoctoparcomum
limitao,provvelquevocsercapazdeconstruiroseuprprioramalatravsdeumProjectHookoudeoutra
desenvolvedordaferramenta,comofizemoscomoRASProjectBuilder.Esperemosqueestecaptulolhetrouxe
algumcdigotilparaimplementaremseuambientededesenvolvimentoeaindamaisimportante
vaiinspirloparaconstruirferramentaseextensesqueiroreforaroVFPIDEeseu
experinciaemdesenvolvimento.

Captulo16:Criaoderelatrios 505

Captulo16
criandoRelatrios
"amesmacoisadecadavezcomoprogresso.Primeiroelesteignoram,depoiselesdizemquevoclouco,
emseguida,perigoso,entohumapausaeentovocnopodeencontraralgumquediscordadevoc".
(TonyBenncitadoem"TheObserver",Londres,06deoutubrode1991)

desenvolvedoresVisualFoxPronotiverammuitomotivosparafestejaremdesdeantesdolanamentodo
VisualFoxPro3.0quandosetratadeterumestadodadesignerderelatrioart.Arealidade
dedesenvolvimentodesoftwarequeosrelatriossocruciais.Osrelatriossoutilizadospelosnossos
paraanalisarosterabytesdedadosqueasaplicaesacompanhar.podemserutilizadasestassadas
clientes
simplesmentelembrarousuriodenmerodetelefonedochefe,ouparapermitirqueoCEOparadecidir
umaimportantefusobilionria.porissoqueoprocessodecriaoderelatriosto
sobre
importanteeporqueosdesenvolvedoresVFPprecisadeumsacogravedetruquesquandoalavancaro
boaoleReportDesigner.

Ofocoprincipaldamaioriadasaplicaesdebancodedadosarmazenarinformaesimportantesque
fundamentalparaaspessoasqueusamossistemas.Oseguintefuncionalidademaiscrticooprocessode
resumirerelatarasinformaesparaquepossaserusadopelaempresaparatomardecises
combasenosdadosqueregistado.
Euouvidesenvolvedoresexperientesdizemqueamelhormaneiradecriarrelatrioscontratar
algumquegostadefazlas.Elesflatoutnoquercriarrelatrios.Nopassado,temos
desenvolvedoresouviudizercoisascomo"Eunofaodados",masultimamenteestamoscomeandoaouviro"euno
fazerrelatrios"mantra.Asadadedadosoobjetivodamaioriadasaplicaes.Algunsclientesquerem
sadaelaboradaquepodeserusadoparapublicarumlivrooufolhetodevendas,outrossprecisamdeum
Listadosltimosnmerosdevendasparagarantirqueosobjectivosestoasercumpridosdiariamente.Francamente,
adorafazerrelatrios.Osrelatriossoaalmadosclientesquetrabalhamparaenstemosgrande
esteautor
prazerquandoosdadosbrutossotransformadoseminformaesquepermitequeosclientes
analisaroseunegcio.
Asadadeumaplicativoumtimolugarparacomearaoprojetarumnovoaplicativo.
Quandonossentamoscomumclienteparainiciarrequisitosrecolherinicialmenteperguntaroquea
objectivodosistemaparaocliente.Oprximopassodefinirosrelatrioseasadaeles
precisogerareanalisar.Vocdeveestarseperguntando,porquecomearcomosrelatrios?Ocliente
indicandoasdiferentesentidadeseatributoscomoelesdiscutirassadas.Estesfacilmentetraduzira
Oselementosdedadosdomodelodedados.
OverdadeirotruquefazeratoroVFPRelatrioDesignerseporsuavez,nasdireesquea
osclientesprecisam.Estecaptulovaiabordaralgumastcnicasbsicaseinteressantesparaajudlo
geraralgunsdosrelatriosqueosclientesexigem.
importantenotarnestemomentoquemuitasdassugestesapresentadasnestecaptuloaplicamsea
ambososrelatrioseetiquetas.HmuitassemelhanasentreorelatrioeMarcademoda,
quasecomoseelessoomesmocdigointernamente.Vemosduasdiferenassignificativasentreo
designers.OprimeiroodilogoNovaetiquetaapresentadoparaumnovortuloquelistatodososAvery
formatosdeetiquetasdisponveisparaseleo.Asegundadiferenaamaneirapadropginasso

506 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

definidodentrodoarquivo|ConfiguraodaPgina...dilogoquandonovosrelatriosertulossocriados.Relatrios
padroparaimprimirapginadeimpresso,enquantoosrtulospadroparaaimpressoemtodaapgina.
TodasasamostrasapresentaramnestecaptulopodeserencontradanoprojectoCH16.pjx.Todos
AmostrasderelatriopodeserexecutadodeformaCh16Rpts.

Figura16.1AformaCh16Rptsdemonstratodasasamostrasedicasdiscutidos
aolongodestecaptulo

Regrarelatrio#1
AregranmeroumparaaobtenoderelatosdesucessonoVFPdeixarVisualFoxProfazeroque
fazmelhor,quemanipularosdados.UsandotcnicascomprovadascomoSQLSelectsoumesmo
algunscomandosdeidadedadosXbasemodacomo SCAN...ENDSCANparaprocessarosdadosecriarum
cursorparaorelatrioparaoformatoumaprticaquetemfuncionadoporanos.EsteoKeepIt
metodologiasimplesSimon(KISS)quetemosutilizadoparaacriaoderelatrioscomoVFP
ReportDesigner.

tcnicasdeformatao
OpersonagemdeBillyCrystalFernandonoSaturdayNightLivecunhouafrase:"Nocomo
vocsente,comovocolha,eeuolhomaravilhosa."Istonopodeserditoosuficientequandosetrata
relatos.porissoquevamosabordaralgumasdasquestes"bonito"quenosajudaramaolongodo
anosepodemelhorarosrelatriosgerados.
Comoavelocidadedeimpressocomfontesdeimpressora
desenvolvedoresFoxProsemudouparaomundodoWindowsdevoltanosdias2.x.Umadasgrandes
VantagensdaversodoWindowsfoiainvenoderelatriosgrficoseacapacidadede
facilmenteterdiferentesfontes.Comesserecursorecmdescobertafoiumagrandetradeoff.relatriosgrficos
somuitomaislentosdoqueosseushomlogosdoDOS.Arazoparaistoqueaimagemenviadaparao
impressoraemvezdofluxoASCIIdoDOSrelatrios.Omesmoaindavlidohojeem
VisualFoxPro.

Captulo16:Criaoderelatrios 507

UmamaneiradeacelerarrelatriosgeradosapartirdoReportDesignerousodeimpressora
fontesespecficasnosrelatrios.Ento,oquefontessoosmelhores?Issovaidependerdeasimpressorasasua
osclientesestousando.Porexemplo,osnossosclientesparaamaiorpartetmpadronizadoem
HewlettPackardLaserJets.EstasimpressorastmCGTimeseUniversnativa.muitosdeimpressora
osfabricantesestoincluindofontesTrueTypeemmemria.

Comoparageraroefeitode"greenbar"(Exemplo:GreenBar.frx,
GreenBar2.frx)
Oefeito"greenbar"umretrocessoparaopapelquefoiusadonasimpressorasdealtavelocidade
tipicamenteassociadoscommainframesdeferrograndes.Odocumentotemalternandobarrasverdesebrancos
paraajudaraspessoasquelemorelatrioaseguirosdadosatravsdeumagrandefolhadepapel.
Criandoumfacsmiledepapelgreenbartosimplescomoimpressosombreadacamposretngulo.em
ImprimirQuandoalgica,cdigolugarsemelhanteaoseguinte:
MOD(RECNO(),2)=0

Figura16.2ControlandoaimpressoQuandodeumretngulosombreadonafaixadedetalhes
criaoefeitodebarverde

O MOD()funorecebeoprimeiroparmetro,dividepelosegundoparmetroe
retornaoresto.Nocdigoquetemosaqui,aimpressoquandoalgicaverdadequalqueroutroregistro
assimregistrosalternadosobterumfundosombreado.Aumentarosegundoparmetroparadiminuiro
frequnciadosombreamento.
Humasegundatcnica(demonstradonaamostraGreenBar2.frx)termltiplos
linhasdedetalheemordemconsecutivadetersombreamento.Estatcnicasegueamesmapremissacom
oretngulosombreadoeutilizaaimpressoQuandoquetemcdigosemelhanteaeste:

INLIST(MOD(RECNO(),6),4,5,0)

Oexemplodecdigoteroefeitodeimprimirtrsregistrossemsombreamentoseguidopor
trsregistroscomsombreamento.Aimplementaodicasimples.Primeirodescobrircomo
muitaslinhasdedetalhequevocquersombraedobrlo.Estenmeroosegundoparmetroda
MOD()funo.Orestodosparmetrosparao INLIST()funosoosrestosque
MOD()irretornar.Vocvaiprecisarfazermetadedosrestososparmetrosparaa
INLIST().Sequiserqueosombreamentorevertida,altereocdigonaimpressoQuando:
508 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

INLIST(MOD(RECNO(),6),1,2,3)

Elefuncionabemsevocremoverabordadoretngulosombreadonestasituao,casocontrrio,
vocterlinhasentrecadalinhadedetalhe.Seleodoretngulosombreadoemudando
otamanhodacanetapara"none"atravsdomenuFormatarpodefazerisso.
Pelanossaexperincia,recomendasereduzironmerodelinhasecaixasdoretnguloem
orelatrio,porqueelessodifceisdetrabalharcomumavezqueacolocaosobreorelatrioserdiferente
entreimpressoras.melhortestarumexemplosimplessobreasvriasimpressorasdeclientesantesde
estimarotempodedesenvolvimentodeumrelatriocomlinhasecaixasemtodoolayout.Tambmnossa
experinciaqueosombreamentopodemelhorarolayoutefazerobjetossedestacam.

Comogerarcaixasdeseleoemrelatrios(exemplo:Checks.frx)
Quantosclientesestoacostumadosaver .T.ou .F.Emumrelatrioparaumcampolgicoecomo
muitosdelesentenderasintaxelgica?Estamoscertodequehalgunsusuriosquepodemresponder
simaessa,masquantosdesenvolvedoresqueremexplicaroqueistosignificaparaumvicepresidenteda
GeneralMotors?
ParaeconomizarumpoucocaraeterqueescreverumapginadedocumentaoparaoDiretorde
RecursosHumanospodeexplicara .T.e .F.ValoreslgicosparaoVPdeRecursosHumanos,
odesenvolvedorvemcomumasoluosimplestransformarosvaloreslgicosempersonagens
aexpressorelatrio.Existemvriastcnicasquefuncionam:

IIF(lVisited,"Y","N") &&ExibeSimouNo
IIF(lVisited,"Sim","") &&Somentepositivosdeexibio
TRANSFORM(lVisited,"Y") Exibe&&"Y"ou"N"

Mesmoqueessasopessoteis,elesnososuficientementepicanteparaosolhosdeumVP.Entons
precisavirparacimacomumaoutraalternativa.Oquerealmentegrindsparaumdesenvolvedorexperienteum
declaraocomo"relatriosGee,oMicrosoftAccesstempoucoagradvelcaixasnosrelatrios,assim
comoomeuformulriodeentradadedados.VocestdizendoaplicativosdoVisualFoxPronopodefazerisso"?Talvezeu
deveriateromeusecretriopontapdeacessoabertoetmno."Comovocpodeimaginar,asoluo
muitofcilquandoumdesafioapresentadacomoeste<risos>.
Wingdingsparaoresgate!Vocusaumatcnicamuitoparecidacomaprimeiralinhadecdigono
amostrasqueacabamosdediscutir.Usandooimediatose( IIF),queimprimirumpersonagemdoWingdings
conjuntodecaracteresemvezdafontepadrodorelatrio.Entovocpergunta,comodiaboseuseiqueoASCII
valordaWingdingqueseparececom?Humappletquevemcomtodasasjanelas
sistemasoperacionaischamaromapadecaracteres(verFigura16.3).
Clicandosobreocarterdeescolhavaicoloclono"Caracteresareadecpia".o
miniaplicativotambmmostraovalorASCIIdopersonagemnocantoinferiordireitoquepodeserusadoem
combinaodeteclasALTparadesenvolvedorescomumaprefernciadoteclado.Irparatrsa
VFP,ecoleocaracterenacaixadedilogoexpressoderelatrionaparteapropriadado IIF
declarao(verFigura16.4).AlterarafonteparaoobjetoparaafonteWingdingsevocest
bomquantofeito.Figura16.5mostraorelatriodeexemplonomododedesigner,Figura16.6mostraa
relatrionomododevisualizao.

Captulo16:Criaoderelatrios 509
Figura16.3doWindowsminiaplicativoCharacterMapumaexcelentefontedegrficospara
serusadoemrelatrios(eformas),semopesodeumarquivogrfico

Figura16.4Umavezquevoccopiaropersonagemnomapadecaracteres,collonorelatrio
expresso

510 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura16.5DepoisdealterarotipodeletraparaWingdings,elevaifazerocdigoilegvelem
oReportDesigner.Eleaindalegvelnodilogoexpressoderelatrio.

Figura16.6Otrabalhofcilcomcaixasdeseleocompensacomumaaparnciaprofissional
relatrio

Devenotarseparaoregistroqueestatcnicatambmfuncionaparadadosexibidosemumagrade
eemformas.
Comoreduzir/aumentaroespaoembrancoaoimprimircamposdememorando
(Exemplo:WhiteSpace.frx/.prg)
Aquantidadedeinformaoapresentadaemcamposdememorandopodeconsumirmaispapeldoquens
gostar.Temosencontradoamaneiramaisfcildereduzirousodepapelemexcessoemrelatriosminimizaro
espaoembrancodecamposdememorandoaoimprimirorelatrio.Amesmatcnicapodeserutilizadapara
espaoduplolongascadeiasdetextotambm.
Estadicabastantesimples,umavezdimensionamentoobjetosumatarefacomumdesenvolvedorquando
relatriosdeconcepo.Apontaconcentraseaalturadoobjecto.NaFigura16.7,vemoso
objetomaisdireitamaiscurtadoqueamaisesquerda.Istofoiconseguidodimensionandoofundo
paracimacomoteclado.VocpodeusaromouseparafazerissoouumacombinaodateclaShift
almdecimaouparabaixoteclasdeseta.Otruquemoveraparteinferiordoobjecto,mesmocomalinha
aoladodeexpressodoobjecto.

Captulo16:Criaoderelatrios 511

Atcnicadecolagemdiscutidosnestaseosfuncionasevocfizer
notemSnaptoGriddefinidoparaorelatrio.SeSnaptoGridactivada,o
objetonoirfazerpequenasalteraesincrementaisparaotamanhodo
objetosimelevaifazeralteraesdetamanhoemrelaoaotamanhodagradedefinidoparao
relatrio.

Figura16.7EsteomododedesignerdedoiscamposnorelatrioWhiteSpace.frx.o
nicadiferenaqueoesquerdo"maisalto"eocaminhocertoera"encolheuse".

Oexatooposto,crescendoaalturadoobjetodopadroVFP,podedara
benefciodeespaoembrancoextraparadeixarespaoparanotasoumelhoraralegibilidadedorelatrio.
Achaveparaoespaoembrancoextranoesticarloapsosegundoindicadordelinha(sublinhado).
Estamesmapontapodeserusadaparaoespaoembrancodetalhelinhabem.Apenasencolhersetodososcampos
alinhaeremoveroespaoembrancoentreeleseabarradebanda.Issopodesalvarpginase
em
pginasderelatrioslongos.Tambmpodesignificaradiferenaentreaimpressodeumnicorelatriopgina
equeocupaapenasumpardelinhasnasegundapgina.

Comoexibirumcamponavisualizao,masdemodonoimprimir(Exemplo:
GreenBar.frx)
Semprequisincluircomentriosparaousuriofinalemumrelatrio,masnotlosaparecerem
oresultadofinalimpresso?Estepequenotruquepermitequeositensaservistonomododeprvisualizaoda
relatar,masnoinclulosnacpiaimpressadorelatrio.
IssofeitoadicionandoaseguinteimpressoQuandoacondioparaumobjetoderelatrio:

NOWEXIST("Imprimir...")

Aamostradocaptuloutilizadoorelatriogreenbar.Humanotaparaenviarorelatrioparao
presidentedogrupo.Elesaparecenomododevisualizao.
Outrarazo,podemosveresserecursosendotilpararelatriosqueimprimemseguro
emformao.Porexemplo,tomerelatriodeumgerentequelistaossalriosdosfuncionrios.
acessodeseguranadadoparaosusuriosautorizadosparaexecutarorelatrio.Seelesacidentalmenteimprimiro
denunciaraumaimpressoraemumareacbicaedepoistomarumtelefonema,eesquecerqueelesimprimiramo
relatrio,problemasbviospodeseguir.Osfuncionriossosusceptveisdevlo,enohaveria
problemasnoparaso.Paraevitaraimpressodainformaoseguraemtudo,vocpodeempregareste
tcnicaparaseprotegercontrapossveisproblemas.

Comominimizaradorusandolinhasecaixas(Exemplo:PeriodYtd.frx)
TemosditoduranteotempoquetemosusadoasversesWindowsdoFoxProeVisualFoxPro
queousodelinhasecaixasdeveserevitadosemprequepossvel.Arazoparaisto
simples,dependendodosdriversdeimpressoraouimpressoraenvolvidos.Aslinhastendematerum
menteprpriasobreondeelesqueremimprimiremumapgina.Ovaiflutuaraoredor,porvezes,
algunspixels,esvezespormais.Nsgostamosdereferirseaesteproblemacomoa"linhadeflutuao
512 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

sndrome".Ento,oqueestsafazerquandoperguntadoporumclienteparareproduzirumaformaqueparece
maiscomopapeldegrficodeumrelatriousadoparaanalisarumnegcio?Bastaseguiralgumasdasregras
temosdesenvolvido.
Jdissemosaregranmeroum,limitarousodelinhas.Issonosignificavoltar
parasublinharposiescomosinaldemenos.Usamoslinhasdesublinharosnossosttulosdepginae
liberalmenteuslosparasublinharoscabealhoserodapsGrupodediferenciarblocosdedetalhe.
Estestiposdelinhasnocausamadorquedescritonopargrafoanterior.Usoadequado
dalarguradacanetaeestilocanetavaimelhorarosrelatrios.
Regranmerodoisusaroobjetoderetnguloaocriarumacaixa.Herdamosuma
nmeroderelatrios,cadaumcontendoumacaractersticapeculiarosdesenvolvedoresoriginaisutilizadosquatro
linhas(emvezdeumretngulo)paraexibirumacaixa.Aprimeiravezquevocprecisaparaestenderacaixafeita
comlinhassersuficienteparatransformaroseucabelogrisalho.Realinharcadalinhaumtrabalhotedioso.Seo
relatriosofrede"sndromelinhadeflutuao,"issosserampliadacomodiferente
osladosdaformaflutuandoparalongeumdooutro.
Finalmente,seumalinhaverticaleusadoemvriasbandas,desenharumalinhaemtodasasbandasque
necessrio.Nuncatenteusarumalinhaseparadanocabealhodegrupo,abandadetalheedogrupo
rodap.Vocvaieconomizaraborrecimentosmaistarde,quandomantendoorelatrio,chamandoaumalinhaqueatravessa
asbandas.Destaforma,vocnoterquesepreocuparcomalinhandoascorretamenteouqueo
problemanalinhadeflutuaocausarproblemasdesuporte.Aoutravantagemqueaslinhastambmseestendem
abandaseestendequandoorelatrioexecutado.

Comousaroflutuadorparaasuavantagem
AfuncionalidadedeflutuaodoReportDesignercrticoemrelatriosdeformataocomcamposque
soimpressossobummemorandomultiline.
Ocontedodeumcampomemorandocostumaimprimirmaisdeumalinha.Oqueacontececomosobjetos
quesoparaimprimirdepoisouabaixodocampomemorando?Seelesnosomarcadosaflutuarouserfixado
emrelaoparteinferiordabanda,elesseroimpressasdentro(emcimaouporbaixo)danota
emformao.Estetipicamenteumacaractersticaindesejvel.Coloqueosoutrosobjetosabaixodoelstico
campoemarclosfixoemrelaoparteinferiordabandaoudefinirapropriedadefloatda
objeto.Abandairajustarasuaalturadeacordocomocontedodasmemriasdeduranteaimpresso
eosoutrositenspermanecerosempreabaixodosmemorandos.Seosmemorandosestoembrancoquenovai
seralocadoespaonabandaetudoabaixoirmoverse.

Comoimprimirsmbolosdebalacomcamposesticveis( Exemplo:
BulletMemo.frx)
Algumavezvocjimpressoocontedodeumcampodememorandooucampodecaracteresgrandeequeria
marcaroinciodequecomumamarcadebala?Existeumproblemaquandoexisteumobjectorelatrio
queelsticaetemotextoqueenvolvemaisdeumalinhaantesdoitemcommarcador.Sel
hcamposelsticosqueprecedemoitemcommarcasvocpodesimplesmentecolocarummarcadormarcadoraoladodo
detexto(verFigura16.8).

Captulo16:Criaoderelatrios 513
Figura16.8Esteumexemploqueimprimeummarcadoraoladodoinciodeumacadeiadetexto
queenvolveaoutralinha
longo

Figura16.9Esteumexemplodoqueacontecequandoasbalasnoestoflutuandocorretamente
comotextoassociado

Asoluoapresentadaaplicaseaqualquerobjectoderelatrioquenecessitamdeseraoladounsdosoutros
emumrelatrioquandoessesobjetossoinferioresaumoutroobjetoextensvel.Esteproblemafacilmente
resolvido.Criardoisobjetosdecamposeparadas.Aprimeiraabalaquepodeserumsimplesasterisco,
ouvocpodeencontrarumpersonagemWingdingouarquivodeimagemparapreencheressanecessidade.Osegundo
queimprimeumcampodecaracteresdecomprimento.Oexemplo(BulletMemo.frx)usaacombinaodeum
umobjetodecampo
campodecaractereseumcampodememorandoseparadoporlinefeeds.Certifiquesedequeambososcamposso
definiraflutuarequeoobjetoderelatriousadoparaimprimirotextolongadefinidocomoStretchcom
transbordar.Ocampodebaladevesergrandeosuficienteparaparcialmenteajustesobocampomemorando.De
sobrepondoosdoisobjetosderelatrio,osdoisiroflutuarjuntos.Casocontrrio,elesvosepararcomo
demonstradanaFigura16.9.Certifiquesedequevoctambmenviarocampodebalaparatrsdemodoqueo
larguranoimpedeaimpressodoobjetoderelatrioextensvelqueimprimeotextolongo.
adicional

Comoconstruirumendereodecorrespondnciasemlacunas(exemplo:Address.frx)
Muitasvezesvemososdesenvolvedoreslutamparalivrarsedadiferenaapresentadaentrealinhadeendereo
umaeacidade,estadoeCEP.Estegeralmenteassociadacomamenorfrequncia
preenchidalinhadeendereodois.Estaslacunastipicamentenosopreferidaspelosclientes.Naverdade,este

514 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

autorumavezganhouumtrabalhodedesenvolvimento,porqueelesabiaumpardetcnicasparalivraro
"Linhaembrancoexplodiu"deimportantesetiquetasdeendereamentodeumclientepotencial.
Aprimeiratcnicautilizaavulgarmenteconhecida"linhaRemoverseembranco"caractersticaque
disponvelsobaimpressoQuandodilogoparacadaobjetoderelatrio.Issofuncionabemparartulosdesde
geralmentenohoutroobjectoaoladodoendereodaetiqueta.Istonemsempreverdadenuma
relatrio.Orelatriopodeterumendereonaesquerdaedetalhessobreaempresadireita
ladodorelatrio.Sehouverquaisquerdetalhessobreamesmalinhaquelinhadeendereodois,vocestem
problemasporqueVFPnopoderemoveralinha,umavezquenoestembranco.

Figura16.10Esteumexemplodedoisendereosdiferentesexibidosema
"Lacuna"deixadaporumalinhadeendereovaziodoisnoendereoDAFUG

Esteolugarondeasegundatcnicavemacalhar.OVFPReportDesignertemdois
"Caracteresespeciais",avrgulaepontoevrgula,quesotratadosdeformadiferenteemumrelatrio
expresso.Avrgulaconcatenatesitensemconjuntonaexpressoeincluiumespao
entreeles.Seaexpressoconcatenadaestivervazia,issosetraduzemumacadeianula( ESPAO(0)).
Elepodesertraduzidoliteralmentenocdigocomo:
IIF(VAZIO(<expression>),espao(0),espao(1)+ALLTRIM(<expression>)).

Opontoevrgulaliteralmenteconvertidoemumretornodecarroe/oualimentaodelinha.Seo
expressoestvaziadalinhaeliminadadamesmamaneiracomoquandoo"RemoverlinhaSe
opoembranco"estdefinida.Outrobenefcioladobomquevocpodemisturaretiposdedadosfsforoneste
maneira.VFPirlidarcomaimpressosemforarodesenvolvedorparatransformlosao
Tipodedadosdecaracteres.
Ento,comosetirarproveitodessescaracteresespeciais?Aquiestocdigousadono
exemploapresentadonaFigura16.10:

cUserGroup,"("+ALLTRIM(cAbbr)+")"cAddress1cAddress2ALLTRIM(cCity)+
",",CState,espao(1),cPostalCode

Estaexpressodeumalinhausadoemvezdequatroobjetosderelatriodetextoindividuais.o
desvantagemdestatcnicaquevoctemapenasumtipodeletraparatodooobjeto.

ComousarlegendasdecampoDBCemrelatrios(exemplo:DynCaption.frx)
OcontinerbancodedadosVFPpermiteinserirlegendasparacadacampoemumatabelaouexibio.
Infelizmente,oReportDesignernotirarproveitodesserecursodamesmaforma
comoocriadordeformulrios.Vocsobterocampoemumobjetoderelatriodecampoquandovocarrastaumcampode

Captulo16:Criaoderelatrios 515

DataEnvironmentrelatrio.Legendacamponocolocadonorelatrio,poisemumformulrio.o
tcnicadescritanestaseopermitequeosrelatriosdelerdinamicamenteoBancodeDados
Legendasrecipienteatravsda DBGETPROP()funo.
Atcnicaimplementadousandoumobjetodecampodesdequeumobjetortulorelatrionopodeser
alteradodinamicamenteemtempodeexecuo.Emvezdecodificaroscabealhosdecolunaourtulosdecampoem
orelatrio,vocpodeobteralegendacampoapartirdorecipientedebancodedados.Noobjetodecampoentra
umaexpressoquemodeladoapsaseguintesintaxe:

DBGETPROP(<tabela.campo>,"campo","Legenda")

Issodaosdesenvolvedoresumamelhorflexibilidade,fazendoalteraesslegendasdecampono
bancodedados.Seousurioqueralegendarelatrioalterado,bastaatualizaralegendacampono
bancodedados.Agrandedesvantagemodesempenhomaislentodesdeorelatrioprecisaacessarobancodedados
recipientedecadavezqueaexpressoavaliada.Avantagemquetodososrelatriosqueutilizamesta
tcnicateramesmalegendaparaomesmocampo.Aconsistnciaumacoisaboa.Vocpode
tambmfazeralteraesnoscabealhosdecolunaertulosdecamposemanecessidadederecompilaro
aplicaoouenviarumarquivoderelatrioatualizadoseparadamentepararefletiraalteraosolicitada.

problemasdabanda
Estaseodocaptulorelatrionotemnadaavercomasquestesdaindstriadamsica,emvez
comousarosdadosdeagrupamentocaractersticasdoVFPReportWriterparafacilitarsuacriaoderelatrios.

Comoevitarrodapscabealhosrfosevivos(Exemplo:
HdrFootCutoff.frx)
Umcabealhodegruporfoquandonohlinhasdedetalheimpressosentreeleeofimdo
pgina.Issoacontecequandovoctemespaosuficientenofinaldeumapginaderelatrioparaimprimirogrupo
cabealho,masnoespaosuficienteparaimprimiralinhadedetalhe.Orodapdegrupovivoquandoh
noespaosuficienteentrealtimalinhadedetalheenofimdapginadorelatrioparaimprimirogrupo
rodap.
OcabealhodogruporfosimplesdecorrigirdesdeoRelatrioVFPDesignertemumbuilt
nomecanismoparalidarcomisso.Aquiestoospassosparaimplementarestatcnica:
1.Primeiro,vparaabandadetalheseobteraalturadabanda.Dumduplocliquesobreo
detalhebarraparaabrirodilogoDetail.
2.Copieaalturadabandanareadetransferncia.
3.VparaacaixadedilogoAgrupamentodeDados(ReportMenu,AgrupamentodeDados...)eselecione
ogrupoquevocesttentandoevitardeserrfo.
4.Naparteinferiordapgina,vocverum"grupoIniciaremnovapginaquandomenos
doque"Spinner.Coleaalturadetalhenestegirador.Estevalordevesermaior
doqueaalturadabandadedetalhe.Nspreferimosadefinirissoparaaalturadodetalhe
bandamaisaalturadecabealhodegrupoparaassegurarquepodemosencaixarpelomenosumdetalhe
registroeocabealhodogrupo.
516 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

ORelatrioVFPverificadoresdedesignerdepoisdeimprimircadarodapdegrupoparaoquartoesquerdana
parteinferiordapginaparaverseelepodecaberoprximocabealhodogrupo.Esteclculoespaopginaleva
emcontaoespaoinciogrupoqueintroduziunopasso4acima.Sehouverespaoparaamboso
cabealhodogrupoeumdetalhelinhadocabealhoimpresso.
Nohcomoconstrudoemcapacidadedelidarcomosrodapsvivas,mas,felizmente,huma
soluobastantesimples:
1.Obtenhaosdetalhesegrupobandasrodapprojetadoetrabalharexatamentedamaneiraque
querqueelesparaorelatrio.
2.Nestemomentovocprecisaparaexpandirotamanhodalinhadedetalhepelaalturado
rodapdegrupo.Vocserainserodeumnovoobjetoparaafaixadedetalhes.
3.Emseguida,crieumobjetodecamponorodapdegrupoqueaalturadorodapdegrupo.
Esteobjetovaiserumcampofictcioquenuncaimprimeassimalargurapodeser
oquequiser.Nscolocaralgumtextonaexpressocomo"Rodap
Espaoreservado,noimpressa."Nscrilonabandaderodapporquedimensionadapara
atodaaalturadabanda.IssonosdaVisualprecisamosdimensionlocorretamente.
4.Nodilogodepropriedadesparaesteobjetocampofictcio,certifiquesedeirparaaimpresso
Quandodedilogoedefiniro"Removerlinhaseembranco",ecoloqueum .F.,No"Print
somentequandoaexpressoforverdadeiracaixadetexto".Essaconfiguraogarantequeestemanequim
camponuncaimpressa.
5.Esteobjectomovidaparaabandadedetalheecolocadonaparteinferiordodetalhe
banda.Eledeveintrometersecontraomenorobjetonafaixadedetalhesamenosquevoc
querespaoentreasfaixasdedetalhesnorelatrioimpresso.Movaafaixadedetalhes
barsefirmementeaesteobjetodepoisdeterposicionadolo.
OqueistoconsegueparaenganarVisualFoxProempensaralinhadedetalheprecisademais
espaodoqueelerealmentefaz.OVFPReportDesigneragorapensaqueprecisadeespaosuficienteparao
detalhereal,maisorodapdegrupo.Seelenotemespaosuficientenaparteinferiordapgina,ele
imprimeodetalheeremoveoespaoreservadorodap.Agoraorodapseencaixamuitobemnapgina
quandoimpresso.Seofalsificadolinhadedetalhenoseencaixa,entoelesemoveparaaprximapginaea
rodaptemacompanhiadepelomenosumalinhadedetalheenomaisviva.

ComotersegundasbandasresumocomEOF()(Exemplo:
EOFBreakIt.frx)
ORelatrionativaDesignerfornecettuloeoresumobandasparaimprimirasinformaesno
incioefimdorelatrio.Estasbandasfornecemacapacidadeparaumdesenvolvedorparacolocareste
resumodasinformaesemsuaprpriapginaouinclulonofluxodorelatrio.Esevocquiser
algunsnmerosderesumoparaimprimirapsaltimalinhadedetalhee,emseguida,terumapginaderesumocompleto
comestatsticasdorelatrioemumapginaseparada(idealparaabandaresumo)?
Esteolugarondeumagrupamentode EOF()fornecealgumaflexibilidadeparaodesenvolvedor.isto
forneceumrodapbandadegrupoquepodeserusadoparaacontagemderesumo,somas,eorestodo
caractersticasagregadasembutidonoReportDesigner.Oconstrudoembandaresumopodeentoserusada
comaopo"Novapgina"setparaforaroresumodorelatriorealparasuaprpriapgina.o
Captulo16:Criaoderelatrios 517

Resumobandapodeentoserutilizadoparaasnteserelatriorealcomumformatodiferenteoupode
servircomoumresumoexecutivo.

Comocriarquebrasdecontroleflexveis(Exemplo:EOFBreakIt.frx/PRG)
Criandoumrelatrioquepodeserusadoparadiferentescritriosdeordenaodequebraedecontroloumdesafio.
Reutilizaoumdosobjetivosdeumbomdesigndesoftware,paraquepossamosteracapacidadedereutilizaocom
relatrios?Estaseodemonstraummtodoparareutilizarrelatriosmostrandoumfcil
VFP
soluo/truquequevocpodeachartilparaeliminaranecessidadedevriosrelatriosque
fundamentalmentetmamesmainformao.
OprogramaEOFBreakIterespectivorelatrioquevemcomocaptulode
Arquivosdedesenvolvedordedownloaddisponvelemwww.hentzenwerke.comdemonstraisso
tcnica.
Construirorelatrioparaatenderaosrequisitosdocliente.Quandonoestoagrupamento
breaks,emvezdeusarocampo(s)comoaexpresso,useumaexpressodenomedogrupogenrico.em
orelatrioexemplousamosaexpressocBreakGroup.
OrestodatcnicaimplementadanocdigoSQLSelect(oupontosdevista,setiveressa
preferncia)aoprepararosdadosparaorelatrio.Cadaumadasexpressesdeagrupamentoso
camposdinmicosquesocriadosatravsda ASclusula.Oscamposvirtuaistambmsoutilizadosna
ORDERBYclusulatambm.Istocomovocobterorelatrioparaimprimircomquebrasdecontroledinmico.
Aquiestumcdigodeexemplo:

****Executeprimeiraversodorelatrio****
v_groupsbygroupcatUSE

*SELECT,cCategoryAScBreakGroup
DEv_groupsbystate
ORDERBYcBreakGroup
INTOCURSORcurReport

*Publicarorelatrioseosdados
IF_TALLY>0
REPORTFORMEOFBreakitPREVIEWNOCONSOLE
OUTRO
MESSAGEBOX("Nohdadospararelatar!",0+16,_Screen.Caption)
FIMSE

****Executesegundaversodomesmorelatrio****
v_groupsbystateUSE

SELECT*,cStateAScBreakGroup
DEv_groupsbystate
ORDERBYcBreakGroup
INTOCURSORcurReport

*Publicarorelatrioseosdados
IF_TALLY>0
REPORTFORMEOFBreakitPREVIEWNOCONSOLE
OUTRO
MESSAGEBOX("Nohdadospararelatar!",0+16,_Screen.Caption)
FIMSE

518 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Aprimeirainstnciadorelatrioimprimeosregistrosagrupadosporcategoria,asegundainstncia
agrupadasporestado.Achaveparaobteresteconjuntodeagrupamentoo <expressodecampo>AS
cBreakGroup.
OcBreakGrouptambmpodeserumcampovirtualnavistatambm.Nsusamosestatcnica
umpoucoemnossocadadiadetrabalho,umavezquereduzonmeroderelatriosparamanteremumgrande
sistema.Muitasvezesvemosasemelhananasadamuitoantesdeosusuriosfazem.Istopodeser
umaenormepoupanadetemponamaioriadosprojetosdedesenvolvimento.

Comoconstruirduas(oumais)conjuntosdelinhasdedetalhe(Exemplo:PeriodYtd.frx)
Osdesenvolvedorestmafinadoashabilidadesdemarchaparaforavriostiposderelatriosquelistamdetalhesde
umtipoououtro.UmaquestoquepostadoemdiscussesonlinesobreCompuServe,
FoxForum.comouaUniversalThreadvezemquando"Comopossoimprimirvriosconjuntosde
linhasdedetalhe?"Aperguntageralmentegiraemtornodetalhesdeduastabelasdiferentes,cadaum
terseusprpriosdadosnicos,aindaprecisasermisturadosentresiaolongodomesmorelatrio.o
mesmatcnicapodeserutilizadapararesolveroproblemacomosdoisconjuntosdedadosdentrodeumatabela.
Oexemplovemoscomfrequnciaemnossorelatrioanecessidadedeimprimiroresumodetalhespara
umgrupodeitensparaoperododorelatrioatual,seguidodiretamentepelostotaisyeartodatepara
cadaumdessesitens.Nestecaso,osdetalhessoosmesmos,masosartigossorepetidasparacada
agrupamento.
Comodissemosnoinciodestecaptulo,vamosVisualFoxProfazeroquefazmelhor,emprimeirolugar
esmagasobreosdados.Ospassosirseguirumpadro.OpadrovaiexigirumSQLSelect
paracadaconjuntoderegistrosdedetalhe.UmdoscamposnoSQLSELECTserumtipoderegistroqueir
distinguirafaixadedetalhesqueelepertence.Escolherotipodedadoseovalordestecampo
importante,umavezqueutilizadoparadeterminaraordemdabandadetalhe.CadaSQLSELECTdeveter
osmesmosnomesdecampoetamanhoexatodesdeasconsultasserofundidosemconjuntocoma UNIO
clusulaapsasconsultasdetalhedabandasoexecutados.
OexemplodescritonaPeriodYtd.prgelistadosnocdigoabaixoresponde
pergunta"Quaissoasvendasdelivrosdecadagrupodeusuriosparaoltimotrimestrede1999epara
oanointeiro?"

SELECIONEcUserGroup,
ySalesASySalesReported,
"P"AScPeriodOrYTD,
dPeriodEnd
DEch16sales
ONDEdPeriodEnd={^19991231}
INTOCURSORcurPeriod

SELECIONEcUserGroup,
SUM(ySales)ASySalesReported,
"Y"AScPeriodOrYTD,
{^19991231}ASdPeriodEnd
DEch16sales
ONDEdPeriodEnd=>{^19990101}
EdPeriodEnd=<{^19991231}
GROUPBYcUserGroup
INTOCURSORcurYTD

SELECT*

Captulo16:Criaoderelatrios 519

DEcurPeriod
UNIO
SELECT*
DEcurYTD
ORDERBY3,1
INTOCURSORcurReport

IF_TALLY>0
REPORTFORMPeriodYTDPREVIEWNOWAITNOCONSOLE
OUTRO
MESSAGEBOX("Nohdadospararelatar!",0+16,_Screen.Caption)
FIMSE

Aprimeiraconsultaobtmosltimostrimestredevendas.Asegundaconsultareneadatadeanopara
nmerosparacadagrupodeusurios.AfinalSQLSelectfundeasduasprimeirasconsultasemconjuntoe
classificaainformaopelotipodedetalheregistro(cPeriodOrYTD),seguidopelogrupodeusurios
nome.Ocursornoexemplotem4linhasdedadosqueproduz4linhasdedetalheno
relatrio.

Tabela16.1OsdadosnocursorchamadocurReport

cUserGroup ySalesReported cPeriodOrYTD dPeriodEnd


DetroitAreaFoxUserGroup 750.0000 P 12/31/1999
SterlingHeightsComputerClub 50.0000 P 12/31/1999
DetroitAreaFoxUserGroup 2450.0000 Y 12/31/1999
SterlingHeightsComputerClub 400.0000 Y 12/31/1999

Olayoutdorelatrioimportantetambm.Achaveparaosucessodorelatriogerarum
grupoparaocampotipodedetalherecorde.Istooquegeraomecanismoderepetioqueproduz
asdiferenteslinhasdedetalhe.
Hmuitasvariaesnestatcnica.Sevocestivercombinandodiferentesdadosde
tabelasdiferentes,osSQLSelecionaseumpoucomaistediosoaocdigo.Osconjuntosderesultadosdeve
corresponderexatamentedecampoparacampo,tantoemtamanhoetipodedados.Paragarantirosresultadosconjuntos
podeterderealizarconversesdedadosoucolunasdeinseroemsuasinstruesSQL.
correspondem,voc
520 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura16.11OmultidetalhelayoutdorelatrionoReportDesignernotarquecada
grupodelinhasdedetalhedevetersuaprpriabandadegrupo

Comosimularumalinhadedetalhemaisdeumapgina(exemplo:
DetBigPage.frx)
HumalimitaocomoVFPReportDesignercomaalturadebandarelatrio.Omximo
alturadeumanicabandaocomprimentodapgina(combasenocontroladordaimpressoraconcebidocom
ouimpressoem).Issosignificaquevocnopodeterumaextensodedetalhebandasobreumapgina.Ento,oqueum
desenvolvedorquefazerseosdadosemumregistromuitograndeparaimprimiremumapgina?Felizmentehuma
fcilsoluoparaesteproblema.
Primeirovocprecisacriarumagrupamentode RECNO()nacaixadedilogorelatriodeagrupamento(Relatrio|
MenudadosAgrupamento).Opcionalmente,possvelselecionaroagrupamentoem RECNO()parainiciarumanova
Apginasemproblemas.Sevoctiveroutrosgruposnorelatrio,fazera RECNO()agrupar
ogrupodenvelmaisalto(maisprximodafaixadedetalhe).Fecheodilogodeagrupamentoparavoltarao
ReportDesigner.Asalturasdebandapginacabealhoerodapdeveserdefinidaemprimeirolugar.Verifiqueseo
bandadocabealhodapginadefinidopara"heightbandaConstant".
Achaveparafazerestetrabalhotruqueutilizarastrsbandascomotodaabandadedetalhes.o
trsbandasenvolvidassoa RECNO()cabealhodegrupo,oVFPfornecidaDetalheBandedo
RECNO()Gruporodap.Cadaumadastrsbandaspodeteraalturadeumapginainteira(amenos
alturadocabealhoerodapdapginacombinada).Istosignificaqueosdetalhespodemserapresentadasem
3pginasinteirasemvezdapginalimitadopeloReportDesigner.
Existemduasopesadicionaisdisponveis.Sevocquerumdetalhededuaspginasvocdevefazer
odetalhee,ouo RECNO()Cabealhodegrupoourodapdegrupomaior.Comograndevocpode
pergunta?Abandadetalhedevesertograndequantovocpodecaberemumapginadepapel,menosocabealhodapgina
ealturasderodapdepgina.Eleirvariardeacordocomotamanhodopapelesevocestiverimprimindoem
Retratooumodopaisagem.Sevocquerumdetalhedetrspginasquevocprecisaparaexpandirtantoo
RECNO()GrupoCabealhoerodapalturadetamanhodepginainteira.
Captulo16:Criaoderelatrios 521

Existeumasituaoemqueestetruquenoirfuncionarequea
impressodoscamposdememorandoqueestodefinidosparaesticar.Umtrechodo
Bandafarcomqueorelatriodeultrapassarolimitedeumapginaemumanica
Detalhe
banda(quealimitaoqueestetruquefuncionaemtorno).

Nestepontovocestprontoparaolayoutdoscampos,rtuloseoutrosobjetosnorelatrio.Todos
camposdeveterumtamanhofixo.Nenhumdosobjectospodeserdefinidoparaflutuarumavezqueoestiramento
indisponvel.Vocvaiprecisardetamanholongoscamposdetextoquesoesperadosparaquebraautomticaparaserum
tamanhofixo.Estenodeveserumgrandeproblema,umavezqueagoravoctemvriaspginasparatrabalharcom
paraainformao.

Comocorrigiralocalizaoderodap(Exemplo:FixFooter.frx)
Temsidosemprenossofocoparafazerrelatriosdeboaaparnciaeseromaiscompactopossvel,mas
devezemquandosomosconvidadosparaimprimirespaoembrancoadicional.Nesteparticularseolida
comumpedidodeumtamanhofixodocabealho,detalhe,eumacombinaoderodap.
Asituaocomosesegue.Umusurioquerterosdezmelhoresfuncionriosdecadagrupodevendas
impressasemordemdesempenhodevendas.Algunsgruposdevendaspodeter10funcionriosdevendasoutras
podemtermenosde10trabalhadores.Ochefedogrupodevendasnoquerjogarfavoritos
equeramesmaquantidadedeespaodedicadoacadaumdosgruposnorelatrio,independentemente
donmerodepessoasnogrupo.
Estasolicitaonicarequer"foradacaixa"pensar.Primeirovocprecisacriarumrelatrio
varivel.NoexemploquechamouesterelatriovarivelnMaxRowsInGroup.Estavarivel
definidoparacontaronmeroderegistrospormeiodaopoCalcularnoagrupamento.Inicializeopara
zero,marcloparaaliberaoapsorelatrioetloreporaonveldogrupo.
Norodapdegrupocolocouumcampocomaseguinteexpresso:

REPLICATE(CHR(13),<nFixedRows>nMaxRowsInGroup)

O CHR(13)umretornodecarro.Certifiquesedemarcarotrechocomestouroparaeste
REPLICATEcampod.Oretornodecarroadicionaumalinhaembrancoparaocampoelstico.Aexpresso
<NFixedRows>onmeromximodelinhasquepretendeimprimirnabandadedetalhes.o
exemploderelatriotemumvalorcodificadode10.Issonoprecisaserocaso.Vocpode
preprocessocursorselecionadocomoSQLSelect:

SELECTCOUNT(cCategory)ASnCount
DEch16ug
GROUPBYcCategory
INTOCURSORcurTemp

SELECTMAX(*)ASnFixedRows
DEcurTemp
INTOCURSORcurTemp2

522 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Nesteexemplo,altimaconsultadlheonmeromximodelinhasquevocvai
processocomumagrupamentorelatrio.Estevalorpodeserusadocomopartedo replicadas()afunode
fazerosrelatriosumpoucomaisdinmico.
Figura16.12OrelatriodeexemplorodapfixomostradonoReportDesigner.Achave
paraosucessodefixaraposiodainformaoderodapgrupoousodo
VFPREPLICATE()funonorodapdegrupo.

Comoimprimir"Continuao"quandoodetalheoverflows(Exemplo:
WhiteSpace.frx/.prg)
Jtemumpedidoparaimprimir"Continuao..."norodapdeumapginaquandoogrupo
cabealho/detalhesimprimiremumapginaeterminarnaprximapgina?SevocseguiroMicrosoft
direocomoartigoKnowledgeBaseQ118560,vocestarperseguindoumaraposanoerro
direo.Atcnicadescritanoartigonofuncionaemtodososcasos.Defacto,deo
tcnicasquetmtentadoaolongodosanos,asegundatcnicadiscutidanestaseono
exatamenteperfeitoemnossosolhos,masosresultadosestocorretos.
KnowledgeBaseartigoQ118560,"ComoIndicarRegistroContinuanaPrximaPgina
Report"deveriaserchamadode"HowtoRaramenteImprimirContinua."Elesugereacriaodeumrelatrio
varivelparaogrupocomumvalorinicialde f.eumvaloralojade .T.,emseguida,
condicionadoaimpressode"Continuao..."naparteinferiordapginadofactodeestavarivel
falso .Oqueacontecequequandoumnovogrupocomea,avariveldefinidacomo .F.,emseguida,definir
a .T.,quandooprximolbumdogrupoimpressa.Seoprximoregistroapsoquesepassana
pginaseguinte,"Continuao"nosoimpressos.Portanto,anicavez"Continuao"impresso
quandoocabealhodegrupoimpressosemquaisquerdetalhessobreamesmapgina.Seissoquevocest
procurando,entovoctemamaissimplesdasduassolues.
Amelhorsoluoexigeautilizaodeumavariveldememriapblica.Nonossoexemplo,vamoscham
oglNewGroupvarivel.Antesdeexecutarorelatrio,declararavarivelmemriapblicae
inicializeocomofalse.Avariveldememriamanipuladoemumpardefunes.Naturalmente
estasfunesdevemestarnapilhadechamadasoudisponveisatravsdo SETPROCEDIMENTOcomando.

Captulo16:Criaoderelatrios 523

OglNewGroupvariveldefinidacomoverdadeiracadavezqueumnovogrupoencontradono
relatrio.Chamarumafuno,GroupHeaderOnExitnonossoexemplo,de"Rundocabealhodogrupo
ExpressoemExit",queisso.AvarivelglNewGroupentodefinidacomofalsacadavezqueo
rodapdegrupoforencontrado,chamandooutrafuno,GroupFooterOnExitnonossoexemplo,
apartirde"RunExpressionaosair"dorodapdegrupo.OqueistodizaoReportDesignerque
orodapdegrupofoiimpressoeocabealhodogrupoaindanofoiimpressa,portanto,
nohnecessidadedeimprimiramensagem"Continuao"norodap.Aquiestoexemplosda
procedimentosnecessrios:

GroupHeaderOnExitFUNO
glNewGroup=.T.
RETURN.T.

GroupFooterOnExitFUNO
glNewGroup=.F.
RETURN.T.

TheRunExpressonasadanopermiteaatribuiodeserfeitodiretamente.Isto
porissoquegerarasfunes.Oltimoitemnecessrioamensagemnorodapdapgina.o
expressousadanoobjetocampopodeseralgoparecidocomoseguintecdigo:

IIF(glNewGroup,"Detalhescontinuanapginaseguinte...",ESPAO(0))

Agora,orelatriosimprimeo"Continuao"naspginasquetmlinhasdedetalheaindaparaimprimir
antesdorodapdegrupo(mesmoembranco)impresso.

Outrastcnicasderelatrio
Comoevitarproblemascomaimpressoracodificados
Osrelatriosso,porvezes,concebidodeumaformaqueobrigaumdesenvolvedorparaescolherasconfiguraescomo
retrato,paisagem,duplex,ououtrasconfiguraesespecficasdaimpressora.Muitasvezes,aescolhafeitacombaseem
onmerodecamposdedadosqueprecisamserimpressanaslinhasdedetalhe.Algumasescolhassofeitas
combaseemexignciasdosclientes.Essasescolhaspodemacidentalmentesersalvonorelatrioepode
causarproblemascomaimpressoemimpressorasdeclientes.
Aorientaodaimpressoradeterminadopelaconfiguraonoarquivo|dedilogoConfigurarpginanoVisual
FoxProquandoumrelatrioestsendomodificado.Voc,ento,entrarnodilogodeconfiguraodeimpressopara
orientao.Seleccioneaorientaoqueorelatrioexige.Essaconfiguraovaificarcomorelatrio
selecionaro
noimportaoqueaconfiguraodaorientaoparaessaimpressora(sejaemWindowsouopadroVFP
impressoraconfiguradaatravsdeum SYS(1037)).AchavedeixaraimpressorapadrodoWindowsselecionada
fazendoaselecodeorientao.Seoutraimpressoraselecionado,VFPvaiamarraraconfiguraodo
antes
impressoraparaorelatrio
Existemalgumaspreocupaescomacaixadedilogodeconfiguraodaimpressoraqueprecisamserobservados.
terproblemasnoseguintecenrio.
Umpode
Vamosdizerquevocseguiutodososnossospassosdescritosacimaetudofuncionoumuitobem.
Agorachame SYS(1037)eescolheralgumaoutraimpressoraquediferentedopadrodoWindows
impressora.Agora Modificarrelatrio,nofazerqualqueralteraoemtudo,massapertarCTRL+Wpara
salvaro

524 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

relatrio.VisualFoxProacaboudesalvarasinformaessobreumaimpressoradedesenvolvimentoespecficodentro
seurelatrio,substituindoasconfiguraesoriginais"impressorapadro".Agora,orelatrioserimpressoparaque
impressoraespecficaouuseosatributosassociadosaessaimpressoraaoimprimirorelatrioparao
impressoradocliente.Adiferenaentreasimpressoraspodemsersutisousignificativo.Seo
impressoradedesenvolvimentosuportaduplexeaimpressoradoclientenofaz,instruesparao
aimpressopodeterefeitosnegativos.
porissoquesedevesempre Modificarrelatrio,enquanto SYS(1037)(ouArquivo|Configuraodapgina)
paraaimpressorapadro.VejaocaptulosobreProjectHooksparaverumatcnicaquevaiesfregarisso
definida
codificadoinformaesdorelatrioapartirdosarquivosFRX.

ComousaroConstrutordeexpressesparaoscamposdecursornodefinidos
DataEnvironmentdorelatrio
OconstrutordeexpressesaparentementeficoumaisinteligentequandousadocomoReportDesignerentre
FoxPro2.6eVisualFoxPro.Foiotempoeotempoprovoumaisumavezquenomaisinteligente
sempremelhor.Voltarnos2,6diasoConstrutordeexpressesiriaexibirtodososcamposemtodoo
tabelasabertas.OExpressionBuilderVFPexibeapenasoscamposparaastabelasincludasno
DataEnvironmentdorelatrio.AabundnciadedesenvolvedoresnoutilizaroDataEnvironment,masfazer
alavancaroConstrutordeexpresses.

Figura16.13OConstrutordeexpressescomatabeladaOrdemdobancodedadosTasTrade
camposespalhadosaomemvars
Captulo16:Criaoderelatrios 525

OExpressionBuilderVFP(verFigura16.13)acessadoatravsdoRelatriodeExpresso
dilogo.Eleexibeoscamposdatabelanoladoesquerdodacaixadedilogoeasvariveiscomescopono
ladodireitodacaixadedilogo.Omtodoparapreencheroladodevariveissimplesmenteabriratabelaou
visualizar,ouexecutaralgumcdigoSQLSelectparaconstruirumcursor,emseguida,tornlooreadetrabalhoativa.
ExecutaroseguintecdigonajanelaVFPComando:

SCATTERMEMOMEMVAR

Asvariveiscriadassoexibidasnacaixadelistanocantoinferiordireitoda
ExpressionBuilder.Vocpodeusaressasvariveisnaexpresso,assimcomooscamposdeuma
mesacomumduplocliquesobreavariveldememriaouportabulaesparaalistaeselecionaro
varivelquevocdeseja.Umadasvantagenscolateraisparaestatcnicaoaliasdatabelano
includonaexpressocomoquandovocselecionarumcamponacaixadedilogo.Discorgidocodificaooalias
naexpressofazorelatrioinflexvelquandopoderiaserutilizadocomvriosdiferentes
cursores.

Comoobterosformatosdeetiquetasparaestardisponvel
UmadasperguntasfrequentesposoudedesenvolvedoresVFPaprimeiravezquecriarrtulos
comoelespodemprcarregarosdiferentesformatosdeetiquetapadrodisponveisnomercado?tem
maisde80diferentesAvery layoutssuportadosnativamentenoVisualFoxPro.
OdiferenteAveryetiquetasformatossoarmazenadasnoregistro(verFigura16.15).Sevocs
queroslayoutscarregado,amaneiramaisfcilexecutaroAssistentedeetiquetaVFP.umdosraros
vezesrecomendvelexecutarosassistentesdoVisualFoxPro.VerFigura16.14paraamensagem
queexibidopelaprimeiravezoassistenteexecutado.

Figura16.14AprimeiravezqueexecutaroAssistentedeetiquetaquevocapresentadocomuma
janelademensagemdizendoqueeleestindoparaadicionarosformatospadrodeetiquetaAvery
osdisponveisnoVFP
para

VoctambmpodeadicionarosformatosparaoregistroclicandoduasvezesnoarquivoLabels.regem
as HOME()+"Tools\AddLabel\"diretriodoWindowsExplorer.IssoexecutaoEditordoRegistro
ecarregaasconfiguraesnoregistro.EstaamesmamaneiraqueoAssistentedeetiquetacarregao
Registro.

526 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Figura16.15OsformatosdeetiquetasAverysoarmazenadasnoRegistrodoWindows

RelatrioMetadadosManipulao
OcdigofonterelatrioVisualFoxProarmazenadoemordinriasVFPmesaslivrescoma
extensesFRX/DRF.Comotodosnsmanipulardadosparaumavida(bemamaioriadens)apenas
naturalparansqueremosinvadirosarquivosdemetadados.Achavepara"mexercomocdigo"
sexecutaressasoperaesembackups.Nuncaexecutarumaferramentahackerdecdigonanicacpia
qualquertabeladerelatrio(ouqualquerumadasoutrastabelasdemetadados).Noprecisomuitoparadesativara
ReportDesignerdeabrirumrelatrio.Depoisdeentenderessepodereflexibilidade,e
olayoutdoarquivoderelatrio,vocpodeaproveitaresseconhecimentoparaconstruirferramentasquefacilitamasua
experinciaemdesenvolvimento.

Comovocalterarfontesdeprogramao?(Exemplo:ChgFont.prg)
Aplicaessodistribudosparaosclientesquetmumavariedadedegostos.Umdositensque
clientesmaiscomopersonalizadasparaosseusgostoslayoutsderelatrioefontes.Enquantoosdesenvolvedorespodem
fazerumaboavidamudandoeaprimorandoosrelatrios,hfrequentementepoucotempoparalidarcomisso
aspectodonossotrabalhoeessasmudanastornamsefrequentementeumaprioridademaisbaixa.
OproblemacomoReportDesignerquandosetratadefontesmudanaquevocdeve
escolhernosotipodeletra,masotamanho,eseeleestemnegritoouitlicoparaoobjetorelatrio.Issosignifica
vocdeveselecionarosobjetosquetmexatamenteosmesmosatributosdafonte,casocontrrio,todoselessetornamo
mesmo.Esteumprocessomuitotediosoparaosrelatriosquetmummontedediferentestamanhoseestilosdefonte.
Esehouvesseumamaneiradeaceleraroprocesso?
Ascaractersticasdorelatriosoarmazenadosemformatodetabela.ONomeDaFontearmazenadono
colunafontfacedestatabela.Asoluoverificaratabelaesubstituirovalordo
colunacomumnovoNomeDaFonte.AquiestocdigodoncleodoprogramaChgFont:

USE(tcReportMetadata)EXCLUSIVOIN0ALIAScurFontChanger

curFontChangerSELECIONAR

SCAN
IF!EMPTY(fontface)
SUBSTITUIRfontfaceCOMtcFontNameINcurFontChanger

Captulo16:Criaoderelatrios 527

FIMSE
ENDSCAN

USOEMcurFontChanger

Houtrassituaescomovriasfontessendousadosnomesmorelatrioevocpode
squermudarasespecficas,porexemplo:

REPLACEALLfontfaceCOM"Arial"PARAFontSize=10

Humperigocomesteprocessoquevocprecisaestarciente.fontesdiferentestm
diferentesmtricasdefonte.Oqueistosignifica,fontesdiferentestmdiferentesalturas,larguras,
formas,tamanhoseestilos.Issopodeterladoruimafetasenoforusadoadequadamente.Sevoc
usandoumafontedetamanhofixosimples,comoCourierNewedecidirmudarparaalgocomoGoudy
Stout,seusobjetosdeetiquetapodeficartruncadodesdeVisualFoxProarmazenaalargurapixelda
objetosdetexto.Ostamanhosdosdesignersdedesenvolvimentonosoreflexodoquevoccomeaquando
vocexecutarorelatriocomum REPORTFORMcomando.Seumafonteespecificadaemumrelatrionoestcarregado
PCdousurio,oWindowsirsubstituiraquelequesesenteintimamenterepresentaosmesmosatributos
no
afonteespecificada.OWindowsnemsemprebomparaissoeorelatriopodeimprimirdeformadiferente
doqueprojetado.Poroutrolado,sevocestsemovendoparafontescommtricasdefontesemelhantequeser
guardarummontedetempoeesforoagradaraocliente.

Comoconverterformatosdepapel(Letter>A4impresso)(Exemplo:Letter2A4.prg)
Osdesenvolvedoresquetmclientescommaisdeumpadrodetamanhodepapel,taiscomo8,5x11e
A4,iroapreciarestaseo.Nsviemosatravsdeumprogramaqueconverteostiposdepapelparatodos
relatriosemumdiretrio.Paraaquelesquenoofazem,elevaitedarumpoucomaisdeconhecimentosobreacoragem
dosmetadadosrelatrio.OsdesenvolvedoresquetrabalhamdeformanativanomundodaA4etmclientesque
trabalharcompapeldetamanhodeletrapodefacilmentereverteraengenhariadoprocessoparaassuasnecessidades.

Listagem16.1EssecdigoconverteumrelatriodaCartaaotamanhodepapelA4

lcOldSelectLOCAL &&Defesasdoworkareaatual
lnCounterLOCAL &&PARAcontadordeloop
LOCALlaFRX &&Gamaderelatrios

lcOldSelect=SELECIONAR()

Selecionar0
=ADIR(laFRX,'*.FRX')

PARAlnCounter=1aALEN(laFRX,1)ETAPA1
USE(laFRX[lnCounter,1])IN0EXCLUSIVE

*AltereadefinionoprimeiroregistodecartaparaA4
SUBSTITUIRexprcomSUBSTR(Expr,1,AT("PAPERSIZE",Expr)2)+
"PAPEL=9"+
SUBSTR(Expr,AT("PAPERSIZE",Expr)+12),
LarguraCOM77433.000

LOCALIZARparaaguarnio(expr)='date()'

528 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SEACHADO()
SUBSTITUIRposioHCOM1.562,5,LarguraCOM8854,167
FIMSE

LOCALIZARparaaguarnio(Expr)=""Pgina"'

SEACHADO()
SUBSTITUIRposioHCOM66250.000
FIMSE

LOCALIZARparaaguarnio(Expr)="_PAGENO"

SEACHADO()
SUBSTITUIRposioHCOM70416.667
FIMSE

USAR
ENDFOR

SELECIONAR(lcOldSelect)

RETORNA

Concluso
Relatriospodeserdivertidoapenasporcausadosdesafiosqueenfrentamosnaslimitaesdo
VisualFoxProReportDesigner.Nssempredescobrirqueosclientespagantesapresentarainda
outrorelatrioqueelesprecisamqueaprincpiopareceserimpossveldentrodesseslimites.Narealidade,
temhavidopoucosrelatosdequenopoderiarealizarusandoasferramentasVFPnosd.em
oprximocaptulovamosdiscutiralgunsitensadicionaisnagestodoprocessodecomunicao.
Captulo17:GerenciamentodeRelatrios 529

Captulo17
GerenciandoRelatrios
"Reportmimeminhacausacorretamente".("Hamlet",deWilliamShakespeare)

UsandooVisualFoxProReportDesignerapenasmetadedabatalhaquandoageraoderelatrios
paraosusuriosdeumaplicativo.EnquantoabatalhacomoReportDesignerpodeserumdesafio,
haoutrametadedopresenteprocesso,quegereacriaoderelatrios,
apresentaoesada.Estecaptuloabrangeumasriededicassobrepolirasada,
trabalharcomomododerelatriodeprvisualizao,depuraoeumpardealternativasde
utilizandorecursosnativosVFPeautomao.
comunicao

Nocaptuloanterior,nscobrimosalgumasdicasetcnicassobrecomotrabalhardiretamentecomo
ReportDesigner.Estecaptulotemumfocoligeiramentediferentenamedidaemqueamaiorpartedadiscusso
centraseno REPORTFORMcomandooumecanismosalternativos.

ComoaproveitarrelatrioseDataSessions
VisualFoxProrelatriospadroparaodatasessionatual.Osrelatriostambmsocapazesderodarem
seusprpriosDataSessionsprivadas,assimcomoformas.Enquantoissosoacomoumacaractersticaintrigante
alavancagememprimeirolugar,nosencontramosraramenteuslos(consulteaseo"Comovisualizarmltipla
relatriosdeumasvez").
Aprincipalrazoporquenousardatasessionprivadadorelatrioquegeralmenteusamos
SQLSelectcdigoparaprepararosdadosparaorelatrio.Seusarmosumrelatriocomumaprivada
datasession,temosquecodificaroscursoresnoDataEnvironment,outemosdeescrevercdigo
especificamenteparaorelatrionosmtodosdaDataEnvironment.Ambososcenriostm
desvantagensemnossaopinioumavezqueocdigosutilizvelnorelatriodefinido.Orelatrio
tornasergida,umavezquespodeserusadocomoscursoresestticos.Osrelatrioscomhardware
dataenvironmentscodificadostmpoucaflexibilidadequenosejaacapacidadedealavancarparametrizado
pontosdevista.
Oprocessoalternativoqueusamosconfiguraroscursoresrelatrioemumformulriocomumprivado
datasession.OcdigoSQLqueusamostipicamenteproduzidaapartirdeumnmerodeusuriodefinida
critrio.Oscritriosusuriosoinseridosatravsdainterfacedoformulrio.Combasenacombinaode
seleesintroduzidospeloutilizadorquedinamicamenteconstruiroSQLSelect(s)egerarocursorfinal(s)
quesoutilizadosnorelatrio.Desdejtemosumaformaparapermitiraousurioaentradado
critrios,porquenotirarproveitodedatasessionprivadadoformulrio?Ocdigoquepodeser
gerado(atravsdesubstituiesdemacro)muitomaisfcildetrabalharcomaformadoqueseriaem
ummtodorelatrioDataEnvironment.
Desdequeorelatriousaadatasessionpadro(querealmentesignificaodatasessionatual,
Nodatasession1)podemosdefinirosdadosespecificamenteparaumrelatrioatravsdeumcritrioderelatrios
formar,oupodemosusarodatasessiondeoutraforma(comoumformulriodeentradadedados),seasexigncias
personalizados
exigilo.Estaabordagemproporcionaflexibilidadecompleta.

530 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro
Comocriarummodeloderelatrioparaumprojeto(exemplo:
Untitled.frx)
UmadasqueixasmaiscomunssobreVisualFoxProafaltaderelatriosorientadosaobjeto.isto
serialegalparadefinirumrelatrioetmasmesmascaractersticasdebaseserherdadacomoclasses,mas
temosquesecontentarcomoutratcnicamodaantigadeterummodeloderelatrio.o
tcnicadescritabomnofatodequepodemosalavancaralgumcomportamentopadrodoVisual
FoxPro.
Oqueacontecequandovocexecutaocdigoaseguirnajaneladecomando?

CRIARRELATRIO

UmnovorelatrioabertonoVFPReportDesigner.Nestemomento,orelatriono
chamado.(ElemostrasecomooRelatrioN,ondeNonmerodesequnciadorelatriocriadopara
essasessoVFP.)VocspodeexecutarumSalvarcomonomenu,noumSalvarparaarquivoatual
nome.Oqueacontecequandovocexecutaocdigoaseguirnajaneladecomando?

CRIARRELATRIOuntitled

AmesmacoisaumnovorelatriosemnomeabertonoRelatrioVFPDesignere
spodesersalvacomoSalvarcomo.Ento,oqueestacontecendoaqui?Voctambmdeveestarseperguntandoporque
ningumgostariadeacrescentarodesnecessrio"untitled"nalinhadecomando?Achaveaqui
alavancarestecomportamentonativodoVisualFoxPro.Primeirocrieumnovorelatrioeguardlocomo
nome"untitled.frx".Agora,quandoVFPsolicitadoacriarumnovorelatriocomo REPORTCRIAR
untitledcomando,elevaiabriromodelo"untitled.frx"noReportDesigner,desdeque
podeserencontrado.
Ento,comopodemosaproveitarestecomportamento?Oprimeiropassoodecriarorelatrio
modelo.Cadaprojetopodeserdiferente,mascriarasbasesdorelatrioparaqueeleatendaa
necessidadesdocliente.Noexemploocaptulo"untitled.frx"queincluemonomedosistemae
onmerodapginanocabealho,adatanorodap,umagrupamentoem EOF(),edefiniropadro
fonteparaorelatrioparaTahoma.Numambientedeproduo(ousistema)domniosgenricospodemser
criadoparacoisascomoonomedoaplicativo,oequivalenteselecodelinguagemnatural
critrios,data,hora,nmerodepginas,nomedorelatrio,oudeumagrupamentono EOF().Vocpodedimensionaro
cabealhos,rodaps,incluirpginasttulopadro,equalqueroutracoisaqueseucoraodesejaouqueo
demandasdosclientes.
Outratcnicaqueusamosotempotodoparaincluiro"untitled.frx"emumprojeto.Salvamos
omodeloparaodiretriorelatriodoprojeto.Istotornaseomodeloparatodooprojeto.
Quandotemosumnovorelatrioparadesenvolveracabamosdemodificarorelatrio"semttulo"doProjeto
Gerente.Issopermitequeasequipesdedesenvolvimentoparacompartilharomodelocomumparaoprojetoepara
termodelosseparadosparadiferentesclientesouprojetos,mesmodiferentesparaamesma
cliente.Exclumosorelatrio"semttulo"noProjectManagerparaqueelenoestincludoemqualquer
lanadoexecutvel.umrelatrioqueosclientesnuncaseriaexecutadoporissonohnecessidadede
liberlo.
Umoutropontovaleapenadiscutirestamelhoraroumodificaromodelo.Desdeo
comportamentopadrodoVisualFoxProparasalvaronovorelatriocomumnomediferente,vocvai
sempreprecisaSalvarcomo"untitled.frx".Porqueestamosaconstruirrelatriosapartirdeummodeloesttico

Captulo17:GerenciamentodeRelatrios 531

emvezdeumaclassedinmica,todasasmudanasfeitasnomodelonosopropagadasparaexistente
relatriosqueforamcriadoscomosmodelos.

Comoimprimirumintervalodepginas(ExemploRange.scx)
ApginadeimpressovarianoRelatrioVFPDesignerpareceserumadicabvia,masaqueleque
porvezes,ajudaroutrosdesenvolvedoresdescobrirporissodecidimosinclulonestecaptulo.a GAMA
clusulasobrea REPORTFORMcomandopermitequeosdesenvolvedores(eusurios)paraespecificaraspginasque
quersadaparaaimpressora,teladedesktopVFP,ouumarquivo.
Oseguintecdigodeexemploforneceumaolhadaemummtododealavancaresserecursoemum
aplicao:

REPORTFORM(lcReportName)PARANOCONSOLEIMPRESSORA
GAMA(THISFORM.txtStartPage.Value),(THISFORM.txtEndPage.Value)

Afaixaignoradaseorelatriovisualizado.Agamadeincionopodeserinferiora1,mas
ofimalcancepodesermaiordoqueonmerodepginasnorelatrio.Sesuafaixadeinciomais
queonmerodepginas,voctemumafolhadepapelembranco.
Comomostraoexemplodecdigo,achaveparapermitiraentradadointervalodepginasparaorelatrio.
Adicioneumpardecaixadetextoourotadorescontrolesaumformulrioparadaraosusuriosumagamadeentrar.Fao
seoscampospadroa1paraapginainicialealgoridiculamentealtocomo999a
certificarsedetodasaspginassoimpressosseelesnotoqueselecioneointervalo.Esteumperfeito
recursoparaadicionaraoseuformulriodebasedecritriosdorelatrio.

Comoimprimir"Pginaxdey'emumrelatrio(ExemploPageXofY.frx/SCX)
UmadasperguntasmaisfrequentesfeitaspelosdesenvolvedoresdoVisualFoxProcomoobtero
nmerodepginasqueestonorelatrioparaqueelespossamimprimirxxPginadeaanorelatrio.Muitos
documentopacotesdesoftwarecentradacomoprocessadoresdetextotersidocapazdefazerissoporanos.
MuitosprodutosdeoutrosMicrosoft,comoopacoteOfficetemessesrecursos,entoporquenoVisual
FoxPro?Bem,maisumavezhumprocessoquepodeexecutarnossosrelatriosatravsdeobtereste
responda.
VisualFoxProarmazenaonmerodapginaatualemumavariveldosistemachamada _PAGENO.No
finaldorelatrio,onmerodepginasarmazenadonestavarivel.Asoluomaiscomum
propostoparaesteproblemaexecutarorelatrioduasvezes,primeiro:

pnTotalReportPagesPRIVADOS
pnTotalReportPages=0
REPORTFORM<ReportFormName>NOCONSOLE
pnTotalReportPages=_PAGENO

Ombitodavariveldememria(pnTotalReportPagesnoexemplo)deveser
PRIVATEumavezqueserutilizadoforadomtodo/procedimentoquedeclaradoquandoo
relatriocriado.Noseesqueadeinicializaro PRIVATEvariveldememriaquecontero
nmerodepginasantesdeexecutarorelatrioparaafasedepagecounter.Casocontrrio,pode
terproblemascomorelatrionocorrerumavezqueestavarivelprovavelmenteusadonorelatrio.Neste

532 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

apontarospnTotalReportPagesvariveldememriacontmonmerodepginasevocpodeusar
seasegundavezquevocexecutarorelatrio.

Figura17.1Oexemploderelatriocabealhomostraapginaxdey,nocantosuperiordireito
canto.

Aquiestumexemplodeosnmerosdepginaaserimpressonorelatrio.Elepermitequevoc
visualizarorelatrionomododedesign,semterdecriarototaldepginasvarivelcomantecedncia.

"Pgina"+ALLTRIM(STR(_PAGENO))+
IIF(TYPE("pnTotalReportPages")="N","de"+ALLTRIM(STR(pnTotalReportPages)),"")

Comoalternativa,aseguintelinhadecdigousadopormuitosdesenvolvedoresVFPparadeterminar
onmerodepginasemumrelatrio.:

REPORTFORM<ReportFormName>NOCONSOLEparaNUL

AmaiordesvantagemdoxxPginadatcnicayyqueorelatriorealmentefunciona
duasvezesoquepodeserdemoradopararelatriosmaislongos.AcaixadedilogorelatriodeimpressoVFPtambm
exibidoduasvezesduranteaimpressoparaaimpressora,umavezparaafasedecontagemeumavezparao
sadarealdorelatrio.Aovisualizarumrelatrio,odilogoexibidaumavezparao
contandofase.nossaexperinciaqueosusuriosfinaisencontraroacertodedesempenhosuperao
benefciodeteressainformao,masatcnicafuncionabemparaaquelesquevemissocomouma
deveter.

Comopermitirqueosusuriosparaselecionaronmerodecpias
(Exemplo
PageXofY.frx/SCX)
usuriosdeaplicativosamoparagerarrelatrioseelesgostamdedistribulosaosseusvriosco
trabalhadoresepatres.Assim,orequisitodeimpressodeumnmerodeterminadodecpiasum
pedidodedesenvolvimentodosistemafrequentequerequerumasoluogenricoaserdesenvolvido.
Asoluoumaplancie PARAlaoemtornodeum FORMRELATRIOumavezquenoconstrudonaclusulade
o REPORTFORM.Umainterfaceprecisadeserconstrudaqueirsuportarumutilizadorseleccionaronmerode
cpias,amenosquehajaumrequisitoespecficodequeumnmerofixodecpiassogerados.
Captulo17:GerenciamentodeRelatrios 533

Figura17.2Oformulriodeexemploquepermitequeosusuriosinsiramentre1e999cpiasde
umrelatrioparaaimpressora

OcdigodeexemploparalidarcomestatcnicaencontradonoExecutarRelatriocommandbutton.o
sadadepreviewrequerapenasumaiteraoatravsdageraoderelatrios.Nsachamosquepodeser
diversoparadesencadearumainterfacehostilpelousurioparafazerousurioprvisualizaoonmerodecpiasque
selecionar.Sugerimostambmalgunsquestionamentosapropriadasehouvervaisermaisdoque20oumais
cpiasfeitasdesdeacreditamosrvoressuficientesnaflorestatropicalsulamericanaterencontradoum
morteprematura:
IFTHISFORM.opgOutput.Value="Preview"
lnNumberOfCopies=1
lcOutput ="PREVIEW"
OUTRO
lnNumberOfCopies=THISFORM.spnCopies.Value
lcOutput ="Paraaimpressora"
FIMSE

PARAlnCount=1alnNumberOfCopies
REPORTFORM(lcReportName)&lcOutputNOCONSOLE
ENDFOR

Ocontroleexemplogiratrioondeasconfiguraesdepropriedadesopararestringironmerode
cpiasdesermenosdoque1emaiordoque999.
Outraopoparalidarcommltiplascpiasusaro PROMPTclusulasobrea FORMRELATRIO
comandopermitindoqueousuriofinalparaselecionarumnmerodecpiasseodriverdeimpressoraoferecesuportea
opo.Temosficadolongedo PROMPTclusulaporquenossosusuriosnoqueriaextra
esse
dedilogoexibidaapsaformatpicadeentradacritriosdorelatrioemnossasaplicaes.Estemtodode
selecionandoonmerodecpiasmosocontroleparaodriverdeimpressodoWindowsparaalavancaro
acapacidadedaimpressoraparaimprimircpiassemcorrerorelatriovriasvezes.Estaumaformamais
formaeficientedeobtermaisdeumacpiaparaumaimpressora.

Comoencontrara"Varivelnoencontrado"errosemumrelatrio
desenvolvedoresVFPqueusaramoReportDesigneremalgummomentotercorridocontrao
"<Varivel>noencontradovarivel"mensagemdeerroaotestarasuamaisrecenteaplicativoexecutvel.
Estamensagemagravante,umavezqueapresentadosemdizerondeaexpresso
falhasnorelatrio.Estaexpresso,porvezes,difcildeencontrarumavezquenopodeserdezenas
decamposnorelatrio.Paraagravaresteproblema,aexpressofalhapoderiaserna
534 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

clculodecampos,clculodevariveisderelatriooudeimpressoquandoascondies.Vocj
rastreouumaexpressoruimnorelatriodeoutrapessoanaimpressodeumobjetodelinhaQuando?
Condio.Confieemns,nomuitodivertido.
Felizmente,existeumatcnicaqueaceleraorastreamentodesseserrosdolorosos.Achave
paraumaresoluorpidasuspenderocdigodoprogramaapsoscursoresfinaissopreparados.Seeste
noprtica,prepararosdadosmanualmente.Umavezqueosdadossopreparados,modificarorelatrioe
visualizlo.Oerroserexibida.DepoisdefecharomododerelatriodeprvisualizaodoRelatrio
Designerirexibirocampodeexpressoqueoerroestocorrendo.Nesteponto,vocpode
fazeracorreo,salvarorelatrioetentenovamente.Repitaatquetodososerrossoerradicados.

Comoevitarterumrelatriodesativaromenudosistema
Jtinhaumavisualizaoderelatriofechareomenudesativado?HouveumerronoVFP5.0
quenotemoscertezafoicorrigidonomaisrecenteversodoVFP.Esteumdaquelesdolorosa,
intermitente,edifcildereproduzirerrosquenoacontecemcomtodososrelatrios.Asoluono
dolorosaporissovaleapenamencionarnestemomento.
Ospassosquetmsidocomumadesativaodomenudosistemasoasseguintes:
1.Executarumformulrioparaumrelatrioquecontmoscritriosdeseleco.
2.Visualizeorelatrionecessria(atravsdeumcommandbutton).
3.Fecheorelatrioutilizandoobotoparafecharajaneladevisualizaonoladosuperiordireito
canto.
4.Fecheoformulriocritriosdorelatrio.

Nesteponto,todosositensdomenuestodesactivadasapenascomoumformulriomodalestsendoexecutado.Seo
foradomododerelatriodeprvisualizaoutilizandoachavedeescapeoudasadacommandbuttonnaprvisualizao
usuriosai
barradeferramentasositensdomenunoestodesativadas.Asoluoparaembrulharo FORMULRIODERELATRIO
comandocomum menuPressionee POPMENU.

IMPULSOMENU_MSYSMENU
REPORTFORM<ReportName>PREVIEW...
POPMENU_MSYSMENU

Oimpulsomenuepoptemalgunsrequisitosdememriasignificativos,maso
potnciadamquinanecessrioparaexecutaraplicativosbaseadosVFP6.0podefacilmentelidarcomisso.

Comoagruparpginasderelatriosdiferentes
Hmomentosemquevrioslayoutsderelatriocompletamentediferentesprecisamserrecolhidosou
sequenciadonasada.Tivemosclientesquetmdocumentoslegaisquesoregularmente
impressaempapeltotalmentediferente,massoconsideradospartedeumpacote.Comopodeseobter
oReportDesignerparaimprimirrelatriosdiferentesparadiferentespginasdeimpresso,outotalmentediferente
layoutsdesercotejarjuntos?
Asoluocriamoslevoualgunsforadacaixapensar.Oprojetobsico
consistenautilizaodeumformulriodeseleocritriosdorelatriodeconduo.Estaformatemtodooselecionvelpelo
usurio

Captulo17:GerenciamentodeRelatrios 535

objetosdeinterfaceparadeterminaroconjuntoderegistrosdebase.Esteformulriodepoisde"drives"osrelatriospara
emsequncia.
impresso
Umavezqueousuriofazaseleocritriosdoobjetoderelatrioentraemao.Asequncia
podesermodeladonasetapasaseguir:
1.Asconsultassoexecutadosparaobteroconjuntoderegistroscorrespondentesseleesdousurio.
2.LoopStartatravsdoresultadodaconsultainicial.
3.Subqueryparaorelatriodeumfeitoparaobterumoumaisregistrosparaorelatriobaseado
naconsultainicial
4.FORMARELATRIO<relatrio1>.
5.Subqueryparaorelatriodedoisfeitaparaobterumoumaisregistrosparaorelatriobaseado
naconsultainicial.
6.FORMULRIODERELATRIO<relatrio2>.
7.Mantenharepetiratravsdetodososrelatrios.
8.Loopparaaetapa3atquetodososregistrossoprocessados.

Figura17.3Estaaarquiteturausadaparachamardiferentesrelatriosemseqnciaquando
embalagemeconfrontodediferenteslayoutsderelatrio

Noincio,oprojetoparecequemaisadequadoparaosrelatriosquenoimprimemnmerosdepgina
umavezquecadarelatrioirinicializaro _PAGENOvarivelpara1quandoorelatrioimpresso.Existeum
maneiradecontornarestalimitao,criandouma PRIVATEvarivelquemantmocontroledorelatrio
pginasimpressas.Inicializaravariveldememriapara0edepoisdecadarelatrio,adicioneovalorde
_PAGENOAele.Emnossosrelatriosquenormalmenteusamaseguinteexpressoparaimprimironmerodepgina
sobreorelatrio:

"Pgina"+ALLTRIM(STR(_PAGENO))

Nasituaodelayoutmultirelatrioprecisamosadicionaravariveldememriaprivadaparao
nmerodepginasnorelatrioatual:

536 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

"Pgina"+ALLTRIM(STR(_PAGENO+
IIF(TYPE("pnAllPrevPages")="N",pnAllPrevPages,0)))

Recomendamosverificarotipodavariveldememriaprivadaparaquepossaexecutaro
relatrioindependente(semoformulriodechamada).Seorelatrioforexecutadocomoprocessodeintercalao,o
variveljserdefinidoeorelatrioircorrerbem.Sevocestapenastestandoorelatrio
sozinho(isto,prvisualizardoReportDesigner),verificandootipodevarivelvaievitaruma
"Varivelnoencontrado"erro.Amaioriadosrelatriosnorequeremvrioslayouts,masseasituao
surgequandovocprecisadeles,pelomenosvocterumpontodepartidaparacomear.

Comoexibirumcostume'PrintingDialog"(ExemploContacts.frx,
ChangePrintingWindow.prg)
Aolongodosanosmuitosdesenvolvedorestmperguntadosobrecomoalteraro"Printing..."dilogoexibida
quandoumrelatrioenviadoparaumaimpressora.Umadasrazesmuitosdesenvolvedoresgostamdefornecersuaprpria
dilogoqueodilogoVFPobservaonomedorelatrioqueestaserimpressa.Figura17.4mostraum
exemplodestedilogo.Serque"timelistd.frx"temalgumsignificadoparaumusuriofinal?Estes
desenvolvedoresgostariadetermaiscontrolesobreovisor.issopodeserfeito?Claroque,casocontrrio
porquensimprimirumaseonocaptulo?

Figura17.4AcaixadedilogodeimpressoVFP

PrimeiroverifiqueoChangePrintingWindow.prgprogramadisponvelcomocaptulode
Desenvolvedorbaixararquivosdisponveisemwww.hentzenwerke.com.Ocdigodoprograma
podeserencontradaemListagem17.1.
Listagem17.1Essecdigoexibeumacaixadedilogopersonalizadaimpresso
LPARAMETERtcTitle,tcIcon,tcText

*NomedaJanelaVFPdajaneladeimpressopadro
#DEFINECcWIN_PRINTING"Imprimir..."

*Definirasvariveis
locais

lcFontLOCAL
lnSizeLOCAL
lcStyleLOCAL
lnTitleLOCAL
lnLeftBorderLOCAL
lnTopBorderLOCAL
lnHeightLOCAL

Captulo17:GerenciamentodeRelatrios 537

lnWidthLOCAL

*Apenasalterarajanelaseeleexistir
IFWEXIST(ccWIN_PRINTING)
IFEMPTY(WPARENT(ccWIN_PRINTING))
lcFont =WFONT(1,ccWIN_PRINTING)
lnSize =WFONT(2,ccWIN_PRINTING)
lcStyle =WFONT(3,ccWIN_PRINTING)
lnHeight =FONTMETRIC(6,lcFont,lnSize,lcStyle)
lnWidth =FONTMETRIC(4,lcFont,lnSize,lcStyle)+
FONTMETRIC(1,lcFont,lnSize,lcStyle)
lnLeftBorder=SYSMETRIC(3)/lnHeight
lnTitle =(SYSMETRIC(9)2)/lnWidth
lnTopBorder =SYSMETRIC(4)/lnWidth

DEFINEWindowCustomPrint
DEWLROW(ccWIN_PRINTING),WLCOL(ccWIN_PRINTING)
WROWSTAMANHO(ccWIN_PRINTING)lnTopBorder,
WCOLS(ccWIN_PRINTING)lnLeftBorder
SISTEMA
TTULOtcTitle
MINIMIZARZOOMFLOATFECHAR
conedearquivo(tcIcon)
FONTlcFont,lnSize
ESTILOlcStyle
CORRGB(0,0,0,192,192,192)

DEFINEWindowCustomPrintReport
DE0,0
TO(WROWS(ccWIN_PRINTING)lnTopBorder)/3,
WCOLS(ccWIN_PRINTING)lnLeftBorder
NENHUM
FONTlcFont,lnSize
ESTILOlcStyle
CORRGB(0,0,0,192,192,192)
INCustomPrintJANELA

AtivarjanelaCustomPrint
ATIVARccWIN_PRINTINGINDICADOREMCustomPrint
MoverajanelaccWIN_PRINTINGTO(lnTopBorder+lnTitle),lnLeftBorder
AtivarjanelaCustomPrintReport
@1,1SAYPADC(tcText,WCOLS("CustomPrintReport"))
FIMSE
FIMSE

RETORNA""

OcdigoparaafrentesevoctiverdesenvolvidonoFoxPro2.x.ParaaquelesFoxPro
promotoresquecomearamcomageraoVFP,ocdigopodenoserfcil.
Oprogramatemtrsparmetros.Oprimeiroottulodoformulrio,seguindoseoconedeforma,e
finalmente,umamensagemparaserapresentadonodilogo.Usandoa janelaDefinircomando,ns
podecriar,umaformadeestiloFoxPro2.xidadenamemria.A ativarajaneladecomando,emseguida,
fazcomqueajanelarecmdefinidovisvelecolocaemfoco.A moverajaneladecomando
tomandoodilogoVFPexistenteemovloparaforadatelavisvelparaqueonovodilogopersonalizada
vistoeonicodilogodeimpressovisvel.O @1,1SAYmostraotextodefinidoemque
linhanalinhaumecolunaumdaquelaforma.
538 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Omtododeobterodilogopersonalizadaaserexibidarequerumachamadadiretamenteapartirdeum
denunciarocampoparaoprocedimentoChangePrintingWindow.Oprogramadeterminaseo
relatrioimprimirouprvisualizarparaverseodilogoVFPestativo.Nscriamosumcampono
informarnottulorelatriooubandadecabealho.Estenovocampomodeladoapsoseguinte
expresso:

ChangePrintingWindow("impressopersonalizada","Print.ico","ImpressodeContatos...")

Humpardeinconvenientesaestaabordagem.Oprimeiroarazomaisatraente
Nsnormalmenteficarcomajanelanormal.Ocommandbuttoncancelarnoestdisponvel.
Portanto,ousurionotemaopodecancelaraimpresso.Estapodeserumacaractersticaemalgunscasos
quandoorelatriodeveserexecutado,noimportaoqu.Asegundaqueosnmerosdepginanoso
exibidocomoorelatriogerado.Nspodemosultrapassaresteproblemapelaadiodeumcampona
cabealhodorelatrioquechamaummtodopersonalizadoqueexibeo _PAGENOvarivelsobreocostume
Formato.

ComoalterarottulodajanelaVisualizaodeImpresso(Exemplo:
Contacts.scx/frx)
Muitosdesenvolvedoresnoqueremqueajaneladevisualizaodeimpressopadroemsuasaplicaes,pois
ottulodoformulriodevisualizaoexibeonomedoarquivoderelatrio.
OVFP REPORTFORMcomandotemuma JANELAclusulaquepermitequeosdesenvolvedoresparadefinirum
formarqueorelatriopodeserexibido.Aspropriedadesdedefiniodeformulriosousadospelorelatrio
emvezdajanelanativaVFPPreview.Aquiestumexemplodecdigodecomopodemosusareste
tcnica:

loReportFormLOCAL
lcClassPathLOCAL
lcReportLOCAL

lcReport ="Contatos"

*Criaraformaqueaprvisualizaocorrereescondertodasasoutrasjanelas.
loReportForm=NEWOBJECT("frmPreview","ch16.vcx")

HideWindowsALL

*Faaasdefiniesdajanelacomsuaspreferncias
COMloReportForm
.Altura =_SCREEN.Height30
.Largura =_SCREEN.Width10
.Nome ="LoReportForm"
.Caption=.Caption+""+LcReport

TECLADO"{ctrl+f10}"
ENDWITH

REPORTFORM(lcReport)JaneladevisualizaoloReportForm

*Solteasformasetrazeroutrasjanelasdevolta
loReportForm.Release()

Captulo17:GerenciamentodeRelatrios 539

MostrarasjanelasALL

RETORNA

Umdosproblemasencontradosduranteodesenvolvimentodestatcnicafoiadequeo
formarWindowStatedefiniodapropriedadenaclassenoimporta.Nsconfigurloparamaximizado,mas
aformasemprevemtonaunmaximized.Nstentamosdefinilonaclasse,enstentamosdefinilo
nocdigoumavezqueaclassefoiinstanciado.Umavezquenemumadessasconfiguraestrabalhouforamos
o TECLADOcomandoparamaxoformulrio.
AclassedeformulrioqueusamosnasamostraschamadofrmPrevieweestnoCh16.vcx
bibliotecadeclassesincludasnocaptulodearquivosdedesenvolvedordedownloaddisponvelem
www.hentzenwerke.com.
Asnicaspropriedadesdefinidasnestaclassequenosoasconfiguraespadrosoaformade
AlwaysOnTopeLegenda.HumasegundaclassequeumasubclassedofrmPreview
classechamadafrmPreviewSDI.Esteumdenvelsuperior(tambmconhecidocomoumainterfacededocumentonico
ouSDI)formulrioutilizadoparaomesmofim,masparaumaaplicaobaseadaSDI(consulteaseco"Como
mostrarumavisualizaoderelatriocomoumaseodenvelsuperiorformulrio"nestecaptulo).
O REPORTFORMcomandofazcomqueoformulriopersonalizadoVisibleporissonohnecessidadedelidarcom
issonocdigo.NsocultartodasasoutrasjanelasdeaplicativosapenasnocasodeexistiremquaisquerAlwaysOnTop
formaserestaurlosquandoaprvisualizaoestiverconcluda.

Comomostrarumavisualizaoderelatriocomoumformulriode
nvelsuperior
ContactsSDI.scx/frx) (Exemplo:
VisualFoxPro5.0deuaosdesenvolvedoresacapacidadedeconstruirformulriosdenvelsuperior.Estasformasde
foradareadetrabalhodoVFP.VisualFoxPro6.0introduziuumnovorecursocomo INDICADOREM
executar
clusulade REPORTFORMcomandoparavisualizarrelatriosemumformulriodenvelsuperior.Estanova
permitequeosdesenvolvedoresqueestoconstruindoaplicaesSDIparavisualizarrelatriossemexpor
funcionalidade
oambientedetrabalhoVisualFoxPro.
Estadicaestconstruindosobreasoluodescritanaseo"Comomudarottulode
Imprimirjaneladevisualizao".Vocprecisaconstruirumaclassedeformulriocomaaparnciadesejada.Issopode
serumaclassedeformulrioVFPquecriadocomocriadordeformulrios,ouprogramaticamentepormeiodo
DEFINECLASS.AchavedefiniroShowWindowpropriedadepara2comoformulriodenvelsuperior.

540 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura17.5formulriodeentradadedadosdenvelsuperioredenvelsuperiorvisualizaoderelatrio

AclassedeformaqueusamosnasamostraschamadofrmPreviewSDIeestna
Ch16.vcxbibliotecadeclasseincludonocaptulosdesenvolvedorarquivosdedownloaddisponvelem
.www.hentzenwerke.comEstaclasseumasubclassedaformafrmPreviewportanto
olharparaalgumasdaspropriedadespadrodefinidosnestaclassetambm.
Oconceitodenvelsuperiorrelatriodeprvisualizaopodesertransportadomaisumpasso,fazendoo
formadevisualizaodorelatrioserumMDI(MultipleDocumentInterface)formulriofilhodeoutrodenvelsuperior
Formato.ApropriedadeadicionalquetemdeserconfiguradoparadistinguirestaaMDIFormpropriedade.
DefinaoMDIFormpropriedadepara .T..Avantagemdestapropriedadeparadesenvolvedoresquetm
umaplicativoSDIeterumformulrioprincipalqueoutrasformasdeMDIexecutadodentro.Istodamesma
olharesentirdeumaaplicaoVFPpadro,masmaiscontrolesobreamanipulaodeeventos/mtodode
aprincipalformaquevocnotemcomoobjeto_screenVFP.
QueremostambmnotarnestemomentoqueomenudosistemaVFPeJaneladecomandoso
desativadacomoseumformulriomodalestsendoexecutadoquandovocvisualizarrelatriosemumformulriodenvel
afirmouqueessecomportamentopordesign.Acausaparaissoqueavisualizaodorelatriono
superior.Microsoft
seuprprioloopinternamentedentroVisualFoxProeimpedequeoutrasjanelasdefuncionar.
IssoestdocumentadonoartigoQ178384daMicrosoftBasedeConhecimento.Asoluoadicionarum
NOWAITparmetroparaachamadaparao REPORTFORM.Notemoscertezadequeasramificaessotodos
toimportante,umavezquenuncaverajaneladecomandoemumaplicativodeproduo.o
menuusadoemumaplicativoSDInoomenudosistemaVFPtambm,masnspensamosqueesteera
importantemencionar,casovocestejadesarmadoporestecomportamento.

Comoprvisualizarvriosrelatriosdeumasvez(ExemploMultiReps.scx)
UmadasvantagensemocionantesdoVisualFoxProafacilidadedetervriasinstnciasdeum
Formato.Osusuriospodemcompararosfactosrastreadossobreclientesumemumformulrioeclientedois

Captulo17:GerenciamentodeRelatrios 541

emoutraformadentrodeumaplicativo.Serqueesserecursosejaagradvelcomrelatriosbem?
Absolutamente!
O REPORTFORMcomandotemesta NOWAITclusulaquenotemabsolutamentenadaavercom
o WindowWAIT.Eleprojetadoparapermitirqueocdigoaseguirachamadarelatriodeexecuoe
deixaorelatriodisponvelnajaneladorelatriodeprvisualizao.Parapermitirqueosusuriosabrirvriosrelatrios
edeixeajaneladeprvisualizaopermanecernatelausandoaseguintesintaxe:

REPORTFORM(ReportName)PREVIEWNOWAIT

Issofuncionabem,amenosquevocquisertrazerumoutrovisualizaodorelatriodomesmorelatrio.
Estepodeseromesmonomedorelatrio,masinformaesdeconsultadiferente,ouomesmorelatrioexatopara
ousuriopodeolharparadiferentespginas.Seonomedorelatrioomesmo,masvocquerescolherum
informarpormaiscritriosdeconsultaquevocnopodeusaromesmonomedorelatrio.(Consulteaseo"Como
osusuriosfinaisparamodificarlayoutsderelatrio"destecaptuloparaummtododegerarnovos
chegar
arquivosderelatriodemetadadosparacontornaresseproblema.)

AclusulaNOWAITtemumefeitocolateralinteressante.Desdequeorelatrio
cdigoacabadoeoutracorreatrsdoFORMULRIODERELATRIO,parecequeo
OmododevisualizaodorelatrioperdeoDataEnvironmentoupelomenoso
cursornoestligadoa.Clicandonabarradeferramentasdevisualizaoparairparaapgina2
acaixadedilogoabertatabelaVFP.Esteimpraticvelemumaplicativodeproduo.o
ouposteriortraz
soluoparaissousarumDatasessionprivadaparaorelatrio.
542 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura17.6Esteumexemplodedoisdosmesmosrelatrioscorrendoemduasdiferentes
janelasdevisualizao.Cadarelatrioposicionadoemumapginadiferente.

Sevocnoprecisaexecutaromesmorelatrioquevocpodeexecutarrelatriosdurantetodoodiaetodaanoiteneste
moda(desdequetodoselestmDataSessionsprivadas)dentrodoslimitesdamemriaearquivo
alas.

Comoremoverinformaessobreaimpressoranosrelatriosde
produo
HumaabundnciadearmadilhasemumprodutotocomplicadocomoVisualFoxPro.Umdosmelhor
problemasconhecidosasinformaesdaimpressoracodificadoqueficaarmazenadonosmetadadosdorelatrio.
Aquestogiraemtornodaimpressorautilizadacomoorelatriodesenvolvido.Informaesespecficaspara
estaimpressoraarmazenadocomorelatrioepodecausarconfusocomumdriverdeimpressoradiferenteusado
noambientedeaplicativodeproduo.
Umexemploodesenvolvimentoderelatrioscomumaimpressoraquesuportaimpressofrenteeverso.Seo
ambientedeproduodoclientetemimpressorasquenosuportamaimpressoduplex,vocpoderiater
problemasdeimpressodosrelatrios.Amesmacoisapoderiaacontecerseaimpressoratemumdesenvolvimento
maiorresoluodoqueasimpressorasdeproduo.
Asoluoenvolvehackearosdadosdaimpressoraparaforadametadadosrelatrio(FRX).o
ainformaoarmazenadanoprimeiroregistodorelatrio.Alinhainferiorquemuitosegura
embrancoparaforatantooTAGecamposTag2.ApartedifcilvemcomocampoEXPR.este
campoprecisasermodificadodeformaseletiva.EmEXPRvocpodeespecificaronmerodecpias,os
orientaodapgina,aimpressoradeusar,ealgumasoutrascoisas.NscomentaraDEVICE,

Captulo17:GerenciamentodeRelatrios 543
DRIVER,OUTPUT,DEFAULT,PrintQuality,yresolution,TTOPTIONe
opesdeduplexparatodososrelatrios,colocandoum"*"nafrentedecadaoponocampoEXPR.
Orestodosquetemosqueencontrou(orientao,PaperSize,cpias)emnosso
relatriosnotiveramumefeitonegativo.
UmasoluoautomatizadaparaesteproblemadiscutidonocaptuloHooksprojetocomum
seochamada"ComoremoverasinformaesdaimpressoraapartirVFPrelatrios".

Comopermitirqueosusuriosfinaisparamodificarlayoutsde
relatrio(Exemplo
ModiReports.scx)
Temosacertezadecaminhosquemuitosdesenvolvedorestmcruzadocomumclientequeumusurioforteo
(Oupensaqueelesso)paraabriroVFPReportDesignerecriarosseusprpriosrelatrios.este
suficiente
seoirmostrarcomovocpodeexporoVFPReportDesignerparaosusuriosemtempodeexecuomodo
elespodemnosmodificarrelatriosexistentes,maspodecriarnovosrelatriostambm.Orelatrio
Designerestdisponvelemtempodeexecuovocnovaiobtero"Recursonodisponvel"infameerros
quevoccomeacomosoutrosdesigners.
Umadaschavesparaabrirafuncionalidademanterosrelatriosexcludosna
projetareenviloscomoexecutvelparainstalaonositedocliente.Osarquivosderelatrioso
tipicamenteincludasnoarquivodeprojetoeincorporadonoEXEdistribudoouarquivodeAPP.Seosusuriosesto
indoparamodificarorelatrio,elesdevemserexcludosnoprojetoparaqueelesnosoincorporadasao
executvel.Essesarquivosdeorigemrelatrioestoincludasnoprogramadeconfigurao/instalao.Destejeito
osusuriospodemmodificarosrelatriosatravsdeumaversodedesenvolvimentodoVisualFoxProouatravsdo
executvelquevocconstruiuparaeles.
OsusuriosfinaisvaiprecisardealgumforteconhecimentotcnicodoVFPReportDesignerna
esteponto.Issoprovavelmentevaiexigiralgumtreinamentodaequipededesenvolvimentoouformaofora
classes.Podemosrecomendarquecomprarumacpiadestelivroparalerosdoiscaptulossobre
relatriosparaentendermelhoralgumasdascomplexidadeseabordagensparaaresoluoderelatrios
problemas.Srio,osusuriosteroumforteentendimentodoesquemadebancodedadoseo
ReportDesignerdesercapazdeusaressafuncionalidade,masquefoiprdeterminadoantesdotempo
quandoosusuriossolicitaramessacapacidadeadhoc.

544 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura17.7Exemploexecutarexecutveltempocomconfiguraespadromodificandoumrelatrio
Paracriarumnovorelatrioquevocpodetomarumadeduasabordagens.Oprimeirofazerumasimplese
simples CREATEREPORTcomando.Oformulriodeexemplo(ModiReports.scx)temestecdigono
CriarrelatriocommandbuttonCliquemtodo.Aoutraopoaproveitaratcnica
discutidonaseosobre"Comocriarummodeloderelatrioparaumprojeto"eparaexecutarcdigocomo:

CRIARRELATRIOuntitled

IssofarcomqueomodeloderelatriochamadoUntitled.frxousvaitrazeropadro
VFPlayoutdorelatriopadroseoUntitled.frxnoexiste.
AsbarrasdeferramentasRelatrioDesigners(controlesderelatrio,layoutepaletadecores)osEstadosso
armazenadasnoarquivorecursodoaplicativo(FoxUser.dbf)emlinhascomcamposdeIDiguala
"TTOOLBAR".Amaneiramaisfcildegarantirqueseuaplicativoteracessoaonecessrio
barrasdeferramentascriarumarquivoderecursolimpo,definilocomooarquivoderecursoparaodesenvolvimento
meioambiente,modificarumrelatrio,abrirtodasasbarrasdeferramentas(atravsdomenuView),esalvarorelatrio.
Guardarforadoarquivoderecursosparaaplicaesquevocpretendelanarcomamodificaorelatrio
capacidade.Estearquivodeverserenviadocomoseuapp.
Outromtodocriarum"View"padmenuchamado_msm_view.Nestemenuadicionarum
barVFP.Onmerodebarrasaseradicionadoo_mvi_toolb.Tendoestaopodemenuemsua
aplicativofarcomqueasbarrasdeferramentasdisponveis.
Hperigosemexporessafuncionalidade?Emumapalavra,absolutamente!Agrandepreocupao
aexposiosuporteextracomocliente.Tolegalquantoesterecurso,podemosdizercom
confianaqueosusuriosvosemetememproblemasporquebrarocdigoevocvaitera
ligarparaosuporte.Adesvantagembempenaemborasevoctembonsclientesquesocapazes
aesterespeitoevocpodeeconomizartempoeenergiafazendoessespequenosajustesaquieali.

Captulo17:GerenciamentodeRelatrios 545

ComoimprimirumcampomemorandocomformatoRichText(Exemplos
RtfReport1.frx,RtfReport2.frx,ReportsProc.prg)
Umadasvantagenslegaisdeumdesignergrficoderelatriosoaumentodefontesdefazer
umrelatrioaparecermaispalatvel.Umdosproblemasapresentadosparaosdesenvolvedoresfontesemmudana
notextoemumcampo.AsoluoparaestasituaoparaalavancaroRichTextFormat(RTF)
dedocumentos.Estetextopodeserarmazenadanamemriadeum(ouemgeral)decampodentrodeumquadro.este
podeserimpressoemumrelatrioVFPusandoocontroleacopladoimagem/ActiveXquesemelhanteem
formato
muitasmaneirasdeOleBoundControldeumformulrio.
Existemduasabordagensquejtrabalhei.Aprimeiraopo(demonstradona
RTFReport1.frxexemplo)paraarmazenarodocumentoRTFnumcampogeral.Ocampogeral
podeserdirectamenteaproduodeumrelatrioporligaodocampoparaocontroloderelatrio.bemconhecido
queoscamposgeraisVFPincharatalpontoqueelestomammaisespaodoqueooriginal
documentos,portanto,muitosdesenvolvedorestmevitadolos.

Figura17.8relatrioMulticolunademonstrandosadadoFormatoRichText
documentosarmazenadosemumatabelaVFP

Asegundaabordagem(demonstradonoexemploRtfReport2.frx)paraarmazenaraRTF
documentosemumarquivodememorando.Vinculandoorelatrioparaumcampomemorandoquecontmo
svaiexibirocdigoRTFcomotexto,noutilizeascaractersticasdeformatao.Asoluo
cdigoRTFembruto
copiarocdigoRTFparaumarquivotemporrioeanexloaumcursortemporrioemum
campogeral.Orelatrioentoligadoparaocampogeraltemporrianotemporria
cursor.ColocarodocumentoRTFemumcursortemporrioremoveogeneralpermanente
campoinchaodesdeocursordesaparecequandoelafechada.Oprocessooseguinte:
1.ModificarasuamesaaplicativoparaqueelecontmumcampomemorandochamadomRTFTextpara
guardarodocumentoRTFcru.
2.PreenchaatabelacomosdocumentosRTFdesejados.
3.Adicioneoseguintecdigoaoseuarquivodeprocedimento:
*ReportsProc.prg
#DEFINEccRTFFILE "Temp.rtf"

546 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

*EsteprocedimentoirpouparcdigoRTFcampodememorandoparaum
*ArquivoRTFdocumentonodisco,emseguida,anexloaumtemporria
*CursornoumcampoGeral
**********************
PROCEDIMENTOAppendGenRTF
**********************
LPARAMETERtcMemoFieldName

lcRTFTempDirectoryLOCAL
lcRTFTempFileLOCAL
lcOldSelectLOCAL
lcOldSafetyLOCAL

lcRTFTempDirectory=ADDBS(SYS(2023))
lcRTFTempFile =LcRTFTempDirectory+ccRTFFILE
lcOldSelect =SELECIONAR()
lcOldSafety =SET("SAFETY")

*CopieomemorandoRTFatualparaumarquivo
OFFSEGURANASET
COPYMEMO(tcMemoFieldName)a(lcRTFTempFile)

*Anexaaocursortemporrio
SE!USADO("curRTFGeneral")
CRIARCURSORcurRTFGeneral(gRTFg)
FIMSE

SELECIONARcurRTFGeneral
APPENDBLANK
APPENDGENERALgRTFFROM(lcRTFTempFile)CLASSEWord.DocumentLIGAO

SELECIONAR(lcOldSelect)
RETURN.T.
ENDPROC

*Esteprocedimentovaisairembranco(remover)oRTFGeralcampo
*EapagaroarquivoRTFtemporria
**********************
PROCEDIMENTOBlankGenRTF
**********************
lcRTFTempDirectoryLOCAL
lcRTFTempFileLOCAL
lcOldSelectLOCAL
lcOldSafetyLOCAL

SE!USADO("curRTFGeneral")
*Nadaparafazer
OUTRO
lcRTFTempDirectory=ADDBS(SYS(2023))
lcRTFTempFile =LcRTFTempDirectory+ccRTFFILE
lcOldSelect =SELECIONAR()
lcOldSafety =SET("SAFETY")

SELECIONARcurRTFGeneral

OFFSEGURANASET
CamposembrancogRTF
ERASE(lcRTFTempFile)
Captulo17:GerenciamentodeRelatrios 547

SELECIONAR(lcOldSelect)
SETSAFETY&lcOldSafety
FIMSE

RETURN.T.
ENDPROC
4.Crieumrelatriocomumaimagem/ActiveXcontroleligadonabandadedetalheseseligam
loparaocampogRTF.
5.AdicioneumachamadaparaAppendGenRTF(<RTFMemofieldname>)naOnEntry()eventos
dafaixadedetalhedorelatrio.Issopreencheocampogeraldomemorando
campo.
6.AdicioneumachamadaparaBlankGenRTF()noeventoOnExit()dabandadedetalhesda
relatrio.IssoremoveodocumentoRTFpreviamenteimpresso.
7.Certificarsedeque SETPROCEDUREparaReportsProcADITIVO,executarorelatrio.
8.CadaumdosseusdocumentosRTFimpressanabandadeseurelatriodedetalhe!

Comoselecionarabandejadepapel
SevocestiverescrevendoumrelatriousandooReportDesigner,vocpodeconfiguraroalimentadorautilizar(acada
vezquevocimprimirorelatrio)escolhendoArquivoConfigurar/pginanomenue,emseguida,empurrandoo
commandbutton"Configuraodeimpresso".Lvocpodedefinirqualbandejavocquereelesalvocomo
relatrio.Voctambmpodemudloemtempodeexecuosedesejarouseousuriodefinirasconfiguraesem
runtimevia SYS(1037).
SevocnoestusandooReportDesigner,entovocdevecontarcomo (1037)SYSconfigurao.Voc
nopoderealmentemudaraconfiguraodaimpressorapormeiodeprogramao,masvocpodefingir.Sevocsouber
impressorachamadode"HPLaserJet4P"naseoimpressorasdoPaineldecontroleevocquerescolher
o
aalimentaomanual,vocpodefazeroseguinte:

SETimpressoranomeie"HPLaserJet4P"

IFPRTINFO(7)!=4 &&Senodefinidaparaalimentaomanual
TECLADO"{TAB}{TAB}{TAB}M{ENTER}"
=SYS(1037)
FIMSE

EstecdigoinstruiVFPparadirecionarasadaimpressaemumaimpressoradefinidonoWindowscomo
"HPLaserJet4P",emseguida,verificaparaverseaalimentaomanualnoestselecionada.Seno,ento
trazo SYS(1037)dilogo(Configurarimpresso)eencheobufferdetecladocomo
teclasnecessriasparaescolherdealimentaomanualnalistaOrigemdopapel.(Estamossupondo
noexisteoutrafontedepapelquecomeacom"M").Umdosproblemasqueesteocdigo
muitoespecficoparaodriverdeimpressoraeseofabricantedaimpressoramudaodriver,vocpode
descobrirqueocdigonoestmaisfuncionando.

548 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

OutrasalternativasaoRelatrionativaDesigner
ToeficientequantooReportDesigner,umpoucodesajeitadoetemalgumaslimitaes.Umavezquevivemos
emummundobaseadoemcomponentes,porquenoaproveitaralgumasdasoutrasopesdisponveisparans?este
seoirabordarumpardetcnicasqueusamosemnossodesenvolvimentodeaplicativos
experincia.

ComousarautomaoOLEparaoWord(ExemploWordAuto1.prg,
WordAuto2.prg)
Umadascaractersticasmaisestranhasquejvimosnahistriasoftwareeraumprocessamentodetextoaddin
paraLotus123emmeadosdadcadade1980.Desenvolvedoresgostamdetentarenfiarumpinoquadradoatravsdeuma
buracoredondo.NohnenhumarazoparatentarempurrarVisualFoxProparasetornarumprocessadordetexto
quandohumasriedeexcelentesaquelesjnomercado.AutomationWordviaVisual
BasicforApplications(VBA)permitequeosdesenvolvedoresparamanipularMicrosoftWordepodeser
usadoparacriarrelatrios.
EstaseotentardemonstraralgumasnoesbsicassobrecomosubstituirWordpara
oReportDesigner,nocomoumguiacompletosobrecomomanipularWord.Parasabermaissobreesta
irparawww.hentzenwerke.comeprocuraroTamarE.GranoreDellaMartin
livro."AautomaodeescritriocomVisualFoxPro."
Osexemplosapresentadosparaestaseomostraralgunsconceitosbsicosquevocprecisaparaimplementar
quandoautomatizaroWord.OprimeiroparaobterumarefernciadeobjetoaprpriaPalavracomumachamadapara
CREATEOBJECT("Word.Application").

Listagem17.2EssecdigousaautomaoparacriarumatabelanoWorde,emseguida,formata

*WordAuto2.prg
LoWordLOCAL
loDocumentLOCAL
LOCALLorange
loTableLOCAL

#DEFINECCCRCHR(13)
#DEFINECcTABCHR(9)

CH16OPENDATABASE
USEv_shortcontactlistIN0
v_shortcontactlistSELECIONAR

lnRecCount=RECCOUNT("v_shortcontactlist")

LoWord =CREATEOBJECT("Word.Application")
loWord.Visible=.T.

*Crieumnovodocumentousandoomodelopadro"Normal"
loDocument =LoWord.Documents.Add()
Lorange =LoDocument.Range()

*CriarumatabeladoWordcomumalinhaextradedadose3colunas
loTable=loWord.ActiveDocument.Tables.Add(LorAnge,lnRecCount+1,3)

Captulo17:GerenciamentodeRelatrios 549

COMloTable
COM.Rows[1]
.Cells[1].Range.InsertAfter("Name")
.Cells[1].Range.Font.Name="Tahoma"
.Cells[2].Range.InsertAfter("Companhia")
.Cells[2].Range.Font.Name="Tahoma"
.Cells[3].Range.InsertAfter("Email")
.Cells[3].Range.Font.Name="Tahoma"
.Shading.Texture=100
ENDWITH

SCAN
COM.Rows[RECNO()+1]
.Cells[1].Range.InsertAfter(ALLTRIM(Last_Name)+","+
ALLTRIM(First_name))
.Cells[1].Range.Font.Name="Tahoma"
.Cells[1]=10.Range.Font.Size
.Cells[2].Range.InsertAfter(ALLTRIM(Company_Name))
.Cells[2].Range.Font.Name="Tahoma"
.Cells[2]=10.Range.Font.Size
.Cells[3].Range.InsertAfter(ALLTRIM(EMAIL_NAME))
.Cells[3].Range.Font.Name="Tahoma"
.Cells[3]=10.Range.Font.Size
ENDWITH
ENDSCAN
ENDWITH

lcDirectory=FULLPATH(CURDIR())

loWord.ActiveDocument.SaveAs(lcDirectory+"ContList.doc")
loWord.Quit()

LIBERTAOloDocRange
LIBERTAOloTable
LIBERTAOLorange
LIBERTAOloDocument
LIBERTAOLoWord

RETORNA

*:EOF:*
550 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Figura17.9DemonstraodedadosVFPsendoapresentadonoMicrosoftWord

Comoficoudemonstradonasamostras,gerandorelatriosnoWordpodecausarumdesenvolvedor
marchaparaforaumpoucodecdigo.umprocessomuitomanual.Umamaneiradeevitarissodesenvolver
algunsmodelosdoWord(.dot)arquivosdeantecedncia.bookmarksqueusamos,quepodemserpreenchidos
comdadosVFP.Osfavoritossonomeadosespaosreservadosdentrodeummodelodedocumento.o
seguintecdigoumamaneiradelerosnomesdosmarcadoresemumamatriz:

lnCountMarksloWord.ActiveDocument.Bookmarks.Count=()

DIMENSOLamark(lnCountMarks)

PARAlnCount=1alnCountMarks
Lamark[lnCount]=loWord.ActiveDocument.BookMarks(lnCount).Name
ENDFOR

Umavezqueosmarcadoressodeterminadosapartirdomodeloquevocpodecombinloscomo
dedadosquetemdeserinseridonoindicador.Estetratadocomocdigocomosesegue:

loWord.ActiveDocument.Bookmarks["Cidade"].select()
loWord.Selection.TypeText(lcCity)

OmtodoSelectdestacatodoomarcadoreomtodoTypeTextsubstituilo
comotextoquepassado.Umapalavradecautelacadamarcadordeveserpreenchidocom
dadosdecaracteresquevocvaiprecisarparatraduziloparaotipodecaractereantesdeenfilono
documentodoWord.

Comosadaparaoutrostiposdearquivo
Oavanodeferramentasdeusuriofinaltempermitidoodesenvolvedordoaplicativoparaseconcentrarna
componentesnonotificaodedesenvolvimentodeaplicaes.Maisemaispessoasestoficando
proficientecomasferramentasdoMicrosoftOfficecomoWord,ExceleAccess.Estasferramentastmpoderosa
Grficoserelatrioscapacidades.HtambmoutrasferramentascomooLotus123,QuattroPro,e
Captulo17:GerenciamentodeRelatrios 551

Visio.desenvolvedoresVFPtemumpardemaneirasdeaproveitaressasferramentas.Oprimeirorequeruma
compreensodoVisualBasicforApplications(VBA)eescrevercdigoparaautomatizarprodutos.
Infelizmente,esteconceitosestdisponvelparaferramentasqueimplementaramVBAetm
expostaumainterfacequepodesermanipuladapormeiodeautomao.Asegundaemaisgenrico
mtodoexportarqualquerumdeumasriedediferenteslayoutsdearquivoscomunsparaquepossamserimportados
emoutrasferramentas.
Hmuitosbenefciosbviosparaalavancaressasferramentasusuriofinal.Omaioropreenchimento
emrecursosquenosonativosparaVisualFoxPro.VFPnopodeseraferramentade"fazertudo"que
poderiadesejar.Vivemosemummundodedesenvolvimentobaseadoemcomponenteshoje.Issopermitequeos
paraadicionarfuncionalidadesaplicaes,independentementedascaractersticasMicrosoftfornecedentroVFP.
desenvolvedores
Asegundavantagem/benefciodeusarasferramentasdeusurioscomexperinciaemqueelespodemcriar
qualquersadaoseucoraodeseja,dentrodolimitedaferramenta.Issotambmpermitelhesreduzirasua
investimentofinanceironociclodedesenvolvimentodesoftwarepersonalizadoepermitequeosdesenvolvedoresde
aconcentrarsenaspartesdodesenvolvimentodeaplicaesemquesedestacam.
software
Existemdoiscomandosquepodemserutilizadosparacriarficheirosnativasparaoutrospacotesdesoftware.
A EXPORTcomandogeradiferentesformatosdearquivodeplanilha.Osegundocomando, COPY
TO,podegerartodososarquivosqueo EXPORTcomandopodeemuitosoutros.Eletambmtemalguns
maisclusulasquelhedomaiscontrolesobreoscamposqueseroincludosnoarquivoexportado.
Tudoissoresumesea,capacidadederelatriosadhoccompletasempredesejouqueonosso
usuriospedirparaquasetodasasaplicaesquedesenvolvemos.Achaveparaumaimplementaobemsucedida
deHadHocabstraindodeinformaoacomplexidadedomodelodedados.Istoondea
exibieseconsultasestabelecidaspodeviracalhar.Tendoestespredefinidaremovea
educaodasassociaesexternasparaosusurios.Elepodeserumpoucofrustranteexplicandoumnormalizada
bancodedadosparaosusuriosquemaisdoqueentenderonegcio,masnotemidiasobrerelacional
teoriabasededados.
porissoquensfornecemosumainterfacequepermiteaosusuriosselecionarotipodedadosqueelesquerem
eexportloparaumnmerodediferentesformatosdearquivo.Osformatosquetrabalhammaiscomumente
comsoSDF,WK1,CVS,XL5,FOX2X(freemesaDBFS),edelimitadas(vrgulaeguia).
Istofuncionamelhoremconjuntocomumadasferramentasdeconsultacomerciaisoumesmoumcaseiro
formulrioquepermiteaosusuriosselecionardadosespecficosouospontosdevistaeconsultaspredefinidas.

ComocriarHTMLesadadetextoASCII(ExemploHTMLMerge.prg)
FoxProtevea TEXTMERGErecursoparagerararquivosdetexto,desdesuasrazesnoDOS.Hoje,
desenvolvedoresVisualFoxPropodemalavancaressacapacidadedesadapoderosaparagerardinamicamente
pginasHTMLearquivosdetextoASCII.
Existemalgunsconceitosquevocprecisaentenderparaobterresultadodajunodetextogerado.o
SETTEXTMERGEcomandoprecisaserchamadoduasvezes.Aprimeirachamadaligao TEXTMERGE
funcionalidade.Asegundalinhaabreoarquivo,queasadadirigida:

SETTEXTMERGEON
SETTEXTMERGETO(tcFileName)ADITIVONOSHOW

O ADITIVOclusulasobrea SETTEXTMERGEcomandopermiteanexarsadaparaum
arquivoexistente,e NOSHOWsemelhanteao NOCONSOLEclusulasobrea FORMREPORT,eleremoveo
ecoapartirdodesktopVFP.Oarquivoabertonamesmamaneiraqueaaberturadeumarquivousando

552 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

aentradadearquivodebaixonvelVFPesadadocomando FOPEN().Oidentificadordearquivoarmazenadono
_TEXTVariveldosistema.IssolhedacapacidadedetambmusararquivodecomandosdebaixonvelIOpara
derivarinformaesqueoarquivoestsendogerado.Nalistagemdeexemplo,usamoso fseek()
funoparadeterminaronmerodebytesnoarquivo.

Listagem17.3EstalistagemdecdigoparcialgeraHTMLquepodeservisualizadoemumweb
navegador

*HTMLMerge.prg
LPARAMETERtcFileName
#DEFINEccHTMLTEMPLATEHEAD [TemplateHead.htm]

IFRECCOUNT()>0
*Copiarmodeloparaonovoarquivoestamoscriando
CpiadearquivoccHTMLTEMPLATEHEADTO(tcFileName)

*Abranovoarquivoemesclarrestodotexto
SETTEXTMERGEON
SETTEXTMERGETO(tcFileName)ADITIVONOSHOW

*Designao
\<Palign="center"><fontface="Tahoma"><b>1001AmostraDicasListadecontatosHTML
\\</B></font>
\<P></p>
\<Tableborder="0"width="900">

*CriarlinhadeHTMLparatodososregistrosnoconjuntodedados
SCAN
\ <Tr>
\ <Td><fontface="Tahoma"size=2>
\\ <<ALLTRIM(last_name)+","+ALLTRIM(first_name)>></font></td>
\ <Td><fontface="Tahoma"size=2><<ALLTRIM(EMAIL_NAME)>></font></td>
\ <Td><fontface="Tahoma"size=2><<ALLTRIM(company_name)>></font></td>
\ <Td><fontface="Tahoma"size=2><<ALLTRIM(cidade)>></font></td>
\ <Td><fontface="Tahoma"size=2><<Estado>></font></td>
\ <Td><fontface="Tahoma"size=2><<postalcode>></font></td>
\</Tr>
ENDSCAN

*Envolvaseorodapdorelatrio
\</Table>
\<P><fontface="Tahoma"size="2">
\<<DATETIME()>><br>
\<<>>TcFileName

*Obteronmerodebytesnoarquivo
lnFileSize=fseek(_TEXT,0,2) &&Determineotamanhodoarquivo,atribuirapnSize

*ObterotamanhodoarquivousandooarquivodecomandosdebaixonvelIO
\<br><<"A"+tcFileName+""+ALLTRIM(STR(lnFileSize))+"bytes".>>
\</Font></p>
\</Body>
\</Html>

*FecheoarquivoedesligarTEXTMERGE

Captulo17:GerenciamentodeRelatrios 553

SETTEXTMERGETO
SETTEXTMERGEOFF
FIMSE

Figura17.10DemonstraodedadosVFPsendoapresentadoemumnavegadorweb

Nalistagemdeexemplo,usamosuma cpiadearquivodecomandoparacopiarumarquivoparaomesmo
planejarparagerarusando
arquivocomons TEXTMERGE.Emseguida,abraoarquivocomo ADITIVOclusuladeanexar
obtermaisinformaessobreoarquivo.Algunsdosleitorespodemestarseperguntandoporqueestariafazendo
esta.OquetemosfeitocomantecednciacriarumapginaHTMLemnossoeditorHTMLfavorito.este
nospermitecriarmodelosusandoaconveninciadoWhatYouSeeIsWhatYouGet
(Quase)editor.Estatcnicadnosumaimagemdefundopossvelcabealhopadro,e
algumasconfiguraesdefonteparatodasaspginasHTMLgerado.Omesmopodeserfeitoparaumrodapcomum
tambm.Istosignificaqueapenasosdadosdinmicaprecisadesercodificadaeformatado.
HumcertonmerodeprodutoscomerciaisqueauxiliamnageraodasadaHTML
como"WebConnect"deRickStrahl.Sevoctemnecessidadessimplesopoderde TEXTMERGEter
otrabalhofeitocomfacilidade.O TEXTMERGErecursotambmumaalternativaparao FORMULRIODERELATRIO
ASCII.Apesardeelenotermaisesforoparaformatarasadaemcdigo,voctemmuitomais
controlocomoformatoquandoseutiliza TEXTMERGEemvezdo ASCIIopo.

ComogerarsadaPDF
OPortableDocumentFormatAdobeAcrobat(PDF)vemganhandompetocomoum
formatopadronaWebecomoummecanismodetrocadesadaformatada.Gerando
sadaparaaWeb,historicamente,temexigidoasadaformataousandotagsHTML.oAcrobat
ReaderestdisponvelgratuitamenteearquivosPDFpodemservisualizadosdiretamentenonavegadordawebatravsdo

554 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

controleActiveXparaInternetExplorereumaddinparaoNetscape.Tambmplataforma
independente,umavezquepodeservisualizadonoWindowsounoMacintosh.OsarquivosAcrobatso
tambmcomprimidoqueidealparaosrelatriosdequeprecisamdeserdistribudo.
relatriosVFPsogeradoscomoumarquivoPDF,imprimindodiretamenteparaaimpressoraPDFWriter
condutor.IstorequerumalicenacompletadoAdobeAcrobat,masavisualizaodasadanica
requerAdobeAcrobatReader,quegratuito.UmavezquevocimprimirumrelatrioaoPDFWriter
driverdaimpressora,vocsersolicitadoafornecerumnomeparaoarquivoPDF.Oficheirobaseadona
motorAdobePostScripteasadacolocadaparaforaexatamentecomoasadaestarianaVFP
janeladevisualizaoouparaumaimpressora.VocaindaestlimitadoscaractersticasdoRelatrioVFP
Designer,masavisualizaoedistribuiodorelatrioreforada.

Figura17.11EsteumrelatrioVFPapresentadoemAdobeAcrobat

VocpodecriararquivosPDFapartirdequalquerprogramaquepodesadaparaumaimpressora.Vocpodeatmesmo
combinaraautomaoparaWord(ououtroprograma)apartirdeVFP,emseguida,imprimiressasadaparao
driverdeimpressoraPDFWriter.
DepoisqueoarquivoPDFcriado,elepodeseranotadacomoAdobeExchange.Estaumaoutra
recursonoprodutoAdobeAcrobat.Quantasvezesvocdesejouparaacapacidadede
procurartextodentrodeumrelatrio?Estaoutragrandevantagemdestatcnicavocpodepesquisar
paraotextodentrodasadadorelatrio.muitorpido,mesmocomdocumentosgrandes.Hotlinksparawebsites
soaovivoeiriniciaronavegadorwebpadroquandoelessoclicados.Estascaractersticastornam
arevisodaVFPrelatriosinterativos.
Todososrecursosdescritosnestaseoexigeminteraodousurio.Sevocdesejagerar
relatriosparaoformatoPDFautnoma,visiteositedaWestWind(www.westwind.com)paraescolher
seasclasseswwPDFlivrescriadosporRickStrahl.
Captulo17:GerenciamentodeRelatrios 555

Comorevisarocdigododesignerderelatrios/label(Exemplo
ReportWalkthru.prg,ReportWalkthru01.frx,cMeta.vcx)
TodoocdigorelatrioquegeramosnaVFPReportDesignerarmazenadoemumarquivodemetadadosderelatrio
(.frx).IssononadamaisdoqueumVFPmesalivre.Oproblemacolocadopelatabelademetadados
quenosepodelercomfacilidadeasinformaesarmazenadasemlinhasecolunas.Nspodemosnavegarna
tabelasdemetadados,masissonoamigvelcomodesenvolvedorquer.Estaseoapresentardois
tcnicasparaanalisaredocumentarocdigoderelatrio.
Omtodopreferidodeobterinformaesparaforadastabelasdemetadadosconsultara
informaesatravsdeinstruesSQLSELECT.Vocvaiterumamelhorcompreensodorelatrio
metadadoscortandoosarquivosderelatrio.Semprecortarcpiasdocdigofontedeproduo.
Hackingoarquivoderelatrionotograndeumnegcio,umavezqueinicialmentepodeparecerumavezquebem
documentadosnoprojetono +HOME()"Filespec\"diretrio.Selecioneaversoapropriada
deVFP(ie60Spec.pjx)evisualizaro60Frx1e60Frx2relatrios.Humaabundnciadedetalhesem
essesrelatriosparalevlonocaminhoparaaconstruodeumadocumenterrelatrio.Naturalmente,umavezque
escreverumcaptulosobrerelatriosediscutirtcnicasderevisodecdigoedocumentao
somos
seusrelatrios,nofariasentidoparadarumexemplo.
UmavezqueosagradveispessoaldaMicrosoftforamtiposuficienteparadocumentarolayoutdorelatrio
arquivo,novamosentraremissoemdetalhes.Noentanto,humcamponoarquivoqueno
documentadaemerecealgumaexplicao.EsteocampoTimeStamp.oTimeStamp
campoumcampode32bits(numricocompactados)queaequipededesenvolvimentoFoxProcriadoparasalvar
noespaodearquivonosrelatriosertulo(bemcomoosprojetos,formas,bibliotecadeclassesvisual)
metadados.Estecampousadoparadeterminarseosobjectostmdeserrecompiladoesoactualizados
semprequeoobjetonorelatrioouortuloalterado.Ocdigoparaprocessarocampo
emumformatoquenormalmentelidocomodataehorafornecidonaListagem17.4.
EstecdigopodeserencontradonabibliotecadeclassesCMeta.vcxcomopartedocaptulode
Arquivosdedesenvolvedordedownloaddisponvelemwww.hentzenwerke.com.

Listagem17.4ConvertendoocampoTimeStampemumarquivoFRXsimplesumavezquevoc
entenderoalgoritmoparatransformloemumformatodedataehoraemqueestamosacostumadosa
leitura
LPARAMETERtnTimeStamp,tcStyle

lcRetValLOCAL &&Dadossolicitadosretornadodeprocedimento

IFTYPE('tnTimeStamp')!="N" &&Timestampdevesernumrico
WAITWINDOW"carimbodetempopassounonumrico"
RETORNA""
FIMSE

IFtnTimeStamp=0 &&Timestampzeroatconstrudoemprojeto
RETURN"NoconstrudoemApp"
FIMSE

IFTYPE('tcStyle')!="C" &&Estiloderetornopadroparaambosdataehora
tcStyle="DATETIME"
FIMSE

556 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

SE!INLIST(UPPER(tcStyle),"DATE","TIME","DATETIME")
WindowWAIT"parmetrodeestilodeveserDATA,HORA,ouDATETIME"
RETORNA""
FIMSE
lnYear =((TnTimeStamp/(2**25)+1980))
lnMonth =((LnYearINT(lnYear) )*(2**25))/(2**21)
lnDay =((LnMonthINT(lnMonth))*(2**21))/(2**16)

lnHour =((LnDayINT(lnDay) )*(2**16))/(2**11)


lnMinute=((lnHourINT(lnHour) )*(2**11))/(2**05)

&&Multipliquepordoisparacorrigirproblemadetruncagemconstrudoem
&&Aoalgoritmodecriao(Fonte:SuporteTcnicoMicrosoft)
lnSecond=((lnMinuteINT(lnMinute))*(2**05))*2

lcRetVal=""

IF"DATE"$UPPER(tcStyle)
lcRetVal=lcRetVal+RIGHT("0"+ALLTRIM(STR(INT(lnMonth))),2)+"/"+
RIGHT("0"+ALLTRIM(STR(INT(lnDay))),2)
+"/"+
RIGHT("0"+ALLTRIM(STR(INT(lnYear))),2)
FIMSE

IF"TIME"$UPPER(tcStyle)
lcRetVal=lcRetVal+IIF("DATE"$UPPER(tcStyle)",","")
lcRetVal=lcRetVal+RIGHT("0"+ALLTRIM(STR(INT(lnHour))),2)
+":"+
DIREITA("0"+ALLTRIM(STR(INT(lnMinute))),2)+":"+
RIGHT("0"+ALLTRIM(STR(INT(lnSecond))),2)
FIMSE

RETURNlcRetVal

Ocdigoparaprocessarosmetadadosparasadaquepodeseravaliaotambmpodeserencontradoem
oReportWalkThru.prgqueestdisponvelcomopartedodesenvolvedordocaptulo
Baixararquivosdisponveisemwww.hentzenwerke.com.

Aquioncleodessecdigo,queprocessaosmetadadosderelatrioeconverteadata.

loMetaDecode =CREATEOBJECT("ctrMetaDecode")

*CriarumatabelaapartirdoFormulriodoRelatrioabertoporqueo
*Mtodosmemorandoteralgunsretornosdecarroinseridosentre
*diferentesmtodos.
*SELECT,
APRD(loMetaDecode.TimeStamp2Date(timestamp),18)AScTimeStamp
DEFrxData
ONDEVAZIO(Expr!)
ORDERBYvpos,posioH
INTOCURSORFrxDataWT

REPORTFORMrptWT.frxNOCONSOLEPREVIEW

Captulo17:GerenciamentodeRelatrios 557

Figura17.12EsteumexemploderelatriogeradopeloprogramaReportWalkThru
Comovocpodever,escrevendoferramentasrpidasquefornecemsadafazequiparevisesderelatrios
muitomaisfcildoqueterdesenvolvedoresexaminarcadaexpressodeobjetoatravsdoRelatrioVFP
Designer.

Concluso
verdadequeoVisualFoxProReportDesignertemumasriedelimitaesirritantes.
Esperoqueasdicasetcnicasapresentadasnestecaptuloirajudarosusuriosaobterumamelhor
apresentaodasadadeestessolicitarem.Astcnicasnestecaptulososoluesalternativaspara
muitasdaslimitaes,maselestambmsoprojetadosparapermitirquevocfaaumamaisflexvel
mecanismoparausuriosderelatrios.Esperamosquevocencontrouestestil.

558 1001CoisasQueVocSempreQuisSaberSobreVisualFoxPro

Vous aimerez peut-être aussi