1446 lines
30 KiB
C++
1446 lines
30 KiB
C++
//
|
|
// Copyright 2001 - Microsoft Corporation
|
|
//
|
|
//
|
|
// Created By:
|
|
// Geoff Pease (GPease) 23-JAN-2001
|
|
//
|
|
// Maintained By:
|
|
// Geoff Pease (GPease) 23-JAN-2001
|
|
//
|
|
#include "pch.h"
|
|
#include "DocProp.h"
|
|
#include "DefProp.h"
|
|
#include "IEditVariantsInPlace.h"
|
|
#include "PropertyCacheItem.h"
|
|
#include "PropertyCache.h"
|
|
#include "AdvancedDlg.h"
|
|
#include "shutils.h"
|
|
#include "WMUser.h"
|
|
#include "IEditVariantsInPlace.h"
|
|
#include "EditTypeItem.h"
|
|
#pragma hdrstop
|
|
|
|
DEFINE_THISCLASS( "CAdvancedDlg" )
|
|
|
|
//
|
|
// This value is the offset of images in the bitmap representing the
|
|
// icons when multiple documents have been selected.
|
|
//
|
|
#define MULTIDOC_IMAGE_OFFSET_VALUE 2
|
|
|
|
// ************************************************************************
|
|
//
|
|
// Constructor / Destructor
|
|
//
|
|
// ************************************************************************
|
|
|
|
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// A new CAdvancedDlg was created successfully.
|
|
//
|
|
// E_OUTOFMEMORY
|
|
// Out of memory.
|
|
//
|
|
// other HRESULTs.
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::CreateInstance(
|
|
CAdvancedDlg ** pAdvDlgOut
|
|
, HWND hwndParentIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
|
|
Assert( pAdvDlgOut != NULL );
|
|
|
|
CAdvancedDlg * pthis = new CAdvancedDlg;
|
|
if ( pthis != NULL )
|
|
{
|
|
hr = THR( pthis->Init( hwndParentIn ) );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
*pAdvDlgOut = pthis;
|
|
(*pAdvDlgOut)->AddRef( );
|
|
}
|
|
|
|
pthis->Release( );
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
}
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
CAdvancedDlg::CAdvancedDlg( void )
|
|
: _cRef( 1 )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
Assert( 1 == _cRef );
|
|
Assert( NULL == _hwndParent );
|
|
Assert( NULL == _hdlg );
|
|
|
|
Assert( NULL == _hwndList );
|
|
|
|
Assert( NULL == _pEdit );
|
|
Assert( NULL == _pItem );
|
|
|
|
InterlockedIncrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
}
|
|
|
|
//
|
|
// Description:
|
|
// Intializes the instance of the class. Put things that can
|
|
// fail into this method.
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::Init(
|
|
HWND hwndParentIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
_hwndParent = hwndParentIn;
|
|
|
|
// IUnknown stuff
|
|
Assert( _cRef == 1 );
|
|
|
|
//
|
|
// Initialize the common controls
|
|
//
|
|
|
|
INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX)
|
|
, ICC_LISTVIEW_CLASSES | ICC_USEREX_CLASSES | ICC_DATE_CLASSES
|
|
};
|
|
|
|
BOOL b = TBOOL( InitCommonControlsEx( &iccx ) );
|
|
if ( !b )
|
|
goto ErrorGLE;
|
|
|
|
//
|
|
// Create the dialog
|
|
//
|
|
|
|
_hdlg = CreateDialogParam( g_hInstance
|
|
, MAKEINTRESOURCE(IDD_ADVANCEDVIEW)
|
|
, _hwndParent
|
|
, DlgProc
|
|
, (LPARAM) this
|
|
);
|
|
if ( NULL == _hdlg )
|
|
goto ErrorGLE;
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
|
|
ErrorGLE:
|
|
{
|
|
DWORD dwErr = TW32( GetLastError( ) );
|
|
hr = HRESULT_FROM_WIN32( dwErr );
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
CAdvancedDlg::~CAdvancedDlg( )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
if ( NULL != _pEdit )
|
|
{
|
|
_pEdit->Release( );
|
|
}
|
|
|
|
if ( NULL != _hdlg )
|
|
{
|
|
DestroyWindow( _hdlg );
|
|
}
|
|
|
|
InterlockedDecrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
}
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
// ************************************************************************
|
|
|
|
|
|
//
|
|
// QueryInterface
|
|
//
|
|
STDMETHODIMP
|
|
CAdvancedDlg::QueryInterface(
|
|
REFIID riid,
|
|
LPVOID *ppv
|
|
)
|
|
{
|
|
TraceQIFunc( riid, ppv );
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if ( IsEqualIID( riid, __uuidof(IUnknown) ) )
|
|
{
|
|
*ppv = static_cast< IUnknown * >( this );
|
|
hr = S_OK;
|
|
}
|
|
#if 0
|
|
else if ( IsEqualIID( riid, __uuidof(IShellExtInit) ) )
|
|
{
|
|
*ppv = TraceInterface( __THISCLASS__, IShellExtInit, this, 0 );
|
|
hr = S_OK;
|
|
}
|
|
#endif
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
((IUnknown*) *ppv)->AddRef( );
|
|
}
|
|
|
|
QIRETURN( hr, riid );
|
|
}
|
|
|
|
//
|
|
// AddRef
|
|
//
|
|
STDMETHODIMP_(ULONG)
|
|
CAdvancedDlg::AddRef( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
_cRef ++; // apartment
|
|
|
|
RETURN( _cRef );
|
|
}
|
|
|
|
//
|
|
// Release
|
|
//
|
|
STDMETHODIMP_(ULONG)
|
|
CAdvancedDlg::Release( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
_cRef --; // apartment
|
|
|
|
if ( 0 != _cRef )
|
|
RETURN( _cRef );
|
|
|
|
delete this;
|
|
|
|
RETURN( 0 );
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
//
|
|
// Dialog Proc and Property Sheet Callback
|
|
//
|
|
// ***************************************************************************
|
|
|
|
|
|
//
|
|
// DlgProc
|
|
//
|
|
INT_PTR CALLBACK
|
|
CAdvancedDlg::DlgProc(
|
|
HWND hDlgIn
|
|
, UINT uMsgIn
|
|
, WPARAM wParam
|
|
, LPARAM lParam
|
|
)
|
|
{
|
|
// Don't do TraceFunc because every mouse movement will cause this function to be called.
|
|
WndMsg( hDlgIn, uMsgIn, wParam, lParam );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
CAdvancedDlg * pPage = (CAdvancedDlg *) GetWindowLongPtr( hDlgIn, DWLP_USER );
|
|
|
|
if ( uMsgIn == WM_INITDIALOG )
|
|
{
|
|
SetWindowLongPtr( hDlgIn, DWLP_USER, lParam );
|
|
pPage = (CAdvancedDlg *) lParam ;
|
|
pPage->_hdlg = hDlgIn;
|
|
}
|
|
|
|
if ( pPage != NULL )
|
|
{
|
|
Assert( hDlgIn == pPage->_hdlg );
|
|
|
|
switch( uMsgIn )
|
|
{
|
|
case WM_INITDIALOG:
|
|
lr = pPage->OnInitDialog( );
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
lr = pPage->OnCommand( HIWORD(wParam), LOWORD(wParam), LPARAM(lParam) );
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
lr = pPage->OnNotify( (int) wParam, (LPNMHDR) lParam );
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
|
lr = SendMessage( pPage->_hwndList, WM_SETFOCUS, wParam, lParam );
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
SetWindowLongPtr( hDlgIn, DWLP_USER, NULL );
|
|
lr = pPage->OnDestroy( );
|
|
break;
|
|
|
|
case WM_HELP:
|
|
lr = pPage->OnHelp( (LPHELPINFO) lParam );
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
lr = pPage->OnContextMenu( (HWND) wParam, LOWORD(lParam), HIWORD(lParam) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return lr;
|
|
}
|
|
|
|
|
|
//
|
|
// ListViewSubProc
|
|
//
|
|
LRESULT CALLBACK
|
|
CAdvancedDlg::ListViewSubclassProc(
|
|
HWND hwndIn
|
|
, UINT uMsgIn
|
|
, WPARAM wParam
|
|
, LPARAM lParam
|
|
, UINT_PTR uIdSubclassIn
|
|
, DWORD_PTR dwRefDataIn
|
|
)
|
|
{
|
|
// Don't do TraceFunc because every mouse movement will cause this function to be called.
|
|
WndMsg( hwndIn, uMsgIn, wParam, lParam );
|
|
|
|
LRESULT lr = FALSE;
|
|
CAdvancedDlg * pPage = (CAdvancedDlg *) dwRefDataIn;
|
|
|
|
Assert( NULL != pPage );
|
|
Assert( hwndIn == pPage->_hwndList );
|
|
Assert( IDC_PROPERTIES == uIdSubclassIn );
|
|
|
|
switch( uMsgIn )
|
|
{
|
|
case WM_COMMAND:
|
|
return pPage->List_OnCommand( LOWORD(wParam), HIWORD(wParam), lParam );
|
|
|
|
case WM_NOTIFY:
|
|
return pPage->List_OnNotify( (int) wParam, (LPNMHDR) lParam );
|
|
|
|
case WM_VSCROLL:
|
|
return pPage->List_OnVertScroll( LOWORD(wParam), HIWORD(wParam), (HWND) lParam );
|
|
|
|
case WM_HSCROLL:
|
|
return pPage->List_OnHornScroll( LOWORD(wParam), HIWORD(wParam), (HWND) lParam );
|
|
|
|
case WM_CHAR:
|
|
return pPage->List_OnChar( (UINT) wParam, lParam );
|
|
|
|
case WM_KEYDOWN:
|
|
return pPage->List_OnKeyDown( (UINT) wParam, lParam );
|
|
}
|
|
|
|
return DefSubclassProc( hwndIn, uMsgIn, wParam, lParam );
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
//
|
|
// Private methods
|
|
//
|
|
// ***************************************************************************
|
|
|
|
|
|
//
|
|
// WM_INITDIALOG handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnInitDialog( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
int iSize;
|
|
LVCOLUMN lvc;
|
|
TCHAR szTitle[ 64 ]; // random
|
|
ULONG idxFolder;
|
|
|
|
HIMAGELIST hil;
|
|
|
|
LRESULT lr = TRUE; // set the focus
|
|
|
|
Assert( NULL != _hdlg ); // this should have been initialized in the DlgProc.
|
|
|
|
_hwndList = GetDlgItem( _hdlg, IDC_PROPERTIES );
|
|
TBOOL( NULL != _hwndList );
|
|
|
|
//
|
|
// Enable ListView for Grouping mode.
|
|
//
|
|
|
|
SetWindowLongPtr( _hwndList, GWL_STYLE, GetWindowLongPtr( _hwndList, GWL_STYLE ) | LVS_AUTOARRANGE | LVS_SHOWSELALWAYS);
|
|
ListView_SetExtendedListViewStyle( _hwndList, LVS_EX_FULLROWSELECT );
|
|
ListView_EnableGroupView( _hwndList, TRUE );
|
|
|
|
//
|
|
// Add the image list
|
|
//
|
|
|
|
hil = ImageList_LoadImage( g_hInstance
|
|
, MAKEINTRESOURCE(IDB_TREE_IMAGELIST)
|
|
, 16
|
|
, 0
|
|
, RGB(255,0,255)
|
|
, IMAGE_BITMAP
|
|
, LR_SHARED
|
|
);
|
|
|
|
hil = ListView_SetImageList( _hwndList
|
|
, hil
|
|
, LVSIL_SMALL
|
|
);
|
|
Assert( NULL == hil ); // there shouldn't have been a previous image list.
|
|
|
|
//
|
|
// Setup up common values.
|
|
//
|
|
|
|
lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.pszText = szTitle;
|
|
|
|
//
|
|
// Add Column 0
|
|
//
|
|
|
|
lvc.iSubItem = 0;
|
|
|
|
iSize = LoadString( g_hInstance, IDS_PROPERTY_HEADER_ITEM, szTitle, ARRAYSIZE(szTitle) );
|
|
AssertMsg( 0 != iSize, "Missing string resource?" );
|
|
|
|
ListView_InsertColumn( _hwndList, 0, &lvc );
|
|
|
|
//
|
|
// Add Column 1
|
|
//
|
|
|
|
lvc.iSubItem = 1;
|
|
|
|
iSize = LoadString( g_hInstance, IDS_VALUE_HEADER_ITEM, szTitle, ARRAYSIZE(szTitle) );
|
|
AssertMsg( 0 != iSize, "Missing string resource?" );
|
|
|
|
ListView_InsertColumn( _hwndList, 1, &lvc );
|
|
|
|
//
|
|
// Add the groups - In the end, if a group contains no items, the group
|
|
// header will not be shown.
|
|
//
|
|
|
|
for ( idxFolder = 0; NULL != g_rgTopLevelFolders[ idxFolder ].pPFID; idxFolder ++ )
|
|
{
|
|
//
|
|
// Add the property folder as a group item.
|
|
//
|
|
|
|
int iRet;
|
|
WCHAR szBuf[ 256 ]; // random
|
|
|
|
iRet = LoadString( g_hInstance, g_rgTopLevelFolders[ idxFolder ].nIDStringRes, szBuf, ARRAYSIZE(szBuf) );
|
|
AssertMsg( 0 != iRet, "Missing resource?" );
|
|
if ( 0 == iRet )
|
|
continue;
|
|
|
|
LVGROUP lvg;
|
|
|
|
lvg.cbSize = sizeof(LVGROUP);
|
|
lvg.mask = LVGF_HEADER | LVGF_GROUPID;
|
|
lvg.iGroupId = idxFolder;
|
|
lvg.pszHeader = szBuf;
|
|
|
|
LRESULT iItem = ListView_InsertGroup( _hwndList, -1, &lvg );
|
|
TBOOL( -1 != iItem );
|
|
}
|
|
|
|
//
|
|
// Subclass the listview
|
|
//
|
|
|
|
TBOOL( SetWindowSubclass( _hwndList, ListViewSubclassProc, IDC_PROPERTIES, (DWORD_PTR) this ) );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_COMMAND handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnCommand(
|
|
WORD wCodeIn
|
|
, WORD wCtlIn
|
|
, LPARAM lParam
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
switch ( wCtlIn )
|
|
{
|
|
case IDC_SIMPLE:
|
|
if ( BN_CLICKED == wCodeIn )
|
|
{
|
|
THR( (HRESULT) SendMessage( _hwndParent, WMU_TOGGLE, 0, 0 ) );
|
|
}
|
|
break;
|
|
}
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_NOTIFY handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnNotify(
|
|
int iCtlIdIn
|
|
, LPNMHDR pnmhIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
switch( pnmhIn->code )
|
|
{
|
|
case NM_CLICK:
|
|
lr = OnNotifyClick( (LPNMITEMACTIVATE) pnmhIn );
|
|
break;
|
|
}
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// NM_CLICK handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnNotifyClick(
|
|
LPNMITEMACTIVATE pnmIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = S_FALSE;
|
|
|
|
INT iItem;
|
|
|
|
Assert( NULL != pnmIn );
|
|
|
|
if ( -1 == pnmIn->iItem )
|
|
{
|
|
LVHITTESTINFO lvhti;
|
|
|
|
lvhti.pt = pnmIn->ptAction;
|
|
|
|
iItem = ListView_SubItemHitTest( _hwndList, &lvhti );
|
|
if ( -1 == iItem )
|
|
goto Cleanup;
|
|
|
|
if ( 1 != lvhti.iSubItem )
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
if ( 1 != pnmIn->iSubItem )
|
|
goto Cleanup;
|
|
|
|
iItem = pnmIn->iItem;
|
|
}
|
|
|
|
STHR( CreateControlForProperty( iItem ) );
|
|
|
|
Cleanup:
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_NOTIFY handler for the ListView Subclass
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::List_OnNotify(
|
|
int iCtlIdIn
|
|
, LPNMHDR pnmhIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr;
|
|
|
|
switch( pnmhIn->code )
|
|
{
|
|
case NM_KILLFOCUS:
|
|
if ( NULL != _pEdit )
|
|
{
|
|
STHR( PersistControlInProperty( ) );
|
|
_pEdit->Release( );
|
|
_pEdit = NULL;
|
|
}
|
|
break;
|
|
}
|
|
|
|
lr = DefSubclassProc( _hwndList, WM_NOTIFY, (WPARAM) iCtlIdIn, (LPARAM) pnmhIn );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_COMMAND handler for the ListView Subclass
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::List_OnCommand(
|
|
WORD wCtlIn
|
|
, WORD wCodeIn
|
|
, LPARAM lParam
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
switch ( wCtlIn )
|
|
{
|
|
case IDC_INPLACEEDIT:
|
|
if ( EN_KILLFOCUS == wCodeIn || CBN_KILLFOCUS == wCodeIn )
|
|
{
|
|
if ( NULL != _pEdit )
|
|
{
|
|
STHR( PersistControlInProperty( ) );
|
|
_pEdit->Release( );
|
|
_pEdit = NULL;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
lr = DefSubclassProc( _hwndList, WM_COMMAND, MAKEWPARAM( wCtlIn, wCodeIn ), lParam );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_CHAR handler for ListView Subclass
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::List_OnChar(
|
|
UINT uKeyCodeIn
|
|
, LPARAM lParam
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
#if 0
|
|
SHORT sRepeatCount = ( lParam & 0xFFFF );
|
|
SHORT sScanCode = ( lParam & 0xF0000 ) >> 16;
|
|
BOOL fExtended = ( lParam & 0x100000 ) != 0;
|
|
BOOL fContext = ( lParam & 0x40000000 ) != 0;
|
|
BOOL fTransition = ( lParam & 0x80000000 ) != 0;
|
|
#endif
|
|
|
|
INT iItem = ListView_GetSelectionMark( _hwndList );
|
|
if ( -1 == iItem )
|
|
return DefSubclassProc( _hwndList, WM_KEYDOWN, uKeyCodeIn, lParam );
|
|
|
|
hr = STHR( CreateControlForProperty( iItem ) );
|
|
if ( S_OK == hr )
|
|
{
|
|
HWND hwnd = GetFocus( );
|
|
if ( _hwndList != hwnd )
|
|
{
|
|
lr = SendMessage( hwnd, WM_CHAR, (WPARAM) uKeyCodeIn, lParam );
|
|
}
|
|
}
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_KEYDOWN handler for ListView Subclass
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::List_OnKeyDown(
|
|
UINT uKeyCodeIn
|
|
, LPARAM lParam
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
#if 0
|
|
SHORT sRepeatCount = ( lParam & 0xFFFF );
|
|
SHORT sScanCode = ( lParam & 0xF0000 ) >> 16;
|
|
BOOL fExtended = ( lParam & 0x100000 ) != 0;
|
|
BOOL fContext = ( lParam & 0x40000000 ) != 0;
|
|
BOOL fTransition = ( lParam & 0x80000000 ) != 0;
|
|
#endif
|
|
|
|
switch ( uKeyCodeIn )
|
|
{
|
|
case VK_F2:
|
|
{
|
|
INT iItem = ListView_GetSelectionMark( _hwndList );
|
|
if ( -1 != iItem )
|
|
{
|
|
STHR( CreateControlForProperty( iItem ) );
|
|
}
|
|
}
|
|
// fall thru
|
|
|
|
default:
|
|
lr = DefSubclassProc( _hwndList, WM_KEYDOWN, (WPARAM) uKeyCodeIn, lParam );
|
|
break;
|
|
}
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_VSCROLL handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::List_OnVertScroll(
|
|
WORD wCodeIn
|
|
, WORD wPosIn
|
|
, HWND hwndFromIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
//
|
|
// Cancel any editting that's going on. This matches the behavior of
|
|
// DefView.
|
|
//
|
|
|
|
if ( NULL != _pEdit )
|
|
{
|
|
_pEdit->Release( );
|
|
_pEdit = NULL;
|
|
}
|
|
|
|
LRESULT lr = DefSubclassProc( _hwndList, WM_VSCROLL, MAKEWPARAM( wCodeIn, wPosIn ), (LPARAM) hwndFromIn );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// WM_HCSCROLL handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::List_OnHornScroll(
|
|
WORD wCodeIn
|
|
, WORD wPosIn
|
|
, HWND hwndFromIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
//
|
|
// Cancel any editting that's going on. This matches the behavior of
|
|
// DefView.
|
|
//
|
|
|
|
if ( NULL != _pEdit )
|
|
{
|
|
_pEdit->Release( );
|
|
_pEdit = NULL;
|
|
}
|
|
|
|
LRESULT lr = DefSubclassProc( _hwndList, WM_HSCROLL, MAKEWPARAM( wCodeIn, wPosIn ), (LPARAM) hwndFromIn );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
|
|
//
|
|
// WM_DESTROY handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnDestroy( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
//
|
|
// Description:
|
|
// Creates and initializes the control to edit the property selected.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Successfully created and initialized control.
|
|
//
|
|
// S_FALSE
|
|
// Read-only property - no control created.
|
|
//
|
|
// E_FAIL
|
|
// Failed to create control.
|
|
//
|
|
// other HRESULTs
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::CreateControlForProperty(
|
|
INT iItemIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
BOOL bRet;
|
|
CLSID clsidControl;
|
|
RECT rectItem;
|
|
RECT rectList;
|
|
UINT uCodePage;
|
|
LVITEM lvi;
|
|
DEFVAL * pDefVals;
|
|
int iImage;
|
|
|
|
PROPVARIANT * ppropvar;
|
|
|
|
IPropertyUI * ppui = NULL;
|
|
|
|
lvi.iItem = iItemIn;
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iSubItem = 0;
|
|
|
|
bRet = TBOOL( ListView_GetItem( _hwndList, &lvi ) );
|
|
if ( !bRet )
|
|
goto ControlFailed;
|
|
|
|
_pItem = (CPropertyCacheItem *) lvi.lParam;
|
|
AssertMsg( NULL != _pItem, "Programming error - how did this item get added?" );
|
|
|
|
hr = THR( _pItem->GetImageIndex( &iImage ) );
|
|
if ( S_OK != hr )
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Don't invoke the "Edit control" if the property is read-only.
|
|
//
|
|
|
|
if ( PTI_PROP_READONLY == iImage )
|
|
{
|
|
hr = S_FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = STHR( _pItem->GetControlCLSID( &clsidControl ) );
|
|
if ( S_OK != hr )
|
|
goto Cleanup;
|
|
|
|
hr = THR( _pItem->GetCodePage( &uCodePage ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = STHR( _pItem->GetPropertyUIHelper( &ppui ) );
|
|
if ( S_OK != hr )
|
|
goto Cleanup;
|
|
|
|
hr = THR( _pItem->GetPropertyValue( &ppropvar ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = STHR( _pItem->GetStateStrings( &pDefVals ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
Assert( NULL == _pEdit );
|
|
hr = THR( CoCreateInstance( clsidControl, NULL, CLSCTX_INPROC, TYPESAFEPARAMS(_pEdit) ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
bRet = TBOOL( ListView_GetSubItemRect( _hwndList, lvi.iItem, 1, LVIR_BOUNDS , &rectItem) );
|
|
if ( !bRet )
|
|
goto ControlFailed;
|
|
|
|
//
|
|
// Make sure the rect is only in the visible region of the list view.
|
|
//
|
|
|
|
bRet = TBOOL( GetWindowRect( _hwndList, &rectList ) );
|
|
if ( !bRet )
|
|
goto ControlFailed;
|
|
|
|
if ( rectItem.right > rectList.right - rectList.left )
|
|
{
|
|
rectItem.right = rectList.right - rectList.left;
|
|
}
|
|
|
|
if ( rectItem.left < 0 )
|
|
{
|
|
rectItem.left = 0;
|
|
}
|
|
|
|
hr = THR( _pEdit->Initialize( _hwndList, uCodePage, &rectItem, ppui, ppropvar, pDefVals ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
if ( NULL != ppui )
|
|
{
|
|
ppui->Release( );
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
ControlFailed:
|
|
hr = THR( E_FAIL );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Description:
|
|
// Informs the control, _pEdit, to persist its value into the variant.
|
|
//
|
|
// Return Value:
|
|
// S_OK
|
|
// Success! Property value updated.
|
|
//
|
|
// S_FALSE
|
|
// _pEdit was NULL.
|
|
//
|
|
// other HRESULTs.
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::PersistControlInProperty( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
LVITEM lvi;
|
|
LVFINDINFO lvfi;
|
|
VARTYPE vt;
|
|
|
|
PROPVARIANT * ppropvar;
|
|
|
|
if ( NULL == _pEdit )
|
|
goto NoEditControlEditting;
|
|
|
|
lvfi.flags = LVFI_PARAM;
|
|
lvfi.lParam = (LPARAM) _pItem;
|
|
lvfi.vkDirection = VK_DOWN;
|
|
|
|
lvi.iItem = ListView_FindItem( _hwndList, -1, &lvfi );
|
|
if ( -1 == lvi.iItem )
|
|
goto NoEditControlEditting;
|
|
|
|
hr = THR( _pItem->GetPropertyValue( &ppropvar ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
switch( ppropvar->vt )
|
|
{
|
|
case VT_EMPTY:
|
|
case VT_NULL:
|
|
{
|
|
hr = THR( _pItem->GetDefaultVarType( &vt ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
vt = ppropvar->vt;
|
|
break;
|
|
}
|
|
|
|
PropVariantInit( ppropvar );
|
|
|
|
hr = STHR( _pEdit->Persist( vt, ppropvar ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
if ( S_OK == hr )
|
|
{
|
|
hr = THR( _pItem->MarkDirty( ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( _pItem->GetPropertyStringValue( (LPCWSTR *) &lvi.pszText ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
lvi.mask = LVIF_TEXT;
|
|
lvi.iSubItem = 1;
|
|
|
|
BOOL bRet = TBOOL( ListView_SetItem( _hwndList, &lvi ) );
|
|
if ( !bRet )
|
|
goto NoEditControlEditting;
|
|
|
|
//
|
|
// Tell the property sheet to activate the "Apply" button.
|
|
//
|
|
|
|
PropSheet_Changed( GetParent( _hwndParent ), _hwndParent );
|
|
}
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
|
|
NoEditControlEditting:
|
|
hr = THR( S_FALSE );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// WM_HELP handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnHelp(
|
|
LPHELPINFO pHelpInfoIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
THR( DoHelp( (HWND) pHelpInfoIn->hItemHandle, pHelpInfoIn->MousePos.x, pHelpInfoIn->MousePos.y, HELP_WM_HELP ) );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
|
|
//
|
|
// WM_CONTEXTMENU handler
|
|
//
|
|
LRESULT
|
|
CAdvancedDlg::OnContextMenu(
|
|
HWND hwndIn
|
|
, int iXIn
|
|
, int iYIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
LRESULT lr = FALSE;
|
|
|
|
THR( DoHelp( hwndIn, iXIn, iYIn, HELP_CONTEXTMENU ) );
|
|
|
|
RETURN( lr );
|
|
}
|
|
|
|
|
|
//
|
|
// Description:
|
|
// Handles locating the item within the list view and construct
|
|
// a fake IDC to IDH to display the correct help text for the
|
|
// item.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Success.
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::DoHelp(
|
|
HWND hwndIn
|
|
, int iXIn
|
|
, int iYIn
|
|
, UINT uCommandIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
HWND hwndList = GetDlgItem( _hdlg, IDC_PROPERTIES );
|
|
|
|
if ( hwndList == hwndIn )
|
|
{
|
|
BOOL bRet;
|
|
HRESULT hr;
|
|
int iItem;
|
|
RECT rcList;
|
|
LVITEM lvi;
|
|
LPCWSTR pszHelpFile; // don't free
|
|
UINT uHelpId;
|
|
|
|
CPropertyCacheItem * pItem;
|
|
|
|
LVHITTESTINFO lvhti;
|
|
|
|
DWORD mapIDStoIDH[ ] = { IDC_PROPERTIES, 0, 0, 0 };
|
|
|
|
bRet = TBOOL( GetWindowRect( hwndList, &rcList ) );
|
|
if ( !bRet )
|
|
goto Cleanup;
|
|
|
|
lvhti.pt.x = iXIn - rcList.left;
|
|
lvhti.pt.y = iYIn - rcList.top;
|
|
lvhti.flags = LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON;
|
|
|
|
iItem = ListView_HitTest( hwndList, &lvhti );
|
|
if ( -1 == iItem )
|
|
goto Cleanup; // item not found.
|
|
|
|
lvi.iItem = iItem;
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iSubItem = 0;
|
|
|
|
bRet = TBOOL( ListView_GetItem( _hwndList, &lvi ) );
|
|
if ( !bRet )
|
|
goto Cleanup;
|
|
|
|
pItem = (CPropertyCacheItem *) lvi.lParam;
|
|
AssertMsg( NULL != pItem, "Programming error - how did this item get added?" );
|
|
|
|
hr = THR( pItem->GetPropertyHelpInfo( &pszHelpFile, &uHelpId ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
mapIDStoIDH[ 1 ] = uHelpId;
|
|
|
|
TBOOL( WinHelp( hwndIn, pszHelpFile, uCommandIn, (DWORD_PTR)(LPSTR) mapIDStoIDH ) );
|
|
}
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
//
|
|
// Public methods
|
|
//
|
|
// ***************************************************************************
|
|
|
|
|
|
//
|
|
// Description:
|
|
// Hides the dialog.
|
|
//
|
|
// Return Value:
|
|
// S_OK
|
|
// Success!
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::Hide( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
|
|
ShowWindow( _hdlg, SW_HIDE );
|
|
hr = S_OK;
|
|
|
|
HRETURN( hr );
|
|
}
|
|
|
|
//
|
|
// Description:
|
|
// Shows the dialog.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Success!
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::Show( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
ShowWindow( _hdlg, SW_SHOW );
|
|
SetFocus( _hdlg );
|
|
|
|
HRETURN( hr );
|
|
}
|
|
|
|
//
|
|
// Description:
|
|
// Populates the properties of the dialog.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Success!
|
|
//
|
|
// E_INVALIDARG
|
|
// ppcIn is NULL.
|
|
//
|
|
// other HRESULTs.
|
|
//
|
|
HRESULT
|
|
CAdvancedDlg::PopulateProperties(
|
|
CPropertyCache * ppcIn
|
|
, DWORD dwDocTypeIn
|
|
, BOOL fMultipleIn
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr;
|
|
RECT rect;
|
|
LVCOLUMN lvc;
|
|
BOOL bRet;
|
|
LVITEM lvi;
|
|
ULONG idxFolder;
|
|
ULONG idxProperty;
|
|
|
|
CPropertyCacheItem * pItem;
|
|
|
|
int iItem = 0;
|
|
|
|
//
|
|
// Check parameters
|
|
//
|
|
|
|
if ( NULL == ppcIn )
|
|
{
|
|
ReplaceListViewWithString( IDS_NOPROPERTIES_CAPTION );
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
|
|
_fMultipleSources = fMultipleIn;
|
|
|
|
//
|
|
// Clear out the previous list view contents.
|
|
//
|
|
|
|
TBOOL( ListView_DeleteAllItems( _hwndList ) );
|
|
|
|
//
|
|
// See if we have any properties to show.
|
|
//
|
|
|
|
hr = STHR( ppcIn->GetNextItem( NULL, &pItem ) );
|
|
if ( S_OK == hr )
|
|
{
|
|
//
|
|
// Walk the default property list and add items that match this property
|
|
// folder to listview.
|
|
//
|
|
// If the SHIFT key is down, all properties retrieved and added will be
|
|
// shown (if possible).
|
|
//
|
|
|
|
for ( idxProperty = 0; NULL != g_rgDefPropertyItems[ idxProperty ].pszName; idxProperty ++ )
|
|
{
|
|
if ( !( g_rgDefPropertyItems[ idxProperty ].dwSrcType & dwDocTypeIn )
|
|
&& !( GetKeyState( VK_SHIFT ) < 0 )
|
|
)
|
|
{
|
|
continue; // property doesn't apply
|
|
}
|
|
|
|
//
|
|
// Search the property cache for the entry.
|
|
//
|
|
|
|
hr = STHR( ppcIn->FindItemEntry( g_rgDefPropertyItems[ idxProperty ].pFmtID
|
|
, g_rgDefPropertyItems[ idxProperty ].propID
|
|
, &pItem
|
|
) );
|
|
if ( S_OK != hr )
|
|
continue; // property not found... skip it
|
|
|
|
Assert ( NULL != pItem ); // paranoid
|
|
|
|
//
|
|
// Find the group that the property belongs too.
|
|
//
|
|
|
|
for ( idxFolder = 0; NULL != g_rgTopLevelFolders[ idxFolder ].pPFID; idxFolder ++ )
|
|
{
|
|
if ( *g_rgDefPropertyItems[ idxProperty ].ppfid == *g_rgTopLevelFolders[ idxFolder ].pPFID )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
AssertMsg( NULL != g_rgTopLevelFolders[ idxFolder ].pPFID, "Missing folder for listed property. Check DOCPROP.CPP." );
|
|
|
|
//
|
|
// Add the property name below the group
|
|
//
|
|
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_GROUPID;
|
|
lvi.iSubItem = 0;
|
|
lvi.iItem = iItem;
|
|
lvi.iGroupId = idxFolder;
|
|
lvi.lParam = (LPARAM) pItem;
|
|
|
|
hr = THR( pItem->GetImageIndex( &lvi.iImage ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
lvi.iImage = 0;
|
|
}
|
|
else
|
|
{
|
|
if ( _fMultipleSources )
|
|
{
|
|
lvi.iImage += MULTIDOC_IMAGE_OFFSET_VALUE;
|
|
}
|
|
}
|
|
|
|
hr = THR( pItem->GetPropertyTitle( (LPCWSTR *) &lvi.pszText ) );
|
|
if ( FAILED( hr ) )
|
|
continue;
|
|
|
|
iItem = ListView_InsertItem( _hwndList, &lvi );
|
|
if ( -1 == iItem )
|
|
continue;
|
|
|
|
//
|
|
// Now add the property value.
|
|
//
|
|
|
|
lvi.mask = LVIF_TEXT;
|
|
lvi.iItem = iItem;
|
|
lvi.iSubItem = 1;
|
|
|
|
hr = THR( pItem->GetPropertyStringValue( (LPCWSTR *) &lvi.pszText ) );
|
|
if ( FAILED( hr ) )
|
|
continue;
|
|
|
|
bRet = TBOOL( ListView_SetItem( _hwndList, &lvi ) );
|
|
if ( !bRet )
|
|
continue;
|
|
|
|
iItem ++;
|
|
}
|
|
|
|
//
|
|
// Give the first item focus
|
|
//
|
|
|
|
ListView_SetItemState( _hwndList, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED );
|
|
}
|
|
|
|
if ( 0 == iItem )
|
|
{
|
|
if ( _fMultipleSources )
|
|
{
|
|
ReplaceListViewWithString( IDS_NOCOMMONS_CAPTION );
|
|
}
|
|
else
|
|
{
|
|
ReplaceListViewWithString( IDS_NOPROPERTIES_CAPTION );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Auto-adjust the column widths making sure that the first column doesn't
|
|
// make itself too big.
|
|
//
|
|
|
|
TBOOL( ListView_SetColumnWidth( _hwndList, 0, LVSCW_AUTOSIZE_USEHEADER ) );
|
|
|
|
bRet = TBOOL( GetClientRect( _hwndList, &rect ) );
|
|
if ( bRet )
|
|
{
|
|
lvc.mask = LVCF_WIDTH;
|
|
bRet = TBOOL( ListView_GetColumn( _hwndList, 0, &lvc ) );
|
|
if ( bRet )
|
|
{
|
|
int iSize = rect.right / 2;
|
|
|
|
if ( lvc.cx > iSize )
|
|
{
|
|
TBOOL( ListView_SetColumnWidth( _hwndList, 0, iSize ) );
|
|
TBOOL( ListView_SetColumnWidth( _hwndList, 1, iSize ) );
|
|
}
|
|
else
|
|
{
|
|
TBOOL( ListView_SetColumnWidth( _hwndList, 1, rect.right - lvc.cx ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !bRet )
|
|
{
|
|
TBOOL( ListView_SetColumnWidth( _hwndList, 1, LVSCW_AUTOSIZE_USEHEADER ) );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
}
|
|
|
|
|
|
//
|
|
// Description:
|
|
// Hides the list view control and displays a STATIC window with
|
|
// the text found in the string resource idsIn.
|
|
//
|
|
void
|
|
CAdvancedDlg::ReplaceListViewWithString( int idsIn )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
int iRet;
|
|
RECT rc;
|
|
WCHAR szCaption[ 255 ]; // random
|
|
|
|
iRet = LoadString( g_hInstance, idsIn, szCaption, ARRAYSIZE(szCaption) );
|
|
AssertMsg( iRet, "Missing string resource?" );
|
|
|
|
ShowWindow( _hwndList, SW_HIDE );
|
|
TBOOL( GetWindowRect( _hwndList, &rc ) );
|
|
iRet = MapWindowRect( HWND_DESKTOP, _hdlg, &rc );
|
|
TBOOL( 0 != iRet );
|
|
|
|
HWND hwnd = CreateWindow( WC_STATIC
|
|
, szCaption
|
|
, WS_CHILD | WS_VISIBLE
|
|
, rc.left
|
|
, rc.top
|
|
, rc.right - rc.left
|
|
, rc.bottom - rc.top
|
|
, _hdlg
|
|
, (HMENU) -1
|
|
, g_hInstance
|
|
, NULL
|
|
);
|
|
TBOOL( NULL != hwnd );
|
|
|
|
HFONT hFont = (HFONT) SendMessage( _hdlg, WM_GETFONT, 0, 0 );
|
|
SendMessage( hwnd, WM_SETFONT, (WPARAM) hFont, 0 );
|
|
|
|
TraceFuncExit( );
|
|
} |