Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.186.6] |
|
Сообщ.
#1
,
|
|
|
В очередной раз написал класс, который двигает и растягивает контролы при изменении размера диалога.
Естественно, захотелось сделать так, чтобы диалог нельзя было сделать меньше определенного размера. Тупо вбивать не хочется, более привлекает, просто чтобы размер диалога не делался менее исходного. Куски кода, имеющие отношение к делу: *.h : class CBlackListManagerDlg : public CDialog { // Construction public: .... ControlMover cm; .... *.cpp: BOOL CBlackListManagerDlg::OnInitDialog() { CDialog::OnInitDialog(); cm.Initialise(this); return TRUE; // return TRUE unless you set the focus to a control } void CBlackListManagerDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { // TODO: Add your message handler code here and/or call default if(cm.m_lWidth > 100){ lpMMI->ptMinTrackSize = CPoint(cm.m_lWidth, 300); } CDialog::OnGetMinMaxInfo(lpMMI); } Ну и в самом мувере: class ControlMover{ public: LONG m_lWidth; LONG m_lHeight; void Initialise(CWnd* pParent); .... void ControlMover::Initialise(CWnd* pParent){ m_pParent = pParent; if (!m_pParent) return; CRect rcDialog; m_pParent->GetClientRect(rcDialog); m_lWidth = rcDialog.Width(); m_lHeight = rcDialog.Height(); ... Все прозрачно, ясно, но... Под ХП все работает ожидаемым образом: Прикреплённая картинка
А под 7й окно распидорашивает в неимоверную ширину: Прикреплённая картинка
Сам я руками размер окна не изменяю, так что единственный вариант - что на этапе OnInitDialog() в m_lWidth заносится какой-то мусор. Спрашивается - почему? Что эдакого семерка делает более чрезпопно, чем ХП? Добавлено Поставил костыль: void CBlackListManagerDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { if(cm.m_lWidth > 100 && cm.m_lWidth < 2000){ lpMMI->ptMinTrackSize = CPoint(cm.m_lWidth, 300); } CDialog::OnGetMinMaxInfo(lpMMI); } и теперь тихо офигеваю, т.к. это подействовало. 7ка что, два раза инит диалог вызывает? |
Сообщ.
#2
,
|
|
|
Из того что ты привел ничего не понятно. Код простой все на виду, един. что вижу так это что булет если не указать парент? вроде как члены не будут инициализированы
|
Сообщ.
#3
,
|
|
|
Все, решен вопрос, семерка OnGetMinMaxInfo первый раз вызывает до OnInitDialog. Поставил защиту в виде проверки, проинициализировано ли все в классе ControlMover. Заодно пофиксил еще кое-то и попрятал что не должно торчать наружу в защищенные методы. Не идеально... Но теперь пашет, как ожидалось.
Добавлено Цитата Cfon @ Из того что ты привел ничего не понятно. Код простой все на виду, един. что вижу так это что будет если не указать парент? вроде как члены не будут инициализированы Ну если на входе передать NULL то конечно ничего вообще работать не будет, ну и печали особой в том не будет, прога то основную функцию выполнять сможет, просто свистелко-перделка "автоподгонка под размер" не будет работать. Гораздо веселее когда в таком случае ставят ассерт, и все к чертям вылетает, и попробуй без дебагера найти концы |
Сообщ.
#4
,
|
|
|
Сообщ.
#5
,
|
|
|
красиво
я если честно вообще стараюсь не тратить время на интерфейс, ИМХО главное назначение программы сначала решаю чтобы программа выполняла свою цель, ну а потом занимаюсь интерфейсом. |
Сообщ.
#6
,
|
|
|
Cfon, на самом деле тут оно нахрен не надо, изначально в другой проге делал, которая для просмотра и редактирования картинок, просто захотел инкапсулировать и выдернуть так чтобы легким движением руки в любой проект потом кидать. Вот теперь сижу и смотрю как допилить, чтобы оба списка масштабировались, и при этом не усложнить все до маразма. В смысле чтобы при растягивании оба списка оставались примерно одной ширины.
|
Сообщ.
#7
,
|
|
|
Цитата barazuk @ Cfon, на самом деле тут оно нахрен не надо, изначально в другой проге делал, которая для просмотра и редактирования картинок, просто захотел инкапсулировать и выдернуть так чтобы легким движением руки в любой проект потом кидать. на самом деле все уже придумано и выложено в инет например вот: https://www.codeproject.com/Articles/116/Layout-Manager-for-Dialogs-Formviews-DialogBars-an |
Сообщ.
#8
,
|
|
|
Цитата Cfon @ на самом деле все уже придумано и выложено в инет Ай вещь на самом деле простецкая настолько, что проще самому с нуля сделать, чем если что разбираться в чужом говнокоде чтобы что-то прикрутить Добавлено Цитата Cfon @ например вот: О боже какой адский трындец |
Сообщ.
#9
,
|
|
|
ну хз смотри сам, а я всегда сначала гуглю особенно на codeproject или sourceforge.net
просто мне так удобнее |
Сообщ.
#10
,
|
|
|
Цитата Cfon @ ну хз смотри сам, а я всегда сначала гуглю особенно на codeproject или sourceforge.net Я обычно только подглядываю основную идею... В 99% случаев допиливание и вылов багов в чужом мегакоде на все случаи жизни намного дольше, чем сделать ту маленькую штучку, которую собственно нужно сделать из того парового велосипеда на ядерной тяге, который обычно пафосно городят там где достаточно 20 строк кода |
Сообщ.
#11
,
|
|
|
вот пример MFC диалога c Layout (упростил макс ).
вся работа происходит в OnInitDialog. Все что нам нужно добавить в проект файлы ETSLayout.cpp(.h) и поменять базовый класс диалога c CDialogEx на ETSLayoutDialog. VS 2010. Прикреплённый файлTestLayout.zip (95,2 Кбайт, скачиваний: 95) |
Сообщ.
#12
,
|
|
|
Цитата Cfon @ на самом деле все уже придумано и выложено в инет например вот: https://www.codeproject.com/Articles/116/Layout-Manager-for-Dialogs-Formviews-DialogBars-an Получается так, что не всё. Чтобы как-то ограничить размеры окна достаточно обработать сообщение WM_SIZE. Полученные в сообщении размеры сравниваем с ограничениями, и если надо используем "SetWindowPos". Разве этого не достаточно ? |
Сообщ.
#13
,
|
|
|
Цитата ЫукпШ @ "SetWindowPos". И получаем ill behaved application. Для этого обрабатывается OnGetMinMaxInfo. |
Сообщ.
#14
,
|
|
|
Цитата ЫукпШ @ Чтобы как-то ограничить размеры окна достаточно обработать сообщение WM_SIZE. Вообще, для того, чтоб в диалоге изменять позицию и размер контролов нужно обрабатывать сообщение WM_WINDOWPOSCHANGING |
Сообщ.
#15
,
|
|
|
Цитата barazuk @ Цитата ЫукпШ @ "SetWindowPos". И получаем ill behaved application. С чего это вдруг ? Прежде чем советовать, я сам попробовал. Можешь не сомневаться - это устойчиво работает. Добавлено Цитата Олег М @ Цитата ЫукпШ @ Чтобы как-то ограничить размеры окна достаточно обработать сообщение WM_SIZE. Вообще, для того, чтоб в диалоге изменять позицию и размер контролов нужно обрабатывать сообщение WM_WINDOWPOSCHANGING Вопрос был о том, "как ограничить размер диалога ?" При изменении размеров окна в оконную процедуру посылается сообщение WM_SIZE с установленными размерами. По этому событию можно сравнить установленные размеры с ограничениями и, если надо, установить допустимые размеры окна. --- Чтобы в диалоге менять что-то, можно использовать любые нужные функции WINAPI. Функции создания "диалога" это оболочка вокруг CreateWindow(Ex). С интерпретатором описания диалогового окна, представленного на языке ресурсов. Это обычные окна (которые все функционально - диалоги), и всё содержимое "диалогов" можно делать исключительно "вручную". Те посредством непосредственного вызова CreateWindow для всех окошек-контролов всех нужных классов. |
Сообщ.
#16
,
|
|
|
да да живите в своём мире
все уже давно придумано, layout рулит |
Сообщ.
#17
,
|
|
|
Цитата ЫукпШ @ Вопрос был о том, "как ограничить размер диалога ?" При изменении размеров окна в оконную процедуру посылается сообщение WM_SIZE с установленными размерами. По этому событию можно сравнить установленные размеры с ограничениями и, если надо, установить допустимые размеры окна Как раз по этому событию ты ничего особо сделать с окном не можешь, Либо это будет работать дико коряво. WM_WINDOWPOSCHANGING вызывается до изменения и в нем ты можешь вернуть новые размеры окна, т.е. ограничить размер диалога, а заодно изменить контролы. Больше никаких сообщений обрабатывать не нужно, В том числе getminmax |
Сообщ.
#18
,
|
|
|
Цитата ЫукпШ @ посылается сообщение WM_SIZE с установленными размерами. По этому событию можно сравнить установленные размеры с ограничениями и, если надо, установить допустимые размеры окна. А что, после сет виндов поз снова WM_SIZE не вызовется? Не совсем хорошая практика, как по мне. |
Сообщ.
#19
,
|
|
|
Цитата barazuk @ Цитата ЫукпШ @ посылается сообщение WM_SIZE с установленными размерами. По этому событию можно сравнить установленные размеры с ограничениями и, если надо, установить допустимые размеры окна. А что, после сет виндов поз снова WM_SIZE не вызовется? Обязательно вызовется - а как же иначе. Но новые правильно установленные размеры окна окажутся в допустимых пределах по их размерам. Это значит, что "SetWindowPos" вызвана не будет, ибо незачем. Никакого "автогенератора" не получится. Добавлено Олег М, WM_WINDOWPOSCHANGING это как раз результат работы SetWindowPos. ссылка Из обработчика этого сообщения я бы эту функцию вызвать не рискнул. |
Сообщ.
#20
,
|
|
|
Цитата ЫукпШ @ Олег М, WM_WINDOWPOSCHANGING это как раз результат работы SetWindowPos. ссылка Из обработчика этого сообщения я бы эту функцию вызвать не рискнул Кто ж ее там вызывает? Там в параметрах сообщения можно вернуть новый размер окна |
Сообщ.
#21
,
|
|
|
Цитата Олег М @ Там в параметрах сообщения можно вернуть новый размер окна Да вернуть-то можно, но не всегда. WM_WINDOWPOSCHANGING - это прямое следствие SetWindowPos. Но эта функция используется не только для изменения размеров окна. Значит, надо ещё правильно отфильтровать флаги. Возникает также вопрос - а что будет, если размер окна поменять другой функцией WINAPI ? (Напрмер, MoveWindow) --- Алгоритм процедуры в WM_SIZE проще, всё действует по-факту попытки изменить именно размеры окна неважно чем, неважно как. |
Сообщ.
#22
,
|
|
|
Цитата ЫукпШ @ Да вернуть-то можно, но не всегда А когда нельзя? Добавлено Цитата ЫукпШ @ Возникает также вопрос - а что будет, если размер окна поменять другой функцией WINAPI ? (Напрмер, MoveWindow) Будет отправлено это сообщение. Оно всегда отправляется, при изменении позиции или размера окна. |
Сообщ.
#23
,
|
|
|
Цитата Олег М @ Цитата ЫукпШ @ Да вернуть-то можно, но не всегда А когда нельзя? Эта функция используется не только для изменения размеров окна. И вместо размеров может быть любой мусор. --- А что будет, если в новых версиях Виндус будут добавлены новые флаги ? Может быть алгоритм снова придётся переделывать.. Нет, не уговоришь. Работать по-факту происходящего всегда надёжнее. |
Сообщ.
#24
,
|
|
|
Цитата ЫукпШ @ Нет, не уговоришь. Работать по-факту происходящего всегда надёжнее. Кто ж тебя уговаривает? Тебе рассказывают как надо делать правильно. Не доходит, ну и ладно. |
Сообщ.
#25
,
|
|
|
Цитата Олег М @ Цитата ЫукпШ @ Нет, не уговоришь. Работать по-факту происходящего всегда надёжнее. Кто ж тебя уговаривает? Тебе рассказывают как надо делать правильно. Не доходит, ну и ладно. Ты даже не знал, что в указанном тобой сообщении размеры окна пересылаются не всегда. И при этом рассказываешь, "как надо правильно". |
Сообщ.
#26
,
|
|
|
Цитата ЫукпШ @ И при этом рассказываешь, "как надо правильно". Идеологически правильно обрабатывать OnGetMinMaxInfo. Он вызывается ПЕРЕД любым изменением размера, и специально для этого предназначен А изменение размера из WM_SIZE... Это костыль |
Сообщ.
#27
,
|
|
|
Цитата ЫукпШ @ Ты даже не знал, что в указанном тобой сообщении размеры окна пересылаются не всегда. И при этом рассказываешь, "как надо правильно". С чего ты решил, что не знал? Вот мой код, от 2001 года вроде void CScopeDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) { CDialog::OnWindowPosChanging(lpwndpos); if (GetMinSize()==CSize(0,0)) return; if (!(lpwndpos->flags & SWP_NOSIZE)) { CSize sz(lpwndpos->cx,lpwndpos->cy); ApplyAnchors(this,GetMinSize(),sz,__anchors); lpwndpos->cx=sz.cx; lpwndpos->cy=sz.cy; } } А вот цитата из MSDN, насчёт WM_WINDOWPOSCHANGING While this message is being processed, modifying any of the values in WINDOWPOS affects the window's new size, position, or place in the Z order. An application can prevent changes to the window by setting or clearing the appropriate bits in the flags member of WINDOWPOS. |
Сообщ.
#28
,
|
|
|
Цитата barazuk @ Идеологически правильно обрабатывать OnGetMinMaxInfo. Он вызывается ПЕРЕД любым изменением размера, и специально для этого предназначен В свое время писал специальный класс, Layout, на который можно накидывать контролы, которые будут перемещаться и изменять размер, в зависимости от размеров диалога. Именно через OnGetMinMaxInfo ЕМНИП это и делал. Все работало и до сих пор работает гдето далеко уверен что на ура |
Сообщ.
#29
,
|
|
|
Цитата KILLER @ В свое время писал специальный класс, Layout, на который можно накидывать контролы, которые будут перемещаться и изменять размер, в зависимости от размеров диалога. а щас используешь его? |
Сообщ.
#30
,
|
|
|
Цитата Cfon @ а щас используешь его? А щас я уже с MFC и WinApi не работал пару лет уже. Ну так то помню что да как работает, какие то конкретные вещи через гугл за пару секунд гуглятся. Добавлено Если не забуду могу как до дома доберусь, посмотреть конкретно через какие функции я делал. Там класс практически для тех же целей что и у ТС. Единственное там возможно еще и отрисовка кастомных контролов запилена, я уж и не помню. |
Сообщ.
#31
,
|
|
|
Цитата KILLER @ Цитата Cfon @ а щас используешь его? А щас я уже с MFC и WinApi не работал пару лет уже. Ну так то помню что да как работает, какие то конкретные вещи через гугл за пару секунд гуглятся. ясно |