Snippet Manager!
So, I started this bloody ages ago and it kinda sorta got abandoned. :( BUT NOW IT’S BACK! And better than ever, with a plugin system which I just blogged about. :)
Unfortunately, it is still windows only. I will build it for Linux some day, I promise!
You can check it out here, I’m rather pleased with it so far, even if the development is really really slow.
wxWidgets: Loading Symbols from a DLL (and using ::Connect)
[Apologies if the entry is a little unclear, I just threw this together in about 10 minutes, I wanna get it out there... it's fucking hard to find any sort of information when it comes to this at the moment]
Quick entry, gonna turn this into a tutorial soon. The code is a bit of a mess, since I was just throwing stuff together while I was figuring this out. I’ll tidy it up when it’s tutorial tiems.
Basically, I recently developed a [url=http://snip.gd/plugins.php]plugin system[/url] for my [url=http://snip.gd/]snippet manager[/url]. The way it works is simple: It loads symbols from a DLL into the application, which can be called from a dynamically created menu. First off, the main code [this is the messy bit for the time being]
This code opens a subdirectory within the working directory called “plugins”, and grabs all the DLLs from them. If the DLL contains a symbol called SnippetManagerPluginMain (the only required symbol for the plugins, I kept them simple) it will add it to the menu.
Additionally, it also checks for two optional optional symbols, which are pretty cool. They simply return strings, which assign the name and the keyboard shortcut for the plugin. If neither is set, it has no keyboard shortcut, and the name defaults to the name of the DLL file.
/// <plugin SYSTEM> <!-- ALPHA! --> #if defined(__WXMSW__) // windows plugins - load ./plugins/*.dll if(wxDir::Exists(wxT("./plugins/"))) { wxDir plugin_dir(wxT("./plugins/")); if(plugin_dir.HasFiles()) { wxArrayString files; wxDir::GetAllFiles(wxT("./plugins/"), &files); wxMenu* plugin_menu = new wxMenu(wxT("")); wxDynamicLibrary* lib; wxString label; char* ks; bool showmenu = false; for(unsigned int i = 0; i < files.GetCount(); i++) { lib = new wxDynamicLibrary(); if(files.Item(i).Find(wxT(".dll")) != -1) { lib->Load(files[i]); if(lib->HasSymbol(L"SnippetManagerPluginMain")) { showmenu = true; if(lib->HasSymbol(L"SnippetManagerPluginName")) { label = wxString(((SnippetManagerPluginName)lib->GetSymbol(L"SnippetManagerPluginName"))(), wxConvUTF8); } else { label = files[i].AfterFirst('\\').AfterFirst('\\').BeforeLast('.'); } this->plugins.push_back((SnippetManagerPlugin)lib->GetSymbol(L"SnippetManagerPluginMain")); if(lib->HasSymbol(L"SnippetManagerKeyboardShortcut")) { ks = ((SnippetManagerKeyboardShortcut)lib->GetSymbol(L"SnippetManagerKeyboardShortcut"))(); label += L"\t" + wxString(ks, wxConvUTF8); } plugin_menu->Append(wxID_PLUGIN + i, label); Connect(wxID_PLUGIN + i, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(Snippet_ManagerFrame::handle_plugin)); } } } if(showmenu) { mbar->Append(plugin_menu, wxT("&Plugins")); } } } #endif /// </plugin>[
In order to bind the events to the menu, the ::Connect method is called. This is an alternative to using EVENT_TABLE, and allows events to be allocated dynamically at runtime. wxID_PLUGIN is a custom variable, and basically, any of the menu items within the menu will call the main frame’s [il]handle_plugin[/il] method. The important part, however, is the fact that each one has a different ID, even though they use the same method.
The method itself then uses the ID of the event calling it to lookup the DLL’s symbol, which were added in this->plugins.
void Snippet_ManagerFrame::handle_plugin(wxCommandEvent &e) { this->plugins[e.GetId() - wxID_PLUGIN](this->ui->uid.mb_str(), fill_p_snip(this->ui->get_active_stc()->snip, this->ui->get_active_stc()->GetText())); }
Of course, some of the code here doesn’t really mean jack all, since there are custom methods and stuff used in it. But the base of it is clear. I’ll try to write another (small) application and a tutorial covering the steps over the weekend.
Until then, have fun! :)
Categories
Blogroll
- My other blog
- Beki Sutcliffe
- Charlie Baker
- Denis Delimarschi
- Derek Ackley
- Ian Mellett
- Joe Otero
- Josh Erickson
- Ryan Alford
- Cupcake Hax0r (I write here!)
