Блокировка окна
От: IRaven Ниоткуда  
Дата: 06.04.05 03:31
Оценка:
Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое
Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?
Re: Блокировка окна
От: byterus Россия  
Дата: 06.04.05 03:46
Оценка:
Здравствуйте, IRaven, Вы писали:

IR>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

Ну например можно при вызове второго окна сделать Okno1.MainPanel.Enabled:=False, второе — StayOnTop. Должно работать.
MySQL stored procedure debugging
Re[2]: Блокировка окна
От: IRaven Ниоткуда  
Дата: 06.04.05 04:01
Оценка:
Здравствуйте, byterus, Вы писали:

IR>>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

B>Ну например можно при вызове второго окна сделать Okno1.MainPanel.Enabled:=False, второе — StayOnTop. Должно работать.


Enabled — наглухо заблокирует форму, тогда уже о ее перетаскивании речи идти не может
StayOnTop — сохранить возможность использования контролов на форме, этого тоже не надо. Требуется комбинация Enabled := False + возможность перетаскивания
Re[3]: Блокировка окна
От: byterus Россия  
Дата: 06.04.05 04:23
Оценка: 2 (1)
Здравствуйте, IRaven, Вы писали:

IR>Здравствуйте, byterus, Вы писали:


IR>>>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>>>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

B>>Ну например можно при вызове второго окна сделать Okno1.MainPanel.Enabled:=False, второе — StayOnTop. Должно работать.


IR>Enabled — наглухо заблокирует форму, тогда уже о ее перетаскивании речи идти не может

IR>StayOnTop — сохранить возможность использования контролов на форме, этого тоже не надо. Требуется комбинация Enabled := False + возможность перетаскивания

Я написал не Form.Enabled а Form.MainPanel.Enabled, все контролы можно положить на эту MainPanel
MySQL stored procedure debugging
Re[4]: Блокировка окна
От: IRaven Ниоткуда  
Дата: 06.04.05 04:51
Оценка:
Здравствуйте, byterus, Вы писали:

IR>>Enabled — наглухо заблокирует форму, тогда уже о ее перетаскивании речи идти не может

IR>>StayOnTop — сохранить возможность использования контролов на форме, этого тоже не надо. Требуется комбинация Enabled := False + возможность перетаскивания
B>Я написал не Form.Enabled а Form.MainPanel.Enabled, все контролы можно положить на эту MainPanel

Извините, просмотрел. Можно в принципе, но у меня уже около сотни окон работают. Переделавыть все на панели долго. Есть еше варианты?
Re[5]: Блокировка окна
От: byterus Россия  
Дата: 06.04.05 05:12
Оценка:
Здравствуйте, IRaven, Вы писали:

IR>Здравствуйте, byterus, Вы писали:


IR>>>Enabled — наглухо заблокирует форму, тогда уже о ее перетаскивании речи идти не может

IR>>>StayOnTop — сохранить возможность использования контролов на форме, этого тоже не надо. Требуется комбинация Enabled := False + возможность перетаскивания
B>>Я написал не Form.Enabled а Form.MainPanel.Enabled, все контролы можно положить на эту MainPanel

IR>Извините, просмотрел. Можно в принципе, но у меня уже около сотни окон работают. Переделавыть все на панели долго. Есть еше варианты?


Можно пробежаться по контролам и задизейблить, все это очень не красиво. Непонятно, зачем нужно перетаскивать окно и одновременно блокировать контролы? Даже если вы это реализуете то выглядеть это будет непривычно, можете назвать программы где есть такие возможности?
MySQL stored procedure debugging
Re[5]: Блокировка окна
От: Diouzshev Россия  
Дата: 06.04.05 05:33
Оценка: 14 (1)
Hello, IRaven!
You wrote on Wed, 06 Apr 2005 04:51:21 GMT:

I> Извините, просмотрел. Можно в принципе, но у меня уже около сотни

I> окон работают.

I> Переделавыть все на панели долго.


Если подумать — недолго.
Нужно написать наследник от TForm, который будет в OnCreate (Create, AfterConstruction, где заработает) создавать панель и перекладывать все контролы с формы на нее автоматом.

А в твоих сотнях форм поменять только
TMyForm132 = class(TForm) на TMyForm132 = class(TPaneledForm) и в Uses прописать

Имхо это проще, чем оконную процедуру у всей сотни форм переписывать

With best regards, Alexander Diouzshev-Maltsev.
Posted via RSDN NNTP Server 1.9
Re: Блокировка окна
От: Danchik Украина  
Дата: 06.04.05 09:34
Оценка:
Здравствуйте, IRaven, Вы писали:

IR>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

Я могу тебе предложить решение для псевдо-модальных окон, только никак не пойму зачем тебе таскать 1 окно?
Это ж тебе еще надо и кнопочки на 1 окне дизаблить и черт знает еще чего.
Re: Блокировка окна
От: Vodyamba Россия  
Дата: 06.04.05 22:52
Оценка:
Здравствуйте, IRaven, Вы писали:

IR>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

Надо делать как сказали... второе окно сделать StayOnTop, а все контролы сделать Контрол.enabled:=false
Могу дать процедуру, которая перебирает все контролы... чуть подредактируешь и всё ОК будет...
Данная процедура устанавливает всем компонентам всех форм свойство Ctl3d:=true и подобные...
Получилась габаритная правда... но работает...
Procedure v_not_flat_component;
Var
i1,i:integer;
Begin
for i1:=0 to application.ComponentCount-1 do
 if application.Components[i1].InheritsFrom(TForm) then

   for i := 0 to application.Components[i1].ComponentCount-1 do
    begin
     if application.Components[i1].Components[i].InheritsFrom(TEdit) then
        TEdit(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TDBEdit) then
        TDBEdit(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TMaskEdit) then
        TMaskEdit(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TComboBox) then
        Begin
        TComboBox(application.Components[i1].Components[i]).Ctl3D := True;
        TComboBox(application.Components[i1].Components[i]).BevelKind := BkNone;
        end;
     if application.Components[i1].Components[i].InheritsFrom(TDBComboBox) then
        Begin
        TDBComboBox(application.Components[i1].Components[i]).Ctl3D := True;
        TDBComboBox(application.Components[i1].Components[i]).BevelKind := BkNone;
        end;
     if application.Components[i1].Components[i].InheritsFrom(TStringGrid) then
        TStringGrid(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TDBGrid) then
        TDBGrid(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TTreeview) then
        TTreeview(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TListBox) then
        TListBox(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TShellTreeview) then
        TShellTreeview(application.Components[i1].Components[i]).Ctl3D := True;
     if application.Components[i1].Components[i].InheritsFrom(TMemo) then
        TMemo(application.Components[i1].Components[i]).Ctl3D := True;
    end;
end;


Кто подправит, и уменьшит размер буду благодарен...
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[2]: Блокировка окна
От: Аноним  
Дата: 06.04.05 23:32
Оценка:
Здравствуйте, Vodyamba, Вы писали:


V>Кто подправит, и уменьшит размер буду благодарен...


А вот в Билдере (вернее, в С++) есть dymamic_cast — код можно было бы сократить раза в 3.
Может и в Делфях что-то аналогичное есть, не знаю...
Re[2]: Блокировка окна
От: Danchik Украина  
Дата: 07.04.05 06:19
Оценка:
Здравствуйте, Vodyamba, Вы писали:

V>Здравствуйте, IRaven, Вы писали:


IR>>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

V>Надо делать как сказали... второе окно сделать StayOnTop, а все контролы сделать Контрол.enabled:=false

V>Могу дать процедуру, которая перебирает все контролы... чуть подредактируешь и всё ОК будет...
V>Данная процедура устанавливает всем компонентам всех форм свойство Ctl3d:=true и подобные...
V>Получилась габаритная правда... но работает...
Да уж габаритней и не придумаеш

V>Кто подправит, и уменьшит размер буду благодарен...


Повторяю твою процедуру но более компактней. Поддерживает все контролы .

Вызывай
RemoveFlat (Application)


uses
  TypInfo;

procedure RemoveFlat (Component: TComponent);
var
  K: Integer;
  aPropInfo : PPropInfo;
begin
  if Component = nil then
    Exit;

  if Component is TControl then begin
    aPropInfo := GetPropInfo (Component, 'Ctl3D', [tkEnumeration]);
    if aPropInfo <> nil then
      SetOrdProp (Component, aPropInfo, Ord (True));

    aPropInfo := GetPropInfo (Component, 'BevelKind', [tkEnumeration]);
    if aPropInfo <> nil then
      SetOrdProp (Component, aPropInfo, Ord (bkNone));
  end;

  for K := 0 to Component.ComponentCount - 1 do
    RemoveFlat (Component.Components [K]);
end;


А вобще то бредовый поход к интерфейсу
Re[3]: Блокировка окна
От: Vodyamba Россия  
Дата: 07.04.05 11:06
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Vodyamba, Вы писали:


V>>Здравствуйте, IRaven, Вы писали:


IR>>>Хочется сделать такую вещь: имеется 2 окна: 1 — вызывающее, 2 -вызываемое

IR>>>Нужно чтобы при вызванном втором окне, первое оставалось неактивным при этом сохраняя возможность его перетаскивания. Так сказать модальность без модальности. Как я понимаю решение — в отловке сообщений на перетаскивание WM_CHIT... и игнорирование остальных. Т.е. надо подменить исходную процедуру окна. Есть еще варианты?

V>>Надо делать как сказали... второе окно сделать StayOnTop, а все контролы сделать Контрол.enabled:=false

V>>Могу дать процедуру, которая перебирает все контролы... чуть подредактируешь и всё ОК будет...
V>>Данная процедура устанавливает всем компонентам всех форм свойство Ctl3d:=true и подобные...
V>>Получилась габаритная правда... но работает...
D>Да уж габаритней и не придумаеш

Спасибочки... сейчас проверю... как всё это работает на деле...
Попозже напишу...

На первый взгляд твоя процедура более умная, чем моя.... и компактная....
Re[6]: Блокировка окна
От: IRaven Ниоткуда  
Дата: 08.04.05 04:03
Оценка:
Здравствуйте, Diouzshev, Вы писали:

D>Если подумать — недолго.

D>Нужно написать наследник от TForm, который будет в OnCreate (Create, AfterConstruction, где заработает) создавать панель и перекладывать все контролы с формы на нее автоматом.
D>А в твоих сотнях форм поменять только
D>TMyForm132 = class(TForm) на TMyForm132 = class(TPaneledForm) и в Uses прописать
D>Имхо это проще, чем оконную процедуру у всей сотни форм переписывать

Сделано это все для псевдомодальности. Есть у меня TCustomMyForm, от которого унаследованы все формы. Псевдомодальность соответственно многоуровневая. Т.е. можно вызвать фактически несколько форм одна из другой, и при активации любой, содержащей ссылку на дочернюю будет активироваться дочерняя. Перетаскивание нужно, т.к. приложение MDI, и иногда для удобства требуется передвигать родительские формы. По-моему идея с перекладкой компонентов на панель одна из самых легких. Правда у меня проблемы будут с сохранением форм в базу, все-таки манипулировать панелью прийдется.
Re[2]: Блокировка окна
От: IRaven Ниоткуда  
Дата: 08.04.05 04:05
Оценка:
Здравствуйте, Vodyamba, Вы писали:

V>Здравствуйте, IRaven, Вы писали:


V>Надо делать как сказали... второе окно сделать StayOnTop, а все контролы сделать Контрол.enabled:=false

V>Могу дать процедуру, которая перебирает все контролы... чуть подредактируешь и всё ОК будет...
V>Данная процедура устанавливает всем компонентам всех форм свойство Ctl3d:=true и подобные...
V>Получилась габаритная правда... но работает...

Не выйдет. Это решение только для 2-х уровней вызовов. У меня же их должно быть сколько угодно. Больше подходит вариант с перетаскиванием на панель.
Re[2]: Блокировка окна
От: IRaven Ниоткуда  
Дата: 08.04.05 04:08
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Я могу тебе предложить решение для псевдо-модальных окон, только никак не пойму зачем тебе таскать 1 окно?

D>Это ж тебе еще надо и кнопочки на 1 окне дизаблить и черт знает еще чего.

Именно псевдомодальность нужна. Как в Парусе. Enabled в False сделать выйдет без проблем
Re[3]: Блокировка окна
От: Аноним  
Дата: 08.04.05 06:02
Оценка: +1
А не проще ли:

type
  TWinControlStub = class(TWinControl);

procedure RemoveFlat (Control: TControl);
var
  i: Integer;
begin
  if Control is TWinControl then 
    TWinControlStub(Control).Ctl3D := True;

    for i := 0 to Control.ControlCount - 1 do
      RemoveFlat (Control.Controls[i]);
  end;
end;
Re[3]: Блокировка окна
От: Danchik Украина  
Дата: 08.04.05 09:19
Оценка: 1 (1)
Здравствуйте, IRaven, Вы писали:

IR>Здравствуйте, Danchik, Вы писали:


D>>Я могу тебе предложить решение для псевдо-модальных окон, только никак не пойму зачем тебе таскать 1 окно?

D>>Это ж тебе еще надо и кнопочки на 1 окне дизаблить и черт знает еще чего.

IR>Именно псевдомодальность нужна. Как в Парусе. Enabled в False сделать выйдет без проблем


Хм, а я то думал что псевдомодальность это не так то все просто
Псевдомодальность в моем понимании это окно которое висит поверх вызвавшего его окна и как бы ты не дергался оно там и держится, не мешая при этом другим окнам. Да и еще запрещается ввдод (клики, кнопки) на вызвавшем окне. Поставить Always On Top и задизаблить контролы на вызвавшей форме? Какая же это модальность это просто решение частичного случая.
Представь себе ситуацию когда тебе надо открыть два окна и из них вызвать псевдомодальные. Чесно юзер не возьмет себе в толк к какому окну пренадлежит другое, а ще если из псевдомодального вызвать еще одно псевдомодальное ууу... — будет бардакевич.

Смотри картинки:
F1 и F2 просто формы, M1 и M2 ихние псевдомодальные окна, а M1M — псевдомодальное окно окна M1

(как неправильно: Z-order просто ни в красную армию...)


    _________
 __|__       |
|     | F2___|__
| F1 _|__|      |
|   |    |  M2  |
|___| M1 _____  |
    |___|     | |
        | M1M |_|
        |     |
        |_____|



(Правильно 1)


    _________
 __|__       |
|     | F2___|__
| F1 _|__|_     |
|   |      |M2  |
|___| M1 __|__  |
    |___|     | |
        | M1M |_|
        |     |
        |_____|


А теперь представь себе код который следит за тем что бы когда кликнуит или выберут на таск баре (да как угодно) на M1M или M1 или F1 получилось картинка (см. Правильно 1)
А если кликнуть на M2 или F2 — получилась картинка:

    _________
 __|         |
|  |    F2___|__
|F1|     |      |
|  |_____|  M2  |
|___| M1 |      |
    |___||      |
        ||______|
        |     |
        |_____|


Мне когда то пришлось такую проблему решать. И нескрою все получилось как нельзя лучше и с малой кровью. Правда WinAPI начитался... яб сказал до опупения. А под конец для развлечения добавил моргание заголовка модального окна если кликнул в форму которая его вызвала. Типа куда кликаеш — закрой сначала меня

Другое дело если тебе такая функциональность не нужна

Summary: Берегите ваших юзеров, они иногда только в Word в своей жизни и видели
Re[4]: Блокировка окна
От: Danchik Украина  
Дата: 08.04.05 10:57
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>А не проще ли:


А>
А>type
А>  TWinControlStub = class(TWinControl);

А>procedure RemoveFlat (Control: TControl);
А>var
А>  i: Integer;
А>begin
А>  if Control is TWinControl then 
А>    TWinControlStub(Control).Ctl3D := True;

А>    for i := 0 to Control.ControlCount - 1 do
А>      RemoveFlat (Control.Controls[i]);
А>  end;
А>end;
А>


Ну что тебе сказать... Куда же ты BevelKind дел (эт правда неважно)? Да и зачем дергать тех кто не пользуется этим свойством. А если "умный" контрол реинтродюснул Ctl3d или BevelKind.
Это был просто пример чтоб увидеть как работать с RTTI (Runtime Type Information). Я не помню поддерживает TWinControl то или иное свойство (посмотрел, вспомнил ), я знаю что мне надо изменить их.

Причем с этим подходом можна прекрассно проставлять свойство ReadOnly чтоб сделать форму нередактируемой но живой.
Привожу пример процедуры для тех кому интересно (поддерживаются Developer Express's cxEditors)

procedure SetReadOnlyForControls (Component : TComponent; ReadOnly : Boolean);
var
  K : Integer;
  aPropInfo : PPropInfo;
  aObj : TObject;
begin
  for K := 0 to Component.ComponentCount - 1 do begin
    aPropInfo := GetPropInfo (Component.Components [K], 'Properties', [tkClass]);
    if aPropInfo = nil then
      aObj := Component.Components [K]
    else begin
      aObj := GetObjectProp (Component.Components [K], aPropInfo);
      if aObj = nil then
        Continue;
    end;

    aPropInfo := GetPropInfo (aObj, 'ReadOnly', [tkEnumeration]);
    if aPropInfo = nil then begin
      if aObj is TWinControl then
        if Pos('CHECKBOX', UpperCase (aObj.ClassName)) > 0 then
          TWinControl (aObj).Enabled := not ReadOnly;
      Continue;
    end;

    if aPropInfo.SetProc = nil then
      Continue;

    { only boolean props }
    if GetTypeData (aPropInfo.PropType^).BaseType^ <> System.TypeInfo(Boolean) then
      Continue;

    SetOrdProp (aObj, aPropInfo, Ord (ReadOnly));
  end;
end;
Re[3]: Блокировка окна
От: Vodyamba Россия  
Дата: 10.04.05 08:12
Оценка:
Здравствуйте, IRaven, Вы писали:

IR>Не выйдет. Это решение только для 2-х уровней вызовов. У меня же их должно быть сколько угодно. Больше подходит вариант с перетаскиванием на панель.


Непонятно чуть чуть "2-х уровней вызовов"... можно подробнее...
Re[4]: Блокировка окна
От: IRaven Ниоткуда  
Дата: 16.04.05 04:13
Оценка:
Здравствуйте, Danchik, Вы писали:

IR>>Именно псевдомодальность нужна. Как в Парусе. Enabled в False сделать выйдет без проблем

D>Хм, а я то думал что псевдомодальность это не так то все просто
D>Псевдомодальность в моем понимании это окно которое висит поверх вызвавшего его окна и как бы ты не дергался оно там и держится, не мешая при этом другим окнам. Да и еще запрещается ввдод (клики, кнопки) на вызвавшем окне. Поставить Always On Top и задизаблить контролы на вызвавшей форме? Какая же это модальность это просто решение частичного случая.

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

D>Представь себе ситуацию когда тебе надо открыть два окна и из них вызвать псевдомодальные. Чесно юзер не возьмет себе в толк к какому окну пренадлежит другое, а ще если из псевдомодального вызвать еще одно псевдомодальное ууу... — будет бардакевич.


Прошу учесть — сохранение активности серий тоже должно быть. Т.е. если я активирую любое окно из серии то активным станет последнее в цепочке вызванное окно. Какждое окно не может породить более одного "псевдомодального"(или псевдоактивного) окна.

D>Смотри картинки:

D>F1 и F2 просто формы, M1 и M2 ихние псевдомодальные окна, а M1M — псевдомодальное окно окна M1

D>(как неправильно: Z-order просто ни в красную армию...)


D>А теперь представь себе код который следит за тем что бы когда кликнуит или выберут на таск баре (да как угодно) на M1M или M1 или F1 получилось картинка (см. Правильно 1)

D>А если кликнуть на M2 или F2 — получилась картинка:

[skipped]

Так мы и реализовали. Активная серия вся пермещается на ближайший z-порядок, т.е. как нарисована на втором рисунке. Это я с самого начала и имел ввиду, только видать некорректно выражался.
Спасибо за советы и ответы!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.