📄 mylistctrl.cpp
字号:
if( strchr(lpszDate,' ') != NULL )
sscanf(lpszDate,"%4d-%d-%d %2d:%2d:%2d",
&nYear,&nMon,&nDay,&nHour,&nMin,&nSec);
else
sscanf(lpszDate,"%4d-%d-%d",
&nYear,&nMon,&nDay);
}
}
odtVal = COleDateTime(nYear,nMon,nDay,nHour,nMin,nSec);
return odtVal;
}
//////////////////////////////////////////////////////////////////
int CMyListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CListCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
//
// Register ourselves as a drop target for files
//
DragAcceptFiles(TRUE);
return 0;
}
void CMyListCtrl::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
// Add initialization code
EnableToolTips(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
//
// PUBLIC SetDropMode()
//
// Specify how the control will react to dropped files/folders.
//
// Return value:
// FALSE: the structure was not populated correctly,
// the default settings will be used.
// TRUE: changes to the drop mode accepted
//
//
//
BOOL CMyListCtrl::SetDropMode(const CMyListCtrl::DROPLISTMODE& dropMode)
{
//
// If they want to use a callback, ensure they also
// specified the address of a function...
//
if(dropMode.iMask & DL_USE_CALLBACK && dropMode.pfnCallback == NULL)
{
// Must specify a function if using DL_USE_CALLBACK flag
ASSERT(FALSE);
return FALSE;
}
m_dropMode = dropMode;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// Handle the WM_DROPFILES message
//
void CMyListCtrl::OnDropFiles(HDROP dropInfo)
{
//
// Get the number of pathnames (files or folders) dropped
//
UINT nNumFilesDropped = DragQueryFile(dropInfo, 0xFFFFFFFF, NULL, 0);
//
// Iterate through the pathnames and process each one
//
TCHAR szFilename[MAX_PATH + 1];
CString csPathname;
CString csExpandedFilename;
for (UINT nFile = 0 ; nFile < nNumFilesDropped; nFile++)
{
//
// Get the pathname
//
DragQueryFile(dropInfo, nFile, szFilename, MAX_PATH + 1);
//
// It might be shortcut, so try and expand it
//
csPathname = szFilename;
csExpandedFilename = ExpandShortcut(csPathname);
if(!csExpandedFilename.IsEmpty())
{
csPathname = csExpandedFilename;
}
//
// Now see if its something we allow to be dropped
//
UINT iPathType = 0;
if(ValidatePathname(csPathname, iPathType))
{
//
// By default, we insert the filename into the list
// ourselves, but if our parent wants to do something flashy
// with it (maybe get the filesize and insert that as an extra
// column), they will have installed a callback for each
// droppped item
//
if(m_dropMode.iMask & DL_USE_CALLBACK)
{
//
// Let them know about this list control and the item
// droppped onto it
//
if(m_dropMode.pfnCallback)
m_dropMode.pfnCallback(this, csPathname, iPathType);
}
else
{
InsertPathname(csPathname);
}
}
}
//
// Free the dropped-file info that was allocated by windows
//
DragFinish(dropInfo);
}
//////////////////////////////////////////////////////////////////
//
// ExpandShortcut()
//
// Uses IShellLink to expand a shortcut.
//
// Return value:
// the expanded filename, or "" on error or if filename
// wasn't a shortcut
//
// Adapted from CShortcut, 1996 by Rob Warner
// rhwarner@southeast.net
// http://users.southeast.net/~rhwarner
CString CMyListCtrl::ExpandShortcut(CString& csFilename) const
{
USES_CONVERSION; // For T2COLE() below
CString csExpandedFile;
//
// Make sure we have a path
//
if(csFilename.IsEmpty())
{
ASSERT(FALSE);
return csExpandedFile;
}
//
// Get a pointer to the IShellLink interface
//
HRESULT hr;
IShellLink* pIShellLink;
hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID*) &pIShellLink);
if (SUCCEEDED(hr))
{
//
// Get a pointer to the persist file interface
//
IPersistFile* pIPersistFile;
hr = pIShellLink->QueryInterface(IID_IPersistFile, (LPVOID*) &pIPersistFile);
if (SUCCEEDED(hr))
{
//
// Load the shortcut and resolve the path
//
// IPersistFile::Load() expects a UNICODE string
// so we're using the T2COLE macro for the conversion
//
// For more info, check out MFC Technical note TN059
// (these macros are also supported in ATL and are
// so much better than the ::MultiByteToWideChar() family)
//
hr = pIPersistFile->Load(T2COLE(csFilename), STGM_READ);
if (SUCCEEDED(hr))
{
WIN32_FIND_DATA wfd;
hr = pIShellLink->GetPath(csExpandedFile.GetBuffer(MAX_PATH),
MAX_PATH,
&wfd,
SLGP_UNCPRIORITY);
csExpandedFile.ReleaseBuffer(-1);
}
pIPersistFile->Release();
}
pIShellLink->Release();
}
return csExpandedFile;
}
//////////////////////////////////////////////////////////////////
//
// ValidatePathname()
//
// Checks if a pathname is valid based on these options set:
// Allow directories to be dropped
// Allow files to be dropped
// Only allow files with a certain extension to be dropped
//
// Return value:
// TRUE: the pathname is suitable for selection, or
// FALSE: the pathname failed the checks.
//
// If successful, iPathType specifies the type of path
// validated - either a file or a folder.
BOOL CMyListCtrl::ValidatePathname(const CString& csPathname, UINT& iPathType) const
{
//
// Get some info about that path so we can filter out dirs
// and files if need be
//
BOOL bValid = FALSE;
struct _stat buf;
int result = _tstat( csPathname, &buf );
if( result == 0 )
{
//
// Do we have a directory? (if we want dirs)
//
if ((m_dropMode.iMask & DL_ACCEPT_FOLDERS) &&
((buf.st_mode & _S_IFDIR) == _S_IFDIR))
{
bValid = TRUE;
iPathType = DL_FOLDER_TYPE;
}
else if ((m_dropMode.iMask & DL_ACCEPT_FILES) &&
((buf.st_mode & _S_IFREG) == _S_IFREG))
{
//
// We've got a file and files are allowed.
//
iPathType = DL_FILE_TYPE;
//
// Now if we are filtering out specific types,
// check the file extension.
//
if(m_dropMode.iMask & DL_FILTER_EXTENSION)
{
LPTSTR pszFileExt = PathFindExtension(csPathname);
// if(CString(pszFileExt).CompareNoCase(m_dropMode.csFileExt) == 0)
// Compare extention of file dropped with extentions allowed.
CString lwrFileExt = "*";
lwrFileExt += pszFileExt;
lwrFileExt.MakeLower();
CString dropModeFileExt = m_dropMode.csFileExt;
dropModeFileExt.MakeLower();
if (lwrFileExt == dropModeFileExt)
{
bValid = TRUE;
}
}
else
{
bValid = TRUE;
}
}
}
return bValid;
}
//////////////////////////////////////////////////////////////////
//
// InsertPathname()
//
// This is used to insert a dropped item when a callback function
// hasn't been specified.
//
// It also checks if duplicate files are allowed to be inserted
// and does the necessary.
//
int CMyListCtrl::InsertPathname(const CString& csFilename)
{
if(!(m_dropMode.iMask & DL_ALLOW_DUPLICATES))
{
//
// We don't allow duplicate pathnames, so
// see if this one is already in the list.
//
LVFINDINFO lvInfo;
lvInfo.flags = LVFI_STRING;
lvInfo.psz = csFilename;
if(FindItem(&lvInfo, -1) != -1)
return -1;
}
return InsertItem(0, csFilename);
}
////////////////////////////////////////////
// Tool Tip Text Functions //
// Modified algorithm from codeguru.com //
// by Kory Becker, kory@dummysoftware.com //
////////////////////////////////////////////
int CMyListCtrl::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
int row, col;
RECT cellrect;
row = CellRectFromPoint(point, &cellrect, &col );
if ( row == -1 )
{
return -1;
}
pTI->hwnd = m_hWnd;
pTI->uId = (UINT)((row<<10)+(col&0x3ff)+1);
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = cellrect;
return pTI->uId;
}
// CellRectFromPoint - Determine the row, col and bounding rect of a cell
// Returns - row index on success, -1 otherwise
// point - point to be tested.
// cellrect - to hold the bounding rect
// col - to hold the column index
int CMyListCtrl::CellRectFromPoint(CPoint & point, RECT * cellrect, int * col) const
{
int colnum;
CHeaderCtrl* pHeader;
int nColumnCount;
// If not REPORT style for the list, then use 1 column
// Otherwise, find the column in the report style view.
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
{
// Window is not Report style, so no headers. Deal with it!
nColumnCount = 1;
}
else
{
// Get the number of columns in Report style.
pHeader = (CHeaderCtrl*)GetDlgItem(0);
nColumnCount = pHeader->GetItemCount();
}
// Get the top and bottom row visible
int row = GetTopIndex();
int bottom = row + GetCountPerPage();
if( bottom > GetItemCount() )
bottom = GetItemCount();
// Loop through the visible rows
for( ;row <=bottom;row++)
{
// Get bounding rect of item and check whether point falls in it.
CRect rect, rectLabel;
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
{
// If not Report style, get label / icon boundaries.
GetItemRect( row, &rect, LVIR_ICON );
GetItemRect( row, &rectLabel, LVIR_LABEL );
}
else
{
// If Report style, get bounds of cell.
GetItemRect( row, &rect, LVIR_BOUNDS );
}
if( rect.PtInRect(point) ||
rectLabel.PtInRect(point))
{
bool InLabel = false;
// Store which part user clicked on if in ICON view,
// clicked the Label or the Icon?
if (rect.PtInRect(point))
{
InLabel = false;
}
else if (rectLabel.PtInRect(point))
{
InLabel = true;
}
// Now find the column
for( colnum = 0; colnum < nColumnCount; colnum++ )
{
// Getting column width
int colwidth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -