head.gif (2436 bytes) Latest source from CVS My Binaries My sourcecode

Contact me at :

04 July 99

Stephen Hassard e-mailed me to let me know of a problem in the popups when you navigate them with the keyboard where you can go beyond the end of the popups. He sent me the code snippet to fix it as well and I merged it in. I took the opportunity to also merge in several bug fixes that jugg had sent me some time back as well. These fixed a memory leak that occurred when the About dialog was opened several times as well as removed a few redundancies from the desktop sources.

I then proceeded to look into the Desktop.c file as I had noticed (as well as heard complaints on the mailing list <g>) of right-cliking on a task on the task bar not bringing up the context menu for that particular application. I found that the current code consisted of one line for the WM_RBUTTONDOWN event:

SendMessage((HWND)GetWindowLong(hwnd, GWL_USERDATA), 0x313, 0, GetMessagePos());

I replaced that with a tried and tested code fragment from my LSTasks - slightly modified to suit the present case:

	int i, x, y;
	POINT pt;
	BOOL result;
	HMENU hMenu;
	RECT r;

	x = pt.x;
	y = pt.y;
	for (i=0; i= 0) {
		hMenu = GetSystemMenu(winList[i].Handle, FALSE);
		result = TrackPopupMenu(hMenu, TPM_RETURNCMD|TPM_LEFTBUTTON, x, y, 0, hwnd, NULL);
		if (result) {
			SendMessage(winList[i].Handle, WM_SYSCOMMAND, (WPARAM)result, MAKELPARAM(x, y));
	GetClientRect(hwnd, &r);
	InvalidateRect(hwnd, &r, TRUE);

That seemed to fix the context menu problem. I have put the new sources and binaries on my site. Incidentally, some people have complained about the Lsvwm.Dll on my binaries not working properly. I have never used the VWM and when I tried to load the Lsvwm.Dll on my machine, I got nothing. So I still don't know whether I've got the right DLL or not but I'll check into this again.

03 July 99

Amirul Shukry e-mailed me to say that he'd had to roll his own project files for Hook.Dll as the project file on CVS is for VC++ 6.0 and he's got VC++ 5.0 and that he had managed to get a 5kb Hook.Dll file as opposed to the 36kb one that was in my binary distribution. As a difference of 30kb could become pretty hefty when it is loaded into every running process, I checked into this and found that this was due to the project being set to compile as simply "Multithreaded" instead of "Multithreaded DLL" in the project options - incidentally, changing that particular option drops down the debug version of DLL sizes too (it changed Hook.Dll from 207kb to 76kb). So I have updated the binaries to include the new smaller Hook.Dll (and fixed the problem of the wrong VWM Dll being included in the last binary package).

As a couple of news sites reported that the new Hook.Dll was 76kb down from 207kb, I came back and re-read what I'd written. I realized that it was pretty confusing - my sentences sometimes tend to run on till they get pretty convoluted :-) Anyway, the reduction of 76kb from 207kb was for the debug build. The release build of Hook.Dll is now a tiny 4kb as opposed to the original size of 36kb. Just thought I'd clarify <g>

02 July 99

I received an e-mail from Matt Welch who pointed out that I might have included an old Lsapi.Dll with my binary ZIP file and I checked out what he said and he was perfectly right! So I have updated the ZIP binary file to include a completely new build off my machine (and that might include anything else that I'd done since the last build <g>)

I finally got around to working on the popup stuff I'd mentioned yesterday. It was actually inspired by a suggestion that SynTruth posted on the LiteStep mailing list where he mentioned that it would be nice if the popups could support a full background image like Lichen on WindowMaker provides as seen here and here. I looked at the two screenshots and it seemed to me at least that the popups were actually mirroring the desktop image and that is what I decided to do.

The coding actually turned out to be quite simple as I had to do only two changes which involved maybe about ten lines of code. I had to introduces a new Step.Rc option called PopupUseDeskImage and I disabled the painting of background bitmaps for individual popup items if PopupUseDeskImage was specified in Step.Rc. I also disabled the drawing of the bevel for individual popup items. I then used the PaintDesktop command to paint the desktop as it appears beneath the popup window to get the desktop image on the popups and then drew a bevel around the entire popups. Note that I left the title and bottom images alone so that they would still be drawn. And that was it ... voila! A new option for the popups! :-) You can find the brand spanking new binaries and sources on my site, linked above.

I know that the next request is going to be the facility to change the background image from the desktop image to a user specified one but I'm not going to look into that for a while as I'm onto a new project - namely, right-click menus on the task bar. When I first checked this, it wouldn't work at all but today it works fine except for a command prompt window. I don't know what's up with that but I intend to find out.

01 July 99

I ran into Maduin on IRC last evening and began talking to him about his ideas for a new way of implementing configuration information as opposed to the current Step.Rc format. There had been some discussion on the Dev team mailing list about the idea as well and Maduin had come to realize that the idea wasn't really aimed at core modules but at third-party modules and this dovetailed with my personal opinion that third-party module config info should be kept in a separate file than Step.Rc (like the initial idea for Modules.Ini) and I proposed to him that he work on the idea so that we could use it as part of the SDK for modules in b25. This would enable us to have a separate module config file that was much more extensible than the INI format and would also (hopefully) lead to all modules having a graphical configurator - that's the direction that I'd like to see LS modules (and even the core) take. Now this won't mean that those who like to mess with the files with a text editor won't have their chance but only that those who don't like to get their hands dirty won't have to :-)

I was planning to do some work on the popups today but as I have to go out, I don't know whether I'll get around to that. Will update later as to whether I get anything done there or not. I have received some oblique comments about the look of the site <g> Hey, don't blame me, I'm a coder not a graphic designer :-) Anybody wants to do a redesign of the site, you are welcome to send me a suggestion (and graphics, layout etc.) You know where to find me - if not just mail FahimF@email.com.

Well I'm back and what do I find in my inbox but an e-mail from Lowspirit with a complete site design and since I liked his design - which was both simple and clean - I will use it. Thanks Lowspirit! As for work, I haven't done any today at all as I've been out book hunting and it is almost 9:00 p.m. currently but I guess it can always wait till tomorrow :-)

I checked out the latest CVS source feed and it still doesn't contain the hook DLL source directory and so, I checked things out a bit further and what do you know? It isn't there because it hadn't got uploaded from my machine :-) I had created the hook source directory on the CVS but hadn't updated the source files, duh! So I finally did that and the hook source should be there on the next CVS feed.

30 June 99

I had been working on shell hooks for a while now since Peter Edwards had figured out how to implement them when Explorer is not the shell. The problem with the shell hooks turned out to be one of initializaton - you had to make certain calls to SystemParametersInfo before calling SetWindowsHookEx to set the shell hook. Here is the code fragment that Peter sent me as an example of how to do the initialization:


memset(&mm, 0, sizeof(MINIMIZEDMETRICS));
mm.cbSize = sizeof(MINIMIZEDMETRICS);
mm.iArrange |= ARW_HIDE; // ARW_HIDE == 8

Once I got that implemented, I discovered that the shell hook had to be in a separate DLL as the hook procedure is loaded into the address space of every new process that starts and that meant writing a brand new DLL for LiteStep that would simply implement the shell hooks. This took a little while as lots of real life stuff continued to crop up in my life - such as being let go by my current employer. Anyway, the time away from work gave me the necessary time and solitude to finish the shell hook and see how it worked under LiteStep.

I decided to make the shell hook DLL as small as possible as it was going to be loaded into the address space of every process which started after it. I also decided to make the DLL store the handle to the main window of the process which sets the shell hook so that the hook DLL can send messages back to the window to notify it of situations that the calling process wanted to monitor. This was the final code that I came up with:

** Hook.Def **

** Hook.h **
#ifndef __HOOK_H
#define __HOOK_H

#include "../lsapi/lsapi.h"
#include "../litestep/wharfdata.h"

#ifdef HOOK_DLL
	#define HOOK_EXPORT __declspec(dllexport)
	#define HOOK_EXPORT __declspec(dllimport)

#ifdef __cplusplus
extern "C" {

HOOK_EXPORT void AttachHookDll(HWND hwndParent);

#ifdef __cplusplus

LRESULT CALLBACK ShellProc(int nCode, WPARAM wParam, LPARAM lParam);


** Hook.Cpp **
#define STRICT

#define HOOK_DLL
#include "hook.h"

#pragma data_seg("SHAREDATA")
static HHOOK g_hHook=0;
static HWND parent=NULL;
#pragma data_seg()

void AttachHookDll(HWND hwndParent) {

	if (hwndParent) {
		parent = hwndParent;
		memset(&mm, 0, sizeof(MINIMIZEDMETRICS));
		mm.cbSize = sizeof(MINIMIZEDMETRICS);
		mm.iArrange |= ARW_HIDE; // ARW_HIDE == 8
		g_hHook = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, hInst, 0);
		if (!g_hHook)
			MessageBox(parent, "Error creating shell Hook!", "Hook", MB_OK);
	} else {
		g_hHook = 0;

LRESULT CALLBACK ShellProc(int nCode, WPARAM wParam, LPARAM lParam)
	HWND hwnd = (HWND)wParam;

	if (0 > nCode)
		return (CallNextHookEx(g_hHook, nCode, wParam, lParam));
	switch (nCode) {
		PostMessage(parent, LM_MINMAXWIN, (WPARAM)hwnd, 0);
		PostMessage(parent, LM_ACTIVEWIN, (WPARAM)hwnd, 0);
		PostMessage(parent, LM_ADDWINDOW, (WPARAM)hwnd, 0);
		PostMessage(parent, LM_REMOVEWINDOW, (WPARAM)hwnd, 0);
	return 0;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
	if (fdwReason == DLL_PROCESS_ATTACH) {
		// We don't need thread notifications for what we're doing.  Thus, get
		// rid of them, thereby eliminating some of the overhead of this DLL,
		// which will end up in nearly every GUI process anyhow.
		hInst = hinstDLL;
	return TRUE;

The passing of messages from the shell hook DLL led to me adding a few new messages to LSAPI so that the shell DLL could inform Desktop.Dll (or any other module that used Hook.Dll for that matter) about the creation of a new window, destruction of a new window, minimizing of a window or changing of active windows. Once all of that was done, I had to rip out the old code from Desktop.C that implemented a timer that would check for open app windows every 250ns and instead build the windows list based on messages sent from the hook procedure. So that is where the current build stands.

Back to Home Page Back to Developer Journal Back to Journal Archive

Site Design by : Lowspirit