Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.17;
Скачать: CL | DM;

Вниз

Scrollbar & Enabled - bug?   Найти похожие ветки 

 
HCode   (2006-02-19 18:04) [0]

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

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

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


 
Vladimir Kladov   (2006-02-19 21:56) [1]

ну так в чем проблема? Трудно вызвать GetWndowHandle, что ли.


 
HCode   (2006-02-19 22:50) [2]

В смысле? В KOL.SetEnabled?


 
ECM ©   (2006-02-20 11:41) [3]

Посмотрел ситуацию...

> Трудно вызвать GetWndowHandle, что ли.

Это, конечно, первое что приходит в голову - но, к сожалению, дела не меняет..:(

procedure TForm1.KOLForm1FormCreate(Sender: PObj);
begin
 ScrollBar1.CreateWindow;
 ScrollBar1.Enabled := FALSE;
end;

Хендл окна создается - запрет его тоже проходит нормально...

Но, ScrollBar1 всё равно в конце-концов получается  Enabled = TRUE.

Происходит это из-за отложенной инициализации ScrollBar-a при создании:
//[function WndProcScrollBar]

function WndProcScrollBar( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
begin
 Result := False;
 case Msg.message of
   WM_CREATE:
     PostMessage(Sender.Handle, KSB_INITIALIZE, KSB_KEY, KSB_KEY);

   KSB_INITIALIZE:
     if (Msg.wParam = Msg.lParam) and (Msg.wParam = KSB_KEY) then
     begin
       Sender.SBPageSize := Sender.fSBPageSize;
       Sender.SBMinMax := Sender.fSBMinMax;
       Sender.SBPosition := Sender.fSBPosition;
     end;
 end;
end;


Жирные строки (даже каждая в отдельности) приводит к тому, что окно
скроллбара снова оказывается незапрещенным.

Тайный смысл почему тут используется PostMessage (а не прямая инициализация в NewScrollbar или уж в крайнем случае SendMessage) мне неясен...

У меня получилось исправить сей момент двумя способами:

1) Заменить PostMessage на SendMessage

function WndProcScrollBar( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
begin
 Result := False;
 case Msg.message of
   WM_CREATE:
     SendMessage(Sender.Handle, KSB_INITIALIZE, KSB_KEY, KSB_KEY);

   KSB_INITIALIZE:
     if (Msg.wParam = Msg.lParam) and (Msg.wParam = KSB_KEY) then
     begin
       Sender.SBPageSize := Sender.fSBPageSize;
       Sender.SBMinMax := Sender.fSBMinMax;
       Sender.SBPosition := Sender.fSBPosition;
     end;
 end;
end;


2) Заставить выполниться инициализацию до запрета ScrollBar-a (пока не годится для MCK):

procedure TForm1.KOLForm1FormCreate(Sender: PObj);
begin
 ScrollBar1.CreateWindow;
 Applet.ProcessMessages;
 ScrollBar1.Enabled := FALSE;
end;


 
homm ©   (2006-02-20 12:36) [4]


> Тайный смысл почему тут используется PostMessage (а не прямая
> инициализация в NewScrollbar или уж в крайнем случае SendMessage)
> мне неясен...
Только не в NewScrollbar, а в WndProcScrollBar реакцией на WM_CREATE. В NewScrollbar нет еще хендела, и
Sender.SBPageSize := Sender.fSBPageSize;
идентично
Sender.fSBPageSize := Sender.fSBPageSize;

2 Vladimir Kladov

> ну так в чем проблема? Трудно вызвать GetWndowHandle, что ли.
По-моему это откровенная грубость. Зачем так на новичков нападать?


 
ECM ©   (2006-02-20 14:50) [5]


> Только не в NewScrollbar, а в WndProcScrollBar реакцией
> на WM_CREATE. В NewScrollbar нет еще хендела

Это как раз понятно...это касаемо первого варианта решения [3]
Я имел ввиду второй вариант решения (может я слишком сумбурно описал)
т.е. всмыле что особой разницы между вызовом CreateWindow в OnFormCreare и в функции NewScrollBar нет... :))


 
Vladimir Kladov   (2006-02-20 16:15) [6]

Ну хорошо, в OnFormCreate не прокатывает, последняя инстанция, что ли. Есть еще OnShow (только флажок добавить, что показ идет в первый раз), там и сделать.

А вообще из мухи слона делаете. Что за надобность такая скроллбар запрещать (вдруг). Не проще ли сделать, чтобы его не было видно, пока он не нужен.

а жирных строк в коде я не вижу. Dolphin"ом смотрю, а он не показывает. (Иначе было бы очень весело грузить некоторые ветки на полторы сотни сообщений в браузере)


 
ECM ©   (2006-02-20 17:08) [7]

Да нет, никаких мух и слонов...:)
Я думаю - вариант с заменой Post на Send - ставит всё на свои места
кода не увеличивает - глюки вроде не добавляет...
я в письме забросил исправление...


 
HCode   (2006-02-20 17:47) [8]


> Ну хорошо, в OnFormCreate не прокатывает, последняя инстанция,
>  что ли. Есть еще OnShow (только флажок добавить, что показ
> идет в первый раз), там и сделать.

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


 
Vladimir Kladov   (2006-02-20 18:55) [9]

А зачем тогда вообще посылать  сообщение? Я бы мог прямо в WM_CREATE и сделать все что нужно. Но увы...

Я же говорю: есть еще OnShow.


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


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

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


 
ECM ©   (2006-02-20 21:12) [11]


> Но увы...

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


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

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

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


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


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

МудрЕно :)


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

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


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

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


 
ECM ©   (2006-02-21 21: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_DISABLED or SBS_Directions[ BarSide ],
   False,
   nil
 );
 Result.DetachProc(WndProcCtrl);
 Result.fLookTabKeys := [tkTab];
//  Result.AttachProc(WndProcScrollBar);  
 AParent.AttachProc(WndProcScrollBarParent);
end;

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


 
ECM ©   (2006-02-21 21:10) [16]

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


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

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

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


 
ECM ©   (2006-02-28 16:31) [18]


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

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


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

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

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

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


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

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;


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

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


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

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 22:26) [23]

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


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

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... :)


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


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

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

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


 
ECM ©   (2006-03-02 18:47) [26]

Исследовав ситуацию выяснил, что для текущей версии 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 не используется ...
Попробуйте протестировать у себя этот вариант...!


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

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


 
HCode   (2006-03-03 15:24) [28]

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


 
ECM ©   (2006-03-03 15:49) [29]

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

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

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



Страницы: 1 вся ветка

Текущий архив: 2006.12.17;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.062 c
15-1164707613
Rentgen
2006-11-28 12:53
2006.12.17
Mайл-сервер WinGate | *


15-1164602002
Думкин
2006-11-27 07:33
2006.12.17
Имидж России, Сибири.


15-1164366912
dreamse
2006-11-24 14:15
2006.12.17
Подскажите компонент


15-1164428991
IMHO
2006-11-25 07:29
2006.12.17
Почему Центробанк скупает доллары тоннами


11-1141244125
appla
2006-03-01 23:15
2006.12.17
Проблема. КОЛ не генерирует корректний .inc файл