На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
  
> Как разумно ограничить размер диалога?
    В очередной раз написал класс, который двигает и растягивает контролы при изменении размера диалога.

    Естественно, захотелось сделать так, чтобы диалог нельзя было сделать меньше определенного размера.

    Тупо вбивать не хочется, более привлекает, просто чтобы размер диалога не делался менее исходного.

    Куски кода, имеющие отношение к делу:

    ExpandedWrap disabled
      *.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);
      }


    Ну и в самом мувере:
    ExpandedWrap disabled
      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 заносится какой-то мусор. Спрашивается - почему? Что эдакого семерка делает более чрезпопно, чем ХП?

    Добавлено
    Поставил костыль:

    ExpandedWrap disabled
      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ка что, два раза инит диалог вызывает?
      Из того что ты привел ничего не понятно. Код простой все на виду, един. что вижу так это что булет если не указать парент? вроде как члены не будут инициализированы :D
        Все, решен вопрос, семерка OnGetMinMaxInfo первый раз вызывает до OnInitDialog. Поставил защиту в виде проверки, проинициализировано ли все в классе ControlMover. Заодно пофиксил еще кое-то и попрятал что не должно торчать наружу в защищенные методы. Не идеально... Но теперь пашет, как ожидалось.

        Добавлено
        Цитата Cfon @
        Из того что ты привел ничего не понятно. Код простой все на виду, един. что вижу так это что будет если не указать парент? вроде как члены не будут инициализированы


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

        Гораздо веселее когда в таком случае ставят ассерт, и все к чертям вылетает, и попробуй без дебагера найти концы :)
        Сообщение отредактировано: barazuk -
          Результат:

          Прикреплённая картинка
          Прикреплённая картинка
            красиво :D
            я если честно вообще стараюсь не тратить время на интерфейс, ИМХО главное назначение программы ;)

            сначала решаю чтобы программа выполняла свою цель, ну а потом занимаюсь интерфейсом.
            Сообщение отредактировано: Cfon -
              Cfon, на самом деле тут оно нахрен не надо, изначально в другой проге делал, которая для просмотра и редактирования картинок, просто захотел инкапсулировать и выдернуть так чтобы легким движением руки в любой проект потом кидать. Вот теперь сижу и смотрю как допилить, чтобы оба списка масштабировались, и при этом не усложнить все до маразма. В смысле чтобы при растягивании оба списка оставались примерно одной ширины.
              Сообщение отредактировано: barazuk -
                Цитата barazuk @
                Cfon, на самом деле тут оно нахрен не надо, изначально в другой проге делал, которая для просмотра и редактирования картинок, просто захотел инкапсулировать и выдернуть так чтобы легким движением руки в любой проект потом кидать.

                на самом деле все уже придумано и выложено в инет :)
                например вот: https://www.codeproject.com/Articles/116/Layout-Manager-for-Dialogs-Formviews-DialogBars-an
                  Цитата Cfon @
                  на самом деле все уже придумано и выложено в инет


                  Ай вещь на самом деле простецкая настолько, что проще самому с нуля сделать, чем если что разбираться в чужом говнокоде чтобы что-то прикрутить

                  Добавлено
                  Цитата Cfon @
                  например вот:


                  О боже какой адский трындец :)
                    ну хз смотри сам, а я всегда сначала гуглю особенно на codeproject или sourceforge.net :D
                    просто мне так удобнее :P
                      Цитата Cfon @
                      ну хз смотри сам, а я всегда сначала гуглю особенно на codeproject или sourceforge.net


                      Я обычно только подглядываю основную идею... В 99% случаев допиливание и вылов багов в чужом мегакоде на все случаи жизни намного дольше, чем сделать ту маленькую штучку, которую собственно нужно сделать из того парового велосипеда на ядерной тяге, который обычно пафосно городят там где достаточно 20 строк кода :)
                      Сообщение отредактировано: barazuk -
                        вот пример MFC диалога c Layout (упростил макс :D ).
                        вся работа происходит в OnInitDialog. Все что нам нужно добавить в проект файлы ETSLayout.cpp(.h) и поменять базовый класс диалога c CDialogEx на ETSLayoutDialog.
                        VS 2010.
                        Прикреплённый файлПрикреплённый файлTestLayout.zip (95,2 Кбайт, скачиваний: 95)
                        Сообщение отредактировано: Cfon -
                          Цитата Cfon @
                          на самом деле все уже придумано и выложено в инет :)
                          например вот: https://www.codeproject.com/Articles/116/Layout-Manager-for-Dialogs-Formviews-DialogBars-an

                          Получается так, что не всё.
                          Чтобы как-то ограничить размеры окна достаточно обработать сообщение WM_SIZE.
                          Полученные в сообщении размеры сравниваем с ограничениями, и если надо используем "SetWindowPos".
                          Разве этого не достаточно ?
                          Сообщение отредактировано: ЫукпШ -
                            Цитата ЫукпШ @
                            "SetWindowPos".


                            И получаем ill behaved application.

                            Для этого обрабатывается OnGetMinMaxInfo.
                              Цитата ЫукпШ @
                              Чтобы как-то ограничить размеры окна достаточно обработать сообщение WM_SIZE.

                              Вообще, для того, чтоб в диалоге изменять позицию и размер контролов нужно обрабатывать сообщение WM_WINDOWPOSCHANGING
                                Цитата barazuk @
                                Цитата ЫукпШ @
                                "SetWindowPos".


                                И получаем ill behaved application.

                                С чего это вдруг ?
                                Прежде чем советовать, я сам попробовал.
                                Можешь не сомневаться - это устойчиво работает.

                                Добавлено
                                Цитата Олег М @
                                Цитата ЫукпШ @
                                Чтобы как-то ограничить размеры окна достаточно обработать сообщение WM_SIZE.

                                Вообще, для того, чтоб в диалоге изменять позицию и размер контролов нужно обрабатывать сообщение WM_WINDOWPOSCHANGING

                                Вопрос был о том, "как ограничить размер диалога ?"
                                При изменении размеров окна в оконную процедуру
                                посылается сообщение WM_SIZE с установленными размерами.
                                По этому событию можно сравнить установленные размеры с ограничениями и,
                                если надо, установить допустимые размеры окна.
                                ---
                                Чтобы в диалоге менять что-то, можно использовать любые нужные функции WINAPI.
                                Функции создания "диалога" это оболочка вокруг CreateWindow(Ex).
                                С интерпретатором описания диалогового окна, представленного на языке ресурсов.
                                Это обычные окна (которые все функционально - диалоги), и всё содержимое
                                "диалогов" можно делать исключительно "вручную". Те посредством
                                непосредственного вызова CreateWindow для всех окошек-контролов всех нужных классов.
                                Сообщение отредактировано: ЫукпШ -
                                  да да живите в своём мире :D
                                  все уже давно придумано, layout рулит
                                  Сообщение отредактировано: Cfon -
                                    Цитата ЫукпШ @

                                    Вопрос был о том, "как ограничить размер диалога ?"
                                    При изменении размеров окна в оконную процедуру
                                    посылается сообщение WM_SIZE с установленными размерами.
                                    По этому событию можно сравнить установленные размеры с ограничениями и,
                                    если надо, установить допустимые размеры окна

                                    Как раз по этому событию ты ничего особо сделать с окном не можешь, Либо это будет работать дико коряво.
                                    WM_WINDOWPOSCHANGING вызывается до изменения и в нем ты можешь вернуть новые размеры окна, т.е. ограничить размер диалога, а заодно изменить контролы. Больше никаких сообщений обрабатывать не нужно, В том числе getminmax
                                      Цитата ЫукпШ @
                                      посылается сообщение WM_SIZE с установленными размерами.
                                      По этому событию можно сравнить установленные размеры с ограничениями и,
                                      если надо, установить допустимые размеры окна.


                                      А что, после сет виндов поз снова WM_SIZE не вызовется? :whistle:

                                      Не совсем хорошая практика, как по мне.
                                        Цитата barazuk @
                                        Цитата ЫукпШ @
                                        посылается сообщение WM_SIZE с установленными размерами.
                                        По этому событию можно сравнить установленные размеры с ограничениями и,
                                        если надо, установить допустимые размеры окна.


                                        А что, после сет виндов поз снова WM_SIZE не вызовется? :whistle:

                                        Обязательно вызовется - а как же иначе.
                                        Но новые правильно установленные размеры окна окажутся
                                        в допустимых пределах по их размерам.
                                        Это значит, что "SetWindowPos" вызвана не будет, ибо незачем.
                                        Никакого "автогенератора" не получится.

                                        Добавлено
                                        Олег М, WM_WINDOWPOSCHANGING это как раз результат работы SetWindowPos.
                                        ссылка
                                        Из обработчика этого сообщения я бы эту функцию вызвать не рискнул.
                                          Цитата ЫукпШ @
                                          Олег М, WM_WINDOWPOSCHANGING это как раз результат работы SetWindowPos.
                                          ссылка
                                          Из обработчика этого сообщения я бы эту функцию вызвать не рискнул

                                          Кто ж ее там вызывает? Там в параметрах сообщения можно вернуть новый размер окна
                                            Цитата Олег М @
                                            Там в параметрах сообщения можно вернуть новый размер окна

                                            Да вернуть-то можно, но не всегда.
                                            WM_WINDOWPOSCHANGING - это прямое следствие SetWindowPos.
                                            Но эта функция используется не только для изменения размеров окна.
                                            Значит, надо ещё правильно отфильтровать флаги. Возникает также вопрос - а что
                                            будет, если размер окна поменять другой функцией WINAPI ?
                                            (Напрмер, MoveWindow)
                                            ---
                                            Алгоритм процедуры в WM_SIZE проще, всё действует по-факту попытки изменить именно
                                            размеры окна неважно чем, неважно как.
                                              Цитата ЫукпШ @
                                              Да вернуть-то можно, но не всегда

                                              А когда нельзя?

                                              Добавлено
                                              Цитата ЫукпШ @
                                              Возникает также вопрос - а что
                                              будет, если размер окна поменять другой функцией WINAPI ?
                                              (Напрмер, MoveWindow)

                                              Будет отправлено это сообщение. Оно всегда отправляется, при изменении позиции или размера окна.
                                                Цитата Олег М @
                                                Цитата ЫукпШ @
                                                Да вернуть-то можно, но не всегда

                                                А когда нельзя?

                                                Эта функция используется не только для изменения размеров окна.
                                                И вместо размеров может быть любой мусор.
                                                ---
                                                А что будет, если в новых версиях Виндус будут добавлены новые флаги ?
                                                Может быть алгоритм снова придётся переделывать..
                                                Нет, не уговоришь.
                                                Работать по-факту происходящего всегда надёжнее.
                                                  Цитата ЫукпШ @
                                                  Нет, не уговоришь.
                                                  Работать по-факту происходящего всегда надёжнее.

                                                  Кто ж тебя уговаривает? Тебе рассказывают как надо делать правильно. Не доходит, ну и ладно.
                                                    Цитата Олег М @
                                                    Цитата ЫукпШ @
                                                    Нет, не уговоришь.
                                                    Работать по-факту происходящего всегда надёжнее.

                                                    Кто ж тебя уговаривает? Тебе рассказывают как надо делать правильно. Не доходит, ну и ладно.

                                                    Ты даже не знал, что в указанном тобой сообщении размеры
                                                    окна пересылаются не всегда.
                                                    И при этом рассказываешь, "как надо правильно".
                                                      Цитата ЫукпШ @
                                                      И при этом рассказываешь, "как надо правильно".


                                                      Идеологически правильно обрабатывать OnGetMinMaxInfo. Он вызывается ПЕРЕД любым изменением размера, и специально для этого предназначен :)

                                                      А изменение размера из WM_SIZE... Это костыль
                                                        Цитата ЫукпШ @
                                                        Ты даже не знал, что в указанном тобой сообщении размеры
                                                        окна пересылаются не всегда.
                                                        И при этом рассказываешь, "как надо правильно".


                                                        С чего ты решил, что не знал? Вот мой код, от 2001 года вроде

                                                        ExpandedWrap disabled
                                                          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.
                                                          Цитата barazuk @
                                                          Идеологически правильно обрабатывать OnGetMinMaxInfo. Он вызывается ПЕРЕД любым изменением размера, и специально для этого предназначен :)

                                                          В свое время писал специальный класс, Layout, на который можно накидывать контролы, которые будут перемещаться и изменять размер, в зависимости от размеров диалога. Именно через OnGetMinMaxInfo ЕМНИП это и делал. Все работало и до сих пор работает гдето далеко уверен что на ура :-?
                                                            Цитата KILLER @
                                                            В свое время писал специальный класс, Layout, на который можно накидывать контролы, которые будут перемещаться и изменять размер, в зависимости от размеров диалога.

                                                            а щас используешь его?
                                                              Цитата Cfon @
                                                              а щас используешь его?

                                                              А щас я уже с MFC и WinApi не работал пару лет уже. Ну так то помню что да как работает, какие то конкретные вещи через гугл за пару секунд гуглятся. :-?

                                                              Добавлено
                                                              Если не забуду могу как до дома доберусь, посмотреть конкретно через какие функции я делал. Там класс практически для тех же целей что и у ТС. Единственное там возможно еще и отрисовка кастомных контролов запилена, я уж и не помню.
                                                              Сообщение отредактировано: KILLER -
                                                                Цитата KILLER @
                                                                Цитата Cfon @
                                                                а щас используешь его?

                                                                А щас я уже с MFC и WinApi не работал пару лет уже. Ну так то помню что да как работает, какие то конкретные вещи через гугл за пару секунд гуглятся. :-?

                                                                ясно :)
                                                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                0 пользователей:


                                                                Рейтинг@Mail.ru
                                                                [ Script execution time: 0,0923 ]   [ 22 queries used ]   [ Generated: 27.04.24, 10:53 GMT ]