|
|
//
// Microsoft Windows Media Technologies
// Copyright (C) Microsoft Corporation, 1999 - 2001. All rights reserved.
//
//
// This workspace contains two projects -
// 1. ProgHelp which implements the Progress Interface
// 2. The Sample application WmdmApp.
//
// ProgHelp.dll needs to be registered first for the SampleApp to run.
// Includes
//
#include "appPCH.h"
// Constants
//
#define DEVFILES_LV_NUMCOLS 3
#define DEVFILES_COL_MARGIN 3
#define SMALL_IMAGE_WIDTH 16
const CLSID CLSID_WMDMProgressHelper = {0x8297A5B4,0x5113,0x11D3,{0xB2,0x76,0x00,0xC0,0x4F,0x8E,0xC2,0x21}}; const IID IID_IWMDMProgressHelper = {0x1DCB3A10,0x33ED,0x11d3,{0x84,0x70,0x00,0xC0,0x4F,0x79,0xDB,0xC5}};
const CLSID CLSID_WMDMOperationHelper = {0x9FB01A67,0xA11E,0x4653,{0x8E,0xD6,0xB5,0xCE,0x73,0xCD,0xA3,0xE3}}; const IID IID_IWMDMOperationHelper = {0x41216997,0xC4D9,0x445A,{0xA3,0x88,0x39,0x3D,0x2B,0x85,0xA0,0xE5}};
// Macros
//
// Local functions
//
INT_PTR CALLBACK DevFiles_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK WndProc_DevFiles_LV(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// Local Variables
//
/////////////////////////////////////////////////////////////////////
//
// Function implementations
//
CDevFiles::CDevFiles() { m_hwndDevFiles = NULL; m_hwndDevFiles_LV = NULL;
m_iFolderIcon = 0;
m_dwTotalTicks = 0; m_dwWorkingTicks = 0;
m_pProgHelp = NULL;
m_wndprocDevFiles_LV = NULL;
CoInitialize( NULL ); }
CDevFiles::~CDevFiles() { CoUninitialize(); }
HWND CDevFiles::GetHwnd( void ) { return m_hwndDevFiles; }
HWND CDevFiles::GetHwnd_LV( void ) { return m_hwndDevFiles_LV; }
BOOL CDevFiles::Create( HWND hwndParent ) { BOOL fRet = FALSE;
// Create the Device Files dialog
//
m_hwndDevFiles = CreateDialogParam( g_hInst, MAKEINTRESOURCE( IDD_DEVICEFILES ), hwndParent, DevFiles_DlgProc, (LPARAM)this ); ExitOnNull( m_hwndDevFiles );
// Get a handle to the ListView control of the Device Files dialog
//
m_hwndDevFiles_LV = GetDlgItem( m_hwndDevFiles, IDC_LV_DEVICEFILES );
// Set the user data to be this CDevFiles class pointer
//
SetWindowLongPtr( m_hwndDevFiles_LV, GWLP_USERDATA, (LPARAM)this );
// Subclass the listview
//
m_wndprocDevFiles_LV = (WNDPROC) SetWindowLongPtr( m_hwndDevFiles_LV, GWLP_WNDPROC, (LONG_PTR)WndProc_DevFiles_LV );
// Initialize image list
//
ExitOnFalse( InitImageList() );
// Initialize columns
//
ExitOnFalse( InitColumns() );
// Handle Drag and Dropped files
//
DragAcceptFiles( m_hwndDevFiles, TRUE );
// Show the window
//
ShowWindow( m_hwndDevFiles, SW_SHOW );
fRet = TRUE;
lExit:
return fRet; }
VOID CDevFiles::Destroy( void ) { // Remove all the item from the listview control
//
RemoveAllItems();
// Destroy the window
//
if( m_hwndDevFiles ) { DestroyWindow( m_hwndDevFiles ); } }
BOOL CDevFiles::InitImageList( void ) { BOOL fRet = FALSE; HRESULT hr; IMalloc *pMalloc = NULL; LPITEMIDLIST pidl = NULL; HIMAGELIST hShellImageList = NULL; SHFILEINFO si; CHAR szWinPath[MAX_PATH+1]; UINT nRet;
// Get the index of the folder icon
//
nRet = GetWindowsDirectory( szWinPath, sizeof(szWinPath)/sizeof(szWinPath[0]) ); if (nRet == 0 || nRet > sizeof(szWinPath)/sizeof(szWinPath[0])) { // Failed to get the windows directory
goto lExit; }
// Get a shell ID list for the desktop folder
//
hr = SHGetSpecialFolderLocation( g_hwndMain, CSIDL_DESKTOP, &pidl ); ExitOnFail( hr );
// Get the shell's small icon image list and set that to be the listview's image list
//
hShellImageList = (HIMAGELIST) SHGetFileInfo( (LPCTSTR)pidl, 0, &si, sizeof(si), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON ); if( hShellImageList ) { ListView_SetImageList( m_hwndDevFiles_LV, hShellImageList, LVSIL_SMALL ); } // Get the shell's normal icon image list and set that to be the listview's image list
//
hShellImageList = (HIMAGELIST) SHGetFileInfo( (LPCTSTR)pidl, 0, &si, sizeof(si), SHGFI_PIDL | SHGFI_SYSICONINDEX ); if( hShellImageList ) { ListView_SetImageList( m_hwndDevFiles_LV, hShellImageList, LVSIL_NORMAL ); }
SHGetFileInfo( szWinPath, 0, &si, sizeof(si), SHGFI_SYSICONINDEX ); m_iFolderIcon = si.iIcon;
// Everything went Ok
//
fRet = TRUE;
lExit:
// Free the pointer to the shell's ID list
//
if (pidl) { hr = SHGetMalloc( &pMalloc ); if( SUCCEEDED(hr) && pMalloc ) { pMalloc->Free( pidl ); } }
return fRet; }
BOOL CDevFiles::InitColumns( void ) { LVCOLUMN lvcol; INT i; char szCol[MAX_PATH];
//
// Add the report-view columns to the listview
// The column names and starting sizes are stored in the resource string table
//
lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; lvcol.fmt = LVCFMT_LEFT;
for( i=0; i < DEVFILES_LV_NUMCOLS; i++ ) { // Get the column size
//
LoadString( g_hInst, IDS_COLSIZE_1+i, szCol, sizeof(szCol) ); lvcol.cx = atoi( szCol ); // Get the column name
//
LoadString( g_hInst, IDS_COLNAME_1+i, szCol, sizeof(szCol) ); lvcol.pszText = szCol; // Add the column the the listview
//
ListView_InsertColumn( m_hwndDevFiles_LV, i, &lvcol ); }
return TRUE; }
VOID CDevFiles::OnSize( LPRECT prcMain ) { INT nX, nY, nW, nH; RECT rcMain; RECT rcDevice;
GetWindowRect( g_hwndMain, &rcMain ); GetWindowRect( g_cDevices.GetHwnd(), &rcDevice );
nX = (rcDevice.right - rcMain.left) - 2*GetSystemMetrics( SM_CXEDGE ); nY = 0; nW = prcMain->right - prcMain->left - nX; nH = prcMain->bottom - prcMain->top;
SetWindowPos( m_hwndDevFiles, NULL, nX, nY, nW, nH, SWP_NOZORDER ); SetWindowPos( m_hwndDevFiles_LV, NULL, 0, 0, nW, nH-22, SWP_NOZORDER ); }
BOOL CDevFiles::SendFilesToDevice( LPSTR pszFiles, UINT uNumFiles ) { BOOL fRet = FALSE; WCHAR wszName[MAX_PATH]; CHAR szName[MAX_PATH]; LPSTR psz; DWORD dwTotalSize = 0L; UINT uFile; HRESULT hr; HTREEITEM hItem; CItemData *pItemData; IWMDMStorageControl *pStorageControl = NULL; IWMDMStorage *pNewObject = NULL; IWMDMStorage *pInStorage = NULL; IWMDMProgress *pProgress = NULL; IWMDMOperation *pOperation = NULL; IWMDMOperationHelper *pOperationHelper = NULL; IWMDMRevoked *pRevoked = NULL; LPWSTR pwszRevokedURL = NULL; DWORD dwRevokedURLLen = 0; DWORD dwRevokedBitFlag;
// Get the selected device/storage
//
hItem = g_cDevices.GetSelectedItem( NULL ); ExitOnNull( hItem );
// Get the itemdata class associated with the hItem and
// retrieve the IWMDMStorage for it
//
pItemData = (CItemData *) TreeView_GetLParam( g_cDevices.GetHwnd_TV(), hItem ); ExitOnNull( pItemData );
pInStorage = ( pItemData->m_fIsDevice ? pItemData->m_pRootStorage : pItemData->m_pStorage ); ExitOnNull( pInStorage );
// Tally the file sizes
//
psz = pszFiles; for( uFile = 0; uFile < uNumFiles; uFile++ ) { dwTotalSize += GetTheFileSize( psz );
psz += lstrlen(psz) + 1; }
// Create the progress dialog
//
ExitOnFalse( m_cProgress.Create(g_hwndMain) );
m_cProgress.SetOperation( "Sending Files..." ); m_cProgress.SetCount( 0, uNumFiles ); m_cProgress.SetRange( 0, 100 ); m_dwTotalTicks = dwTotalSize; m_dwWorkingTicks = 0;
// Create the progress interface
//
hr = CoCreateInstance( CLSID_WMDMProgressHelper, NULL, CLSCTX_ALL, IID_IWMDMProgress, (void**)&pProgress ); ExitOnFail( hr );
pProgress->AddRef();
hr = pProgress->QueryInterface( IID_IWMDMProgressHelper, reinterpret_cast<void**> (&m_pProgHelp) ); ExitOnFail( hr );
m_pProgHelp->SetNotification( m_hwndDevFiles, WM_DRM_PROGRESS );
// Setup for copy using operation interface.
if( g_bUseOperationInterface ) { // Create the progress interface
//
hr = CoCreateInstance( CLSID_WMDMOperationHelper, NULL, CLSCTX_INPROC_SERVER, IID_IWMDMOperationHelper, (void**)&pOperationHelper ); ExitOnFail( hr );
hr = pOperationHelper->QueryInterface( IID_IWMDMOperation, reinterpret_cast<void**> (&pOperation) ); ExitOnFail( hr );
// Pass the SecureChannelClient as a pointer to the ProgHelper object.
// The object is inproc so it should be safe to pass pointers
pOperationHelper->SetSAC( (void*)g_cWmdm.m_pSAC ); }
// Acquire the storage control interface
//
hr = pInStorage->QueryInterface( IID_IWMDMStorageControl, reinterpret_cast<void**>(&pStorageControl) ); ExitOnFail( hr );
// Loop through the files, transfering each one
//
psz = pszFiles; for( uFile = 0; uFile < uNumFiles && !m_cProgress.IsCancelled(); uFile++ ) { hr = StringCchCopy(szName, sizeof(szName)/sizeof(szName[0]), psz);
if (FAILED(hr)) { fRet = FALSE; break; } if (!MultiByteToWideChar( CP_ACP, 0, szName, -1, wszName, sizeof(wszName)/sizeof(wszName[0]) )) { hr = HRESULT_FROM_WIN32(GetLastError()); fRet = FALSE; break; } // Set progress bar stats for this file
//
m_cProgress.IncCount(); StripPath( szName ); m_cProgress.SetDetails( szName ); m_cProgress.Show( TRUE );
UiYield();
pNewObject = NULL;
// Copy using operation interface.
if( g_bUseOperationInterface ) { // @@@@ The implementation treats the argument as a WCHAR*, not a
// BSTR, so this is ok. The simplest solution is to change the
// interface definition to WCHAR*. Will that cause any harm?
// (Interface appears to be a private one.)
//
// The alternative is to call SysAllocString. The issue with
// this approach is handling errors. Also SysAllocString inexplicably
// returns NULL when *wszName = 0. Can that happen?
//
pOperationHelper->SetFileName( wszName );
hr = pStorageControl->Insert( WMDM_MODE_BLOCK | WMDM_CONTENT_FILE | WMDM_CONTENT_OPERATIONINTERFACE, NULL, pOperation, pProgress, &pNewObject ); } else { hr = pStorageControl->Insert( WMDM_MODE_BLOCK | WMDM_CONTENT_FILE, wszName, NULL, pProgress, &pNewObject ); }
// Handle the case where one of the needed components was revoked
if( hr == WMDM_E_REVOKED ) { char pszCaption[MAX_PATH]; char pszErrorMsg[MAX_PATH];
// Hide progress window before displaying error messages
m_cProgress.Show( FALSE );
// Get Revocation interface from WMDM
hr = pStorageControl->QueryInterface( IID_IWMDMRevoked, (void**)&pRevoked ); if( hr != S_OK || pRevoked == NULL ) { // Latest version of WMDM not avalible on machine?
fRet = FALSE; break; }
// Get revocation information from WMDM
hr = pRevoked->GetRevocationURL( &pwszRevokedURL, &dwRevokedURLLen, &dwRevokedBitFlag ); if( FAILED(hr) ) { fRet = FALSE; break; } // The application has been revoked
if( dwRevokedBitFlag & WMDM_APP_REVOKED ) { LoadString( g_hInst, IDS_REVOKED_CAPTION, pszCaption, sizeof(pszCaption) ); LoadString( g_hInst, IDS_APP_REVOKED, pszErrorMsg, sizeof(pszErrorMsg) );
::MessageBoxA( g_hwndMain, pszErrorMsg, pszCaption, MB_OK ); } // A component needed for the transfer has been revoked, give the user
// a chance to look for an update on the internet.
else { LoadString( g_hInst, IDS_REVOKED_CAPTION, pszCaption, sizeof(pszCaption) ); LoadString( g_hInst, IDS_COMPONENT_REVOKED, pszErrorMsg, sizeof(pszErrorMsg) ); if( ::MessageBoxA( g_hwndMain, pszErrorMsg, pszCaption, MB_YESNO ) == IDYES ) { ShellExecuteW(g_hwndMain, L"open", pwszRevokedURL, NULL, NULL, SW_SHOWNORMAL); } } CoTaskMemFree( pwszRevokedURL ); break; } if( SUCCEEDED(hr) && pNewObject ) { CItemData *pStorageItem = new CItemData; if( pStorageItem ) { hr = pStorageItem->Init( pNewObject );
if( SUCCEEDED(hr) ) { g_cDevFiles.AddItem( pStorageItem ); } else { delete pStorageItem; } }
pNewObject->Release(); }
psz += lstrlen(psz) + 1; }
// Make sure the dialog is hidden and then destroy it
//
m_cProgress.SetPos( -1 ); m_cProgress.Show( FALSE ); m_cProgress.Destroy();
// refresh the device/devicefiles display
g_cDevices.UpdateSelection( NULL, FALSE );
lExit: if( pOperationHelper ) { pOperationHelper->Release(); } if( pOperation ) { pOperation->Release(); } if( pStorageControl ) { pStorageControl->Release(); } if( pRevoked ) { pRevoked->Release(); }
if( m_pProgHelp ) { m_pProgHelp->Release(); m_pProgHelp = NULL; }
if( pProgress ) { pProgress->Release(); }
return fRet; }
BOOL CDevFiles::OnDropFiles( HWND hWnd, WPARAM wParam, LPARAM lParam ) { LPSTR lpsz = NULL; HANDLE hDrop = (HANDLE) wParam; UINT uNumFiles;
// Turn the drop list into a double-zero-terminated list of strings
//
lpsz = DropListToBuffer( (HDROP)hDrop, LTB_NULL_TERM, &uNumFiles ); ExitOnNull( lpsz );
// Send those files to the selected device
//
SendFilesToDevice( lpsz, uNumFiles );
lExit:
// Close the dragdrop operation
//
DragFinish( (HDROP)hDrop );
if( lpsz ) { MemFree( lpsz ); }
return 0; // return zero if we process this message
}
VOID CDevFiles::RemoveAllItems( void ) { INT i; INT nCount;
nCount = ListView_GetItemCount( m_hwndDevFiles_LV );
// Remove the items one at a time, from the bottom up
//
for( i=nCount-1; i >= 0; i-- ) { RemoveItem( i ); } }
BOOL CDevFiles::RemoveItem( INT nItem ) { CItemData *pStorage;
pStorage = (CItemData *) ListView_GetLParam( m_hwndDevFiles_LV, nItem );
if( pStorage ) { delete pStorage; }
return ListView_DeleteItem( m_hwndDevFiles_LV, nItem ); }
BOOL CDevFiles::AddItem( CItemData *pStorage ) { LVITEM lvitem; INT nItem; CHAR sz[MAX_PATH]; INT m_iSysFolderIcon = 0;
// Set the icon index.
// If the storage is a folder, use the folder icon, otherwise
// use the icon associated with that file type.
//
if( pStorage->m_dwAttributes & WMDM_FILE_ATTR_FOLDER ) { lvitem.iImage = m_iFolderIcon; } else { TCHAR szType[MAX_PATH]; lvitem.iImage = GetShellIconIndex( pStorage->m_szName, szType, sizeof(szType)/sizeof(szType[0]) ); }
lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; lvitem.iItem = 10000; lvitem.iSubItem = 0; lvitem.pszText = pStorage->m_szName; lvitem.lParam = (LPARAM)pStorage;
// Insert the item into the listview
//
nItem = ListView_InsertItem( m_hwndDevFiles_LV, &lvitem ); if( -1 == nItem ) { return FALSE; }
// Set the size field blank for a folder, or for the file size for a file
//
ListView_SetItemText( m_hwndDevFiles_LV, nItem, 1, ( (pStorage->m_dwAttributes & WMDM_FILE_ATTR_FOLDER) ? " " : FormatBytesToSz(pStorage->m_dwSizeLow, 0, 1, sz, sizeof(sz)) ) );
// Set the description field to be the display date
//
{ SYSTEMTIME systime;
// Copy the WMDMDATETIME fields to a SYSTEMTIME structure for manipulation
//
systime.wYear = pStorage->m_DateTime.wYear; systime.wMonth = pStorage->m_DateTime.wMonth; systime.wDayOfWeek = 0; systime.wDay = pStorage->m_DateTime.wDay; systime.wHour = pStorage->m_DateTime.wHour; systime.wMinute = pStorage->m_DateTime.wMinute; systime.wSecond = pStorage->m_DateTime.wSecond; systime.wMilliseconds = 0;
ListView_SetItemText( m_hwndDevFiles_LV, nItem, 2, FormatSystemTimeToSz( &systime, sz, sizeof(sz) ) ); }
// Update the status bar with the changes resulting from the insertion of this item
//
UpdateStatusBar();
return TRUE; }
VOID CDevFiles::UpdateStatusBar( void ) { INT nCount; UINT uStrID; HTREEITEM hItem = g_cDevices.GetSelectedItem( NULL );
if( NULL == hItem ) { // If no device is selected, blank out the pane specifying the number of files
//
g_cStatus.SetTextSz( SB_PANE_DEVFILES, "" ); } else { // If a device is selected, set the statusbar pane that shows the number of files
//
nCount = ListView_GetItemCount( m_hwndDevFiles_LV );
// Get the grammatically-appropriate format string to use
//
if( nCount == 0 ) { uStrID = IDS_SB_DEVICEFILES_MANY; } else if( nCount == 1 ) { uStrID = IDS_SB_DEVICEFILES_ONE; } else { uStrID = IDS_SB_DEVICEFILES_MANY; }
// Set the text of the pane
//
g_cStatus.SetTextFormatted( SB_PANE_DEVFILES, uStrID, nCount, NULL ); } }
INT CDevFiles::GetSelectedItems( INT nItems[], INT *pnSelItems ) { INT nRet = -1; INT nNumSelItems = ListView_GetSelectedCount( m_hwndDevFiles_LV ); INT nNumItems = ListView_GetItemCount( m_hwndDevFiles_LV ); INT nItemRoom = *pnSelItems; INT i; INT iIndex;
// Initialize return parameters
//
*pnSelItems = nNumSelItems;
// If there isn't enough room for all the selected items, or if there
// aren't any selected items, return -1.
// The space needed is already in the nSelItems OUT param.
//
if( nItemRoom < nNumSelItems || 0 == nNumSelItems ) { return -1; }
// Loop thru all the items to determine whether or not they are
// selected. Fill in the OUT array with the ones that are.
//
for( i=0, iIndex=0; i < nNumItems; i++ ) { UINT uState = ListView_GetItemState( m_hwndDevFiles_LV, i, LVIS_SELECTED | LVIS_FOCUSED );
if( uState & LVIS_SELECTED ) { nItems[iIndex++] = i;
if( uState & LVIS_FOCUSED ) { // Remember which item has focus, so it can be returned to the caller
//
nRet = i; } } }
// If there are selected items, but nothing has focus, use the first selected item
//
if( nRet == -1 && nNumSelItems > 0 ) { nRet = nItems[0]; }
return nRet; }
// Is it ok to delete the currently selected files?
BOOL CDevFiles::OkToDelete() { INT nNumItems = ListView_GetItemCount( GetHwnd_LV() ); CItemData *pStorage = NULL;
// Loop thru all the items to determine whether or not they are
// selected. Enable delete if any selected file can be deleted.
//
for( int iIndex=0; iIndex < nNumItems; iIndex++ ) { if( ListView_GetItemState( GetHwnd_LV(), iIndex, LVIS_SELECTED ) ) { pStorage = (CItemData *) ListView_GetLParam( GetHwnd_LV(), iIndex ); if( pStorage && (pStorage->m_dwAttributes & WMDM_FILE_ATTR_CANDELETE) ) return TRUE; } }
return FALSE; }
/////////////////////////////////////////////////////////////////////
//
// Non-C++ functions
//
INT_PTR CALLBACK DevFiles_DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WORD wId = LOWORD((DWORD)wParam); WORD wNotifyCode = HIWORD((DWORD)wParam); static CDevFiles *cDevFiles = NULL; static HWND hwndLV = NULL;
switch( uMsg ) { case WM_INITDIALOG: cDevFiles = (CDevFiles *)lParam; hwndLV = GetDlgItem( hWnd, IDC_LV_DEVICEFILES ); break;
case WM_NOTIFY: { LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam; UINT uCode = pnmv->hdr.code;
switch( uCode ) { case LVN_BEGINDRAG: SendMessage( hwndLV, uMsg, wParam, lParam ); break; default: break; } } break;
case WM_DRM_PROGRESS: { PROGRESSNOTIFY *pNotify = (PROGRESSNOTIFY *)lParam;
switch( pNotify->dwMsg ) { case SFM_BEGIN: break;
case SFM_PROGRESS: { DWORD dwTicks = cDevFiles->m_dwWorkingTicks + pNotify->dwCurrentTicks;
cDevFiles->m_cProgress.SetPos( (INT)( dwTicks*100/cDevFiles->m_dwTotalTicks ) ); cDevFiles->m_cProgress.SetBytes( dwTicks, cDevFiles->m_dwTotalTicks ); } break;
case SFM_END: cDevFiles->m_dwWorkingTicks += pNotify->dwTotalTicks; break; }
UiYield();
// If the user cancelled the operation, tell the progress interface
//
if( cDevFiles->m_cProgress.IsCancelled() ) { // Notify progress interface
//
cDevFiles->m_pProgHelp->Cancel(); } } break;
default: break; } return 0; }
LRESULT CALLBACK WndProc_DevFiles_LV(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static CDevFiles *cDevFiles = NULL; WORD wId = LOWORD((DWORD)wParam); WORD wNotifyCode = HIWORD((DWORD)wParam);
if( NULL == cDevFiles ) { cDevFiles = (CDevFiles *) GetWindowLongPtr( hWnd, GWLP_USERDATA ); }
switch( uMsg ) { case WM_DROPFILES: return cDevFiles->OnDropFiles( hWnd, wParam, lParam );
case WM_KEYDOWN: if( wParam == VK_DELETE ) { SendMessage( g_hwndMain, WM_DRM_DELETEITEM, 0, 0 ); return 0; } break;
case WM_CONTEXTMENU : { HMENU hMenuAll; HMENU hMenuStorage;
hMenuAll = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT_MENU)); hMenuStorage = GetSubMenu(hMenuAll, 1);
// Enable/disable delete
if( !cDevFiles->OkToDelete() ) { EnableMenuItem( hMenuStorage, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED ); }
TrackPopupMenu( hMenuStorage, TPM_LEFTALIGN | TPM_RIGHTBUTTON, LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
DestroyMenu(hMenuAll); break; }
case WM_COMMAND : { switch (wParam) { case IDM_PROPERTIES : { // Display propeties dialog for this storage
INT nNumItems = ListView_GetItemCount( hWnd ); CItemData *pStorage = NULL;
// Get the storage of the item with focus.
//
for( int iIndex=0; iIndex < nNumItems; iIndex++ ) { if( ListView_GetItemState( hWnd, iIndex, LVIS_FOCUSED ) ) { pStorage = (CItemData *) ListView_GetLParam( hWnd, iIndex ); break; } } // Display the properties dialog
if( pStorage ) { DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_PROPERTIES_STORAGE), g_hwndMain, StorageProp_DlgProc, (LPARAM)pStorage ); } break; } case IDM_DELETE : { // Pass delete message on to main window
PostMessage( g_hwndMain, uMsg, wParam, lParam ); } } }
default: break; }
return CallWindowProc( cDevFiles->m_wndprocDevFiles_LV, hWnd, uMsg, wParam, lParam ); }
|