День добрый.
Стоит задача — написать hex differ на чистом winapi на C / C++ (т.е. графическое приложение наподобие опции "Сравнить по содержимому" в Total Commander'е для бинарных файлов). Один нюанс — программа должна работать с большими файлами (> 4 Гб). Выглядеть это должно примерно как во встроенной утилите Lister, встроенной в тот же Тотал (в режиме hex-отображения, конечно). Неважно какого объема файл открываешь — по вертикальному скроллу должна быть возможность попасть в любую часть файла.
Но пока более простая задача — сделать аналог Lister'а.
В качестве графического объекта был выбран RichEdit, т.к. нужно будет подсвечивать различия между файлами другим цветом.
Для подкачки кусков файла использую маппинг — функции CreateFileMapping / MapViewOfFile.
Проблема заключается в том, что я плохо представляю как реализовать незаметную подкачку другого куска (64 кб) и возможность по скроллу перейти в любое место файла.
Правильно ли я представляю, как это будет выглядеть:
1). При загрузке файла вычисляем его размер и выставляем диапазон у скролла RichEdit'а как размер файла / 8, т.к. по 8 байт будет в каждой строке.
2). Устанавливаем для RichEdit-объектов собственную процедуру обработки сообщений, где будем отслеживать скролл-сообщения и заменять подкачанный кусок по необходимости.
Есть сложности в определении этой необходимости. Например, если мы сейчас находимся по смещению FFFE, и спустимся ещё на пару байт вниз, то нужно подкачать следующий кусок файла, но при этом на экране должны остаться байты по смещениям FFF0, например с предыдущего куска.
Предполагаемое решение — памить кусками по 64 кб но по смещениям, не кратным 64 Кб.
Например: в анчале программы загружен кусок 0x0000 — 0xFFFF. Если мы переступаем смещение 0xF000, то грузим кусок 0xE000 — x1DFFF.
3). Маппим первые 64 кбайта файла и отображаем на RichEdit'е.
Второй вопрос — какие примерные действия над самим RichEdit'ом нужно совершать в обработчике скролл-сообщений? Я слабо представляю как связать скролл с диапазоном в весь файл и вывод куска в RichEdit, чтобы это правильно работало.
Здравствуйте, Cloudo, Вы писали:
C>Но пока более простая задача — сделать аналог Lister'а.
C>В качестве графического объекта был выбран RichEdit, т.к. нужно будет подсвечивать различия между файлами другим цветом. C>Для подкачки кусков файла использую маппинг — функции CreateFileMapping / MapViewOfFile.
C>Проблема заключается в том, что я плохо представляю как реализовать незаметную подкачку другого куска (64 кб) и возможность по скроллу перейти в любое место файла.
Насколько я понимаю, редактирование не предполагается, выделение строк/символов — тоже.
Тогда зачем нам кузнецRichEdit? Управление его скролбаром может обернуться кучей багов — все таки скроллбар учитывает текущий объем текста, загруженный в редактор.
ИМХО достаточно вызвать DrawText, чтобы нарисовать текст.
Насчет незаметной подкачки. Загрузить кусок выше и кусок ниже отображаемого. Если происходит скролирование, то при достижении граничного значения (скажем, когда до края блока остается меньше количество_строк_умещающихся_на экране/2) загружать очередную порцию данных.
А вообще, в целом по задаче...
Для просмотра файлов размером > 4 Гб управление через скроллбар не очень хорошая затея — получается слишком грубо, малейшее прикосновение и текущая позиция будет улетать пес знает куда. Нужно хорошенько обдумать способ навигации.
_____________________
С уважением,
Stanislav V. Zudin
Re: Просмотр больших файлов в RichEdit (аналог Lister в Tota
Спасибо за ответ.
Я сначала делал через ListBox и ручную отрисовку текста. У меня просто подгружался кусок в 64кб, и два листбокса заполнялись 8 (по ширине) на 32 (по высоте) байт. При этом для перехода к следующему 8х32 блоку были обычные кнопки вида "<<" ">>" (была также возможность вбить смещение вручную в edit). При этом новый 64кб кусок подгружался только в случае необходимости.
Но такой вариант не устроил по 3 причинам:
— обязательно нужны скроллы, причем управление должно осуществляться как с клавиатуры, так и мышой (т.е. стрелка вверх / вниз — на одну строку... PageUp / PageDown — по страницам).
— должна быть возможность изменять размер окна (я делал диалогом)
— при перерисовке изображение не должно мерцать (насколько я понимаю если использовать не ручную отрисовку, а предоставить ричедиту отрисовываться самому, такой проблемы не будет... либо же использовать двойную буферизацию, но листбокс всё равно не подходит, т.к. нужна навигация, которую пришлось бы писать самому).
Мне и посоветовали использовать RichEdit вместо ListBox'а — цвет в нем без проблем меняется.
Насчет скроллов — они обязательны, причем на весь большой файл (как в Lister'е в total commaner'е), там же как то удалось сделать скролл на весь файл ^^.
> Carc
Спасибо, посмотрю в сторону Windowless RichEdit.
Может есть какие-нибудь опен соурсные хекс редакторы на винапи, я бы подсмотрел как там это делается (я пока не нашёл) ^^
Re[3]: Просмотр больших файлов в RichEdit (аналог Lister в T
Здравствуйте, Cloudo, Вы писали:
>> Stanislav V. Zudin
>> Carc C>Спасибо, посмотрю в сторону Windowless RichEdit.
C>Может есть какие-нибудь опен соурсные хекс редакторы на винапи, я бы подсмотрел как там это делается (я пока не нашёл) ^^
На codeproject.com Дока от MS
а вот и та самая статья на кодепрожекте
По моему на том же самом codeproject.com попадались и какие-то примеры по HEX-редакторам.
Здравствуйте, rus blood, Вы писали:
RB>Здравствуйте, Carc, Вы писали:
C>>Дока от MS
RB>Оригинальный способ получения IID_ITextServices... RB>Он что, не фиксированный?
Хм, не понял!?! Я внимательно не анализировал эти COM-интерфейсы, но явно есть признаки что интерфейсы TOM это не сугубо и только RichEdit`овские приблуды. Вон к слову из той же студии уше нечто похожего торчат (не утверждаю, что это так, но весьма похоже на то)...
И потом, вызов CreateTextServices в случае с RichEdit все ж вернет имплементацию интерфейсов под конкретный RichEdit...
Здравствуйте, Cloudo, Вы писали:
C>Насчет скроллов — они обязательны, причем на весь большой файл (как в Lister'е в total commaner'е), там же как то удалось сделать скролл на весь файл ^^.
Здесь акцент не на возможности — сделать то несложно.
Допустим у тебя файл 4Гб, высота клиентской области — 900пкс (при разрешении экрана 1280х1024 вполне реальное значение). Легко подсчитать, что при перемещении скроллбара всего на 1пкс файл будет смещаться почти на 4,5 МБ
Сделать, лишь бы отвязались, можно. Но не думаю, что пользователи придут в восторг от этого.
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Просмотр больших файлов в RichEdit (аналог Lister в T
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Здравствуйте, Cloudo, Вы писали:
C>>Насчет скроллов — они обязательны, причем на весь большой файл (как в Lister'е в total commaner'е), там же как то удалось сделать скролл на весь файл ^^.
SVZ>Здесь акцент не на возможности — сделать то несложно. SVZ>Допустим у тебя файл 4Гб, высота клиентской области — 900пкс (при разрешении экрана 1280х1024 вполне реальное значение). Легко подсчитать, что при перемещении скроллбара всего на 1пкс файл будет смещаться почти на 4,5 МБ SVZ>Сделать, лишь бы отвязались, можно. Но не думаю, что пользователи придут в восторг от этого.
А в чем проблема?
Скролл вертикальный должен работать как обычно — чтобы все привычно. Раз 1px равен 15 метрам данных, значъ такъ! Просто скролл нужно кастомизовать — добавить дополнительный функционал. Чтобы можно было проскроллить на заданное число байтов.
Только разумнее всего делать, чтобы дополнительный функционал был видимым пользователю, чтобы сделан был как дополнительные элементы UI — еще кнопочки те же. Контекстное меню не лучший выход. Хотя в данном конкретном случае HEX-вьювера можно и через меню, т.к. видимо такими вьюверами будут пользоваться весьма подготовленные юзеры — они и так догадаются про меню. Только все равно через меню — это костыль сбоку, просто так легче сделать. А по уму, конечно же, а) кнопки — функционал должен быть видимым, б) кнопки — это один клик, меню уже два. Если нужно часто скроллить, а оно понадобится, лишний клик в варианте с меню будет доставать.
Здравствуйте, Cloudo, Вы писали:
C>День добрый. C>Стоит задача — написать hex differ на чистом winapi на C / C++ (т.е. графическое приложение наподобие опции "Сравнить по содержимому" в Total Commander'е для бинарных файлов). Один нюанс — программа должна работать с большими файлами (> 4 Гб). Выглядеть это должно примерно как во встроенной утилите Lister, встроенной в тот же Тотал (в режиме hex-отображения, конечно). Неважно какого объема файл открываешь — по вертикальному скроллу должна быть возможность попасть в любую часть файла.
RichEdit не самый лучший выбор. Посмотрите на Scintilla'у, может понравится.
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, Cloudo, Вы писали:
C>>День добрый. C>>Стоит задача — написать hex differ на чистом winapi на C / C++ (т.е. графическое приложение наподобие опции "Сравнить по содержимому" в Total Commander'е для бинарных файлов). Один нюанс — программа должна работать с большими файлами (> 4 Гб). Выглядеть это должно примерно как во встроенной утилите Lister, встроенной в тот же Тотал (в режиме hex-отображения, конечно). Неважно какого объема файл открываешь — по вертикальному скроллу должна быть возможность попасть в любую часть файла.
M>RichEdit не самый лучший выбор. Посмотрите на Scintilla'у, может понравится.
RichEdit нормальный выбор, если руки с головой местами не поменялись при рождении. Но повторю, не получится в RichEdit подгружать часть текста. Придется все 4 гига файла в него сразу и грузить, во всеми вытекающими последствиями по работе с памятью...
Такие вещи проще ручками приписать. Крутить капу RichEdit только из-за нужно вертикальных скролбаров — это из пушки по воробьям. RichEdit хорош когда пойдет большая пьянка необходимость в куче другого функционала: отображение рисунков, объектов OLE — вот тут он просто замечательная штука. Но у топик-стартера вроде как подобной задачи и рядом не стояло. Если нужны только скролбары, то ключевой Nichname на RSDN это kefir — у него есть продукт где аккурат все ручками с полного нуля сделано в смысле отображения текста, а не базируется хоть на каком-нибудь контроле Windows.
PS: был еще такой сайт MVPs — хоть убейте адреса не помню, только как выглядит. (а гугл ясное дело на такой смачный ключевик как MVP какой только ереси не выдает). Вот на том сайте в разделе С++ была серия уроков по созданию текстового редактора с нуля. Примечательно в тех уроках было то, что там собственно сам редактор тоже с нуля писался, с полного (никаких сабклассингов или суперклассингов Edit и иже с ними). Соответственно там очень подробно все расписывалось, от отображения текста в районах WM_PAINT, до обработки и увязки со скролбарами. Стоит посмотреть (сори, но действительно адреса не помню сайта, нечто вроде "100 lessons from MVPs").
Здравствуйте, Carc, Вы писали:
C>Скролл вертикальный должен работать как обычно — чтобы все привычно. Раз 1px равен 15 метрам данных, значъ такъ! Просто скролл нужно кастомизовать — добавить дополнительный функционал. Чтобы можно было проскроллить на заданное число байтов. C>Только разумнее всего делать, чтобы дополнительный функционал был видимым пользователю, чтобы сделан был как дополнительные элементы UI — еще кнопочки те же. Контекстное меню не лучший выход. Хотя в данном конкретном случае HEX-вьювера можно и через меню, т.к. видимо такими вьюверами будут пользоваться весьма подготовленные юзеры — они и так догадаются про меню. Только все равно через меню — это костыль сбоку, просто так легче сделать. А по уму, конечно же, а) кнопки — функционал должен быть видимым, б) кнопки — это один клик, меню уже два. Если нужно часто скроллить, а оно понадобится, лишний клик в варианте с меню будет доставать.
Кнопки обычно используют, чтобы шагать от одного изменения к другому.
Я бы сделал вместо скроллбара две шкалы — для грубой навигации и для точной. По грубой шкале перемещается "окно", размер которого можно менять. Точная шкала отображает положение внутри "окна". Т.е. что-то подобное видеоредакторам.
Только мы все равно не знаем, кто будет использовать этот редактор и для каких целей.
Может ТС нужно курсовик сдать, тогда все эти рассуждения — в пользу бедных
_____________________
С уважением,
Stanislav V. Zudin
Re[6]: Просмотр больших файлов в RichEdit (аналог Lister в T
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Здравствуйте, Carc, Вы писали:
C>>Скролл вертикальный должен работать как обычно — чтобы все привычно. Раз 1px равен 15 метрам данных, значъ такъ! Просто скролл нужно кастомизовать — добавить дополнительный функционал. Чтобы можно было проскроллить на заданное число байтов. C>>Только разумнее всего делать, чтобы дополнительный функционал был видимым пользователю, чтобы сделан был как дополнительные элементы UI — еще кнопочки те же. Контекстное меню не лучший выход. Хотя в данном конкретном случае HEX-вьювера можно и через меню, т.к. видимо такими вьюверами будут пользоваться весьма подготовленные юзеры — они и так догадаются про меню. Только все равно через меню — это костыль сбоку, просто так легче сделать. А по уму, конечно же, а) кнопки — функционал должен быть видимым, б) кнопки — это один клик, меню уже два. Если нужно часто скроллить, а оно понадобится, лишний клик в варианте с меню будет доставать.
SVZ>Кнопки обычно используют, чтобы шагать от одного изменения к другому. SVZ>Я бы сделал вместо скроллбара две шкалы — для грубой навигации и для точной. По грубой шкале перемещается "окно", размер которого можно менять. Точная шкала отображает положение внутри "окна". Т.е. что-то подобное видеоредакторам.
Любопытное решение! И наверное стоит разнести по разным сторонам (один слева, второй справа)!?! Чтобы не мучаться с точностью попадания в конкретный скролбар...
SVZ>Только мы все равно не знаем, кто будет использовать этот редактор и для каких целей. SVZ>Может ТС нужно курсовик сдать, тогда все эти рассуждения — в пользу бедных
И то верно...
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, Marty, Вы писали:
M>>Здравствуйте, Cloudo, Вы писали:
C>>>День добрый. C>>>Стоит задача — написать hex differ на чистом winapi на C / C++ (т.е. графическое приложение наподобие опции "Сравнить по содержимому" в Total Commander'е для бинарных файлов). Один нюанс — программа должна работать с большими файлами (> 4 Гб). Выглядеть это должно примерно как во встроенной утилите Lister, встроенной в тот же Тотал (в режиме hex-отображения, конечно). Неважно какого объема файл открываешь — по вертикальному скроллу должна быть возможность попасть в любую часть файла.
M>>RichEdit не самый лучший выбор. Посмотрите на Scintilla'у, может понравится. C>RichEdit нормальный выбор, если руки с головой местами не поменялись при рождении. Но повторю, не получится в RichEdit подгружать часть текста. Придется все 4 гига файла в него сразу и грузить, во всеми вытекающими последствиями по работе с памятью...
Все можно переписать заново. И получиться возможно лучше
Спасибо всем за ответы, с Ваших советов не стал делать через ричедит, а прикрутил кастомный вертикальный скролл к листбоксу.
Рассуждали про использование приложения... использовать его никто не будет, это тестовое задание, главное — показать работоспособность.
Получилось немного коряво, на мой взгляд, т.к. кошмарно долгая отрисовка, но вроде работоспособно (опыта то у меня маловато — первый "проект" на винапи).
Здравствуйте, Carc, Вы писали:
C>Хм, не понял!?! Я внимательно не анализировал эти COM-интерфейсы, но явно есть признаки что интерфейсы TOM это не сугубо и только RichEdit`овские приблуды. Вон к слову из той же студии уше нечто похожего торчат (не утверждаю, что это так, но весьма похоже на то)...
C>И потом, вызов CreateTextServices в случае с RichEdit все ж вернет имплементацию интерфейсов под конкретный RichEdit...
Вернет он IUnknown, а вот query-ить нужно будет интерфейс, чей IID импортируется из библиотеки через GetProcAddress.