Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.10;
Скачать: CL | DM;

Вниз

Окно поверх всех окон - проблема(+)   Найти похожие ветки 

 
UNIVERSAL   (2004-09-09 10:25) [0]

Для модераторов: В FAQ и поиске ничего не нашёл, точнее нашёл, но не то.
Здравствуйте уважаемые Мастера. Вроде всё легко, но глюк замучал. Сделал CBT хук на HCBT_ACTIVATE, HCBT_MINMAX, HCBT_MOVESIZE, хотя наверное хватило бы только HCBT_ACTIVATE, но это я уже просто от безысходности добавил. Так вот окно действительно выводится поверх всех, но иногда, а именно, когда я щёлкаю мышью на окно, которое должно быть поверх всех, или на главное окно приложения, а потом на чужое окно оно уходит вниз, т.е. перестаёт быть поверх всех. Пробовал создать новое приложение только с одним главным окном и сделать его TOPMOST с помощью того же хука - работает, и даже, когда я на него щёлкаю мышью. Но дело в том,что мне нужно именно чтобы не главное окно приложения было поверх всех.  Может кто сталкивался подскажите.

Вот код модуля хука

library H_CBT;
uses
 SysUtils,
 Windows, Messages, shellapi;
{$R *.RES}
type
PHookRec = ^THookRec;
THookRec = record
            WndHandle: HWND;
            HookHandle: HHOOK;
           end;
const rHookRec: PHookRec=nil;
      WM_SETWNDMSGTOP=WM_USER+106;
var HookSet:boolean;
//
procedure EntryPointProc(Reason: Integer);forward;
//
function CBTProc(nCode : Integer; wParam, lParam: integer): LResult; stdcall;
begin
if nCode >= 0 then
begin
 if ((nCode=HCBT_ACTIVATE) or (nCode=HCBT_MINMAX)or (nCode=HCBT_MOVESIZE)){ and (wParam<>rhookrec^.HookHandle) }then
  SendMessage(rHookRec^.WndHandle ,WM_SETWNDMSGTOP,wParam,1);
end;
Result := CallNextHookEx(rhookrec^.HookHandle, nCode, wParam, lParam);
end;
// поставить хук
procedure SetCBTHook;
begin
rHookRec^.HookHandle:= SetWindowsHookEx(WH_CBT,@CBTProc,HInstance,0);
// SendMessage(rHookRec^.WndHandle ,WM_SETWNDMSGTOP,0,1);
HookSet:=rHookRec^.HookHandle>0;
end;
// убрать хук
procedure RemoveCBTHook;
begin
SendMessage(rHookRec^.WndHandle ,WM_SETWNDMSGTOP,0,0);
HookSet:=UnhookWindowsHookEx(rHookRec^.HookHandle);
end;

procedure EntryPointProc(Reason: Integer);
const
hMapObject: THandle = 0; // this project was declared with Assignable Typed Constants
begin
case reason of
 DLL_PROCESS_ATTACH:
  begin
   hMapObject := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(THookRec), "_CBT");
   rHookRec := MapViewOfFile(hMapObject, FILE_MAP_WRITE, 0, 0, 0);
  end;
 DLL_PROCESS_DETACH:
  begin
   try
    UnMapViewOfFile(rHookRec);
    CloseHandle(hMapObject);
   except
   end;
  end;
end;
end;

// we have to tell the DLL where our entry point proc is and call it as an attach

procedure SetMainHandle(Handle: HWND);stdcall;
begin
rHookRec^.WndHandle:= Handle;
end;

function HookIsSet:Boolean;stdcall;
begin
Result:=HookSet;
end;
exports
HookIsSet,
SetCBTHook,
RemoveCBTHook,
SetMainHandle;
begin
HookSet:=false;
DllProc := @EntryPointProc;
EntryPointProc(DLL_PROCESS_ATTACH);
end.


 
UNIVERSAL   (2004-09-09 11:44) [1]

Ау люди вы где? Неужеди никто не сталкивался с этим?

Один способ, но не совсем то что надо я нашёл: это в обработке сообщения, которое отсылает хук моему окну поставить вместо
 SetWindowPos(frmMessages.handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOACTIVATE)
этот код  SetWindowPos(Application.handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOACTIVATE), но тогда HWND_TOPMOST получается всё приложение. в общем терпимо конечно, но это уже дело принципа.


 
DVM ©   (2004-09-09 11:57) [2]

Зачем тут ловушка вообще? Единственный способ быть почти всегда поверх всех - это в таймере двигать свое окно наверх с пом. SetWindowPos, причем чем таймер чаще, тем это будет надежнее.
НО ВСЕГДА ПОВЕРХ ВСЕХ ОКОН НЕЛЬЗЯ!


 
UNIVERSAL   (2004-09-09 12:06) [3]

А почему не ловушка? И это не "единственный способ". В таймере, я думаю будут "провалы", с окном или тормоза, если сильно маленкий интервал задать.  А с ловушкой у меня проблем нет, проблема мне кажется с глюком у делфей(ну или у меня из-за незнания :-) ), которые главную форму приложения делают поверх окон, а неглавную не всегда. И ещё дело в том, что у меня уже есть два таймера из-за сабжа приложения, не хочется мне ещё один лепить. Неужели в Аське и Download Master-е используется таймер? что-то я сомневаюсь.


 
сруигкфещк   (2004-09-09 12:18) [4]

Не понял, а в чём проблема то ?

{ and (wParam<>rhookrec^.HookHandle) } - зачем коментарил ?
хотя должно быть wParam <> rHookRec^.WndHandle

Result := CallNextHookEx(rhookrec^.HookHandle, nCode, wParam, lParam); - лестная строка для других форм :о), но как ты хочешь сделать ТОР-окно, если передаёшь код об активации окна дальше по цепочке получателей сообщений ?

Может так ?
function CBTProc(nCode : Integer; wParam, lParam: integer): LResult; stdcall;
begin
if (nCode = HCBT_ACTIVATE) and (wParam <> rHookRec^.WndHandle)
 then
 begin
 SendMessage(rHookRec^.WndHandle ,WM_SETWNDMSGTOP,wParam,1);
 CBTProc := 0;
 end
 else
 Result := CallNextHookEx(rhookrec^.HookHandle, nCode, wParam, lParam);
end;

Где rHookRec^.WndHandle - HWND нужного тебе окна для показа на верху ? Попробуй...


 
DVM ©   (2004-09-09 12:18) [5]


> UNIVERSAL   (09.09.04 12:06) [3]

Большинство игр с легкостью перекроют твое окно.

> Неужели в Аське и Download Master-е используется таймер?
> что-то я сомневаюсь.

А это легко узнать, воспользовавшись SPY++. А если они используют ловушки, то скорее всего есть dll с характерными экспортируемыми функциями.
Но я бы лично обошелся без ловушек. При первом запуске двинуть окно наверх. Потом обрабатывая WM_WINDOWPOSCHANGING, не давать ему "спуститься ниже".
А еще есть fsStayOnTop.


 
UNIVERSAL   (2004-09-09 12:43) [6]

2сруигкфещк блин, правда ошибся :)
2DVM ©  fsStayOnTop -по-моему это работает только внутри данного приложения.
Неужели дело в хуке? ведь в приложении, где хук шлёт сообщение для MainForm всё работает...


 
UNIVERSAL   (2004-09-09 14:28) [7]

2сруигкфещк rHookRec^.WndHandle - да это хендл HWND нужного мне окна для показа на верху. К сожалению суть не поменялась :(.


 
evvcom ©   (2004-09-10 03:49) [8]

..сруигкфещк = cheburator..


> fsStayOnTop -по-моему это работает только внутри данного
> приложения.

Не только, но если есть другое окно с fsStayOnTop, то оно с легкостью может перекрыть первое.


 
UNIVERSAL   (2004-09-10 09:20) [9]

2evvcom Спасибо за расшифровку :)


 
UNIVERSAL   (2004-09-10 09:33) [10]

Кстати объясните попутно, пожалста, ещё одну вещь:
вот код, который мне посоветовал cheburator.

function CBTProc(nCode : Integer; wParam, lParam: integer): LResult; stdcall;
begin
if (nCode = HCBT_ACTIVATE) and (wParam <> rHookRec^.WndHandle)
then
begin
SendMessage(rHookRec^.WndHandle ,WM_SETWNDMSGTOP,wParam,1);
CBTProc := 0;
end
else
Result := CallNextHookEx(rhookrec^.HookHandle, nCode, wParam, lParam);
end;

Ну так вот у меня он не хочет корректно работать почему-то (окна в приложении не двигаются.), хотя в примерах я видел именно такой код и это считается правильным. Отличе от моего в том что я не присваиваю процедуре хука результат 0, когда его  обрабатываю, а вызываю обработку следующего хука, причём, всегда (см модуль в первом сообщении). Хотелось бы узнать как именно правиль и что происходит, если не присваивать процедуре хука 0?. Заранее благодарен.


 
tmp_name   (2004-09-10 13:59) [11]

Почему используется: "SendMessage(rHookRec^.WndHandle ,WM_SETWNDMSGTOP,wParam,1);",
а не как в MSDN написано: "SetWindowPos(rHookRec^.WndHandle, HWND_TOPMOST, x, y, w, h, 0);"?
Я поставил кнопку на Form1, на клик написал: SetWindowPos(Form2.Handle, HWND_TOPMOST, Form2.Left, Form2.Top, Form2.Width, Form2.Height, 0);. Все работает.


 
UNIVERSAL   (2004-09-10 14:32) [12]

Не понял связи между хуком и кликом на кнопку. При авктивации других окон это окно "упадёт" под него. можно конечно сразу попробовать поставить окно на верх, не отсылая сообщения для него....


 
tmp_name   (2004-09-10 16:22) [13]

Если тебе нужен был хук только для topmost, то это изврат какой-то получается.
Попробуй новый пример:
2 видимые формы.
На первую кидаешь TApplicationEvents и на события Activate и DeActivate этого компонента пишешь:
SetWindowPos(Form2.Handle, HWND_TOPMOST, Form2.Left, Form2.Top, Form2.Width, Form2.Height, 0);



Страницы: 1 вся ветка

Текущий архив: 2004.10.10;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.066 c
4-1093600176
vidiv
2004-08-27 13:49
2004.10.10
Отключение устройств в winnt


8-1089901612
Time
2004-07-15 18:26
2004.10.10
WAV/MP3/MP2/MP1/OGG


14-1095919272
gn
2004-09-23 10:01
2004.10.10
Читайте назночение программ некоторые фразы меня впечатлили :-)


14-1095453117
GanibalLector
2004-09-18 00:31
2004.10.10
Проверка существования почты на HOTMAIL


14-1095594379
_iceman_home
2004-09-19 15:46
2004.10.10
Проблемы с монитором