Поиск:

Ответ в темуСоздание новой темы Создание опроса
> OnSize, в чем ошибка? 
:(
    Опции темы
assasinnn
Дата 25.8.2009, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 19.8.2009

Репутация: нет
Всего: нет



Вопрос таков: перегружаю функцию OnSize(). В своем диалоговом окне добиваюсь, чтобы кнопки при растягивании либо вверх, либо вправо сохраняли свои позиции относительно главного окна.
Получил такой код:
Код

void CMobileTISDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);
    if(Flag)
    {
        CRect R = CRect(0,0,0,0);
        GetWindowRect(&R);
        ScreenToClient(&R);
        LONG right = R.right - MinSize.right;// СRect MinSize заполняется в OnInitDialog и содержит размеры главного окна при старте программы
        LONG top = R.top - MinSize.top;
        int nCount = ResData.size();
        for(int i=0;i<nCount;i++)
        {
            GetDlgItem(ResData[i].nID)->MoveWindow(ResData[i].aRect.left+right,
                ResData[i].aRect.top+top,
                ResData[i].aRect.Width(),
                ResData[i].aRect.Height());
        }
    }
}

ResData это вектор, содержащий структуры вида
Код

struct  ResizeStruct
{
    CRect aRect;//прямоугольник для кнопки
    UINT nID;//идентификатор кнопки
};


заполнение структуры происходит при вызове функции
Код

void CMobileTISDlg::SetResData(UINT nID)
{
    ResizeStruct Res;
    Res.aRect = CRect(0,0,0,0);
    GetDlgItem(nID)->GetClientRect(&Res.aRect);
    Res.nID = nID;
    ResData.push_back(Res);
}


Проблема в том, что почему то при тестировании программы кнопки вместо того, чтобы вести себя, как описано выше, сбиваются в одну кучу в левом краю программы. В чем моя ошибка?
PM MAIL   Вверх
Andrey44
Дата 26.8.2009, 07:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



 smile Я бы сделал совсем не так
Код

struct  ResizeStruct
{
    CPoint aPoint;//Левый верхний угол для кнопки
    UINT nID;//идентификатор кнопки
};

void CMobileTISDlg::SetResData(UINT nID)
{
    ResizeStruct Res;
    CRect rc, rcForm;
    GetDlgItem(nID)->GetClientRect(&rc);
    GetClientRect(&rcForm);
    Res.aPoint.x = rcForm.right - rc.left; Res.aPoint.y = rcForm.bottom - rc.top;
    Res.nID = nID;
    ResData.push_back(Res);
}

void CMobileTISDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialog::OnSize(nType, cx, cy);
    if(Flag)
    {
        int nCount = ResData.size();
        for(int i=0;i<nCount;i++)
        {
            GetDlgItem(ResData[i].nID)->SetWindowPos(&wndTop, cx - ResData[i].aPoint.x, cy - ResData[i].aPoint.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
        }
    }
}

Не проверял, но по моему должно работать smile 


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 26.8.2009, 07:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Первый раз OnSize приходит ДО вызова OnInitDialog: возможно с нулевыми размерами и при неинициализированных ResData). Если есть уверенность в том, что здесь все в порядке (там у тебя флаг какой-то, возможно, он рулит), то есть отладчик: посмотри по шагам как считается, чего гадать.


--------------------
...
PM   Вверх
assasinnn
Дата 26.8.2009, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 19.8.2009

Репутация: нет
Всего: нет



Цитата(Andrey44 @ 26.8.2009,  07:03)

Не проверял, но по моему должно работать smile

Как не жаль, но опять все в гармонь
PM MAIL   Вверх
assasinnn
Дата 26.8.2009, 08:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 19.8.2009

Репутация: нет
Всего: нет



Цитата(Earnest @ 26.8.2009,  07:42)
посмотри по шагам как считается, чего гадать.

Просмотрел вариант Andrey44, он действительно проще и лучше. Только вопрос остался.
прошел отладчиком, получается, что при вызове функции GetDlgItem(nID)->GetClientRect(); левый край и вершина устанавливаются абсолютно всегда в ноль, оттого все пляски. Почему так может быть?

Это сообщение отредактировал(а) assasinnn - 26.8.2009, 08:55
PM MAIL   Вверх
Andrey44
Дата 26.8.2009, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Цитата(assasinnn @  26.8.2009,  08:44 Найти цитируемый пост)
Почему так может быть?

Где вызывается функция SetResData?


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Cheloveck
Дата 26.8.2009, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



 smile  
Цитата(assasinnn @  25.8.2009,  22:50 Найти цитируемый пост)
сбиваются в одну кучу в левом краю программы
 омг... у программы есть левый край?  smile 



--------------------
user posted image
PM Jabber   Вверх
assasinnn
Дата 26.8.2009, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 19.8.2009

Репутация: нет
Всего: нет



Цитата(Cheloveck @ 26.8.2009,  08:59)
 у программы есть левый край? 

в левом краю окна программы. От этого вопрос поменял свою суть?)

Добавлено через 59 секунд
Цитата(Andrey44 @ 26.8.2009,  08:57)

Где вызывается функция SetResData?

в OnInitDialog()
PM MAIL   Вверх
Andrey44
Дата 26.8.2009, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 12
Всего: 26



Ты можешь посмотреть значения вектора ResData?


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
assasinnn
Дата 26.8.2009, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 19.8.2009

Репутация: нет
Всего: нет



Цитата(Andrey44 @ 26.8.2009,  09:21)
Ты можешь посмотреть значения вектора ResData?

Andrey44, спасибо! Я настроил. В твоем варианте надо было только заменить GetClientRect() (забыл я совсем, что у нее свойство такое устанавливать top и left в 0) на GetWindowRect() и ScreenToClient()

Это сообщение отредактировал(а) assasinnn - 26.8.2009, 10:09
PM MAIL   Вверх
Cheloveck
Дата 26.8.2009, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Я так понял, что вопрос решился. Но на последок покажу как я добился того, что у меня все контролы перемещаются/растягиваются при изменении размеров окна. У меня есть такой класс
Код

template<class T_Ctrl>
class MovableCtrl : public T_Ctrl
{
public:
    void    SetMovableData(int fixOffsetX, int fixOffsetY, bool isFixedOffset,
                float proportOffsetX, float proportOffsetY, int fixWidth,
                int fixHeight, bool isFixedSize, float proportWidth, 
                float proportHeight);

    void    MoveControl(const int parentWidth, const int parentHeight);
private:
    int        fixOffsetX_; // Фиксированное смещение контрола по X.
    int        fixOffsetY_; // Фиксированное смещение контрола по Y.
    // isFixedOffset = true - контрол не перемещается.
    // proportOffsetX и proportOffsetY игнорируются.
    bool    isFixedOffset_; 
    float    proportOffsetX_; // Пропорциональное смещение по X.
    float    proportOffsetY_; // Пропорциональное смещение по Y.
    int        fixWidth_; // Фиксированная ширина контрола.
    int        fixHeight_; // Фиксированная выста контрола.
    // isFixedSize = true - ширина и высота фиксированы.
    // proportWidth и proportHeight игнорируются.
    bool    isFixedSize_;
    float    proportWidth_; // Ширина контрола в пропорции от ширины окна.
    float    proportHeight_; // Высота контрола в пропорции от высоты окна.
};
//-------------------------------------------------------------------

template<class T_Ctrl>
void MovableCtrl<T_Ctrl>::SetMovableData(int fixOffsetX, int fixOffsetY, 
                    bool isFixedOffset, float proportOffsetX, 
                    float proportOffsetY, int fixWidth, int fixHeight,
                    bool isFixedSize, float proportWidth, float proportHeight)
{
    fixOffsetX_ = fixOffsetX;
    fixOffsetY_ = fixOffsetY;
    if(!(isFixedOffset_ = isFixedOffset))
    {
        proportOffsetX_ = proportOffsetX;
        proportOffsetY_ = proportOffsetY;
    }
    fixWidth_ = fixWidth;
    fixHeight_ = fixHeight;
    if(!(isFixedSize_ = isFixedSize))
    {
        proportWidth_ = proportWidth;
        proportHeight_ = proportHeight;
    }
}
//-------------------------------------------------------------------

template<class T_Ctrl>
void MovableCtrl<T_Ctrl>::MoveControl(const int parentWidth, 
                    const int parentHeight)
{
    RECT rect;
    rect.left = fixOffsetX_;
    rect.top = fixOffsetY_;
    if(!isFixedOffset_)
    {
        rect.left += static_cast<int>( static_cast<float>(parentWidth) *
        proportOffsetX_ );
        rect.top += static_cast<int>( static_cast<float>(parentHeight) *
        proportOffsetY_ );
    }
    rect.right = rect.left + fixWidth_;
    rect.bottom = rect.top + fixHeight_;
    if(!isFixedSize_)
    {
        rect.right += static_cast<int>( static_cast<float>(parentWidth) *
        proportWidth_ );
        rect.bottom += static_cast<int>( static_cast<float>(parentHeight) *
        proportHeight_ );
    }

    T_Ctrl::MoveWindow(&rect);
}


Все контролы, которые должны двигаться, я объявляю объетом этого шаблона с параметром нужного класса. Инициализировав его методом SetMovableData в обработчике OnSize вызываю метод MoveControl с параметрами самого OnSize. Для плавности добавляю таймер. Немного математики при инициализации и больше никаких проблем.

P.S. думаю в комментах всё описано.


--------------------
user posted image
PM Jabber   Вверх
voov
Дата 31.8.2009, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Патамушта мы пилоты
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 29.11.2007

Репутация: 8
Всего: 8



Цитата(Cheloveck @  26.8.2009,  10:28 Найти цитируемый пост)
Для плавности добавляю таймер

а можно об этом подробнее?
PM MAIL   Вверх
Cheloveck
Дата 31.8.2009, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Цитата(voov @  31.8.2009,  14:32 Найти цитируемый пост)
а можно об этом подробнее? 

Можно
Код

afx_msg void MainWnd::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);

    width_ = cx;
    height_ = cy;
    if( !sizeTimerID_ )
        sizeTimerID_ = SetTimer(ID_TIMER_RESIZE, 100, NULL);
}

void MainWnd::MoveControls(int widthWnd, int heightWnd)
{
    CWnd *focusWnd = GetFocus(); // Сохраняем указатель на окно с фокусом.
    pEdit_Height_->MoveControl(widthWnd, heightWnd);
    pTreeView_RegionList_->MoveControl(widthWnd, heightWnd);
    pStatic_Arrow_->MoveControl(widthWnd, heightWnd);
    //...................
    if(::IsWindow(focusWnd->GetSafeHwnd()))
        focusWnd->SetFocus(); // Возвращаем фокус назад.
}

afx_msg void MainWnd::OnTimer(UINT_PTR nIDEvent)
{
    if(nIDEvent == sizeTimerID_)
    {
        static int width = 0; // Тут вместо статиков можно и члены класса. 
        static int height = 0; // Просто у меня такой класс только один.
        if(width == width_ && height == height_) // Додвигали до конца.
        {
            KillTimer(sizeTimerID_);
            sizeTimerID_ = 0;
        }
        else // Двигаем дальше.
        {
            MoveControls(width_, height_);
            width = width_;
            height = height_;
        }
    }
}

Примерно так. width_ и sizeTimerId - члены класса.


--------------------
user posted image
PM Jabber   Вверх
voov
Дата 31.8.2009, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Патамушта мы пилоты
**


Профиль
Группа: Участник
Сообщений: 460
Регистрация: 29.11.2007

Репутация: 8
Всего: 8



ага, т.е. это устранит мерцание при активном растягивании
PM MAIL   Вверх
Cheloveck
Дата 31.8.2009, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1578
Регистрация: 26.7.2008
Где: Тула

Репутация: нет
Всего: 32



Цитата(voov @  31.8.2009,  19:50 Найти цитируемый пост)
ага, т.е. это устранит мерцание при активном растягивании 

не совсем устранит, но заметно снизит.


--------------------
user posted image
PM Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0542 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.