From: Wade Humeniuk
Subject: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <9m22d0$fj6$1@news3.cadvision.com>
I want to try to create windows outside of CAPI within LWW.  Does anyone
know how I can hook into the windows event handler that CAPI uses to receive
windows events and route them into my own handler?  Has anyone done this
already?

Would this be the way to go, or instead, do something like the example code
for OpenGL does and grab the window handle and then use external calls to
the win32 API to do drawing and such?

The reason I what to do this is use the Windows GDI interface to do alpha
blending and have better control of Blitting operations (the operation
argument for
gp:pixblt seems to have no effect anymore, though I seem to remember it
having one).

Wade

From: Greg Menke
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <m3lmkb9tpn.fsf@europa.pienet>
> I want to try to create windows outside of CAPI within LWW.  Does anyone
> know how I can hook into the windows event handler that CAPI uses to receive
> windows events and route them into my own handler?  Has anyone done this
> already?
> 
> Would this be the way to go, or instead, do something like the example code
> for OpenGL does and grab the window handle and then use external calls to
> the win32 API to do drawing and such?

If you can get the window handle, then this would be the way to go-
though it won't get you directly into the message stream.  If you
really needed that, you might rig a dll function to insert itself in
the window procedure chain and have it copy significant messages out
to LW via FFI callbacks.  I've not done it, though it <should> be
possible, or at least something like it, from what I've read so far of
LW's FFI.  It might even be possible to get the message to pass thru
LW, in which case your Lisp code could be a real window procedure.

Gregm
From: Clive Tong
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <uvgjd7sxm.fsf@scientia.com>
Fernando <···@wanadoo.es> writes:

> I'm not sure if I understand what you're asking... Do you want to subclass
> this 'external' window? If yes, it should be rather easy, as long as you can
> pass the address of a lisp callback function to Windows.  I never tried it,
> but it should be possible to stop the GC from messing around with this
> function's address... :-?

This happens automatically - the stub used to return into the foreign
callable is statically allocated as you can see from: 

CL-USER 1 > (fli:define-foreign-callable fred () (print "called"))
FRED

CL-USER 2 > (fli:make-pointer :symbol-name 'fred :functionp t)
#<Pointer to type :FUNCTION = #x2000309A>

and using room you can see that the address #x2000309a lies in a
static segment (and hence isn't going to be moved by the garbage
collector).
From: Paul Tarvydas
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <l_th7.13140$f01.2887976@news3.rdc1.on.home.com>
"Fernando" <···@wanadoo.es> wrote in message
·······································@4ax.com...
> On Wed, 22 Aug 2001 22:55:10 -0600, "Wade Humeniuk"
<········@cadvision.com>
> wrote:
>
> >I want to try to create windows outside of CAPI within LWW.  Does anyone

It's surprisingly straight-forward.  I experimented around and managed to
create C-based (Win32) windows and MFC-based dialogs inside DLL's that LWW
could control.  For reasons that escape me now (:-) I managed to subclass a
Windows window in C whose WndProc was written in Lisp.

The worst problem I had was grinding through the MS documentation and trying
to determine how to write windowing stuff within a DLL (all the examples I
found assumed that WinMain was owned by the C++ side of the world - this
isn't necessary).

The question that kept coming up was "when calling CreateWindow, what
parameter do I supply for the 'HWND hWndParent' parameter?".  The answer
(unless you're using Win16 :-) is to use the result of
"GetModuleHandle(NULL)".

The only other problem was getting all of the :stdcall's and :cdecl's the
right way around in the FLI definitions.

pt
·········@tscontrols.com
From: Wade Humeniuk
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <9m5vgm$vu7$1@news3.cadvision.com>
>
> It's surprisingly straight-forward.  I experimented around and managed to
> create C-based (Win32) windows and MFC-based dialogs inside DLL's that LWW
> could control.  For reasons that escape me now (:-) I managed to subclass
a
> Windows window in C whose WndProc was written in Lisp.
>

From the online MSDN manual,

typedef struct _WNDCLASS {
    UINT       style;
    WNDPROC    lpfnWndProc;
    int        cbClsExtra;
    int        cbWndExtra;
    HINSTANCE  hInstance;
    HICON      hIcon;
    HCURSOR    hCursor;
    HBRUSH     hbrBackground;
    LPCTSTR    lpszMenuName;
    LPCTSTR    lpszClassName;
} WNDCLASS, *PWNDCLASS;

HWND CreateWindow(
  LPCTSTR lpClassName,  // registered class name
  LPCTSTR lpWindowName, // window name
  DWORD dwStyle,        // window style
  int x,                // horizontal position of window
  int y,                // vertical position of window
  int nWidth,           // window width
  int nHeight,          // window height
  HWND hWndParent,      // handle to parent or owner window
  HMENU hMenu,          // menu handle or child identifier
  HINSTANCE hInstance,  // handle to application instance
  LPVOID lpParam        // window-creation data
);

I am assuming that you registered a window class with lpfnWndProc set it to
a Lisp external callable function.  Then you called CreateWindow or
CreateWindowEx with the new class.  I am assuming that LispWorks has a
thread servicing the GetMessage function and is dispatching messages for
your window.

There seem to be some hooks into the win32 message/window system directly
with

win32::def-window-proc
win32::create-window
win32::create-window-ex
win32::make-message-function
win32::add-window-message-function
...

(Use the package-browser I just posted and browse the win32 package)

I think I would perfer to tap into the functionality that is already
available.

IF Xanalys would make some documentation available to how to use these
internal functions...

As an aside,it would be nice if LispWorks had function documentation, as in

(defun foo ()
    "This is an internal LispWorks function - args are....., valid values
are...,see other..."


I am interested that you said you could create and control MFC dialogs.  I
am not familiar with MFC, but isn't it a set of C++ GUI classes and other
componets?  How did you use their functionality?

> The worst problem I had was grinding through the MS documentation and
trying
> to determine how to write windowing stuff within a DLL (all the examples I
> found assumed that WinMain was owned by the C++ side of the world - this
> isn't necessary).

Wade
From: Paul Tarvydas
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <7OPh7.17730$f01.4305939@news3.rdc1.on.home.com>
"Wade Humeniuk" <········@cadvision.com> wrote in message
·················@news3.cadvision.com...
...
> I am assuming that you registered a window class with lpfnWndProc set it
to
> a Lisp external callable function.  Then you called CreateWindow or
> CreateWindowEx with the new class.  I am assuming that LispWorks has a
> thread servicing the GetMessage function and is dispatching messages for
> your window.

Basically, yes.  My actual goal was to build dynamically-loadable 'C' dll
components (including Windows-manipulation components), so I did everything
with pointers and hashtables (and this is the reason why posting my code
would not be useful to anyone - the simple Windows stuff is hidden by the
overhead of detecting and managing dynamic components).

I did not suss out exactly how LispWorks dispatched messages to my window,
but I did presume that by using GetModuleHandle(NULL), I was creating
windows whose parent was LWW.  Certainly, when my program crashed, the call
stack was littered with LWW machinery.

...
> I am interested that you said you could create and control MFC dialogs.  I
> am not familiar with MFC, but isn't it a set of C++ GUI classes and other
> componets?  How did you use their functionality?
>

Yes, MFC is the "Microsoft Foundation Classes" - the C++ framework supplied
with Microsoft Visual Studio - the development toolkit from Microsoft.  It
has a fairly intense learning curve.  In the documentation, technical note
TN011 explains how to build a DLL that uses MFC (it's simple - you create a
static variable that holds your CWinApp-derived object, then make calls to
it).  The only reason that I mentioned it at all, was that for the longest
time, the documentation had me convinced that MFC used all sorts of magic
and wouldn't work without owning the WinMain function.  Stumbling onto TN011
unravelled the problem.  [Note that this is exactly the opposite to the
comments in the rest of your message regarding lack of LWW docs - MSDN comes
with two CD's full of documentation, but that's not helpful, either :-].  I
do not yet know if an SDI or MDI frame can be built inside a DLL (I do know
that MFC and Windows was built via a process of random accretion of features
and, thus, it is not valid to extrapolate theories about its operation
without performing specific tests.  The fact that dialogs can be created
from within a DLL does not infer that more aggressive features like SDI and
MDI (single-document-interface and multiple-document-interface, resp.) can
be created from within a DLL).

I was interested in hooking to MFC because my company has written many apps
in MFC.  If I were to start from scratch and desparately wanted to hook to
existing GUI libraries, I'd investigate ActiveX and hooking to Visual Basic.
VB is apparently the language of choice for Windows development (it
certainly has better/more convenient GUI-building facilities than Visual
C++).

All of that said, I've been using CAPI for the last few months and I intend
to keep doing so.  Compared to stuff like MFC, CAPI is wonderfully simple
and understandable.

pt
From: Marc Battyani
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <8B1762EE24D2FAFD.5111880774C3CF71.221B138FC3A7CF92@lp.airnews.net>
"Wade Humeniuk" <········@cadvision.com> wrote in message
·················@news3.cadvision.com...
> I want to try to create windows outside of CAPI within LWW.  Does anyone
> know how I can hook into the windows event handler that CAPI uses to
receive
> windows events and route them into my own handler?  Has anyone done this
> already?
>
> Would this be the way to go, or instead, do something like the example
code
> for OpenGL does and grab the window handle and then use external calls to
> the win32 API to do drawing and such?
>
> The reason I what to do this is use the Windows GDI interface to do alpha
> blending and have better control of Blitting operations (the operation
> argument for
> gp:pixblt seems to have no effect anymore, though I seem to remember it
> having one).

I don't use CAPI but I make all the GUI of my industrial software with the
Windows API.
I defined the Win32 functions I need with FLI and it works very well.

(fli:define-foreign-callable ("lisp-wnd-func" :result-type (:one-of :long
(:boolean :long)))
        ((hWnd :hwnd) (Msg :ulong) (wParam :ulong) (lParam :long))
...
(w32:def-window-proc hWnd Msg wParam lParam))))

(defvar *lisp-wnd-func* (fli:make-pointer :symbol-name "lisp-wnd-func"
:functionp t))

You can then give this pointer to the register-class function.

Marc
From: Wade Humeniuk
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <9m62fr$1sm$1@news3.cadvision.com>
> I don't use CAPI but I make all the GUI of my industrial software with the
> Windows API.
> I defined the Win32 functions I need with FLI and it works very well.
>
> (fli:define-foreign-callable ("lisp-wnd-func" :result-type (:one-of :long
> (:boolean :long)))
>         ((hWnd :hwnd) (Msg :ulong) (wParam :ulong) (lParam :long))
> ...
> (w32:def-window-proc hWnd Msg wParam lParam))))
>
> (defvar *lisp-wnd-func* (fli:make-pointer :symbol-name "lisp-wnd-func"
> :functionp t))
>
> You can then give this pointer to the register-class function.

Thanks Marc,

This may be what I resort to.

I really want to use CAPI, but there is some functionality to do with
graphics-ports that I need.

These are from the GDI interface:

AlphaBlend - no comparable graphics-port function, want something like
gp:aplha-blend
BitBlt - maps to gp:pixblt, but operation arg does not seem to have an
effect anymore
TransparentBlt - no comparable interface, need something like
gp:transparent-blt
RoundRect - draw a round rectangle, need gp:draw-round-rectangle

And..

Nice, but not absolutely necessary, some kind of interface to GDI+,
particularly the class Image (supports BMP, GIF, JPEG,EXIF, PNG and TIFF).
But how to call C++ libraries from LispWorks? (besides writing a C wrapper
dll around the C++ classes)

Also the user gestures that use in the input-model of an output-pane are
only a subset of the possible gestures (messages) that you can get from
Windows.

Wade
From: Marc Battyani
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <5AC33F239F0F8761.45017B27A10FFF35.FE1209E360CA1033@lp.airnews.net>
"Wade Humeniuk" <········@cadvision.com> wrote in message
·················@news3.cadvision.com...

> But how to call C++ libraries from LispWorks? (besides writing a C wrapper
> dll around the C++ classes)

Write Lisp code that generate the wrapper. This is what I do when I have
tedious repetitive C++ wrapper code to write. It works very well, I recently
generated 22000 lines of C++ from 675 lines of Lisp.

Marc
From: Wade Humeniuk
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <9m6cbr$6hk$1@news3.cadvision.com>
> > But how to call C++ libraries from LispWorks? (besides writing a C
wrapper
> > dll around the C++ classes)
>
> Write Lisp code that generate the wrapper. This is what I do when I have
> tedious repetitive C++ wrapper code to write. It works very well, I
recently
> generated 22000 lines of C++ from 675 lines of Lisp.

Do you use any window's resources (dialogs, images, menus) in your Lisp
image?  I mean do you attach some resources to the LispWorks executable
(with some kind of resource tool)?

Wade
From: Marc Battyani
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <77A1BE3BE4E53139.A5019EAF9BF17FB9.34E4409EE2558314@lp.airnews.net>
"Wade Humeniuk" <········@cadvision.com> wrote in message
·················@news3.cadvision.com...
> > > But how to call C++ libraries from LispWorks? (besides writing a C
> wrapper
> > > dll around the C++ classes)
> >
> > Write Lisp code that generate the wrapper. This is what I do when I have
> > tedious repetitive C++ wrapper code to write. It works very well, I
> recently
> > generated 22000 lines of C++ from 675 lines of Lisp.
>
> Do you use any window's resources (dialogs, images, menus) in your Lisp
> image?  I mean do you attach some resources to the LispWorks executable
> (with some kind of resource tool)?

I don't use resource as all is dynamic. The dialogs are contructed
dynamically from Lisp through a create-window for the dialog and then other
create-windows for the edits, buttons etc. The menus are also dynamic.I have
never used a dialog editor. I much prefer to write code than ressources. Or,
in that case, write code that generate the dialogs from the CLOS classes.
The code approach has some nice possibilities like recomputing the layout of
the dialog when the user resizes it.

Marc
From: Paul Tarvydas
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <I7Rh7.17798$f01.4419024@news3.rdc1.on.home.com>
"Wade Humeniuk" <········@cadvision.com> wrote in message
·················@news3.cadvision.com...

> But how to call C++ libraries from LispWorks? (besides writing a C wrapper
> dll around the C++ classes)

Are you aware of the 'extern "C" { ... }" stuff in msoft C++?

In a C++ program, you can turn off name-mangling and use the C calling
convention (no "this" pointer) by wrapping code inside an extern "C"
declaration.  For example:

SomeClass variable;
extern "C" {
  __declspec(dllexport) int LispCallableFunc (int x) {
    return variable.someMethod (x);
  }
}

The __declspec(dllexport) macro declares a DLL entry point.  The extern "C"
stuff ensures that the name "LispCallableFunc" is not mangled.

pt
From: Marc Battyani
Subject: Re: LispWorks, How to Hook Into Windows Event Handler
Date: 
Message-ID: <71696CD339AB6F66.698A6BF3B60A2816.61EBE70ED08BCCAF@lp.airnews.net>
"Fernando" <···@wanadoo.es> wrote in message
·······································@4ax.com...
> On Fri, 24 Aug 2001 18:15:26 +0200, "Marc Battyani"
> <·············@fractalconcept.com> wrote:
>
>
> >I don't use CAPI but I make all the GUI of my industrial software with
the
> >Windows API.
>
> Why did you use the raw api instead of capi? O:-) Sounds slightly
> masochistic... ;-)

When I use a language I take the standard and then I write everything that
is not in it. I may also use some source code if available and of sufficient
quality but I try to never use proprietary stuff.
Also I do like writing application frameworks. 10 years ago, I've written a
C++ application framework like MFC, but better for sure ;-), that was
completely portable to Windows and Mac. To be completely portable I did not
use any widget (controls, edit, buttons, etc.) but only basic functions like
DrawLine, DrawText etc... It was fun, I could have a Mac look and feel in my
Windows application and vice versa. I don't earn this code anymore now (I
sold it to the Sage Group) but I still like to write application frameworks.
My current one, is 100% in Lisp, Windows only and create and manage all the
GUI automatically from the CLOS classes. I can even generate C++ code for
dialog boxes if I want to (the code is ugly, not for human use but the
dialogs are nice).

Marc