📄 atlshellext.h
字号:
{
ATLTRACENOTIMPL(_T("IShellView2::HandleRename"));
}
STDMETHOD(SelectAndPositionItem)(LPCITEMIDLIST /*pidlItem*/, UINT /*uFlags*/, POINT* /*point*/)
{
ATLTRACENOTIMPL(_T("IShellView2::SelectAndPositionItem"));
}
// View handlers
LRESULT _ViewActivate(UINT uState)
{
ATLTRACE2(atlTraceCOM, 0, _T("IShellView::_ViewActivate %d\n"), uState);
// Don't do anything if the state isn't really changing
if( m_uState==uState ) return S_OK;
T *pT = static_cast<T*>(this);
pT->_ViewDeactivate();
// Only do this if we are active
if( uState!=SVUIA_DEACTIVATE ) {
pT->_MergeMenus(uState);
pT->_UpdateToolbar();
}
m_uState = uState;
return 0;
}
LRESULT _ViewDeactivate(void)
{
ATLTRACE2(atlTraceCOM, 0, _T("IShellView::_ViewDeactivate\n"));
//if( m_uState != SVUIA_DEACTIVATE ) {
T *pT = static_cast<T*>(this);
m_uState = SVUIA_DEACTIVATE;
pT->_MergeMenus(m_uState);
pT->_MergeToolbar(m_uState);
//}
return 0;
}
// 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.
void _GetShellSettings(SHELLFLAGSTATE &sfs, DWORD dwMask)
{
typedef void (WINAPI *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
HINSTANCE hinstShell32;
hinstShell32 = ::LoadLibrary(TEXT("shell32.dll"));
if( hinstShell32!=NULL ){
PFNSHGETSETTINGSPROC pfnSHGetSettings = (PFNSHGETSETTINGSPROC) ::GetProcAddress(hinstShell32, "SHGetSettings");
if(pfnSHGetSettings) (*pfnSHGetSettings)(&sfs, dwMask);
::FreeLibrary(hinstShell32);
}
}
// A helper function which will take care of some of
// the fancy new Win98 settings...
void _UpdateShellSettings(void)
{
// Update the m_ShellFlags state
_GetShellSettings(m_ShellFlags,
SSF_DESKTOPHTML |
SSF_NOCONFIRMRECYCLE |
SSF_SHOWALLOBJECTS |
SSF_SHOWATTRIBCOL |
SSF_DOUBLECLICKINWEBVIEW |
SSF_SHOWCOMPCOLOR |
SSF_WIN95CLASSIC);
// Update the ListView control accordingly
DWORD dwExStyles = 0;
if( !m_ShellFlags.fWin95Classic && !m_ShellFlags.fDoubleClickInWebView ) {
dwExStyles |= LVS_EX_ONECLICKACTIVATE |
LVS_EX_TRACKSELECT |
LVS_EX_UNDERLINEHOT;
}
ListView_SetExtendedListViewStyle(m_hwndList, dwExStyles);
}
LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
#ifdef STRICT
return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
#else
return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
#endif
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
T *pT = (T*)::GetWindowLong(hWnd, GWL_USERDATA);
if(uMessage == WM_NCCREATE) {
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
pT = (T*)(lpcs->lpCreateParams);
::SetWindowLong(hWnd, GWL_USERDATA, (LONG)pT);
// Set the window handle
pT->m_hWnd = hWnd;
return 1;
}
ATLASSERT(pT);
MSG msg = { pT->m_hWnd, uMessage, wParam, lParam, 0, { 0, 0 } };
const MSG *pOldMsg = pT->m_pCurrentMsg;
pT->m_pCurrentMsg = &msg;
// pass to the message map to process
LRESULT lRes;
BOOL bRet = pT->ProcessWindowMessage(pT->m_hWnd, uMessage, wParam, lParam, lRes, 0);
// restore saved value for the current message
ATLASSERT(pT->m_pCurrentMsg == &msg);
pT->m_pCurrentMsg = pOldMsg;
if(!bRet) lRes = pT->DefWindowProc(uMessage, wParam, lParam);
return lRes;
}
// Message handlers
LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
ATLTRACE2(atlTraceWindowing, 0, _T("IShellView::OnSetFocus\n"));
::SetFocus(m_hwndList);
return 0;
}
LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
ATLTRACE2(atlTraceWindowing, 0, _T("IShellView::OnKillFocus\n"));
return 0;
}
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T *pT = static_cast<T*>(this);
pT->_UpdateShellSettings();
return 0;
}
LRESULT OnNotifySetFocus(UINT /*CtlID*/, LPNMHDR /*lpnmh*/, BOOL &/*bHandled*/)
{
ATLTRACE2(atlTraceWindowing, 0, _T("IShellView::OnNotifySetFocus\n"));
ATLASSERT(m_pShellBrowser);
// Tell the browser one of our windows has received the focus. This should always
// be done before merging menus (_ViewActivate() merges the menus) if one of our
// windows has the focus.
T *pT = static_cast<T*>(this);
m_pShellBrowser->OnViewWindowActive((IShellView *)pT);
pT->_ViewActivate(SVUIA_ACTIVATE_FOCUS);
return 0;
}
LRESULT OnNotifyKillFocus(UINT /*CtlID*/, LPNMHDR /*lpnmh*/, BOOL &/*bHandled*/)
{
ATLTRACE2(atlTraceWindowing, 0, _T("IShellView::OnNotifyKillFocus\n"));
T *pT = static_cast<T*>(this);
pT->_ViewActivate(SVUIA_ACTIVATE_NOFOCUS);
return 0;
}
LRESULT OnInitMenu(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T *pT = static_cast<T*>(this);
pT->_UpdateMenu((HMENU)wParam);
return 0;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
// Resize the ListView to fit our window
if(m_hwndList) ::MoveWindow(m_hwndList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
return 0;
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return 1; // avoid flicker
}
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// Create the ListView
T *pT = static_cast<T*>(this);
if( pT->_CreateListView() )
if( pT->_InitListView() )
pT->_FillListView();
return 0;
}
// Operations
typedef enum {
TBI_STD = 0,
TBI_VIEW,
TBI_LOCAL
} TOOLBARITEM;
typedef struct
{
TOOLBARITEM nType;
TBBUTTON tb;
} NS_TOOLBUTTONINFO, *PNS_TOOLBUTTONINFO;
BOOL _AppendToolbarItems(
PNS_TOOLBUTTONINFO pButtons,
int nCount,
LPARAM lOffsetFile,
LPARAM lOffsetView,
LPARAM lOffsetCustom)
{
ATLASSERT(nCount>0);
ATLASSERT(!::IsBadReadPtr(pButtons, nCount*sizeof(NS_TOOLBUTTONINFO)));
ATLASSERT(m_pShellBrowser);
LPTBBUTTON ptbb = (LPTBBUTTON)::GlobalAlloc(GPTR, sizeof(TBBUTTON)*nCount);
if( ptbb==NULL ) return FALSE;
for( int j=0; j<nCount; j++ ) {
switch( pButtons[j].nType ) {
case TBI_STD:
(ptbb + j)->iBitmap = lOffsetFile + pButtons[j].tb.iBitmap;
break;
case TBI_VIEW:
(ptbb + j)->iBitmap = lOffsetView + pButtons[j].tb.iBitmap;
break;
case TBI_LOCAL:
(ptbb + j)->iBitmap = lOffsetCustom + pButtons[j].tb.iBitmap;
break;
}
(ptbb + j)->idCommand = pButtons[j].tb.idCommand;
(ptbb + j)->fsState = pButtons[j].tb.fsState;
(ptbb + j)->fsStyle = pButtons[j].tb.fsStyle;
(ptbb + j)->dwData = pButtons[j].tb.dwData;
(ptbb + j)->iString = pButtons[j].tb.iString;
}
m_pShellBrowser->SetToolbarItems(ptbb, nCount, FCT_MERGE);
::GlobalFree((HGLOBAL)ptbb);
return TRUE;
}
UINT _GetMenuPosFromID(HMENU hMenu, UINT ID) const
{
UINT nCount = ::GetMenuItemCount(hMenu);
for( UINT i=0; i<nCount; i++ ) {
if( ::GetMenuItemID(hMenu, i)==ID ) return i;
}
return (UINT)-1;
}
BOOL _AppendMenu(HMENU hMenu, HMENU hMenuSource, UINT nPosition)
{
ATLASSERT(::IsMenu(hMenu));
ATLASSERT(::IsMenu(hMenuSource));
// Get the HMENU of the popup
if( hMenu==NULL ) return FALSE;
if( hMenuSource==NULL ) return FALSE;
// Make sure that we start with only one separator menu-item
int iStartPos = 0;
if( ::GetMenuState(hMenuSource, 0, MF_BYPOSITION) & MF_SEPARATOR ) {
if( (nPosition==0) ||
(::GetMenuState(hMenu, nPosition-1, MF_BYPOSITION) & MF_SEPARATOR) ) {
iStartPos++;
}
}
// Go...
int nMenuItems = ::GetMenuItemCount(hMenuSource);
for( int i=iStartPos; i<nMenuItems; i++ ) {
// Get state information
UINT state = ::GetMenuState(hMenuSource, i, MF_BYPOSITION);
TCHAR szItemText[256];
int nLen = ::GetMenuString(hMenuSource, i, szItemText, sizeof(szItemText)/sizeof(TCHAR), MF_BYPOSITION);
// Is this a separator?
if( state & MF_SEPARATOR ) {
::InsertMenu(hMenu, nPosition++, state | MF_STRING | MF_BYPOSITION, 0, _T(""));
}
else if( state & MF_POPUP ) {
// Strip the HIBYTE because it contains a count of items
state = LOBYTE(state) | MF_POPUP;
// Then create the new submenu by using recursive call
HMENU hSubMenu = ::CreateMenu();
_AppendMenu(hSubMenu, ::GetSubMenu(hMenuSource, i), 0);
ATLASSERT(::GetMenuItemCount(hSubMenu)>0);
// Non-empty popup -- add it to the shared menu bar
::InsertMenu(hMenu, nPosition++, state | MF_BYPOSITION, (UINT)hSubMenu, szItemText);
}
else if( nLen>0 ) {
// Only non-empty items should be added
ATLASSERT(szItemText[0]!=_T('\0'));
ATLASSERT(::GetMenuItemID(hMenuSource, i)>FCIDM_SHVIEWFIRST && ::GetMenuItemID(hMenuSource, i)<FCIDM_SHVIEWLAST);
// Here the state does not contain a count in the HIBYTE
::InsertMenu(hMenu, nPosition++, state | MF_BYPOSITION, ::GetMenuItemID(hMenuSource, i), szItemText);
}
}
return TRUE;
}
BOOL _IsExplorerMode() const
{
ATLASSERT(m_pShellBrowser);
HWND hwndTree = NULL;
return( SUCCEEDED(m_pShellBrowser->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree );
}
// Overridables
BOOL _CreateListView(void)
{
// Initialize and create the actual List View control
ATLASSERT((m_dwListViewStyle & (WS_VISIBLE|WS_CHILD))==(WS_VISIBLE|WS_CHILD));
m_dwListViewStyle &= ~LVS_TYPEMASK;
switch( m_FolderSettings.ViewMode ) {
case FVM_ICON:
m_dwListViewStyle |= LVS_ICON;
break;
case FVM_SMALLICON:
m_dwListViewStyle |= LVS_SMALLICON;
break;
case FVM_LIST:
m_dwListViewStyle |= LVS_LIST;
break;
case FVM_DETAILS:
m_dwListViewStyle |= LVS_REPORT;
break;
default:
m_dwListViewStyle |= LVS_ICON;
break;
}
if( FWF_AUTOARRANGE & m_FolderSettings.fFlags ) m_dwListViewStyle |= LVS_AUTOARRANGE;
#if (_WIN32_IE >= 0x0500)
if( FWF_SHOWSELALWAYS & m_FolderSettings.fFlags ) m_dwListViewStyle |= LVS_SHOWSELALWAYS;
#endif
if( FWF_ALIGNLEFT & m_FolderSettings.fFlags ) m_dwListViewStyle |= LVS_ALIGNLEFT;
// Go on,.. create ListView control
m_hwndList = ::CreateWindowEx( FWF_NOCLIENTEDGE & m_FolderSettings.fFlags ? 0 : WS_EX_CLIENTEDGE,
WC_LISTVIEW,
NULL,
m_dwListViewStyle,
0,0,0,0,
m_hWnd,
(HMENU)IDC_LISTVIEW,
_Module.GetModuleInstance(),
NULL);
if( m_hwndList==NULL ) return FALSE;
T *pT = static_cast<T*>(this);
pT->_UpdateShellSettings();
return TRUE;
}
BOOL _InitListView(void) { return TRUE; };
BOOL _FillListView(void) { return TRUE; };
BOOL _MergeToolbar(UINT uState) { return TRUE; };
BOOL _MergeMenus(UINT uState) { return TRUE; };
BOOL _UpdateToolbar() { return TRUE; };
BOOL _UpdateMenu(HMENU hMenu) { return TRUE; };
};
//////////////////////////////////////////////////////////////////////////////
// CShellPropertyPage
template <class T>
class ATL_NO_VTABLE CShellPropertyPage :
public IShellPropSheetExt,
public IShellExtInit,
public CWindow
{
public:
TCHAR m_szFileName[MAX_PATH];
const MSG *m_pCurrentMsg;
CShellPropertyPage()
{
m_szFileName[0]=_T('\0');
}
// IShellPropSheetExt
STDMETHOD(AddPages)(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
{
T* pT = static_cast<T*>(this);
TCHAR szCaption[40];
::LoadString(_Module.GetResourceInstance(), T::IDS_TABCAPTION, szCaption, sizeof(szCaption)/sizeof(TCHAR));
PROPSHEETPAGE psp = { 0 };
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
psp.hInstance = _Module.GetResourceInstance();
psp.pszTemplate = MAKEINTRESOURCE(T::IDD);
psp.hIcon = 0;
psp.pszTitle = szCaption;
psp.pfnDlgProc = (DLGPROC)T::PageDlgProc;
psp.pcRefParent = NULL;
psp.pfnCallback = T::PropSheetPageProc;
psp.lParam = (LPARAM)pT;
HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&psp);
if( hPage==NULL ) return E_OUTOFMEMORY;
if( pfnAddPage(hPage, lParam)==FALSE ) {
::DestroyPropertySheetPage(hPage);
return E_FAIL;
}
pT->AddRef(); // This reference is release by the callback
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, T::ID_TAB_INDEX); // COMCTRL Ver 4.71 allows us to set the initial page index
}
STDMETHOD(ReplacePage)(UINT /*uPageID*/, LPFNADDPROPSHEETPAGE /*lpfnReplaceWith*/, LPARAM /*lParam*/)
{
// The Shell doesn't call this for file class Property Sheets
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -