Newsgroup: it.comp.programmare.win32
Titolo: load diretto di un file

Ciao a tutti.
	Ho realizzato un'applicazione in Vc++ 6 che legge dei file con
estensione particolare. Volevo sapere se esiste un modo per far caricare
direttamente all'applicazione il file trascinandovelo sopra come
generalmente si fa nelle applicazioni windows.
Grazie a chiunque mi sapra' aiutare.
ciao Stefano

Prova ad aggiungere il metodo OnDropFiles con il CLW...
void CMyDlg::OnDropFiles(HDROP hDropInfo)
{
	TCHAR buf[MAX_PATH];
	int howmany=DragQueryFile(hDropInfo,-1,buf,MAX_PATH);
	for (int i=0;i<howmany;i++)
	{
		DragQueryFile(hDropInfo,i,buf,MAX_PATH);
		OnFileOpen(buf);
	}
}
Luc.


 generalmente si fa nelle applicazioni windows.
La cosa piu` semplice e` chiamare DragAcceptFiles sulla
CWnd che vuoi che accetti i file "trascinatici su`", cioe`
normalmente aggiungere una riga al codice generato per
te dal Wizard nell'InitInstance della tua applicazione:
 // The one and only window has been initialized, so show and update it.
 m_pMainWnd->DragAcceptFiles();        // la riga da aggiungere
 m_pMainWnd->ShowWindow(SW_SHOW);
 m_pMainWnd->UpdateWindow();
Cosi` facendo, la tua finestra accettera` il drop di files
(di qualsiasi tipo).  Quando i file vengono droppati ricevi
un messaggio WM_DROPFILES, quindi aggiungine la gestione
(col class-wizard); un esempio-giocattolo:
void CMainFrame::OnDropFiles(HDROP hDropInfo)
{
    CString dropmsg;
    UINT nFiles = DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
    if(nFiles==1) {
        DragQueryFile(hDropInfo, 0, dropmsg.GetBufferSetLength(MAX_PATH),
MAX_PATH);
        dropmsg.ReleaseBuffer();
    } else {
        dropmsg.Format("%d files", nFiles);
    }
    AfxMessageBox(dropmsg);
}
Naturalmente, nella tua applicazione tu vorrai normalmente
[a] eventualmente controllare che ci sia un solo file alla
volta come in questo esempio (o se no fare un ciclo di
DragQueryFile su tutti i file droppati assieme su di te),
[b] fare qualcosa di piu` costruttivo con i filename stessi
se per te accettabili (ad esempio aprire i files).
Note che le due linee:
 // Enable drag/drop open
 m_pMainWnd->DragAcceptFiles();
vengono inserite per te dal Wizard se hai usato il wizard
stesso per associare l'applicazione a una certa estensione.
La gestione di default cerca di caricare il file come tuo
documento (anche se il tipo non e` adatto...).
Si puo` fare di meglio, dando un feedback grafico di "e` OK
droppare qui" solo per drop che puoi effettivamente accettare,
ma non e` esattamente altrettanto banale quanto accettare
qualsiasi drop di files (e solo di files) e selezionare la
cosa a posteriori, dopo che il drop e` avvenuto, come in
questo esempio.  Sostanzialmente, devi usare nella tua
classe di view una COleDropTarget (tipicamente ne terrai
un'istanza come membro della tua classe derivata da CView)
e chiamarne la funzione-membro Register (passando come unico
argomento il puntatore alla CWnd che puo` accettare i drop,
tipicamente "this") normalmente in fase di creazione della
tua finestra (nella OnCreate, che ottieni gestendo il WM_CREATE
della tua finestra).  Non scordare l'#include <afxole.h>...!
Normalmente lo metterai nel tuo stdafx.h assieme agli altri.
Inoltre, dovrai chiamare AfxOleInit() all'inizio della tua
InitInstance, e NON chiamare la DragAcceptFiles (se del caso,
commenta via quella che ti ha inserito il wizard).
Nella tua classe view farai override delle apposite funzioni
virtuali ("add virtual function..." da ClassView, ecc ecc).
Ecco un semplice esempio, basato sul fatto di avere nella
tua classe View due membri dati, un bool m_isdragok (che
viene inizializzato a false nel costruttore) ed una CString
m_sfn.  Spero che la logica sia chiara...:
DROPEFFECT CMfcapView::OnDragEnter(COleDataObject* pDataObject, DWORD
dwKeyState, CPoint point)
{
    // di default non accettiamo il drag
    m_isdragok = false;
    // vediamo se l'oggetto draggato e` un tot di files
    FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1,
TYMED_HGLOBAL };
    STGMEDIUM stgmed;
    if(pDataObject->GetData(CF_HDROP, &stgmed, &fmtetc)) {
        // si`, sono files, esaminiamoli meglio
        HDROP hdrop = (HDROP)GlobalLock(stgmed.hGlobal);
        bool isok=false;
        if(hdrop) {
            UINT nFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0);
            if(nFiles==1) {
                // e` un file solo, vediamo come si chiama
                DragQueryFile(hdrop, 0, m_sfn.GetBufferSetLength(MAX_PATH),
MAX_PATH);
                m_sfn.ReleaseBuffer();
                // lo accettiamo se e solo se e` un .txt
                m_isdragok= 0 == m_sfn.Right(4).CompareNoCase(".txt");
            }
            GlobalUnlock(hdrop);
        }
        ReleaseStgMedium(&stgmed);
        // segnaliamo, anche graficamente, l'accettazione:
        if(m_isdragok)
            return DROPEFFECT_COPY;
    }
 return CView::OnDragEnter(pDataObject, dwKeyState, point);
}
void CMfcapView::OnDragLeave()
{
    // resettiamo il flag di accettazione drag
    m_isdragok = false;
 CView::OnDragLeave();
}
DROPEFFECT CMfcapView::OnDragOver(COleDataObject* pDataObject, DWORD
dwKeyState, CPoint point)
{
    // continuiamo a segnalara l'accettazione se del caso
    if(m_isdragok)
        return DROPEFFECT_COPY;
 return CView::OnDragOver(pDataObject, dwKeyState, point);
}
BOOL CMfcapView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect,
CPoint point)
{
    if(m_isdragok) {
        // apriamo il file-documento che abbiamo accettato
        AfxGetApp()->OpenDocumentFile(m_sfn);
        return TRUE;
    }
 return CView::OnDrop(pDataObject, dropEffect, point);
}
Alex

 Alex
Grazie!!! Tutto molto chiaro e preciso. Ora provo ad applicarlo e vedro'
i risultati.
Stefano
-- 
" Catastrofi del nostro secolo: Hiroshima 45, Cernobyl 86, Windows 95. "

 
Grazie dell'aiuto!
