Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];

Вниз

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

 
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 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.03 c
9-1085024752
Hater
2004-05-20 07:45
2004.10.10
Сохранение игры


4-1093831190
Registr
2004-08-30 05:59
2004.10.10
Получение каталога Windows в NT


14-1095877438
_silver
2004-09-22 22:23
2004.10.10
Дальнеёшее развитие процессоров.


14-1095628442
Yanis
2004-09-20 01:14
2004.10.10
Не могу ветку про бесплатный доступ к сайту найти :)


1-1096024316
V l a d i m i r
2004-09-24 15:11
2004.10.10
Как уменьшить сетку на форме?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский