Конференция "KOL" » Modal form memorized their size [Delphi, Windows]
 
  • RusSun © (14.03.10 16:46) [0]
    Доброе время суток.
    Конечно про модальные формы было сказанно довольно много,
    но всё же задам вопрос: Может кому приходилось делать
    так чтобы модальная форма запоминала свои размеры (top,left,h...,w...).

    то есть при следующем открытии сохранённые размеры использовались бы формой.
  • Vladimir Kladov © (14.03.10 17:20) [1]
    И что в этом такого необычного?
  • RusSun © (16.03.10 20:21) [2]
    Доброе время суток.

    Вот простой пример с которого пытаюсь сделать в своей программе,
    только вот не задача не могу применить его.
    Чтобы не заморачиваться просто прячу форму и снова показываю и при
    закрытии основного окна закрываю.

    program Project1;

    uses
     windows,
     kol;

    {$R *.res}
    type  TOnEvent = procedure( Sender: PObj )of object;
    var
    form,Button1,
    editbox1,editbox2,
    form2,Button5,Button6,
    Button7,Button8,Button9,
    ListBox1:PControl;
    HintWND,HintWnd2: HWND;
    TI: TToolInfo;
    Tips: array[0..9] of PChar = (
      'Кнопка Открыть',
      'ЭдитБох1',
      'ЭдитБох2',
      '',
      'Сохранить',
      'Удалить',
      'Очистить',
      'Добавить',
      'Отмена',
      'ListBox1');

    //область для процедур
    procedure mousemove(Dummy:pointer;Sender: PControl; var Mouse: TMouseEventData );
    begin
    with TI do
    begin
      cbSize:=sizeof(TI);
      uFlags:=TTF_SUBCLASS;
      //if Assigned( Form2 ) then hWnd2:=Sender.GetWindowHandle else
      hWnd:=Sender.GetWindowHandle;
      uID:=0;
      Rect.Left:=Sender.ClientRect.Left;
      Rect.Top:=Sender.ClientRect.Top;
      Rect.Right:=Sender.ClientRect.Right;
      Rect.Bottom:=Sender.ClientRect.Bottom;
      hInst:=HInstance;
      lpszText:=Tips[Sender.Tag];
      form.StatusText[0]:=Tips[Sender.Tag];
    end;
    if Assigned( Form2 ) then SendMessage(HintWnd2,TTM_ADDTOOL,0,DWORD(@TI)) else
    SendMessage(HintWnd,TTM_ADDTOOL,0,DWORD(@TI));
    end;
    procedure Destr2(Dummy:pointer;Sender:PControl);
    begin
    DestroyWindow(HintWnd2);
    Form.Show;
    end;
    //************************************************************
    // Здесь вызываю показываю модальным окном
    //************************************************************
    procedure clickbutton1(Dummy:pointer;Sender:PControl; var mouse:TMouseEventData);
    begin
    if not Assigned( Form2 ) then
       NewForm(  Applet ,'');
     Form2.Showmodal;
    end;

    procedure Destr(Dummy:pointer;Sender:PControl);
    begin
    DestroyWindow(HintWnd);
    end;
    procedure Close_form(DummySelf,Sender: PControl; var Accept: Boolean);
    begin
    accept:=true;
    end;
    //************************************************************
    // Закрытие модальной формы
    //************************************************************
    procedure Close_form2(DummySelf,Sender: PControl; var Accept: Boolean);
    begin
    Accept := FALSE;
    Form2.Hide;
    button1.Focused:=true;//Передаю фокус ввода
    end;

    Begin
    //********************************************************
    // первая форма
    //********************************************************
    form:=NewForm(Applet,'hide'+#39+'s '+#8470+'1').SetSize(330,240).CenterOnParent;
    form.StatusText[0]:=pchar('');
    form.tag:=3;
    Button1:=NewButton(form,'Form2.Showmodal').autosize(true);
    Button1.CenterOnParent;//размещаент объект по середине родительского.
    Button1.Tag:=0;
    Button1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    EditBox1:= NewEditBox(form,[]).SetPosition( 10, 34 ).SetSize( 60, 0 );
    EditBox1.Color:=clWhite;
    EditBox1.Text :=' 10.00 ';
    editbox1.Tag:=1;
    EditBox1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
       
    EditBox2:= NewEditBox(form,[]).SetPosition( 10, 58 ).SetSize( 60, 0 );
    EditBox2.Color:=clWhite;
    EditBox2.Text :=' 10.01 ';
    editbox2.Tag:=2;
    EditBox2.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    //область для работы
    Button1.OnClick:=TonEvent(MakeMethod(nil,@clickbutton1));
    HintWnd:=CreateWindowEx(0,TOOLTIPS_CLASS,nil,0,CW_USEDEFAULT,CW_USEDEFAULT,CW_US EDEFAULT,CW_USEDEFAULT,form.GetWindowHandle,0,HInstance,nil);
    form.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    form.OnDestroy:=TonEvent(MakeMethod(nil,@Destr));
    form.OnClose:=TOnEventAccept(MakeMethod(nil,@Close_form));
    //********************************************************
    // вторая форма
    //********************************************************
    Form2:= NewForm(Applet,'hide'+#39+'s '+#8470+'2'){.SetPosition( 202, 192 )}.SetClientSize( 320, 222 ).CenterOnParent;
    Form2.Style := Form.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);//отключаем кнопку раскрыть и минимизировать
    form2.Tag:=3;
    ListBox1 := NewListBox( form2, [ loNoIntegralHeight ] ).SetPosition( 6, 6 ).SetSize( 241, 169 );
    ListBox1.Color := clWindow;
    ListBox1.CurIndex := 0;
    ListBox1.Tag:=9;
    ListBox1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    Button5:= NewButton( form2, 'Сохранить' ).SetPosition( 156,192).SetSize( 74, 0 );
    Button5.tag:=4;
    Button5.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    Button6:= NewButton( form2, 'Удалить' ).SetPosition( 80,192).SetSize( 72, 0 );
    Button6.tag:=5;
    Button6.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    Button7:= NewButton( form2, 'Очистить' ).SetPosition( 250,148).SetSize( 68, 0 );
    Button7.tag:=6;
    Button7.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    Button8:= NewButton( form2, 'Добавить' ).SetPosition(8,192).SetSize( 68, 0 );
    Button8.tag:=7;
    Button8.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    Button9:= NewButton( form2, 'Отмена' ).SetPosition( 236,192).SetSize( 68, 0 );
    Button9.tag:=8;
    Button9.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    HintWnd2:=CreateWindowEx(0,TOOLTIPS_CLASS,nil,0,CW_USEDEFAULT,CW_USEDEFAULT,CW_U SEDEFAULT,CW_USEDEFAULT,form2.GetWindowHandle,0,HInstance,nil);
    form2.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    form2.OnDestroy:=TonEvent(MakeMethod(nil,@Destr2));
    form2.OnClose:=TOnEventAccept(MakeMethod(nil,@Close_form2));
    form2.Hide;
    Run(form);

    end.

  • RusSun © (16.03.10 20:21) [3]
    В своей программе делаю тоже самое


    //************************************************************
    // Здесь вызываю показываю модальным окном
    //************************************************************
    procedure Edit(Sender:pcontrol);
    begin
    if not Assigned( EditQst ) then
       NewForm(  Applet ,'');
    EditQst.Showmodal;
     //логичнее всего тут поставить EditQst.free
     //чтобы избавится от двойного нажатия на закрытие
     //но тогда больше форма не открывается :(
    //EditQst.free;
    end;



    //************************************************************
    // Закрытие модальной формы
    //************************************************************
    procedure EditQstClose(Dummy:pointer;Sender: PControl;  var Accept: Boolean);
    begin
    accept:=false; // Запрещаю закрытие
    EditQst.hide; // прячу
    QRez.Focused:=true;//передаю фокус на другую форму
    //закрытие приходится делать дважды
    //хотя в простом примере и так работает:(
    end;


    и ...
    //************************************************************
    //Форма которую хочу прятать
    //************************************************************
    EditQst:=NewForm(applet,'Редактирование вопроса').SetSize( 496,285  ).SetPosition( 327, 248 );
    EditQst.Color := TColor(clBtnface);
    EditQst.Style := Form.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);//отключаем кнопку раскрыть и минимизировать
    EditQst.Font.FontName := 'MS Sans Serif';
    EditQst.Font.FontCharset := 0;
    EditQst.Tag:=2; //HINT
    EditQst.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    EditQst.OnResize:=TonEvent(MakeMethod(nil,@formResize));

    PB1 := NewPaintBox(EditQst ).SetPosition(0, 0 ).SetSize(362, 216 );
    PB1.Color := TColor(clWhite);
    PB1.Tag:=2; //HINT
    PB1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    L1 := NewLabel( PB1, 'Вопрос:' ).SetPosition( 12, 23 ).SetSize( 50, 0 );
    L1.Font.Color := TColor(clblue);
    //Ввод вопроса
    EB1 := NewEditBox( PB1, [  ] ).SetPosition( 68, 18).SetSize( 282, 0);
    EB1.Color := clWindow;
    EB1.Tag:=5; //HINT
    EB1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    L2 := NewLabel( PB1, 'Ответы:' ).SetPosition( 8, 53 ).SetSize( 54, 0 );
    L2.Font.Color := TColor(clblue);
      {$R Form1_BitBtn2.res}
    Bt2 := NewBitBtn( PB1, 'Добавить', [  ], glyphLeft, LoadBmp( hInstance, 'BITBTN2_BITMAP', PB1 ), 1 ).SetPosition( 70, 52 ).SetSize( 84, 22 );
    Bt2.Color := TColor(clBtnFace);
    Bt2.TextShiftX := 1;
    Bt2.TextShiftY := 1;
    Bt2.OnClick:=TonEvent(MakeMethod(nil,@Bt2click));
    Bt2.Tag:=6; //HINT
    Bt2.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    {$R Form1_BitBtn1.res}
    Bt1 := NewBitBtn( PB1, 'Удалить', [  ], glyphLeft, LoadBmp( hInstance, 'BITBTN1_BITMAP', PB1  ), 1 ).SetPosition( 164, 52 ).SetSize( 78, 22 );
    Bt1.Color := TColor(clBtnFace);
    Bt1.TextShiftX := 1;
    Bt1.TextShiftY := 1;
    Bt1.OnClick:=TonEvent(MakeMethod(nil,@Bt1click));
    Bt1.Tag:=7; //HINT
    Bt1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    QuestionCheckList:=newlistview(PB1,lvsDetailNoHeader,[lvoNoScroll,lvoCheckBoxes] ,nil,nil,nil).SetPosition(12,82).SetSize(332,132);
    QuestionCheckList.Tag:=2; //HINT
    QuestionCheckList.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    B1 :=NewButton( EditQst, 'Да' ).SetPosition( 216, 224 ).SetSize( 75, 25 );
    B1.OnClick:=TonEvent(MakeMethod(nil,@DaBtn));
    B1.Tag:=8; //HINT
    B1.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));

    B2 :=NewButton( EditQst, 'Отмена' ).SetPosition( 304, 224 ).SetSize( 75, 25 );
    B2.OnClick:=TonEvent(MakeMethod(nil,@CloseBtn));
    B2.Tag:=4; //HINT
    B2.OnMouseMove:=TonMouse(MakeMethod(nil,@mousemove));
    HintWnd3:=CreateWindowEx(0,TOOLTIPS_CLASS,nil,0,CW_USEDEFAULT,CW_USEDEFAULT,CW_U SEDEFAULT,CW_USEDEFAULT,EditQst.GetWindowHandle,0,HInstance,nil);
    EditQst.OnClose:=TOnEventAccept(MakeMethod(nil,@EditQstClose));
    EditQst.hide;
    //************************************************************


    весь код : http://slil.ru/28805632
  • Игорь Шевченко © (16.03.10 22:05) [4]
    Не знаю, как на KOL, в Windows решается обработчиком одного сообщения:

    например, та самая модальная форма:

    unit modal;

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

    type
     TfModal = class(TForm)
       Edit1: TEdit;
       Button1: TButton;
     private
       procedure WmActivate (var Message: TWMActivate); message WM_ACTIVATE;
     end;

    var
     fModal: TfModal;

    implementation
    uses Types;

    var
     IsSaved: Boolean;
     SavedPos: TRect;

    {$R *.dfm}

    { TfModal }

    procedure TfModal.WmActivate(var Message: TWMActivate);
    begin
     if Message.Active = WA_INACTIVE then
     begin
       GetWindowRect(Handle, SavedPos);
       IsSaved := true;
     end
     else if IsSaved then
       MoveWindow(Handle, SavedPos.Left, SavedPos.Top,
         SavedPos.Right - SavedPos.Left, SavedPos.Bottom - SavedPos.Top, true);
     inherited;
    end;
    end.

  • RusSun © (17.03.10 17:38) [5]
    Доброе время суток.
    Вы имеете ввиду что-то вроде
    ....
    var
    IsSaved: Boolean; SavedPos: TRect;
    ....
    function WndProcActiv(Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
    begin
     Result:=false;
     if M.message =WM_NCACTIVATE then
     begin
       Result:=true;
       if Bool(M.wParam) then  begin GetWindowRect(EditQst.Handle, SavedPos); //GetWindowRect(ParentHandle, ParentRect);
                                     IsSaved := true;
       end else if IsSaved then
      MoveWindow(EditQst.Handle, SavedPos.Left, SavedPos.Top,
        SavedPos.Right - SavedPos.Left, SavedPos.Bottom - SavedPos.Top, true)
     end;
    end;
    ....
    EditQst.AttachProc(@WndProcActiv);



    Хм... Не получится  форма создается и уничтожается runtime
  • Vladimir Kladov © (17.03.10 19:03) [6]
    В KOL+MCK я использовал событие OnFormCreate. Если MCK не используется, все еще проще: код установки размеров и позиции встраивается просто в тот участок кода, который создаёт форму. В VCL, аналогично я использую OnCreate формы. И никакой разницы, модальная форма или нет.
  • RusSun © (17.03.10 19:10) [7]
    Спасибо. Принято. Вопрос: как избавится от того, что когда форма
    уже вновь создаваясь и получив нужные (l,t,w,h)
    всё же не появляется там же где её закрыли,
    а смещается то влево, то вправо?
  • Vladimir Kladov © (17.03.10 20:07) [8]
    Искать ошибку.
  • Игорь Шевченко © (18.03.10 21:04) [9]

    > Хм... Не получится  форма создается и уничтожается runtime


    не вижу проблемы обработать WM_ACTIVATE у динамически создаваемой формы. В KOL разве нет аналога WindowProc ?
  • Vladimir Kladov © (18.03.10 22:14) [10]
    Есть OnMessage, он лучше. Так как не требует наследовать новый класс, работает для любого контрола или формы.

    НО. The WM_ACTIVATE message is sent to both the window being activated and the window being deactivated. Каждый раз, а не при первой активации после создания.

    И. Зачем сначала создавать форму одного размера, выравнивая на ней контролы, а затем менять ее размер, получая кучу сообщений об изменении размеров родительских контролов и перевыравнивая все выровненные дочерние. Когда можно задать размеры сразу при создании.
  • RusSun © (19.03.10 15:00) [11]
    Доброе время суток.
    Отдохнул один день. Отказался от старого варианта.
    Посмотрел новый. И всё пошло как надо.
    ...
    var
    IsSaved:boolean;SavedPos: TRect;
    ...
    function WndProcActiv(Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
    begin
     Result:=false;
     if M.message =WM_NCMOUSEMOVE then
     begin
       Result:=true;
       if Bool(M.wParam) then  begin
          GetWindowRect(EditQst.Handle, SavedPos);
                 IsSaved := true;
                               end;

     end;
    end;
    ...
    if not IsSaved then
    EditQst:=NewForm(QRez,'Редактирование вопроса').SetSize( 496,305  ).SetPosition( 327, 248 ) else
    EditQst:=NewForm(QRez,'Редактирование вопроса').SetSize(SavedPos.Right - SavedPos.Left, SavedPos.Bottom - SavedPos.Top).SetPosition( SavedPos.Left, SavedPos.Top );
    ...
    EditQst.AttachProc(@WndProcActiv);
    ...
    formResize(Sender);//если размеры изменятся, то и содержимое тоже
    ...


    Всем Спасибо, тема закрыта;)
  • RusSun © (19.03.10 15:03) [12]
    Можно было просто через событие Onmessage
    без AttachProc(@WndProcActiv)
    не сразу посмотрел:)
 
Конференция "KOL" » Modal form memorized their size [Delphi, Windows]
Есть новые Нет новых   [134430   +2][b:0][p:0.007]