Introduction
Currently, many popular software products support plug-ins, such as Winamp and realplay. By using plug-in technology, these software provides considerable convenience for future software upgrades and feature extensions. It is particularly important that by using plug-in technology, the function expansion of the software will not be completely limited by the software vendors, as long as any third-party developer or programmer complies with the plug-in interface standards provided by the software to develop plug-ins, it is completely compatible with the main software, this makes it possible for users to personalize the application. Based on the many advantages of plug-in technology, this article will discuss the creation of plug-ins, application support for plug-ins, and other issues.
Design Concept and plug-in interface standards
Generally, applications that support plug-ins usually place plug-ins in a specified directory. During program execution, the system first searches for plug-ins in this directory, if yes, the plug-in is inserted into the application, and the application is responsible for releasing the plug-in when it stops running.
There is no fixed rule on the form in which the plug-in is provided. It can be an independent application, a dynamic link library, or some other file formats, regardless of the form in which the plug-in is provided, it is easy to use. This article uses a Flexible Dynamic Link Library as a plug-in. The Dynamic Link Library provides the calling of plug-in functions for applications through external export functions, it is also easy for applications to dynamically load dynamic linked libraries. This is different from the previous use of the dynamic link library. Generally, the application knows in advance which dynamic link libraries need to be used, and what functions the Dynamic Link Library provides, applications that allow the use of plug-ins cannot predict how many plug-ins will be developed by third-party developers after the software is released, and what functions are provided by the plug-ins. Therefore, you need to establish a unified interface standard between the application and plug-ins that allow the plug-in and use this interface standard to manage all the later plug-ins. Here, the main program and plug-ins are implemented through a standard DLL export function, mainly used to create plug-in objects in the main program:
Bool plug_createobject (void ** pobj)
{
* Pobj = new cpluga;
Return * pobj! = NULL;
}
The class cpluga is derived from the base class cplugbase in the dynamic link library and provides most of the main functions of the plug-in, such as obtaining plug-in icons, functional interface functions provided by plug-ins, and releasing plug-ins. The structure of the Base Class cplugbase is as follows:
Class cplugbase
{
Public:
Cplugbase (){};
Virtual hicon getIcon () = 0;
Virtual void interface (int K) = 0;
Virtual void release () = 0;
};
Considering that the main program cannot predict the number of plug-ins to be inserted, to facilitate the management of plug-in objects, the template class carray is used to store and manage plug-in objects, the array managed by this template class is a plug_st structure object. The plug_st structure records the cplugbase pointer provided by the plug-in class and the instance handle of the Dynamic Link Library as the plug-in carrier. The specific definitions are as follows:
Typedef struct {
Cplugbase * pobj;
Hinstance hins;
} Plug_st, * lpplug_st;
In addition, every time a new plug-in is added to an application, the associated buttons or menus should be added to the main program interface, this allows you to call internal function functions of the plug-in through buttons or menus on the main program interface. This article aims to achieve this by adding a button to the toolbar. The icon on the button is provided by the plug-in, and the application obtains the icon handle through the getIcon () function of the plug-in class, and draw it on the toolbar button.
Extended plug-in support for common applications
The plug-in support function is not exclusive to big-name software such as Winamp and realplay. Any common application can be extended as an application supporting the plug-in through program encoding. Generally, this part of the extension code is completed in the main framework class. Based on the above ideas, first search for the plug-ins in the subdirectory under the application directory to see if any plug-ins are provided in the form of dynamic link libraries, if the dynamic link library is not found in this directory, it indicates that there are no plug-ins currently, so the program does not need to do further processing. If the plug-ins are found, insert them to the application one by one. The code for searching plug-ins is as follows:
......
Getmodulefilename (null, filename, max_path); // get the Application Path
Strpath = cstring (filename); // you can specify the subdirectory Plugins in the current directory.
Strpath = strpath. Left (strpath. getlength ()-cstring (afxgetappname (). getlength ()-4) + cstring ("plugins ");
Cstring strfindfile = strpath + "\ *. dll ";
// Search for all dynamic link libraries under the subdirectory plugins
Win32_find_data WFD;
Handle HF = findfirstfile (strfindfile, & WFD); // find the first
If (HF! = Invalid_handle_value)
{
// Insert the plug-in to the application if it is found
Createplug (strpath + "\" + WFD. cfilename );
While (findnextfile (HF, & WFD) // continue searching for the next
Createplug (strpath + "\" + WFD. cfilename );
Findclose (HF); // end the search
}
The createplug () function is used to load the plug-in to the application. Its Parameters specify the absolute path of the plug-in to be loaded. During implementation, first load the plug-in module to the memory through the loadlibrary () function, and save the obtained instance handle to the hins of the plug_st structure, finally, add the structure object to the carray Template Class Object m_arrplugobj. The main implementation code is as follows:
Plug_st STPS;
Zeromemory (& STPS, sizeof (STPs ));
STPs. hins = loadlibrary (szplug );
Pfn_plug_createobject pfunc = (pfn_plug_createobject) getprocaddress (STPs. hins, _ T ("plug_createobject "));
If (pfunc (void **) & STPs. pobj ))
M_arrplugobj.add (STPs );
In the interaction with users, the following process is taken: Extract all plug-in icons from the plug-in dynamic link library and place them in the image list, finally, create the corresponding button on the floating toolbar and draw the plug-in icon on it. The resource ID of the create button on the toolbar starts from id_plug_pointer and accumulates the resource IDs of the later plug-ins. For specific implementation, refer to the following code:
Int size = m_arrplugobj.getsize ();
M_imagelist.create (16, 16, ilc_color32, size + 1, size );
For (INT I = 0; I <size; I ++)
M_imagelist.add (m_arrplugobj [I]. pobj-> getIcon ());
Ctoolbarctrl & ctrlbar = m_wndplugbar.gettoolbarctrl ();
Ctrlbar. setimagelist (& m_imagelist );
Tbbutton BTN;
For (I = 0; I <size; I ++)
{
BTN. ibitmap = I;
BTN. idcommand = id_plug_pointer + I; // command to be sent when button pressed
BTN. fsstate = tbstate_enabled; // button state -- see below
BTN. fsstyle = tbstyle_button; // button style -- see below
BTN. dwdata = 0; // application-defined value
BTN. istring = NULL; // zero-based index of Button label string
Ctrlbar. addbuttons (1, & BTN );
}
The command responses to the buttons of each plug-in cannot be mapped using the common on_command macro, but the command ing to an ID range must be implemented using the on_command_range macro:
Begin_message_map (cmainframe, cmdiframewnd)
......
On_command_range (id_plug_pointer, id_plug_pointer + 256, onplughit)
End_message_map ()
......
Void cmainframe: onplughit (uint NID)
{
Int id = NID-id_plug_pointer;
If (ID> = 0 & id <m_arrplugobj.getsize ())
{
// Call the function of the corresponding plug-in.
If (m_arrplugobj [ID]. pobj)
M_arrplugobj [ID]. pobj-> interface (ID );
}
}
To ensure the effective release of system resources, you must ensure that all loaded plug-in resources are released before the program ends:
For (INT I = 0; I <m_arrplugobj.getsize (); I ++)
{
If (m_arrplugobj [I]. pobj)
M_arrplugobj [I]. pobj-> release ();
If (m_arrplugobj [I]. hins)
Freelibrary (m_arrplugobj [I]. hins );
}
M_arrplugobj.removeall ();
So far, as long as the application finds the existence of the dynamic link library of the plug-in under the Plugins subdirectory, it will load it into the program and use the toolbar button to complete user interaction with the newly added plug-in. To remove a plug-in from a program, you only need to delete the corresponding plug-in module under the plug-in directory.
Plug-in Creation
The creation of the plug-in is actually the creation of the dynamic link library, so it is relatively simple in general, but there are some differences between the dynamic link library as the plug-in carrier and the normal dynamic link library. For example, the plug-in must provide icons for the main application, in addition, you must set it to "use MFC in a static library" during compilation so that all resources can be packaged into the plug-in module during compilation, otherwise, an icon cannot be drawn on the toolbar button when the application inserts a plug-in. When creating a plug-in, the plug-in must also follow the interface standards of the same main program. This is mainly reflected by the export function:
Library "pluga"
Description 'pluga Windows dynamic link library'
Exports
Plug_createobject @ 1
The export function plug_createobject is used to create a plug-in object in the application:
Bool winapi plug_createobject (void ** pobj)
{
* Pobj = new cpluga;
Return * pobj! = NULL;
}
As mentioned above, cpluga is a derived class of the base class cplugbase. You can reload several virtual functions of cplugbase as needed to implement some unique functions of this plug-in. In addition, because the main program obtains the plug-in icon through getIcon (), it must first use loadicon () when the dynamic link library is loaded () the function loads the icon to the memory and saves its handle to m_hicon. Wait for the main program to get it through the getIcon () function, the eobject () function is used to release a Dynamic Linked Library.
Summary
By using the preceding method, you can add plug-in support functions for common applications, and expand the functions of the software in the form of plug-ins after the software is released. The operation process is flexible and convenient. Due to this extension, various functional modules of the software are distributed across different plug-ins. During software upgrade or maintenance, you only need to replace the corresponding plug-ins, this can play a positive role in software upgrade and maintenance. The program described in this article is compiled by Microsoft Visual C ++ 6.0 under Windows 98.