Muitos amigos tem me perguntado em como montar uma tela usando MarkBrowse com tabela temporária. E pra ser honesto no começo é meio chato, mas depois que você pega o jeito, fica muito fácil trabalhar com a classe FWMarkBrowse, principalmente se você estiver trabalhando com tabelas existente, mas trabalhar com tabela temporária não é difícil, só dá um trabalhinho extra. A classe FWMarkBrowse fornece um objeto do tipo grade, com botões laterais e uma coluna com a opção de marca e desmarca. Esta classe pode ser usada dentro de uma janela ou outro componente tipo Panel, ou simplesmente pode ser a própria janela que será aberta. Para saber mais acesse http://tdn.totvs.com/display/public/PROT/FWMarkBrowse Então vamos ao que interessa, irei mostrar um simples exemplo onde irei exibir uma janela, onde está tela teremos botões, filtro, configurações extras da tela e pesquisa. O exemplo que irei postar, poderia ficar mais resumido em relação a codificação, mas para ficar mais claro, deixe o fonte o mais completo e detalhado.
//Irei incluir algumas bibliotecas #INCLUDE "PROTHEUS.CH" #INCLUDE "FWMVCDEF.CH"
//Iniciar a rotina User Function MCFG0006I() //Declarar variáveis locais Local oColumn Local aCampos := {} Local aColumns := {} Local cArqTrb Local cIndice1, cIndice2, cIndice3,cIndice4 := "" Local nX Local lMarcar := .F. Local aSeek := {} Local bKeyF12 := {|| U_MCFG006M(),oBrowse:SetInvert(.F.),oBrowse:Refresh(),oBrowse:GoTop(.T.) } //Programar a tecla F12 //Declarar variáveis privadas Private oBrowse := Nil Private cCadastro := "Usuários do Sistema" Private aRotina := Menudef() //Se for criar menus via MenuDef //Criar a tabela temporária AAdd(aCampos,{"TR_OK" ,"C",002,0}) //Este campo será usado para marcar/desmarcar AAdd(aCampos,{"TR_ST" ,"C",001,0}) AAdd(aCampos,{"TR_ID" ,"C",006,0}) AAdd(aCampos,{"TR_NOME" ,"C",050,0}) AAdd(aCampos,{"TR_LOGIN","C",020,0}) AAdd(aCampos,{"TR_CARGO","C",050,0}) AAdd(aCampos,{"TR_DEPTO","C",050,0}) AAdd(aCampos,{"TR_EMAIL","C",150,0}) AAdd(aCampos,{"TR_SUPER","C",006,0}) AAdd(aCampos,{"TR_POS" ,"N",012,0}) //Se o alias estiver aberto, fechar para evitar erros com alias aberto If (Select("TRB") <> 0) dbSelectArea("TRB") TRB->(dbCloseArea ()) Endif //A função CriaTrab() retorna o nome de um arquivo de trabalho que ainda não existe e dependendo dos parâmetros passados, pode criar um novo arquivo de trabalho. cArqTrb := CriaTrab(aCampos,.T.) //Criar indices cIndice1 := Alltrim(CriaTrab(,.F.)) cIndice2 := cIndice1 cIndice3 := cIndice1 cIndice4 := cIndice1 cIndice1 := Left(cIndice1,5) + Right(cIndice1,2) + "A" cIndice2 := Left(cIndice2,5) + Right(cIndice2,2) + "B" cIndice3 := Left(cIndice3,5) + Right(cIndice3,2) + "C" cIndice4 := Left(cIndice4,5) + Right(cIndice4,2) + "D" //Se indice existir excluir If File(cIndice1+OrdBagExt()) FErase(cIndice1+OrdBagExt()) EndIf If File(cIndice2+OrdBagExt()) FErase(cIndice2+OrdBagExt()) EndIf If File(cIndice3+OrdBagExt()) FErase(cIndice3+OrdBagExt()) EndIf If File(cIndice4+OrdBagExt()) FErase(cIndice4+OrdBagExt()) EndIf //A função dbUseArea abre uma tabela de dados na área de trabalho atual ou na primeira área de trabalho disponível dbUseArea(.T.,,cArqTrb,"TRB",Nil,.F.) //A função IndRegua cria um índice temporário para o alias especificado, podendo ou não ter um filtro IndRegua("TRB", cIndice1, "TR_NOME" ,,, "Indice Nome...") IndRegua("TRB", cIndice2, "TR_LOGIN",,, "Indice Login...") IndRegua("TRB", cIndice3, "TR_EMAIL",,, "Indice E-mail...") IndRegua("TRB", cIndice4, "TR_ID" ,,, "Indice ID...") //Fecha todos os índices da área de trabalho corrente. dbClearIndex() //Acrescenta uma ou mais ordens de determinado índice de ordens ativas da área de trabalho. dbSetIndex(cIndice1+OrdBagExt()) dbSetIndex(cIndice2+OrdBagExt()) dbSetIndex(cIndice3+OrdBagExt()) dbSetIndex(cIndice4+OrdBagExt()) //Popular tabela temporária, irei colocar apenas um unico registro If RecLock("TRB",.t.) TRB->TR_OK := " " TRB->TR_ST := "S" //situação TRB->TR_ID := "000000" TRB->TR_NOME := "Administrador" TRB->TR_LOGIN := "Admin" TRB->TR_CARGO := "Administrador" TRB->TR_DEPTO := "Depto TI" TRB->TR_EMAIL := "administrador@empresa.com" TRB->TR_SUPER := "" TRB->TR_POS := 1 MsUnLock() Endif TRB->(DbGoTop()) If TRB->(!Eof()) //Irei criar a pesquisa que será apresentada na tela aAdd(aSeek,{"Nome" ,{{"","C",050,0,"Nome" ,"@!"}} } ) aAdd(aSeek,{"Login" ,{{"","C",006,0,"Login" ,"@!"}} } ) aAdd(aSeek,{"E-mail",{{"","C",100,0,"E-mail",""}} } ) aAdd(aSeek,{"ID" ,{{"","C",006,0,"ID" ,"@!"}} } ) //Agora iremos usar a classe FWMarkBrowse oBrowse:= FWMarkBrowse():New() oBrowse:SetDescription(cCadastro) //Titulo da Janela oBrowse:SetParam(bKeyF12) // Seta tecla F12 oBrowse:SetAlias("TRB") //Indica o alias da tabela que será utilizada no Browse oBrowse:SetFieldMark("TR_OK") //Indica o campo que deverá ser atualizado com a marca no registro oBrowse:oBrowse:SetDBFFilter(.T.) oBrowse:oBrowse:SetUseFilter(.T.) //Habilita a utilização do filtro no Browse oBrowse:oBrowse:SetFixedBrowse(.T.) oBrowse:SetWalkThru(.F.) //Habilita a utilização da funcionalidade Walk-Thru no Browse oBrowse:SetAmbiente(.T.) //Habilita a utilização da funcionalidade Ambiente no Browse oBrowse:SetTemporary() //Indica que o Browse utiliza tabela temporária oBrowse:oBrowse:SetSeek(.T.,aSeek) //Habilita a utilização da pesquisa de registros no Browse oBrowse:oBrowse:SetFilterDefault("") //Indica o filtro padrão do Browse //Permite adicionar legendas no Browse oBrowse:AddLegend("TR_ST=='N'","GREEN" ,"Usuários Liberados") oBrowse:AddLegend("TR_ST=='S'","RED" ,"Usuários Bloqueados") //Adiciona uma coluna no Browse em tempo de execução oBrowse:SetColumns(MCFG006TIT("TR_ID" ,"ID" ,03,"@!",0,010,0)) oBrowse:SetColumns(MCFG006TIT("TR_NOME" ,"Nome" ,04,"@!",1,080,0)) oBrowse:SetColumns(MCFG006TIT("TR_LOGIN","Login" ,05,"@!",1,040,0)) oBrowse:SetColumns(MCFG006TIT("TR_CARGO","Cargo" ,06,"@!",1,050,0)) oBrowse:SetColumns(MCFG006TIT("TR_DEPTO","Depto" ,07,"@!",1,100,0)) oBrowse:SetColumns(MCFG006TIT("TR_EMAIL","E-mail" ,08,"",1,100,0)) oBrowse:SetColumns(MCFG006TIT("TR_SUPER","Superior" ,09,"@!",1,020,0)) oBrowse:SetColumns(MCFG006TIT("TR_POS" ,"RECNO" ,11,"@E9999999",2,20,0)) //Adiciona botoes na janela oBrowse:AddButton("Enviar Mensagem" , { || U_MCFG006M()},,,, .F., 2 ) oBrowse:AddButton("Detalhes" , { || MsgRun('Coletando dados de usuário(s)','Relatório',{|| U_RCFG0005() }) },,,, .F., 2 ) oBrowse:AddButton("Legenda" , { || MCFG006LEG()},,,, .F., 2 ) //Indica o Code-Block executado no clique do header da coluna de marca/desmarca oBrowse:bAllMark := { || MCFG6Invert(oBrowse:Mark(),lMarcar := !lMarcar ), oBrowse:Refresh(.T.) } //Método de ativação da classe oBrowse:Activate() oBrowse:oBrowse:Setfocus() //Seta o foco na grade Else Return EndIf //Limpar o arquivo temporário If !Empty(cArqTrb) Ferase(cArqTrb+GetDBExtension()) Ferase(cArqTrb+OrdBagExt()) cArqTrb := "" TRB->(DbCloseArea()) Endif Return(.T.)
//Função para marcar/desmarcar todos os registros do grid Static Function MCFG6Invert(cMarca,lMarcar) Local cAliasSD1 := 'TRB' Local aAreaSD1 := (cAliasSD1)->( GetArea() ) dbSelectArea(cAliasSD1) (cAliasSD1)->( dbGoTop() ) While !(cAliasSD1)->( Eof() ) RecLock( (cAliasSD1), .F. ) (cAliasSD1)->TR_OK := IIf( lMarcar, cMarca, ' ' ) MsUnlock() (cAliasSD1)->( dbSkip() ) EndDo RestArea( aAreaSD1 ) Return .T.
//Caso crie os botões por função, abaixo seque um exemplo Static Function MenuDef() Local aRot := {} ADD OPTION aRot TITLE "Enviar Mensagem" ACTION "U_MCFG006M()" OPERATION 6 ACCESS 0 ADD OPTION aRot TITLE "Detalhes" ACTION "MsgRun('Coletando dados de usuário(s)','Relatório',{|| U_RCFG0005() })" OPERATION 6 ACCESS 0 //ADD OPTION aRot TITLE "Legenda" ACTION "" OPERATION 6 ACCESS 0 Return(Aclone(aRot))
//Função para criar as colunas do grid Static Function MCFG006TIT(cCampo,cTitulo,nArrData,cPicture,nAlign,nSize,nDecimal) Local aColumn Local bData := {||} Default nAlign := 1 Default nSize := 20 Default nDecimal:= 0 Default nArrData:= 0 If nArrData > 0 bData := &("{||" + cCampo +"}") //&("{||oBrowse:DataArray[oBrowse:At(),"+STR(nArrData)+"]}") EndIf /* Array da coluna [n][01] Título da coluna [n][02] Code-Block de carga dos dados [n][03] Tipo de dados [n][04] Máscara [n][05] Alinhamento (0=Centralizado, 1=Esquerda ou 2=Direita) [n][06] Tamanho [n][07] Decimal [n][08] Indica se permite a edição [n][09] Code-Block de validação da coluna após a edição [n][10] Indica se exibe imagem [n][11] Code-Block de execução do duplo clique [n][12] Variável a ser utilizada na edição (ReadVar) [n][13] Code-Block de execução do clique no header [n][14] Indica se a coluna está deletada [n][15] Indica se a coluna será exibida nos detalhes do Browse [n][16] Opções de carga dos dados (Ex: 1=Sim, 2=Não) */ aColumn := {cTitulo,bData,,cPicture,nAlign,nSize,nDecimal,.F.,{||.T.},.F.,{||.T.},NIL,{||.T.},.F.,.F.,{}} Return {aColumn}
//Função para criar a tela de legenda Static Function MCFG006LEG() Local oLegenda := FWLegend():New() oLegenda:Add( '', 'BR_VERDE' , "Usuários Liberados" ) oLegenda:Add( '', 'BR_VERMELHO', "Usuários Bloqueados") oLegenda:Activate() oLegenda:View() oLegenda:DeActivate() Return NilAgora, como identificar se o registro está selecionado? Para isso é necessário verificar (neste exemplo) o campo TR_OK, ele é responsável em receber a marcação
//Na sua função, você poderia fazer assim: TRB->( DbSetOrder(1) ) TRB->( DbGoTop() ) nCont:=0 While !TRB->(Eof()) If !Empty(TRB->TR_OK) //Se diferente de vazio, é porque foi marcado cPara += Alltrim(TRB->TR_EMAIL)+";" nCont++ Endif TRB->( dbSkip() ) EndDo if nCont == 0 Alert("Selecione pelo menos um usuario!") return EndifSimples o uso da função, não é mesmo?