Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "KOL";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];

Вниз

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 вся ветка

Форум: "KOL";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.041 c
15-1163240820
Sergey Masloff
2006-11-11 13:27
2006.12.17
Методики разработки в условиях нехватки ресурсов.


2-1164760887
Alek Aaz
2006-11-29 03:41
2006.12.17
Форматирование строк.


2-1164884539
kulkse
2006-11-30 14:02
2006.12.17
из DBGrid в ListBox


2-1164726603
PitTong
2006-11-28 18:10
2006.12.17
Текстовый редактор


15-1164606305
Тульский
2006-11-27 08:45
2006.12.17
Кидалово с жильем





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский