Конференция "Компоненты" » Создание компонента со скроллбарами [D7, WinXP]
 
  • EG (20.07.07 18:45) [0]
    Задача: написать визуальный компонент (), видимую область которого можно прокручивать его собственными  скроллбарами.

    Пояснения: компонент наследуется от TCustomControl'a, обладает свойством Align.

    Вопрос: Что нужно сделать, чтобы у компонента появились виндузовские скроллбары? Есть мнение, что это свойство наследуется от WinControl'a, но не открыто...и что копать к тому же надо в сторону WinApi...

    Очень хочется или подробного комментария, или не менее полезную ссылку. Заранее большое спасибо всем отклинувшимся.
  • Dib@zol © (20.07.07 19:02) [1]

    > копать к тому же надо в сторону WinApi...

    эт правильно. Нужно в CreateParams добавить два стилевых флага: WM_HSCROLL и WM_VSCROLL.
  • EG (20.07.07 19:25) [2]

    > Нужно в CreateParams добавить два стилевых флага


    Это как-то так?

    procedure TMyComponent.CreateParams(var Params: TCreateParams);
    begin
     Params.Style := WM_HSCROLL;
    end;



    Ругается, что параметр задан не верно... Не подскажите синтаксис установки параметров?
  • Dib@zol © (20.07.07 19:29) [3]
    Эх... Никада не делал этого раньше... Я про CreateParams только слышал. Ваще мой тебе совет переходи на АПИ. А с этим погоди ща разберёмся.
  • Dib@zol © (20.07.07 19:34) [4]
    Удалено модератором
  • EG (20.07.07 19:42) [5]

    > Тфу ёшкинсвет, не WM_, а WS_ !!!!!!!!!!! Прости великодушно.
    > ..

    Круто! Заработало! Но чуточку не так, как я ожидал... Теперь мой компонент - отдельное окно... летает себе... но скролл появился!

    И чего это он выпал из контейнера...

    Отделение произошло из-за чего? Что не так с Controls'ами?
  • EG (20.07.07 20:00) [6]
    Разобрался! Вернул на место. Люди, не повторяйте моих ошибок!
    Свойство Params.Style задается в предке, не стоит его полностью изменять, если в этом нет нужды.

    Полная картина выглядит так:

    procedure TMyComponent.CreateParams(var Params: TCreateParams);
    begin
     inherited;
     Params.Style := Params.Style + WS_HSCROLL + WS_VSCROLL;
    end;

    Dib@zol ©  - отдельное спасибо!
  • Dib@zol © (20.07.07 20:00) [7]
    Дело вот в этом. Изини, тож забыл :)
    Params.Style := Params.Style + WM_HSCROLL;
  • Dib@zol © (20.07.07 20:01) [8]

    > Люди, не повторяйте моих ошибок!

    Уже повторили :) Надо ж блин, как совпало ;)
  • EG (20.07.07 20:10) [9]
    А вариант с WinApi как бы выглядел?
  • Dib@zol © (20.07.07 20:20) [10]
    var
     ScrollHWND:HWND;
     WP : Pointer;

    ...

    ScrollHWND:=CreateWindow(0, 'STATIC', '', WS_VISIBLE or WS_CHILD or WS_HSCROLL or WS_VSCROLL, 1, 1, 300, 300, Parent, 0, HInstance, nil);
    longInt(WP):=SetWindowLong(ScrollHWND, GWL_WNDPROC, LongInt(@NewWndProc));

    Где Parent - хендл родительского окна. NewWndProc нужно?
  • EG (20.07.07 20:21) [11]

    > NewWndProc нужно?


    Да!
  • Dib@zol © (20.07.07 20:28) [12]
    function NewWndProc(hWnd : HWND; Msg, WParam, LParam : LongInt) : LongInt; stdcall;
    begin
     Result:=0;
     case Msg of

       WM_COMMAND:
         begin
           // Здесь принимаются сообщения от дочерних контролов
         end;

       WM_CTLCOLOR*:
         begin
           // Ответственные за перерисовку (WM_CTLCOLORSTATIC, WM_CTLCOLOREDIT итп)
         end;

       // Да мало ли чего ещё сюда можно напихать! :) Эти - просто примеры.

       else Result:=CallWindowProc(WP, hWnd, Msg, WParam, LParam);
     end;
    end;
  • EG (20.07.07 20:32) [13]
    Огромный Тенкс!!!!

    Я думаю, что тема прикрыта, но не закрыта...
  • Юрий Зотов © (21.07.07 11:57) [14]
    > EG   (20.07.07 20:32) [13]

    Ну, раз тема не закрыта, то предложу еще одно решение - взять стандартный TScrollBox.

    :о)
  • Dib@zol © (21.07.07 12:17) [15]

    > Юрий Зотов ©   (21.07.07 11:57) [14]

    > Задача: написать визуальный компонент
  • {RASkov} © (21.07.07 13:29) [16]
    > [15] Dib@zol ©   (21.07.07 12:17)
    >
    > > Юрий Зотов ©   (21.07.07 11:57) [14]
    >
    > > Задача: написать визуальный компонент

    Зачем его писать, если он уже написан? :)

    > EG
    Чем твоя задача отличается от [14]? Хотя может.... тогда уже наследуйся от него(TScrollBox)...или его предка (скролингвиндов)... имхо.
    Зачем с нуля "велик" делать?
  • Юрий Зотов © (21.07.07 13:49) [17]
    > Dib@zol ©   (21.07.07 12:17) [15]

    Довольно часто ЗАДАЧА возникает лишь по причине незнания того, что она уже давно ЗАДАЧЕЙ вовсе не является.
    :о)
  • Dib@zol © (21.07.07 14:05) [18]
    Удалено модератором
  • Юрий Зотов © (21.07.07 15:24) [19]
    > Dib@zol ©   (21.07.07 14:05) [18]

    Один человек спросил у другого, где можно купить сигарет. Тот ответил, что их можно купить в магазине, который находится в 5 километрах.

    А другой человек сказал, что такой же магазин находится за углом, в 50 метрах. И тогда первый человек возразил: "Ну так или иначе, я поццказал".

    И ведь действительно подсказал. Но лучше бы он этого не делал.
  • EG (23.07.07 18:33) [20]
    Поверьте, велик делать никому не охота, а просто приходится...
    Причина проста: нужен компонент с нестандартной функциональностью. Точнее с такой, какой готовые варианты и решения не обладают в полной мере.


    > Чем твоя задача отличается от [14]?


    Тем, что компонент должен быть самодостаточным в своей функциональности.

    Требуемый компонент - это не скроллбар. Скроллбар лишь одна из его видимых частей, реализующая определенную функциональность, в данном случае скроллирование видимой области.
  • Юрий Зотов © (23.07.07 18:43) [21]
    > EG   (23.07.07 18:33) [20]

    А почему бы эту прокручиваемую область не сделать в виде агрегированного TScrollBox?
  • EG (23.07.07 18:45) [22]
    Хм... Ни разу не юзал эту вещь... может помочь в моей ситуации?
  • Юрий Зотов © (23.07.07 19:14) [23]
    Если компонент оконный, а его прокручиваемая область по своей функциональности ничем не отличается от TScrollBox, то ее и надо делать этим самым TScrollBox-ом.

    Компонент в своем конструкторе создает TScrollBox, его Owner-ом и Parent-ом ставит Self, выставляет позицию, размеры и прочие настройки TScrollBox-а. Вот и все.

    Еще более простой вариант - взять фрейм, накидать на него все, что нужно, написать в нем необходимый код и зарегистрировать его в качестве компонента.
  • Игорь Шевченко © (24.07.07 15:24) [24]

    > Если компонент оконный, а его прокручиваемая область по
    > своей функциональности ничем не отличается от TScrollBox,
    >  то ее и надо делать этим самым TScrollBox-ом


    Если нечто выглядит как собака, лает как собака и кусается как собака, то это и есть собака.

    Все компоненты с прокручваемой областью наследуются от TScrollingWinControl, все зависит от того, насколько область совпадает с желаемой клиентской областью. Если совпадает, как у TScrollBox/TForm/TFrame то проще наследоваться от них, если несовпадает, то проще создавать вложенный контрол, унаследованный от TScrollingWinControl.
  • Макс Черных © (25.07.07 01:46) [25]

    > Все компоненты с прокручваемой областью наследуются от TScrollingWinControl,
    >  все зависит от того, насколько область совпадает с желаемой
    > клиентской областью. Если совпадает, как у TScrollBox/TForm/TFrame
    > то проще наследоваться от них, если несовпадает, то проще
    > создавать вложенный контрол, унаследованный от TScrollingWinControl.
    >

    Ну не надо так категорично. :) Не все. (TCustomGrid = class(TCustomControl)) При написании всяких гридов и т.п. особенно, если могут быть фиксируемые столбцы, гораздо логичнее использовать стандартные скроллы. А вот лепить туда вложенный контрол будет уже вырыванием гландов через известное место. :)
  • Игорь Шевченко © (25.07.07 09:42) [26]
    Макс Черных ©   (25.07.07 01:46) [25]

    Не соглашусь хотя бы по той причине, что CustomGrid - довольно сложный компонент. И писать нечто подобное не для массового использования просто невыгодно.
  • EG (01.08.07 19:50) [27]
    HELP!
    Подскажите, как сказать системе, что сообщение

    WMVScroll(var Message: TWMVScroll)



    обработано?

    Или я не понимаю, что происходит: обрабатываю это сообщение с флагом SB_LINEUP, а мне после этого тут же валится еще одно сообщение с флагом SB_THUMBPOSITION.
  • EG (01.08.07 19:58) [28]
    На всякие пожарный привожу полный код:

    procedure TMyDocument.WMVScroll(var Message: TWMVScroll);
    var
     sbInfo : TSCROLLINFO;
     ScrollDY : integer;
     YScrollFullLength: integer;
     DocumentDY: integer;
    begin

     case ( Message.ScrollCode ) of
     {lineUp}
       0:
         begin

           sbInfo.fMask := SIF_POS or SIF_RANGE or SIF_TRACKPOS;
           sbInfo.cbSize := sizeof(TSCROLLINFO);
           GetScrollInfo( Handle, SB_VERT, sbInfo );
           YScrollFullLength := sbInfo.nMax - sbInfo.nMin;
           ScrollDY := YScrollFullLength div 100;
           DocumentDY := ( ScrollDY * FDocumentHeight ) div YScrollFullLength;
           MoveDocumentPosition( 0, DocumentDY );
           Repaint();

           sbInfo.cbSize := sizeof(TSCROLLINFO);
           sbInfo.fMask := SIF_POS;
           sbInfo.nPos := sbInfo.nPos - ScrollDY;
           SetScrollInfo( Handle, SB_VERT, sbInfo, true );
           
         end;
     {lineDown}
       1:;
     {PageUp}
       2:ShowMessage('');
     {PageDown}
       3:;
     {THUMBPOSITION}
     else
       begin
         sbInfo.fMask := SIF_POS or SIF_RANGE or SIF_TRACKPOS;
         sbInfo.cbSize := sizeof(TSCROLLINFO);
         GetScrollInfo( Handle, SB_VERT, sbInfo );

         if ( sbInfo.nPos <> sbInfo.nTrackPos )
           then
             begin
               ScrollDY := sbInfo.nPos - sbInfo.nTrackPos;
               YScrollFullLength := sbInfo.nMax - sbInfo.nMin;
               DocumentDY := ( ScrollDY * FDocumentHeight ) div YScrollFullLength;
               MoveDocumentPosition( 0, DocumentDY );
               Repaint();

               sbInfo.cbSize := sizeof(TSCROLLINFO);
               sbInfo.fMask := SIF_POS;
               sbInfo.nPos := sbInfo.nTrackPos;
               SetScrollInfo( Handle, SB_VERT, sbInfo, true );
             end;
       end;
     end;  

    end;

  • Lacmus © (01.08.07 20:40) [29]
  • EG (01.08.07 20:52) [30]

    > Lacmus ©   (01.08.07 20:40) [29]
    >
    > http://msdn2.microsoft.com/en-us/library/ms651284.aspx


    Может я тупой, но ненашел там ответа
  • EG (01.08.07 20:52) [31]

    > Lacmus ©   (01.08.07 20:40) [29]
    >
    > http://msdn2.microsoft.com/en-us/library/ms651284.aspx


    Может я тупой, но не нашел там ответа...
  • Lacmus © (01.08.07 21:05) [32]
    "Return Value

    If an application processes this message, it should return zero. "

    Значений Message.ScrollCode больше, чем Вы обрабатываете
  • EG (02.08.07 18:16) [33]

    > Lacmus ©   (01.08.07 21:05) [32]
    >
    > "Return Value
    >
    > If an application processes this message, it should return
    > zero. "
    >
    > Значений Message.ScrollCode больше, чем Вы обрабатываете


    Да, я тупой. Спасибо. Помогло.
  • bogdan10110 © (18.07.08 12:01) [34]
    Удалено модератором
  • DimaBr © (18.07.08 13:47) [35]
    Удалено модератором
  • имя (28.03.12 19:13) [36]
    Удалено модератором
  • имя (28.03.12 19:13) [37]
    Удалено модератором
 
Конференция "Компоненты" » Создание компонента со скроллбарами [D7, WinXP]
Есть новые Нет новых   [134427   +34][b:0][p:0.004]