You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1985 lines
50 KiB
1985 lines
50 KiB
/**************************************************************************
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
PARTICULAR PURPOSE.
|
|
|
|
Copyright 1998 Microsoft Corporation. All Rights Reserved.
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
|
|
File: ShlView.cpp
|
|
|
|
Description: Implements IShellView.
|
|
|
|
**************************************************************************/
|
|
|
|
/**************************************************************************
|
|
#include statements
|
|
**************************************************************************/
|
|
|
|
#include "ShlView.h"
|
|
#include "Guid.h"
|
|
#include "Commands.h"
|
|
#include "resource.h"
|
|
#include "Tools.h"
|
|
#include "ViewList.h"
|
|
#include "DropSrc.h"
|
|
|
|
/**************************************************************************
|
|
global variables
|
|
**************************************************************************/
|
|
|
|
MYTOOLINFO g_Tools[] =
|
|
{
|
|
IDB_VIEW_SMALL_COLOR, IDM_NEW_FOLDER, VIEW_NEWFOLDER, IDS_NEW_FOLDER, TBSTATE_ENABLED, TBSTYLE_BUTTON,
|
|
IDB_STD_SMALL_COLOR, IDM_NEW_ITEM, STD_FILENEW, IDS_NEW_ITEM, TBSTATE_ENABLED, TBSTYLE_BUTTON,
|
|
0, IDM_SEPARATOR, 0, 0, 0, TBSTYLE_SEP,
|
|
IDB_VIEW_SMALL_COLOR, IDM_VIEW_LARGE, VIEW_LARGEICONS, IDS_VIEW_LARGE, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
|
|
IDB_VIEW_SMALL_COLOR, IDM_VIEW_SMALL, VIEW_SMALLICONS, IDS_VIEW_SMALL, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
|
|
IDB_VIEW_SMALL_COLOR, IDM_VIEW_LIST, VIEW_LIST, IDS_VIEW_LIST, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
|
|
IDB_VIEW_SMALL_COLOR, IDM_VIEW_DETAILS, VIEW_DETAILS, IDS_VIEW_DETAILS, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP,
|
|
0, -1, 0, 0, 0, 0,
|
|
};
|
|
|
|
extern CViewList *g_pViewList;
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::CShellView()
|
|
|
|
**************************************************************************/
|
|
|
|
CShellView::CShellView(CShellFolder *pFolder, LPCITEMIDLIST pidl)
|
|
{
|
|
g_DllRefCount++;
|
|
|
|
#ifdef INITCOMMONCONTROLSEX
|
|
|
|
INITCOMMONCONTROLSEX iccex;
|
|
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
|
iccex.dwICC = ICC_LISTVIEW_CLASSES;
|
|
InitCommonControlsEx(&iccex);
|
|
|
|
#else
|
|
|
|
InitCommonControls();
|
|
|
|
#endif //INITCOMMONCONTROLSEX
|
|
|
|
m_hMenu = NULL;
|
|
m_fInEdit = FALSE;
|
|
m_hAccels = LoadAccelerators(g_hInst, MAKEINTRESOURCE(IDR_ACCELS));
|
|
|
|
m_pPidlMgr = new CPidlMgr();
|
|
if(!m_pPidlMgr)
|
|
{
|
|
delete this;
|
|
return;
|
|
}
|
|
|
|
m_psfParent = pFolder;
|
|
if(m_psfParent)
|
|
m_psfParent->AddRef();
|
|
|
|
//get the shell's IMalloc pointer
|
|
//we'll keep this until we get destroyed
|
|
if(FAILED(SHGetMalloc(&m_pMalloc)))
|
|
{
|
|
delete this;
|
|
return;
|
|
}
|
|
|
|
m_pidl = m_pPidlMgr->Copy(pidl);
|
|
|
|
m_uState = SVUIA_DEACTIVATE;
|
|
|
|
if(g_pViewList)
|
|
g_pViewList->AddToList(this);
|
|
|
|
m_ObjRefCount = 1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::~CShellView()
|
|
|
|
**************************************************************************/
|
|
|
|
CShellView::~CShellView()
|
|
{
|
|
if(g_pViewList)
|
|
g_pViewList->RemoveFromList(this);
|
|
|
|
if(m_pidl)
|
|
{
|
|
m_pPidlMgr->Delete(m_pidl);
|
|
m_pidl = NULL;
|
|
}
|
|
|
|
if(m_psfParent)
|
|
m_psfParent->Release();
|
|
|
|
if(m_pMalloc)
|
|
{
|
|
m_pMalloc->Release();
|
|
}
|
|
|
|
if(m_pPidlMgr)
|
|
{
|
|
delete m_pPidlMgr;
|
|
}
|
|
|
|
g_DllRefCount--;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IUnknown Implementation
|
|
//
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::QueryInterface
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::QueryInterface(REFIID riid, LPVOID *ppReturn)
|
|
{
|
|
*ppReturn = NULL;
|
|
|
|
//IUnknown
|
|
if(IsEqualIID(riid, IID_IUnknown))
|
|
{
|
|
*ppReturn = this;
|
|
}
|
|
|
|
//IOleWindow
|
|
else if(IsEqualIID(riid, IID_IOleWindow))
|
|
{
|
|
*ppReturn = (IOleWindow*)this;
|
|
}
|
|
|
|
//IShellView
|
|
else if(IsEqualIID(riid, IID_IShellView))
|
|
{
|
|
*ppReturn = (IShellView*)this;
|
|
}
|
|
|
|
if(*ppReturn)
|
|
{
|
|
(*(LPUNKNOWN*)ppReturn)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::AddRef
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP_(DWORD) CShellView::AddRef()
|
|
{
|
|
return ++m_ObjRefCount;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::Release
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP_(DWORD) CShellView::Release()
|
|
{
|
|
if(--m_ObjRefCount == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return m_ObjRefCount;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IOleWindow Implementation
|
|
//
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::GetWindow()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::GetWindow(HWND *phWnd)
|
|
{
|
|
*phWnd = m_hWnd;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::ContextSensitiveHelp()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::ContextSensitiveHelp(BOOL fEnterMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IShellView Implementation
|
|
//
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::TranslateAccelerator()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::TranslateAccelerator(LPMSG pmsg)
|
|
{
|
|
if(m_fInEdit)
|
|
{
|
|
if((pmsg->message >= WM_KEYFIRST) && (pmsg->message <= WM_KEYLAST))
|
|
{
|
|
TranslateMessage(pmsg);
|
|
DispatchMessage(pmsg);
|
|
return S_OK;
|
|
}
|
|
}
|
|
else if(::TranslateAccelerator(m_hWnd, m_hAccels, pmsg))
|
|
return S_OK;
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::EnableModeless()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::EnableModeless(BOOL fEnable)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnActivate()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnActivate(UINT uState)
|
|
{
|
|
//don't do anything if the state isn't really changing
|
|
if(m_uState == uState)
|
|
return S_OK;
|
|
|
|
OnDeactivate();
|
|
|
|
//only do this if we are active
|
|
if(uState != SVUIA_DEACTIVATE)
|
|
{
|
|
//merge the menus
|
|
m_hMenu = CreateMenu();
|
|
|
|
if(m_hMenu)
|
|
{
|
|
OLEMENUGROUPWIDTHS omw = {0, 0, 0, 0, 0, 0};
|
|
MENUITEMINFO mii;
|
|
|
|
m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
|
|
|
|
//add your top level sub-menu here, if desired
|
|
|
|
//get the view menu so we can merge with it
|
|
ZeroMemory(&mii, sizeof(mii));
|
|
mii.cbSize = sizeof(mii);
|
|
mii.fMask = MIIM_SUBMENU;
|
|
|
|
//merge our items into the File menu
|
|
if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_FILE, FALSE, &mii))
|
|
{
|
|
MergeFileMenu(mii.hSubMenu, (BOOL)(SVUIA_ACTIVATE_FOCUS == uState));
|
|
}
|
|
|
|
//merge our items into the Edit menu
|
|
if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_EDIT, FALSE, &mii))
|
|
{
|
|
MergeEditMenu(mii.hSubMenu, (BOOL)(SVUIA_ACTIVATE_FOCUS == uState));
|
|
}
|
|
|
|
//merge our items into the View menu
|
|
if(GetMenuItemInfo(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
|
|
{
|
|
MergeViewMenu(mii.hSubMenu);
|
|
}
|
|
|
|
//add the items that should only be added if we have the focus
|
|
if(SVUIA_ACTIVATE_FOCUS == uState)
|
|
{
|
|
}
|
|
|
|
m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd);
|
|
}
|
|
}
|
|
|
|
m_uState = uState;
|
|
|
|
UpdateToolbar();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnDeactivate()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::OnDeactivate(VOID)
|
|
{
|
|
if(m_uState != SVUIA_DEACTIVATE)
|
|
{
|
|
if(m_hMenu)
|
|
{
|
|
m_pShellBrowser->SetMenuSB(NULL, NULL, NULL);
|
|
|
|
m_pShellBrowser->RemoveMenusSB(m_hMenu);
|
|
|
|
DestroyMenu(m_hMenu);
|
|
|
|
m_hMenu = NULL;
|
|
}
|
|
|
|
m_uState = SVUIA_DEACTIVATE;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::UIActivate()
|
|
|
|
This function activates the view window. Note that activating it
|
|
will not change the focus, while setting the focus will activate it.
|
|
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::UIActivate(UINT uState)
|
|
{
|
|
//don't do anything if the state isn't really changing
|
|
if(m_uState == uState)
|
|
return S_OK;
|
|
|
|
//OnActivate handles the menu merging and internal state
|
|
OnActivate(uState);
|
|
|
|
//only do this if we are active
|
|
if(uState != SVUIA_DEACTIVATE)
|
|
{
|
|
TCHAR szName[MAX_PATH] = TEXT("");
|
|
LRESULT lResult;
|
|
int nPartArray[1] = {-1};
|
|
|
|
//update the status bar
|
|
//set the number of parts
|
|
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
|
|
|
|
//set the text for the parts
|
|
m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)g_szExtTitle, &lResult);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::MergeFileMenu()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::MergeFileMenu(HMENU hMenu, BOOL fFocus)
|
|
{
|
|
MENUITEMINFO mii;
|
|
UINT uPos = 0;
|
|
|
|
ZeroMemory(&mii, sizeof(mii));
|
|
|
|
//uPos += AddFileMenuItems(hMenu, 0, IDM_SEPARATOR, FALSE);
|
|
uPos += AddFileMenuItems(hMenu, 0, 0, TRUE);
|
|
|
|
//add a separator
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_SEPARATOR;
|
|
mii.wID = IDM_SEPARATOR;
|
|
mii.fState = MFS_ENABLED;
|
|
|
|
//insert this item at the beginning of the menu
|
|
InsertMenuItem(hMenu, uPos, TRUE, &mii);
|
|
uPos++;
|
|
|
|
if(fFocus)
|
|
{
|
|
TCHAR szText[MAX_PATH];
|
|
|
|
//add the Delete item
|
|
LoadString(g_hInst, IDS_DELETE, szText, sizeof(szText));
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_STRING;
|
|
mii.fState = MFS_ENABLED;
|
|
mii.dwTypeData = szText;
|
|
mii.wID = IDM_DELETE;
|
|
InsertMenuItem(hMenu, uPos, TRUE, &mii);
|
|
uPos++;
|
|
|
|
//add the Rename item
|
|
LoadString(g_hInst, IDS_RENAME, szText, sizeof(szText));
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_STRING;
|
|
mii.fState = MFS_ENABLED;
|
|
mii.dwTypeData = szText;
|
|
mii.wID = IDM_RENAME;
|
|
InsertMenuItem(hMenu, uPos, TRUE, &mii);
|
|
uPos++;
|
|
|
|
//add a separator
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_SEPARATOR;
|
|
mii.wID = IDM_SEPARATOR;
|
|
mii.fState = MFS_ENABLED;
|
|
InsertMenuItem(hMenu, uPos, TRUE, &mii);
|
|
uPos++;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::MergeViewMenu()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::MergeViewMenu(HMENU hMenu)
|
|
{
|
|
MENUITEMINFO mii;
|
|
|
|
ZeroMemory(&mii, sizeof(mii));
|
|
mii.cbSize = sizeof(mii);
|
|
|
|
//add a separator at the correct position in the menu
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_SEPARATOR;
|
|
mii.wID = IDM_SEPARATOR;
|
|
mii.fState = MFS_ENABLED;
|
|
InsertMenuItem(hMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
|
|
|
|
AddViewMenuItems(hMenu, 0, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::MergeEditMenu()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::MergeEditMenu(HMENU hMenu, BOOL fFocus)
|
|
{
|
|
if(hMenu)
|
|
{
|
|
MENUITEMINFO mii;
|
|
TCHAR szText[MAX_PATH];
|
|
|
|
ZeroMemory(&mii, sizeof(mii));
|
|
mii.cbSize = sizeof(mii);
|
|
|
|
if(fFocus)
|
|
{
|
|
LoadString(g_hInst, IDS_CUT, szText, sizeof(szText));
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_STRING;
|
|
mii.fState = MFS_ENABLED;
|
|
mii.dwTypeData = szText;
|
|
mii.wID = IDM_CUT;
|
|
InsertMenuItem(hMenu, -1, TRUE, &mii);
|
|
|
|
LoadString(g_hInst, IDS_COPY, szText, sizeof(szText));
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_STRING;
|
|
mii.fState = MFS_ENABLED;
|
|
mii.dwTypeData = szText;
|
|
mii.wID = IDM_COPY;
|
|
InsertMenuItem(hMenu, -1, TRUE, &mii);
|
|
}
|
|
|
|
//add the paste menu items at the correct position in the menu
|
|
LoadString(g_hInst, IDS_PASTE, szText, sizeof(szText));
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
mii.fType = MFT_STRING;
|
|
mii.fState = MFS_ENABLED;
|
|
mii.dwTypeData = szText;
|
|
mii.wID = IDM_PASTE;
|
|
InsertMenuItem(hMenu, -1, TRUE, &mii);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::MergeToolbar()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::MergeToolbar(VOID)
|
|
{
|
|
int i;
|
|
TBADDBITMAP tbab;
|
|
LRESULT lStdOffset;
|
|
LRESULT lViewOffset;
|
|
|
|
m_pShellBrowser->SetToolbarItems(NULL, 0, FCT_MERGE);
|
|
|
|
tbab.hInst = HINST_COMMCTRL;
|
|
tbab.nID = (int)IDB_STD_SMALL_COLOR;
|
|
m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 0, (LPARAM)&tbab, &lStdOffset);
|
|
|
|
tbab.hInst = HINST_COMMCTRL;
|
|
tbab.nID = (int)IDB_VIEW_SMALL_COLOR;
|
|
m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 0, (LPARAM)&tbab, &lViewOffset);
|
|
|
|
//get the number of items in tool array
|
|
for(i = 0; -1 != g_Tools[i].idCommand; i++)
|
|
{
|
|
}
|
|
|
|
LPTBBUTTON ptbb = (LPTBBUTTON)GlobalAlloc(GPTR, sizeof(TBBUTTON) * i);
|
|
|
|
if(ptbb)
|
|
{
|
|
for(i = 0; -1 != g_Tools[i].idCommand; i++)
|
|
{
|
|
(ptbb + i)->iBitmap = 0;
|
|
switch(g_Tools[i].uImageSet)
|
|
{
|
|
case IDB_STD_SMALL_COLOR:
|
|
(ptbb + i)->iBitmap = lStdOffset + g_Tools[i].iImage;
|
|
break;
|
|
|
|
case IDB_VIEW_SMALL_COLOR:
|
|
(ptbb + i)->iBitmap = lViewOffset + g_Tools[i].iImage;
|
|
break;
|
|
}
|
|
|
|
(ptbb + i)->idCommand = g_Tools[i].idCommand;
|
|
(ptbb + i)->fsState = g_Tools[i].bState;
|
|
(ptbb + i)->fsStyle = g_Tools[i].bStyle;
|
|
(ptbb + i)->dwData = 0;
|
|
(ptbb + i)->iString = 0;
|
|
}
|
|
|
|
m_pShellBrowser->SetToolbarItems(ptbb, i, FCT_MERGE);
|
|
|
|
GlobalFree((HGLOBAL)ptbb);
|
|
}
|
|
|
|
UpdateToolbar();
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::Refresh()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::Refresh(VOID)
|
|
{
|
|
//empty the list
|
|
ListView_DeleteAllItems(m_hwndList);
|
|
|
|
//refill the list
|
|
FillList();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::CreateViewWindow()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::CreateViewWindow( LPSHELLVIEW pPrevView,
|
|
LPCFOLDERSETTINGS lpfs,
|
|
LPSHELLBROWSER psb,
|
|
LPRECT prcView,
|
|
HWND *phWnd)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
*phWnd = NULL;
|
|
|
|
//if our window class has not been registered, then do so
|
|
if(!GetClassInfo(g_hInst, NS_CLASS_NAME, &wc))
|
|
{
|
|
ZeroMemory(&wc, sizeof(wc));
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = WndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = g_hInst;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = NS_CLASS_NAME;
|
|
|
|
if(!RegisterClass(&wc))
|
|
return E_FAIL;
|
|
}
|
|
|
|
//set up the member variables
|
|
m_pShellBrowser = psb;
|
|
m_FolderSettings = *lpfs;
|
|
|
|
//get our parent window
|
|
m_pShellBrowser->GetWindow(&m_hwndParent);
|
|
|
|
*phWnd = CreateWindowEx( 0,
|
|
NS_CLASS_NAME,
|
|
NULL,
|
|
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
|
|
prcView->left,
|
|
prcView->top,
|
|
prcView->right - prcView->left,
|
|
prcView->bottom - prcView->top,
|
|
m_hwndParent,
|
|
NULL,
|
|
g_hInst,
|
|
(LPVOID)this);
|
|
|
|
if(!*phWnd)
|
|
return E_FAIL;
|
|
|
|
MergeToolbar();
|
|
|
|
m_pShellBrowser->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::DestroyViewWindow()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::DestroyViewWindow(VOID)
|
|
{
|
|
//Make absolutely sure all our UI is cleaned up.
|
|
UIActivate(SVUIA_DEACTIVATE);
|
|
|
|
if(m_hMenu)
|
|
DestroyMenu(m_hMenu);
|
|
|
|
DestroyWindow(m_hWnd);
|
|
|
|
//release the shell browser object
|
|
m_pShellBrowser->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::GetCurrentInfo()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
|
|
{
|
|
*lpfs = m_FolderSettings;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::AddPropertySheetPages()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::AddPropertySheetPages( DWORD dwReserved,
|
|
LPFNADDPROPSHEETPAGE lpfn,
|
|
LPARAM lParam)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::SaveViewState()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::SaveViewState(VOID)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::SelectItem()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::GetItemObject()
|
|
|
|
**************************************************************************/
|
|
|
|
STDMETHODIMP CShellView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
|
|
{
|
|
*ppvOut = NULL;
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::WndProc()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CALLBACK CShellView::WndProc( HWND hWnd,
|
|
UINT uMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
CShellView *pThis = (CShellView*)GetWindowLong(hWnd, VIEW_POINTER_OFFSET);
|
|
|
|
switch (uMessage)
|
|
{
|
|
case WM_NCCREATE:
|
|
{
|
|
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
|
|
pThis = (CShellView*)(lpcs->lpCreateParams);
|
|
SetWindowLong(hWnd, VIEW_POINTER_OFFSET, (LONG)pThis);
|
|
|
|
//set the window handle
|
|
pThis->m_hWnd = hWnd;
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
return pThis->OnSize(LOWORD(lParam), HIWORD(lParam));
|
|
|
|
case WM_CREATE:
|
|
return pThis->OnCreate();
|
|
|
|
case WM_DESTROY:
|
|
return pThis->OnDestroy();
|
|
|
|
case WM_SETFOCUS:
|
|
return pThis->OnSetFocus();
|
|
|
|
case WM_KILLFOCUS:
|
|
return pThis->OnKillFocus();
|
|
|
|
case WM_ACTIVATE:
|
|
return pThis->OnActivate(SVUIA_ACTIVATE_FOCUS);
|
|
|
|
case WM_COMMAND:
|
|
return pThis->OnCommand( GET_WM_COMMAND_ID(wParam, lParam),
|
|
GET_WM_COMMAND_CMD(wParam, lParam),
|
|
GET_WM_COMMAND_HWND(wParam, lParam));
|
|
|
|
case WM_INITMENUPOPUP:
|
|
return pThis->UpdateMenu((HMENU)wParam);
|
|
|
|
case WM_NOTIFY:
|
|
return pThis->OnNotify((UINT)wParam, (LPNMHDR)lParam);
|
|
|
|
case WM_SETTINGCHANGE:
|
|
return pThis->OnSettingChange((LPCTSTR)lParam);
|
|
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
pThis->DoContextMenu(LOWORD(lParam), HIWORD(lParam), FALSE, (UINT)-1);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return DefWindowProc(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnSetFocus()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnSetFocus(VOID)
|
|
{
|
|
/*
|
|
Tell the browser one of our windows has received the focus. This should always
|
|
be done before merging menus (OnActivate merges the menus) if one of our
|
|
windows has the focus.
|
|
*/
|
|
m_pShellBrowser->OnViewWindowActive(this);
|
|
|
|
OnActivate(SVUIA_ACTIVATE_FOCUS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnKillFocus()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnKillFocus(VOID)
|
|
{
|
|
OnActivate(SVUIA_ACTIVATE_NOFOCUS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnCommand()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnCommand(DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
|
|
{
|
|
//ignore command messages while in edit mode
|
|
if(m_fInEdit)
|
|
return 0;
|
|
|
|
DoContextMenu(0, 0, FALSE, dwCmdID);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::UpdateMenu()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::UpdateMenu(HMENU hMenu)
|
|
{
|
|
UINT uCommand;
|
|
|
|
//enable/disable your menu items here
|
|
OpenClipboard(NULL);
|
|
HGLOBAL hClip = GetClipboardData(RegisterClipboardFormat(CFSTR_SAMPVIEWDATA));
|
|
CloseClipboard();
|
|
|
|
EnableMenuItem(hMenu, IDM_PASTE, MF_BYCOMMAND | (hClip ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
|
|
|
|
uCommand = ListView_GetSelectedCount(m_hwndList);
|
|
EnableMenuItem(hMenu, IDM_CUT, MF_BYCOMMAND | (uCommand ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
|
|
EnableMenuItem(hMenu, IDM_COPY, MF_BYCOMMAND | (uCommand ? MF_ENABLED : MF_DISABLED | MF_GRAYED));
|
|
|
|
switch(m_FolderSettings.ViewMode)
|
|
{
|
|
case FVM_ICON:
|
|
uCommand = IDM_VIEW_LARGE;
|
|
break;
|
|
|
|
case FVM_SMALLICON:
|
|
uCommand = IDM_VIEW_SMALL;
|
|
break;
|
|
|
|
case FVM_LIST:
|
|
uCommand = IDM_VIEW_LIST;
|
|
break;
|
|
|
|
case FVM_DETAILS:
|
|
default:
|
|
uCommand = IDM_VIEW_DETAILS;
|
|
break;
|
|
}
|
|
|
|
CheckMenuRadioItem(hMenu, IDM_VIEW_LARGE, IDM_VIEW_DETAILS, uCommand, MF_BYCOMMAND);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::UpdateToolbar()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::UpdateToolbar(VOID)
|
|
{
|
|
LRESULT lResult;
|
|
UINT uCommand;
|
|
|
|
//enable/disable/check the toolbar items here
|
|
switch(m_FolderSettings.ViewMode)
|
|
{
|
|
case FVM_ICON:
|
|
uCommand = IDM_VIEW_LARGE;
|
|
break;
|
|
|
|
case FVM_SMALLICON:
|
|
uCommand = IDM_VIEW_SMALL;
|
|
break;
|
|
|
|
case FVM_LIST:
|
|
uCommand = IDM_VIEW_LIST;
|
|
break;
|
|
|
|
case FVM_DETAILS:
|
|
default:
|
|
uCommand = IDM_VIEW_DETAILS;
|
|
break;
|
|
}
|
|
|
|
m_pShellBrowser->SendControlMsg( FCW_TOOLBAR,
|
|
TB_CHECKBUTTON,
|
|
uCommand,
|
|
MAKELPARAM(TRUE, 0),
|
|
&lResult);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnNotify()
|
|
|
|
**************************************************************************/
|
|
|
|
#define MENU_MAX 100
|
|
|
|
LRESULT CShellView::OnNotify(UINT CtlID, LPNMHDR lpnmh)
|
|
{
|
|
switch(lpnmh->code)
|
|
{
|
|
/*
|
|
The original shell on NT will always send TTN_NEEDTEXTW, so handle the
|
|
cases separately.
|
|
*/
|
|
case TTN_NEEDTEXTA:
|
|
{
|
|
LPNMTTDISPINFOA pttt = (LPNMTTDISPINFOA)lpnmh;
|
|
int i;
|
|
|
|
for(i = 0; -1 != g_Tools[i].idCommand; i++)
|
|
{
|
|
if(g_Tools[i].idCommand == pttt->hdr.idFrom)
|
|
{
|
|
LoadStringA(g_hInst, g_Tools[i].idString, pttt->szText, sizeof(pttt->szText));
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TTN_NEEDTEXTW:
|
|
{
|
|
LPNMTTDISPINFOW pttt = (LPNMTTDISPINFOW)lpnmh;
|
|
int i;
|
|
|
|
for(i = 0; -1 != g_Tools[i].idCommand; i++)
|
|
{
|
|
if(g_Tools[i].idCommand == pttt->hdr.idFrom)
|
|
{
|
|
LoadStringW(g_hInst, g_Tools[i].idString, pttt->szText, sizeof(pttt->szText));
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_SETFOCUS:
|
|
OnSetFocus();
|
|
break;
|
|
|
|
case NM_KILLFOCUS:
|
|
OnDeactivate();
|
|
break;
|
|
|
|
case HDN_ENDTRACK:
|
|
{
|
|
g_nColumn = ListView_GetColumnWidth(m_hwndList, 0);
|
|
ListView_SetColumnWidth(m_hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
|
|
}
|
|
return 0;
|
|
|
|
case LVN_DELETEITEM:
|
|
{
|
|
NM_LISTVIEW *lpnmlv = (NM_LISTVIEW*)lpnmh;
|
|
|
|
//delete the pidl because we made a copy of it
|
|
m_pPidlMgr->Delete((LPITEMIDLIST)lpnmlv->lParam);
|
|
}
|
|
break;
|
|
|
|
#ifdef LVN_ITEMACTIVATE
|
|
|
|
case LVN_ITEMACTIVATE:
|
|
|
|
#else //LVN_ITEMACTIVATE
|
|
|
|
case NM_DBLCLK:
|
|
case NM_RETURN:
|
|
|
|
#endif //LVN_ITEMACTIVATE
|
|
|
|
DoContextMenu(0, 0, TRUE, (DWORD)-1);
|
|
return 0;
|
|
|
|
case LVN_GETDISPINFO:
|
|
{
|
|
NMLVDISPINFO *lpdi = (NMLVDISPINFO*)lpnmh;
|
|
LPITEMIDLIST pidl = (LPITEMIDLIST)lpdi->item.lParam;
|
|
|
|
//is the sub-item information being requested?
|
|
if(lpdi->item.iSubItem)
|
|
{
|
|
//is the text being requested?
|
|
if(lpdi->item.mask & LVIF_TEXT)
|
|
{
|
|
//is this a folder or a value?
|
|
if(m_pPidlMgr->IsFolder(pidl))
|
|
{
|
|
LoadString(g_hInst, IDS_FOLDER_DATA, lpdi->item.pszText, lpdi->item.cchTextMax);
|
|
}
|
|
//its an item
|
|
else
|
|
{
|
|
m_pPidlMgr->GetData(pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
|
|
}
|
|
}
|
|
}
|
|
//the item text is being requested
|
|
else
|
|
{
|
|
//is the text being requested?
|
|
if(lpdi->item.mask & LVIF_TEXT)
|
|
{
|
|
STRRET str;
|
|
|
|
if(SUCCEEDED(m_psfParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &str)))
|
|
{
|
|
GetTextFromSTRRET(m_pMalloc, &str, pidl, lpdi->item.pszText, lpdi->item.cchTextMax);
|
|
}
|
|
}
|
|
|
|
//is the image being requested?
|
|
if(lpdi->item.mask & LVIF_IMAGE)
|
|
{
|
|
IExtractIcon *pei;
|
|
|
|
if(SUCCEEDED(m_psfParent->GetUIObjectOf(m_hWnd, 1, (LPCITEMIDLIST*)&pidl, IID_IExtractIcon, NULL, (LPVOID*)&pei)))
|
|
{
|
|
UINT uFlags;
|
|
|
|
//GetIconLocation will give us the index into our image list
|
|
pei->GetIconLocation(GIL_FORSHELL, NULL, 0, &lpdi->item.iImage, &uFlags);
|
|
|
|
pei->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case LVN_BEGINLABELEDIT:
|
|
{
|
|
NMLVDISPINFO *lpdi = (NMLVDISPINFO*)lpnmh;
|
|
LPITEMIDLIST pidl = (LPITEMIDLIST)lpdi->item.lParam;
|
|
DWORD dwAttr = SFGAO_CANRENAME;
|
|
|
|
m_psfParent->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &dwAttr);
|
|
if(SFGAO_CANRENAME & dwAttr)
|
|
{
|
|
m_fInEdit = TRUE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case LVN_ENDLABELEDIT:
|
|
{
|
|
LRESULT lResult = 0;
|
|
NMLVDISPINFO *pdi = (NMLVDISPINFO*)lpnmh;
|
|
|
|
if(pdi->item.pszText)
|
|
{
|
|
//the user wants to keep the change
|
|
LVITEM lvItem;
|
|
LPITEMIDLIST pidl;
|
|
WCHAR wszNewName[MAX_PATH];
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = pdi->item.iItem;
|
|
ListView_GetItem(m_hwndList, &lvItem);
|
|
|
|
LocalToWideChar(wszNewName, pdi->item.pszText, MAX_PATH);
|
|
|
|
/*
|
|
This will cause this class' RenameItem function to be called. This
|
|
can cause problems, so the m_fInEdit flag will prevent RenameItem
|
|
from being called on this object. SetNameOf will also free the old
|
|
PIDL, so we don't have to do it again.
|
|
*/
|
|
HRESULT hr = m_psfParent->SetNameOf(NULL, (LPITEMIDLIST)lvItem.lParam, wszNewName, 0, &pidl);
|
|
|
|
if(SUCCEEDED(hr) && pidl)
|
|
{
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.lParam = (LPARAM)pidl;
|
|
ListView_SetItem(m_hwndList, &lvItem);
|
|
lResult = TRUE;
|
|
}
|
|
}
|
|
|
|
m_fInEdit = FALSE;
|
|
return lResult;
|
|
}
|
|
|
|
case LVN_BEGINDRAG:
|
|
{
|
|
HRESULT hr;
|
|
IDataObject *pDataObject = NULL;
|
|
UINT uItemCount;
|
|
LPITEMIDLIST *aPidls;
|
|
|
|
//get the number of selected items
|
|
uItemCount = ListView_GetSelectedCount(m_hwndList);
|
|
if(!uItemCount)
|
|
return 0;
|
|
|
|
aPidls = (LPITEMIDLIST*)m_pMalloc->Alloc(uItemCount * sizeof(LPITEMIDLIST));
|
|
|
|
if(aPidls)
|
|
{
|
|
int i;
|
|
UINT x;
|
|
|
|
for(i = 0, x = 0; x < uItemCount && i < ListView_GetItemCount(m_hwndList); i++)
|
|
{
|
|
if(ListView_GetItemState(m_hwndList, i, LVIS_SELECTED))
|
|
{
|
|
LVITEM lvItem;
|
|
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = i;
|
|
|
|
ListView_GetItem(m_hwndList, &lvItem);
|
|
aPidls[x] = (LPITEMIDLIST)lvItem.lParam;
|
|
x++;
|
|
}
|
|
}
|
|
|
|
hr = m_psfParent->GetUIObjectOf( m_hWnd,
|
|
uItemCount,
|
|
(LPCITEMIDLIST*)aPidls,
|
|
IID_IDataObject,
|
|
NULL,
|
|
(LPVOID*)&pDataObject);
|
|
|
|
if(SUCCEEDED(hr) && pDataObject)
|
|
{
|
|
IDropSource *pDropSource = new CDropSource;
|
|
DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
|
|
DWORD dwAttributes = SFGAO_CANLINK;
|
|
|
|
hr = m_psfParent->GetAttributesOf( uItemCount,
|
|
(LPCITEMIDLIST*)aPidls,
|
|
&dwAttributes);
|
|
|
|
if(SUCCEEDED(hr) && (dwAttributes & SFGAO_CANLINK))
|
|
{
|
|
dwEffect |= DROPEFFECT_LINK;
|
|
}
|
|
|
|
DoDragDrop( pDataObject,
|
|
pDropSource,
|
|
dwEffect,
|
|
&dwEffect);
|
|
|
|
pDataObject->Release();
|
|
pDropSource->Release();
|
|
}
|
|
|
|
m_pMalloc->Free(aPidls);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
{
|
|
UpdateToolbar();
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnSize()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnSize(WORD wWidth, WORD wHeight)
|
|
{
|
|
//resize the ListView to fit our window
|
|
if(m_hwndList)
|
|
{
|
|
MoveWindow(m_hwndList, 0, 0, wWidth, wHeight, TRUE);
|
|
|
|
ListView_SetColumnWidth(m_hwndList, 0, g_nColumn);
|
|
ListView_SetColumnWidth(m_hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnCreate()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnCreate(VOID)
|
|
{
|
|
//create the ListView
|
|
if(CreateList())
|
|
{
|
|
if(InitList())
|
|
{
|
|
FillList();
|
|
}
|
|
}
|
|
|
|
HRESULT hr;
|
|
IDropTarget *pdt;
|
|
|
|
//get the IDropTarget for this folder
|
|
hr = m_psfParent->CreateViewObject( m_hWnd,
|
|
IID_IDropTarget,
|
|
(LPVOID*)&pdt);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//register the window as a drop target
|
|
RegisterDragDrop(m_hWnd, pdt);
|
|
|
|
pdt->Release();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnDestroy()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnDestroy(VOID)
|
|
{
|
|
//unregister the window as a drop target
|
|
RevokeDragDrop(m_hWnd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::CreateList()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CShellView::CreateList(VOID)
|
|
{
|
|
DWORD dwStyle;
|
|
|
|
dwStyle = WS_TABSTOP |
|
|
WS_VISIBLE |
|
|
WS_CHILD |
|
|
WS_BORDER |
|
|
LVS_NOSORTHEADER |
|
|
LVS_SHAREIMAGELISTS |
|
|
LVS_EDITLABELS;
|
|
|
|
switch(m_FolderSettings.ViewMode)
|
|
{
|
|
default:
|
|
case FVM_ICON:
|
|
dwStyle |= LVS_ICON;
|
|
break;
|
|
|
|
case FVM_SMALLICON:
|
|
dwStyle |= LVS_SMALLICON;
|
|
break;
|
|
|
|
case FVM_LIST:
|
|
dwStyle |= LVS_LIST;
|
|
break;
|
|
|
|
case FVM_DETAILS:
|
|
dwStyle |= LVS_REPORT;
|
|
break;
|
|
|
|
}
|
|
|
|
if(FWF_AUTOARRANGE & m_FolderSettings.fFlags)
|
|
dwStyle |= LVS_AUTOARRANGE;
|
|
|
|
m_hwndList = CreateWindowEx( WS_EX_CLIENTEDGE,
|
|
WC_LISTVIEW,
|
|
NULL,
|
|
dwStyle,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
m_hWnd,
|
|
(HMENU)ID_LISTVIEW,
|
|
g_hInst,
|
|
NULL);
|
|
|
|
if(!m_hwndList)
|
|
return FALSE;
|
|
|
|
GetShellSettings();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::InitList()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CShellView::InitList(VOID)
|
|
{
|
|
LVCOLUMN lvColumn;
|
|
TCHAR szString[MAX_PATH];
|
|
|
|
//empty the list
|
|
ListView_DeleteAllItems(m_hwndList);
|
|
|
|
//initialize the columns
|
|
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvColumn.fmt = LVCFMT_LEFT;
|
|
lvColumn.pszText = szString;
|
|
|
|
lvColumn.cx = g_nColumn;
|
|
LoadString(g_hInst, IDS_COLUMN1, szString, sizeof(szString));
|
|
ListView_InsertColumn(m_hwndList, 0, &lvColumn);
|
|
|
|
lvColumn.cx = g_nColumn;
|
|
LoadString(g_hInst, IDS_COLUMN2, szString, sizeof(szString));
|
|
ListView_InsertColumn(m_hwndList, 1, &lvColumn);
|
|
|
|
ListView_SetImageList(m_hwndList, g_himlLarge, LVSIL_NORMAL);
|
|
ListView_SetImageList(m_hwndList, g_himlSmall, LVSIL_SMALL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::FillList()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::FillList(VOID)
|
|
{
|
|
LPENUMIDLIST pEnumIDList;
|
|
|
|
if(SUCCEEDED(m_psfParent->EnumObjects(m_hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList)))
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
DWORD dwFetched;
|
|
|
|
//turn the listview's redrawing off
|
|
SendMessage(m_hwndList, WM_SETREDRAW, FALSE, 0);
|
|
|
|
while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
|
|
{
|
|
AddItem(pidl);
|
|
/*
|
|
*/
|
|
}
|
|
|
|
//sort the items
|
|
ListView_SortItems(m_hwndList, CompareItems, (LPARAM)m_psfParent);
|
|
|
|
//turn the listview's redrawing back on and force it to draw
|
|
SendMessage(m_hwndList, WM_SETREDRAW, TRUE, 0);
|
|
InvalidateRect(m_hwndList, NULL, TRUE);
|
|
UpdateWindow(m_hwndList);
|
|
|
|
pEnumIDList->Release();
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::GetShellSettings()
|
|
|
|
**************************************************************************/
|
|
|
|
#if (_WIN32_IE >= 0x0400)
|
|
typedef VOID (WINAPI *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
|
|
|
|
VOID CShellView::GetShellSettings(VOID)
|
|
{
|
|
SHELLFLAGSTATE sfs;
|
|
HINSTANCE hinstShell32;
|
|
|
|
/*
|
|
Since SHGetSettings is not implemented in all versions of the shell, get the
|
|
function address manually at run time. This allows the extension to run on all
|
|
platforms.
|
|
*/
|
|
|
|
ZeroMemory(&sfs, sizeof(sfs));
|
|
|
|
/*
|
|
The default, in case any of the following steps fails, is classic Windows 95
|
|
style.
|
|
*/
|
|
sfs.fWin95Classic = TRUE;
|
|
|
|
hinstShell32 = LoadLibrary(TEXT("shell32.dll"));
|
|
if(hinstShell32)
|
|
{
|
|
PFNSHGETSETTINGSPROC pfnSHGetSettings;
|
|
|
|
pfnSHGetSettings = (PFNSHGETSETTINGSPROC)GetProcAddress(hinstShell32, "SHGetSettings");
|
|
if(pfnSHGetSettings)
|
|
{
|
|
(*pfnSHGetSettings)(&sfs, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC);
|
|
}
|
|
FreeLibrary(hinstShell32);
|
|
}
|
|
|
|
DWORD dwExStyles = 0;
|
|
|
|
if(!sfs.fWin95Classic && !sfs.fDoubleClickInWebView)
|
|
{
|
|
dwExStyles |= LVS_EX_ONECLICKACTIVATE |
|
|
LVS_EX_TRACKSELECT |
|
|
LVS_EX_UNDERLINEHOT;
|
|
}
|
|
|
|
ListView_SetExtendedListViewStyle(m_hwndList, dwExStyles);
|
|
}
|
|
#else
|
|
VOID CShellView::GetShellSettings(VOID)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnSettingChange()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnSettingChange(LPCTSTR lpszSection)
|
|
{
|
|
if(0 == lstrcmpi(lpszSection, TEXT("ShellState")))
|
|
{
|
|
GetShellSettings();
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::DoContextMenu()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::DoContextMenu(WORD x, WORD y, BOOL fDefault, DWORD dwCmdIn)
|
|
{
|
|
UINT uSelected = 0;
|
|
LPITEMIDLIST *aSelectedItems = NULL;
|
|
LPCONTEXTMENU pContextMenu = NULL;
|
|
|
|
if(m_uState != SVUIA_ACTIVATE_NOFOCUS)
|
|
{
|
|
uSelected = ListView_GetSelectedCount(m_hwndList);
|
|
}
|
|
|
|
if(uSelected)
|
|
{
|
|
aSelectedItems = (LPITEMIDLIST*)m_pMalloc->Alloc((uSelected + 1) * sizeof(LPITEMIDLIST));
|
|
|
|
if(aSelectedItems)
|
|
{
|
|
UINT i;
|
|
LVITEM lvItem;
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_STATE | LVIF_PARAM;
|
|
lvItem.stateMask = LVIS_SELECTED;
|
|
lvItem.iItem = 0;
|
|
|
|
i = 0;
|
|
|
|
while(ListView_GetItem(m_hwndList, &lvItem) && (i < uSelected))
|
|
{
|
|
if(lvItem.state & LVIS_SELECTED)
|
|
{
|
|
aSelectedItems[i] = (LPITEMIDLIST)lvItem.lParam;
|
|
i++;
|
|
}
|
|
lvItem.iItem++;
|
|
}
|
|
m_psfParent->GetUIObjectOf( m_hwndParent,
|
|
uSelected,
|
|
(LPCITEMIDLIST*)aSelectedItems,
|
|
IID_IContextMenu,
|
|
NULL,
|
|
(LPVOID*)&pContextMenu);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_psfParent->CreateViewObject( m_hwndParent,
|
|
IID_IContextMenu,
|
|
(LPVOID*)&pContextMenu);
|
|
}
|
|
|
|
if(pContextMenu)
|
|
{
|
|
HMENU hMenu = CreatePopupMenu();
|
|
|
|
/*
|
|
See if we are in Explore or Open mode. If the browser's tree is present,
|
|
then we are in Explore mode.
|
|
*/
|
|
BOOL fExplore = FALSE;
|
|
HWND hwndTree = NULL;
|
|
if(SUCCEEDED(m_pShellBrowser->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
|
|
{
|
|
fExplore = TRUE;
|
|
}
|
|
|
|
if(hMenu && SUCCEEDED(pContextMenu->QueryContextMenu( hMenu,
|
|
0,
|
|
0,
|
|
MENU_MAX,
|
|
CMF_NORMAL |
|
|
(fExplore ? CMF_EXPLORE : 0) |
|
|
((uSelected > 1) ? MYCMF_MULTISELECT: 0))))
|
|
{
|
|
UINT uCommand;
|
|
|
|
if(fDefault)
|
|
{
|
|
MENUITEMINFO mii;
|
|
int nMenuIndex;
|
|
|
|
uCommand = 0;
|
|
|
|
ZeroMemory(&mii, sizeof(mii));
|
|
mii.cbSize = sizeof(mii);
|
|
mii.fMask = MIIM_STATE | MIIM_ID;
|
|
|
|
nMenuIndex = 0;
|
|
|
|
//find the default item in the menu
|
|
while(GetMenuItemInfo(hMenu, nMenuIndex, TRUE, &mii))
|
|
{
|
|
if(mii.fState & MFS_DEFAULT)
|
|
{
|
|
uCommand = mii.wID;
|
|
break;
|
|
}
|
|
|
|
nMenuIndex++;
|
|
}
|
|
}
|
|
else if(-1 != dwCmdIn)
|
|
{
|
|
//this command will get sent directly without bringing up the menu
|
|
uCommand = dwCmdIn;
|
|
}
|
|
else
|
|
{
|
|
uCommand = TrackPopupMenu( hMenu,
|
|
TPM_LEFTALIGN | TPM_RETURNCMD,
|
|
x,
|
|
y,
|
|
0,
|
|
m_hWnd,
|
|
NULL);
|
|
}
|
|
|
|
if(uCommand > 0)
|
|
{
|
|
//some commands need to be handled by the view itself
|
|
switch(uCommand)
|
|
{
|
|
case IDM_VIEW_LARGE:
|
|
OnViewLarge();
|
|
break;
|
|
|
|
case IDM_VIEW_SMALL:
|
|
OnViewSmall();
|
|
break;
|
|
|
|
case IDM_VIEW_LIST:
|
|
OnViewList();
|
|
break;
|
|
|
|
case IDM_VIEW_DETAILS:
|
|
OnViewDetails();
|
|
break;
|
|
|
|
default:
|
|
{
|
|
CMINVOKECOMMANDINFO cmi;
|
|
|
|
ZeroMemory(&cmi, sizeof(cmi));
|
|
cmi.cbSize = sizeof(cmi);
|
|
cmi.hwnd = m_hWnd;
|
|
cmi.lpVerb = (LPCSTR)MAKEINTRESOURCE(uCommand);
|
|
|
|
pContextMenu->InvokeCommand(&cmi);
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
DestroyMenu(hMenu);
|
|
}
|
|
|
|
pContextMenu->Release();
|
|
}
|
|
|
|
if(aSelectedItems)
|
|
m_pMalloc->Free(aSelectedItems);
|
|
|
|
UpdateToolbar();
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::AddItem()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CShellView::AddItem(LPCITEMIDLIST pidl)
|
|
{
|
|
LVITEM lvItem;
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
|
|
//set the mask
|
|
lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
|
|
|
//add the item to the end of the list
|
|
lvItem.iItem = ListView_GetItemCount(m_hwndList);
|
|
|
|
//set the item's data
|
|
lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidl);
|
|
|
|
//get text on a callback basis
|
|
lvItem.pszText = LPSTR_TEXTCALLBACK;
|
|
|
|
//get the image on a callback basis
|
|
lvItem.iImage = I_IMAGECALLBACK;
|
|
|
|
//add the item
|
|
if(-1 == ListView_InsertItem(m_hwndList, &lvItem))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::DeleteItem()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CShellView::DeleteItem(LPCITEMIDLIST pidl)
|
|
{
|
|
//delete the item from the list
|
|
int nIndex = FindItemPidl(pidl);
|
|
|
|
if(-1 != nIndex)
|
|
{
|
|
return ListView_DeleteItem(m_hwndList, nIndex);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::RenameItem()
|
|
|
|
**************************************************************************/
|
|
|
|
BOOL CShellView::RenameItem(LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew)
|
|
{
|
|
//don't allow this to be called if this object is the being edited
|
|
|
|
if(m_fInEdit)
|
|
return TRUE;
|
|
|
|
//find the item in the list
|
|
int nIndex = FindItemPidl(pidlOld);
|
|
|
|
if(-1 != nIndex)
|
|
{
|
|
BOOL fReturn;
|
|
LVITEM lvItem;
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = nIndex;
|
|
ListView_GetItem(m_hwndList, &lvItem);
|
|
|
|
m_pPidlMgr->Delete((LPITEMIDLIST)lvItem.lParam);
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = nIndex;
|
|
lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidlNew);
|
|
fReturn = ListView_SetItem(m_hwndList, &lvItem);
|
|
ListView_Update(m_hwndList, nIndex);
|
|
return fReturn;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::GetPidl()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CShellView::GetPidl()
|
|
{
|
|
return m_psfParent->CreateFQPidl(NULL);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::GetFQPidl()
|
|
|
|
**************************************************************************/
|
|
|
|
LPITEMIDLIST CShellView::GetFQPidl()
|
|
{
|
|
return m_psfParent->CreateFQPidl(NULL);
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::FindItemPidl()
|
|
|
|
**************************************************************************/
|
|
|
|
int CShellView::FindItemPidl(LPCITEMIDLIST pidl)
|
|
{
|
|
LVITEM lvItem;
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_PARAM;
|
|
|
|
for(lvItem.iItem = 0; ListView_GetItem(m_hwndList, &lvItem); lvItem.iItem++)
|
|
{
|
|
LPITEMIDLIST pidlFound = (LPITEMIDLIST)lvItem.lParam;
|
|
HRESULT hr = m_psfParent->CompareIDs(0, pidl, pidlFound);
|
|
if(SUCCEEDED(hr) && 0 == HRESULT_CODE(hr))
|
|
{
|
|
//we found the item
|
|
return lvItem.iItem;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::MarkItemsAsCut()
|
|
|
|
Marks the items as cut.
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::MarkItemsAsCut(LPCITEMIDLIST *aPidls, UINT uItemCount)
|
|
{
|
|
UINT i;
|
|
|
|
for(i = 0; i < uItemCount; i++)
|
|
{
|
|
LPITEMIDLIST pidlTemp = m_pPidlMgr->GetLastItem(aPidls[i]);
|
|
int nIndex = FindItemPidl(pidlTemp);
|
|
|
|
if(nIndex != -1)
|
|
{
|
|
ListView_SetItemState(m_hwndList, nIndex, LVIS_CUT, LVIS_CUT);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::EditItem()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::EditItem(LPCITEMIDLIST pidl)
|
|
{
|
|
int i;
|
|
|
|
i = FindItemPidl(pidl);
|
|
|
|
if(-1 != i)
|
|
{
|
|
SetFocus(m_hwndList);
|
|
|
|
//put the ListView into edit mode
|
|
ListView_EditLabel(m_hwndList, i);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::UpdateData()
|
|
|
|
**************************************************************************/
|
|
|
|
VOID CShellView::UpdateData(LPCITEMIDLIST pidl)
|
|
{
|
|
int i;
|
|
|
|
i = FindItemPidl(pidl);
|
|
|
|
if(-1 != i)
|
|
{
|
|
LVITEM lvItem;
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = i;
|
|
ListView_GetItem(m_hwndList, &lvItem);
|
|
|
|
m_pPidlMgr->Delete((LPITEMIDLIST)lvItem.lParam);
|
|
|
|
ZeroMemory(&lvItem, sizeof(lvItem));
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = i;
|
|
lvItem.lParam = (LPARAM)m_pPidlMgr->Copy(pidl);
|
|
ListView_SetItem(m_hwndList, &lvItem);
|
|
ListView_Update(m_hwndList, i);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnViewLarge()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnViewLarge(VOID)
|
|
{
|
|
m_FolderSettings.ViewMode = FVM_ICON;
|
|
|
|
DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
|
|
dwStyle &= ~LVS_TYPEMASK;
|
|
dwStyle |= LVS_ICON;
|
|
SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnViewSmall()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnViewSmall(VOID)
|
|
{
|
|
m_FolderSettings.ViewMode = FVM_SMALLICON;
|
|
|
|
DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
|
|
dwStyle &= ~LVS_TYPEMASK;
|
|
dwStyle |= LVS_SMALLICON;
|
|
SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnViewList()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnViewList(VOID)
|
|
{
|
|
m_FolderSettings.ViewMode = FVM_LIST;
|
|
|
|
DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
|
|
dwStyle &= ~LVS_TYPEMASK;
|
|
dwStyle |= LVS_LIST;
|
|
SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
CShellView::OnViewDetails()
|
|
|
|
**************************************************************************/
|
|
|
|
LRESULT CShellView::OnViewDetails(VOID)
|
|
{
|
|
m_FolderSettings.ViewMode = FVM_DETAILS;
|
|
|
|
DWORD dwStyle = GetWindowLong(m_hwndList, GWL_STYLE);
|
|
dwStyle &= ~LVS_TYPEMASK;
|
|
dwStyle |= LVS_REPORT;
|
|
SetWindowLong(m_hwndList, GWL_STYLE, dwStyle);
|
|
|
|
return 0;
|
|
}
|
|
|