4 uses KOL
, Windows
, Messages
;
7 TWndMethod
= procedure(var Message: TMessage
) of object;
9 function MakeObjectInstance(Method
: TWndMethod
): Pointer;
10 procedure FreeObjectInstance(ObjectInstance
: Pointer);
11 function AllocateHWnd(Method
: TWndMethod
): HWND
;
12 procedure DeallocateHWnd(Wnd
: HWND
);
13 function IncColor(C
: TColor
; D
: integer): TColor
;
14 procedure AjustBitmap(const M
: KOL
.PBitmap
; S
, C
: TColor
);
19 PObjectInstance
= ^TObjectInstance
;
20 TObjectInstance
= packed record
24 0: (Next
: PObjectInstance
);
25 1: (Method
: TWndMethod
);
29 PInstanceBlock
= ^TInstanceBlock
;
30 TInstanceBlock
= packed record
32 Code
: array[1..2] of Byte;
34 Instances
: array[0..100] of TObjectInstance
;
38 InstBlockList
: PInstanceBlock
;
39 InstBlockCount
: integer;
40 InstFreeList
: PObjectInstance
;
42 { Standard window procedure }
43 { In ECX = Address of method pointer }
46 function StdWndProc(Window
: HWND
; Message, WParam
: Longint;
47 LParam
: Longint): Longint; stdcall; assembler;
55 MOV EAX,[ECX].Longint
[4]
61 { Allocate an object instance }
63 function CalcJmpOffset(Src
, Dest
: Pointer): Longint;
65 Result
:= Longint(Dest
) - (Longint(Src
) + 5);
68 function MakeObjectInstance(Method
: TWndMethod
): Pointer;
70 BlockCode
: array[1..2] of Byte = (
72 $E9); { JMP StdWndProc }
75 Block
: PInstanceBlock
;
76 Instance
: PObjectInstance
;
78 if InstFreeList
= nil then
80 Block
:= VirtualAlloc(nil, PageSize
, MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
81 Block
^.Next
:= InstBlockList
;
82 Move(BlockCode
, Block
^.Code
, SizeOf(BlockCode
));
83 Block
^.WndProcPtr
:= Pointer(CalcJmpOffset(@Block
^.Code
[2], @StdWndProc
));
84 Instance
:= @Block
^.Instances
;
86 Instance
^.Code
:= $E8; { CALL NEAR PTR Offset }
87 Instance
^.Offset
:= CalcJmpOffset(Instance
, @Block
^.Code
);
88 Instance
^.Next
:= InstFreeList
;
89 InstFreeList
:= Instance
;
90 Inc(Longint(Instance
), SizeOf(TObjectInstance
));
91 until Longint(Instance
) - Longint(Block
) >= SizeOf(TInstanceBlock
);
92 InstBlockList
:= Block
;
94 Result
:= InstFreeList
;
95 Instance
:= InstFreeList
;
96 InstFreeList
:= Instance
^.Next
;
97 Instance
^.Method
:= Method
;
101 { Free an object instance }
103 procedure FreeObjectInstance(ObjectInstance
: Pointer);
105 if (ObjectInstance
<> nil) and (InstBlockCount
> 0) then
107 PObjectInstance(ObjectInstance
)^.Next
:= InstFreeList
;
108 InstFreeList
:= ObjectInstance
;
110 if InstBlockCount
= 0 then begin
111 VirtualFree(InstBlockList
, 0, MEM_RELEASE
);
112 InstBlockList
:= nil;
113 ObjectInstance
:= nil;
119 UtilWindowClass
: TWndClass
= (
121 lpfnWndProc
: @DefWindowProc
;
129 lpszClassName
: 'KOLFakeUtilWindow');
131 function AllocateHWnd(Method
: TWndMethod
): HWND
;
133 TempClass
: TWndClass
;
134 ClassRegistered
: Boolean;
136 UtilWindowClass
.hInstance
:= HInstance
;
137 ClassRegistered
:= GetClassInfo(HInstance
, UtilWindowClass
.lpszClassName
,
139 if not ClassRegistered
or (TempClass
.lpfnWndProc
<> @DefWindowProc
) then
141 if ClassRegistered
then
142 Windows
.UnregisterClass(UtilWindowClass
.lpszClassName
, HInstance
);
143 Windows
.RegisterClass(UtilWindowClass
);
145 Result
:= CreateWindowEx(WS_EX_TOOLWINDOW
, UtilWindowClass
.lpszClassName
,
146 '', WS_POPUP
{!0}, 0, 0, 0, 0, 0, 0, HInstance
, nil);
147 if Assigned(Method
) then
148 SetWindowLong(Result
, GWL_WNDPROC
, Longint(MakeObjectInstance(Method
)));
151 procedure DeallocateHWnd(Wnd
: HWND
);
155 Instance
:= Pointer(GetWindowLong(Wnd
, GWL_WNDPROC
));
157 if Instance
<> @DefWindowProc
then FreeObjectInstance(Instance
);
160 procedure SplitColor(C
: TColor
; var r
, g
, b
: integer);
162 b
:= (c
and $FF0000) shr 16;
163 g
:= (c
and $00FF00) shr 08;
164 r
:= (c
and $0000FF) shr 00;
167 procedure AjustBitmap
;
178 function CalcColor(c1
, c2
, c3
: integer): integer;
180 if c1
= c3
then begin
190 { Result := 255 * c1 div c3 - c1 * (255 - c1) * (255 - c2) div c3 div (255 - c3);
193 Result
:= c1
* c2
div c3
;
194 if c2
= 0 then Result
:= c1
* 150 div 255;
195 if Result
> 255 then Result
:= 255;
196 if Result
< 50 then Result
:= Result
+ 50;
199 a := c1 * (255 - c1) * c2 * (255 - c2) div c3 div (255 - c3);
200 a := 255 * 255 - 4 * a;
202 x1 := Trunc((255 - sqrt(a)) / 2);
203 x2 := Trunc((255 + sqrt(a)) / 2);
204 if x1 > x2 then Result := Trunc(x1)
205 else Result := Trunc(x2);
213 if m
.Width
= 0 then exit
;
214 if m
.Height
= 0 then exit
;
215 t
:= NewBitmap(m
.Width
, m
.Height
);
216 m
.PixelFormat
:= pf24bit
;
218 SplitColor(Color2RGB(s
), r
, g
, b
);
219 if r
= 0 then r
:= 1;
220 if g
= 0 then g
:= 1;
221 if b
= 0 then b
:= 1;
222 SplitColor(Color2RGB(c
), r2
, g2
, b2
);
223 for j
:= 0 to t
.Height
- 1 do begin
225 for i
:= 0 to t
.Width
- 1 do begin
226 p
.rgbtRed
:= CalcColor(p
.rgbtRed
, r2
, r
);
227 p
.rgbtGreen
:= CalcColor(p
.rgbtGreen
, g2
, g
);
228 p
.rgbtBlue
:= CalcColor(p
.rgbtBlue
, b2
, b
);
243 if p
.rgbtBlue
< 255 - D
then p
.rgbtBlue
:= p
.rgbtBlue
+ D
else p
.rgbtBlue
:= 255;
244 if p
.rgbtRed
< 255 - D
then p
.rgbtRed
:= p
.rgbtRed
+ D
else p
.rgbtRed
:= 255;
245 if p
.rgbtGreen
< 255 - D
then p
.rgbtGreen
:= p
.rgbtGreen
+ D
else p
.rgbtGreen
:= 255;
247 if p
.rgbtBlue
> D
then p
.rgbtBlue
:= p
.rgbtBlue
- D
else p
.rgbtBlue
:= 000;
248 if p
.rgbtRed
> D
then p
.rgbtRed
:= p
.rgbtRed
- D
else p
.rgbtRed
:= 000;
249 if p
.rgbtGreen
> D
then p
.rgbtGreen
:= p
.rgbtGreen
- D
else p
.rgbtGreen
:= 000;
255 InstBlockList
:= nil;