строка в ячейке stringgrid
StringGrid1->Cells[0][0] = "слово1 слово2 слово3"
Помогите пожалуйста вывести каждое слово с новой строки
StringGrid1->Cells[0][0] = "слово1 слово2 слово3"
Помогите пожалуйста вывести каждое слово с новой строки
Либо используем функцию типа split для разделения строки по символу "пробел", либо ручками в цикле определяем pos (strpos?) символа #32 и раздираем строку до следующего #32 или конца строки.
У меня ячейка формируется из строки, которая в свою очередь формируется из нескольких полей БД. В подсознании я понимаю, что надо разделить строку по какому нибудь делителю и вывести каждый кусок с сновой строки. Вообщем как это реализовать в StringGrid1DrawCell не знаю и в инете ничего нет. Сделал все и раскрасил как надо и фокус обвел как задумывал, а тут уперся. Прогу то почти доделал.
Понимающих прошу откликнутья!
У меня ячейка формируется из строки, которая в свою очередь формируется из нескольких полей БД. В подсознании я понимаю, что надо разделить строку по какому нибудь делителю и вывести каждый кусок с сновой строки. Вообщем как это реализовать в StringGrid1DrawCell не знаю и в инете ничего нет. Сделал все и раскрасил как надо и фокус обвел как задумывал, а тут уперся. Прогу то почти доделал.
Понимающих прошу откликнутья!
Года два назад пробовал сделать тоже самое, не нашел штатного решения.
Только вручную определять какой высоты будет текст, если ограничить его по ширине, ресайзить высоту строки и вручную рисовать его...
Кстати, какая версия билдера? Возможно в последней есть такой функционал.
Либо можно попробовать другие сторонние гриды... Стандартный в Builder 6 через чур примитивен...
UPD: так как вам нужно просто каждую строку вывести с новой строки (без переноса строк, если она не влезает) - то просто изменить высоту строки таблицы и ручками рисовать текст.
Я уже столько сделал и мне осталось только вот этот функционал реализовать. Нашел только в дельфи, может кто поможет перевести в ВСВ
Многострочные ячейки в StringGrid.
Сперва необходимо установить свойство DefaultDrawing в False
procedure TForm1.StringGrid1DrawCell(Sender: TObject;
Col, Row: Longint;
Rect: TRect;
State: TGridDrawState);
var
Line1: string;
Line2: string;
ptr: integer;
padding: integer;
hGrid: TStringGrid;
begin
hGrid:= (Sender as TStringGrid);
ptr := Pos(';', hGrid.Cells[Col, Row]);
if ptr > 0 then
begin
Line1 := Copy(hGrid.Cells[Col, Row], 1, ptr - 1);
Line2 := Copy(hGrid.Cells[Col, Row], ptr + 1,
Length(hGrid1.Cells[Col,Row]) - ptr);
end
else Line1 := hGrid.Cells[Col, Row];
hGrid.Canvas.FillRect(Rect);
hGrid.Canvas.TextOut(Rect.Left, Rect.Top + 2, Line1);
if ptr > 0 then
hGrid.Canvas.TextOut(Rect.Left, Rect.Top -
hGrid.Canvas.Font.Height + 3, Line2);
end;
К рисованию имеет отношение этот кусок:
hGrid->Canvas->FillRect(Rect);
hGrid->Canvas->TextOut(Rect->Left, Rect->Top + 2, Line1);
hGrid->Canvas->TextOut(Rect->Left, Rect->Top + hGrid->Canvas->Font->Height + 3, Line2);
Кстати в примере не раскрыта тема высоты строки.
Попробовал этот пример в разных настройках.
Байда какая-то - первая строка отрисовывается нормально,
вторая то появляется то исчезает
TStringGrid *hGrid = (TStringGrid*)Sender;
char *Line1 = new char[100];
Line1="11111111! 111111111111111111111111! 111111111! 111111111!";
hGrid->Canvas->FillRect(Rect);
DrawText(hGrid->Canvas->Handle,(Line1), strlen(Line1), &Rect,DT_WORDBREAK);
Работает без глюков но не переносит по разделителю.
Все равно что-нибудь вымучаю
TStringGrid *hGrid = (TStringGrid*)Sender;
char *Line1 = new char[100];
Line1="test\r\ntest\r\ntest\r\ntest\r\ntest\r\n";
hGrid->Canvas->FillRect(Rect);
DrawText(hGrid->Canvas->Handle,(Line1), strlen(Line1), &Rect,DT_WORDBREAK);
Спасибо кто поддержал!
char *Line1 = new char[100];
Line1="test\r\ntest\r\ntest\r\ntest\r\ntest\r\n";
Решив одну проблему, автор создал себе другую: утечка памяти детектед.
Предложу вариант, как можно сделать правильно (чтобы утечки памяти не было):
strcpy(Line1, "test\r\ntest\r\ntest\r\ntest\r\ntest\r\n");
strcpy(Line1, "test\r\ntest\r\ntest\r\ntest\r\ntest\r\n");
и что же здесь "правильного"?
Нет, от освобождения памяти не избавляет. Но, как я понимаю, проблема утечки памяти здесь не в том, что автор выделил память с помощью new, а потом не удалил с помощью delete[] (тем более что автор привел не весь код программы, и мог сделать удаление позже). Проблема в том, что после выполнения присваивания
указатель Line1 указывает уже не на ту область памяти, которая была до этого выделена с помощью new, а на начало константной строки "test\r\ntest\r\ntest\r\ntest\r\ntest\r\n", содержащейся в коде программы (или в области памяти, в которой хранятся констатные данные программы). И выделенная с помощью new область памяти теперь уже никак не связана с указателем. И освободить ее уже в принципе нельзя, даже если потом выполнить delete[]. Т.е. память выделена, а освободить ее (или как-то использовать) - нельзя.
Небольшой тест иллюстрирующий вышесказанное:
#include <cstring>
using namespace std;
void testNewDelete()
{
char *Line1 = new char[10000000];
Line1 = "test\r\ntest\r\ntest\r\ntest\r\ntest\r\n";
// а если заменить на
// strcpy(Line1, "test\r\ntest\r\ntest\r\ntest\r\ntest\r\n");
// то утечки нет
delete[] Line1;
}
int main()
{
unsigned int i = 0;
while(i++ < 1000)
testNewDelete();
}
При его выполнении, программа вылетает из-за нехватки памяти. Если произвести описанную в коде замену - то программа отрабатывает нормально.
Ну скажем так, ИМХО этот вариант более правильный, чем у автора, в том плане что в нем нет проблем которые есть в том варианте, который был у автора (хотя может быть конечно, что есть другие промахи):
1. Нет описанной утечки памяти, и есть возможность освободить память с помощью delete.
2. Указатель остается указателем на область памяти, содержимое которой можно менять, и по этому указателю можно потом записывать новое содержимое - перезаписывать строку (например, использовать указатель для передачи в какую-нибудь функцию в качестве аргумента, которая записывает по переданному указателю строку - результат своего выполнения). Чего нельзя сделать (будет какой-нибудь access violation) после присваивания указателю начала константной строки.
Но если автору перезаписывать строку не требуется (требуется передать строку в функцию один раз и все) - то тогда можно присвоить указатель константной строке (но тогда без использования new):
hGrid->Canvas->FillRect(Rect);
DrawText(hGrid->Canvas->Handle,(Line1), strlen(Line1), &Rect,DT_WORDBREAK);
void __fastcall TFrmMain::FormActivate(TObject *Sender)
{
.....
// Заполняем Стринггрид
for(int i = 0; i < StringGrid1->RowCount; i++) {
for(int j = 0; j < StringGrid1->ColCount; j++) {
if(quancells == Queue->RecordCount) break;
AnsiString text;
text = Queue->FieldByName("condition")->AsString;
text = text + " ";
text = text + Queue->FieldByName("number")->AsString;
text = text + "\nпозывной - ";
text = text + Queue->FieldByName("sign")->AsString;
text = text + "\nрайон дис. - ";
text = text + Queue->FieldByName("region")->AsString;
text = text + "\nвыполн. заявок - ";
text = text + Queue->FieldByName("quantity")->AsString;
text = text + "\nн.с. - ";
text = text + Queue->FieldByName("inittime")->AsString;
StringGrid1->Cells[j] = text;
Queue->Next(); quancells++;
}
}
....
}
//-----------------------------------------------------------
void __fastcall TFrmMain::StringGrid1DrawCell(TObject *Sender, int ACol,
int ARow, TRect &Rect, TGridDrawState State)
{
// Здесь прорисовка текста
DrawText(StringGrid1->Canvas->Handle,
StringGrid1->Cells[ACol][ARow].c_str(), strlen(StringGrid1->Cells[ACol][ARow].c_str()),
&Rect, DT_WORDBREAK); // Выводим текст в ячейку используя ф-цию WinAPI
}