Hello,
I succeeded in having a DLL with a form that is ALWAYS on top of every form
in windows. I posted some messages about it, but got no reaction. Here is a
solution, if someone knows a better one, please let me know !!
I think there is a small misunderstanding between peaple concening the
nature of 'always on top'. For me it means: 'ALWAYS on top', for others it
means 'on top if it does'nt bother me to much...'.
Setting the DLL's application.handle to the application.handle of the exe
caused my program to behave exactly the way 'others' like it. That is
because Delphi executes a peace of code that hides the 'always on top' form
if the app swiches away.
(forms.pas, Winmain. Look at the comments...)
WM_ACTIVATEAPP: // Case: if user swiches app
begin
Default;
FActive := TWMActivateApp(Message).Active;
if TWMActivateApp(Message).Active then
begin
RestoreTopMosts;
PostMessage(FHandle, CM_ACTIVATE, 0, 0)
end
else
begin
// Hide the ontop window if other app activates !!
NormalizeTopMosts; // Works only if application.handle<>0 !!
PostMessage(FHandle, CM_DEACTIVATE, 0, 0);
end;
end;
To let it behave the way I want it some things had to be done:
- Compile source of exe and DLL with runtime packages (1 Application
object instead of 2 !
- Call Normalizetopmosts + SetWindowpos (to get topwindow on top again) 1
time when the program starts, this 'confuses' the Normalizetopmosts routine
in that it increases a counter that will never reach 0 again.
(forms.pas, NormalizeTopMosts. Look at the comments...)
procedure TApplication.NormalizeTopMosts(IncludeMain: Boolean);
var
I: Integer;
Info: TTopMostEnumInfo;
begin
if Application.Handle <> 0 then // Deault value for DLL application
handle !!
begin
if FTopMostLevel = 0 then
begin
Info.TopWindow := Handle;
Info.IncludeMain := IncludeMain;
EnumWindows(@GetTopMostWindows, Longint(@Info));
if FTopMostList.Count <> 0 then // This is the counter I was talking
about...
begin
Info.TopWindow := GetWindow(Info.TopWindow, GW_HWNDPREV);
if GetWindowLong(Info.TopWindow, GWL_EXSTYLE)
and WS_EX_TOPMOST <> 0 then
Info.TopWindow := HWND_NOTOPMOST;
for I := FTopMostList.Count - 1 downto 0 do
SetWindowPos(HWND(FTopMostList[I]), Info.TopWindow, 0, 0, 0, 0,
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;
end;
Inc(FTopMostLevel); // Increase counter
end;
end;
I hope this will never be a problem for any of us...
Bert Kortenbach.