Lisp, Dcl e duplo clique

Vou desenferrujar um pouco o meu lisp, hehehe
respondendo ao desafio do crackster, sim é possível implementar duplo clique no dcl quando o fazemos sobre list_box

segundo o help (F1!!!!), ao clicarmos, selecionarmos algum controle da nossa dcl, ela informa atravez do seu "action" qual foi a $key, o $value e tambem o $reason do controle que foi acessado. Veja quais são as $reason possíveis:
1 = pressionou enter em um controle qualquer, um edit_box por exemplo
2 = somente em edit_box. O cara tirou do foco do controle, clicando o TAB por exemplo
3 = sliders, o cara tirou o foco do controle, clicando o TAB por exmeplo
4 = list_box e image_button, o cara deu duplo clique ou clique simples

na verdade é um pouco mais complexo que isso, mas em linhas gerais é por aí

para testarmos então esse duplo clique, analize este programa, primeiro o dcl:

teste : dialog {
  label = "Teste duplo clicque" ;
  :
boxed_column {
     label="Dê duplo clique num item";
    :
list_box { key = "lista"; } }
  :button {
     key = "cancel";
     is_cancel=true;
     label="Cancela";}}


agora o lisp:

(defun c:teste (/ dcl lista acao n)
;carrega o dcl na memória  
  (setq dcl (load_dialog "d:/teste.dcl")
;lista de item do listbox:
    lista '("pedra" "papel" "tesoura")
;variavel auxiliar para armazenar o item escolhido:
    n    nil
;função anonima para proceder as ações do dcl:
    acao (lambda (key value reason)
;testa qual controle foi chamado:
           (cond ((= key "lista")
;se foi o list_box, e se foi duplo clique (reason==4)
              (if (= reason 4)
            (
progn
;mostre qual foi o item selecionado
              (alert (setq n (nth (atoi value) lista)))
;encerre o dcl com um "OK"
              (done_dialog 1))))
;aqui iria a ação de outros controles...
             )))

;inicia o quadro de dialogo
  (new_dialog "teste" dcl)

;preenche a lista de itens do list_box:
  (start_list "lista" 3)
  (
foreach o lista (add_list o))
  (
end_list)

;|define qual é a ação do nosso list_box
  se tivessemos mais uns 20 controles, todos eles teriam
 a mesma ação e poderiamos fazer:
 (foreach k '("lista" "key1" "key2" "keyn")
   (action_tile k "(acao $key $value $reason)") )
 |;

  (action_tile "lista" "(acao $key $value $reason)")

;interpreta a saida do dialogo apos iniciar ele:
  (if (= 1 (start_dialog))
;| se done_dialog é 1, clicou OK ou no nosso caso, como não temos um botão OK
 foi o duplo clique quem encerrou o DCL
 se clicarmos o botão cancela, o done_dialog devolve 0
 claro que se queremos interromper o dcl por outro motivo, é só colocar
 (done_dialog NUM)
 onde NUM seria um inteiro qualquer que testariamos neste IF
 |;

    (alert (strcat  "Voce escolheu um item!!!\n Ele é: " n)))
;descarrega o dcl:
  (unload_dialog dcl)
  )



Note que fiz algumas considerações no código.
basicamente, mostrei como poderíamos sobreescrever o botão CANCEL.

Se quizesse mudar o OK, tambem daria, bastaria colocar uma propriedade (is_default = true;) num controle de botão (button)

veja como preenchi a lista do list_box. Muita gente coloca os itens na propriedade list ( list = "1\n2\n3" ; ) dentro do arquivo do dcl, mas ai fica ruim para obter o texto do item selecionado

também optei por definir o action_tile dos controles via lisp e não no dcl.
iso facilita a escrita do programa, pois você não precisa escrever o código dentro de string.

por fim, dei a dica de como encerrar o dcl por outro motivo.
Qual motivo?

Por exmeplo, digamos que algum controle do dcl seja um botão para capturar uma coordenada na tela com a função getpoint do lisp.

Não poderíamos simplesmmente colocar uma ação assim:

(action_tile "botao" "(setq pt (getpoint \"Clique um ponto\"))")

ao clicar o botão, isso causaria um erro fatal no seu cad!!!! já discuti isso aqui no blog algumas vezes...


neste caso a solução seria fazer um looping, jogando a parte que pede o ponto para DEPOIS de encerrar o dcl:

(setq faz t)
(
while faz
  (new_dialog "teste" dcl)

  ;|subrotinas que preenchem os controles|;
  (action_tile "botao" "(done_dialog 2)")
  
  
  (
setq dlg (start_dialog))
  (
cond ((= dlg 0) (alert "clicou CANCEL") (setq faz nil))
    ((
= dlg 1) (alert "clicou OK"))
    ((
= dlg 2) (setq pt (getpoint "\nEntre com o ponto")))))




Percebe? assim o looping é executado até que clicamos o botão CANCELA

é isso....
gostou? deixe um comentário!!!

10 comentários:

  1. Boa Tarde......tenho visto seu blog e ele é muito bom...eu sendo amador em lisp tem ajudado muito....gostaria de saber se poderia me ajudar em que uma rotina lisp abre um dcl com varias opções, ao clicar um destes botões, abre outro dcl escolher uma lista, sendo que a rotina em lisp que executara o desenho ou inserção do bloco esta na escolha neste segundo dcl......

    ResponderExcluir
  2. é simples:

    em algum botao ou coisa assim coloque um action assim:

    action: "(abre_outrodcl)";

    onde "abre_outrodcl" é uma lisp que contem um programa que abra outro dcl....

    uma dica:
    ja que um programa chama outro, mas os dois são parte de um mesmo, coloque todas as definicoes de dcl num mesmo arquivo, assim ao fazer:

    ( setq dcl (load_dialog "dcl.dcl"))

    so precisa armazenar uma vez o numero do dcl...

    ai o programa principal tem o

    ( new_dialog "principal" dcl )

    e o secundario:

    ( new_dialog "secundario" dcl)

    ResponderExcluir
  3. ola neyton estou precisando de sua ajuda, tenho um aplicativo em lisp do cad 2004 que eu usava muito, ele serve peara inserir janelas, quando eu tento usa-la no cad 2010 aparece um erro, "ADA' com o ponto
    de inserção>no function definition: DOS_WAITCURSOR; error: An error has
    occurred inside the *error* functionno function definition: DOS_WAITCURSOR ", o problema e que eu nao intendo nada de lisp, se vc puder me ajuda eu agradeceria muito
    espero que vc possa me ajudar, um abraço

    ResponderExcluir
  4. vc precisa de um plugin do autocad chamado dos_lib procure le no google para a sua versão e instale ele

    ResponderExcluir
  5. neyton muito obrigado, era exatamente isto, valeu mesmo vc nao sabe o quanto ajudou, espero q vc possa continuar com seu blog por muito tempo ajudando mais pessoas, um abraço.

    ResponderExcluir
  6. Aw, this was a really nice post. In idea I would like to put in writing like this additionally - taking time and actual effort to make a very good article… but what can I say… I procrastinate alot and by no means seem to get something done.

    ResponderExcluir
  7. Olá Neyton,tenho o mesmo nome seu,achei até engraçado,sou de brasilia df.

    ResponderExcluir
  8. Olá neyton,grande coincidência o meu nome e quase igual ao teu,sou de brasilia df.

    ResponderExcluir
  9. Olá neyton,grande coincidência o meu nome e quase igual ao teu,sou de brasilia df.

    ResponderExcluir