Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Scrollbar & Enabled - bug?


Страницы:   1 2

HCode ©   (2006-02-19 18:04:00) 

procedure TForm1.MainFormFormCreate(Sender: PObj);
begin
 ScrollBar1.Enabled:= false; // Не работает!
 //  Button1.Visible:= false; // Работает.
end;

Поверхностная отладка показала, что при вызове SetEnabled - ScrollBar1.fHandle =0.

P.S. Версия KOL - 2.33


ECM   (2006-03-03 15:49:00) [1]

Во-первых присутствует, только надо включить TabStop и установить на него фокус (я думаю можно это свойство засветить в MCK - плохого в этом нет ничего - а кому то может пригодится):

 ScrollBar1.Style := ScrollBar1.Style or WS_TABSTOP;  
Теперь при получении фокуса (программно или после щелчка мыши) scrollbar реагирует (сам, без доп. кода в KOL)

А во вторых - это не всегда удобно - допустим у Вас два скроллбара вертикальный и горизонтальный и хочется чтобы клавиатурный скроллинг выполнялся одновременно (без переключения фокуса). Вобщем мысль такая:
Вести обработку нажатия кнопок надо в предке т.е. общем в контроле (это не всем нужно да и для этих целей уже ScrollBox есть) - и лучше это сделать в программе руками. Слишком много вариантов - все не учтешь..
Так как оно сейчас - не ограничивает Ваши возможности...
...ИМХО


HCode   (2006-03-03 15:24:00) [2]

Все работает, спасибо!
Но возник еще один вопрос. Почему отсутствует поддержка управления ScrollBar'а клавиатурой?


Владимир Кладов   (2006-03-03 06:35:00) [3]

А и протестируем. Вот в выходеной буду обновление делать, заодно может уже и попадет туда. У меня есть пара проектов со скроллбаром. На них и гляну.


ECM   (2006-03-02 18:47:00) [4]

Исследовав ситуацию выяснил, что для текущей версии ScrollBar-a (2.33) действительно имеет место следующее:
- невозможность "нормально" обработать SB_ENDSCROLL и SB_THUMBPOSITION;
- не работает установка ширины (для sbVertical) или высоты (для sbHorizontal);
- собственно Subj ветки :))

Исправления предложенные мной в [3] вобщем тоже негодятся (выяснил при тщательном тестировании). В результате могу предолжить вариант исправлений, который по моим тестам исправляет ситуацию полностью, (вот только не знаю правильно ли это идеологически? - без создания окна для ScrollBar-а прямо в NewScrollBar - пока не получается все поставить на место). Вобщем вот исправления для KOL.PAS (исправленные места - {!ecm}{/!ecm}):

//[function NewScrollBar]
function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
const SBS_Directions: array[ TScrollerBar ] of DWORD = ( SBS_HORZ or SBS_BOTTOMALIGN,
     SBS_VERT or SBS_RIGHTALIGN );
begin
 Result := _NewCommonControl(
   AParent,
   'SCROLLBAR',
   WS_VISIBLE or WS_CHILD or SBS_Directions[ BarSide ],
   False,
   nil
 );
{!ecm}
 Result.GetWindowHandle;
{/!ecm}

 Result.DetachProc(WndProcCtrl);
 Result.fLookTabKeys := [tkTab];

//#ecm  Result.AttachProc(WndProcScrollBar);
 AParent.AttachProc(WndProcScrollBarParent);
end;
//[END NewScrollBar]


//[function WndProcScrollBarParent]
function WndProcScrollBarParent( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
var
 Bar: PControl;
 SI: TScrollInfo;
 NewPos: Integer;
 AllowChange: Boolean;
 Cmd: Word;

begin
 Result := False;
...
       Cmd := Msg.wParam and $0000FFFF;
       case Cmd of
         SB_BOTTOM: NewPos := SI.nMax;
         SB_TOP: NewPos := SI.nMin;
         SB_LINEDOWN: NewPos := SI.nPos + 1;
         SB_LINEUP: NewPos := SI.nPos - 1;
         SB_PAGEDOWN: NewPos := SI.nPos + Integer(SI.nPage);
         SB_PAGEUP: NewPos := SI.nPos - Integer(SI.nPage);
          {!ecm}
         SB_THUMBPOSITION,SB_THUMBTRACK: NewPos := SI.nTrackPos;
         SB_ENDSCROLL: NewPos := SI.nPos;
         {/!ecm}
       
         else
           Exit;
       end;
...


В результате - все три приведенных выше глюка исчезают, плюс код облегчается - теперь WndProcScrollBar не используется ...
Попробуйте протестировать у себя этот вариант...!


HCode   (2006-03-01 13:56:00) [5]


> Вообще, припоминаю, что скроллбар я начал делать, а доделал кто-то другой.

И к сожалению это заметно. Отсутствует возможность назначить обработчик для некоторых событий, например - SB_ENDSCROLL. Отследить это событие проверяя значение Cmdв процедуре ScrollBarSBScroll(Sender: PControl; Cmd: Word) невозможно. Приходится ловить это событие в фукции FormMessage(var Msg: tagMSG; var Rslt: Integer), что несколько неудобно.

2 ECM
Похоже, вы больше всех понимаете в этой проблеме. Пожалуйста, если вас не затруднит, покажите изменения в KOL.pas устраняющие ошибку - "Enabled" и если можно, описанную :) в начале этого сообщения.


Thaddy   (2006-02-28 23:05:00) [6]

Yes, I somewhat misunderstood :) But fact remains that people want 'features' or even expect 'feature' from the VCL to propagate to KOL :)
And my code sometimes helps a liitle ;) (But isn't failproof!) An example is the CS_NOCLOSE style, that is not possible from default KOL code.

But I agree, better to do things right in the first place... :)


ecm   (2006-02-28 22:26:00) [7]

Тут дело не в пересоздании (ReCreate) , а в отложеном создании окна... И в ошибке инициализации параметров окна (что естественно) до его создания.
Что касается VCL то в том что по каждому пустяку окно пересоздается - не есть хорошо...:) Т.е - это отнюдь не достоинство VCL - сколько раз приходилось наступать на грабли, что после изменения параметров окна - его Handle становился другим.


Thaddy   (2006-02-28 21:41:00) [8]

My code causes any extra information that is necessary to create the WindowClass to be reinitialised.: The KOL object remains existing, the Windwos API class is reinstantiated. The code is a free interpretation of how the VCL works!


ecm   (2006-02-28 21:30:00) [9]

Тут главный критерий - отсутствие багов в работе... может такая суперотложенная инициализация(Post из WM_CREATE) и нужна (хотя я не могу себе представить зачем).  Я не применяю ScrollBar - мне судить тяжело - тут надо потестировать ...
На мой взгляд - надо инициализацию перенести прямо в обработчик WM_CREATE


Thaddy   (2006-02-28 21:29:00) [10]

Simply calling Createwindow is dangeous and can cause leaks.

This code can also cause problems, but works in most cases (even for scrollbar)

// Code to simulate recreatewindow for KOL controls
// Surfaces protected fields and methods outside kol.pas
type
 PHack = ^THack;
 THack = object(TControl)end;

procedure ReCreateWindow(aControl:PControl);
begin
DestroyWindow(aControl.Getwindowhandle);// nil window is ignored
PHack(aControl).fHandle:=0;                     // rest of object stays intact
aControl.CreateWindow;                           // Now call create window
end;


Vladimir Kladov   (2006-02-28 20:39:00) [11]

я вообще плохо реагирую на слово "баг". Для меня баг, это когда все падает, и надо систему перезагружать.

Так все-таки, чего исправлять? А то  что-то запутался. (Нет, ECM, в самом деле, все выкинуть что ли. А что останется?).

Вообще, припоминаю, что скроллбар я начал делать, а доделал кто-то другой. Можно историю поднять. А уже потом я как-то для него зеркало добавил. Так что не могу точно сказать, почему там внутри так, а не иначе.


ECM   (2006-02-28 16:31:00) [12]


> Можно ли боротся с этой ошибкой без модификации KOL.pas?

Можно - см. пост [3] вариант 2)


HCode   (2006-02-28 15:27:00) [13]

2 Vladimir Kladov
Если установить свойство в ScrollBar даже в среде разработки, то ScrollBar все равно доступен пользователю :(

2 ECM
Можно ли боротся с этой ошибкой без модификации KOL.pas?


ECM   (2006-02-21 21:10:00) [14]

З.Ы. т.е все дело в применении SetScrollInfo (и SetScrollRange - имхо надо бы пользоваться только SetScrollInfo как рекомендовано в MSDN) - без флага
SIF_DISABLENOSCROLL сбрасывает состояние DISABLED.


ECM   (2006-02-21 21:00:00) [15]


> WS_DISABLED в стиле есть, но при создании окна скроллбара
> ни на что не влияет. Видимо, так устроен скролбар в АПИ.
>  Для него срабатывает EnableWindow / WM_ENABLE, но только
> когда он уже виден на экране.

Мне кажется Вы не правы - WS_DISABLED при создании - влияет как надо
просто потом при обработке KSB_INITIALIZE в WndProcScrollBar он заново
разрешается см. [3]. В этом можно убедится если временно изметить в KOL.PAS:

function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
const SBS_Directions: array[ TScrollerBar ] of DWORD = ( SBS_HORZ or SBS_BOTTOMALIGN,
     SBS_VERT or SBS_RIGHTALIGN );
begin
 Result := _NewCommonControl(
   AParent,
   'SCROLLBAR',
   WS_VISIBLE or WS_CHILD or WS_DISABLEDor SBS_Directions[ BarSide ],
   False,
   nil
 );
 Result.DetachProc(WndProcCtrl);
 Result.fLookTabKeys := [tkTab];
//  Result.AttachProc(WndProcScrollBar); 
 AParent.AttachProc(WndProcScrollBarParent);
end;

Подчеркнутый текст у Вас тоже не виден?
(добавлен WS_DISABLED и выброшена WndProcScrollBar)
Можно убедится что в тестовом проекте - ScrollBar будет задизабленным


Vladimir Kladov   (2006-02-21 19:53:00) [16]

Точно сказать не могу. Создал тестовый проект, походил по шагам. (Кстати, отложенная отправка сообщения форме работает). WS_DISABLED в стиле есть, но при создании окна скроллбара ни на что не влияет. Видимо, так устроен скролбар в АПИ. Для него срабатывает EnableWindow / WM_ENABLE, но только когда он уже виден на экране.


HCode   (2006-02-20 22:55:00) [17]


> если даже в OnShow не работает, делается так: в OnShow себе
> же (форме) отправляется сообщение например WM_USER_1, в
> OnMessage оно ловится, и делает что надо. Есть еще метод
> "ленивый": таймер на 100 ms "завести", но тут гарантий чуть
> меньше.

МудрЕно :)


> А кстати, может и не работать в OnShow, действительно: ведь
> сообщение которое там в обработчике WM_CREATE отправлялось,
>  может (и даже наверняка) оказалось в очереди после которое
> вызывает срабатывание OnShow.

Странно... На кнопке, рамке и возможно других элементах - работает, даже в OnCreate, не говоря уже о OnShow. Почему это присуще только ScrollBar'у?


Vladimir Kladov   (2006-02-20 21:22:00) [18]

если даже в OnShow не работает, делается так: в OnShow себе же (форме) отправляется сообщение например WM_USER_1, в OnMessage оно ловится, и делает что надо. Есть еще метод "ленивый": таймер на 100 ms "завести", но тут гарантий чуть меньше.

А кстати, может и не работать в OnShow, действительно: ведь сообщение которое там в обработчике WM_CREATE отправлялось, может (и даже наверняка) оказалось в очереди после которое вызывает срабатывание OnShow.


ECM   (2006-02-20 21:12:00) [19]


> Но увы...

А можно узнать подробнее почему?
Что-то я никак не могу понять причину... в каких случаях еще может приходить "ненужный" WM_CREATE?
Заранее благодарен...


HCode   (2006-02-20 20:02:00) [20]


> Уважаемый Владимир, разумеется, прежде чем сообщить сюда
> об этой ошибке я попробывал вызывать ScrollBar1.Enabled:
> = false; в OnFormCreate, но к сожалению это не помогло.

Извините, описался :(
Как раз имелось ввиду не OnCreate, а OnShow!


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо