In a Windows environment, whether using Visual C or Delphi or other software development tools developed, although there is a difference, it is the same: all of them run under the Windows operating system. In the process of program development, some Windows systems are often added to their own applications, such as copy, deletion, lookup, and running programs, such as files. These functions are available under the Windows operating system, obviously if they can call these features directly to reduce the size of the program and the workload of the developer, and because these functions are completed directly through the operating system. Will greatly reduce the probability of exception errors in this part of the program. Although the Windows system also has a lot of errors, the commonly used function is still relatively small, and the patch can reduce system errors by lower limits, so the programmer can put the debug error in other places, For calling system features, this part of this code can be debugged without having to put too much energy, because this part of the debugging work is made up of Microsoft when the operating system is released. This article is programmed by the shell, implements the search file, running the program, the control toolbar, the maximum and minimization window, and the operation interface of the program is shown in Figure 1:
Figure 1. Windows shell programming interface renderings
First, implementation method
The programming method directly using the Windows operating system part is to program the programming of the Windows operating system enclosure, and can be called by several programming interfaces provided by the operating system, and can even follow their own intentions. Some functions are modified and extended in the application. However, this information is not particularly much, and it is very troublesome, and it is very troublesome to program the outer shell programming with the usual programming method. It is necessary to set the relevant structural objects, and the data in such a structure. Ten more than ten times, so it is very cumbersome to configure it. Below will be described in a relatively simple shell - copy file:
... SHFILEOPSTRUCT FILEOP; // File Operation Structure Fileop.hwnd = M_HWND; // Set Handle // Setting Operation, Copy With FO_COPY, delete FO_DELETEFILEOP.WFUNC = FO_COPY; fileop.pfrom = m_source; // Source file path FileOp.pTo = m_detect; // destination file path FileOp.fFlags = FOF_ALLOWUNDO; // allow recovery FileOp.hNameMappings = NULL; FileOp.lpszProgressTitle = strTitle; // set the title SHFileOperation (& FileOp); // copy execution housing if ( Fileop.fanyOperationsaborted) // Monitoring there is no stop trace ("an Operation Was Aborted !!! / N"); ......
Although the above code is achieved, although the effect is still good, it is more troublesome, which is just a relatively simple shell operation, for some complicated shell operations such as system trays, task bars, etc. programming, even more It is particularly serious, and like this programming, the MFC does not provide a packaged program class library, which is provided only the WINAPI application interface of the system, and therefore there will be a feeling of SDK programming during program development.
Com (Component Object Model, Component Object Model) is a binary and network standard created by Microsoft, as well as Microsoft to promote and have been widely recognized. In the COM standard, the COM object is well encapsulated. The customer cannot access the details of the object, providing the unique access path to the user to access through the COM interface. There are two meanings for the COM interface: first it is a set of functions that can be modified, whereby the customer can make certain things; second, it is also more important, the interface is between the components and their clients. protocol. In other words, the interface not only defines what function available, and it defines what the object is to do when the function is called. The Windows operating system itself is a large COM component object, as well as some necessary COM interfaces to the client, so we can program the Windows housing directly through these COM interfaces. There is a little affirmation before the program is officially written: The COM interface needs to be used in the program. To operate the COM object. So first add to the code initialization COM and terminate the COM. Generally, the initialization COM and terminate COM code are usually added to the beginning of the application class's initInstance () function:
... Coinitialize (NULL); // Initialization com ... counitialize (); // Terminate COM code ...
The above two functions can be used well in the MFC program and non-MFC programs. In addition, if the program framework is based on an MFC, then simply call the AFXoleinit () function can achieve the same purpose. And don't have to explicitly call the code for terminating the COM. In the COM standard, the only way to access the COM object is a COM interface, so the COM interface is first available in writing a WINDOWS system shell. The COM interface used is iShellDispatch, which is derived from the IDispatch interface. There is definition in the VC98 / include / EXDISP.H header file of the VC installation directory. The following is some interface definitions that will be used:
! ...... EXTERN_C const IID IID_IShellDispatch; #if defined (__ cplusplus) && defined (CINTERFACE) interface DECLSPEC_UUID ( "D8F015C0-C278-11CE-A49E-444553540000") IShellDispatch: public Idispatch {public: ...... virtual HRESULT STDMETHODCALLTYPE MinimizeAll (void) = 0; virtual HRESULT STDMETHODCALLTYPE UndoMinimizeALL (void) = 0; virtual HRESULT STDMETHODCALLTYPE FileRun (void) = 0; virtual HRESULT STDMETHODCALLTYPE CascadeWindows (void) = 0; virtual HRESULT STDMETHODCALLTYPE TileVertically (void) = 0; virtual HRESULT STDMETHODCALLTYPE TileHorizontally (void) = 0; virtual HRESULT STDMETHODCALLTYPE ShutdownWindows (void) = 0; virtual HRESULT STDMETHODCALLTYPE Suspend (void) = 0; virtual HRESULT STDMETHODCALLTYPE SetTime (void) = 0; virtual HRESULT STDMETHODCALLTYPE TrayProperties (void) = 0; virtual HRESULT STDMETHODCALLTYPE Help (void) = 0; Virtual HRESULT stdmethodCallType Findfiles (Void) = 0; Virtual HResult stdmethodCallType FindComputer (void) = 0;}; ...... This interface creates a COM pair in the cocreateInstance () function The pointer to which it will be pointed to it. This function client can avoid dealing with the explicit same type of plant, in fact, the COGETCLASSOBJECT () function is also called to get the COM object class, but it creates through the class factory. The object's process is encapsulated, and only the user specifies the CLSID of the object class and the interface pointer to the interface to be output. It is clear that it is very convenient to create a COM object. You can access this pointer after getting the COM object pointer. Call the method in the COM object to implement all kinds of functions of the Windows housing. Below is some of the key code to implement this feature:
... hResult sc; // Return the result ishelldispatch * pshelldisp = null; // Initialization interface pointer // Directly create a COM object sc = COCREATEINSTANCE (CLSID_SHELL, // Specify the COM object identifier null to be created, // Specify when aggregated The external object interface pointer clsctx_server, / / Specify the component category, you can specify the process within the process. Id_idispatch, // specify the interface ID, you need to pay attention to the COM created to be // The interface ID of the object, not the interface identifier (lpvoid *) & pshelldisp of the class object; // The interface pointer of the object returned to the function returned / * In the above code, COCREATEINSTANCE first calls the CogetClassObject function to create a class factory object, and then use The interface pointer of the obtained class factory object creates a real COM object, and finally release the class object object and returns so that it is very easy to put the class factory, which is easier to use. * / if (failed (sc)) // must use Failed or SUCCECED to determine if the COM object creates a success Return; pshelldisp-> findFiles (); // Call the method in the COM object pshelldisp-> release (); // release The application-connected pointer is called the FindFiles () method of the COM object to perform the system shell operation of the lookup file. Similarly, the corresponding housing operation can be performed according to the actual needs of the actual call response, mainly include the following methods: Minimizeall: All windows minimize, the Undominimizeall: Restore window minimizes, Filerun: "Run ...", CascadeWindows : Macked window, TileVertically: Vertical Tile, Tilehorizontally: Horizontal Tile, ShutdownWindows: Close Windows, Suspend hangs, setTime: Setting time, TRAYPROPERTIES: Task Bar Properties, Help Windows: Help, FindFiles: Find file, FindComputer: Find a computer, etc.
These interfaces are defined in the VC98 / Include / EXDISP.H header file of the VC installation directory, which can be written in the case where the response is written.
Second, programming steps
1. Start Visual C 6.0, generate a Win32 application, the project is named "shell";
2. Add the application icon resource App_ICON and dialog box resources DLG_MAIN, the dialog interface is designed in the picture above;
3. Add the mouse click to process function using Class Wizard to add a mouse click to the dialog.
4, add code, compile the running program.
Third, the program code
/ # define inc_ole2 # define win32_lean_and_mean # define strict # include
#include
#include
#include
#include
#include "taskbar.h" #include "resource.h" // datastatic WNDPROC g_pfnOldProc; static HWND g_hwndButton = NULL; static HWND g_hDlg = NULL; static HINSTANCE g_hInstance; static HICON g_hIconLarge; static HICON g_hIconSmall; // functionsstatic VOID OnRunPrograms ( VOID); static VOID OnFindFiles (VOID); static VOID OnMinimizeAll (VOID); static VOID OnUndoMinimize (VOID); static VOID OnTaskbarProperties (VOID); static VOID OnAddTab (HWND); static VOID OnDeleteTab (VOID); static VOID OnInitDialog (HWND ); static VOID OnButtonActivation (VOID); // callbacksLRESULT CALLBACK APP_DlgProc (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK ButtonProc (HWND, UINT, WPARAM, LPARAM); INT APIENTRY WinMain (hINSTANCE hInstance, hINSTANCE hPrevious, LPSTR lpsz, INT iCmd) {BOOL b; g_hIconLarge = (HICON) LoadImage (hInstance, "APP_ICON", IMAGE_ICON, GetSystemMetrics (SM_CXICON), GetSystemMetrics (SM_CXICON), 0); g_hIconSmall = (HICON) LoadImage (hInstance, "APP_ICON", IMAGE_ICON, GetSystemMetrics (SM_CXSMICON), GetSystemMetric s (SM_CXSMICON), 0); // initialize OLE libraries CoInitialize (NULL); InitCommonControls (); // run main dialog g_hInstance = hInstance; b = DialogBox (hInstance, "DLG_MAIN", NULL, (DLGPROC) APP_DlgProc); / / exit DestroyIcon (g_hIconLarge); DestroyIcon (g_hIconSmall); // free the objects used by ITaskbarList DestroyWindow (g_hwndButton); OnDeleteTab (); CoUninitialize (); return b;} LRESULT CALLBACK APP_DlgProc (HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) {switch (uiMsg) {case WM_INITDIALOG: OnInitDialog (hDlg); break; case WM_COMMAND: switch (wParam) {case IDC_FINDFILES: OnFindFiles (); return 1; case IDC_RUNPROGRAMS: OnRunPrograms ();
return 1; case IDC_MINIMIZE: OnMinimizeAll (); return 1; case IDC_UNDOMINIMIZE: OnUndoMinimize (); return 1; case IDC_PROPERTIES: OnTaskbarProperties (); return 1; case IDC_ADDTAB: OnAddTab (hDlg); return 1; case IDC_DELETETAB: OnDeleteTab () ; return 1; case IDCANCEL: EndDialog (hDlg, FALSE); return 0;} break;} return 0;} VOID OnFindFiles (VOID) {HRESULT sc; IShellDispatch * pShellDisp = NULL; sc = CoCreateInstance (CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) & pShellDisp); if (FAILED (sc)) return; pShellDisp-> FindFiles (); pShellDisp-> Release (); return;} VOID OnTaskbarProperties (VOID) {HRESULT sc; IShellDispatch * pShellDisp = NULL; sc = CoCreateInstance (CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) & pShellDisp); if (FAILED (sc)) return; pShellDisp-> TrayProperties (); pShellDisp-> Release (); return;} VOID OnRunPrograms (VOID) {HRESULT SC; ishellDispatch * pshe llDisp = NULL; sc = CoCreateInstance (CLSID_Shell, NULL, CLSCTX_SERVER, IID_IShellDispatch, (LPVOID *) & pShellDisp); if (FAILED (sc)) return; pShellDisp-> FileRun (); pShellDisp-> Release (); return;} VOID OnMinimizeAll (VOID) {HRESULT sc; IShellDispatch * pShellDisp = NULL; sc = CoCreateInstance (CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) & pShellDisp); if (FAILED (sc)) return; pShellDisp-> MinimizeAll (); pShellDisp -> Release (); return;} VOID OnUndoMinimize (VOID) {HRESULT sc; IShellDispatch * pShellDisp = NULL; sc = CoCreateInstance (CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) & pShellDisp);
IF (failed (sc)) return; pshelldisp-> undominimizeall (); pshelldisp-> release (); return;} void onInitdialog (hwnd hdlg) {// set the icons (t / f as to large / small icon) g_hdlg = hDlg; SendMessage (hDlg, WM_SETICON, FALSE, (LPARAM) g_hIconSmall); SendMessage (hDlg, WM_SETICON, TRUE, (LPARAM) g_hIconLarge);} VOID OnAddTab (HWND hWnd) {static BOOL g_bFirstTime = TRUE; HRESULT sc; ITaskbarList * pDisp = NULL; sc = CoCreateInstance (CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) & pDisp); if (FAILED (sc)) return; // call the first time only if (g_bFirstTime) {g_bFirstTime = FALSE; pDisp- > HrInit (); // create a new button window g_hwndButton = CreateWindow ( "button", "My Button", WS_CLIPSIBLINGS | BS_PUSHBUTTON, 0, 0, 58, 14, hWnd, NULL, g_hInstance, NULL); g_pfnOldProc = (WNDPROC SubclassWindow (g_hwndbutton, buttonproc);} pdisp-> addtab (g_hwndbutton); pdisp-> release (); return;} void ONDeleTab (void) {HRESULT sc; itaskbarlist * PDisp = NULL; sc = CoCreateInstance (CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) & pDisp); if (FAILED (sc)) return; pDisp-> DeleteTab (g_hwndButton); pDisp-> Release (); return; } LRESULT CALLBACK ButtonProc (HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) {switch (uiMsg) {case WM_NCACTIVATE: if (wParam == TRUE) OnButtonActivation (); break;} return CallWindowProc (g_pfnOldProc, hwnd, uiMsg, wParam , lParam); void onbuttonactivation (void) {HMENU HMENU; Rect R; long x, y; // Get Some window handles hwnd h0 = findwindow ("shell_traywnd", null; hwnd h1 =
FindWindowEx (h0, NULL, "RebarWindow32", NULL); HWND h2 = FindWindowEx (h1, NULL, "MSTaskSwWClass", NULL); HWND h3 = FindWindowEx (h2, NULL, "SysTabControl32", NULL); GetWindowRect (h3, & r ); // get the currently selected button and // create a new popup menu hmenu = CreatePopupMenu (); INT i = TabCtrl_GetCurSel (h3); if (i == - 1) {AppendMenu (hmenu, MF_STRING, IDC_DELETETAB, "& Close ");} else {AppendMenu (hmenu, MF_STRING, IDC_MINIMIZE," & Minimize All "); AppendMenu (hmenu, MF_STRING, IDC_UNDOMINIMIZE," & Undo Minimize All "); AppendMenu (hmenu, MF_SEPARATOR, 0, NULL); AppendMenu (hmenu, MF_STRING, IDC_PROPERTIES, "& Taskbar Properties");} // set and immediately reset its size to get // the current width and height LONG l = TabCtrl_SetItemSize (h3, 0, 0); TabCtrl_SetItemSize (h3, LOWORD (l), HIWORD (L)); // Have the menu to Appear Just Above the button if (i == - 1) {Point Pt; getCursorpos (& PT); x = pt.x; y = pt.y;} else {x = R.LEFT LOWORD (L) * i 3; y = GetSystemMetrics - (HiWord (L) 1);} TRACKPOPUPMENU (HMENU, TPM_BOTTOMALIGN, X, Y, 0, G_HDLG, 0); DestroyMenu (HMENU); return;} four, small knot
This example introduces a simple and practical method using COM technology to implement Windows system shell, and explains the programming and idea of the COM program design for Windows system shells. Under the premise of the central ideology of this article, not only can the Windows system shells can be programmed, but also for other applications that provide COM interfaces, such as using similar methods in their own applications to the Office office. Support for the kit, etc. Therefore, the focus should not be placed in the specific program code, but is the design idea and method of the program.