Use Shell extension to implement the source code Statistics Program)

Source: Internet
Author: User

Use shell extension to implement the source code statistics program

Author/king_dxs

Download source code

I. Preface
In the Windows Resource Manager window, we have seen software such as WinZIP and WinRAR that can add several menu items to the default shortcut menu of files or folders, it allows users to directly compress/decompress the files in the windows without entering the software, which is very convenient for users. This is undoubtedly a good application model, it is what we call the Shell extension technology. This article will take a common source code statistics program as an example to illustrate how to implement Shell extension technology. Below is the program running:


Figure 1 sample code run 1


Figure 2 sample code run 2

II. Implementation Principle
To expand the default menu of files or folders in any Windows window, we must enable Windows to load our program segment in the displayed shortcut menu. Generally, we use the COM component to achieve this purpose. COM components include in-process service programs, local service programs, and remote service programs. To let explorer load and execute our code, you must use an in-process service program, which is represented by DLL. After the DLL is loaded, it is mapped to the virtual address space of the executable program, we provide some interfaces to explorer. When explorer calls shortcut menus while displaying them, we can do what we want in those interfaces, such as adding shortcut menus, implement the menu item function and so on to implement Shell extension .?
As for source code statistics, it is not difficult to implement. Here I take the C/C ++-style source code as an example and apply a simple statistical rule. When a statistical file is used, we read the code content into the cache, determine whether each character is a linefeed (\ n). If yes, add 1 to the count. Of course, we make statistics on folders more meaningful, so we can use recursive methods to traverse all the files in the folder and find out the valid files (here I only count the C/C ++ program, therefore, only the suffix is. C ,. CPP ,. according to the previous method, the total number of lines of all codes in the folder can be obtained.

Iii. Implementation Process

  • 1. Create a VC project, select the atl com Appwizard type, and name the project srccount to go to the next step;
  • 2. select the service type as DLL (the default option). You do not need the support of MFC here (it is easier to compile code if you add the support of MFC, but the program loses the short and concise nature of ATL, the bear's paw and the fish cannot have both of them :)), go to the next step;
  • 3. Now the project configuration information is displayed. Click OK to create an ATL COM component.
  • 4. Now we add a component object and select new ATL Object… on the shortcut menu of the project ..., In the subsequent dialog box, select simple object, click Next, enter countlines in "short name", select the default option on the attributes properties page, and click OK. We can see that an interface icountlines has been added in the VC workspace.
  • 5. Add a method for this interface. Right-click the shortcut menu of the interface and choose Add method ..., The method is named GetFileLines and its parameters are [in] BSTR * pFilePath, [out] int * lines. It is used to count the number of lines in the source code file. The following is the main implementation of the Code:
    //////////////////////////////////////// ////////////////////////////////////////: Get the number of lines of code in the source file // parameter: 1. pfilepath: enter a parameter to specify the path of the source file; // 2. lines: output parameter to obtain the number of lines of code in the source file. Stdmethodimp ccountlines: getfilelines (BSTR * pfilepath, int * lines) {// The total number of lines containing the Code int totalline = 0 ;? // Open the file handle hfile = createfile (tchar *) pfilepath ,? Generic_read, file_share_read, null, open_existing, file_attribute_normal, null); If (handle)-1 = hfile) {* lines =-1; return s_false ;} // open the buffer to store the file content DWORD dwfilesize = getfilesize (hfile, null); byte * lpbuffer = new byte [dwfilesize]; memset (lpbuffer, 0, dwfilesize );? DWORD dwread = 0; bool breadfile = readfile (hfile, lpbuffer, dwfilesize, & dwread, null); Assert (breadfile & dwread = dwfilesize );? // Here we only use a simple statistical rule, that is, the mark for (unsigned I = 0; I <dwfilesize; I ++) {If (lpbuffer [I] = ''\ n') {totalline ++ ;}// release the buffer Delete [] lpbuffer; closehandle (hfile); // Save the number of lines of code * lines = totalline + 1 ;? Return s_ OK ;}
  • 6. Add the GetFolderLines method. It calculates the code of each file in the folder Based on the recursive algorithm. The code is not written here. See the source code.
  • 7. Add IShellExtInit and IContextMenu to the base class of CCountLines.
  • 8.when the browser javaser.exe loads our program segment, it will call the IShellExtInit interface initialization menu, and then call the interface IContexMenu to process the right-click menu, so we will expose the above interface in the DLL component. You only need to add an interface to the in_com_map () and END_COM_MAP () macros.
  • 9. Call the Initialize () method of the IShellExtInit interface when initializing the shortcut menu in the Windows window. The function prototype is as follows:
    HRESULT Initialize(LPCITEMIDLIST pidlFolder,LPDATAOBJECT lpdobj, HKEY hkeyProgID );

    We will perform necessary initialization actions in this function, such as saving the complete path of the file name and the key value of the registry.

  • 10. The browser calls the IContexMenu interface to explain and execute commands. This is the main part of the source code statistics. We call the above algorithm to calculate the code of the selected folder according to the agreed rules. This interface has the following three methods to implement:
// Display the command description on the status bar of the window. It is worth noting that we need to process the ASCII and UNICODE codes to adapt to different systems. HRESULT GetCommandString (UINT idCmd, UINT uFlags, UINT * pwReserved, LPSTR pszName, UINT cchMax); // run the menu command to implement specific functions. HRESULT InvokeCommand (LPCMINVOKECOMMANDINFO pici); // Add the shortcut menu HRESULT QueryContextMenu (HMENU hmenu, UINT indexMenu, UINT id1_first, UINT idCmdLast, UINT uFlags) here );

Here, only the implementation of InvokeCommand () is used as an example. For more information, see the source code.

//////////////////////////////////////// ////////////////////////////////////////: Run the shortcut menu command // parameter: 1. pici: HRESULT CCountLines: InvokeCommand (LPCMINVOKECOMMANDINFO pici) {BOOL bEx = FALSE; BOOL bUnicode = FALSE ;? If (pici-> cbSize = sizeof (CMINVOKECOMMANDINFOEX) {bEx = TRUE; if (pici-> fMask & CMIC_MASK_UNICODE) {bUnicode = TRUE ;}} // The lpVerb parameter has two identifiers: for example, if the height is not 0, it is a command string. Otherwise, the shortcut menu offset value is provided at the low level. If (! BUnicode & HIWORD (pici-> lpVerb) {if (StrCmpIA (pici-> lpVerb, "Stat. ") {return E_FAIL;} else if (bUnicode & HIWORD (CMINVOKECOMMANDINFOEX *) pici)-> lpVerbW) {if (StrCmpIW (CMINVOKECOMMANDINFOEX *) pici)-> lpVerbW, L "Stat. ") {return E_FAIL;} else if (LOWORD (pici-> lpVerb )! = IDM_SRC_COUNT) {return E_FAIL;} else {assert (0 = HIWORD (pici-> lpVerb); int lines = 0; TCHAR szTitle [MAX_PATH] = {0 }; TCHAR szMsg [MAX_PATH] = {0}; TCHAR szFormat [MAX_PATH] = {0}; memset (szMsg, 0, MAX_PATH ); // Save the current cursor and reset it to the wait shape HCURSOR hOldCursor = GetCursor ();?? HCURSOR hNewCursor = LoadCursor (_ Module. GetModuleInstance (), MAKEINTRESOURCE (IDC_COUNT_WAIT); assert (hNewCursor); SetCursor (hNewCursor );? TCHAR szTemp [MAX_PATH] = {0}; LoadString (_ Module. getModuleInstance (), IDS_TOTAL_LINES, szFormat, MAX_PATH); if (SUCCEEDED (GetFolderLines (BSTR *) & m_pszPath, & lines) {wsprintf (szMsg, szFormat, (LPTSTR) m_pszPath, lines);} // restore the default cursor shape SetCursor (hOldCursor); // display the Statistics Code LoadString (_ Module. getModuleInstance (), IDS_TITLE, szTitle, MAX_PATH); MessageBox (pici-> hwnd, szMsg, szTitle, MB_ OK | MB_ICONINFORMATION);} return S_ OK ;}

4. Others
This program is an in-process service program and runs regsvr32 for registration (Note: In the VC compiler, the COM component will automatically call regsvr32 for registration during compilation. Please refer to the project configuration file ), for example, if the component has been copied to C: \ WinNT \ System32, we will enter the following command line for registration:


Figure 3 sample code run 3

Because it is statistics on folders, you still need

    HKEY_CLASSES_ROOT\Directory\Shellex\ContextMenuHandlers\

Next, create a new item named SrcCount. Its default key value is the GUID of the component. Here:

    {548773BA-874E-4C02-9DC7-B7A096772C7D}

Now, in resource manager, click the shortcut menu on the folder. Do you see any more menu items: source code statistics ..., When you click this item, you can perform Code statistics.
This program is mainly to show how to use shell extension, so the focus is on the program design method, not to do everything perfect. There are also some details worth improving, such as the shell extended menu beautification effect (such as the Popular software WinZip, WinRAR and other interface effects, and the shortcut menu can be painted with bitmap). In addition, the functions of the program can be further expanded. This article mainly collects statistics on the C/C ++ source code. We can extend the relevant statistical rules, you can collect statistics on the source code of compilation, Java, Delphi, and other languages. You can also select and set statistical rules in the form of a dialog box. If you are interested, you can try it.
Although this program is compiled in Windows XP and VC ++ 6.0, it can be used in Windows 9x/NT/2000/XP. This article briefly introduces the implementation method of shell extension technology, for details about the language, please refer to the source code attached to this article, or send an email to me.

V. References
1. msdn, Microsoft Corp.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.