Как считать страницы в контроле Richtextbox?

  • Автор темы advenedizo
  • Дата начала
A

advenedizo

#1
Здравствуйте.
Как мне посчитать количество страниц в контроле RichTextBox если учесть, что форматирование по ходу текста может быть различным, а текст может содержать картинки и другие объекты?

И ещё, в данное время менее важный для меня, но, наверное, более сложный вопрос:
как можно реализовать визуальное представление многостраничности?
 
M
#3
Элементарно ватсон :blink:

Код:
		[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);

[StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}

private enum ScrollBarDirection
{
SB_HORZ = 0,
SB_VERT = 1,
SB_CTL = 2,
SB_BOTH = 3
}

private enum ScrollInfoMask
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
}
Использование:

Код:
			SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf( si );
si.fMask = (int) ScrollInfoMask.SIF_ALL;
if (GetScrollInfo( richTextBox1.Handle, (int) ScrollBarDirection.SB_VERT, ref si ))
{

int pageCount = (int)Math.Ceiling((si.nMax - si.nMin) / (double)si.nPage);
}
 
A

advenedizo

#4
mms, спасибо большое.

А нет возможности получить размеры области RichTextBox'а, занятой текстом (или картинками)?

Допустим, такая задача: нужно определить количество страниц, которые бы занимал текст из выделенного диапазона. Но, это я к примеру.
 
A

advenedizo

#5
Кстати, если использовать предложенный mms вариант, то в случае, когда из текста, состоящего из нескольких страниц, вырезаешь большой кусок, сокращения количества страниц не происходит.
Я так понимаю, в этом случае необходимо посылать сообщение WM_VSCROLL?

Как это сделать?
На какое событие лучше всего?
 
M
#6
<!--QuoteBegin-advenedizo+24:08:2007, 14:07 -->
<span class="vbquote">(advenedizo @ 24:08:2007, 14:07 )</span><!--QuoteEBegin-->А нет возможности получить размеры области RichTextBox'а, занятой текстом (или картинками)?
[snapback]76290" rel="nofollow" target="_blank[/snapback]​
[/quote]

Не очень понимаю, что имеется ввиду.

<!--QuoteBegin-advenedizo+24:08:2007, 14:07 -->
<span class="vbquote">(advenedizo @ 24:08:2007, 14:07 )</span><!--QuoteEBegin-->Допустим, такая задача: нужно определить количество страниц, которые бы занимал текст из выделенного диапазона. Но, это я к примеру.
[snapback]76290" rel="nofollow" target="_blank[/snapback]​
[/quote]

Если шрифт одинаковый, то размеры выбранного текста (без картинок) можно получить при помощи MeasureString. По другому - фиг знает, мулировать поведение ричтекстбокса, либо попытаться получить нужную инфу через рефлекшен.

<!--QuoteBegin-advenedizo+24:08:2007, 14:23 -->
<span class="vbquote">(advenedizo @ 24:08:2007, 14:23 )</span><!--QuoteEBegin-->Кстати, если использовать предложенный mms вариант, то в случае, когда из текста, состоящего из нескольких страниц, вырезаешь большой кусок, сокращения количества страниц не происходит.
[snapback]76294" rel="nofollow" target="_blank[/snapback]​
[/quote]

Всё работает, после изменения текста нужно еще раз вызвать функцию считывающую параметры скроллера.
 
A

advenedizo

#7
mms спасибо огромное за ответы.


Почему MeasureString не подходит, понятно из постановки задачи
Насчет рефлекшн - что-то никак не пойму, каким образом она может здесь помочь.

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

<!--QuoteBegin-mms+24:08:2007, 13:53 -->
<span class="vbquote">(mms @ 24:08:2007, 13:53 )</span><!--QuoteEBegin-->Всё работает, после изменения текста нужно еще раз вызвать функцию считывающую параметры скроллера.
[snapback]76254" rel="nofollow" target="_blank[/snapback]​
[/quote]

Работает, но не всегда корректно.
К примеру, если вырезать весь текст, значение количества страниц не измениться.
(Вызов фунции по событию TextChanged)
 
M
#8
<!--QuoteBegin-advenedizo+28:08:2007, 07:58 -->
<span class="vbquote">(advenedizo @ 28:08:2007, 07:58 )</span><!--QuoteEBegin-->А замарачиваюсь я потому, что по ходу дела может всплыть куча дополнительных требований, с которыми предложенный вариант с GetScrollInfo может не справиться.
Например, теперь мне нужно определить номер текущей страницы.
Работает, но не всегда корректно.
К примеру, если вырезать весь текст, значение количества страниц не измениться.
(Вызов фунции по событию TextChanged)[/quote]

Чутка расширим функционал и вуаля:

Native декларации:

Код:
		[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);

[StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}

private enum ScrollBarDirection
{
SB_HORZ = 0,
SB_VERT = 1,
SB_CTL = 2,
SB_BOTH = 3
}

private enum ScrollInfoMask
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
}

[DllImport( "user32.dll", SetLastError=true, EntryPoint="GetScrollBarInfo")]
private static extern int GetScrollBarInfo(IntPtr hWnd, uint idObject, ref SCROLLBARINFO psbi);

[StructLayout(LayoutKind.Sequential)]
public struct SCROLLBARINFO
{
public int cbSize;
public Rectangle rcScrollBar;
public int dxyLineButton;
public int xyThumbTop;
public int xyThumbBottom;
public int reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public int[] rgstate;
}

private const uint OBJID_HSCROLL = 0xFFFFFFFA;
private const uint OBJID_VSCROLL = 0xFFFFFFFB;
private const uint OBJID_CLIENT = 0xFFFFFFFC;

private const uint STATE_SYSTEM_UNAVAILABLE = 0x00000001;
Использование:

Код:
			SCROLLBARINFO psbi = new SCROLLBARINFO();
psbi.cbSize = Marshal.SizeOf(psbi);

if (GetScrollBarInfo(richTextBox1.Handle, OBJID_VSCROLL, ref psbi) != 0)
{
int pageCount = 0;
double curPage = 0;
if (psbi.rgstate[0] == STATE_SYSTEM_UNAVAILABLE)
{
pageCount = 0;
curPage = 0;
}
else
{
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf( si );
si.fMask = (int) ScrollInfoMask.SIF_ALL;

if (GetScrollInfo( richTextBox1.Handle, (int) ScrollBarDirection.SB_VERT, ref si ))
{
pageCount = (int)Math.Ceiling((si.nMax - si.nMin) / (double)si.nPage);
curPage = si.nPos / (double)si.nPage + 1;
}
}
}
pageCount - количество страниц.
curPage - текущая страница, дабл, потому что может быть отскролирована только часть страницы.