Clipper On Line • Ver Tópico - Menu com mouse no Clipper

Menu com mouse no Clipper

Discussão sobre a linguagem CA-Clipper.

Moderador: Moderadores

 

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 18:58

Sinceramente... melhor partir pra Harbour... mas dá pra fazer.

Primeira coisa importante:
Se for clipper 5.2, só mesmo usando rotinas da superlib pra mouse.

Segunda coisa importante:
O Windows usa mouse.
Qualquer teste de uso de teclado e mouse no Clipper pode levar a 100% de CPU.
É obrigatório usar em conjunto, por exemplo, da OSLIB, pra não sobrecarregar o computador.

O ponto fundamental de sucesso é: não tenha pressa, uma coisa de cada vez.

Vamos pensar em um menu, como é que ele funciona.....
Precisa mostrar as opções....
Vamos facilitar colocando em um array:

aOpcoes := { "primeira", "segunda", "terceira", "quarta", "quinta" }


Pra mostrar, vai ser uma linha embaixo da outra:


#include "inkey.ch"

PROCEDURE Main

   LOCAL nCont, nOpc := 1, nKey
   LOCAL aOpcoes := { "primeira", "segunda", "terceira", "quarta", "quinta" }

   DO WHILE .T.
      FOR nCont = 1 TO Len( aOpcoes )
         @ 3 + nCont, 10 SAY Pad( aOpcoes[ nCont ], 30 ) COLOR "W/B"
      NEXT
      nKey := Inkey(0)
      IF nKey == K_ESC
         EXIT
      ENDIF
   ENDDO

   RETURN


Pronto.
O Pad(x,30) é pra todos ficarem com 30 colunas

menu.png
menu.png (11.38 KiB) Visualizado 3493 vezes
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 19:04

Agora... precisamos destacar a opção atual....
Se for opção atual, mostrar de outra cor...

Pera aí....
Atenção a essa parte....
SE FOR OPÇÃO Atual, mostra de uma cor, senão mostra de outra.
SE... SENÃO...
Oras... isso é IF ELSE, ou IIF()
IF opção = atual, uma cor, ELSE outra cor
iif( opção = atual, uma cor, outra cor )

      FOR nCont = 1 TO Len( aOpcoes )
         @ 3 + nCont, 10 SAY Pad( aOpcoes[ nCont ], 30 ) COLOR iif( nCont == nOpc, "N/W", "W/B" )
      NEXT


menu.png
menu.png (10.57 KiB) Visualizado 3492 vezes
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 19:12

Bom...
agora movimentar com setas....
Se tecla pra cima (UP), diminui 1 na opção
Mas... e se ultrapassar o limite?
Se... estiver na opção 1.... vai pra última... senão... só diminui 1
Mas qual é a última? se aOpcoes contém a lista, Len( aOpcoes ) vai retornar a quantidade.

      CASE nKey == K_UP  ; nOpc := iif( nOpc == 1, Len( aOpcoes ), nOpc - 1 )


E pra baixo... parecido.
Se tecla pra baixo (DOWN), soma 1 na opção
pra baixo: Se... estiver na última... vai pra primeira... senão... só soma 1

      CASE nKey == K_DOWN; nOpc := iif( nOpc == Len( aOpcoes ), 1, nOpc + 1 )


Pronto, temos um menu com movimento pelas setas.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 19:25

Antes de expandir, vamos pensar....
Que tal usar no aplicativo inteiro?
Que tal fazer com qualquer quantidade de opções, em qualquer linha e em qualquer coluna?
Bom... vamos transformar em função...

Vamos ver as variáveis:
   LOCAL nCont, nOpc := 1, nKey
   LOCAL aOpcoes := { "primeira", "segunda", "terceira", "quarta", "quinta" }


Bom...
nOpc é o número da opção... ela não vai ser fixa, porque pode ser diferente em cada uso
aOpcoes é a lista... ela não vai ser fixa, porque pode ser diferente em cada uso
Linha e coluna.... não pode ser 3 e 10, porque pode ser diferente em cada uso

Então....
FUNCTION Menu( nLinha, nColuna, aOpcoes, nOpc )


Agora ajustar o fonte pra usar isso.

#include "inkey.ch"

PROCEDURE Main

   LOCAL nOpc1 := 1

   Menu( 3, 10, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc1 )

   RETURN

FUNCTION Menu( nLinha, nColuna, aOpcoes, nOpc )

   LOCAL nCont, nKey

   DO WHILE .T.
      FOR nCont = 1 TO Len( aOpcoes )
         @ nLinha + nCont, nColuna SAY Pad( aOpcoes[ nCont ], 30 ) COLOR iif( nCont == nOpc, "N/W", "W/B" )
      NEXT
      nKey := Inkey(0)
      DO CASE
      CASE nKey == K_ESC ; EXIT
      CASE nKey == K_UP  ; nOpc := iif( nOpc == 1, Len( aOpcoes ), nOpc - 1 )
      CASE nKey == K_DOWN; nOpc := iif( nOpc == Len( aOpcoes ), 1, nOpc + 1 )
      ENDCASE
   ENDDO

   RETURN nOpc


Continua funcionando perfeito, mas agora serve pra mais de um menu

menu.png
menu.png (8.64 KiB) Visualizado 3492 vezes
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 19:31

Continua funcionando perfeito, mas agora serve pra mais de um menu


Será que é verdade?
Vamos ver...

PROCEDURE Main

   LOCAL nOpc1 := 1, nOpc2 := 1, nOpc3 := 1

   Menu( 5, 10, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc1 )
   Menu( 10, 15, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc2 )
   Menu( 15, 20, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc3 )

   RETURN


menu.png


Uia... é verdade...
Já dá pra usar no aplicativo inteiro... mas só se melhorar o visual, lógico...
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 19:55

Vamos pensar.....
o menu fica em linha + opc, significa que a primeira opção fica em linha + 1.
Então vamos passar um traço em... LINHA
Começa aonde... se na coluna NCOLUNA começam as opções, então vai começar em coluna -1
Mas... vou pedir o menu na coluna 10 e ele vai começar na 9?
melhor ajustar o texto pra coluna + 1.

Ok.. linha nLinha, coluna nColuna....
E aonde termina? depende da quantidade de opções.
pensar... linha 10, uma opção... linha 10 é o traço, linha 11 é a opção, então vamos fazer o traço na linha 12
tá... essa 12 então equivale a nLINHA + quantidade + 1, 10 + 1 + 1, que dá 12
E coluna... parecido... nColuna + 30 + 2 (fixamos na rotina tamanho 30). porque + 2 e não + 1? porque o traço inicial entrou na contagem.
Então temos um quadrado que começa em nLinha, nColuna, e termina em nLinha + Len( aOpcoes ) + 1, nColuna + 32
  @ nLinha, nColuna TO nLinha + Len( aOpcoes ) + 1, nColuna + 32


Fonte completo:

#include "inkey.ch"

PROCEDURE Main

   LOCAL nOpc1 := 1, nOpc2 := 1, nOpc3 := 1

   Menu( 5, 10, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc1 )
   Menu( 10, 15, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc2 )
   Menu( 15, 20, { "primeira", "segunda", "terceira", "quarta", "quinta" }, @nOpc3 )

   RETURN

FUNCTION Menu( nLinha, nColuna, aOpcoes, nOpc )

   LOCAL nCont, nKey

   DO WHILE .T.
      @ nLinha, nColuna TO nLinha + Len( aOpcoes ) + 1, nColuna + 32
      FOR nCont = 1 TO Len( aOpcoes )
         @ nLinha + nCont, nColuna + 1 SAY Pad( aOpcoes[ nCont ], 30 ) COLOR iif( nCont == nOpc, "N/W", "W/B" )
      NEXT
      nKey := Inkey(0)
      DO CASE
      CASE nKey == K_ESC ; EXIT
      CASE nKey == K_UP  ; nOpc := iif( nOpc == 1, Len( aOpcoes ), nOpc - 1 )
      CASE nKey == K_DOWN; nOpc := iif( nOpc == Len( aOpcoes ), 1, nOpc + 1 )
      ENDCASE
   ENDDO

   RETURN nOpc


Resultado

menu.png


Mas... e o mouse?

Só pense um pouco.....
Se a rotina pode ser usada no aplicativo inteiro....
Significa que poderia alterar o aplicativo inteiro pra coisa mais simples...

E o mouse? usando no aplicativo inteiro, quando alterar pra mouse, vai ter alterado o aplicativo inteiro de uma vez!!!!

Entendeu? aplicativo INTEIRO.
Então... você está trabalhando para o mouse... sem mexer com mouse...

Seria parecido converter para Harbour....
Você não precisa converter o aplicativo inteiro, você pode ir organizando as coisas, e depois ao invés de muitas rotinas... bastaria mexer na rotina base de tudo.
Você tem muitos aplicativos pra mexer.... vai centralizando com o tempo... e isso já significa estar preparando pra troca.

No caso do menu... poderiam ser dezenas de menus pra colocar mouse... e depois das alterações, vai ser apenas um - colocando no central, vale pra todos.

Ah... mas tem menu horizontal e vertical....
Tudo bem, faz um pro horizontal e outro pro vertical...
Vai acrescentando recursos, pra atender exceções.

Não sei fazer... tudo bem... começa fazendo o que sabe, e com o tempo vai acrescentando o que for aprendendo.
Vai vendo o que vai precisando...

O que pode faltar nesse?
Talvez opção pra SAVE SCREEN e RESTORE SCREEN, pra chamar por uma rotina, o menu aparecer, e sumir depois de selecionar a opção.
Talvez um parâmetro... pra se um menu chamar submenu, não apagar o menu anterior da tela.

É assim que funciona... faz um básico... e aos poucos vai melhorando.
E fazendo um só pro aplicativo inteiro... pode alterar visual, mouse, ou tudo que quiser de uma vez.

Ao pegar uma rotina pronta, pode ser difícil entender.
Porque?
Ué... porque ele foi evoluindo com o tempo, de acordo com as necessidades, e pegando ele pronto, parece ter coisas que não precisa - ou ainda não precisou.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 20:12

Agora vamos ao mouse....
A rotina de mouse costuma converter os "clicks" em código INKEY.
Então... é verificar se nKey (que seria o inkey()) equivale a algum "click".

CASE nKey == K_LBUTTONDOWN


Tá... mas... se apertou o mouse, vai fazer o que?
Pra isso, vamos precisar da posição do mouse: MRow(), e MCol()
E da posição das opções..... complicou....

não... vamos pensar.... vamos lembrar da rotina que já temos...

a opção 1 fica em nLinha + 1, opção 2 em nLinha + 2, etc. quantidade de opções é Len( aOpcoes ), tamanho é 30, coluna começa em nColuna e termina em nColuna + 30... temos exatamente como saber as posições aonde tudo está.

Para o click selecionar alguma coisa:
MRow() - tem que ser entre nLinha + 1 e nLinha + Len( nOpcoes )
MCol() - tem que ser entre nColuna + 1 e nColuna + 1 + 30

opção 1... fica em nLinha + 1.... Então é fazer o cálculo ao contrário.... linha do click menos nLinha... começa por aí... para retornar a opção que corresponde à linha do click.

Pra comparar com cada opção... FOR/NEXT
E talvez melhor criar um array contendo as coordenadas de cada opção, pra separar a rotina complexa em duas rotinas mais simples.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 21:22

Aproveitei pra testar tamanhos diferentes de menu e colocar opção de ENTER.

A má notícia:
Não tenho como testar no Clipper, então tive que testar como Harbour.

A boa notícia:
Em clipper é trocar o Inkey(0) pelo equivalente da Superlib que também trata o mouse
Ainda tenho as rotinas pra Clipper aqui, coloco depois.


#include "inkey.ch"

PROCEDURE Main

   LOCAL nOpc1 := 1, nOpc2 := 1, nOpc3 := 1

   Menu( 5, 10, { "Conhecimento", "Manifesto", "Nota Fiscal", "BPE", "NFCE" }, @nOpc1 )
   Menu( 10, 15, { "Envia XML", "Consulta Recibo", "Consulta Protocolo", "Salva XML" }, @nOpc2 )
   Menu( 15, 20, { "Cancela", "Salva", "Deixa assim mesmo" }, @nOpc3 )

   RETURN

FUNCTION Menu( nLinha, nColuna, aOpcoes, nOpc )

   LOCAL nCont, nKey, aMousePos := {}, nOpcClick

   SET EVENTMASK TO INKEY_ALL - INKEY_MOVE
   FOR nCont = 1 TO Len( aOpcoes )
      AAdd( aMousePos, { nLinha + nCont, nColuna + 1, nLinha + nCont, nColuna + 1 + 30 } )
   NEXT

   DO WHILE .T.
      @ nLinha, nColuna TO nLinha + Len( aOpcoes ) + 1, nColuna + 32
      FOR nCont = 1 TO Len( aOpcoes )
         @ nLinha + nCont, nColuna + 1 SAY Pad( aOpcoes[ nCont ], 30 ) COLOR iif( nCont == nOpc, "N/W", "W/B" )
      NEXT
      nKey := Inkey(0)
      DO CASE
      CASE nKey == K_ENTER ; EXIT
      CASE nKey == K_ESC ; EXIT
      CASE nKey == K_UP  ; nOpc := iif( nOpc == 1, Len( aOpcoes ), nOpc - 1 )
      CASE nKey == K_DOWN; nOpc := iif( nOpc == Len( aOpcoes ), 1, nOpc + 1 )
      CASE nKey == K_LBUTTONDOWN
         nOpcClick := ASCan( aMousePos, { | e | MRow() == e[ 1 ] .AND. MCol() >= e[ 2 ] .AND. MRow() == e[ 3 ] .AND. mCol() <= e[ 4 ] } )
         IF nOpcClick != 0
            nOpc := nOpcClick
         ENDIF
      ENDCASE
   ENDDO

   RETURN nOpc


men.png


Alguns podem dizer... mas eu queria que saisse no click do mouse.... ué... pra sair é acrescentar EXIT.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 21:42

Coloquei como imagem pra mostrar de onde vieram as coordenadas

menu.png


      CASE nKey == K_LBUTTONDOWN
         nOpcClick := ASCan( aMousePos, { | e | MRow() == e[ 1 ] .AND. MCol() >= e[ 2 ] .AND. MRow() == e[ 3 ] .AND. mCol() <= e[ 4 ] } )
         IF nOpcClick != 0
            nOpc := nOpcClick
         ENDIF


Ao invés de FOR/NEXT, usei AScan().

{ | e | MRow() == e[ 1 ] .AND. MCol() >= e[ 2 ] .AND. MRow() == e[ 3 ] .AND. mCol() <= e[ 4 ] }


o que significa isso?
tem lá a primeira opção... linha 6, coluna 11, até linha 6, coluna 31

Isso está verificando se clicou no mouse na mesma linha da opção, e nas colunas aonde tem o texto da opção.
se click = linha 6 e click >= coluna 11 e click = linha 6 e click <= coluna 31

deixei a parte inútil de propósito:
de repente quer menu vertical, ou quer fazer cada opção usando duas linhas...
em certos casos precisaria das 4 coordenadas, então se aproveitar a rotina como modelo, já teria todas as coordenadas.

Chamar a atenção:
Foi criada uma rotina básica, e devagar foram sendo acrescentados recursos.
A rotina que atendeu 3 menus, ao colocar mouse - numa única rotina - o mouse já funcionou nos 3 menus.

Outro uso básico, que tal um Sim/Não com mouse?

nSimNao := Menu( 5, 10, { "Sim", "Não" }, 1 )


Ou talvez criar uma rotina MsgYesNo() e nessa rotina já mostrar centralizado na tela e retornar .T. ou .F., conforme a resposta.

O limite de até onde vai a função é a criatividade, e mais que isso: a necessidade
Conforme vamos precisando de algo mais, vamos acrescentando.
Por exemplo.... que tal uma letra ou número, para o usuário digitar e ir direto lá, sem precisar do mouse?
Pois é... vamos transformando em um menu pronto pra qualquer situação, e automaticamente, fazendo isso com o aplicativo inteiro que usar essa rotina.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 19 Jul 2019 22:18

#define K_LBUTTONDOWN 1002
#define K_RBUTTONDOWN 1004

static lIsMouse
static MouseRow  := 0
static MouseCol  := 0

    function MyInkey(mTempo,mHotKey)

    Local nKey     := 0
    Local nSeconds := 0
    Local mAcao
    mHotKey  := iif(mHotKey==NIL,.t.,mHotKey)
    mTempo   := iif(mTempo==NIL,-1,mTempo)
    nSeconds := Seconds()

    if lIsMouse == NIL
       lIsMouse := Sls_IsMouse()
    endif

    if lIsMouse
       Rat_On()
    endif

    do while .t.
       IdleToW95((mTempo != -1))
       nKey := Inkey()
       if lIsMouse
          if Rat_Leftb()
             MouseRow := Rat_Rowl()
             MouseCol := Rat_Coll()
             nKey     := K_LBUTTONDOWN
          elseif Rat_Rightb()
             MouseRow := Rat_Rowr()
             MouseCol := Rat_Colr()
             nKey     := K_RBUTTONDOWN
          else
             MouseRow := 0
             MouseCol := 0
          endif
       endif
       do case
       case nKey != 0
          exit
       case mTempo == 0
       case Seconds() - nSeconds >= mTempo
          exit
       endcase
    enddo

    if lIsMouse
       Rat_Off()
    endif

    if ( mAcao := SetKey(nKey) ) != NIL .and. mHotKey
       Eval(mAcao,ProcName(),ProcLine(),ReadVar())
       nKey := 888
    endif
    return nKey

function MouseRow()
return MouseRow

function MouseCol()
return MouseCol

function IdleToW95(mForcaIdle)

Static IdleSeconds := 0
Static IdleTime    := "00:00:00"
mForcaIdle := Iif(mForcaIdle==NIL,.f.,mForcaIdle)

If IdleTime != Time() .Or. mForcaIdle
   IdleSeconds += 1
   IdleTime    := Time()
   If IdleSeconds > 1 .Or. mForcaIdle
      IdleSeconds := 0
      OL_AutoYield(.f.)
      OL_Yield()
      OL_AutoYield(.t.)
   Endif
Endif
return NIL

    function SLS_ISMOUSE(lSet)
    if lIsMouse==NIL
      lIsMouse := rat_exist()
    endif
    if lSet#nil
       if .not. lSet
          lIsMouse := .f.
       endif
    endif
    return lIsMouse
    *----------------------------------------------------------------

    function rat_lmcode
    return K_LBUTTONDOWN
    *----------------------------------------------------------------

    function rat_rmcode
    return K_RBUTTONDOWN


É fonte meu da época, de 2008, 11 anos atrás....

IdeToW95() é pra liberar tempo a cada alguns segundos.
MyInkey() foi pra substituir principalmente Inkey(0), e liberar tempo ao invés de ficar parado

O teste de mouse é durante o Inkey(x), e é ativado/desativado, pra não ficar testando mouse à toa, e também pra "dar tempo ao Windows".

Dentro de MyInkey() salva as coordenadas de mouse nas variáveis estáticas MouseRow e MouseCol, e na época usava MouseRow() e MouseCol() pra retornar o conteúdo dessas variáveis.
IMPORTANTE TUDO NO MESMO FONTE.
Porque? variáveis estáticas visíveis só nesse fonte, MyInkey() atualizando essas variáveis, e MouseRow() e MouseCol() funções visíveis em todo aplicativo mas pegando o conteúdo dessas variáveis escondidas do restante do aplicativo

O ideal, se for fazer em Clipper, é deixar o fonte o mais próximo possível de Harbour, por exemplo, trocando o nome de MouseRow() e MouseCol() pra MRow() e MCol().
Nessa época ainda não pensava nesses detalhes.

Estou postando o fonte original, porque se eu mexer não vou poder testar o resultado.
Mas aqui ele fica dentro de outro fonte, se eu cortei alguma parte que não devia é só avisar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 20 Jul 2019 18:54

Preparei um ambiente no DOSBOX pra testar aqui, mas descobri uma limitação: O DOSBOX não aceita mouse.
Funciona Clipper, RTLink, Blinker, etc. mas o próprio DOSBOX já avisa que não adianta tentar usar jogos de mouse, que ele não tem isso.
E... como testar mouse sem mouse?
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 21 Jul 2019 07:54

Mais uma opção: título no menu

menu.png


Como fazer isso?
Pensar... o titulo vai ser na linha topo do menu, seria nLinha
Sabemos que a largura é 30, pra simplificar vamos fixar como tamanho 20 pro título.
Isso facilita centralizar, porque são 5 espaços de cada lado, então é só usar nColuna + 5.
E pro texto ficar com tamanho fixo, Pad( texto, 20 )

O que precisamos:

o parâmetro
FUNCTION Menu( nLinha, nColuna, aOpcoes, nOpc, cTitulo )


um valor default:
   hb_Default( @cTitulo, "" )


e mostrar:
      IF Len( cTitulo ) > 0
         @ nLinha, nColuna + 5 SAY Padc( cTitulo, 20 ) COLOR "W/BR"
      ENDIF


Nota: o Clipper não tem hb_Default(), mas é fácil adicionar.
A rotina com tudo acumulado:

#include "inkey.ch"

PROCEDURE Main

   LOCAL nOpc1 := 1, nOpc2 := 1, nOpc3 := 1

   Menu( 5, 10, { "Conhecimento", "Manifesto", "Nota Fiscal", "BPE", "NFCE" }, @nOpc1, "Documento" )
   Menu( 10, 15, { "Envia XML", "Consulta Recibo", "Consulta Protocolo", "Salva XML" }, @nOpc2, "Operacao" )
   Menu( 15, 20, { "Cancela", "Salva", "Deixa assim mesmo" }, @nOpc3, "Solucao" )
   Inkey(0)

   RETURN

FUNCTION Menu( nLinha, nColuna, aOpcoes, nOpc, cTitulo )

   LOCAL nCont, nKey, aMousePos := {}, nOpcClick

   hb_Default( @cTitulo, "" )
   SET EVENTMASK TO INKEY_ALL - INKEY_MOVE
   FOR nCont = 1 TO Len( aOpcoes )
      AAdd( aMousePos, { nLinha + nCont, nColuna + 1, nLinha + nCont, nColuna + 1 + 30 } )
   NEXT

   DO WHILE .T.
      @ nLinha, nColuna TO nLinha + Len( aOpcoes ) + 1, nColuna + 32
      IF Len( cTitulo ) > 0
         @ nLinha, nColuna + 5 SAY Padc( cTitulo, 20 ) COLOR "W/BR"
      ENDIF
      FOR nCont = 1 TO Len( aOpcoes )
         @ nLinha + nCont, nColuna + 1 SAY Pad( aOpcoes[ nCont ], 30 ) COLOR iif( nCont == nOpc, "N/W", "W/B" )
      NEXT
      nKey := Inkey(0)
      DO CASE
      CASE nKey == K_ENTER ; EXIT
      CASE nKey == K_ESC ; EXIT
      CASE nKey == K_UP  ; nOpc := iif( nOpc == 1, Len( aOpcoes ), nOpc - 1 )
      CASE nKey == K_DOWN; nOpc := iif( nOpc == Len( aOpcoes ), 1, nOpc + 1 )
      CASE nKey == K_LBUTTONDOWN
         nOpcClick := ASCan( aMousePos, { | e | MRow() == e[ 1 ] .AND. MCol() >= e[ 2 ] .AND. MRow() == e[ 3 ] .AND. mCol() <= e[ 4 ] } )
         IF nOpcClick != 0
            nOpc := nOpcClick
         ENDIF
      ENDCASE
   ENDDO

   RETURN nOpc

//Clipper
//FUNCTION hb_Default( xVariable, xValue )

//   IF ValType( xVariable ) != ValType( xValue )
//      xVariable := xValue
//   ENDIF

//   RETURN NIL
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor JoséQuintas » 22 Jul 2019 18:55

Olhando a imagem anterior, o box (o contorno do menu) ficou com 1 coluna a mais.
Ué... é olhar aonde desenha o box.... tá + 32 na largura... então reduz pra + 31.

Na prática deixei passar no começo... poderia ter corrigido antes.

Foi só pra postagem como exemplo.
Se fosse pra uso mesmo, vale o que já comentei por aqui: faz algum tipo de alteração, faz todos os testes possíveis, olha como ficou, se dá pra melhorar alguma coisa... e só depois disso acrescenta mais recursos. Quanto antes pegar o problema, mais fácil de fazer a correção, porque tem menos fonte pra olhar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18009
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Menu com mouse no Clipper

Mensagempor sasquast » 15 Ago 2019 16:02

Muito bem explicado. Obrigado.
sasquast
Usuário Nível 1

Usuário Nível 1
 
Mensagens: 26
Data de registro: 31 Jul 2019 16:47
Cidade/Estado: Volta Redonda / RJ
Curtiu: 28 vezes
Mens.Curtidas: 0 vez




Retornar para CA-Clipper

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 4 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro