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

Тема в разделе ".NET", создана пользователем advenedizo, 24 авг 2007.

  1. advenedizo

    advenedizo Гость

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

    И ещё, в данное время менее важный для меня, но, наверное, более сложный вопрос:
    как можно реализовать визуальное представление многостраничности?
     
  2. NikSoft

    NikSoft Гость

    Репутация:
    0
  3. mms

    mms Гость

    Репутация:
    0
    Элементарно ватсон :blink:

    Код (Text):
            [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
    }
    Использование:

    Код (Text):
                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);
    }
     
  4. advenedizo

    advenedizo Гость

    Репутация:
    0
    mms, спасибо большое.

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

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

    advenedizo Гость

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

    Как это сделать?
    На какое событие лучше всего?
     
  6. mms

    mms Гость

    Репутация:
    0
    <!--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]

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

    advenedizo Гость

    Репутация:
    0
    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)
     
  8. mms

    mms Гость

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

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

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

    Код (Text):
            [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;
    Использование:

    Код (Text):
                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 - текущая страница, дабл, потому что может быть отскролирована только часть страницы.
     
  9. advenedizo

    advenedizo Гость

    Репутация:
    0
    Спасибо
     
Загрузка...

Поделиться этой страницей