Конференция "Начинающим" » как работать с TSplitter у которого Align := alNone ?
 
  • Ruzzz © (13.10.08 21:54) [0]
    Нужно изменять размер компонента, у которого также Align := alNone
    Подскажите как быть?

    Цель такова, есть TMemo, его нужно расположить на форме по центру как по вертикали, так и по горизонтали, но нужно иметь возможность изменять размеры этого Memo. Делаю два коэф. которые указывают размеры МЕМО в процентах от размера Form1.ClientWidth и Form1.ClientHeight, и изменяю размер МЕМО в FormResize, также в FormResize "подгоняю" сплитеры к краям МЕМО.

    Проблема в том что не могу сдвинуть сплитеры с места :(
  • Ruzzz © (13.10.08 21:57) [1]
    Фраза "нужно иметь возможность изменять размеры этого Memo" - значить изменять эти коеф-ты, а изменять их я хочу с помощью сплитеров, думаю так будет красивее, чем создавать диалог настроек
  • Юрий Зотов © (13.10.08 22:12) [2]
    Киньте на форму 4 панели (с alTop, alBottom, alkLeft и alRight) и 4 сплиттера (с таким же выравниванием), а потом TMemo с alClient.

    В FormResize устанавливайте размеры панелей. Сплиттеры никуда подгонять не надо, они сами подгонятся.

    Только непонятно - если Memo всегда должен быть по центру, то зачем вообще нужны сплиттеры? Сплиттеры позволяют юзеру менять размеры контролов мышкой, но если он начнет эти размеры менять, то нарушится центровка Memo - а этого ведь не должно быть?
  • Сергей М. © (13.10.08 22:12) [3]
    Нафих тебе сдались сплиттеры - ума не приложу ..

    На форме, кроме собственно мемо, есть еще какие-либо контролы, размер и положение которых зависит от размера и положения мемо ?
  • Ruzzz © (13.10.08 22:19) [4]
    нет, на форме только Мемо и все, про 4 панели думал, но решил пока поискать более "изящное" решение. Планирую сдеалать два сплитера, по вертикали и па горизонтали соотв.. Узер двигает сплитер, и Мемо меняет свой размер (уменьшается/увеличивается) но остается по центру, т.е. противоположная сторона также будет синхронно изменяться. Вот из за этого и не хочу 4 панели, ибо прийдется корректировать размер противоположной панели, поюсь что все мигать начнет.

    Щас пробую с TShape.

    Когда то делал так что при нажатии и удерживании кнопки мыши, контрал передвигался, но тогда я делал компонент. наверное это мне сейчас и нужно. Может что еще подскажете? Заранее спасибо!!!
  • KilkennyCat © (13.10.08 22:48) [5]

    > Когда то делал так что при нажатии и удерживании кнопки
    > мыши,

    ReleaseCapture;
    perform(WM_SysCommand, $F012, 0);
  • Ruzzz © (14.10.08 00:29) [6]
    Спасибо! Но этот способ также как и:

    procedure WMNCHITTEST(var Message : TMessage); message  WM_NCHITTEST;
    ...
    procedure TMoveControl.WMNCHITTEST(var Message: TMessage);
    begin
     if not (csDesigning in ComponentState) then begin
       Message.Result := HTCAPTION;
       if Assigned(FOnMove) then FOnMove(Self);
     end
     else
       Message.Result := HTCLIENT;
    end;

    не совсем подходит, так как зависит от системных настроек "Показывать окно при перемещении" и получить координаты компонента можна получить только когда пользователь отпустит кнопку мыши.

    Я решил использовать что-то типа как в у форм область в правом нижнем углу, для изменения размеров Мемо
  • KilkennyCat © (14.10.08 00:58) [7]

    > получить координаты компонента можна получить только когда
    > пользователь отпустит кнопку мыши.

    неправда.

    > как в у форм область в правом нижнем углу,

    для этого F012 изменяется на другое значение. Не помню какое, вычислял экспериментально.
  • Германн © (14.10.08 01:03) [8]
    Раньше помню часто спрашивали как в рантайме передвигать контролы и как менять их размеры. Сейчас пошли продвинутые вопросы :)
  • {RASkov} © (14.10.08 01:17) [9]
    > Не помню какое

    $F008
  • Ruzzz © (14.10.08 01:36) [10]
    спасибо! ) сделал TControl(Sender).Perform(WM_SYSCOMMAND, SpinEdit1.Value , 0) - много интересного нашел :)

    теперь осталось научить получать предполагаемые новые размеры окна до того как будет отпущена кнопка мыши.


    > > получить координаты компонента можна получить только когда
    >
    > > пользователь отпустит кнопку мыши.
    >
    > неправда.


    KilkennyCat, прошу помощи!!!

    делаю так:
    procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
    begin
     if Button = mbLeft then
     begin
       ReleaseCapture;
       TControl(Sender).Perform(WM_SYSCOMMAND, $F008 , 0); // $F012
     end;
    end;

    procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
    begin
     Caption := IntToStr(x) + ' ' + IntToStr(y);
    end;

    procedure TForm1.Panel1Resize(Sender: TObject);
    begin
     Caption := FloatToStr(Panel1.Width) + ' ' + FloatToStr(Panel1.Height);
    end;



    результата нет :( какие сообщения мыши или резайза ловить? и в каком окне(ну может родителя)?
  • Ruzzz © (14.10.08 02:36) [11]
    KilkennyCat, пока что пришел только к тому чтобы использовать таймер :), это по поводу:

    > получить координаты компонента можна получить только когда
    > пользователь отпустит кнопку мыши.

    неправда.

    -

    подскажите как?
  • KilkennyCat © (14.10.08 08:12) [12]
    ну, например, не зацикливаться на панели. не только она знает про мышь.
  • KilkennyCat © (14.10.08 08:18) [13]
    кроме того, раз контрол перерисовывается, то перерисовывалке его размеры известны.
  • {RASkov} © (14.10.08 13:14) [14]
    Вот попробуй вариант решения задачи:
    DFM
    object Form1: TForm1
     Left = 192
     Top = 114
     Width = 602
     Height = 374
     Caption = 'Form1'
     Color = clBtnFace
     Font.Charset = DEFAULT_CHARSET
     Font.Color = clWindowText
     Font.Height = -11
     Font.Name = 'MS Sans Serif'
     Font.Style = []
     OldCreateOrder = False
     OnResize = FormResize
     PixelsPerInch = 96
     TextHeight = 13
     object Panel1: TPanel
       Left = 164
       Top = 100
       Width = 185
       Height = 61
       BorderWidth = 2
       Caption = 'Panel1'
       TabOrder = 0
       OnMouseDown = Panel1MouseDown
       OnMouseMove = Panel1MouseMove
       object Memo1: TMemo
         Left = 3
         Top = 3
         Width = 179
         Height = 55
         Align = alClient
         Lines.Strings = (
           'Memo1')
         TabOrder = 0
       end
     end
    end



    PAS
    unit Unit1;
    interface
    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;

    type
     TPosMouseRect = (pmNone, pmRect, pmLU, pmU, pmRU, pmR, pmRD, pmD, pmLD, pmL);

     TForm1 = class(TForm)
       Panel1: TPanel;
       Memo1: TMemo;
       procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
       procedure Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
       procedure FormResize(Sender: TObject);
     private { Private declarations }
       OldX, OldY: Integer; PMDown: TPosMouseRect;
     public { Public declarations }
     end;

    var Form1: TForm1;

    implementation

    {$R *.dfm}

    function GetPosMouseInRect(Rct: TRect; MP: TPoint; AVal: Integer): TPosMouseRect;
    function XLeft: Boolean; begin Result:=MP.X<Rct.Left+AVal; end;
    function XRight: Boolean; begin Result:=MP.X>Rct.Right-Rct.Left-AVal; end;
    function XCentr: Boolean; begin Result:=(MP.X>=Rct.Left+AVal) and (MP.X<=Rct.Right-Rct.Left-AVal) end;
    function YTop: Boolean; begin Result:=MP.Y<Rct.Top+AVal; end;
    function YBottom: Boolean; begin Result:=MP.Y>Rct.Bottom-Rct.Top-AVal end;
    function YCenter: Boolean; begin Result:=(MP.Y>=Rct.Top+AVal) and (MP.Y<=Rct.Bottom-Rct.Top-AVal) end;
    begin
     Result:=pmNone;
     if not PtInRect(Rct, MP) then Exit;
     if XLeft and YTop then Result:=pmLU else
     if XLeft and YCenter then Result:=pmL else
     if XLeft and YBottom then Result:=pmLD else
     if XCentr and YTop then Result:=pmU else
     if XRight and YTop then Result:=pmRU else
     if XRight and YCenter then Result:=pmR else
     if XRight and YBottom then Result:=pmRD else
     if XCentr and YBottom then Result:=pmD else
     Result:=pmRect;
    end;

    procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
     OldX:=X; OldY:=Y; PMDown:=GetPosMouseInRect(Panel1.ClientRect, Point(X, Y), 4);
    end;

    procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    var NewX, NewY: Integer;
    begin
     case GetPosMouseInRect(Panel1.ClientRect, Point(X, Y), 4) of
      pmRect, pmNone: Panel1.Cursor:=crDefault;
      pmU, pmD: Panel1.Cursor:=crSizeNS;
      pmLU, pmRD: Panel1.Cursor:=crSizeNWSE;
      pmLD, pmRU: Panel1.Cursor:=crSizeNESW;
      pmL, pmR: Panel1.Cursor:=crSizeWE;
     end;
     if not (ssLeft in Shift) then Exit;
     NewX:=X-OldX;
     NewY:=Y-OldY;
     with (Sender as TControl) do
      case PMDown of
       pmRect: SetBounds(Left + NewX, Top + NewY, Width, Height); //В принципе в данной задаче не нужно.
       pmL:  SetBounds(Left + NewX, Top, Width+-NewX*2, Height);
       pmLU: SetBounds(Left + NewX, Top + NewY, Width+-NewX*2, Height+-NewY*2);
       pmU:  SetBounds(Left, Top + NewY, Width, Height+-NewY*2);
       //pmR: Sorry...
       //pmD: Sorry...
       //pmRD: Sorry...
       //pmLD: Sorry...
      end;
    end;

    procedure TForm1.FormResize(Sender: TObject);
    begin
     Panel1.Left:=(ClientWidth-Panel1.Width) div 2;
     Panel1.Top:=(ClientHeight-Panel1.Height) div 2;
    end;

    end.



    Вот только четыре строчки придумай сам.... у меня математика болит :( Голова ломается....
    Собсно там нужно придумать одну, а остальные аналогично...
    Если придет ко мне озорение я и их напишу тебе, но....)
    :о)
  • {RASkov} © (14.10.08 13:17) [15]
    Есть и глюки, но это не конечный вариант, а направление... :)
  • {RASkov} © (14.10.08 13:43) [16]
    Хотя, я думаю и этого варианта будет достаточно... Нужно только закомментировать изменение курсора в "неполучившихся" местах и делов.... :)
    Т.е. изменение размеров мемо можно производить по верхней, левой стороне и за верхний-левый угол.... Думаю достаточно...
    У меня как-то инвертированно получилось с другими, вот например с правой:
    pmR: SetBounds(Left + NewX, Top, Width - NewX*2, Height);

    - не красиво :(
    В общем... можно и подумать, но сейчас времени нет....
    Так же и после расчета NewX, NewY можно вставить:
    if (NewX>=Panel1.Width-20) or (NewY>=Panel1.Height-20) then Exit; //20 это минимальный размер


    но тоже криво работает.... пишу на коленке.... некогда больно тестить и думать, но думаю натолкну на мысли...
    :)
  • {RASkov} © (15.10.08 21:07) [17]
    Пришло ко мне никому не нужное озарение....
       pmR:    begin
                SetBounds(Left - StepX, Top, Width + StepX*2, Height);
                OldX:=X+StepX;
               end;
       pmD:    begin
                SetBounds(Left, Top - StepY, Width, Height + StepY*2);
                OldY:=Y+StepY;
               end;
       pmRD:   begin
                SetBounds(Left - StepX, Top - StepY, Width + StepX*2, Height + StepY*2);
                OldX:=X+StepX; OldY:=Y+StepY;
               end;
       pmLD:   begin
                SetBounds(Left + StepX, Top - StepY, Width + -StepX*2, Height + StepY*2);
                OldY:=Y+StepY;
               end;
       pmRU:   begin
                SetBounds(Left - StepX, Top + StepY, Width + StepX*2, Height + -StepY*2);
                OldX:=X+StepX;
               end;
      end;


    StepX{Y} - Это которые NewX{Y}....
    А с ограничениями размеров панели.... слишком много кода уже и так :)
    В общем я пробывал сделать общую проверку типа:
    if (Panel1.Width<=20+StepX) or (Panel1.Height<=20+StepY) then Exit;


    Это не вся проверка, а кусок, но все равно глючно все это.....
    Эту проверку нужно вставлять в case перед сменой размеров и положения панели(SetBounds) Т.е. на каждый pmXx....
    Эх.... пригодилось бы только кому :(
    :о)
  • Ruzzz © (16.10.08 03:47) [18]
    спасиб {RASkov}, но я немного не то хочу ) наверное я просто не правильно выразил свои мысли

    если не боитесь вирусов :) то можете попробовать запустить то что у меня получилось http://upload.com.ua/link/900494914
  • Ruzzz © (16.10.08 03:51) [19]
    ну вирусов конечно же нет, программу решил написать по мотивам блокнота DarkRoom
  • Германн © (16.10.08 03:54) [20]

    > Ruzzz ©   (16.10.08 03:47) [18]
    >
    > спасиб {RASkov}, но я немного не то хочу ) наверное я просто
    > не правильно выразил свои мысли
    >
    > если не боитесь вирусов :) то можете попробовать запустить
    > то что у меня получилось http://upload.com.ua/link/900494914
    >

    И что этот запуск даст?
  • {RASkov} © (16.10.08 09:37) [21]
    > [18] Ruzzz ©   (16.10.08 03:47)

    Ясно) Получилось вроде бесспорно лучше чем у меня, но и у меня вроде тоже самое, даже больше.... у меня за любую точку можно менять, а у тебя только за черный квадрат.... Но вот ограничения я не стал делать.... Хотя это(квадрат) может быть задумкой, но я так и не понял для чего вообще нужен этот черный квадрат в блокноте? :) Имхо.... это просто какойто каприз :)
  • Ruzzz © (16.10.08 20:24) [22]
    да, это действитльно больше каприз :) это своего рода попытка программирования интерфейса ) ну и что-то типа блокнота DarkRoom.
  • GrayFace © (16.10.08 22:07) [23]
    Вопрос, ответ на который - WM_NCMOUSEMOVE - все еще актуален? :)
 
Конференция "Начинающим" » как работать с TSplitter у которого Align := alNone ?
Есть новые Нет новых   [134435   +34][b:0][p:0.004]