Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  06:03[Войти] | [Зарегистрироваться]
Ответ на вопрос № 42112

02-05-2006 09:16
Как сделать так, чтобы окно приложения не сворачивалось при нажатии "Свернуть все" (Toggle desktop, Win+D)? (или сворачивалось, но быстро восстанавливалось обратно). Если нажать "Свернуть все", то сворачиваются все окна и выполнение Application.Restore ничего не делает, окно остается скрытым пока снова не нажать "Свернуть все" или кнопку приложения на таск баре.

Это реализуемо: Например QIP icq-клиент не сворачивается при нажатии "Свернуть все"

Зачем это нужно: отображать записки, приколотые к рабочему столу - свернули все - видим записки. Рисовать на рабочем столе - не выход.

Спасибо!

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

17-09-2008 05:49 | Комментарий к предыдущим ответам
>>> Но при этом окно получило WM_SHOWWINDOW (Show = False) с причиной SW_PARENTCLOSING (при этом у Form1 Parent = 0)

Кстати, об этом даже VCL в курсе:

procedure TCustomForm.WMShowWindow(var Message: TWMShowWindow);
const
  ShowCommands: array[saRestore..saMaximize] of Integer =
    (SW_SHOWNOACTIVATE, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);
begin
  with Message do
    case Status of
      SW_PARENTCLOSING:
        begin
          if IsIconic(Handle) then FShowAction := saMinimize else
            if IsZoomed(Handle) then FShowAction := saMaximize else
              FShowAction := saRestore;
          inherited;
        end;
      SW_PARENTOPENING:
        if FShowAction <> saIgnore then
        begin
          ShowWindow(Handle, ShowCommands[FShowAction]);
          FShowAction := saIgnore;
          // This occurs when MainFormOnTaskbar is False
          // and the ShowDesktop button is clicked.
          if Self = Application.MainForm then
            AppIconic := False;
        end;
    else
      inherited;
    end;
end;


09-08-2008 14:02
Выкрутился использованием

PaintDesktop(form1.Canvas.Handle);

Но все равно это не совсем то. Должен быть другой способ.

16-07-2008 21:17 | Комментарий к предыдущим ответам
Проблема до сих пор не решена?

Я делал так:

private
procedure CreateParams(var Params: TCreateParams); override;
...

procedure TForm1.CreateParams(var Params: TCreateParams);
var wd:HWnd;
begin
repeat
wd:=FindWindow('Progman','Program Manager');
until wd<>0;
inherited CreateParams(Params);
Params.WndParent:=wd;
Params.Style:=WS_CHILD;
end;

Работает, форма висит только на рабочем столе и не сворачивается. Все идеально но есть огромный минус - перестает работать прозрачность компонентов на форме и самой формы. То есть у того же Label при включенном transparent фон виден clBtnFace. У формы AlphaBlend не работает... И т.д...
Подозреваю это потому что винда считает что под рабочим столом фона нет и быть не может...

Если убрать строчку:

Params.Style:=WS_CHILD;

то прозрачность работает, форма не сворачивается, но Win+D блокируется. Свернуть все окна кроме формы можно, а вот развернуть обратно - нельзя. Форма словно перехватывает это сообщение и блокирует его... Поэтому способ не годится.

Проблему с прозрачностью не решил до сих пор. Спрашивал автора одной дельфийской программулины которая вела себя корректно, но тот зажлобился. Типа "секрет"...
Намекнул только про назначение рабочего стола родителем, но это я и без него знал.

Подскажите кто знает. Ведь делают же, значит точно можно!

17-01-2008 03:56
Для размышлений:
1. Что касается QIP, то он ловит некое "AppBarNotify" (я так понял, зарегистрированное через RegisterWindowMessage). Смотрел это в Spy++. Наверное, это каким-то образом связано с SHAppBarMessage
Во время сворачивания всех окон, приходит это сообщение с wParam = 2 (м.б. ABN_FULLSCREENAPP?), lParam = 1.
2. Ещё заметил: у меня Total Commander при сворачивании убирается в трей. Так вот, когда жмёшь на "свернуть все окна", то он сворачивается в трей. Т.е. сам Total Commander в курсе, что его сворачивают.
3. Создал обычное пустое приложение, заблокировал CS_MINIMIZE у формы и Application. Приложение сворачивается при Свернуть все окна (никаких WM_SYSCOMMAND не рассылается).
Но при этом окно получило WM_SHOWWINDOW (Show = False) с причиной SW_PARENTCLOSING (при этом у Form1 Parent = 0), а Application - WM_SIZE с SIZE_MINIMIZED и пачку WM_WINDOWPOSCHANGING.

18-11-2006 16:17
Эх... Кто-нибудь решил данную проблематику ? Все вышеупомянутые варианты у меня на машине НЕ сработали ... :( Свертывается все... И честно говоря - я еще НЕ видел программы, которая по этому клику НЕ сворачивалась ...

А про Квип - судя по всему - все зависит от пропатченности винды ... и ее настройки (хотя где такие есть (именно по объекту - свернуть все)?)

03-05-2006 14:04 | Комментарий к предыдущим ответам
А HRESULT какой?
А вот теперь уже не скажу, но вроде OleCheck выдавало сообщение "Класс не зарегистрирован". На доступном мне сейчас компе всё работает нормально в плане CoCreateInstance, хотя данный код никак не влияет на появление окна, кнопка моргает лишняя (если Sleep поставить, иначе не заметить), но больше ничего не происходит.

03-05-2006 13:46
Ну в общем я нашёл комп на котором мой код не работает и вот что получилось:

type
  TDummyObject=class
    class function AppWndProc(var Msg:TMessage):Boolean;
  end;

class function TDummyObject.AppWndProc(var Msg:TMessage):Boolean;
var
  Input:TInput;
begin
  Result:=True;
  case Msg.Msg of
    WM_SIZE:
      if Msg.wParam=SIZE_MINIMIZED then
        SetTimer(Application.Handle,1,200,nil);
    WM_TIMER:begin
        KillTimer(Application.Handle,1);
        FillChar(Input,SizeOf(Input),0);
        SendInput(1,Input,SizeOf(TInput));
        SetForegroundWindow(Application.Handle);
        Application.Restore;
      end;
  else
    Result:=False;
  end;
end;

initialization
  Application.HookMainWindow(TDummyObject.AppWndProc);
finalization
  Application.UnHookMainWindow(TDummyObject.AppWndProc);
end.


Это всё конечно очень грязно (особенно трюк с SendInput) и основано на таймере (то есть будет мигать и нет гарантии срабатывания во всех ситуациях), но у меня вроде заработало.

03-05-2006 13:30 | Комментарий к предыдущим ответам
DRON:

у меня CoCreateInstance всегда возвращает в hs nil

А HRESULT какой?

03-05-2006 12:03
Прошу всех оттестировать и написать о своих результатах!
Ну во первых условие "s = 'WorkerW'" не выполняется (или не всегда выполняется) при сворачивании по Win+D, но всегда срабатывет при сворачивании через меню, во вторых у меня CoCreateInstance всегда возвращает в hs nil, так что ваш код просто не срабатывает.

03-05-2006 08:21 | Сообщение от автора вопроса
Опытным путем найдено, хоть и кривое, но решение! Прошу всех оттестировать и написать о своих результатах! Данное решение позволяет восстанавливать окно сразу после сворачивания по Win+D используя ITaskBarList:


uses ActiveX;

...

const
CLSID_TaskBarList: TCLSID = '{56FDF344-FD6D-11d0-958A-006097C9A090}';
IID_ITaskBarList: TGUID = '{56FDF342-FD6D-11d0-958A-006097C9A090}';

type
ITaskBarList = interface(IUnknown)
['{56FDF342-FD6D-11d0-958A-006097C9A090}']
  function HrInit(): HResult; stdcall;
  function AddTab(WND: HWND): HResult; stdcall;
  function DeleteTab(WND: HWND): HResult; stdcall;
  function ActivateTab(WND: HWND): HResult; stdcall;
  function SetActiveAlt(WND: HWND): HResult; stdcall;
end;

implementation

...

procedure TForm1.Timer1Timer(Sender: TObject); // Таймер каждую миллисекунду
var
hs: ITaskbarList;
s: array[0..255] of char;
begin

GetClassName(GetForegroundWindow,s,255);
if s = 'WorkerW' then //Такой класс у окна которое активно после Win+D (может не только тогда, поэтому и прошу протестить на баги)
begin
CoCreateInstance(CLSID_TaskBarList,nil,CLSCTX_ALL,IID_ITaskBarList,hs);
hs.HrInit; //Инициализируем ITaskBarList
hs.AddTab(Handle); //Создаем на TaskBar'е кнопку нашего окна
hs.ActivateTab(Handle); //Активируем его
hs.DeleteTab(Handle);  //Удаляем кнопку
SetForegroundWindow(Handle); //Активируем наше окно
end;

end;



Кривенько, но лучше чем ничего! Жду отчетов по тестированию! Спасибо всем!

03-05-2006 07:27 | Комментарий к предыдущим ответам
Ну тогда я выбываю из игры, пока не найду комп на котором мой способ не работает :(

03-05-2006 06:54
DRON
У меня тоже не работает, за исключением побочного эффекта (WinXP SP2 Build 2600) :(

03-05-2006 06:09 | Сообщение от автора вопроса
2DRON
Да, скорее всего какие-то настройки и дополнительные программы влияют. У меня предложенные методы не работают (Тоже на XP SP2 и все патчи). Работает только метод Ins'а

03-05-2006 05:04
Ставлю на форму таймер и выполняю "Application.Restore", в XP гарантированно не работает.
Делал то же самое всё работает, похоже это зависит не только от версии виндов (у меня XP SP2 со всеми апдейтами), но и от каких-то настроек.
Любой отказ от WS_EX_TOPMOST заставляет окно сворачиваться.
А у меня нет. Мистика какая-то.

03-05-2006 05:00
Благодаря подсказке Ins решение найдено:

SetWindowLong(Application.Handle,GWL_STYLE,GetWindowLong(Application.Handle,GWL_STYLE)and not WS_GROUP);

Это всё, никаких StayOnTop и прочего не нужно, просто добавьте этот код в DPR-файл. Почему это вообще работает и какие тут могут быть побочные эффекты я не в курсе.
PS: вот вылез один эффект: форма не реагирует на нажатие кнопки приложения на тулбаре.

03-05-2006 04:58 | Сообщение от автора вопроса
Похоже тупичок получился;(

QIP не сворачивается, если включить опцию "поверх всех окон", значит там скорее всего и использовано:

Params.WndParent := 0;
Params.Style := WS_POPUP;
Params.ExStyle := WS_EX_TOPMOST;


Способ действительно рабочий, но для моего случая к сожалению не подходит - нужно чтоб записки были приколоты к рабочему столу, а не поверх всего. Любой отказ от WS_EX_TOPMOST заставляет окно сворачиваться. Даже выполнения кода после его создания с флагом WS_EX_TOPMOST:

SetWindowPos(Handle,HWND_BOTTOM,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE);


делает окно уязвимым для ToggleDesktop;

2DRON: Ставлю на форму таймер и выполняю "Application.Restore", в XP гарантированно не работает.

03-05-2006 02:25
Заметил следующее: Форма StayOnTop, в CreateParams Params.WndParent = 0, Params.Style = WS_POPUP - в WinXP не сворачивается по Win+D

Если это еще не решение, то похоже, копать нужно в этом напрвлении

03-05-2006 02:12 | Комментарий к предыдущим ответам
Кстати, тока что проверил PEID'ом. QIP написан на Delphi!

02-05-2006 23:40 | Комментарий к предыдущим ответам
Почитал ответы. Интересно! Предлагаю убойный вариант: написать письмо разработчикам QIP'a и влоб их спросить, как они это делают.

02-05-2006 23:07
Привет!
qip 2005A. Alpha, Build 7840 - Действительно не сворачивается, если включить опцию "поверх всех окон". Странно однако, разработчики qip знают как это делается, а мы...?

С Уважением...

02-05-2006 14:58
Проверил: отлично разворачивается обычным "Application.Restore", без всяких MessageBox-ов.

02-05-2006 14:39
У кого есть под рукой
Оно у меня всегда под рукой, но блокирование почти всех сообщений из полученного списка к нужному результату не приводит.

Зависшее окно у меня не сворачивается, а вот QIP (вчерашняя версия) у меня всё равно сворачивается. Может в вашем случае стоит сделать листочки Child-ами рабочего стола?

02-05-2006 13:02 | Сообщение от автора вопроса
Думаю тут надо хотя бы выяснить чем заставить программу развернуться, кроме как MessageBox(0,'a','a',0);

Сообщения по ходу вообще никакие не отправляются - сворачивается даже зацикленное зависшее приложение...

02-05-2006 12:38
У кого есть под рукой какая-либо программка для мониторинга сообщений Windows? Может винда какое-нить хитрое сообщение посылает?

02-05-2006 11:51 | Сообщение от автора вопроса
QIP последней версии не сворачивается, еще раз проверил.

Наблюдение:
Если в свернутом состоянии выполнить
MessageBox(Handle,'a','a',0);
то диалог не заставит приложение развернуться, а если
MessageBox(0,'a','a',0);
то оно развернется и отобразит диалог.

02-05-2006 10:53 | Комментарий к предыдущим ответам
К сожалению это не работает. Я тут уже и WM_SYSCOMMAND и WM_SIZE и даже WM_WINDOWPOSCHANGING попробовал, причём и у формы и у Application. Под XP ничего не помогает и упомянутый автором QIP тоже прекрасно сворачивается. Не сворачиваются, по моему, только зависшие окна.

02-05-2006 10:50 | Сообщение от автора вопроса
Такой метод работать не будет. При нажатии "Свернуть все" сворачивается все (даже диалоги и прочие несворачивающиеся окна) причем SC_MINIMIZE им не отправляется! Все программы продолжают думать что они сейчас в развернутом состоянии.
Думал что вообще это фича Windows такая, запретить программам не сворачиваться, чтоб пользователь мог беспрепятственно получить доступ к рабочему столу, однако QIP же остается несвернутым, хотя и мигает 1 раз - очевидно восстанавливает каким-то образом свое окно. Но ни Restore, ни ShowWindow, ни изменение любых параметров через SetWindowLong ни приводят к нужному эффекту!

02-05-2006 10:35
Можно сделать так, но в этом случае Form1 вообще не будет сворачиваться (даже по нажатию на кнопке "свернуть" самой формы). Ничего другого че-то в голову не лезет.

TForm1 = class(TForm)
  private
    { Private declarations }
    procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMSysCommand(var Message: TWMSysCommand);
begin
  if (Message.CmdType and $FFF0 = SC_MINIMIZE) then exit;
  inherited;
end;


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Вода мокрая или сухая?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования