&xwp; now comes with a mini-widget sample (toolkit\miniwdgt.c) which contains an absolute minimum widget without any fancy functionality. All this widget does is display a question mark.

This mini widget was added to show you something to start with. It can definitely be improved. It does not

At the very least, a plug-in DLL must do the following:
  1. It must export three procedures by ordinal.

    a) The "init" export (ordinal 1) gets called once only by the &xcenter; when your DLL gets loaded. The DLL can get loaded in situations other than widget creation, so do not expect this to always be the case. On init, the DLL should register the widget's PM window class (by calling WinRegisterClass). In addition, it can import functions from XFLDR.DLL, whose module handle is given to it (this is optional). However, it must always return a pointer to the array of XCENTERWIDGETCLASS structures in the DLL so that the &xcenter; knows about the classes in the DLL.

    See toolkit\miniwdgt.c for how this is done.

    b) The "uninit" export (ordinal 2) gets called when the DLL is unloaded by the &xcenter;. This can do cleanup, if necessary.

    c) The "query version" export (ordinal 3) gets called even before the "init" export to check the &xwp; version number that this widget requires.

  2. The plug-in DLL must then contain a PM window procedure for the widget class. In the mini widget sample, this is the fnwpSampleWidget procedure. The "Init" export is reponsible for calling WinRegisterClass on that window procedure to create a PM window class from it.

    This is the usual switch/case stuff that is used with every PM window procedure. There are a couple of extra considerations to be made though, which are explained below.

  3. On WM_CREATE, the widget must store the XCENTERWIDGET pointer it receives with mp1 in its QWL_USER window word. That's why the mini widget sample calls WinSetWindowPtr(hwnd, QWL_USER, mp1); on WM_CREATE.

  4. On WM_CONTROL, it should handle notifications from the &xcenter;. The &xcenter; will send WM_CONTROL messages to the widget when it wants to know the widget's size, for example.

    The notification codes that the &xcenter; uses with WM_CONTROL are listed in toolkit\center.h. There will probably be more of them in the future.

  5. Normally, with PM, all unprocessed messages are forwarded to WinDefWindowProc. With widgets, this is different: you must always pass unprocessed messages to the "&xcenter; default widget procedure", whose address is given to your widget in the XCENTERWIDGET structure on WM_CREATE in the pfnwpDefWidgetProc field. (Yes, this is the reason why you must store that structure in your window words.)

    If you do not pass unused messages on, you will severely hurt the widget's functionality. Even worse, you will cause memory leaks because the default widget procedure is responsible for cleaning up resources and important &xcenter; notifications.

  6. Even if you do your own processing on WM_DESTROY, you must always, always pass WM_DESTROY on to pfnwpDefWidgetProc. Otherwise the &xcenter; cannot clean up your widget's resources properly.