Проблемы со сворчиванием в Tray

  • Автор темы Vadik(R)
  • Дата начала
V

Vadik(R)

Собственно, как сверачивать/разворачивать программу из трея я умею. Но работает это только в том случае, если у приложения одна форма. А если приложение имеет форму и какое-нибудь окно ShowMessage, то при сворачивании приложения ShowMessage остается видимым. Собственно, с этим и проблемы. Идея такая, что надо как-то получить все дочерние формы главной формы и их тоже сделать невидимыми. Но, собственно, как отловить это окошко ShowMessage или какой-либо другой диалог - я не знаю. Подскажите, как это сделать или предложите другой вариант свернуть приложение красиво со всеми открытыи в нём окнами.
 
D

Dock1100

Попробуй покопать в сторону GetWindow и GetNextWindow.
 
V

Vadik(R)

Вот код, который есть:
Код:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus, ShellAPI;

type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
Menu: TMenuItem;
Exit: TMenuItem;
Button1: TButton;
procedure WMUser(var Msg: TMessage); message WM_USER;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure MenuClick(Sender: TObject);
procedure ExitClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
public
{ Public declarations }
private
{ Private declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMUser(var Msg: TMessage);
var
P: TPoint;
begin
if Msg.LParam = WM_LBUTTONUP then
begin
SetForegroundWindow(Handle);
Menu.Caption := 'Свернуть';
ShowWindow(Application.Handle, SW_RESTORE);
ShowWindow(Handle, SW_RESTORE);
end;
if Msg.LParam = WM_RBUTTONUP then
begin
GetCursorPos(P);
SetForegroundWindow(Handle);
PopupMenu1.Popup(P.X, P.Y);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
NIData: TNotifyIconData;
begin
Application.OnMinimize := MenuClick;
NIData.cbSize := SizeOf(TNotifyIconData);
NIData.Wnd := Handle;
NIData.uID := 0;
NIData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
NIData.uCallBackMessage := WM_USER;
NIData.hIcon := Application.Icon.Handle;
StrPCopy(NIData.szTip, Application.Title);
Shell_NotifyIcon(NIM_ADD, @NIData);
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
NIData: TNotifyIconData;
begin
NIData.cbSize := SizeOf(TNotifyIconData);
NIData.Wnd := Handle;
NIData.uID := 0;
Shell_NotifyIcon(NIM_DELETE, @NIData);
end;

procedure TForm1.MenuClick(Sender: TObject);
begin
if Menu.Caption = 'Свернуть' then
begin
Menu.Caption := 'Восстановить';
ShowWindow(Handle, SW_HIDE);
ShowWindow(Application.Handle, SW_HIDE);
end
else
begin
Menu.Caption := 'Свернуть';
ShowWindow(Application.Handle, SW_RESTORE);
ShowWindow(Handle, SW_RESTORE);
end;
end;

procedure TForm1.ExitClick(Sender: TObject);
begin
Application.Terminate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('1');
end;

end.
Если кликнуть по кнопке, а потом по трею правой кнопкой мыши -> свернуть, то форма исчезнет (что вполне логично по коду), а вот ShowMessage останется ;)
P.S. Что-то с GetWindow пока ничего хорошего не выходит :(
 
D

Dock1100

Может это поможет:
Помогите!! Как найти дескриптор дочернего диалогового окна?
Помогите разобраться с данной проблемой:
Имеется программа со множеством дочерних окон типа edit button и т.д.
Я написал маленькую програмку получающую дескриптор каждого дочернего окна.
Все было бы хорошо, но когда открываешь какое-нибудь окно типа About или propertis,
которые вроде как тоже являются дочерними к главному окну, моя програмка их не
не обнаруживает. Так как эти окна модальные я взял их дескриптор с помощью
функции GetNextWindow. Теперь программа проверяет родителя диалогового окна
и выясняется что родителем является то самое главное окно.
ВОПРОС: ПОЧЕМУ НИЖЕ ПРИВЕДЕННЫЙ КОД НЕ ВОСПРИНИМАЕТ ДИАЛОГОВОЕ ОКНО КАК ДОЧЕРНЕЕ???
Код:
#include <windows.h>
#include <iostream.h>
HWND hMain;
LPARAM lParam;
HWND hOverWindow;
HWND hTemp;
char lpString[100];

//----------Обработчик дочерних окон-----------\\
BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam){ 
GetWindowText(hwnd,lpString,100);
cout<<lpString<<hwnd<<endl;
return true;
}
//-------------------------------------------------------\\

int main(int argc, char* argv[])
{
if((hMain=FindWindow("BuddyMain",NULL))!=NULL){ //Дескриптор главного окна

EnumChildWindows(hYahooMain,EnumChildProc,lParam);//Определяем дочерние окна
hOverWindow=GetNextWindow(hYahooMain,GW_HWNDPREV);//Определяем дескриптор модального диалогового окна
GetWindowText(hOverWindow,lpString,100);
cout<<lpString<<hOverWindow<<endl;
hTemp=GetParent(hOverWindow);
if(hYahooMain==hTemp) cout<<"nichego ne ponimayu";// выясняем родителя диальгового окна
}
}

return 0;
}





Диалоговое окно не является дочерним по отношению к главному, для них используется другое отношение - ownership (владение). Т.е. главное окно - owner, а диалоговое - owned window. Дескриптор владельца окна возвращает функция GetWindow(<...>, GW_OWNER). Отношение владения устанавливается между т.н. окнами верхнего уровня (имеют тип WS_OVERLAPPED или WS_POPUP) и фактически означает следующее:
1) владеемое окно всегда находится над владельцем в Z-порядке;
2) при изменении видимости владельца аналогично меняется видимость владеемых им окон;
3) при разрушении владельца автоматически разрушаются владеемые им окна.

Отношение parent/child другое: дочерние окна всегда имеют тип WS_CHILD, а их родители могут быть любого типа. Дочернее окно гораздо теснее связано с родителем, чем владеемое окно с владельцем. В частности, оно всегда позиционируется и отображается в клиентской области родительского окна.

Функция GetNextWindow() работает независимо с тремя иерархиями окон (topmost, top-level и child), возвращая следующее/предыдущее окно в Z-порядке той иерархии, которой принадлежит опрашиваемое окно. Например, можно с ее помощью выполнить ту же работу, что и EnumChildWindows(), если в качестве 1-го параметра передать дескриптор первого дочернего окна (относительно данного родителя) и пройтись в цикле по всем окнам данной иерархии.

Добавлено :
В принципе вроде работает, но для MessageBox, а не ShowMessage:
Код:
.......
MessageBox(form1.Handle, PChar('Msg'), PChar('Capt'), mb_ok);
memo1.Lines.Clear;
.......


.......
var i:integer;
h:HWND;
begin
{h:=GetWindow(form1.Handle,GW_ENABLEDPOPUP); }
h:=form1.Handle;
while (h<>0) do
begin
h:=GetNextWindow(h,GW_HWNDPREV);
if GetParent(h)=form1.Handle then
memo1.Lines.Add(inttostr(h));
end;
.......
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!