| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Visual C++/MFC/WTL > CScrollView отцентровать и получить размер вида |
| Автор: Hrundel 1.9.2012, 00:31 | ||
| Всем привет. ( Earnest, тебе отдельный, персональный привет В моей программе вид меньше клиентской области, да еще и со скролом. Внутри вида должен отображаться документ с рабочей областью. По принципу Иллюстратора - то что лежит в рабочей области выводится на печать, то что за пределами - нет. Рабочая область лежит точно в центре вида. Необходимо разместить скролы таким образом, чтобы рабочая область отображалась ровно по середине вида. Арифметика там простая. point.x = размер_самого_вида / 2 - ширина_вида_в_клиентской_области; тоже самое для высоты Но самая засада заключается в том, как получить ширину_вида_в_клиентской_области (ну и высоту тоже конечно) Значит что-то типа GetViewportOrgEx(NULL, &renderSize); могло бы помочь. Всякие GetClientRect() возвращают совсем не то что требуется. Попытался забрать Rect из CScrollView::OnNcCalcSize(bCalcValidRects, lpncsp);
но возвращаемые значения при пересчете не соответствуют истине. Будте добры подскажите. ( На картинке: вид_в_клиентской_области выделен синим ) ![]() Вообще, могу сказать, что найти какую-либо правильную, подходящую функцию в MFC - дело не простое. Всем спасибо. |
| Автор: Hrundel 6.9.2012, 20:08 |
| Привет Earnest, объяснил, конечно, запутано. Чтобы распутать - нацарапал картинку ![]() С термином "рабочая зона" в экземпляре CView согласен. Пойдет. А вот "Рабочая область" это в свою очередь просто лист, как лист бумаги. В рабочую зону можно положить векторный объект, но тогда он, скажем, не будет печататься, а печататься будет только то, что лежит в "рабочей области". По крайней мере так задумано. Понятно, что если сказать ScrollToPosition( рабочая_зона / 2); то скрол крутит и устанавливает центр рабочей зоны в верхний левый угол CView Значит, надо теперь вернуться на какое-то количество пикселей назад, чтобы центр рабочей зоны оказался в центре экземпляра CView Значит, по логике вещей, это должна быть ширина_CView / 2. Тогда и получается: ScrollToPosition( рабочая_зона - ширина_CView ) / 2 Извиняюсь, первый раз немного намудрил. А вообще, пока использую только MM_TEXT, чтобы не путаться. Другие варианты подключу позже. Да и то - если возникнет необходимость. Уж, очень хочется, всегда под рукой размер экземпляра CView иметь. Но, пока так и не получилось. Точнее говоря - получилось, но такая кустарщина, даже показывать стыдно. Об элегантности решения - даже речи нет. А цель такая: (я уже показывал в другой теме). То есть, CView для отображения документа, а в оставшейся части клиентской области CFrameWnd кнопки и прочее. ![]() |
| Автор: Earnest 7.9.2012, 16:06 | ||
| Ладно, с терминами вроде разобрались. Но все равно непонятно, какую роль должны играть скроллы, что они прокручивают? Положение рабочей области в рабочей зоне? или во View? Еще непонятно, как соотносятся клиентская часть вида (далее просто вид) с рабочей зоной. Это одно и тоже или рабочая зона может быть больше? Если может быть больше (и должна прокручиваться во вью), то налицо необходимость в 2 органах управления: прокрутка рабочей зоны относительно вида и прокрутка рабочей области относительно зоны. И это независимые вещи, в один скрол их не впихнешь. А если зона всегда целиком влазит во вью, то давай лишний термин выбросим, и пусть будет просто вид (=клиентская часть вида).
Мне непонятно. Если таки скроллы прокручивают рабочую зону в виде, то зачем так извращаться. Если масштаб одинаковый, то диапазон скролла равен рабочая зона - вид (по каждому измерению). ScrollTo (0) - это позиция, когда 0 зоны совпадает с 0 вида. максимальная позиция скролла равна уже упомянутому (рабочая зона - вид) - это когда, допустим по горизонтали, правый конец рабочей зоны упирается в правую границу вида. Если разность (т.е. диапазон скролла) <= 0, то скроллы убираем или засериваем. При этом позиция области на зоне от этого никак не зависит, чтобы ее двигать, нужен еще один орган управления. Или я опять не так поняла? |
| Автор: Hrundel 7.9.2012, 22:06 | ||
| Привет Earnest, Во первых, спасибо, что пытаешься вникнуть в мой вопрос. Теперь постараюсь уточнить - вообще-то, все очень тривиально. Не знаю на сколько ты знакома с графическими программами на подобие Illustrator, CorelDraw, Freehand, но принцип у них один и тот же. Есть условный "лист", который логичнее всего назвать "зоной вывода" (скажем, на печать или в растровый файл). Объекты документа лежат в "рабочей зоне". Те, которые не попадают в зону вывода не подлежат печати или тому подобное.
Скролы прокручивают положение "рабочей зоны" во View Зона, конечно, больше чем View. Да, именно, так. Это я, конечно, тоже понимаю. И ты поняла все правильно. Моя проблема только в том, что если запрашиваю GetClientRect() во View, то по не совсем мне понятным причинам я получаю значения которые значительно меньше чем экземпляр View. Скажем, у меня окно 1680 шириной, экземпляр CView где-то 1648, а возвращаемое значение 1237 Как так может быть?! Я в недоумении. Может, я прописываю куда-то не туда. Посоветуй, откуда лучше всего запрашивать эти значения, чтобы не было неправильных результатов. ![]() |
| Автор: Earnest 10.9.2012, 08:52 |
| Насчет GetClientRect все очень странно. Эта железобетонная ф-я никогда не подводит. Единственно, хоть ты и не пишешь прямо, есть впечатление, что ты пытаешься "сэкономить", вызывая ее один раз где-то вначале. Если так, то зря. Опыт показывает, что вызывать ее надо в момент использования, и не париться с лишними вызовами. Если нет, то воспользуйся Спаем, он показывает клиентскую область в том числе. И еще, ты с NCCalсSize не химичил? Это единственное, что может "испортить" клиентскую область, насколько я знаю. Т.е. твоя задача состоит в том, чтобы разобраться с размерами клиентской области, а не найти ей замену в формуле. |