Menus e DLLs

Criar menus e barras de ferramentas? simples.. ruim é criar os bitmaps dos botões, não é mesmo?
Mas pior que isso, é ver aquele monte de bitmaps na pasta do seu programa, totalmente desorganizados, então que tal colocar todos eles numa DLL?
É, com ele mesmo o ResHacker, se você já o tem, deve ter a tal dll vazia, mas se não a tem, baixe daqui.
Tá, você já viu um tutorial para fazer a dll, mas tenho certeza de que ele te mandava incluir um a um os bitmaps na dll, certo? Que tal uma rotininha básica pra listar os bitmaps de uma pasta qualquer e criar a dll automaticamente? ai vai: ver a rotina!!
;rotina para pegar uma pasta do HD:
(defun BrowseForFolder ( text / ret shell )
  (
setq shell (vlax-get-or-create-object 
                 "shell.application"))
  (
if (setq ret (vlax-invoke shell "BrowseForFolder"  0 text 1))
      (
setq ret (vlax-get (vlax-get ret "Self") "Path")))
  (
vlax-release-object shell)
  ret)

(
defun c:makedllres (/ dir bat tmp dll scr dll_vazio reshacker)
  (
setq
;configure aqui o caminho onde está a dll vazia:
    dll_vazio "f:/resource kit hacker/dllvazio.dll"
;configure aqui o caminho do reshacker.exe:
    reshacker "f:/resource kit hacker/reshacker.exe")
  (if (setq dll   (getfiled "Criar Dll" "" "dll" 1))
    (
if (setq dir (browseforfolder "indique a pasta dos resources"))
    (
progn
      (setq dll   (vl-string-translate "\\" "/" dll)
            src   (vl-filename-mktemp "" dir ".scr")
            bat   (vl-filename-mktemp "" dir ".bat")
            tmp   (open src "w")
            dir   (vl-string-translate "\\" "/" dir))
      (
vl-file-delete dll)
      (
vl-file-copy dll_vazio dll)
      (
write-line
        (strcat "[FILENAMES]\nExe=\"" dll "\"\nSaveAs=\"" dll "\"\n\n[COMMANDS]")
        tmp)
      
      (
foreach x  (vl-directory-files dir "*.bmp" 1)
        (
write-line
          (strcat "-addoverwrite \"" dir "/" x "\", bitmap, " (vl-filename-base x) ",")
          tmp))
      (
close tmp)
      (
setq tmp (open bat "w"))
      (
write-line
        (strcat "\"" reshacker "\" -script \"" src "\"\ndel \""src "\"\ndel \"" bat "\"\n")
        tmp)
      (
close tmp)
      (
startapp bat))))
  (
princ))


Pegou a rotina? então salve ela em algum lugar, mas tome o cuidado de alterar as linhas onde estão configurados os caminhos para a dll vazia e para o reshacker

VLX e a tecla ESC

Já compilaram suas rotinas para VLX? que opções vocês usaram?
Pergunto isso, pois sempre compilo as minhas para este formato, seja para proteger o código, seja para colocar os *.lsp e *.dcl num arquivo apenas... Bom, mas minha dúvida aqui é o seguinte: quando compilada a rotina VLX, com a opção "Separate NameSpace" habilitada, a tecla ESC já não cancela mais a rotina... Estranho não?
Agora imagine que seu programa faça alguma operação bem demorada, e você decide interromper a execução dele? o que você vai fazer, já que a tecla ESC não cancela mais a execução? ver a rotina
(defun expandlist (el qtd / lst)
  (
repeat qtd (setq lst (cons el lst))))

(
defun init-status (maxvalue msg)
  (
setq status:delta (/ maxvalue 100.0)
        status:str   (apply 'strcat (expandlist (chr 160) 100))
        status:index 0
        status:looping 0
        status:msg msg)
  (
grtext -1 (strcat msg " 00 %" status:str)))

(
defun show-status nil
  (if (>= status:looping (* status:delta status:index))
    (
progn
      (setq status:str (vl-string-subst "|" (chr 160) status:str)
            status:index (1+ status:index))
      (
grtext -1 (strcat status:msg " "
                         (if (< status:index 10) "0" "")
                         (
itoa status:index) " %" status:str))))
  (
setq status:looping (1+ status:looping)))

(
defun end-status nil
  (grtext -1 "")
  (
princ))

(
defun c:teste (/ qtd)
  (
setq qtd 10000)
  (
init-status qtd "processing...")
  (
repeat qtd
    (command)
    (
REDRAW)
    (
show-status))
  (
prompt "\nFIM")
  (
end-status))

Faça o teste, compile a rotina acima para VLX com o Separate NameSpace marcado, carregue o VLX e rode... tente cancelar a rotina, depois tente o mesmo, deixando Separate NameSpace desmarcado... Numa delas você verá um "FIM" na linha de comando, na outra verá o famigerado "Function Cancelled"

Dimensões de slides

Alguém aí já inseriu um arquivo SLD num DCL?
Lá na tile "image" ou image_button?

O slide era retangular, ou quadrado? e como você sabe disso? e image_button tinha a mesma relação de aspecto que o seu slide? E como saber se está?
Mas... O que diabos é relação de aspecto????

Eu explico:
Relação de aspecto: é o valor que obtemos ao dividir a altura pela largura
Num quadrado, temos que esta divisão resulta um, num retângulo, um valor diferente de um.

O que acontece quando tentamos preencher a image_button do dcl com um slide? Mesmo que forcemos as dimensões do slide, assim:
[code](slide_image x1 y1 width height sldname)[/code]
O slide não se deforma, e poderá acontecer de "sobrar" espaço na image_button, certo?
Ai fica meio "feio"... Desproporcional...

Se soubermos qual a relação de aspecto do slide e do image_button poderemos dizer quem é "mais retangular" e assim, calcular x1,y1,width,height que deixem o slide mais bem posicionado, isto é, centralizado

Agora, o comando que cria o slide ( MSLIDE na linha de comando) não pergunta nem diz que tamanho irá ter o slide... Ai complica... Você tem de deixa a área visível do desenho na relação que você precisa...

Mas ainda assim, não saberá qual o tamanho do slide...
Na verdade, ele terá, em pixels, a mesma dimensão dessa área visível, a as propriedades width e height do objeto Window, levam em conta as "bordas" da janela, portanto não são utilizáveis, a não ser que você saiba quantos pixels ela usa...

Com o "print screen" e o paint dá pra contar quantos pixels deu... ( aff ... )

Uma boa dica é, na definição do image_button (ou image), usar o atributo width e o atributo aspect_ratio, ou o atriguto height com o atributo aspect_ratio, pois assim tem-se certeza do tamanho do slide... lembrando que width e height não são dados em pixels, mas em uma proporção do tamanho dos caractéres visualizados no dcl...


Bom, pra encurtar:
É possível "extrair" do slide qual suas dimensões em pixels, para isso temos de ler os BYTES corretos do arquivo e assim, proceder a inserção do slide da melhor maneira, veja a rotina
(defun get-sld-dim (file / tmp l)
  (
setq tmp (open file "r"))
  (
repeat 18 (read-char tmp))
  (
setq l  (list (read-char tmp) (read-char tmp)
                 (
read-char tmp) (read-char tmp)))
  (
close tmp)
  (
list (+ (* 256 (cadr l)) (car l))
        (
+ (* 256 (cadddr l)) (caddr l))))


Para usar, faça (por exemplo):
(get-sld-dim "d:/neyton/expge/expge.sld")

isso irá retornar uma lista, com as dimensões em pixels da largura e da altura do slide, no exemplo, me retornou (721 361), onde 721 é a largura e 361 a altura