Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1412 lines
27 KiB

/*++
Implements IShellView.
--*/
#include <windows.h>
#include <windowsx.h>
#include <objbase.h>
#include <shlobj.h>
#include <docobj.h>
#include <shellapi.h>
#include "pstore.h"
#include "shfolder.h"
#include "shview.h"
#include "guid.h"
#include "resource.h"
#include "tools.h"
#include "utility.h"
#include "enumid.h"
#include "listu.h"
extern HINSTANCE g_hInst;
extern LONG g_DllRefCount;
BOOL
AddListItem(
HWND hWnd,
DWORD dwType,
PST_KEY KeyType,
LPCWSTR szName,
LPITEMIDLIST pidl
);
#define TOOLBAR_ID (L"TBar")
#define INITIAL_COLUMN_POS 100
MYTOOLINFO g_Buttons[] =
{
IDM_MESSAGE1, 0, IDS_TB_MESSAGE1, IDS_MI_MESSAGE1, TBSTATE_ENABLED, TBSTYLE_BUTTON,
IDM_MESSAGE2, 0, IDS_TB_MESSAGE2, IDS_MI_MESSAGE2, TBSTATE_ENABLED, TBSTYLE_BUTTON,
-1, 0, 0, 0, 0,
};
CShellView::CShellView(
CShellFolder *pFolder,
LPCITEMIDLIST pidl
)
{
m_hMenu = NULL;
ZeroMemory(&m_MenuWidths, sizeof(m_MenuWidths));
m_nColumn1 = INITIAL_COLUMN_POS;
m_nColumn2 = INITIAL_COLUMN_POS;
m_pSFParent = pFolder;
if(m_pSFParent)
m_pSFParent->AddRef();
m_pidl = (LPITEMIDLIST)pidl;
m_uState = SVUIA_DEACTIVATE;
m_ObjRefCount = 1;
InterlockedIncrement(&g_DllRefCount);
}
CShellView::~CShellView()
{
if(m_pSFParent)
m_pSFParent->Release();
InterlockedDecrement(&g_DllRefCount);
}
STDMETHODIMP
CShellView::QueryInterface(
REFIID riid,
LPVOID *ppReturn
)
/*++
IUnknown::QueryInterface
--*/
{
*ppReturn = NULL;
if(IsEqualIID(riid, IID_IUnknown))
*ppReturn = (IUnknown*)(IShellView*)this;
else if(IsEqualIID(riid, IID_IOleWindow))
*ppReturn = (IOleWindow*)this;
else if(IsEqualIID(riid, IID_IShellView))
*ppReturn = (CShellView*)this;
else if(IsEqualIID(riid, IID_IOleCommandTarget))
*ppReturn = (IOleCommandTarget*)this;
if(*ppReturn == NULL)
return E_NOINTERFACE;
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
STDMETHODIMP_(DWORD)
CShellView::AddRef()
/*++
IUnknown::AddRef
--*/
{
return InterlockedIncrement(&m_ObjRefCount);
}
STDMETHODIMP_(DWORD)
CShellView::Release()
/*++
IUnknown::Release
--*/
{
LONG lDecremented = InterlockedDecrement(&m_ObjRefCount);
if(lDecremented == 0)
delete this;
return lDecremented;
}
STDMETHODIMP
CShellView::GetWindow(
HWND *phWnd
)
/*++
IOleWindow::GetWindow
--*/
{
*phWnd = m_hWnd;
return S_OK;
}
STDMETHODIMP
CShellView::ContextSensitiveHelp(
BOOL fEnterMode
)
/*++
Inherited from IOleWindow::ContextSensitiveHelp.
--*/
{
return E_NOTIMPL;
}
STDMETHODIMP
CShellView::QueryStatus(
const GUID *pguidCmdGroup,
ULONG cCmds,
OLECMD prgCmds[],
OLECMDTEXT *pCmdText
)
/*++
IOleCommandTarget::QueryStatus
--*/
{
ULONG i;
//
// only process the commands for our command group
//
if(pguidCmdGroup && (*pguidCmdGroup != CLSID_CmdGrp))
return OLECMDERR_E_UNKNOWNGROUP;
//
// make sure prgCmds is not NULL
//
if(prgCmds == NULL)
return E_POINTER;
//
// run through all of the commands and supply the correct information
//
for(i = 0; i < cCmds;i++)
{
switch(prgCmds[i].cmdID)
{
case IDM_MESSAGE1:
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
break;
case IDM_MESSAGE2:
prgCmds[i].cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
break;
}
}
return S_OK;
}
STDMETHODIMP
CShellView::Exec(
const GUID *pguidCmdGroup,
DWORD nCmdID,
DWORD nCmdExecOpt,
VARIANTARG *pvaIn,
VARIANTARG *pvaOut
)
/*++
IOleCommandTarget::Exec
--*/
{
//
// only process the commands for our command group
//
if(pguidCmdGroup && (*pguidCmdGroup == CLSID_CmdGrp))
{
OnCommand(nCmdID, 0, NULL);
return S_OK;
}
return OLECMDERR_E_UNKNOWNGROUP;
}
STDMETHODIMP
CShellView::TranslateAccelerator(
LPMSG pMsg
)
/*++
Same as the IOleInPlaceFrame::TranslateAccelerator, but will be
never called because we don't support EXEs (i.e., the explorer has
the message loop). This member function is defined here for possible
future enhancement.
--*/
{
return E_NOTIMPL;
}
STDMETHODIMP
CShellView::EnableModeless(
BOOL fEnable
)
/*++
Same as the IOleInPlaceFrame::EnableModeless.
--*/
{
return E_NOTIMPL;
}
STDMETHODIMP
CShellView::UIActivate(
UINT uState
)
/*++
IShellView::UIActivate
--*/
{
//
// don't do anything if the state isn't really changing
//
if(m_uState == uState)
return S_OK;
//
// Always do this because we will cause problems if we are going from
// SVUIA_ACTIVATE_FOCUS to SVUIA_ACTIVATE_NOFOCUS or vice versa.
//
m_uState = SVUIA_DEACTIVATE;
m_pShellBrowser->SetMenuSB(NULL, NULL, NULL);
if(m_hMenu) {
DestroyMenu(m_hMenu);
m_hMenu = NULL;
}
//
// only do this if we are active
//
if(uState != SVUIA_DEACTIVATE) {
m_uState = uState;
//
// update the Explorer's menu
//
if(m_hMenu == NULL)
m_hMenu = CreateMenu();
if(m_hMenu) {
MENUITEMINFO mii;
TCHAR szText[MAX_PATH];
m_pShellBrowser->InsertMenusSB(m_hMenu, &m_MenuWidths);
//
// get the menu item's text
//
LoadString(g_hInst, IDS_MI_REGISTRY, szText, sizeof(szText));
//
// build our menu
//
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
mii.fType = MFT_STRING;
mii.fState = MFS_ENABLED;
mii.dwTypeData = szText;
mii.hSubMenu = BuildMenu();
//
// insert our menu
//
InsertMenuItem(m_hMenu, FCIDM_MENU_HELP, FALSE, &mii);
m_pShellBrowser->SetMenuSB(m_hMenu, NULL, m_hWnd);
}
//
// TODO: update the status bar
//
/*
TCHAR szName[MAX_PATH];
LoadString(g_hInst, IDS_PSTORE_TITLE, szName, sizeof(szName));
m_pSFParent->GetPidlFullText(m_pidl, szName + lstrlen(szName), sizeof(szName) - lstrlen(szName));
LRESULT lResult;
int nPartArray[1] = {-1};
//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)szName, &lResult);
*/
}
return S_OK;
}
HMENU
CShellView::BuildMenu(
void
)
{
HMENU hSubMenu = CreatePopupMenu();
if(hSubMenu == NULL)
return NULL;
TCHAR szText[MAX_PATH];
MENUITEMINFO mii;
int nButtons, i;
//
// get the number of items in our global array
//
for(nButtons = 0; g_Buttons[nButtons].idCommand != -1; nButtons++) {
;
}
//
// add the menu items
//
for(i = 0; i < nButtons; i++) {
LoadString(g_hInst, g_Buttons[i].idMenuString, szText, sizeof(szText));
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
if(TBSTYLE_SEP != g_Buttons[i].bStyle) {
mii.fType = MFT_STRING;
mii.fState = MFS_ENABLED;
mii.dwTypeData = szText;
mii.wID = g_Buttons[i].idCommand;
} else {
mii.fType = MFT_SEPARATOR;
}
//
// tack this item onto the end of the menu
//
InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
}
//
// add a couple more that aren't in the button array
//
LoadString(g_hInst, IDS_MI_VIEW_ISTB, szText, sizeof(szText));
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
mii.fType = MFT_STRING;
mii.fState = MFS_ENABLED;
mii.dwTypeData = szText;
mii.wID = IDM_VIEW_ISTB;
//
// tack this item onto the end of the menu
//
InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
LoadString(g_hInst, IDS_MI_VIEW_IETB, szText, sizeof(szText));
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
mii.fType = MFT_STRING;
mii.fState = MFS_ENABLED;
mii.dwTypeData = szText;
mii.wID = IDM_VIEW_IETB;
//
// tack this item onto the end of the menu
//
InsertMenuItem(hSubMenu, (UINT)-1, TRUE, &mii);
return hSubMenu;
}
STDMETHODIMP
CShellView::Refresh(
void
)
/*++
IShellView::Refresh
--*/
{
//
// empty the list
//
ListView_DeleteAllItems(m_hwndList);
//
// refill the list
//
FillList();
return S_OK;
}
STDMETHODIMP
CShellView::CreateViewWindow(
LPSHELLVIEW pPrevView,
LPCFOLDERSETTINGS lpfs,
LPSHELLBROWSER psb,
LPRECT prcView,
HWND *phWnd
)
/*++
CreateViewWindow creates a view window. This can be either the right pane
of the Explorer or the client window of a folder window.
--*/
{
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.ViewMode = lpfs->ViewMode;
m_FolderSettings.fFlags = lpfs->fFlags;
//
// get our parent window
//
m_pShellBrowser->GetWindow(&m_hwndParent);
GetSettings();
*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 == NULL)
return E_FAIL;
//
// addref the IShellBrowser interface to allow communication with Explorer
//
m_pShellBrowser->AddRef();
return S_OK;
}
STDMETHODIMP
CShellView::DestroyViewWindow(
void
)
/*++
The Explorer calls this method when a folder window or the Explorer
is being closed.
--*/
{
if(m_hMenu)
DestroyMenu(m_hMenu);
DestroyWindow(m_hWnd);
//
// release the shell browser object
//
m_pShellBrowser->Release();
return S_OK;
}
STDMETHODIMP
CShellView::GetCurrentInfo(
LPFOLDERSETTINGS lpfs
)
/*++
The Explorer uses GetCurrentInfo to query the view for standard settings.
--*/
{
// TODO, check proper approach.
*lpfs = m_FolderSettings;
// lpfs->ViewMode = m_FolderSettings.ViewMode;
// lpfs->fFlags = m_FolderSettings.fFlags;
return NOERROR;
}
STDMETHODIMP
CShellView::AddPropertySheetPages(
DWORD dwReserved,
LPFNADDPROPSHEETPAGE lpfn,
LPARAM lParam
)
/*++
The Explorer calls this method when it is opening the View.Options...
property sheet. Views can add pages by creating them and calling the
callback function with the page handles.
--*/
{
OutputDebugStringA("IShellView::AddPropertySheetPages\n");
return E_NOTIMPL;
}
STDMETHODIMP
CShellView::SaveViewState(
void
)
/*++
IShellView::SaveViewState
--*/
{
SaveSettings();
return S_OK;
}
STDMETHODIMP
CShellView::SelectItem(
LPCITEMIDLIST pidlItem,
UINT uFlags
)
/*++
IShellView::SelectItem
--*/
{
return E_NOTIMPL;
}
STDMETHODIMP
CShellView::GetItemObject(
UINT uItem,
REFIID riid,
LPVOID *ppvOut
)
/*++
Used by the common dialogs to get the selected items from the view.
--*/
{
return E_NOTIMPL;
}
LRESULT
CALLBACK
CShellView::WndProc(
HWND hWnd,
UINT uMessage,
WPARAM wParam,
LPARAM lParam
)
{
CShellView *pThis = (CShellView*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch (uMessage)
{
case WM_NCCREATE:
{
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
pThis = (CShellView*)(lpcs->lpCreateParams);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM)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_SETFOCUS:
return pThis->OnSetFocus();
case WM_ACTIVATE:
return pThis->OnActivate(wParam, lParam);
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);
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
LRESULT
CShellView::OnSetFocus(
void
)
{
//
// tell the browser we got the focus
//
m_pShellBrowser->OnViewWindowActive(this);
return 0;
}
LRESULT
CShellView::OnActivate(
WPARAM wParam,
LPARAM lParam
)
{
//
// tell the browser we got the focus
//
if(wParam)
m_pShellBrowser->OnViewWindowActive(this);
return 0;
}
LRESULT
CShellView::OnCommand(
DWORD dwCmdID,
DWORD dwCmd,
HWND hwndCmd
)
{
switch(dwCmdID)
{
case IDM_MESSAGE1:
MessageBox(m_hWnd, TEXT("Message 1 was selected"), TEXT("Notice"), MB_OK | MB_ICONEXCLAMATION);
break;
case IDM_MESSAGE2:
MessageBox(m_hWnd, TEXT("Message 2 was selected"), TEXT("Notice"), MB_OK | MB_ICONEXCLAMATION);
break;
case IDM_VIEW_ISTB:
m_bShowISTB = ! m_bShowISTB;
UpdateToolbar();
break;
case IDM_VIEW_IETB:
m_bShowIETB = ! m_bShowIETB;
UpdateToolbar();
break;
}
return 0;
}
HRESULT
CShellView::SaveSettings(
void
)
/*++
Called by IShellView::SaveViewState to store the relevant setting data
to the browser stream.
--*/
{
HRESULT hr;
LPSTREAM pStream;
hr = m_pShellBrowser->GetViewStateStream(STGM_WRITE, &pStream);
if(SUCCEEDED(hr))
{
ULONG uWritten;
pStream->Write(&m_bShowISTB, sizeof(m_bShowISTB), &uWritten);
pStream->Write(&m_bShowIETB, sizeof(m_bShowIETB), &uWritten);
pStream->Write(&m_nColumn1, sizeof(m_nColumn1), &uWritten);
pStream->Write(&m_nColumn2, sizeof(m_nColumn2), &uWritten);
pStream->Release();
}
return hr;
}
HRESULT
CShellView::GetSettings(
void
)
{
HRESULT hr;
LPSTREAM pStream;
hr = m_pShellBrowser->GetViewStateStream(STGM_READ, &pStream);
if(SUCCEEDED(hr)) {
ULONG uRead;
if(S_OK != pStream->Read(&m_bShowISTB, sizeof(m_bShowISTB), &uRead))
m_bShowISTB = FALSE;
if(S_OK != pStream->Read(&m_bShowIETB, sizeof(m_bShowIETB), &uRead))
m_bShowIETB = FALSE;
if(S_OK != pStream->Read(&m_nColumn1, sizeof(m_nColumn1), &uRead))
m_nColumn1 = INITIAL_COLUMN_POS;
if(S_OK != pStream->Read(&m_nColumn2, sizeof(m_nColumn2), &uRead))
m_nColumn2 = INITIAL_COLUMN_POS;
pStream->Release();
}
return hr;
}
LRESULT
CShellView::UpdateMenu(
HMENU hMenu
)
{
return 0;
}
void
CShellView::UpdateToolbar()
{
// nothing to update yet
}
LRESULT
CShellView::OnNotify(
UINT CtlID,
LPNMHDR pNotify
)
{
LPNM_LISTVIEW pNotifyLV = (LPNM_LISTVIEW)pNotify;
LV_DISPINFO *pNotifyDI = (LV_DISPINFO *)pNotify;
LPTBNOTIFY pNotifyTB = (LPTBNOTIFY)pNotify;
LPTOOLTIPTEXT pNotifyTT = (LPTOOLTIPTEXT)pNotify;
switch(pNotify->code)
{
//
// HDN_BEGINTRACK
// HDN_DIVIDERDBLCLICK
// HDN_ENDTRACK
// HDN_ITEMCHANGED
// HDN_ITEMCHANGING
// HDN_ITEMCLICK
// HDN_ITEMDBLCLICK
// HDN_TRACK
//
case HDN_ENDTRACK:
{
m_nColumn1 = ListView_GetColumnWidth(m_hwndList, 0);
m_nColumn2 = ListView_GetColumnWidth(m_hwndList, 1);
break;
}
//
// LVN_BEGINDRAG
// LVN_BEGINLABELEDIT
// LVN_BEGINRDRAG
// LVN_COLUMNCLICK
// LVN_DELETEALLITEMS
// LVN_DELETEITEM
// LVN_ENDLABELEDIT
// LVN_GETDISPINFO
// LVN_INSERTITEM
// LVN_ITEMCHANGED
// LVN_ITEMCHANGING
// LVN_KEYDOWN
// LVN_SETDISPINFO
//
case LVN_DELETEITEM:
{
LPITEMIDLIST pidl = (LPITEMIDLIST)(pNotifyLV->lParam);
//
// free the memory for the pidl associated with this item.
//
if(pidl != NULL)
FreePidl(pidl);
break;
}
// NM_CLICK
// NM_DBLCLK
// NM_KILLFOCUS
// NM_LISTVIEW
// NM_OUTOFMEMORY
// NM_RCLICK
// NM_RDBLCLK
// NM_RETURN
// NM_SETFOCUS
// NM_TREEVIEW
// NM_UPDOWN
//
case NM_RETURN:
case NM_DBLCLK:
{
UINT wFlags = SBSP_RELATIVE | SBSP_DEFMODE;
int iItem = -1;
//
// if we are in explorer mode, start out in DEFBROWSER mode,
// otherwise, start in NEWBROWSER mode.
//
HWND hwnd = NULL;
m_pShellBrowser->GetControlWindow(FCW_TREE, &hwnd);
if(hwnd != NULL) {
wFlags |= SBSP_DEFBROWSER;
} else {
wFlags |= SBSP_NEWBROWSER;
}
//
// loop through all the selected items.
// TODO: if more than two are selected, we only get to view
// two.
//
do {
LV_ITEM item;
iItem = ListView_GetNextItem(m_hwndList, iItem, LVNI_SELECTED | LVNI_ALL);
ZeroMemory(&item, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = iItem;
if(!ListView_GetItem(m_hwndList, &item))
break;
LPCITEMIDLIST pidl = (LPCITEMIDLIST)(item.lParam);
if(pidl != NULL) {
//
// don't browse into items.
//
if(GetLastPidlType(pidl) > PIDL_TYPE_SUBTYPE)
break;
m_pShellBrowser->BrowseObject(pidl, wFlags);
}
//
// if multiple items selected, bring up a new browser
//
wFlags &= ~SBSP_DEFBROWSER;
wFlags |= SBSP_NEWBROWSER;
} while (iItem != -1);
}
//
// TBN_BEGINADJUST
// TBN_BEGINDRAG
// TBN_CUSTHELP
// TBN_ENDADJUST
// TBN_ENDDRAG
// TBN_GETBUTTONINFO
// TBN_QUERYDELETE
// TBN_QUERYINSERT
// TBN_RESET
// TBN_TOOLBARCHANGE
//
case TBN_BEGINDRAG:
default:
return 0;
}
return 0;
}
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);
return 0;
}
LRESULT
CShellView::OnCreate(
void
)
{
//
// create the ListView
//
if(CreateList())
{
if(InitList())
{
FillList();
}
}
return 0;
}
BOOL
CShellView::CreateList(
void
)
{
DWORD dwStyle;
//
// fetch the prior listview style and use
// that as the new listview style.
//
switch (m_FolderSettings.ViewMode) {
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;
default:
dwStyle = LVS_ICON;
break;
}
m_hwndList = CreateWindowEx(
WS_EX_CLIENTEDGE,
WC_LISTVIEW,
NULL,
WS_TABSTOP |
WS_VISIBLE |
WS_CHILD |
WS_BORDER |
LVS_SORTASCENDING |
dwStyle |
LVS_NOSORTHEADER |
0,
0,
0,
0,
0,
m_hWnd,
(HMENU)ID_LISTVIEW,
g_hInst,
NULL
);
return (BOOL)(NULL != m_hwndList);
}
BOOL
CShellView::InitList(
void
)
{
LV_COLUMN lvColumn;
HIMAGELIST himlSmall;
HIMAGELIST himlLarge;
RECT rc;
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 = m_nColumn1;
LoadString(g_hInst, IDS_COLUMN1, szString, sizeof(szString));
ListView_InsertColumn(m_hwndList, 0, &lvColumn);
GetClientRect(m_hWnd, &rc);
lvColumn.cx = m_nColumn2;
LoadString(g_hInst, IDS_COLUMN2, szString, sizeof(szString));
ListView_InsertColumn(m_hwndList, 1, &lvColumn);
int cxSmall;
int cySmall;
int cxLarge;
int cyLarge;
SHFILEINFO sfi;
HIMAGELIST himl;
//
// get large and small icon size info from shell
//
himl = (HIMAGELIST)SHGetFileInfo(
NULL,
0,
&sfi,
sizeof(sfi),
SHGFI_LARGEICON | SHGFI_SYSICONINDEX
);
if(!ImageList_GetIconSize(himl, &cxLarge, &cyLarge)) {
cxLarge = GetSystemMetrics(SM_CXICON);
cyLarge = GetSystemMetrics(SM_CYICON);
}
himl = (HIMAGELIST)SHGetFileInfo(
NULL,
0,
&sfi,
sizeof(sfi),
SHGFI_SMALLICON | SHGFI_SYSICONINDEX
);
if(!ImageList_GetIconSize(himl, &cxSmall, &cySmall)) {
cxSmall = GetSystemMetrics(SM_CXSMICON);
cySmall = GetSystemMetrics(SM_CYSMICON);
}
//
// Create the full-sized and small icon image lists.
//
himlLarge = ImageList_Create(
cxLarge,
cyLarge,
ILC_COLORDDB | ILC_MASK,
4, // initial image count
0
);
himlSmall = ImageList_Create(
cxSmall,
cySmall,
ILC_COLORDDB | ILC_MASK,
4, // initial image count
0
);
//
// Add icons to each image list.
// TODO cache icons
//
HICON hIconSmall;
HICON hIconLarge;
// icon 0: Provider icon
hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_PROVIDER), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_PROVIDER), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
ImageList_AddIcon(himlSmall, hIconSmall);
ImageList_AddIcon(himlLarge, hIconLarge);
// icon 1: type icon
hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_FOLDER), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_FOLDER), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
ImageList_AddIcon(himlSmall, hIconSmall);
ImageList_AddIcon(himlLarge, hIconLarge);
// icon 2: item icon
hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ITEM), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ITEM), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
ImageList_AddIcon(himlSmall, hIconSmall);
ImageList_AddIcon(himlLarge, hIconLarge);
// icon 3: global type
hIconSmall = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_GLOBAL), IMAGE_ICON, cxSmall, cySmall, LR_DEFAULTCOLOR | LR_SHARED);
hIconLarge = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_GLOBAL), IMAGE_ICON, cxLarge, cyLarge, LR_DEFAULTCOLOR | LR_SHARED);
ImageList_AddIcon(himlSmall, hIconSmall);
ImageList_AddIcon(himlLarge, hIconLarge);
//
// Assign the image lists to the list view control.
//
ListView_SetImageList(m_hwndList, himlLarge, LVSIL_NORMAL);
ListView_SetImageList(m_hwndList, himlSmall, LVSIL_SMALL);
return TRUE;
}
BOOL
CShellView::FillList(
void
)
{
LPENUMIDLIST pEnumIDList;
ULONG ulFetched;
LPITEMIDLIST pidl = NULL;
pEnumIDList = new CEnumIDList(m_pidl, TRUE);
if(pEnumIDList == NULL)
return FALSE;
//
// enumerate the sub folders or items, based on the parent m_pidl.
// note that storage is allocated for the pidlNew, which is a copy
// of the current path + pidl - that storage is later freed during
// the processing of LVN_DELETEITEM
//
while( NOERROR == pEnumIDList->Next(1, &pidl, &ulFetched) ) {
LPCWSTR szText = GetPidlText(pidl);
PST_KEY KeyType = GetPidlKeyType(pidl);
DWORD dwPidlType = GetPidlType(pidl);
//
// make a fully qualified (absolute) pidl
//
// LPITEMIDLIST pidlNew = CopyCatPidl(m_pidl, pidl);
//
// free pidl associated with Next enumeration
//
// FreePidl(pidl);
//
// add item with absolute pidl to listview
//
AddListItem(m_hwndList, dwPidlType, KeyType, szText, pidl);
}
pEnumIDList->Release();
return TRUE;
}
BOOL
AddListItem(
HWND hWnd,
DWORD dwType,
PST_KEY KeyType,
LPCWSTR szName,
LPITEMIDLIST pidl
)
/*++
This function is a temporary hack to support image list add/set data.
This will be replaced by an Unicode interface that operates on WinNT and
Win95 in the near future.
--*/
{
LVITEM lvItem;
int nIndex;
DWORD dwIconIndex;
//
// determine which icon to use.
// when PST_KEY is not PST_KEY_LOCAL_MACHINE, use a different folder
// icon at the type and subtype level.
//
switch(dwType) {
case PIDL_TYPE_PROVIDER:
dwIconIndex = 0;
break;
case PIDL_TYPE_TYPE:
case PIDL_TYPE_SUBTYPE:
if(KeyType == PST_KEY_CURRENT_USER)
dwIconIndex = 1;
else
dwIconIndex = 3; // global (shared) icon
break;
case PIDL_TYPE_ITEM:
dwIconIndex = 2;
break;
default:
dwIconIndex = 0;
}
ZeroMemory(&lvItem, sizeof(lvItem));
lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
lvItem.iItem = 0;
lvItem.lParam = (LPARAM)pidl;
lvItem.pszText = (LPTSTR)szName;
lvItem.iImage = dwIconIndex; // image index
nIndex = ListView_InsertItemU(hWnd, &lvItem);
// ListView_SetItemTextU(hWnd, nIndex, 1, (LPWSTR)szValue);
return TRUE;
}