Burbujas Flotantes

User avatar
TOTOVIOTTI
Posts: 422
Joined: Fri Feb 05, 2010 11:30 am
Location: San Francisco - Córdoba - Argentina

Burbujas Flotantes

Post by TOTOVIOTTI »

Hola amigos...

será posible??? Para FW casi nada es imposible.. no? Pero aún no se como...

La idea es hacer unas burbujas flotantes en mi windows que disparen acciones, cualquiera
sean.... que dicen? Será posible?? Maestro Antonio... que dice??

Muchas gracias!!

Roberto
Univ@c I.S.I.
Desarrolladores de Software
http://www.elcolegioencasa.edu.ar
User avatar
Antonio Linares
Site Admin
Posts: 42268
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Burbujas Flotantes

Post by Antonio Linares »

Estimado Roberto,

Puedes mostrarnos un dibujo de lo que necesitas ?

Aunque solo sea un boceto

gracias!
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
TOTOVIOTTI
Posts: 422
Joined: Fri Feb 05, 2010 11:30 am
Location: San Francisco - Córdoba - Argentina

Re: Burbujas Flotantes

Post by TOTOVIOTTI »

Antonio, gracias por responder...

ante todo, excelente el webinar y todas las herramientas siempre disponibles de
este maravilloso lenguaje, GRACIAS.
Obviamente gracias a todos los que colaboraron también..

No supe como adjuntar imágenes, no obstante, para que tengas una idea,
cuando entras a una página web y hay algún botón flotante o fijo para enviar un
whatsapp por ejemplo, algo de ese tipo. Quería añadir a mi windows alguna utilidad
que se pueda pulsar desde un botón que no esté ni en el menú ni en la barra de tareas.

Espero haberme explicado...
mil gracias

Roberto
Univ@c I.S.I.
Desarrolladores de Software
http://www.elcolegioencasa.edu.ar
User avatar
Antonio Linares
Site Admin
Posts: 42268
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Burbujas Flotantes

Post by Antonio Linares »

Ah, te refieres a un círculo que al darle abre un chat o similar, si ?
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
karinha
Posts: 7885
Joined: Tue Dec 20, 2005 7:36 pm
Location: São Paulo - Brasil
Contact:

Re: Burbujas Flotantes

Post by karinha »

Nunca he visto nada parecido a lo que quieres. Creo que solo el sistema operativo ANDROID tiene esto.

Regards, saludos.
João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
User avatar
Antonio Linares
Site Admin
Posts: 42268
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Burbujas Flotantes

Post by Antonio Linares »

Creo que es facil de implementar! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
karinha
Posts: 7885
Joined: Tue Dec 20, 2005 7:36 pm
Location: São Paulo - Brasil
Contact:

Re: Burbujas Flotantes

Post by karinha »

Antonio Linares wrote:Creo que es facil de implementar! :-)
I was anxious. Forward master!

Estaba ansioso. ¡Adelante maestro!

Regards, saludos.
João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
User avatar
Antonio Linares
Site Admin
Posts: 42268
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Burbujas Flotantes

Post by Antonio Linares »

Primero creamos un ejemplo en C, con la ayuda de Claude, para asegurarnos de que es posible hacerlo y que el concepto funciona bien:

test.c

Code: Select all | Expand

#include <windows.h>
#include <math.h>

#define CIRCLE_RADIUS 100
#define WINDOW_SIZE (CIRCLE_RADIUS * 2)

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CreateOpaqueCircle(HWND hwnd);
BOOL IsInsideCircle(int x, int y);

// Variables globales para el movimiento
BOOL isDragging = FALSE;
int dragOffsetX = 0;
int dragOffsetY = 0;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    const char CLASS_NAME[] = "OpaqueCircularControl";

    WNDCLASS wc = {0};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.style = CS_DBLCLKS;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        "Opaque Circular Control",
        WS_POPUP | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_SIZE, WINDOW_SIZE,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hwnd == NULL) {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CREATE:
            CreateOpaqueCircle(hwnd);
            return 0;

        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
            SelectObject(hdc, brush);
            Ellipse(hdc, 0, 0, WINDOW_SIZE, WINDOW_SIZE);
            DeleteObject(brush);
            EndPaint(hwnd, &ps);
            return 0;
        }

        case WM_LBUTTONDOWN: {
            int xPos = LOWORD(lParam);
            int yPos = HIWORD(lParam);
            
            if (IsInsideCircle(xPos, yPos)) {
                isDragging = TRUE;
                dragOffsetX = xPos;
                dragOffsetY = yPos;
                SetCapture(hwnd);
            }
            return 0;
        }

        case WM_MOUSEMOVE: {
            if (isDragging) {
                int xPos = LOWORD(lParam);
                int yPos = HIWORD(lParam);
                
                RECT windowRect;
                GetWindowRect(hwnd, &windowRect);
                int newX = windowRect.left + (xPos - dragOffsetX);
                int newY = windowRect.top + (yPos - dragOffsetY);
                
                SetWindowPos(hwnd, NULL, newX, newY, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
            }
            return 0;
        }

        case WM_LBUTTONUP: {
            if (isDragging) {
                isDragging = FALSE;
                ReleaseCapture();
            }
            return 0;
        }

        case WM_LBUTTONDBLCLK: {
            int xPos = LOWORD(lParam);
            int yPos = HIWORD(lParam);
            
            if (IsInsideCircle(xPos, yPos)) {
                MessageBox(hwnd, "¡Doble clic dentro del círculo!", "Acción", MB_OK);
            }
            return 0;
        }

        case WM_RBUTTONDOWN: {
            int xPos = LOWORD(lParam);
            int yPos = HIWORD(lParam);
            
            if (IsInsideCircle(xPos, yPos)) {
                DestroyWindow(hwnd);
            }
            return 0;
        }        

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void CreateOpaqueCircle(HWND hwnd) {
    HRGN hRgn = CreateEllipticRgn(0, 0, WINDOW_SIZE, WINDOW_SIZE);
    SetWindowRgn(hwnd, hRgn, TRUE);
}

BOOL IsInsideCircle(int x, int y) {
    int centerX = CIRCLE_RADIUS;
    int centerY = CIRCLE_RADIUS;
    double distance = sqrt(pow(x - centerX, 2) + pow(y - centerY, 2));
    return distance <= CIRCLE_RADIUS;
}
Lo construimos con MSVC32 de esta forma:
cl /Fe"CircularControl.exe" /DWIN32 /D_WINDOWS /nologo /W4 /O2 test.c user32.lib gdi32.lib kernel32.lib /link /SUBSYSTEM:WINDOWS
Y funciona correctamente! :-)
Image
Sabiendo que funciona bien ahora se trata de implementar la clase en FWH...
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 42268
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Burbujas Flotantes

Post by Antonio Linares »

Aqui está el EXE por si quereis probarlo:

https://github.com/FiveTechSoft/FWH_too ... ontrol.exe

Con el botón izquierdo del ratón movemos el círculo
Con doble click izquierdo lanzamos una acción
Con el click derecho lo cerramos
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 42268
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Burbujas Flotantes

Post by Antonio Linares »

Versión para FWH:

circle.prg

Code: Select all | Expand

#include "FiveWin.ch"

function Main()

    local oWnd, oCircle 

    DEFINE WINDOW oWnd TITLE "Testing Class TCircle" COLOR "W/BG" SIZE 1200, 800

    oCircle = TCircle():New( 50, 80, 120, CLR_BLUE, oWnd )

    ACTIVATE WINDOW oWnd CENTER

return nil    

CLASS TCircle FROM TControl 

   CLASSDATA lRegistered AS LOGICAL

   DATA   nRadius, hRgn
   DATA   lDragging INIT .F.
   DATA   nDragOffsetX INIT 0
   DATA   nDragOffsetY INIT 0

   METHOD New( nTop, nLeft, nRadius, nRGBColor, oWnd ) CONSTRUCTOR

   METHOD Paint() 

   METHOD Display() INLINE ::BeginPaint(), ::Paint(), ::EndPaint(), 0 

   METHOD LButtonDown( nX, nY, nFlags )  

   METHOD LButtonUp( nX, nY, nFlags ) INLINE ::lDragging := .F., nil 

   METHOD MouseMove( nX, nY, nFlags ) 

   METHOD Destroy() 

ENDCLASS    

METHOD New( nTop, nLeft, nRadius, nRGBColor, oWnd ) CLASS TCircle

   DEFAULT nTop := 0, nLeft := 0, nRadius := 100,;
           oWnd := GetWndDefault()

   ::nTop    = nTop
   ::nLeft   = nLeft
   ::nBottom = nTop + ( nRadius * 2 ) 
   ::nRight  = nLeft + ( nRadius * 2 )
   ::nRadius = nRadius
   ::oWnd    = oWnd   
   ::nStyle  = nOr( WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN )

   ::Register()

   if ! Empty( ::oWnd:hWnd )
      ::Create()
      ::SetBrush( TBrush():New( , nRGBColor ) )
      ::hRgn = CreateEllipticRgn( 0, 0, ::nRadius, ::nRadius )
      SetWindowRgn( ::hWnd, ::hRgn, .T. )
      ::oWnd:AddControl( Self )
   else
      ::oWnd:DefControl( Self )
   endif
 
return Self   

METHOD Paint() CLASS TCircle

    SelectObject( ::hDC, ::oBrush:hBrush )
    Ellipse( ::hDC, 0, 0, ::nRadius, ::nRadius )
    
return 0    

METHOD LButtonDown( nX, nY, nFlags ) CLASS TCircle 

   if ! ::lDragging
      ::lDragging = .T.
      ::nDragOffsetX = nX 
      ::nDragOffsetY = nY 
   endif
   
return nil   

METHOD MouseMove( nX, nY, nFlags ) CLASS TCircle 

   if ::lDragging
      ::Move( ::nTop + nX - ::nDragOffsetX, ::nLeft + nY - ::nDragOffsetY,,, .T. )
   endif
   
return nil   

METHOD Destroy() CLASS TCircle

   if ! Empty( ::hRgn )
      DeleteObject( ::hRgn )
   endif
 
 return ::Super:Destroy()
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
sysctrl2
Posts: 1035
Joined: Mon Feb 05, 2007 7:15 pm
Contact:

Re: Burbujas Flotantes

Post by sysctrl2 »

Master :D
Cesar Cortes Cruz
SysCtrl Software
Mexico

' Sin +- FWH es mejor "
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: Burbujas Flotantes

Post by paquitohm »

Buenísimo estimado Antonio !!!

Se le ve un potencial tremendo:
- Burbujas libres o dentro de la Window
- 3D customizable
- Sombra customizable
- Color y tamaño customizables
- Guardar/ restaurar coordenadas y parámetros customizables

Se le puede sacar un partido tremendo
User avatar
TOTOVIOTTI
Posts: 422
Joined: Fri Feb 05, 2010 11:30 am
Location: San Francisco - Córdoba - Argentina

Re: Burbujas Flotantes

Post by TOTOVIOTTI »

Faaaaaaaaaaaaaaaaaaaaaaaa.....

los dejás un rato y puede más la genialidad...!!!

Gracias Antoniooooooooooooooooooooooooooooo!!!!

Y ya que pedimos... quiero todo lo que dice Paquito!
Así que... manos a la obra! Jajajajajjaa

Tendría que darle un "Action" ahora... veo como hacerlo...
Univ@c I.S.I.
Desarrolladores de Software
http://www.elcolegioencasa.edu.ar
User avatar
TOTOVIOTTI
Posts: 422
Joined: Fri Feb 05, 2010 11:30 am
Location: San Francisco - Córdoba - Argentina

Re: Burbujas Flotantes

Post by TOTOVIOTTI »

Mi "amigo" Claude y yo... bah... todo mérito de él en realidad, le agregó el action:

Code: Select all | Expand

#include "FiveWin.ch"

function Main()
    local oWnd, oCircle

    DEFINE WINDOW oWnd TITLE "Testing Class TCircle" COLOR "W/BG" SIZE 1200, 800

    oCircle = TCircle():New( 50, 80, 120, CLR_BLUE, oWnd, {|| MsgInfo("¡Círculo presionado!", "Acción") } )

    ACTIVATE WINDOW oWnd CENTER

return nil    

CLASS TCircle FROM TControl
   CLASSDATA lRegistered AS LOGICAL

   DATA   nRadius, hRgn
   DATA   lDragging INIT .F.
   DATA   nDragOffsetX INIT 0
   DATA   nDragOffsetY INIT 0
   DATA   bAction

   METHOD New( nTop, nLeft, nRadius, nRGBColor, oWnd, bAction ) CONSTRUCTOR
   METHOD Paint()
   METHOD Display() INLINE ::BeginPaint(), ::Paint(), ::EndPaint(), 0
   METHOD LButtonDown( nX, nY, nFlags )  
   METHOD LButtonUp( nX, nY, nFlags ) 
   METHOD MouseMove( nX, nY, nFlags )
   METHOD Destroy()
   METHOD PerformAction()

ENDCLASS    

METHOD New( nTop, nLeft, nRadius, nRGBColor, oWnd, bAction ) CLASS TCircle
   DEFAULT nTop := 0, nLeft := 0, nRadius := 100,;
           oWnd := GetWndDefault(), bAction := {|| nil }

   ::nTop    = nTop
   ::nLeft   = nLeft
   ::nBottom = nTop + ( nRadius * 2 )
   ::nRight  = nLeft + ( nRadius * 2 )
   ::nRadius = nRadius
   ::oWnd    = oWnd  
   ::nStyle  = nOr( WS_CHILD, WS_VISIBLE, WS_CLIPCHILDREN )
   ::bAction = bAction

   ::Register()

   if ! Empty( ::oWnd:hWnd )
      ::Create()
      ::SetBrush( TBrush():New( , nRGBColor ) )
      ::hRgn = CreateEllipticRgn( 0, 0, ::nRadius, ::nRadius )
      SetWindowRgn( ::hWnd, ::hRgn, .T. )
      ::oWnd:AddControl( Self )
   else
      ::oWnd:DefControl( Self )
   endif
 
return Self  

METHOD Paint() CLASS TCircle
    SelectObject( ::hDC, ::oBrush:hBrush )
    Ellipse( ::hDC, 0, 0, ::nRadius, ::nRadius )
   
return 0    

METHOD LButtonDown( nX, nY, nFlags ) CLASS TCircle
   if ! ::lDragging
      ::lDragging = .T.
      ::nDragOffsetX = nX
      ::nDragOffsetY = nY
      ::PerformAction()
   endif
   
return nil  

METHOD LButtonUp( nX, nY, nFlags ) CLASS TCircle
   ::lDragging := .F.
return nil

METHOD MouseMove( nX, nY, nFlags ) CLASS TCircle
   if ::lDragging
      ::Move( ::nTop + nX - ::nDragOffsetX, ::nLeft + nY - ::nDragOffsetY,,, .T. )
   endif
   
return nil  

METHOD Destroy() CLASS TCircle
   if ! Empty( ::hRgn )
      DeleteObject( ::hRgn )
   endif
 
return ::Super:Destroy()

METHOD PerformAction() CLASS TCircle
   Eval( ::bAction )
return nil
 
Univ@c I.S.I.
Desarrolladores de Software
http://www.elcolegioencasa.edu.ar
User avatar
karinha
Posts: 7885
Joined: Tue Dec 20, 2005 7:36 pm
Location: São Paulo - Brasil
Contact:

Re: Burbujas Flotantes

Post by karinha »

Buén dia. Maestro: Con Multiple-document interface (MDI) NO FUNCIONA!

Sospeché desde el principio. jajajaja

Gracias, tks.

Regards, saludos.
João Santos - São Paulo - Brasil - Phone: +55(11)95150-7341
Post Reply