Changeset 692


Ignore:
Timestamp:
12/2/2008 10:05:33 AM (6 years ago)
Author:
lowjoel
Message:

Move the eshll idea to a separate text file and indented the namespace code.

Location:
branches/erasershellext/cpp
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • branches/erasershellext/cpp/CtxMenu.cpp

    r691 r692  
    3333    const wchar_t* CCtxMenu::m_szMenuTitle = L"Eraser v6"; 
    3434 
    35 HRESULT CCtxMenu::Initialize(LPCITEMIDLIST /*pidlFolder*/, LPDATAOBJECT pDataObj, 
    36                              HKEY /*hProgID*/) 
    37 { 
    38     m_itemID      = 0; 
    39     FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; 
    40     STGMEDIUM stg = { TYMED_HGLOBAL }; 
    41     HDROP     hDrop; 
    42  
    43     //Look for CF_HDROP data in the data object. 
    44     if (FAILED(pDataObj->GetData (&fmt, &stg))) 
    45         //Nope! Return an "invalid argument" error back to Explorer. 
    46         return E_INVALIDARG; 
    47  
    48     //Get a pointer to the actual data. 
    49     hDrop = static_cast<HDROP>(GlobalLock(stg.hGlobal)); 
    50  
    51     //Make sure it worked. 
    52     if (hDrop == NULL) 
    53         return E_INVALIDARG; 
    54  
    55     //Sanity check - make sure there is at least one filename. 
    56     UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); 
    57     if (!uNumFiles) 
    58     { 
     35    HRESULT CCtxMenu::Initialize(LPCITEMIDLIST /*pidlFolder*/, LPDATAOBJECT pDataObj, 
     36                                 HKEY /*hProgID*/) 
     37    { 
     38        m_itemID      = 0; 
     39        FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; 
     40        STGMEDIUM stg = { TYMED_HGLOBAL }; 
     41        HDROP     hDrop; 
     42 
     43        //Look for CF_HDROP data in the data object. 
     44        if (FAILED(pDataObj->GetData (&fmt, &stg))) 
     45            //Nope! Return an "invalid argument" error back to Explorer. 
     46            return E_INVALIDARG; 
     47 
     48        //Get a pointer to the actual data. 
     49        hDrop = static_cast<HDROP>(GlobalLock(stg.hGlobal)); 
     50 
     51        //Make sure it worked. 
     52        if (hDrop == NULL) 
     53            return E_INVALIDARG; 
     54 
     55        //Sanity check - make sure there is at least one filename. 
     56        UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); 
     57        if (!uNumFiles) 
     58        { 
     59            GlobalUnlock(stg.hGlobal); 
     60            ReleaseStgMedium(&stg); 
     61            return E_INVALIDARG; 
     62        } 
     63 
     64        HRESULT hr = S_OK; 
     65        WCHAR Buffer[MAX_PATH] = {0};    
     66        for (UINT i = uNumFiles; i < uNumFiles; i++)     
     67        { 
     68            //TODO: Collect the list of files queried. 
     69            UINT charsWritten = DragQueryFile(hDrop, i, Buffer, sizeof(Buffer) / sizeof(Buffer[0])); 
     70            if (!charsWritten) 
     71                hr = E_INVALIDARG; 
     72            else 
     73                PathQuoteSpaces(Buffer); 
     74        } 
     75 
    5976        GlobalUnlock(stg.hGlobal); 
    6077        ReleaseStgMedium(&stg); 
    61         return E_INVALIDARG; 
    62     } 
    63  
    64     HRESULT hr = S_OK; 
    65     WCHAR Buffer[MAX_PATH] = {0};    
    66     for (UINT i = uNumFiles; i < uNumFiles; i++)     
    67     { 
    68         //TODO: Collect the list of files queried. 
    69         UINT charsWritten = DragQueryFile(hDrop, i, Buffer, sizeof(Buffer) / sizeof(Buffer[0])); 
    70         if (!charsWritten) 
    71             hr = E_INVALIDARG; 
     78        return hr; 
     79    } 
     80    /* 
     81    +-------------------+ 
     82    |                   | 
     83    |                   | 
     84    |                   | 
     85    |                   | 
     86    +-------------------+    +-------------------+ 
     87    |(ICON) Eraser v6 > |    | Erase selected    | //--> erase the files immediately using defaults 
     88    +-------------------+    | Schedule Selected | //--> open the scheduler menu, with files/folders filled in 
     89    |                   |    +-------------------+ 
     90    |                   |    | Secure move       | //--> secure move the files 
     91    |                   |    +-------------------+ // Eraser.Manager Algorithms popup 
     92    |                   |    |(*) Customise      | // set algorithm for this query only 
     93    +-------------------+    +-------------------+ 
     94    */ 
     95 
     96    HRESULT CCtxMenu::QueryContextMenu(HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, 
     97                                       UINT /*uidLastCmd*/, UINT uFlags) 
     98    { 
     99        //If the flags include CMF_DEFAULTONLY then we shouldn't do anything. 
     100        if (uFlags & CMF_DEFAULTONLY) 
     101            return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); 
     102 
     103        //First, create and populate a submenu. 
     104        UINT uID = uidFirstCmd;  
     105        HMENU hSubmenu = CreatePopupMenu();  
     106 
     107        //Create the submenu, following the order defined in the CEraserLPVERB enum 
     108        InsertMenu    (hSubmenu, CERASER_ERASE, MF_BYPOSITION, uID++,               _T("&Erase")); 
     109        InsertMenu    (hSubmenu, CERASER_SCHEDULE, MF_BYPOSITION, uID++,            _T("&Schedule")); 
     110        InsertMenu    (hSubmenu, CERASER_ERASE_ON_RESTART, MF_BYPOSITION, uID++,    _T("Erase on &Restart")); 
     111        //------------------------------------------------------------------------- 
     112        InsertMenuItem(hSubmenu, CERASER_SEPERATOR_1, TRUE, GetSeparator()); 
     113        InsertMenu    (hSubmenu, CERASER_SECURE_MOVE, MF_BYPOSITION, uID++,         _T("Secure &Move"));     
     114        //------------------------------------------------------------------------- 
     115        InsertMenuItem(hSubmenu, CERASER_SEPERATOR_2, TRUE, GetSeparator()); 
     116        InsertMenu    (hSubmenu, CERASER_CUSTOMISE, MF_BYPOSITION, uID++,           _T("&Console"));     
     117 
     118        //Insert the submenu into the Context menu provided by Explorer. 
     119        { 
     120            MENUITEMINFO mii = { sizeof(MENUITEMINFO) }; 
     121            mii.wID = uID++; 
     122            mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID; 
     123            mii.hSubMenu = hSubmenu; 
     124            mii.dwTypeData = const_cast<wchar_t*>(m_szMenuTitle); 
     125 
     126            //Set the bitmap for the registered item. Vista machines will be set using a DIB, 
     127            //older machines will be ownerdrawn. 
     128            OSVERSIONINFO osvi; 
     129            ZeroMemory(&osvi, sizeof(osvi)); 
     130            osvi.dwOSVersionInfoSize = sizeof(osvi); 
     131 
     132            if (GetVersionEx(&osvi) && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && 
     133                osvi.dwMajorVersion >= 6) 
     134            { 
     135                mii.fMask |= MIIM_CHECKMARKS; 
     136                mii.hbmpUnchecked = GetMenuBitmap(); 
     137            } 
     138            else 
     139            { 
     140                mii.fMask |= MIIM_FTYPE; 
     141                mii.fType = MFT_OWNERDRAW; 
     142            } 
     143 
     144            m_itemID = uMenuIndex++; 
     145            InsertMenuItem(hmenu, m_itemID, TRUE, &mii); 
     146        } 
     147 
     148        return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd); 
     149    } 
     150 
     151    HRESULT CCtxMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) 
     152    { 
     153        return HandleMenuMsg2(uMsg, wParam, lParam, NULL); 
     154    } 
     155 
     156    HRESULT CCtxMenu::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, 
     157                                     LRESULT* result) 
     158    { 
     159        //Skip if we aren't handling our own. 
     160        bool handleResult = false; 
     161        switch (uMsg) 
     162        { 
     163        case WM_MEASUREITEM: 
     164            { 
     165                MEASUREITEMSTRUCT* mis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam); 
     166                if (mis->CtlID == m_itemID) 
     167                    handleResult = OnMeasureItem(mis->itemWidth, mis->itemHeight); 
     168                else 
     169                    handleResult = false; 
     170                break; 
     171            } 
     172 
     173        case WM_DRAWITEM: 
     174            { 
     175                DRAWITEMSTRUCT* dis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam); 
     176                if (dis->CtlID == m_itemID) 
     177                    handleResult = OnDrawItem(dis->hDC, dis->rcItem, dis->itemAction, dis->itemState); 
     178                else 
     179                    handleResult = false; 
     180            } 
     181        } 
     182 
     183        if (result) 
     184            *result = handleResult; 
     185        return S_OK; 
     186    } 
     187 
     188    bool CCtxMenu::OnMeasureItem(UINT& itemWidth, UINT& itemHeight) 
     189    { 
     190        LOGFONT logFont; 
     191        if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0)) 
     192            return false; 
     193 
     194        //Measure the size of the text. 
     195        Handle<HDC> screenDC = GetDC(NULL); 
     196        Handle<HFONT> font = CreateFontIndirect(&logFont); 
     197        SelectObject(screenDC, font); 
     198        SIZE textSize; 
     199        if (!GetTextExtentPoint32(screenDC, m_szMenuTitle, wcslen(m_szMenuTitle), &textSize)) 
     200            return false; 
     201 
     202        itemWidth = textSize.cx; 
     203        itemHeight = textSize.cy; 
     204 
     205        //Account for the size of the bitmap. 
     206        UINT iconWidth = GetSystemMetrics(SM_CXMENUCHECK); 
     207        itemWidth += iconWidth; 
     208        itemHeight = std::max(iconWidth, itemHeight); 
     209 
     210        //And remember the minimum size for menu items. 
     211        itemHeight = std::max((int)itemHeight, GetSystemMetrics(SM_CXMENUSIZE)); 
     212        return true; 
     213    } 
     214 
     215    bool CCtxMenu::OnDrawItem(HDC hdc, RECT rect, UINT /*action*/, UINT state) 
     216    { 
     217        //Draw the background. 
     218        LOGBRUSH logBrush = { BS_SOLID, 
     219            (state & ODS_SELECTED) ? 
     220                GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_MENU), 
     221            0 
     222        }; 
     223        Handle<HBRUSH> bgBrush = CreateBrushIndirect(&logBrush); 
     224        FillRect(hdc, &rect, bgBrush); 
     225 
     226        //Then the bitmap. 
     227        { 
     228            //Draw the icon with alpha and all first. 
     229            Handle<HICON> icon(GetMenuIcon()); 
     230            int iconSize = GetSystemMetrics(SM_CXMENUCHECK); 
     231            int iconMargin = GetSystemMetrics(SM_CXEDGE); 
     232            DrawIconEx(hdc, rect.left + iconMargin, rect.top + (rect.bottom - rect.top - iconSize) / 2, 
     233                icon, 0, 0, 0, bgBrush, DI_NORMAL); 
     234 
     235            //Move the rectangle's left bound to the text starting position 
     236            rect.left += iconMargin * 2 + iconSize; 
     237        } 
     238         
     239        //Draw the text. 
     240        SetBkMode(hdc, TRANSPARENT); 
     241        LOGFONT logFont; 
     242        if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0)) 
     243            return false; 
     244 
     245        /*Handle<HFONT> font = CreateFontIndirect(&logFont); 
     246        SelectObject(hdc, font);*/ 
     247        SIZE textSize; 
     248        if (!GetTextExtentPoint32(hdc, m_szMenuTitle, wcslen(m_szMenuTitle), &textSize)) 
     249            return false; 
     250 
     251        COLORREF oldColour = SetTextColor(hdc, (state & ODS_SELECTED) ? 
     252            GetSysColor(COLOR_HIGHLIGHTTEXT) : GetSysColor(COLOR_MENUTEXT)); 
     253        UINT flags = DST_PREFIXTEXT; 
     254        if (state & ODS_NOACCEL) 
     255            flags |= DSS_HIDEPREFIX; 
     256        ::DrawState(hdc, NULL, NULL, reinterpret_cast<LPARAM>(m_szMenuTitle), wcslen(m_szMenuTitle), 
     257            rect.left, rect.top + (rect.bottom - rect.top - textSize.cy) / 2, textSize.cx, textSize.cy, flags); 
     258        SetTextColor(hdc, oldColour); 
     259        return true; 
     260    } 
     261 
     262    HRESULT CCtxMenu::GetCommandString(UINT idCmd, UINT uFlags, UINT* /*pwReserved*/, 
     263                                       LPSTR pszName, UINT cchMax) 
     264    { 
     265        USES_CONVERSION; 
     266 
     267        //Check idCmd, it must be 0 or 1 since we have two menu items. 
     268        if ( idCmd > 2 ) 
     269            return E_INVALIDARG; 
     270 
     271        //If Explorer is asking for a help string, copy our string into the supplied buffer. 
     272        if (!(uFlags & GCS_HELPTEXT))  
     273            return E_INVALIDARG; 
     274 
     275        static LPCTSTR szErase        = _T("Erases the currently selected file\r\n"); 
     276        static LPCTSTR szEraseUnunsed = _T("Erases the currently selected drive's unused disk space\r\n"); 
     277        LPCTSTR pszText = (0 == idCmd) ? szErase : szEraseUnunsed; 
     278 
     279        if (uFlags & GCS_UNICODE) 
     280            //We need to cast pszName to a Unicode string, and then use the Unicode string copy API. 
     281            lstrcpynW((LPWSTR)pszName, T2CW(pszText), cchMax); 
    72282        else 
    73             PathQuoteSpaces(Buffer); 
    74     } 
    75  
    76     GlobalUnlock(stg.hGlobal); 
    77     ReleaseStgMedium(&stg); 
    78     return hr; 
     283            //Use the ANSI string copy API to return the help string. 
     284            lstrcpynA(pszName, T2CA(pszText), cchMax); 
     285 
     286        return S_OK; 
     287    } 
     288 
     289    /* 
     290    usage: Eraser <action> <arguments> 
     291    where action is 
     292    addtask                 Adds tasks to the current task list. 
     293    querymethods            Lists all registered Erasure methods. 
     294 
     295    global parameters: 
     296    --quiet, -q             Do not create a Console window to display progress. 
     297 
     298    parameters for addtask: 
     299    eraser addtask --method=<methodGUID> (--recycled | --unused=<volume> |  --dir=<directory> | [file1 [file2 [...]]]) 
     300    --method, -m            The Erasure method to use. 
     301    --recycled, -r          Erases files and folders in the recycle bin 
     302    --unused, -u            Erases unused space in the volume. 
     303    optional arguments: --unused=<drive>[,clusterTips] 
     304    clusterTips     If specified, the drive's files will have their cluster tips 
     305    erased. 
     306    --dir, --directory, -d  Erases files and folders in the directory 
     307    optional arguments: --dir=<directory>[,e=excludeMask][,i=includeMask][,delete] 
     308    excludeMask     A wildcard expression for files and folders to exclude. 
     309    includeMask     A wildcard expression for files and folders to include. 
     310    The include mask is applied before the exclude mask. 
     311    delete          Deletes the folder at the end of the erasure if specified. 
     312    file1 ... fileN         The list of files to erase. 
     313 
     314    parameters for querymethods: 
     315    eraser querymethods 
     316 
     317    no parameters to set. 
     318 
     319    All arguments are case sensitive. 
     320 
     321    */   
     322 
     323    HRESULT CCtxMenu::InvokeCommand ( LPCMINVOKECOMMANDINFO pCmdInfo ) 
     324    { 
     325        // If lpVerb really points to a string, ignore this function call and bail out. 
     326        if ( HIWORD( pCmdInfo->lpVerb )  != 0) 
     327            return E_INVALIDARG; 
     328 
     329        HRESULT result = E_INVALIDARG; 
     330        // final eraser command to call 
     331        string_type command(L"eraser "); 
     332        string_type files, directories, unuseds; 
     333 
     334        // compile the eraser command syntax 
     335        for (string_list::const_iterator i = m_szSelectedFiles.begin(); 
     336            i != m_szSelectedFiles.end(); ++i) 
     337        { 
     338            files       += L"\"" + *i + L"\" "; 
     339        } 
     340        for (string_list::const_iterator i = m_szSelectedUnused.begin(); 
     341            i != m_szSelectedUnused.end(); ++i) 
     342        { 
     343            unuseds     += L"--unused=\"" + *i + L"\" "; 
     344        } 
     345        for (string_list::const_iterator i = m_szSelectedDirectories.begin(); 
     346            i != m_szSelectedDirectories.end(); ++i) 
     347        { 
     348            directories += L"--dir=\"" + *i + L"\" "; 
     349        } 
     350 
     351        // Get the command index. 
     352        switch(LOWORD(pCmdInfo->lpVerb + 1)) 
     353        { 
     354    #if 0 
     355        case CERASER_ERASE: 
     356            { 
     357                command += L"addtask " + files + unuseds + directories; 
     358                //result = system(command.c_str()); 
     359                break; 
     360            } 
     361        case CERASER_SECURE_MOVE: 
     362            { 
     363                result = S_OK; 
     364                // we need some user interaction, thus we will have a windows form 
     365                // has to be native, so i guess a bit of work 
     366                break; 
     367            } 
     368            // NOT IMPLEMENTED METHODS 
     369            case CERASER_ERASE_ON_RESTART: 
     370            { 
     371                MessageBox (pCmdInfo->hwnd, szMsg, _T("Eraser v6 - Shell Extention Query"), MB_ICONINFORMATION ); 
     372                command += S("--restart ") + objects; 
     373                result = system(command.c_str()); 
     374                break; 
     375            } 
     376            case CERASER_SCHEDULE: 
     377            { 
     378                command += S("--schedule ") + objects; 
     379                result = system(command.c_str()); 
     380                break; 
     381            } 
     382        case CERASER_CONSOLE: 
     383            { 
     384                // interactive eraser console 
     385                break; 
     386            } 
     387    #endif 
     388        default: 
     389            { 
     390                TCHAR szMsg [MAX_PATH + 32]; 
     391                wsprintf ( szMsg, _T("Invalid Query was submitted, unable to process!\n\nCommand ID = %d\n\n"), LOWORD(pCmdInfo->lpVerb) ); 
     392                MessageBox ( pCmdInfo->hwnd, szMsg, _T("Eraser v6 - Shell Extention Query"), MB_ICONINFORMATION ); 
     393            } 
     394            return result; 
     395        } 
     396    } 
     397 
     398    MENUITEMINFO* CCtxMenu::GetSeparator() 
     399    { 
     400        MENUITEMINFO *mii = new MENUITEMINFO();      
     401        mii->cbSize = sizeof(MENUITEMINFO); 
     402        mii->fMask = MIIM_TYPE; 
     403        mii->fType = MF_SEPARATOR; 
     404        return mii; 
     405    } 
     406 
     407    HICON CCtxMenu::GetMenuIcon() 
     408    { 
     409        int smIconSize = GetSystemMetrics(SM_CXMENUCHECK); 
     410        return static_cast<HICON>(LoadImage(theApp.m_hInstance, L"Eraser", 
     411            IMAGE_ICON, smIconSize, smIconSize, LR_LOADTRANSPARENT)); 
     412    } 
     413 
     414    HBITMAP CCtxMenu::GetMenuBitmap() 
     415    { 
     416        BITMAP bitmap; 
     417        ICONINFO iconInfo; 
     418        ZeroMemory(&bitmap, sizeof(bitmap)); 
     419        ZeroMemory(&iconInfo, sizeof(iconInfo)); 
     420        Handle<HICON> icon(GetMenuIcon()); 
     421 
     422        //Try to get the icon's size, bitmap and bit depth. We will try to convert 
     423        //the bitmap into a DIB for display on Vista if it contains an alpha channel. 
     424        if (!GetIconInfo(icon, &iconInfo)) 
     425            return NULL; 
     426 
     427        Handle<HBITMAP> iconMask(iconInfo.hbmMask); 
     428        if (!GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bitmap) || 
     429            bitmap.bmBitsPixel < 32) 
     430            return iconInfo.hbmColor; 
     431 
     432        //Try converting the DDB into a DIB. 
     433        DIBSECTION dibSection; 
     434        HBITMAP dib = CreateDIB(bitmap.bmWidth, bitmap.bmHeight, NULL); 
     435        if (!GetObject(dib, sizeof(dibSection), &dibSection) || 
     436            !GetDIBits(CreateCompatibleDC(NULL), iconInfo.hbmColor, 0, bitmap.bmHeight, 
     437                dibSection.dsBm.bmBits, reinterpret_cast<BITMAPINFO*>(&dibSection.dsBmih), 
     438                DIB_RGB_COLORS)) 
     439        { 
     440            return iconInfo.hbmColor; 
     441        } 
     442 
     443        return dib; 
     444    } 
     445 
     446    HBITMAP CCtxMenu::CreateDIB(LONG width, LONG height, char** bitmapBits) 
     447    { 
     448        BITMAPINFO info; 
     449        ZeroMemory(&info, sizeof(info)); 
     450        info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
     451        info.bmiHeader.biWidth = width; 
     452        info.bmiHeader.biHeight = height; 
     453        info.bmiHeader.biPlanes = 1; 
     454        info.bmiHeader.biBitCount = 32; 
     455        info.bmiHeader.biCompression = BI_RGB; 
     456        char* dibBitmapBits = NULL; 
     457        return ::CreateDIBSection(0, &info, DIB_RGB_COLORS, 
     458            reinterpret_cast<void**>(bitmapBits ? bitmapBits : &dibBitmapBits), NULL, 0); 
     459    } 
    79460} 
    80 /* 
    81 +-------------------+ 
    82 |                   | 
    83 |                   | 
    84 |                   | 
    85 |                   | 
    86 +-------------------+    +-------------------+ 
    87 |(ICON) Eraser v6 > |    | Erase selected    | //--> erase the files immediately using defaults 
    88 +-------------------+    | Schedule Selected | //--> open the scheduler menu, with files/folders filled in 
    89 |                   |    +-------------------+ 
    90 |                   |    | Secure move       | //--> secure move the files 
    91 |                   |    +-------------------+ // Eraser.Manager Algorithms popup 
    92 |                   |    |(*) Customise      | // set algorithm for this query only 
    93 +-------------------+    +-------------------+ 
    94 */ 
    95  
    96 /* 
    97 we have eraser shell scripts (.eshlls) where we use them 
    98 to generate shell extention menus dynamically. 
    99 the syntax is simple. 
    100 This project should be aimed at the 6.1 release. 
    101  
    102 BEGIN @MENU : POSITION($INDEX) 
    103 [ICON="PATH"] 
    104 [TEXT="DISPLAY_TEXT"] 
    105  
    106 [FLAGS=MIIM_*]           
    107 //MIIM_BITMAP 
    108 //MIIM_CHECKMARKS 
    109 //MIIM_DATA 
    110 //MIIM_FTYPE 
    111 //MIIM_ID 
    112 //MIIM_STATE 
    113 //MIIM_STRING 
    114 //MIIM_SUBMENU 
    115 //MIIM_TYPE 
    116  
    117 [TYPE=MF_*] 
    118 //MF_APPEND, 
    119 //MF_BITMAP, 
    120 //MF_BYCOMMAND, 
    121 //MF_BYPOSITION 
    122 //MF_CHECKED 
    123 //MF_DEFAULT 
    124 //MF_DELETE 
    125 //MF_DISABLED 
    126 //MF_ENABLED 
    127 //MF_END 
    128 //MF_GRAYED 
    129 //MF_HELP 
    130 //MF_HILITE 
    131 //MF_INSERT 
    132 //MF_MENUBARBREAK 
    133 //MF_MENUBREAK 
    134 //MF_MOUSESELECT 
    135 //MF_OWNERDRAW 
    136 //MF_POPUP 
    137 //MF_POPUP 
    138 //MF_REMOVE, 
    139 //MF_RIGHTJUSTIFY, 
    140 //MF_SEPARATOR, 
    141 //MF_STRING, 
    142 //MF_SYSMENU, 
    143 //MF_UNCHECKED, 
    144 //MF_UNHILITE 
    145 //MF_USECHECKBITMAPS 
    146 END 
    147  
    148 // Desirable to have bitmaps cached 
    149 @MENU  
    150 { 
    151 BITMAP = "FILE"; 
    152 TEXT="Eraser"; 
    153 BITMAP CHECKED="FILE"; 
    154 BITMAP UNCHECKED="FILE"; 
    155  
    156 // submenu creation 
    157 @MENU  
    158 { 
    159 @CHECKBOX  
    160 { 
    161 } 
    162 @SEPERATOR 
    163 } 
    164 } 
    165  
    166 UINT     cbSize; 
    167 UINT     fMask; 
    168 UINT     fType;         // used if MIIM_TYPE (4.0) or MIIM_FTYPE (>4.0) 
    169 UINT     fState;        // used if MIIM_STATE 
    170 UINT     wID;           // used if MIIM_ID 
    171 HMENU    hSubMenu;      // used if MIIM_SUBMENU 
    172 HBITMAP  hbmpChecked;   // used if MIIM_CHECKMARKS 
    173 HBITMAP  hbmpUnchecked; // used if MIIM_CHECKMARKS 
    174 ULONG_PTR dwItemData;   // used if MIIM_DATA 
    175 __field_ecount_opt(cch) LPSTR    dwTypeData;    // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0) 
    176 UINT     cch;           // used if MIIM_TYPE (4.0) or MIIM_STRING (>4.0) 
    177 HBITMAP  hbmpItem;      // used if MIIM_BITMAP 
    178  
    179 */ 
    180  
    181 HRESULT CCtxMenu::QueryContextMenu(HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, 
    182                                    UINT /*uidLastCmd*/, UINT uFlags) 
    183 { 
    184     //If the flags include CMF_DEFAULTONLY then we shouldn't do anything. 
    185     if (uFlags & CMF_DEFAULTONLY) 
    186         return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); 
    187  
    188     //First, create and populate a submenu. 
    189     UINT uID = uidFirstCmd;  
    190     HMENU hSubmenu = CreatePopupMenu();  
    191  
    192     //Create the submenu, following the order defined in the CEraserLPVERB enum 
    193     InsertMenu    (hSubmenu, CERASER_ERASE, MF_BYPOSITION, uID++,               _T("&Erase")); 
    194     InsertMenu    (hSubmenu, CERASER_SCHEDULE, MF_BYPOSITION, uID++,            _T("&Schedule")); 
    195     InsertMenu    (hSubmenu, CERASER_ERASE_ON_RESTART, MF_BYPOSITION, uID++,    _T("Erase on &Restart")); 
    196     //------------------------------------------------------------------------- 
    197     InsertMenuItem(hSubmenu, CERASER_SEPERATOR_1, TRUE, GetSeparator()); 
    198     InsertMenu    (hSubmenu, CERASER_SECURE_MOVE, MF_BYPOSITION, uID++,         _T("Secure &Move"));     
    199     //------------------------------------------------------------------------- 
    200     InsertMenuItem(hSubmenu, CERASER_SEPERATOR_2, TRUE, GetSeparator()); 
    201     InsertMenu    (hSubmenu, CERASER_CUSTOMISE, MF_BYPOSITION, uID++,           _T("&Console"));     
    202  
    203     //Insert the submenu into the Context menu provided by Explorer. 
    204     { 
    205         MENUITEMINFO mii = { sizeof(MENUITEMINFO) }; 
    206         mii.wID = uID++; 
    207         mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID; 
    208         mii.hSubMenu = hSubmenu; 
    209         mii.dwTypeData = const_cast<wchar_t*>(m_szMenuTitle); 
    210  
    211         //Set the bitmap for the registered item. Vista machines will be set using a DIB, 
    212         //older machines will be ownerdrawn. 
    213         OSVERSIONINFO osvi; 
    214         ZeroMemory(&osvi, sizeof(osvi)); 
    215         osvi.dwOSVersionInfoSize = sizeof(osvi); 
    216  
    217         if (GetVersionEx(&osvi) && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && 
    218             osvi.dwMajorVersion >= 6) 
    219         { 
    220             mii.fMask |= MIIM_CHECKMARKS; 
    221             mii.hbmpUnchecked = GetMenuBitmap(); 
    222         } 
    223         else 
    224         { 
    225             mii.fMask |= MIIM_FTYPE; 
    226             mii.fType = MFT_OWNERDRAW; 
    227         } 
    228  
    229         m_itemID = uMenuIndex++; 
    230         InsertMenuItem(hmenu, m_itemID, TRUE, &mii); 
    231     } 
    232  
    233     return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd); 
    234 } 
    235  
    236 HRESULT CCtxMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) 
    237 { 
    238     return HandleMenuMsg2(uMsg, wParam, lParam, NULL); 
    239 } 
    240  
    241 HRESULT CCtxMenu::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, LRESULT* result) 
    242 { 
    243     //Skip if we aren't handling our own. 
    244     bool handleResult = false; 
    245     switch (uMsg) 
    246     { 
    247     case WM_MEASUREITEM: 
    248     { 
    249         MEASUREITEMSTRUCT* mis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam); 
    250         if (mis->CtlID == m_itemID) 
    251             handleResult = OnMeasureItem(mis->itemWidth, mis->itemHeight); 
    252         else 
    253             handleResult = false; 
    254         break; 
    255     } 
    256  
    257     case WM_DRAWITEM: 
    258     { 
    259         DRAWITEMSTRUCT* dis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam); 
    260         if (dis->CtlID == m_itemID) 
    261             handleResult = OnDrawItem(dis->hDC, dis->rcItem, dis->itemAction, dis->itemState); 
    262         else 
    263             handleResult = false; 
    264     } 
    265     } 
    266  
    267     if (result) 
    268         *result = handleResult; 
    269     return S_OK; 
    270 } 
    271  
    272 bool CCtxMenu::OnMeasureItem(UINT& itemWidth, UINT& itemHeight) 
    273 { 
    274     LOGFONT logFont; 
    275     if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0)) 
    276         return false; 
    277  
    278     //Measure the size of the text. 
    279     Handle<HDC> screenDC = GetDC(NULL); 
    280     Handle<HFONT> font = CreateFontIndirect(&logFont); 
    281     SelectObject(screenDC, font); 
    282     SIZE textSize; 
    283     if (!GetTextExtentPoint32(screenDC, m_szMenuTitle, wcslen(m_szMenuTitle), &textSize)) 
    284         return false; 
    285  
    286     itemWidth = textSize.cx; 
    287     itemHeight = textSize.cy; 
    288  
    289     //Account for the size of the bitmap. 
    290     UINT iconWidth = GetSystemMetrics(SM_CXMENUCHECK); 
    291     itemWidth += iconWidth; 
    292     itemHeight = std::max(iconWidth, itemHeight); 
    293  
    294     //And remember the minimum size for menu items. 
    295     itemHeight = std::max((int)itemHeight, GetSystemMetrics(SM_CXMENUSIZE)); 
    296     return true; 
    297 } 
    298  
    299 bool CCtxMenu::OnDrawItem(HDC hdc, RECT rect, UINT /*action*/, UINT state) 
    300 { 
    301     //Draw the background. 
    302     LOGBRUSH logBrush = { BS_SOLID, 
    303         (state & ODS_SELECTED) ? 
    304             GetSysColor(COLOR_HIGHLIGHT) : GetSysColor(COLOR_MENU), 
    305         0 
    306     }; 
    307     Handle<HBRUSH> bgBrush = CreateBrushIndirect(&logBrush); 
    308     FillRect(hdc, &rect, bgBrush); 
    309  
    310     //Then the bitmap. 
    311     { 
    312         //Draw the icon with alpha and all first. 
    313         Handle<HICON> icon(GetMenuIcon()); 
    314         int iconSize = GetSystemMetrics(SM_CXMENUCHECK); 
    315         int iconMargin = GetSystemMetrics(SM_CXEDGE); 
    316         DrawIconEx(hdc, rect.left + iconMargin, rect.top + (rect.bottom - rect.top - iconSize) / 2, 
    317             icon, 0, 0, 0, bgBrush, DI_NORMAL); 
    318  
    319         //Move the rectangle's left bound to the text starting position 
    320         rect.left += iconMargin * 2 + iconSize; 
    321     } 
    322      
    323     //Draw the text. 
    324     SetBkMode(hdc, TRANSPARENT); 
    325     LOGFONT logFont; 
    326     if (!SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(logFont), &logFont, 0)) 
    327         return false; 
    328  
    329     /*Handle<HFONT> font = CreateFontIndirect(&logFont); 
    330     SelectObject(hdc, font);*/ 
    331     SIZE textSize; 
    332     if (!GetTextExtentPoint32(hdc, m_szMenuTitle, wcslen(m_szMenuTitle), &textSize)) 
    333         return false; 
    334  
    335     COLORREF oldColour = SetTextColor(hdc, (state & ODS_SELECTED) ? 
    336         GetSysColor(COLOR_HIGHLIGHTTEXT) : GetSysColor(COLOR_MENUTEXT)); 
    337     UINT flags = DST_PREFIXTEXT; 
    338     if (state & ODS_NOACCEL) 
    339         flags |= DSS_HIDEPREFIX; 
    340     ::DrawState(hdc, NULL, NULL, reinterpret_cast<LPARAM>(m_szMenuTitle), wcslen(m_szMenuTitle), 
    341         rect.left, rect.top + (rect.bottom - rect.top - textSize.cy) / 2, textSize.cx, textSize.cy, flags); 
    342     SetTextColor(hdc, oldColour); 
    343     return true; 
    344 } 
    345  
    346 HRESULT CCtxMenu::GetCommandString(UINT idCmd, UINT uFlags, UINT* /*pwReserved*/, 
    347                                    LPSTR pszName, UINT cchMax) 
    348 { 
    349     USES_CONVERSION; 
    350  
    351     //Check idCmd, it must be 0 or 1 since we have two menu items. 
    352     if ( idCmd > 2 ) 
    353         return E_INVALIDARG; 
    354  
    355     //If Explorer is asking for a help string, copy our string into the supplied buffer. 
    356     if (!(uFlags & GCS_HELPTEXT))  
    357         return E_INVALIDARG; 
    358  
    359     static LPCTSTR szErase        = _T("Erases the currently selected file\r\n"); 
    360     static LPCTSTR szEraseUnunsed = _T("Erases the currently selected drive's unused disk space\r\n"); 
    361     LPCTSTR pszText = (0 == idCmd) ? szErase : szEraseUnunsed; 
    362  
    363     if (uFlags & GCS_UNICODE) 
    364         //We need to cast pszName to a Unicode string, and then use the Unicode string copy API. 
    365         lstrcpynW((LPWSTR)pszName, T2CW(pszText), cchMax); 
    366     else 
    367         //Use the ANSI string copy API to return the help string. 
    368         lstrcpynA(pszName, T2CA(pszText), cchMax); 
    369  
    370     return S_OK; 
    371 } 
    372  
    373 /* 
    374 usage: Eraser <action> <arguments> 
    375 where action is 
    376 addtask                 Adds tasks to the current task list. 
    377 querymethods            Lists all registered Erasure methods. 
    378  
    379 global parameters: 
    380 --quiet, -q             Do not create a Console window to display progress. 
    381  
    382 parameters for addtask: 
    383 eraser addtask --method=<methodGUID> (--recycled | --unused=<volume> |  --dir=<directory> | [file1 [file2 [...]]]) 
    384 --method, -m            The Erasure method to use. 
    385 --recycled, -r          Erases files and folders in the recycle bin 
    386 --unused, -u            Erases unused space in the volume. 
    387 optional arguments: --unused=<drive>[,clusterTips] 
    388 clusterTips     If specified, the drive's files will have their cluster tips 
    389 erased. 
    390 --dir, --directory, -d  Erases files and folders in the directory 
    391 optional arguments: --dir=<directory>[,e=excludeMask][,i=includeMask][,delete] 
    392 excludeMask     A wildcard expression for files and folders to exclude. 
    393 includeMask     A wildcard expression for files and folders to include. 
    394 The include mask is applied before the exclude mask. 
    395 delete          Deletes the folder at the end of the erasure if specified. 
    396 file1 ... fileN         The list of files to erase. 
    397  
    398 parameters for querymethods: 
    399 eraser querymethods 
    400  
    401 no parameters to set. 
    402  
    403 All arguments are case sensitive. 
    404  
    405 */   
    406  
    407 HRESULT CCtxMenu::InvokeCommand ( LPCMINVOKECOMMANDINFO pCmdInfo ) 
    408 { 
    409     // If lpVerb really points to a string, ignore this function call and bail out. 
    410     if ( HIWORD( pCmdInfo->lpVerb )  != 0) 
    411         return E_INVALIDARG; 
    412  
    413     HRESULT result = E_INVALIDARG; 
    414     // final eraser command to call 
    415     string_type command(L"eraser "); 
    416     string_type files, directories, unuseds; 
    417  
    418     // compile the eraser command syntax 
    419     for (string_list::const_iterator i = m_szSelectedFiles.begin(); 
    420         i != m_szSelectedFiles.end(); ++i) 
    421     { 
    422         files       += L"\"" + *i + L"\" "; 
    423     } 
    424     for (string_list::const_iterator i = m_szSelectedUnused.begin(); 
    425         i != m_szSelectedUnused.end(); ++i) 
    426     { 
    427         unuseds     += L"--unused=\"" + *i + L"\" "; 
    428     } 
    429     for (string_list::const_iterator i = m_szSelectedDirectories.begin(); 
    430         i != m_szSelectedDirectories.end(); ++i) 
    431     { 
    432         directories += L"--dir=\"" + *i + L"\" "; 
    433     } 
    434  
    435     // Get the command index. 
    436     switch(LOWORD(pCmdInfo->lpVerb + 1)) 
    437     { 
    438 #if 0 
    439     case CERASER_ERASE: 
    440         { 
    441             command += L"addtask " + files + unuseds + directories; 
    442             //result = system(command.c_str()); 
    443             break; 
    444         } 
    445     case CERASER_SECURE_MOVE: 
    446         { 
    447             result = S_OK; 
    448             // we need some user interaction, thus we will have a windows form 
    449             // has to be native, so i guess a bit of work 
    450             break; 
    451         } 
    452         // NOT IMPLEMENTED METHODS 
    453         case CERASER_ERASE_ON_RESTART: 
    454         { 
    455             MessageBox (pCmdInfo->hwnd, szMsg, _T("Eraser v6 - Shell Extention Query"), MB_ICONINFORMATION ); 
    456             command += S("--restart ") + objects; 
    457             result = system(command.c_str()); 
    458             break; 
    459         } 
    460         case CERASER_SCHEDULE: 
    461         { 
    462             command += S("--schedule ") + objects; 
    463             result = system(command.c_str()); 
    464             break; 
    465         } 
    466     case CERASER_CONSOLE: 
    467         { 
    468             // interactive eraser console 
    469             break; 
    470         } 
    471 #endif 
    472     default: 
    473         { 
    474             TCHAR szMsg [MAX_PATH + 32]; 
    475             wsprintf ( szMsg, _T("Invalid Query was submitted, unable to process!\n\nCommand ID = %d\n\n"), LOWORD(pCmdInfo->lpVerb) ); 
    476             MessageBox ( pCmdInfo->hwnd, szMsg, _T("Eraser v6 - Shell Extention Query"), MB_ICONINFORMATION ); 
    477         } 
    478         return result; 
    479     } 
    480 } 
    481  
    482 MENUITEMINFO* CCtxMenu::GetSeparator() 
    483 { 
    484     MENUITEMINFO *mii = new MENUITEMINFO();      
    485     mii->cbSize = sizeof(MENUITEMINFO); 
    486     mii->fMask = MIIM_TYPE; 
    487     mii->fType = MF_SEPARATOR; 
    488     return mii; 
    489 } 
    490  
    491 HICON CCtxMenu::GetMenuIcon() 
    492 { 
    493     int smIconSize = GetSystemMetrics(SM_CXMENUCHECK); 
    494     return static_cast<HICON>(LoadImage(theApp.m_hInstance, L"Eraser", 
    495         IMAGE_ICON, smIconSize, smIconSize, LR_LOADTRANSPARENT)); 
    496 } 
    497  
    498 HBITMAP CCtxMenu::GetMenuBitmap() 
    499 { 
    500     BITMAP bitmap; 
    501     ICONINFO iconInfo; 
    502     ZeroMemory(&bitmap, sizeof(bitmap)); 
    503     ZeroMemory(&iconInfo, sizeof(iconInfo)); 
    504     Handle<HICON> icon(GetMenuIcon()); 
    505  
    506     //Try to get the icon's size, bitmap and bit depth. We will try to convert 
    507     //the bitmap into a DIB for display on Vista if it contains an alpha channel. 
    508     if (!GetIconInfo(icon, &iconInfo)) 
    509         return NULL; 
    510  
    511     Handle<HBITMAP> iconMask(iconInfo.hbmMask); 
    512     if (!GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bitmap) || 
    513         bitmap.bmBitsPixel < 32) 
    514         return iconInfo.hbmColor; 
    515  
    516     //Try converting the DDB into a DIB. 
    517     DIBSECTION dibSection; 
    518     HBITMAP dib = CreateDIB(bitmap.bmWidth, bitmap.bmHeight, NULL); 
    519     if (!GetObject(dib, sizeof(dibSection), &dibSection) || 
    520         !GetDIBits(CreateCompatibleDC(NULL), iconInfo.hbmColor, 0, bitmap.bmHeight, 
    521             dibSection.dsBm.bmBits, reinterpret_cast<BITMAPINFO*>(&dibSection.dsBmih), 
    522             DIB_RGB_COLORS)) 
    523     { 
    524         return iconInfo.hbmColor; 
    525     } 
    526  
    527     return dib; 
    528 } 
    529  
    530 HBITMAP CCtxMenu::CreateDIB(LONG width, LONG height, char** bitmapBits) 
    531 { 
    532     BITMAPINFO info; 
    533     ZeroMemory(&info, sizeof(info)); 
    534     info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    535     info.bmiHeader.biWidth = width; 
    536     info.bmiHeader.biHeight = height; 
    537     info.bmiHeader.biPlanes = 1; 
    538     info.bmiHeader.biBitCount = 32; 
    539     info.bmiHeader.biCompression = BI_RGB; 
    540     char* dibBitmapBits = NULL; 
    541     return ::CreateDIBSection(0, &info, DIB_RGB_COLORS, 
    542         reinterpret_cast<void**>(bitmapBits ? bitmapBits : &dibBitmapBits), NULL, 0); 
    543 } 
    544 } 
  • branches/erasershellext/cpp/EraserCtxMenu.vcproj

    r686 r692  
    202202        </Configuration> 
    203203    </Configurations> 
     204    <References> 
     205    </References> 
    204206    <Files> 
    205207        <Filter 
     
    342344            </File> 
    343345        </Filter> 
     346        <File 
     347            RelativePath=".\EShll.txt" 
     348            > 
     349        </File> 
    344350    </Files> 
    345351    <Globals> 
Note: See TracChangeset for help on using the changeset viewer.