K-Meleon
 

Home/News
Screenshots
Download
Documentation
Resources
Get Involved
Forum
Bugs
Development

SourceForge Logo
Spam Chongqed

 

 

 

 

 

 

K-Meleon

Documentation - Developers - Creating a K-Meleon (0.7) plugin

Creating a K-Meleon plugin

A K-Meleon plugin is a dll that is used in tight coupling with the browser. The plugin can subclass the browser window and overhear all messages, it can send messages to affect the browser, it can talk with other plugins, and through a set of K-Meleon callback functions it can communicate with Gecko.

All plugins in the K-Meleon plugin directory are loaded at startup, unless there exists a "kmeleon.plugins.[plugin-name].load" preference set to False.

When a plugin is loaded, K-Meleon calls GetKmeleonPlugin. This should be the only function you have to export. It should return a pointer to a kmeleonPlugin structure. This structure is the connection between the plugin and kmeleon. It holds pointers to a slew of functions, as well as some information about your plugin.

The kmeleonPlugin structure (defined in kmeleon_plugin.h) has two main sections, stuff filled in by you, and stuff filled in by kmeleon.

The things you should fill out are:

  • version - This is the first thing in the structure. It should be set to KMEL_PLUGIN_VER
  • description - This is what the user sees when he/she clicks plugins in the preferences box
  • DoMessage - This is a pointer to the function K-Meleon will call when sending messages to your dll.

The things K-Meleon will fill in are:

  • hParentInstance - This is the HINSTANCE of K-Meleon.
  • hDllInstance - This is the HINSTANCE for your plugin. You should make note of this if you want to access any resources defined in the dll.
  • A pointer to a kmeleonFunctions structure - This structure (kFuncs) holds pointers to all the functions you can call in kmeleon. This is the current set of functions:
    • SendMessage( to, from, subject, data1, data2 )
    • GetCommandIDs( num )
    • NavigateTo( url, windowState )
    • GetDocInfo( mainWnd )
    • GetPreference( type, preference, ret, defaultVal )
    • SetPreference( type, preference, val [, update] )
    • SetStatusBarText( str )
    • GetMozillaSessionHistory( titles, count, index )
    • GotoHistoryIndex( index )
    • RegisterBand( hWnd, name [, visibleOnMenu] )
    • CreateToolbar( parentWnd [, style] )
    • GetID( strID )
    • GetInfoAtPoint( x, y )
    • CommandAtPoint( command, x, y )
    • GetGlobalVar( type, preference, ret )

Right after loading up your dll, and getting the kmeleonPlugin structure, kmeleon will call DoMessage() with an 'Init' message. This is only done once, ever. You can use this time to load graphics and stuff.

Right before unloading your dll, kmeleon calls DoMessage() with a 'Quit' message. This is also only done once. You can use this time to unload those graphics and stuff you loaded earlier. Note that by the time the 'Quit' message is sent, there are no more kmeleon windows on the screen.

Every time a new window is created, kmeleon will send a 'Create' message. A reference to the parent window comes as a parameter.

Kmeleon will send a 'Config' message when the user clicks "Config" in the preferences box. A reference to the preferences box comes as a parameter.

Kmeleon will send a 'DoMenu' message when it encounters your plugin in menus.cfg. A reference to the HMENU, that you should play with, comes as the first parameter. The second parameter is a pointer to a character array holding whatever was put in parenthesis inside menus.cfg. Use that text to create different menu entry commands for your plugin and/or to set the text shown in menus.

Kmeleon will send a 'DoRebar' message soon after 'Create'. It will pass the HWND of the rebar control for the new window that was just created. You can use this time to create a rebar band or 2 or 3... You don't have to worry about size and position, kmeleon should handle that for you. Also note that the rebar id will be ignored and overwritten.

Kmeleon will send 'DoAccel' when it encounters a line for your plugin in accel.cfg. It will pass a pointer to a character array holding whatever was put in parenthesis inside accel.cfg. Use that text to create different accel commands for your plugin. You should return a command id for your command. Use GetCommandIDs() to reserve command ids.

To allow macros to control your plugin, you can accept extra subjects in DoMessage() calls. A pluginmsg() command passes up to two parameters from the macro call. A pluginmsgex() command uses one parameter to send information and a second to point at a text buffer receiving the reply. The simple plugin() command only use the available accel commands.

You can also export a DrawBitmap() function, which is called by the bmp_menu plugin whenever it's time for you to draw your menu icons. If you don't define it, you won't get menu icons.

In order to receive messages, such as WM_COMMAND from your menu items, you should subclass any newly created window, so that messages are routed through your plugin.


#include "stdafx.h"

#define KMELEON_PLUGIN_EXPORTS
#include "kmeleon_plugin.h"

BOOL APIENTRY DllMain (
	HANDLE hModule,
	DWORD ul_reason_for_call,
	LPVOID lpReserved) { 

  return TRUE;
}

LRESULT CALLBACK WndProc (
	HWND hWnd, UINT message, 
	WPARAM wParam, 
	LPARAM lParam);

void * KMeleonWndProc;

int Init();
void Create(HWND parent);
void Config(HWND parent);
void Quit();
void DoMenu(HMENU menu, char *param);
long DoMessage(const char *to, const char *from, const char *subject, long data1, long data2);
void DoRebar(HWND rebarWnd);
int DoAccel(char *param);

kmeleonPlugin kPlugin = {
   KMEL_PLUGIN_VER,
   "A Plugin That Does Nothing",
   DoMessage
};

long DoMessage(const char *to, const char *from, const char *subject, long data1, long data2)
{
   if (to[0] == '*' || stricmp(to, kPlugin.dllname) == 0) {
      if (stricmp(subject, "Init") == 0) {
         Init();
      }
      else if (stricmp(subject, "Create") == 0) {
         Create((HWND)data1);
      }
      else if (stricmp(subject, "Config") == 0) {
         Config((HWND)data1);
      }
      else if (stricmp(subject, "Quit") == 0) {
         Quit();
      }
      else if (stricmp(subject, "DoMenu") == 0) {
         DoMenu((HMENU)data1, (char *)data2);
      }
      else if (stricmp(subject, "DoRebar") == 0) {
         DoRebar((HWND)data1);
      }
      else if (stricmp(subject, "DoAccel") == 0) {
          *(int *)data2 = DoAccel((char *)data1);
      }
      else return 0;

      return 1;
   }
   return 0;
}

int Init(){
   return true;
}

void Create(HWND parent){
   KMeleonWndProc = (void *) GetWindowLong(parent, GWL_WNDPROC);
   SetWindowLong(parent, GWL_WNDPROC, (LONG)WndProc);
}

void Config(HWND parent){
   MessageBox(parent, "This plugin does absolutely nothing", "Nothing", 0);
}

void Quit(){
}

void DoMenu(HMENU menu, char *param){
}

int DoAccel(char *param) {
   return 0;
}

void DoRebar(HWND rebarWnd){
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
   if (message == WM_COMMAND){
	  WORD command = LOWORD(wParam);
   }

   return CallWindowProc((WNDPROC)KMeleonWndProc, hWnd, message, wParam, lParam);
}

extern "C" {
   KMELEON_PLUGIN kmeleonPlugin *GetKmeleonPlugin() {
	  return &kPlugin;
   }

   KMELEON_PLUGIN int DrawBitmap(DRAWITEMSTRUCT *dis) {
	  return 14; // 14 = icon width
   }
}


Ulf
(c) 2000-2001 kmeleon.org. All rights reserved.
design by splif.