![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
На базе TListBox реализовал фильтрующий поиск. Когда вводишь символ, поверх листбокса появляются TEdit и еще один листобокс. Текст вводится в TEdit, отфильтрованные результаты поиска - в дочерний листбокс:
![]() Проблема: при кликаньи дочернего листбокса проявляется (моргает) основной листбокс, также иногда проявляются вертикальный скролбар родительского. Причем, этот скролбар при входе в режим поиска я убираю функцией ShowScrollBar(Handle,SB_VERT,false), но при кликаньи он все равно появляется. Собственно, вопрос: как заставить родительский листбокс не отрисовывать себя, чтобы никаких морганий не было и скролбары не появлялись? |
|
#2
|
||||
|
||||
|
LockWindowUpdate(...).
|
|
#3
|
|||
|
|||
|
Цитата:
Нет. В этом случае вообще все внутри листбокса перестает отрисовываться. Необходимо сделать так, чтобы только строки и скролбары родительского листобокса не отрисовывались. Дочерние контролы должны отрисовываться как обычно. |
|
#4
|
|||
|
|||
|
а если так?
PHP код:
|
|
#5
|
|||
|
|||
|
Цитата:
Вот это помогло. Строки родительского листбокса не проявляются. Теперь осталась проблема со скролбарами. |
|
#6
|
|||
|
|||
|
По поводу скролбаров:
Удалось только перманентно отключить скроллбары через CreateParams, исключить из стиля флаги WS_HSCROLL и WS_VSCROLL. Но это не решает проблему, так как скролбары нужны, когда поиск не используется. Их нужно именно включать и отключать. В принципе, для этого есть SetWindowLong, но вертикальный скролбар почему-то не отключается. Код следующий: Код:
style:=GetWindowLong(Handle,GWL_STYLE);
SetWindowLong(Handle,GWL_STYLE,style and not WS_HSCROLL and not WS_VSCROLL);
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_FRAMECHANGED);Вертикальный скролбар не убирается. Здесь обсуждалась моя проблема, но там пришли к выводу, что это вообще невозможно - отключать скроллбары у уже созданных листбоксов. Я что-то сомневаюсь в этом, может просто что-то еще надо сделать? |
|
#7
|
||||
|
||||
|
Может вы не тем путем пошли? Может проще было завести дополнительно TStringList куда поместить исходные данные. А вот при поиске отображать в вашем листбоксе только отфильтрованные данные.
|
|
#8
|
|||
|
|||
|
Цитата:
В этом случае геморроя еще больше. Та же проблема со скроллбарами + ручная отрисовка. Проблема со скролбарами решилась при помощи CreateParams + RecreateWnd. В CreateParams, в зависимости от режима, исключаются/не исключаются флаги WS_HSCROLL и WS_VSCROLL, а при активации и деактивации поиска вызывается RecreateWnd. Видимо, это единственное решение. Спасибо всем за советы. |
|
#9
|
||||
|
||||
|
Не думаю, что гемороя больше будет. Вот вполне рабочий вариант:
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
procedure ListBox1KeyPress(Sender: TObject; var Key: Char);
procedure Edit1Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
SrcData: TStringList;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.ListBox1KeyPress(Sender: TObject; var Key: Char);
begin
Edit1.Perform(WM_CHAR, LongInt(Key), 0);
end;
procedure TForm1.Edit1Change(Sender: TObject);
Var Index: Integer;
begin
ListBox1.Clear;
SrcData.Find(Edit1.Text, Index);
while Index <= SrcData.Count - 1
do begin
if AnsiUpperCase(Copy(SrcData.Strings[Index],1,Length(Edit1.Text))) <> AnsiUpperCase(Edit1.Text)
then Break;
ListBox1.Items.Add(SrcData.Strings[Index]);
Inc(Index);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SrcData := TStringList.Create;
SrcData.CaseSensitive := False;
SrcData.Text := ListBox1.Items.Text;
SrcData.Sort;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SrcData.Free;
end;
end.
|
|
#10
|
||||
|
||||
|
А что мешало на момент фильтрации сделать невидимым (Visible:=False) родительский ListBox?
|
|
#11
|
|||
|
|||
|
Цитата:
|
|
#12
|
||||
|
||||
|
Ну сам же писал:
Цитата:
|
|
#13
|
|||
|
|||
|
Цитата:
|
|
#14
|
||||
|
||||
|
еще один рабочий вариант (2 TListBox, 1 TEdit - все как у ТС):
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
ListBox1: TListBox;
Edit1: TEdit;
ListBox2: TListBox;
procedure ListBox1KeyPress(Sender: TObject; var Key: Char);
procedure Edit1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure Edit1Change(Sender: TObject);
procedure ListBox2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses StrUtils;
{$R *.dfm}
procedure TForm1.ListBox1KeyPress(Sender: TObject; var Key: Char);
begin
Edit1.Text:=Key;
Edit1.Visible:=True;
ListBox2.Visible:=True;
Edit1.SetFocus;
Edit1.SelStart:=-1;
end;
procedure TForm1.Edit1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key=VK_ESCAPE then
begin
Edit1.Hide;
ListBox2.Hide;
ListBox1.SetFocus;
end;
end;
procedure TForm1.Edit1Change(Sender: TObject);
var
i: Integer;
begin
ListBox2.Clear;
for i:=0 to ListBox1.Items.Count-1 do
begin
if AnsiStartsText(Edit1.Text, ListBox1.Items[i]) then
ListBox2.Items.Add(ListBox1.Items[i]);
end;
end;
procedure TForm1.ListBox2Click(Sender: TObject);
var
i: Integer;
Key: Word;
begin
i:=ListBox1.Items.IndexOf(ListBox2.Items[ListBox2.ItemIndex]);
if i<>-1 then
begin
ListBox1.ItemIndex:=i;
Key:=VK_ESCAPE;
Edit1KeyUp(Edit1, Key, []);
end;
end;
end.http://data.cod.ru/130546 |