home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 13
/
mediashare_13.zip
/
mediashare_13
/
ZIPPED
/
PROGRAM
/
WTJ9403.ZIP
/
FOLEY
/
DLLWIN.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-04-07
|
12KB
|
375 lines
{$S-,R-,V-,I-,B-,F-,W-,A-,G+,X+}
{$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
{*********************************************************}
{* DLLWIN.PAS 1.00 *}
{* Copyright (c) Brian Foley 1993. *}
{* All rights reserved. *}
{*********************************************************}
unit DllWin;
{-Implements TDllWin object}
interface
uses
Strings, WinTypes, WinProcs;
const
wm_First = $0000; { $0000-$7FFF window messages }
id_First = $8000; { $8000-$8FFF child id messages }
id_Internal = $8F00; { $8F00-$8FFF reserved for internal use }
nf_First = $9000; { $9000-$9FFF notification messages }
nf_Internal = $9F00; { $9F00-$9FFF reserved for internal use }
cm_First = $A000; { $A000-$FFFF command messages }
cm_Internal = $FF00; { $FF00-$FFFF reserved for internal use }
wm_Count = $8000; { Number of window messages }
id_Count = $1000; { Number of child ID messages }
nf_Count = $1000; { Number of notification messages }
cm_Count = $6000; { Number of command messages }
type
PMessage = ^TMessage;
TMessage = record
Receiver : hWnd;
Message : Word;
case Integer of
0: (wParam : Word; lParam : Longint; Result : Longint);
1: (wParamLo, wParamHi : Byte;
lParamLo, lParamHi : Word;
ResultLo, ResultHi : Word);
end;
TWindowProc =
function(HW : hWnd; Message, wParam: Word; lParam : Longint) : Longint;
TObject = object
destructor Done; virtual;
end;
PDllWin = ^TDllWin;
TDllWin = object(TObject)
hWindow : hWnd; {window handle}
hParent : hWnd; {parent's window handle}
DefaultProc : TWindowProc; {called by DefWndProc}
constructor Init(HW : hWnd; PCS : PCreateStruct);
destructor Done; virtual;
procedure DefWndProc(var Msg : TMessage); virtual;
procedure Free;
procedure ProcessMessage(var Msg : TMessage);
procedure wmCommand(var Msg : TMessage); virtual wm_First+wm_Command;
procedure wmCreate(var Msg : TMessage); virtual wm_First+wm_Create;
procedure wmClose(var Msg : TMessage); virtual wm_First+wm_Close;
procedure wmNCDestroy(var Msg : TMessage); virtual wm_First+wm_NCDestroy;
procedure wmPaint(var Msg : TMessage); virtual wm_First+wm_Paint;
procedure Paint(PaintDC : HDC; var PaintInfo : TPaintStruct); virtual;
procedure SetupWindow; virtual;
procedure CloseWindow;
function CanClose : Boolean; virtual;
end;
type
PClassRec = ^TClassRec;
TClassRec = record
ClassName : PChar; {points to class name}
VmtLink : Word; {= 'Ofs(TypeOf(ObjectName)^)'}
Init : Pointer; {= '@ObjectName.Init'}
Next : PClassRec; {set to nil initially}
end;
procedure AddWindowClass(var TCR : TClassRec);
{-Add a window class to be managed by DLLWIN}
function TDllWndFunc(hWindow : hWnd; Msg, wParam : Word;
lParam : Longint) : Longint; export;
{-Window function for classes based on TDllWin}
{======================================================================}
implementation
const
gwl_DllWin = 0;
function GetWindowPtr(HW : hWnd) : PDllWin;
{-Get the pointer to the corresponding window object}
begin
GetWindowPtr := PDllWin(GetWindowLong(HW, gwl_DllWin));
end;
procedure SetWindowPtr(HW : hWnd; PDW : PDllWin);
{-Set the pointer to the corresponding window object}
begin
SetWindowLong(HW, gwl_DllWin, Longint(PDW));
end;
{Message dispatching}
type
{Virtual method table}
TVMT = record
InstSize : Word; {size of the object}
NegCheckSum : Word; {check sum (-InstSize)}
DMTPtr : Word; {offset in data segment for DMT}
Reserved : Word;
EntryTable: record end; {the table of method addresses}
end;
{Dynamic method table}
TDMT = record
Parent : Word; {offset of parent DMT}
CacheIndex : Word; {cached index value}
CacheEntry : Word; {cached method offset}
EntryCount : Word; {number of entries in table}
EntryTable : record end; {the table of method addresses}
end;
const
__DefWndProc = SizeOf(TVMT)+4;
procedure DMTLookup; near; assembler;
{-Lookup a dynamic method call
In AX = Dynamic method index
BX = DS-based VMT offset
DX = Default method VMT offset
Out DS:DI = Location of the method's address}
asm
MOV SI,TVMT([BX]).DMTPtr {DS:SI is address of the DMT}
OR SI,SI {if offset is 0, no DMT
JE @3
CMP AX,TDMT([SI]).CacheIndex {does AX = cached index value?}
JNE @1 {if not scan the table}
MOV DI,TDMT([SI]).CacheEntry {else return the cached entry}
JMP @5 {and exit}
@1: MOV DI,DS {ES = DS}
MOV ES,DI
CLD {go forward}
@2: MOV CX,TDMT([SI]).EntryCount {CX has # of entries in table}
LEA DI,TDMT([SI]).EntryTable {ES:DI points to table}
REPNE SCASW {search for index in AX}
JE @4 {if found, save value and return}
MOV SI,TDMT([SI]).Parent {is there a parent DMT?}
OR SI,SI {if SI <> 0, search the parent DMT}
JNZ @2
@3: ADD BX,DX {BX gets VMT offset of def method}
MOV DI,BX {put it in DI and return}
JMP @5
@4: MOV DX,TDMT([SI]).EntryCount {compute offset in entry table}
DEC DX
SHL DX,1
SUB DX,CX
SHL DX,1
ADD DI,DX {add computed offset to base offset}
MOV SI,TVMT([BX]).DMTPtr {SI has offset of original DMT}
MOV TDMT([SI]).CacheIndex,AX {cache the index}
MOV TDMT([SI]).CacheEntry,DI {cache the offset of the method}
@5:
end;
procedure MsgPerform(PDW : PDllWin; var Msg : TMessage;
DVMTIndex, DefVMethod : Word); assembler;
asm
MOV DX,DefVMethod {DX has VMT offset of default virtual method}
MOV AX,DVMTIndex {AX has dynamic method index (WM_FIRST+n)}
LES DI,Msg {ES:DI points to Msg}
PUSH ES {push pointer to Msg on the stack}
PUSH DI
LES BX,PDW {ES:BX points to the window object}
PUSH ES {push PDW on the stack}
PUSH BX
MOV BX,ES:[BX] {BX has the offset of the object's VMT}
CALL DMTLookup {lookup the method to call}
CALL DWORD PTR [DI] {call the method whose address is at DS:[DI]}
end;
destructor TObject.Done;
begin
end;
{TDllWin}
constructor TDllWin.Init(HW : hWnd; PCS : PCreateStruct);
begin
SetWindowPtr(HW, @Self);
hWindow := HW;
hParent := PCS^.hwndParent;
DefaultProc := DefWindowProc;
end;
destructor TDllWin.Done;
begin
if hWindow <> 0 then
DestroyWindow(hWindow);
end;
procedure TDllWin.Free;
begin
Dispose(PDllWin(@Self), Done);
end;
procedure TDllWin.ProcessMessage(var Msg : TMessage);
begin
MsgPerform(@Self, Msg, wm_First+Msg.Message, __DefWndProc);
end;
procedure TDllWin.DefWndProc(var Msg : TMessage); assembler;
asm
LES DI,Self
PUSH TDllWin(ES:[DI]).DefaultProc.Word[2]
PUSH TDllWin(ES:[DI]).DefaultProc.Word[0]
PUSH TDllWin(ES:[DI]).hWindow
LES DI,Msg
PUSH TMessage(ES:[DI]).Message
PUSH TMessage(ES:[DI]).WParam
PUSH TMessage(ES:[DI]).LParamHi
PUSH TMessage(ES:[DI]).LParamLo
CALL CallWindowProc
LES DI,Msg
MOV TMessage(ES:[DI]).ResultLo,AX
MOV TMessage(ES:[DI]).ResultHi,DX
end;
procedure TDllWin.wmCommand(var Msg : TMessage);
begin
if (Msg.wParam < cm_Count) then
MsgPerform(@Self, Msg, cm_First+Msg.wParam, __DefWndProc)
else if (Msg.lParamHi < nf_Count) then
MsgPerform(@Self, Msg, nf_First+Msg.lParamHi, __DefWndProc)
else if Msg.wParam < id_Count then
MsgPerform(@Self, Msg, id_First+Msg.wParam, __DefWndProc)
else
DefWndProc(Msg);
end;
procedure TDllWin.wmCreate(var Msg : TMessage);
begin
SetupWindow;
DefWndProc(Msg);
end;
procedure TDllWin.wmClose(var Msg : TMessage);
begin
CloseWindow;
end;
procedure TDllWin.wmNCDestroy(var Msg : TMessage);
begin
SetWindowPtr(hWindow, nil);
DefWndProc(Msg);
hWindow := 0;
end;
procedure TDllWin.wmPaint(var Msg: TMessage);
var
PaintInfo : TPaintStruct;
begin
BeginPaint(hWindow, PaintInfo);
Paint(PaintInfo.HDC, PaintInfo);
EndPaint(hWindow, PaintInfo);
end;
procedure TDllWin.Paint(PaintDC : HDC; var PaintInfo : TPaintStruct);
begin
end;
procedure TDllWin.SetupWindow;
begin
end;
procedure TDllWin.CloseWindow;
begin
if CanClose then
Free;
end;
function TDllWin.CanClose : Boolean;
begin
CanClose := True;
end;
{support functions}
const
FirstClass : PClassRec = nil;
LastClass : PClassRec = nil;
procedure AddWindowClass(var TCR : TClassRec);
begin
if FirstClass = nil then
FirstClass := @TCR
else
LastClass^.Next := @TCR;
TCR.Next := nil;
LastClass := @TCR;
end;
function FindClassByName(Name : PChar) : PClassRec;
var
PCR : PClassRec;
begin
PCR := FirstClass;
while PCR <> nil do
if StrIComp(Name, PCR^.ClassName) = 0 then begin
FindClassByName := PCR;
Exit;
end
else
PCR := PCR^.Next;
FindClassByName := nil;
end;
function CreateWindowObject(Name : PChar; HW : hWnd;
PCS : PCreateStruct) : PDllWin; assembler;
asm
LES DI,Name {ES:DI points to Name}
PUSH ES
PUSH DI
CALL FindClassByName {see if the name is registered}
MOV BX,DX
OR BX,AX
JZ @1 {not found if DX:AX = 0}
MOV ES,DX
MOV DI,AX
PUSH HW {push HW and PCS onto the stack}
PUSH PCS.Word[2]
PUSH PCS.Word[0]
PUSH TClassRec(ES:[DI]).VmtLink {push the VMT link on the stack}
XOR AX,AX {push a nil pointer on the stack}
PUSH AX
PUSH AX
CALL TClassRec(ES:[DI]).Init {call the constructor}
@1:
end;
function TDllWndFunc(hWindow : hWnd;
Msg : Word;
wParam : Word;
lParam : Longint) : Longint;
var
PDW : PDllWin;
PCreate : PCreateStruct absolute lParam;
Message : TMessage;
begin
if Msg = wm_Create then
PDW := CreateWindowObject(PCreate^.lpszClass, hWindow, PCreate)
else
PDW := GetWindowPtr(hWindow);
if PDW = nil then
TDllWndFunc := DefWindowProc(hWindow, Msg, wParam, lParam)
else begin
Message.Receiver := hWindow;
Message.Message := Msg;
Message.wParam := wParam;
Message.lParam := lParam;
Message.Result := 1;
if Msg = wm_Command then
PDW^.wmCommand(Message)
else
PDW^.ProcessMessage(Message);
TDllWndFunc := Message.Result;
end;
end;
end.