На главную Наши проекты:
Журнал   ·   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
Страницы: (4) 1 2 [3] 4  все  ( Перейти к последнему сообщению )  
> правильное программирование окна свойств , отмена изменений без проверки значений
    Цитата KILLER @
    Цитата Cfon @
    и еще как теперь изменить Tab Order?

    Ctrl+D, или меню Format->Tab Order.

    нет ты не понял, надо в ран-тайм. я создаю кнопку Reset вот ее надо вставить в tab order.

    Цитата KILLER @
    Цитата Cfon @
    а что за вирт функция CPropertyPage::OnReset зачем она нужна? что то не понял я ее отличия от OnCancel.

    Могу предположить, что эта херня просто сбрасывает данные в начальное состояние, без закрытия диалога настроек, а Cancel - отменяет все изменения и закрывает диалог. Но это я так предполагаю, как то не шибко часто встречался с этим обработчиком.

    в том и дело, что я тоже предполагал это, но где кнопка которая ее вызывает? выяснил что ее вызывает кнопка Cancel. вот я и не пойму ее смысл.
    думал что она (Reset) уже есть в CPropertySheet,точнее в ее ресурсах, но не нашел, поэтому создал свою кнопку в ран-тайм.

    Цитата KILLER @
    Цитата Cfon @
    Также попутно есть ли способ в VS2015 создать обработчик нажатия кнопки, созданой ручками, не ручками? :D

    Не понял. Но вообще можно. В самом запущенном случае, я например вручную рисовал кнопку руками, пилил для нее обработчик события(свой класс, без использования MFC функций), расчитывал в ручную координаты клика(попали или нет по нарисованной кнопке,), делал анимацию нажатия вручную. Т.е. в твоем случае можно. Только я не понял что имелось ввиду под "созданой ручками, не ручками" ?

    я имел ввиду в студии есть ли помошники для автоматизации это процесса (создание обработчика кнопки не из ресурса).

    уже разобрался Class Wizard позволит сделать все за нас :D
    Сообщение отредактировано: Cfon -
      Цитата Cfon @
      нет ты не понял, надо в ран-тайм. я создаю кнопку Reset вот ее надо вставить в tab order.

      В какой Tab Order? Я же тебе написал, открываешь свой диалог - меню Format -> Tab Order, там выставляешь порядок обхода контролов, либо в ресурсном файле - все элементы управления, располагаются в шаблоне диалога строго друг за дружкой, как выставленно в Tab Order, если там изменить порядок - тогда и Tab Order поменяется. Ну или можно программно, через SetWindowPos -> https://msdn.microsoft.com/en-us/library/ms...545(VS.85).aspx или вот тут пример есть -> http://www.devx.com/tips/Tip/27741
      Но я программно не заморачивался с этим, хотя судя по доке там проще простого, указываешь хендл ЭУ которому нужно поменять Tab Order, указываешь хендл ЭУ за кем он будет располагаться, ну и флаги с координатами.

      Цитата Cfon @
      в том и дело, что я тоже предполагал это, но где кнопка которая ее вызывает? выяснил что ее вызывает кнопка Cancel. вот я и не пойму ее смысл.

      Я хз, тогда надо читать доку.

      Цитата Cfon @
      я имел ввиду в студии есть помошники для автоматизации это процесса.

      Да есть, берешь открываешь диалог, и жмешь два раза мышкой по кнопке, среда для тебя сгенерирует обработчик события и перенесет курсов в код, в этот новый сгенерированный обработчик.
      Сообщение отредактировано: KILLER -
        Цитата KILLER @
        Ну или можно программно, через SetWindowPos -> https://msdn.microsoft.com/en-us/library/ms...545(VS.85).aspx или вот тут пример есть -> http://www.devx.com/tips/Tip/27741
        Но я программно не заморачивался с этим, хотя судя по доке там проще простого, указываешь хендл ЭУ которому нужно поменять Tab Order, указываешь хендл ЭУ за кем он будет располагаться, ну и флаги с координатами.

        если все контролы в ресурсе, то да нет нужды, но я создаю кнопку Reset программно вот и понадобилось выставить tab order :)

        спс разобрался SetWindowPos помог:
        ExpandedWrap disabled
          BOOL CDjVuPreferenceSheet::OnInitDialog()
          {
              BOOL bResult = CPropertySheet::OnInitDialog();
              CRect buttonRect, tabRect;
              
              // get size and positions OK button and tab control
              GetDlgItem(IDOK)->GetWindowRect(buttonRect);
              GetTabControl()->GetWindowRect(tabRect);
           
              // convert screen measure to client measure
              ScreenToClient(buttonRect);
              ScreenToClient(tabRect);
              
              /*TRACE(_T("buttonRect: left=%d, top=%d, right=%d, bottom=%d\n"),
                  buttonRect.left, buttonRect.top, buttonRect.right, buttonRect.bottom);*/
           
              // calc new position Reset button
              int w = buttonRect.Width();
              buttonRect.left = tabRect.left;
              buttonRect.right = tabRect.left + w;
           
              mResetButton.Create(_T("Reset"), BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
                  buttonRect, this, IDC_RESET_BUTTON);
              mResetButton.SetFont(GetFont());    
           
              // set tab order Reset button
              const CWnd* pPrev = GetDlgItem(IDOK)->GetNextWindow(GW_HWNDPREV);    //<-- вот ана :)
              mResetButton.SetWindowPos(pPrev, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);  
           
              return bResult;
          }


        Цитата KILLER @
        Цитата Cfon @
        я имел ввиду в студии есть помошники для автоматизации это процесса.

        Да есть, берешь открываешь диалог, и жмешь два раза мышкой по кнопке, среда для тебя сгенерирует обработчик события и перенесет курсов в код, в этот новый сгенерированный обработчик.

        нет ты опять не понял меня :D
        то что студия умеет создавать обработчики контролов, которые присутвтвуют в ресурсе, я знаю, но вот то что он может создать обработчик и для не существующей кнопки не знал ( теперь знаю :D ), достаточно заранее определить ID в файле Resource.h
        вот это я создал с помощью мастера Class Wizard:
        ExpandedWrap disabled
          class CDjVuPreferenceSheet : public CPropertySheet
          {
           
           
              DECLARE_MESSAGE_MAP()      
              afx_msg void OnResetButton(); // 1
              
          };
           
           
          BEGIN_MESSAGE_MAP(CDjVuPreferenceSheet, CPropertySheet)
              ON_COMMAND(IDC_RESET_BUTTON, &CDjVuPreferenceSheet::OnResetButton)  //<-- 2
          END_MESSAGE_MAP()
           
          void CDjVuPreferenceSheet::OnResetButton() //<--- 3
          {
          }
        Сообщение отредактировано: Cfon -
          Цитата Cfon @
          то что студия умеет создавать обработчики контролов, которые присутвтвуют в ресурсе, я знаю, но вот то что он может создать обработчик и для не существующей кнопки не знал ( теперь знаю :D ), достаточно заранее определить ID в файле Resource.h

          Если у тебя элемент управления(не важно кнопка это или еще какая то дрянь) имеет HWND, тогда да, достаточно в Resource.h добавить идентификатор, который ты указал в CreateWindow, и добавить его в карту обработки сообщений. А если ты сам нарисовал, и у тебя элемент управления даже не имеет HWND, тогда надо самому писать класс-обработчик событий, расчитывать координаты - куда ткнул пользователь мышкой и вызывать его вручную. В твоем случае как я понял - этого не требуется.

          Цитата Cfon @
          вот это я создал с помощью мастера Class Wizard:

          Ну можно было и руками вообще это написать.
          Сообщение отредактировано: KILLER -
            Цитата KILLER @
            Если у тебя элемент управления(не важно кнопка это или еще какая то дрянь) имеет HWND, тогда да, достаточно в Resource.h добавить идентификатор, который ты указал в CreateWindow, и добавить его в карту обработки сообщений. А если ты сам нарисовал, и у тебя элемент управления даже не имеет HWND, тогда надо самому писать класс-обработчик событий, расчитывать координаты - куда ткнул пользователь мышкой и вызывать его вручную. В твоем случае как я понял - этого не требуется.

            не понял а как это конртол не имеет хендл?

            Цитата KILLER @
            Цитата Cfon @
            вот это я создал с помощью мастера Class Wizard:

            Ну можно было и руками вообще это написать.

            раньше я так и делал ;) но визард упрощает ИМХО
              Цитата Cfon @
              не понял а как это конртол не имеет хендл?

              Ну вот так, полностью нарисованный. Не через CreateWindow, а вручную все рисуется и эмулируется поведение.

              Цитата Cfon @
              раньше я так и делал ;) но визард упрощает ИМХО

              Это когда у тебя ресурсы в одном проекте с исходным кодом. А иногда бывает так, что ресурсы отдельный проект и храняться в DLL, а исходный код, где они используются вообще другой проект. Вот тогда уже через мастер не прокатит. Потому что ресурсы - это другой проект.
                Цитата KILLER @
                Цитата Cfon @
                не понял а как это конртол не имеет хендл?

                Ну вот так, полностью нарисованный. Не через CreateWindow, а вручную все рисуется и эмулируется поведение.

                не имел такой практики :)
                если надо что-то рисовать то рисовал в Picture control или Static control ну или во вьюшке по OnPaint.

                Цитата KILLER @
                Это когда у тебя ресурсы в одном проекте с исходным кодом. А иногда бывает так, что ресурсы отдельный проект и храняться в DLL, а исходный код, где они используются вообще другой проект. Вот тогда уже через мастер не прокатит. Потому что ресурсы - это другой проект.

                ну ты уже слишком строго подходишь к интрументам :D
                я например если что-то где-то можно применить то применяю, ну а если нельзя то нельзя :)
                  Цитата Cfon @
                  ну ты уже слишком строго подходишь к интрументам :D
                  я например если что-то где-то можно применить то применяю, ну а если нельзя то нельзя

                  Ну вот на прошлой работе, был проект. Логика отдельно в одном проекте, ресурсы отдельно в другом проекте. Потому как в одном только солюшине ресурсов больше пол сотни проектов было, в каждом проекте по 20-30 форм, причем все это еще на трех языках и т.д. Это дело очень сложно все поддерживать в одном солюшине, и очень много по памяти будет отгрызать, проще было разделить на отдельные проекты. Ресурсы в виде dll библиотек отдельно, логика, которая подключает все это отдельно. Плюс ко всему многие заморачиваются со всякими темами/скинами и т.п. для своих гуи свистоперделок. А в этом случае удобно ресурсы выносить отдельным проектом в виде DLL, чтоб можно было подкидывать другие DLL, без изменения исходного кода основной программы.

                  Цитата Cfon @
                  если надо что-то рисовать то рисовал в Picture control или Static control ну или во вьюшке по OnPaint.

                  Ага, через DrawFrameControl все отрисовывал, в отдельном классе, и отдельно для него обработчик пилил.
                  Сообщение отредактировано: KILLER -
                    Цитата KILLER @
                    Ну вот на прошлой работе, был проект. Логика отдельно в одном проекте, ресурсы отдельно в другом проекте. Потому как в одном только солюшине ресурсов больше пол сотни проектов было, в каждом проекте по 20-30 форм, причем все это еще на трех языках и т.д. Это дело очень сложно все поддерживать в одном солюшине, и очень много по памяти будет отгрызать, проще было разделить на отдельные проекты. Ресурсы в виде dll библиотек отдельно, логика, которая подключает все это отдельно. Плюс ко всему многие заморачиваются со всякими темами/скинами и т.п. для своих гуи свистоперделок. А в этом случае удобно ресурсы выносить отдельным проектом в виде DLL, чтоб можно было подкидывать другие DLL, без изменения исходного кода основной программы.

                    да я понял :)
                    я говорил о том, что если что-то можно автоматизировать зачем делать ручками?
                    опять же я понимаю, что в некоторых случаях нельзя применить Class Wizard, тогда естественно ручками :D

                    Цитата KILLER @
                    Ага, через DrawFrameControl все отрисовывал, в отдельном классе, и отдельно для него обработчик пилил.

                    не мне стандарных контролов хватает: кнопки, флажки и т.д. :)
                      обнаружил один баг (хотя тщательно не копал) короче не умею я складно писать, поэтому выкладываю код и комменты к нему :D
                      в таком варианте не пашет, при инициализации ползунок устанавливается в конец диапазона:
                      ExpandedWrap disabled
                        CDisplayPage::CDisplayPage()
                            : CPropertyPage(IDD_DISPLAY)
                            // устанавливаю начальное значение (раз)
                            , mMagnifyGlassSizeSliderValue(100)
                        {  
                         
                        }
                         
                        void CDisplayPage::DoDataExchange(CDataExchange* pDX)
                        {      
                            CPropertyPage::DoDataExchange(pDX);
                            DDX_Control(pDX, IDC_MAGNIFYGLASS_SIZE_SPIN, mMagnifyGlassSizeSpin);
                            DDX_Control(pDX, IDC_MAGNIFYGLASS_SIZE_SLIDER, mMagnifyGlasSizeSlider);
                            DDX_Control(pDX, IDC_MAGNIFYGLASS_ZOOM_COMBO, mMagnifyGlassZoomCombo);
                            DDX_Control(pDX, IDC_DRAWBORDER_CHECK, mDrawBorderCheck);
                            DDX_Control(pDX, IDC_KEY_COMBO, mKeyCombo);
                            DDX_Control(pDX, IDC_TOOLBAR_ENABLE_CHECK, mToolbarEnableCheck);
                            DDX_Control(pDX, IDC_TOOLBAR_AUTOHIDE_CHECK, mToolbarAutoHideCheck);
                         
                            DDX_Text(pDX, IDC_MAGNIFYGLASS_SIZE_EDIT, mMagnifyGlassSizeEditValue);  
                            DDV_MinMaxUInt(pDX, mMagnifyGlassSizeEditValue, cBeginRange, cEndRange);        
                            DDX_CBIndex(pDX, IDC_MAGNIFYGLASS_ZOOM_COMBO, mMagnifyGlassZoomIndex);
                            DDX_Check(pDX, IDC_DRAWBORDER_CHECK, mDrawBorderState);
                            DDX_CBIndex(pDX, IDC_KEY_COMBO, mKeyIndex);
                            DDX_Check(pDX, IDC_TOOLBAR_ENABLE_CHECK, mToolbarEnableState);
                            DDX_Check(pDX, IDC_TOOLBAR_AUTOHIDE_CHECK, mToolbarAutoHideState);  
                         
                        // связываю переменную с механизмом обмена данными (два)
                            DDX_Slider(pDX, IDC_MAGNIFYGLASS_SIZE_SLIDER, mMagnifyGlassSizeSliderValue);
                        }
                         
                        BOOL CDisplayPage::OnInitDialog()
                        {      
                            CPropertyPage::OnInitDialog();  
                            
                            const int cBeginRange = 50;
                            const int cEndRange = 300;
                            const int cStep = 10;
                         
                            mMagnifyGlassSizeSpin.SetRange(cBeginRange, cEndRange);
                            mMagnifyGlassSizeSpin.SetPos(mMagnifyGlassSizeEditValue);
                         
                        // инициализация контрола (три)
                            mMagnifyGlasSizeSlider.SetRange(cBeginRange, cEndRange);            
                            mMagnifyGlasSizeSlider.SetPos(mMagnifyGlassSizeSliderValue);
                         
                            TRACE("mMagnifyGlassSizeSliderValue = %d\n", mMagnifyGlassSizeSliderValue);
                         
                            for (int i = cBeginRange; i < cEndRange; i += cStep)
                            {
                                mMagnifyGlasSizeSlider.SetTic(i);
                            }
                         
                        .......................
                         
                            return TRUE;  // return TRUE unless you set the focus to a control
                                          // EXCEPTION: OCX Property Pages should return FALSE
                        }


                      внес некоторые изменения работает:
                      ExpandedWrap disabled
                        CDisplayPage::CDisplayPage()
                            : CPropertyPage(IDD_DISPLAY)
                            
                            , mMagnifyGlassSizeSliderValue(100)
                        {
                        }
                         
                        void CDisplayPage::DoDataExchange(CDataExchange* pDX)
                        {      
                            CPropertyPage::DoDataExchange(pDX);
                            DDX_Control(pDX, IDC_MAGNIFYGLASS_SIZE_SPIN, mMagnifyGlassSizeSpin);
                            DDX_Control(pDX, IDC_MAGNIFYGLASS_SIZE_SLIDER, mMagnifyGlasSizeSlider);
                            DDX_Control(pDX, IDC_MAGNIFYGLASS_ZOOM_COMBO, mMagnifyGlassZoomCombo);
                            DDX_Control(pDX, IDC_DRAWBORDER_CHECK, mDrawBorderCheck);
                            DDX_Control(pDX, IDC_KEY_COMBO, mKeyCombo);
                            DDX_Control(pDX, IDC_TOOLBAR_ENABLE_CHECK, mToolbarEnableCheck);
                            DDX_Control(pDX, IDC_TOOLBAR_AUTOHIDE_CHECK, mToolbarAutoHideCheck);
                         
                            DDX_Text(pDX, IDC_MAGNIFYGLASS_SIZE_EDIT, mMagnifyGlassSizeEditValue);  
                            DDV_MinMaxUInt(pDX, mMagnifyGlassSizeEditValue, cBeginRange, cEndRange);        
                            DDX_CBIndex(pDX, IDC_MAGNIFYGLASS_ZOOM_COMBO, mMagnifyGlassZoomIndex);
                            DDX_Check(pDX, IDC_DRAWBORDER_CHECK, mDrawBorderState);
                            DDX_CBIndex(pDX, IDC_KEY_COMBO, mKeyIndex);
                            DDX_Check(pDX, IDC_TOOLBAR_ENABLE_CHECK, mToolbarEnableState);
                            DDX_Check(pDX, IDC_TOOLBAR_AUTOHIDE_CHECK, mToolbarAutoHideState);  
                         
                            // bug ???
                            //DDX_Slider(pDX, IDC_MAGNIFYGLASS_SIZE_SLIDER, mMagnifyGlassSizeSliderValue);
                         
                            // заменил вот этим
                            if (pDX->m_bSaveAndValidate)
                            {
                                //TRACE("Update slider data member\n");
                                ASSERT(mMagnifyGlasSizeSlider);
                                mMagnifyGlassSizeSliderValue = mMagnifyGlasSizeSlider.GetPos();
                            }
                            else
                            {
                                //TRACE("Update slider control\n");
                                ASSERT(mMagnifyGlasSizeSlider);
                                mMagnifyGlasSizeSlider.SetRange(cBeginRange, cEndRange);
                                mMagnifyGlasSizeSlider.SetPos(mMagnifyGlassSizeSliderValue);
                            }  
                        }
                         
                        BOOL CDisplayPage::OnInitDialog()
                        {      
                            CPropertyPage::OnInitDialog();  
                            
                         
                         
                            mMagnifyGlassSizeSpin.SetRange(cBeginRange, cEndRange);
                            mMagnifyGlassSizeSpin.SetPos(mMagnifyGlassSizeEditValue);
                         
                            // перенес этот код в DoDataExchange
                            /*mMagnifyGlasSizeSlider.SetRange(cBeginRange, cEndRange);          
                            mMagnifyGlasSizeSlider.SetPos(mMagnifyGlassSizeSliderValue);*/
                         
                            TRACE("mMagnifyGlassSizeSliderValue = %d\n", mMagnifyGlassSizeSliderValue);
                         
                            for (int i = cBeginRange; i < cEndRange; i += cStep)
                            {
                                mMagnifyGlasSizeSlider.SetTic(i);
                            }
                         
                        .......................
                         
                            return TRUE;  // return TRUE unless you set the focus to a control
                                          // EXCEPTION: OCX Property Pages should return FALSE
                        }
                      Сообщение отредактировано: Cfon -
                        Думаю, можно было в OnInitDialog просто поставить UpdateData(FALSE);, перед return
                          Цитата Олег М @
                          Думаю, можно было в OnInitDialog просто поставить UpdateData(FALSE);, перед return

                          пробовал не помогло :no-sad:

                          так?
                          ExpandedWrap disabled
                            BOOL CDisplayPage::OnInitDialog()
                            {      
                                CPropertyPage::OnInitDialog();  
                             
                                const int cBeginRange = 50;
                                const int cEndRange = 300;
                                const int cStep = 10;
                             
                                mMagnifyGlassSizeSpin.SetRange(cBeginRange, cEndRange);
                                mMagnifyGlassSizeSpin.SetPos(mMagnifyGlassSizeEditValue);
                             
                            // инициализация контрола (три)
                                mMagnifyGlasSizeSlider.SetRange(cBeginRange, cEndRange);            
                                mMagnifyGlasSizeSlider.SetPos(mMagnifyGlassSizeSliderValue);
                             
                                TRACE("mMagnifyGlassSizeSliderValue = %d\n", mMagnifyGlassSizeSliderValue);
                             
                                for (int i = cBeginRange; i < cEndRange; i += cStep)
                                {
                                    mMagnifyGlasSizeSlider.SetTic(i);
                                }
                             
                            .......................
                             
                                UpdateData(FALSE);
                                   
                                return TRUE;  // return TRUE unless you set the focus to a control
                                              // EXCEPTION: OCX Property Pages should return FALSE
                            }
                            Цитата Cfon @
                            for (int i = cBeginRange; i < cEndRange; i += cStep)
                            mMagnifyGlasSizeSlider.SetTic(i);

                            Наверное из-за этой штуки не работает. Когда ты делаешь SetRange после неё, то всё нормально.
                            После неё SetPos надо в тиках выставлять, наверное.
                            Сообщение отредактировано: Олег М -
                              Цитата Олег М @
                              Цитата Cfon @
                              for (int i = cBeginRange; i < cEndRange; i += cStep)
                              mMagnifyGlasSizeSlider.SetTic(i);

                              Наверное из-за этой штуки не работает. Когда ты делаешь SetRange после неё, то всё нормально.
                              После неё SetPos надо в тиках выставлять, наверное.

                              так?
                              ExpandedWrap disabled
                                BOOL CDisplayPage::OnInitDialog()
                                {      
                                    CPropertyPage::OnInitDialog();  
                                    
                                    
                                    mMagnifyGlassSizeSpin.SetRange(cBeginRange, cEndRange);
                                    mMagnifyGlassSizeSpin.SetPos(mMagnifyGlassSizeEditValue);          
                                 
                                    TRACE("mMagnifyGlassSizeSliderValue = %d\n", mMagnifyGlassSizeSliderValue);
                                 
                                    for (int i = cBeginRange; i < cEndRange; i += cStep)
                                    {
                                        mMagnifyGlasSizeSlider.SetTic(i);
                                    }
                                 
                                    mMagnifyGlasSizeSlider.SetRange(cBeginRange, cEndRange);
                                    mMagnifyGlasSizeSlider.SetPos(mMagnifyGlassSizeSliderValue);
                                 
                                    
                                ..........................
                                    return TRUE;  // return TRUE unless you set the focus to a control
                                                  // EXCEPTION: OCX Property Pages should return FALSE
                                }

                              не работает :no-sad:
                                DDX_Slider просто вызывает SetPos, больше ничего
                                Убери этот SetTic вообще, и попробуй
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (4) 1 2 [3] 4  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0551 ]   [ 16 queries used ]   [ Generated: 27.04.24, 11:38 GMT ]