Консультация № 161669
01.03.2009, 08:56
0.00 руб.
0 33 2
Здравствуйте!
Помогите решить следующую проблему. На форме есть ScrollBox, а в нём StringGrid. Когда курсор попадает на StringGrid, то колесо мыши скроллит его, т.е. выделение по ячейкам ползает. Как можно сделать чтобы грид вообще не скроллился, а скроллился только ScrollBox со всем своим содержимым?

Обсуждение

Неизвестный
01.03.2009, 15:19
общий
Попробуйте использовать SetWindowLong с хэндлом от грида и параметром на новую оконную процедуру

Что-то типа: SaveWinProc := TWndProc(SetWindowLong(Grid.Handle, GWL_WNDPROC, Integer(@GridWinProc)));

А уже в своей GridWinProc отлавливаете события скролла и пересылайте скроллбоксу, а остальные отсылайте в SaveWinProc. Обычно такой трюк проходит со всеми оконными компонентами.
Неизвестный
01.03.2009, 16:02
общий
Armad
Прикольно. Теперь оба скроллинга одновременно работают. Уже ближе, но всё-равно не то. Во-первых, хотелось чтоб в гриде скролла вообще не было, т.е. выделенная ячейка не смещалась. А во-вторых, ScrollBox получился резиновый, хотя это наверное не сложно решается.

PavelGM
Теперь вы переоценили мои силы.

Может посоветуете вообще нечто другое. Я что-то с этим гридом замучился уже. Мне ещё ко всему надо его на печать выводить, а как оказалось это очень затейливое занятие. Что можно использовать для заполнения простенькой таблички (100 Х 4 [строк Х столбцов]) и чтобы на печать выводилось без премудростей?
давно
Профессионал
153662
1070
01.03.2009, 20:51
общий
Как ни странно но прежде чем написать ответ я его проверял в делфи вот эзешник. сетка при выделении ячейки не двигается. У меня 7 версия дэлфи.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 00:04
общий
Вы что таблицу в тексте делаете? Иначе зачем вам скроллбокс и грид одновременно. А ввод нужен или только посмотреть и напечатать? Если ввода нет, то проще самому рисовать табличку в Image, а его разместить в ScrollBox в нужное место.

А может вам вообще проще с Word работать как с COM-объектом в вашем приложении? Там и таблички и печать есть :). Задача-то какая изначально?
Неизвестный
02.03.2009, 05:47
общий
Genia007
У меня в вашем примере только сетка и двигается, а ScrollBox вообще мёртво стоит (при прокрутке колеса). Точнее не сетка, а активная ячейка меняется. То есть движение происходит в гриде, а мне это как раз не нужно. Мне надо чтоб грид не трогался при скролле, как будто он вообще просто нарисованный.

PavelGM
Да, Image скорее всего вёл бы себя как надо, но ввод нужен. Word, ну ... я сначала вообще не хотел Офис использовать, но когда обнаружились проблемы с выводом на печать грида, то пришлось таки сначала в Excell выгружать. А задача вобщем то простая, в Excell за пол дня решил бы, но надо в дельфях. Есть три бухгалтерские формы, они заполняются данными и на основе этих данных создаётся расчёт. Формы не маленькие (первая на 93 строки) вот поэтому и нужен грид и скроллинг. А над гридом идут несколько Edit'ов, наименование предприятия, ну и т.д. Если ещё и Word использовать, то дельфи вообще не нужен, макросами решить такую задачу не составит труда.
давно
Профессионал
153662
1070
02.03.2009, 11:15
общий
Как то странно вот на другой машине сделал тоже самое, вот этот проект, тыкам по ячейке и крутим колесо мыши, выделение остаётся на месте, а содержимое бокса перемещается. Или Вы делаете не так, тогда опишите как?
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 12:39
общий
Да я вобщем-то также делаю, тык в ячейку и кручу колесо. Но бокс не реагирует, только в гриде циферки бегут. Т.е. таким макаром кнопок я не вижу, только если мышкой возьму за ScrollButton (или как его там) и сдвину вниз, тогда вижу Button1 и Button2. Только так. В моей же программе, если ткнуть в Edit и покрутить колесо, то всё дигается как надо, вместе с гридом. Если же ткнуть в ячейку грида, то скроллиться начинает он (грид), т.е. активная ячейка сдвигается. Всё-таки надо отлавливать скрол от грида и отдавать его боксу, но я в сабклассинге не силён.

Попробую по другому объяснить. Если в вашем варианте сделать Height скажем 500, то он растянется вниз, так? У меня именно высота грида равна кол-во строк * высоту строк. Вот тогда и надо скроллить бокс, чтобы увидеть нижние строки. Но у вас бокс вообще колесом не двигается почему-то. Вот, посмотрите мой вариант.
давно
Профессионал
153662
1070
02.03.2009, 13:14
общий
А можно весь проект с исходниками и недостающими файлами? В таком виде как Вы прислали у меня работает как положено: выделяете ячейку или пишете в ней что нибудь, по движению колеса мышки происходит перемещение по скролбоксу. А какая у Вас версия дэлфи? А вот если ткнуть по ячейки и давить клавишу со стрелкой, то тогда идёт движение выделенной ячейки.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Профессионал
153662
1070
02.03.2009, 13:27
общий
Блин понял почему у нас такая разница: у меня стоит программа KatMouse, которая делает дополнительные возможности для кнопок и колеса мышки, и вот если её отключить, то всё становится как Вы пишите, попробую с этим разобраться.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Профессионал
153662
1070
02.03.2009, 14:44
общий
Можно тупо отключить скроллинг прямо в модуле Grids.pas и подключить этот изменённый модуль к проекту, остаётся только научить scrollbox двигаться по движению колеса. Вот этот изменнёный модуль.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Профессионал
153662
1070
02.03.2009, 15:03
общий
Кстате вот так можно распечатать сетку
Код:
uses
printers;

//StringGrid Inhalt ausdrucken
procedure PrintStringGrid(Grid: TStringGrid; Title: string;
Orientation: TPrinterOrientation);
var
P, I, J, YPos, XPos, HorzSize, VertSize: Integer;
AnzSeiten, Seite, Zeilen, HeaderSize, FooterSize, ZeilenSize, FontHeight: Integer;
mmx, mmy: Extended;
Footer: string;
begin
//Kopfzeile, Fu?zeile, Zeilenabstand, Schriftgro?e festlegen
HeaderSize := 100;
FooterSize := 200;
ZeilenSize := 36;
FontHeight := 36;
//Printer initializieren
Printer.Orientation := Orientation;
Printer.Title := Title;
Printer.BeginDoc;
//Druck auf mm einstellen
mmx := GetDeviceCaps(Printer.Canvas.Handle, PHYSICALWIDTH) /
GetDeviceCaps(Printer.Canvas.Handle, LOGPIXELSX) * 25.4;
mmy := GetDeviceCaps(Printer.Canvas.Handle, PHYSICALHEIGHT) /
GetDeviceCaps(Printer.Canvas.Handle, LOGPIXELSY) * 25.4;

VertSize := Trunc(mmy) * 10;
HorzSize := Trunc(mmx) * 10;
SetMapMode(Printer.Canvas.Handle, MM_LOMETRIC);

//Zeilenanzahl festlegen
Zeilen := (VertSize - HeaderSize - FooterSize) div ZeilenSize;
//Seitenanzahl ermitteln
if Grid.RowCount mod Zeilen <> 0 then
AnzSeiten := Grid.RowCount div Zeilen + 1
else
AnzSeiten := Grid.RowCount div Zeilen;

Seite := 1;
//Grid Drucken
for P := 1 to AnzSeiten do
begin
//Kopfzeile
Printer.Canvas.Font.Height := 48;
Printer.Canvas.TextOut((HorzSize div 2 - (Printer.Canvas.TextWidth(Title) div 2)),
- 20,Title);
Printer.Canvas.Pen.Width := 5;
Printer.Canvas.MoveTo(0, - HeaderSize);
Printer.Canvas.LineTo(HorzSize, - HeaderSize);
//Fu?zeile
Printer.Canvas.MoveTo(0, - VertSize + FooterSize);
Printer.Canvas.LineTo(HorzSize, - VertSize + FooterSize);
Printer.Canvas.Font.Height := 36;
Footer := 'Seite: ' + IntToStr(Seite) + ' von ' + IntToStr(AnzSeiten);
Printer.Canvas.TextOut((HorzSize div 2 - (Printer.Canvas.TextWidth(Footer) div 2)),
- VertSize + 150,Footer);
//Zeilen drucken
Printer.Canvas.Font.Height := FontHeight;
YPos := HeaderSize + 10;
for I := 1 to Zeilen do
begin
if Grid.RowCount >= I + (Seite - 1) * Zeilen then
begin
XPos := 0;
for J := 0 to Grid.ColCount - 1 do
begin
Printer.Canvas.TextOut(XPos, - YPos,
Grid.Cells[J, I + (Seite - 1) * Zeilen - 1]);
XPos := XPos + Grid.ColWidths[J] * 3;
end;
YPos := YPos + ZeilenSize;
end;
end;
//Seite hinzufugen
Inc(Seite);
if Seite <= AnzSeiten then Printer.NewPage;
end;
Printer.EndDoc;
end;

//Example
procedure TForm1.Button1Click(Sender: TObject);
begin
//Drucken im Querformat
PrintStringGrid(Grid, 'StringGrid Print Landscape', poLandscape);
//Drucken im Hochformat
PrintStringGrid(Grid, 'StringGrid Print Portrait', poPortrait);
end;


А вот компонент для печати сетки и его описание:
Вкладка Samples
Параметры:

* StringGrid - настраивается на определенный StringGrid.
* AFont - шрифт клеток которые не fixed.
* FixedColor - цвет фона у fixed клеток.
* LightCols и LightRows - это простые StringList'ы, в которых указываются номера столбцов (строк) которые должны быть подсвечены (цвет фона - FixedColor). Это бывает полезно в некоторых случаях.
* PrintStyle - имеет значения psPreview и psPrint, которые говорят сами за себя. Чтобы запустить печать (предв. Просмотр) вызывается метод Execute.
* Title - строка заголовка.
* TitleDate - отображать или нет дату в шапке отчета.
* TitleFont - шрифт заголовка.
* TitleLeft - отступ слева строки заголовка.
* TitleNumPage - отображать или нет номер страницы в шапке (там же где и строка Title) отчета.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 16:52
общий
Да, скроллинг отключился, но это опять немного не то. Когда тычем в ячейку, то всяческий скроллинг прекращается. А надо бы чтоб бокс всё-таки скроллился.

По поводу печати сетки, я целый день рыл в сети в поиске не очень замароченного решения. Но тщетно. Я использую Delphi 10 Lite SP2 и никаких систем отчётов в среде нет. Есть отдельная приблуда Rave Reports, но это мега замороченная вещь. Поставил, посмотрел и убил. Вобщем пока выведу через Excell, а если припечёт в будущем, то буду изучать генераторы отчётов.
давно
Профессионал
153662
1070
02.03.2009, 17:05
общий
А что мой компонент не подходит?
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 17:06
общий
В принципе, мне бы хватило такого решения, если в гриде отключить не скроллинг, а активацию следующей ячейки по скроллу (т.е. чтоб при прокрутке колесом активная ячейка не смещалась). Остальное решает вот это with ScrollBox1.VertScrollBar do Position:=Position+50;

По компоненту, там сказано что используется QReport. У меня его нет. Да бог с ней, с этой сеткой.
давно
Профессионал
153662
1070
02.03.2009, 17:21
общий
У меня тоже нет QReport, однако компонент установился и покрайней мере выводит предварительный просмотр, принтер у меня не установлен на этой машине.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 17:30
общий
Спасибо. Попробую. Но с этой прогой уже заканчиваю. Осталось мелкие пакости убрать, типа ненужного скроллинга. Вобщем-то это типа диплом, знакомая девочка попросила помочь. И мне как бы надо не очень сложно всё реализовать, а то подозрительно будет ...
давно
Профессионал
153662
1070
02.03.2009, 17:32
общий
Вот смотрите вставляю такой код
Код:
procedure TForm1.StringGrid1MouseWheelUp(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
with ScrollBox1.VertScrollBar do Position:=Position-50;
end;

procedure TForm1.StringGrid1MouseWheelDown(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
with ScrollBox1.VertScrollBar do Position:=Position+50;
end;
, опять изменяю модуль Grids.pas, там надо найти место с функциями function TCustomGrid.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; и function TCustomGrid.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; и переделываем так
Код:
//убираем скроллинг в сетке
function TCustomGrid.DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheelDown(Shift, MousePos);
if not Result then
begin
{if Row < RowCount - 1 then Row := Row + 1};
Result := True;
end;
end;

function TCustomGrid.DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheelUp(Shift, MousePos);
if not Result then
begin
{if Row > FixedRows then Row := Row - 1};
Result := True;
end;
end;
// конец уборки скроллинга
получаем наконец нужный результат!!!
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Профессионал
153662
1070
02.03.2009, 17:33
общий
Ну то что диплом я уже понял, у меня тоже в июне защита диплома, там прога с управлением внешних устройств через порт LPT.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 17:59
общий
Второй кусок кода никак не влияет на скроллинг в гриде. Просто за счёт первого куска бокс быстрее скроллится и не видно где там активная ячейка в гриде. Но по гриду она ползает, это факт. Если убрать первый кусок кода, то это будет более очевидно.
давно
Профессионал
153662
1070
02.03.2009, 18:05
общий
Внимательно посмотрите во втором куске кода есть скобки {} которые превращают сточки кода {if Row < RowCount - 1 then Row := Row + 1} в комментарий, это родные строчки движения выделенной ячейки.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 18:10
общий
Вобщем получилось сделать так, как надо. В процедуре StringGrid1MouseMove надо сделать ScrollBox1.SetFocus; Всё, ячейка не двигается. Но остался ещё один неприятный момент. Когда я тычу в первую ячейку, то бокс сам собой скроллится. Вот это бы ещё убрать, было бы вообще кайф.

Скобки я конечно увидел, но они никак не влияют. Я даже всё комментил, между begin и end, но ничего не меняется.
давно
Профессионал
153662
1070
02.03.2009, 18:20
общий
Ну незнаю я почему у Вас не работает вот мой проект, посмотрите. Кстате этот модуль Grids.pas нужно обязательно подключить к проекту через меню дэлфи проект\добавить в проект, комментирование всех строк между операторными скобками приводит к полному отключению скроллинга.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 18:34
общий
Хм, правда ваш вариант работает как надо. А почему мой не реагирует? Полную отключку скролла ведь съел, а пару функций не хочет.

Нажал на кнопку, а там УПС! Это и есть предпросмотр? Выглядит здорово. Только вертикальные линии светлые, а в остальном супер.
давно
Профессионал
153662
1070
02.03.2009, 18:37
общий
Да это предпросмотр, с настройками я не разбирался всё стоит по умолчанию.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 18:40
общий
Засада! Переименовал Grid.pas.old, а проект спокойно компиллится. Поиск по всему компу не дал результата. Как так?
давно
Профессионал
153662
1070
02.03.2009, 18:45
общий
А Вы видели если сделать ScrollBox1.SetFocus;, то не возможно вводить текст в сетку?
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

давно
Профессионал
153662
1070
02.03.2009, 18:48
общий
Насколько я знаю если дэлфи не находит в папки с проектом нужный модуль он его ищет по путям указанным в настройках или подключает стандартный модуль из своей библиотеки.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Неизвестный
02.03.2009, 19:10
общий
Да, SetFocus обламывает ввод. Вобщем исхитрился я с гридом. Я добавил в проект Grid.pas и после компила в папке появился Grid.dcu. Только после этого всё заработало. Но всё же ваш вариант отличается от моего, хотя я не могу найти различий в свойствах и коде. В вашем примере крутишь колесо и сразу скроллинг есть, а у меня надо сначала ткнуть в грид, только тогда скроллит. Причём, если у вас в нижнюю ячейку ткнуть, то она пододвигается, а у меня она так наполовину и висит за границей.
Неизвестный
02.03.2009, 19:16
общий
Нашёл. Если поставить фокус в Edit, то скроллится сразу. А вот половинчатые ячейки у нас обоих.
давно
Профессионал
153662
1070
02.03.2009, 19:36
общий
Как я понял чтобы последняя ячейка была полностью видна нужно сделать размер сетки чуть больше чем нужно для размещения всех ячеек. Да ещё у меня монитор 15 дюймов и разрешение 800*600 поэтому вашу форму видно не всю, а это может сыграть злую шутку на защите вдруг у них такое же разрешение.
Об авторе:
Мои программы со статусом freeware для Windows на моём сайте jonix.ucoz.ru

Форма ответа