Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

ALFREDO-CESAR. Arratrar TShape por un Formulario o TImage?

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: ALFREDO-CESAR. Arratrar TShape por un Formulario o TImage? Responder citando

Hago esto:
Código:

void __fastcall TfrmZonas::LMDShapeButton1MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
    TLMDShapeButton *Objeto = (TLMDShapeButton *)Sender;
    ReleaseCapture();
    SendMessage(Objeto->Handle),WM_NCLBUTTONDOWN, HTCAPTION, 0);
}



y me dice esto:

[C++ Error] UnidadZonas.cpp(372): E2316 'Handle' is not a member of 'TLMDShapeButton'


Que estoy haciendo mal?...

Lo mismo me dice el compilador si utilizo un TShape normal.

Donde está la propiedad "Handle" de un componente TShape.



Y puestos a pedir.

¿Como hago para que el Objeto que estoy arrastrando se mueva con el cursor o se enganche al ratón mientras desplazo el Objeto?

Muchisimas GRACIAS.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Urgente Responder citando

Por favor, necesito que alguien me ayude, es URGENTE.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Hola, bueno el problema es que este componente no tiene Handle asi que no puedes agarrarlo por ahi, pero hay otra forma no tan elegante y simple pero funciona, primero debes declarar las siguentes variables bajo private del header:
bool Arrastrando;
Int CentroH, CentroV;
y vamos a utilizar los tres eventos mouse, para fijar mover y soltar el shape
Código:

void __fastcall TForm1::Shape1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 TShape * oTmpShape = (TShape *)Sender;
     CentroH = oTmpShape->Width / 2;
     oTmpShape->Left = oTmpShape->Left+X-CentroH;
     CentroV = oTmpShape->Height / 2;
     oTmpShape->Top = oTmpShape->Top+Y-CentroV;
     Arrastrando = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Shape1MouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
if (Arrastrando)
{
        TShape * oTmpShape = (TShape *)Sender;
        oTmpShape->Left = oTmpShape->Left+X-CentroH;
        oTmpShape->Top = oTmpShape->Top+Y-CentroV;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Shape1MouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
Arrastrando = False;

}
//---------------------------------------------------------------------------
Espero que te sirva, se puede mejorar el codigo para que no salte al darle click fuera de su centro calculando las coordenadas absolutas respecto al form y aplicando las correcciones pertinentes
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

Gracias Alfredo, lo probaré
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Prueba asi, ya que TShape, no deciende de TWinControl, por lo tanto, no tiene la propiedad Handle, pero haciendo chapuza, trampa, etc etc,
prueba esta codigo..

Código:
void __fastcall TForm1::Shape1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
    // jalamos el control
    TShape  *pS = static_cast<TShape*>(Sender);
    // guardamos el parent original
    TWinControl *parentOriginal = pS->Parent;
    // creamos un panel temporal
    TPanel  *pP = new TPanel(this);
    pP->Parent = this;
    // del tamaño del TShape
    pP->SetBounds(pS->Left,pS->Top,pS->Width,pS->Height);
    pP->Parent = pS->Parent;
    pS->Parent = pP; // metemos el TShap en el panel
    // lo movemos, y al final
    ReleaseCapture();
    SNDMSG(pP->Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    // restauramos el original.
    pS->Parent = parentOriginal;
    pS->Left   = pP->Left;
    pS->Top    = pP->Top;
    delete pP;

}

_________________
Cool
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email MSN Messenger
Mensaje    Asunto: Responder citando

Gracias Cesar por contestar, pero la verdad es que lo que Alfredo me ha ofrecido era lo que realmente necesitaba. Con el codigo que tu me propones solo se vé el perimetro del TPanel, aparte de que el resultado no es Optimo. De la forma que Alfredo me ha propuesto el efecto visual es que arrastras realmente el TLMDShapeButton. Gracias a los dos.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: PARA ALFREDO Responder citando

Alfredo, funciona perfectamente, a falta de el incomodo click que hace que se cambie de sitio. Como tu bien dices hay que calcular las coordenadas, en el momento que hago click, pero despues de intentarlo una y otra vez, he desesperado un poco , ya que no se en que evento tengo que hacerlo realmente y cuando le debo de dar las nuevas coordenadas al Objeto. Si no te supone mucho problema, podrias echarme otra vez una mano? GRACIAS.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Hola, Pues resulta que era mas sencillo de lo que parecia, ya me imaginaba yo convirtiendo coordenadas relativas a absolutas, pues no...
el evento que usamos es del shape y las posiciones X,Y son por tanto relativas a este, asi que solo modifica OnMouseDown como abajo:
Código:
void __fastcall TForm1::Shape1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 TShape * oTmpShape = (TShape *)Sender;
     CentroH = X;//Posicion X donde Hacemos Click sobre el Shape
     oTmpShape->Left = oTmpShape->Left+X-CentroH;
     CentroV = Y;//Posicion Y donde Hacemos Click sobre el Shape
     oTmpShape->Top = oTmpShape->Top+Y-CentroV;
     Arrastrando = true;
}
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

Otra opción, en la que solo tendrás que usar el evento OnMouseMove.

- Pon el siguiente código en el OnMouseMove de cualquier control que necesites mover:
Código:
TControl* control = static_cast<TControl*>(Sender);
static bool pulsado = false;
static TPoint posicion;

if (!pulsado && Shift.Contains(ssLeft))
    posicion = Point(X, Y);

pulsado = Shift.Contains(ssLeft);
if (pulsado)
{
    control->Left += X - posicion.x;
    control->Top  += Y - posicion.y;
}
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Muy bueno!! este _Leo si sabe hacer Aikus con el codigo Smile
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: MIL Gracias Responder citando

Soys unos genios del la programación, es lo único que se me ocurre.

Los dos formas que me proponeis funcionan perfectamente, aunque con la forma de _Leo se escribe menos codigo y no hace falta emplear variables globales a nivel de formulario.

Por otra parte el código de Alfredo también considero que es muy elegante, aunque existia código redundante:
Código:

void __fastcall TForm1::Shape1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
 TShape * oTmpShape = (TShape *)Sender;
     CentroH = X;//Posicion X donde Hacemos Click sobre el Shape
     oTmpShape->Left = oTmpShape->Left+X-CentroH;
     CentroV = Y;//Posicion Y donde Hacemos Click sobre el Shape
     oTmpShape->Top = oTmpShape->Top+Y-CentroV;
     Arrastrando = true;
}

Este código era redundante:

oTmpShape->Left = oTmpShape->Left+X-CentroH;
oTmpShape->Top = oTmpShape->Top+Y-CentroV;


Quedando de esta forma:
Código:

void __fastcall TForm1::Shape1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
     TShape * oTmpShape = (TShape *)Sender;
     CentroH = X;//Posicion X donde Hacemos Click sobre el Shape
     CentroV = Y;//Posicion Y donde Hacemos Click sobre el Shape
     Arrastrando = true;
}


Al final mi codigo ha quedado asi:
Código:

void __fastcall TfrmZonas::LMDShapeButton1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
    TLMDShapeButton * PLSB = (TLMDShapeButton *)Sender;// Puntero al Objeto TLMDShapeButton

    Componente = PLSB->ComponentIndex; // Para saver el Numero de Componente que he pulsado
    LeftAnt = PLSB->Left; // Para guardar su posicion Left anterior por si se rechazo el arrastre
    TopAnt = PLSB->Top;  // Para guardar su posicion Top anterior por si se rechazo el arrastre
}
//---------------------------------------------------------------------------
void __fastcall TfrmZonas::LMDShapeButton1MouseMove(TObject *Sender,
      TShiftState Shift, int X, int Y)
{
    // Codigo de _Leo
    TControl* control = static_cast<TControl*>(Sender);
    static bool pulsado = false;
    static TPoint posicion;

    if (!pulsado && Shift.Contains(ssLeft))
        posicion = Point(X, Y);

    pulsado = Shift.Contains(ssLeft);
    if (pulsado)
    {
        control->Left += X - posicion.x;
        control->Top  += Y - posicion.y;
    }
}
//---------------------------------------------------------------------------
void __fastcall TfrmZonas::LMDShapeButton1MouseUp(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
    if(((TLMDShapeButton *)Sender)->Left > (741 - ((TLMDShapeButton *)Sender)->Width) || ((TLMDShapeButton *)Sender)->Top > (741 - ((TLMDShapeButton *)Sender)->Height))
    {
        ShowMessagePos("La nueva posición está fuera del Plano permitido.\n\n"
        "Si quiere ver los límites del plano active la Rejilla de Orientación,\n"
        "en la pantalla anterior.", frmVentas->Left + 350,frmVentas->Top + 300);

        ((TLMDShapeButton *)Sender)->Left = LeftAnt;
        ((TLMDShapeButton *)Sender)->Top = TopAnt;
    }

    if(((TLMDShapeButton *)Sender)->Left != LeftAnt || ((TLMDShapeButton *)Sender)->Top != TopAnt)
        BtnGuardar->Enabled = true; // Si el arrastre a tenido exito
}
//---------------------------------------------------------------------------



Todo esto, porque es un mapa dibujado en un TImage y necesito saver si el usuario se sale de el, cuando arrastra los Objetos del Formulario.
Así que tengo que controlar que el arrastre se rechace en caso de que se salga.

En resumen que he solucionado el problema gracias a los dos.

Por cierto....
Esta linea ¿Es un puntero a el Objeto TLMDShapeButton?
TLMDShapeButton * PLSB = (TLMDShapeButton *)Sender;// Puntero al Objeto TLMDShapeButton


Perdonar mi ignorancia.
Pero si no es así. ¿Me podeis explicar que es?
No quiero parecer repetitivo,... pero Gracias otra vez.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Bueno gracias por lo de genio, pero en mi caso no debe aplicar ya que tu mejoraste mi codigo, yo me quedo con el de _Leo por que como tu dijiste tiene menos lineas, usa menos eventos y se ahorra unas variables.

Con respecto a tu pregunta aunque estoy algo flojo en teoria creo que
TLMDShapeButton * PLSB es un puntero al tipo de objeto y
= (TLMDShapeButton *)Sender es lo que hace que apunte al objeto en si.

Si me equivoco alguien me corregira espero.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email
Mensaje    Asunto: Responder citando

Gracias Alfredo por tu rapida respuesta, en cuanto al tema, por mi parte ya está todo resuelto. Gracias.
_________________
Muchos hombres no se equivocan jamás porque no se proponen nada razonable.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.