Implement Windows shell programming through COM technology

Source: Internet
Author: User
In a Windows environment, even though there are differences between Visual C ++, Delphi, and other software development tools, there is one thing that is the same: these are all running in windows. In the process of program development, you often need to add some Windows functions to your applications, such as copying, deleting, searching, and running files. These functions are available in the Windows operating system. Obviously, calling these functions directly from the system will not only reduce the program size and the workload of developers, in addition, because these functions are directly completed through the operating system, the probability of exceptions in these programs will be greatly reduced. Although there are many errors in Windows systems, there are still few errors in common functions, and system errors can be reduced through patches, therefore, programmers can focus on debugging errors elsewhere in the application. For code that calls system functions, you do not have to invest too much effort in debugging, this part of debugging has already been done by Microsoft when the operating system was released. This article uses shell programming to implement the functions of searching for files, running programs, control tool bars, and minimizing windows. The program running interface is shown in:


Figure 1. Windows Shell editing interface

  I. Implementation Method

The preceding programming method for directly using some features of the Windows operating system is to program the Windows operating system shell, some functions of the operating system can be called through several programming interfaces provided by the operating system, and some functions can be modified and extended in the application according to your own intentions. However, there are not many materials in this regard, and most of them are not detailed. It is very troublesome to use the common programming method for shell programming, it is easy to set the relevant structure objects, and there are dozens or more data members in such a structure, so the configuration is very cumbersome, the following is an example of a simple shell operation-copy a file:

......
Shfileopstruct fileop; // file operation structure of the shell
Fileop. hwnd = m_hwnd; // set the handle
// Sets the operation mode. fo_copy is used for copying and fo_delete is used for deleting.
Fileop. wfunc = fo_copy;
Fileop. pfrom = m_source; // source file path
Fileop. PTO = m_detect; // target file path
Fileop. fflags = fof_allowundo; // allow Restoration
Fileop. hnamemappings = NULL;
Fileop. lpszprogresstitle = strtitle; // set the title
Shfileoperation (& fileop); // execute shell copy
If (fileop. fanyoperationsaborted) // monitor for abort
Trace ("an operation was aborted !!! /N ");
......

Although the above Code is quite effective, it is quite troublesome to implement it. This is just a simple shell operation, the programming of complex shell operations such as system pallets and task bars is especially serious. In addition, the encapsulated program class library is not provided in MFC, only the winapi application interface of the system is provided, so there is often a feeling of SDK programming in the Process of program development.

COM (Component Object Model, Component Object Model) is a binary and network standard created by Microsoft. It is also a component standard that Microsoft has vigorously promoted and widely recognized. In the com standard, the COM object is well encapsulated, and the customer cannot access the implementation details of the object. The only access channel provided to the user is access through the COM interface. The COM interface has two meanings: first, it is a group of functions that can be called, so that the user can let the object do something. Second, it is more important, interfaces are protocols between components and their customer programs. That is to say, the interface not only defines the available functions, but also defines what the object will do when these functions are called. As a large COM component object, the Windows operating system also provides some necessary com interfaces to the client program. Therefore, we can use these com interfaces to program the Windows Shell directly.

Before the program is formally written and designed, it is certain that the COM interface must be used in the program to operate the COM object. Therefore, you must first add the code for initializing and terminating COM. Generally, the initialization COM and termination com code are added at the beginning of the initinstance () function of the application class and before the return:

......
Coinitialize (null); // initialize com
......
Couninitialize (); // terminate the com code
......

The above two functions can be used well in both the MFC program and the non-MFC program. In addition, if the program framework is based on MFC, you can simply call the afxoleinit () function to achieve the same purpose. And you do not need to explicitly call the code to terminate COM. In the com standard, the only way to access the COM object is the COM interface. Therefore, you must first obtain the COM interface provided by the Program for operating the Windows system shell. The COM interface used is ishelldispatch, which is derived from the idispatch interface and is in the vc98/include/exdisp directory of the VC installation directory. the H header file has definitions. Some interface definitions to be used are excerpted below:

......
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 will get a pointer to the COM object when the cocreateinstance () function creates a COM Object. Through this function client program, you can avoid dealing with similar factories explicitly, in fact, this function also calls the cogetclassobject () function internally to obtain the class factory of COM objects, but it encapsulates the process of creating objects through the class factory, you only need to specify the CLSID of the object class and the interface pointer and Interface ID to be output. Obviously, it is very convenient to directly create a COM object, after obtaining the COM Object Pointer, you can use this pointer to access methods in the COM object to call various functions of the Windows Shell. The following are some key code for implementing this function:

......
Hresult SC; // return the result
Ishelldispatch * pshelldisp = NULL; // initialize the interface pointer
// Directly create a COM Object
SC = cocreateinstance (clsid_shell, // specifies the COM object identifier to be created
Null, // specifies the interface pointer of the external object to be aggregated
Clsctx_server, // specifies the component category. You can specify components outside the process or control objects in the process.
Iid_idispatch, // specify the interface ID. Note that
// The Interface ID of the created COM Object, not the interface identifier of the class factory object
(Lpvoid *) & pshelldisp); // stores the interface pointer of the object returned by the function
/* In the above Code, cocreateinstance first calls the cogetclassobject function to create a class factory object, and then uses the obtained class factory object interface pointer to create a real COM object, finally, release the class factory object and return it. This effectively shields the class factory and makes it easier for users to use it. */
If (failed (SC) // you must use failed or succecced to determine whether the COM object is successfully created.
Return;
Pshelldisp-> findfiles (); // call the methods in the COM Object
Pshelldisp-> release (); // release the requested interface pointer
......

Here, the pshelldisp interface pointer is used to call the findfiles () method of the COM object to find the system shell of the file. Similarly, you can flexibly call the response method to execute shell operations as needed. There are mainly the following methods: minimizeall: minimize all windows, undominimizeall: Minimize recovery windows, filerun: start Menu "run... ", Cascadewindows: stacked window, tilevertically: vertical tile, tilehorizontally: horizontal tile, shutdownwindows: Disable Windows, suspend computer, settime: Set Time, trayproperties: taskbar attribute, help windows: help, findfiles: Find Files, findcomputer: Find computers, etc.

These interfaces are defined in the vc98/include/exdisp. h header file in the VC installation directory. You can compile the response shell operation code by viewing the file.

Ii. programming steps

1. Start visual c ++ 6.0 and generate a Win32 application named "shell ";

2. Add the application icon resource app_icon and the dialog box resource dlg_main. the dialog box interface is designed as one;

3. Use Class Wizard to add and click processing functions for the buttons in the dialog box;

4. Add code and compile and run the program.

  3. program code

/////////////////////////////////////
# Define inc_ole2
# Define win32_lean_and_mean
# Define strict
# Include
# Include
# Include
# Include
# Include
# Include "Taskbar. H"
# Include "resource. H"
// Data
Static 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;
// Functions
Static 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 );
// Callbacks
Lresult callback app_dlgproc (hwnd, uint, wparam, lparam );
Lresult callback buttonproc (hwnd, uint, wparam, lparam );
Int apientry winmain (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), getsystemmetrics (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, 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 * pshelldisp = 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)
{
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 ondeletetab (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, uint uimsg, wparam, lparam)
{
Switch (uimsg)
{
Case wm_ncactivate:
If (wparam = true)
Onbuttonactivation ();
Break;
}
Return callwindowproc (g_pfnoldproc, hwnd, uimsg, wparam, lparam );
}

Void onbuttonactivation (void)
{
Hmenu;
Rect R;
Long X, Y;
// Get some window handles
Hwnd h0 = findwindow ("shell_traywnd", null );
Hwnd H1 = find1_wex (H0, null, "rebarwindow32", null );
Hwnd H2 = find1_wex (H1, null, "mstaskswwclass", null );
Hwnd h3 = find1_wex (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 (sm_cyscreen)-(hiword (l) + 1 );
}
Trackpopupmenu (hmenu, tpm_bottomalign, X, Y, 0, g_hdlg, 0 );
Destroymenu (hmenu );
Return;
}

  Iv. Summary

This example introduces a simple and practical method to implement Windows shell program by using COM technology, and describes the program design of Windows Shell and the methods and ideas of COM program design. After mastering the central idea of programming in this article, we can not only program the Windows system shell, but also program some other applications that provide the COM interface, for example, you can use a similar method to add support for office suites in your own applications. Therefore, the focus should not be on specific program code, but on the design ideas and methods of the program.

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.