PDA

Ver la Versión Completa : Drag & Drop para obtenr nombre y ruta de archivo


MAXIUM
31-03-2024, 03:10:53
Hola. Nunca he realizado esto y no logro entenderlo :confused:

Quisiera arrastrar un archivo cualquiera, sea texto, video o imagen a un TImage y que la ruta de este, aparezca en un TEdit.

Ayuuuuuuda!!!

Casimiro Notevi
31-03-2024, 11:56:56
¿Arrastrar texto o "lo que sea" a un TImage?

MAXIUM
31-03-2024, 15:26:54
¿Arrastrar texto o "lo que sea" a un TImage?
Quise decir archivo de texto... es decir, cualquier archivo de cualquier extensión. No necesariamente a un TImage. Puede ser a un TPanel.

MAXIUM
31-03-2024, 21:53:38
Add ShellAPI and Messages to your project's uses:

uses
ShellAPI, Messages;
Add a method to your form that handles the WM_DROPFILES message.

For example, the following would be placed in the TForm1 declaration in the protected section:

protected
procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
Drag 'n' drop are activated by calling:

DragAcceptFiles(Handle, true);
and deactivated by calling:

DragAcceptFiles(Handle, false);
It is normal to activate drag 'n' drop in the OnCreate event, and deactivate it in the OnClose or OnDestroy events:

procedure TForm1.FormCreate(Sender: TObject);
begin
DragAcceptFiles(Handle, true);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DragAcceptFiles(Handle, false);
end;
This first procedure will enable you to drop files one at a time:

procedure TForm1.WMDropFiles(var Msg: TWMDropFiles);
var filename: PChar;
length: LongWord;
begin
length:= DragQueryFile(Msg.Drop, 0, NIL, 0);
filename:= StrAlloc(length+1);
DragQueryFile(Msg.Drop,0,filename,length+1);
{do something with filename}
Msg.Result:=0;
inherited;
end;

escafandra
01-04-2024, 07:20:48
Antes de usar DragAcceptFiles y DragQueryFile deberías deshabilitar el filtro para los mensajes WM_DROPFILES y WM_COPYGLOBALDATA con la API ChangeWindowMessageFilterEx (https://msdn.microsoft.com/es-es/library/windows/desktop/dd388202(v=vs.85).aspx).


Saludos.

Neftali [Germán.Estévez]
02-04-2024, 09:41:05
Hola. Nunca he realizado esto y no logro entenderlo :confused:
Quisiera arrastrar un archivo cualquiera, sea texto, video o imagen a un TImage y que la ruta de este, aparezca en un TEdit.



No es complicado.
Entendiendo los pasos, con unas pocas líneas se puede conseguir.
Necesitas un componente que reciba los ficheros; En este ejemplo he usado un panel, pero puede ser un TImage, el formulario completo,...
En este caso admite varios ficheros; En ese caso llamará varias veces al procedimiento AddFiles.

Añado el ejemplo completo al FTP del Club (http://terawiki.clubdelphi.com/Delphi/Ejemplos/Win-API/?download=DragFilesExplorer.zip).

He colocado un panel en el formulario y le he llamado pnlArrastrar.

https://i.imgur.com/xgliuxt.png


Y te adjunto el código necesario con los comentarios necesarios.

unit uMain;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
TForm3 = class(TForm)
pnlArrastrar: TPanel; // componente que recibirá los ficheros
procedure FormCreate(Sender: TObject);
private
// Mi procedimiento a ejecutar cuando llegue un mensaje al componente (panel)
procedure LBWindowProc(var Message: TMessage);
// Procedimiento cuando se reciba un fichero arrastrado
procedure WMDROPFILES(var Msg: TMessage);
// Procedimiento para definir qué quiero hacer con el fichero que se arrastre...
procedure AddFile(AFileName:String);
end;

var
Form3: TForm3;
OldLBWindowProc: TWndMethod; // apuntador para el procedimiento original

implementation

{$R *.dfm}

uses
ShellAPI;

procedure TForm3.AddFile(AFileName: String);
begin
Caption := 'Fichero: ' + AFileName;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
// Nos quedamnos con la referencia al procedimniento original
OldLBWindowProc := pnlArrastrar.WindowProc;
// Asignamos nuestro procedimiento personalizado para el panel
pnlArrastrar.WindowProc := LBWindowProc;
// Marcamos que queremos que el panel acepte ficheros (los que vamos a arrastrar)
DragAcceptFiles(pnlArrastrar.Handle, True);
end;

procedure TForm3.LBWindowProc(var Message: TMessage);
begin
// sólo queremor "redefinir" el procedimiento de "arrastrar fichreos..."
if Message.Msg = WM_DROPFILES then
WMDROPFILES(Message); // ejecutamos el nuestro
// Ejecutamos siempre lo que hubiera antes...
OldLBWindowProc(Message);
end;

procedure TForm3.WMDROPFILES(var Msg: TMessage);
var
pcFileName: PChar;
i, iSize, iFileCount: integer;
begin
pcFileName := '';
// número de ficheros arrastrados
iFileCount := DragQueryFile(Msg.wParam, $FFFFFFFF, pcFileName, 255);
for i := 0 to iFileCount - 1 do begin
iSize := DragQueryFile(Msg.wParam, i, nil, 0) + 1;
pcFileName := StrAlloc(iSize);
DragQueryFile(Msg.wParam, i, pcFileName, iSize);
if FileExists(pcFileName) then begin
AddFile(pcFileName); // Llamada a AddFile (lo que queramos hacer con el fichero)
end;
StrDispose(pcFileName);
end;
DragFinish(Msg.wParam);
end;

end.

javipes
02-04-2024, 09:42:58
Aunque ya se ha respondido, te amplio algo que yo utilizo, por si te esclarece más, que yo la primera vez me costó un poco:

Por ejemplo, para que el receptor del drag-and-drop sea un tmemo en tu form, puedes ampliar la clase TMemo con

type
//la clase TMemo sera receptora del drag-and-drop
TMemo = class(Vcl.StdCtrls.TMemo) protected
procedure WMDropFiles(var Message: TWMDropFiles); message WM_DROPFILES;
procedure CreateWnd; override;
procedure DestroyWnd; override;
end;

y estos metodos escribirlos:

{$REGION 'Memo'}
procedure TMemo.CreateWnd;
begin
inherited;
DragAcceptFiles(Handle, true);
end;

procedure TMemo.DestroyWnd;
begin
DragAcceptFiles(Handle, false);
inherited;
end;

procedure TMemo.WMDropFiles(var Message: TWMDropFiles);
var
numfichs: integer;
fn: array[0..MAX_PATH-1] of char;
nomfichero,extension:string;
begin
numfichs := DragQueryFile(Message.Drop, $FFFFFFFF, fn, MAX_PATH);
if numfichs <> 1 then
begin
MessageBox(Handle, 'Solo un fichero.', 'Error descarga', MB_ICONERROR);
Exit;
end;
if DragQueryFile(Message.Drop, 0, fn, MAX_PATH) = 0 then
Exit;
nomfichero := fn; //contiene el path completo
//hacer lo que se quiera con el fichero o con el nombre
end;
{$ENDREGION 'Memo'}

con esto, cualquier tmemo que incluyas en tu form podra ser receptor de drag and drop, por ejemplo para cargar en el el contenido del fichero si es de tipo texto.
Tambien podrías cambiarlo para aplicarlo sobre un tedit y que el receptor fuera el tedit....

javipes
02-04-2024, 09:45:19
Neftali, hemos 'chocado'.
Pero ¿porque no se ve mi codigo bien? cuando he previsualizado lo veía bien antes de enviarlo.....

Neftali [Germán.Estévez]
02-04-2024, 09:50:16
Neftali, hemos 'chocado'.

Si, nos hemos pisado los mensajes..


Pero ¿porque no se ve mi codigo bien? cuando he previsualizado lo veía bien antes de enviarlo.....
Ya está corregido.
Es un error antiguo de vBulletin. A veces cuando se usa la vista previa, se hace un lío con las etiquetas...

javipes
02-04-2024, 09:57:08
;555187']Si, nos hemos pisado los mensajes..

Ya está corregido.
Es un error antiguo de vBulletin. A veces cuando se usa la vista previa, se hace un lío con las etiquetas...

gracias, maestro.