Você está na página 1de 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