|
/////////////////////////////////////////////////////////////////////////////
//
// CDropEdit
// Copyright 1997 Chris Losinger
//
// This code is freely distributable and modifiable, as long as credit
// is given to where it's due. Watch, I'll demonstrate :
//
// shortcut expansion code modified from :
// CShortcut, 1996 Rob Warner
//
////
//
// To use this in an app, you'll need to :
//
// 1) Place a normal edit control on your dialog.
// 2) Check the "Accept Files" property.
//
// 4) In your dialog class, declare a member variable of type CDropEdit
// (be sure to #include "CDropEdit.h")
// ex. CDropEdit m_dropEdit;
//
// 5) In your dialog's OnInitDialog, call
// m_dropEdit.SubclassDlgItem(IDC_YOUR_EDIT_ID, this);
//
// that's it!
//
// This will behave exactly like a normal edit-control but with the
// ability to accept drag-n-dropped files (or directories).
//
// Modified Mid 1998 by Chris Maunder:
// - DropEdit can now accept files and directories at the
// same time
#include "stdafx.h"
#include "DropEdit.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <afxdisp.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDropEdit
CDropEdit::CDropEdit()
{
m_bAllowFiles = m_bAllowDirs = TRUE;
// Initialize OLE libraries
m_bMustUninitOLE = FALSE;
_AFX_THREAD_STATE* pState = AfxGetThreadState();
if (!pState->m_bNeedTerm)
{
SCODE sc = ::OleInitialize(NULL);
if (FAILED(sc))
AfxMessageBox(_T("OLE initialization failed. Make sure that the OLE libraries are the correct version"));
else
m_bMustUninitOLE = TRUE;
}
}
CDropEdit::~CDropEdit()
{
// Uninitialize OLE support
if (m_bMustUninitOLE)
::OleUninitialize();
}
BEGIN_MESSAGE_MAP(CDropEdit, CEdit)
//{{AFX_MSG_MAP(CDropEdit)
ON_WM_CREATE()
ON_WM_DROPFILES()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDropEdit message handlers
int CDropEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;
DragAcceptFiles(TRUE);
return 0;
}
//
// handle WM_DROPFILES
//
void CDropEdit::OnDropFiles(HDROP dropInfo)
{
// Get the number of pathnames that have been dropped
WORD wNumFilesDropped = DragQueryFile(dropInfo, -1, NULL, 0);
CString firstFile="";
// get all file names. but we'll only need the first one.
for (WORD x = 0 ; x < wNumFilesDropped; x++) {
// Get the number of bytes required by the file's full pathname
WORD wPathnameSize = DragQueryFile(dropInfo, x, NULL, 0);
// Allocate memory to contain full pathname & zero byte
char * npszFile = (char *) LocalAlloc(LPTR, wPathnameSize += 1);
// If not enough memory, skip this one
if (npszFile == NULL) continue;
// Copy the pathname into the buffer
DragQueryFile(dropInfo, x, npszFile, wPathnameSize);
// we only care about the first
if (firstFile=="")
firstFile=npszFile;
// clean up
LocalFree(npszFile);
}
// Free the memory block containing the dropped-file information
DragFinish(dropInfo);
// if this was a shortcut, we need to expand it to the target path
CString expandedFile = ExpandShortcut(firstFile);
// if that worked, we should have a real file name
if (expandedFile!="")
firstFile=expandedFile;
struct _stat buf;
// get some info about that file
int result = _stat( firstFile, &buf );
if( result == 0 ) {
// verify that we have a dir (if we want dirs)
if ((buf.st_mode & _S_IFDIR) == _S_IFDIR)
{
if (m_bAllowDirs)
SetWindowText(firstFile);
SetSel(firstFile.GetLength(), firstFile.GetLength());
}
// verify that we have a file (if we want files)
else if ((buf.st_mode & _S_IFREG) == _S_IFREG)
{
if (m_bAllowFiles)
SetWindowText(firstFile);
SetSel(firstFile.GetLength(), firstFile.GetLength());
}
}
}
//////////////////////////////////////////////////////////////////
// use IShellLink to expand the shortcut
// returns the expanded file, or "" on error
//
// original code was part of CShortcut
// 1996 by Rob Warner
// rhwarner@southeast.net
// http://users.southeast.net/~rhwarner
CString CDropEdit::ExpandShortcut(CString &inFile)
{
CString outFile = "";
// Make sure we have a path
ASSERT(inFile != _T(""));
IShellLink* psl;
HRESULT hres;
LPTSTR lpsz = inFile.GetBuffer(MAX_PATH);
// Create instance for shell link
hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID*) &psl);
if (SUCCEEDED(hres))
{
// Get a pointer to the persist file interface
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf);
if (SUCCEEDED(hres))
{
// Make sure it's ANSI
WORD wsz[MAX_PATH];
::MultiByteToWideChar(CP_ACP, 0, lpsz, -1, wsz, MAX_PATH);
// Load shortcut
hres = ppf->Load(wsz, STGM_READ);
if (SUCCEEDED(hres)) {
WIN32_FIND_DATA wfd;
// find the path from that
HRESULT hres = psl->GetPath(outFile.GetBuffer(MAX_PATH),
MAX_PATH,
&wfd,
SLGP_UNCPRIORITY);
outFile.ReleaseBuffer();
}
ppf->Release();
}
psl->Release();
}
inFile.ReleaseBuffer();
// if this fails, outFile == ""
return outFile;
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Chris Maunder is the co-founder of
CodeProject and
ContentLab.com, and has been a prominent figure in the software development community for nearly 30 years. Hailing from Australia, Chris has a background in Mathematics, Astrophysics, Environmental Engineering and Defence Research. His programming endeavours span everything from FORTRAN on Super Computers, C++/MFC on Windows, through to to high-load .NET web applications and Python AI applications on everything from macOS to a Raspberry Pi. Chris is a full-stack developer who is as comfortable with SQL as he is with CSS.
In the late 1990s, he and his business partner David Cunningham recognized the need for a platform that would facilitate knowledge-sharing among developers, leading to the establishment of CodeProject.com in 1999. Chris's expertise in programming and his passion for fostering a collaborative environment have played a pivotal role in the success of CodeProject.com. Over the years, the website has grown into a vibrant community where programmers worldwide can connect, exchange ideas, and find solutions to coding challenges. Chris is a prolific contributor to the developer community through his articles and tutorials, and his latest passion project,
CodeProject.AI.
In addition to his work with CodeProject.com, Chris co-founded ContentLab and DeveloperMedia, two projects focussed on helping companies make their Software Projects a success. Chris's roles included Product Development, Content Creation, Client Satisfaction and Systems Automation.