Page 1 of 2

Burbujas Flotantes

Posted: Wed Sep 11, 2024 1:34 pm
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

Re: Burbujas Flotantes

Posted: Wed Sep 11, 2024 1:41 pm
by Antonio Linares
Estimado Roberto,

Puedes mostrarnos un dibujo de lo que necesitas ?

Aunque solo sea un boceto

gracias!

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 11:21 am
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

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 1:06 pm
by Antonio Linares
Ah, te refieres a un círculo que al darle abre un chat o similar, si ?

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 2:41 pm
by karinha
Nunca he visto nada parecido a lo que quieres. Creo que solo el sistema operativo ANDROID tiene esto.

Regards, saludos.

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 2:43 pm
by Antonio Linares
Creo que es facil de implementar! :-)

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 3:09 pm
by karinha
Antonio Linares wrote:Creo que es facil de implementar! :-)
I was anxious. Forward master!

Estaba ansioso. ¡Adelante maestro!

Regards, saludos.

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 3:20 pm
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...

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 3:24 pm
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

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 4:49 pm
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()

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 5:23 pm
by sysctrl2
Master :D

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 5:28 pm
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

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 6:12 pm
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...

Re: Burbujas Flotantes

Posted: Thu Sep 12, 2024 8:26 pm
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
 

Re: Burbujas Flotantes

Posted: Fri Sep 13, 2024 12:24 pm
by karinha
Buén dia. Maestro: Con Multiple-document interface (MDI) NO FUNCIONA!

Sospeché desde el principio. jajajaja

Gracias, tks.

Regards, saludos.