Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вывод текста, проблемы с форматированием 
:(
    Опции темы
CrazyPerson
Дата 20.12.2008, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.4.2007
Где: Санкт-Петербург

Репутация: нет
Всего: нет



В процессе написания программы понадобилось выводить текст на экран в определенном формате:

name1
  description11
    example11
    example12
  description2
    example21
    example22
name2
...


Сначала пытался использовать для этой цели RichEdit, но не понял как сделать отступы только для части текста.
TreeView тоже не помог, так как описания и примеры могут быть большой длинны, и содержать несколько строчек. А в TreeView, как я понял, один элемент занимает ровно одну строчку.

Никто не знает что было бы удобно использовать для такого форматирования текста?
PM MAIL ICQ   Вверх
GremlinProg
Дата 20.12.2008, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



вот общий, нерекурсивный псевдо-код для вывода динамического дерева
Код

std::vector<Node>stack;

stack.push_back(root_node);

while(!stack.empty()){

  // извлекаем узел из стека
  node = stack.back();

  // определяем число табуляторов для текущего узла
  for( tabs_count = 0 , parent = get_parent(node) ; parent ; parent = get_parent(parent) , ++tabs_count );

  // выводим tabs_count табуляторов в окно
  print_tabs( tabs_count );
  // выводим, собственно, сам текст, связанный с узлом node
  print_content( node );
  // продолжаем итерации для дочерних узлов
  for( child = get_last( get_first_child( node ) ) ; child ; child = get_prev(child) ){
    stack.push_back(child);
  }

}

вместо табуляторов можно использовать любое обозначение отступа: хоть пробелы, хоть отступ на n пикселей при выводе содержимого узла в окно
если содержимое каждого узла многострочное, значит этот отступ нужно делать перед каждой строкой текущего узла

для реализации алгоритма требуется ввести все задействованные методы:
get_parent - возвращает родительский узел, или 0, если такового не существует
get_first_child - возвращает первый дочерний подузел для заданного родительского узла, или 0, если такового не существует
get_last - возвращает самый последний братский подузел, который находится на том же уровне иерархии дерева, у одного родителя, или 0, если такового не существует
get_prev - возвращает предыдущий братский подузел, или 0, если такового не существует
print_tabs - печатает заданное число табуляторов с текущей позиции
print_content  - печатает содержимое узла с текущей позиции
последние 2 метода - на выбор, если многострочный вывод, значит их нужно объединить в один, которому  в параметрах, помимо самого узла, передается tabs_count

если все дочерние узлы находятся в массиве, то можно еще проще сделать продолжение итераций, т.е. без get_first_child, get_last, get_prev:
Код

  // продолжаем итерации для дочерних узлов
  for( i = node.children.size() ; i-- ; ){
    stack.push_back( node.children[i] );
  }

, где node.children - обращение к массиву дочерних узлов, родителя node

Node - псевдо-обозначение идентификатора узла
если все элементы дерева расположены в массиве, значит в качестве Node можно использовать индекс узла в этом массиве
если под каждый элемент дерева распределяется отдельный блок памяти, значит Node - указатель на узел

CrazyPerson, если не понял как приспособить этот алгоритм, тогда выкладывай структуру своей иерархии, подскажем.

Это сообщение отредактировал(а) GremlinProg - 20.12.2008, 16:59


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
CrazyPerson
Дата 20.12.2008, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.4.2007
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Ого, спасибо за столь развернутый ответ! Но к сожалению это несколько не то. Обход самого дерева я то быстро написал.
А проблема у меня возникла со следующей частью кода:

Код

// выводим tabs_count табуляторов в окно
  print_tabs( tabs_count );
  // выводим, собственно, сам текст, связанный с узлом node
  print_content( node );
  


Ну вот в treeView все выводить в одну строку, и соответственно это никак не подходит для многострочного вывода.

А в RichEdit я не понял как выводить "параграф текста" с заданным отступом. Ну как я понял там можно разбивать текст на параграфы и выводить их с различным форматированием. Но вот сделать этого у меня не получилось...
PM MAIL ICQ   Вверх
GremlinProg
Дата 20.12.2008, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



treeView тоже может выводить многострочные узлы:
Цитата(MSDN TVITEMEX Structure)

typedef struct tagTVITEMEX {
    UINT mask;
    HTREEITEM hItem;
    UINT state;
    UINT stateMask;
    LPTSTR pszText;
    int cchTextMax;
    int iImage;
    int iSelectedImage;
    int cChildren;
    LPARAM lParam;
    int iIntegral;
} TVITEMEX, *LPTVITEMEX;

Цитата(MSDN TVITEMEX Structure)

iIntegral
Height of the item. This height is in increments of the standard item height (see TVM_SETITEMHEIGHT). By default, each item gets one increment of item height. Setting this member to 2 will give the item twice the standard height; setting this member to 3 will give the item three times the standard height; and so on. The tree-view control does not draw in this extra area. This extra space can be used by the application for drawing when using custom draw. 

а если использовать RichEdit, то параграф в принципе избыточен, есть более простой способ: писать перед каждой строкой табуляторы в числе tabs_count, размер которых впоследствии можно настроить через EM_SETTABSTOPS
Цитата(MSDN EM_SETTABSTOPS)

wParam
Specifies the number of tab stops contained in the array. If this parameter is zero, the lParam parameter is ignored and default tab stops are set at every 32 dialog template units. If this parameter is 1, tab stops are set at every n dialog template units, where n is the distance pointed to by the lParam parameter. If this parameter is greater than 1, lParam is a pointer to an array of tab stops. 
lParam
Pointer to an array of unsigned integers specifying the tab stops, in dialog template units. If the wParam parameter is 1, this parameter is a pointer to an unsigned integer containing the distance between all tab stops, in dialog template units. 
Windows 95/98/Me: The buffer pointed to by lParam must reside in writable memory, even though the message does not modify the array. 



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
CrazyPerson
Дата 20.12.2008, 23:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.4.2007
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Ага, спасибо. msdn'ом я еще не научился нормально пользоваться, но я стараюсь.
Но и тот и тот способ подразумевает что мне придется вручную разбивать текст на строки, и никакого готового word wrap'a не будет. Или я не правильно понял что в richedit придется добавлять ручками табы перед каждой строчкой?
PM MAIL ICQ   Вверх
GremlinProg
Дата 21.12.2008, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(CrazyPerson @  21.12.2008,  01:27 Найти цитируемый пост)
Но и тот и тот способ подразумевает что мне придется вручную разбивать текст на строки, и никакого готового word wrap'a не будет

да, про word wrap пока ни слова не было, я так понимал, что тебе нужно вывести дерево  с фиксированным числом строк в узлах.
word wrap в корне меняет дело
тогда нужно вводить параграфы
Цитата(MSDN EM_SETPARAFORMAT)

wParam
This parameter is not used; it must be zero. 
lParam
Pointer to a PARAFORMAT structure specifying the new paragraph formatting attributes. Only the attributes specified by the dwMask member are changed. 
Microsoft® Rich Edit 2.0 and later: This parameter can be a pointer to a PARAFORMAT2 structure, which is an extension of the PARAFORMAT structure. Before sending the EM_SETPARAFORMAT message, set the structure's cbSize member to indicate the version of the structure.

Цитата(MSDN PARAFORMAT)

typedef struct _paraformat {
    UINT cbSize;
    DWORD dwMask;
    WORD wNumbering;
    WORD wReserved;
    LONG dxStartIndent;
    LONG dxRightIndent;
    LONG dxOffset;
    WORD wAlignment;
    SHORT cTabCount;
    LONG rgxTabs[MAX_TAB_STOPS];
} PARAFORMAT;

в PARAFORMAT ключевые поля: dwMask и dxStartIndent
[quote MSDN dwMask]
dwMask
Members containing valid information or attributes to set. This parameter can be none or a combination of the following values. If both PFM_STARTINDENT and PFM_OFFSETINDENT are specified, PFM_STARTINDENT takes precedence. 
PFM_ALIGNMENT
The wAlignment member is valid.
PFM_NUMBERING
The wNumbering member is valid.
PFM_OFFSET
The dxOffset member is valid.
PFM_OFFSETINDENT
The dxStartIndent member is valid and specifies a relative value.
PFM_RIGHTINDENT
The dxRightIndent member is valid.
PFM_RTLPARA
Rich Edit 2.0: The wEffects member is valid
PFM_STARTINDENT
The dxStartIndent member is valid.
PFM_TABSTOPS
The cTabStobs and rgxTabStops members are valid.
[/quote]
[quote=MSDN dxStartIndent]
dxStartIndent
Indentation of the first line in the paragraph, in twips. If the paragraph formatting is being set and PFM_OFFSETINDENT is specified, this member is treated as a relative value that is added to the starting indentation of each affected paragraph. 
[/quote]
для установки параграфа нужно:
1. выделитть текст, к которому применяется параграф (если нужно, можно скрыть выделение от пользователя EM_HIDESELECTION)
2. выставить поля PARAFORMAT::cbSize, PARAFORMAT::dwMask и PARAFORMAT::dxStartIndent
3. Вызвать EM_SETPARAFORMAT
после этого даже word wrap не будет переводить строки левее, чем PARAFORMAT::dxStartIndent
PARAFORMAT::dxStartIndent - относительное смещение содержимого параграфа, относительно родительского параграфа

Это сообщение отредактировал(а) GremlinProg - 21.12.2008, 18:14


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
CrazyPerson
Дата 21.12.2008, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 14
Регистрация: 26.4.2007
Где: Санкт-Петербург

Репутация: нет
Всего: нет



О! То что нужно! 
Еще раз спасибо. Вот про EM_SETPARAFORMAT я нашел, а про то, что еще выделять текст надо - не нашел..
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0799 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.