Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема со стилем окна в MFC, Некорректное отображение окна 
V
    Опции темы
KirillV007
Дата 16.10.2010, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



user posted image

Здравствуйте, у меня такая проблема:
Если я делаю размеры окна изменяемыми в методе PreCreateWindow класса CMainFrame, то пустого места игровым полем и границами окна - нет, если делаю размер неизменяемым, то появляется такой баг(пустое место), подскажите в чем может быть проблема?(SDI приложение, компилятор- VC2010)

Вот код PreCreateWindow:
Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWndEx::PreCreateWindow(cs) )
        return FALSE;

    // Call the base-class version
   if( !CFrameWnd::PreCreateWindow(cs) )
      return FALSE;
    
    cs.style = WS_OVERLAPPED | WS_SYSMENU | WS_BORDER;


    // TODO: изменить класс Window или стили посредством изменения
    //  CREATESTRUCT cs
    // Size the window to 1/3 screen size and center it 
    cs.cy = ::GetSystemMetrics(SM_CYSCREEN)/3; 
    cs.cx = ::GetSystemMetrics(SM_CXSCREEN)/3; 
    cs.y = ((226 * 3) - 226) / 2;
    cs.x = ((226 * 3) - 226) / 2;



    return TRUE;
}


Это сообщение отредактировал(а) KirillV007 - 16.10.2010, 22:29
PM MAIL   Вверх
Earnest
Дата 18.10.2010, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



При создании окна указывается его полный размер, включая рамку, заголовок и т.д. Resize-рамка имеет ненулевую толщину, т.е. ее размер нужно учитывать. Удобнее всего это делать с помощью функции AdjustWindowRect. Т.е. задаешь нужный размер клиентской области и стиль окна, и получаешь размер полного окна.


--------------------
...
PM   Вверх
KirillV007
Дата 18.10.2010, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Earnest @ 18.10.2010,  09:38)
При создании окна указывается его полный размер, включая рамку, заголовок и т.д. Resize-рамка имеет ненулевую толщину, т.е. ее размер нужно учитывать. Удобнее всего это делать с помощью функции AdjustWindowRect. Т.е. задаешь нужный размер клиентской области и стиль окна, и получаешь размер полного окна.

А нужно тогда в таком случии както связать PreCreateWindow и AdjustWindowRec или вызывать AdjustWindowRec отдельно ? И еще я читал что аналог этой функции для MFC - это CalcWindowRect, может ее стоит использовать внутри PreCreateWindow ? Как вы думаете?
PM MAIL   Вверх
Emura
Дата 18.10.2010, 18:58 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



имхо, если есть возможность, лучше использовать winapi средства. mfc всего лишь оболочка над winapi.

KirillV007, формулировка проблемы не внятна "пустого места игровым полем и границами окна - нет"...
в чем загвоздка не понятно. smile 
PM   Вверх
Earnest
Дата 22.10.2010, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(KirillV007 @  18.10.2010,  15:39 Найти цитируемый пост)
А нужно тогда в таком случии както связать PreCreateWindow и AdjustWindowRec или вызывать AdjustWindowRec отдельно ?

PreCreateWindow затем и служит, чтобы поправить параметры, передаваемые при создании окна. Поэтому логично вызвать AdjustWindowRec именно здесь.
Цитата(KirillV007 @  18.10.2010,  15:39 Найти цитируемый пост)
И еще я читал что аналог этой функции для MFC - это CalcWindowRect, может ее стоит использовать внутри PreCreateWindow ? 

Это не совсем аналог. CalcWindowRect функция виртуальная, зависящая от конкретного окна, а Adjust - нет. Теоретически можно использовать и ее, но по-моему эта функция предполагает, что окно уже создано (по крайней мере некоторые ее варианты). Так что вызывать ее из PreCreate некорректно. 



--------------------
...
PM   Вверх
KirillV007
Дата 31.10.2010, 10:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Пытаюсь использовать вот так:
Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWndEx::PreCreateWindow(cs) )
        return FALSE;

  


    cs.style =WS_OVERLAPPEDWINDOW & WS_OVERLAPPED |  WS_SYSMENU | WS_BORDER ;

    // TODO: изменить класс Window или стили посредством изменения
    //  CREATESTRUCT cs
    //размер по горизонтали
    cs.cx = 226;
    //размер по вертикали
    cs.cy = 226+
    (::GetSystemMetrics(SM_CYMENU)+::GetSystemMetrics(SM_CYCAPTION));



int wndPosX = cs.cx;  
int wndPosY = cs.cy;  
int wndWidth = 216; 
int wndHeight = 216;  


 
RECT rc;  
rc.left = wndPosX;  
rc.top = wndPosY;  
rc.right = wndPosX + wndWidth;  
rc.bottom = wndPosY + wndHeight;
::AdjustWindowRect(&rc, cs.style, true); 



    return TRUE;
}


но такое ощущение, что код применения функции AdjustWindowRect вообще игнорируется, получается такая же картинка)
PM MAIL   Вверх
Earnest
Дата 1.11.2010, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(KirillV007 @  31.10.2010,  11:50 Найти цитируемый пост)
но такое ощущение, что код применения функции AdjustWindowRect вообще игнорируется, получается такая же картинка) 

Это ты его игнорируешь: получаешь результат, а потом не используешь. rc - автоматическая переменная. Ну изменил ты ее. И что?
Окно-то будет создано на основе данных cs. 



--------------------
...
PM   Вверх
KirillV007
Дата 1.11.2010, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Earnest @ 1.11.2010,  08:40)
Цитата(KirillV007 @  31.10.2010,  11:50 Найти цитируемый пост)
но такое ощущение, что код применения функции AdjustWindowRect вообще игнорируется, получается такая же картинка) 

Это ты его игнорируешь: получаешь результат, а потом не используешь. rc - автоматическая переменная. Ну изменил ты ее. И что?
Окно-то будет создано на основе данных cs.

Спасибо вам за помощь и пояснения, я кажется додумался почти до сути и у меня 3 ключевых вопроса:

1. Что я должен прописывать в структуре LPRect в данном случии, которая идет как параметр функции AdjustWindowRect() - ничего или же приравнивать параметры главного окна?

2. Я должен применять функцию AdjustWindowRect() во время приравнивания параметров cx к размерам окна или же както иначе?

3. Возможно стоит применить AdjustWindowRect() в заголовочном файле отвечающем за вывод именно игрового поля, там тоже есть PreCreateWindow ?

код который написал на основе ваших предыдущих комментариев:

Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWndEx::PreCreateWindow(cs) )
        return FALSE;

int wndPosX = ((226 * 3) - 226) / 2;  
int wndPosY = ((226 * 3) - 226) / 2;  
int wndWidth = 226; 
int wndHeight = 226;  

CRect rc;
rc.left = wndPosX;  
rc.top = wndPosY;  
rc.right = wndPosX + wndWidth;  
rc.bottom = wndPosY + wndHeight;

        cs.style =WS_OVERLAPPEDWINDOW & WS_OVERLAPPED /*& !WS_THICKFRAME*/ ;

    // TODO: изменить класс Window или стили посредством изменения
    //  CREATESTRUCT cs
    //размер по горизонтали
    cs.cx =AdjustWindowRect(rc, cs.style, true);
    //размер по вертикали
    cs.cy =AdjustWindowRect(rc, cs.style, true); 
    cs.y = wndPosY;
    cs.x = wndPosX;


    return TRUE;
}



Это сообщение отредактировал(а) KirillV007 - 2.11.2010, 00:00
PM MAIL   Вверх
Earnest
Дата 2.11.2010, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Прежде всего ты должен включить голову.
1) Ну как это ничего? Ты бы прочитал в MSDN про параметры AdjusWindowRect и подумал хорошенько. На основании чего функция тебе посчитает правильный размер окна? Думаешь, у нее прямая связь с космосом? Все элементарно: ты задаешь желаемый размер клиентского поля и стили окна, а функция вычисляет размер полного окна с учетом всех рамок и т.д. Все это элементарно сделать ручками - просто добавляешь в зависимости от стиля размер меню, толщину рамки и прочее. Но есть готовая функция.
2) Структура CREATESTRUCT содержит параметры, в том числе размер, на основании которых и создается окно. Назначение PreCreateWindow именно в том и состоит, чтобы эти параметры подстроить как тебе нужно.
3) PreCreateWindow можно переопределить у всех MFC-окон, она виртуальная. Однако размер игрового поля определяется именно клиентской областью рамки, поэтому удобнее делать именно там. Ибо сначала создается рамка, а потом в ней вид.

Код не смотрела.


--------------------
...
PM   Вверх
KirillV007
Дата 3.11.2010, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Вот так реализовал и все равно не пашет, как думаешь, в чем загвоздка, вроде все по логике:
1)есть структура с данными для adjustwindowrect - rc
2)передаю ей данные
3)приравниваю параметры cs к результатам работы этой функции

код:
Код

int wndPosX = 0;//стартовая позиция отрисовки окна для x  
int wndPosY = 0;//стартовая позиция отрисовки окна для y  
int wndWidth = 216; // размер клиентской части(только игрового поля) - ширина 
int wndHeight = 216; // размер клиентской части(только игрового поля) - высота 

CRect rc; // передача параметров выше в структуру LPRECT
rc.left = wndPosX;  
rc.top = wndPosY;  
rc.right = wndPosX + wndWidth;  
rc.bottom = wndPosY + wndHeight;


    cs.style =WS_OVERLAPPED | WS_SYSMENU | WS_BORDER; // определение стилей таким образом, чтобы размеры окна не менялись
    ::AdjustWindowRect(rc, cs.style, true);
    // TODO: изменить класс Window или стили посредством изменения
    //  CREATESTRUCT cs
     cs.y = wndPosY;
     cs.x = wndPosX;
    //размер по горизонтали
      cs.cx =rc.right - rc.left;
    //размер по вертикали
      cs.cy =rc.bottom - rc.top;


пробовал и это далее делать
Код

::SetWindowPos(wndTop, wndTop, cs.x, cs.y, cs.cx, cs.cy, SWP_DRAWFRAME);


тоже не работает, может вообще не там копаю)

Это сообщение отредактировал(а) KirillV007 - 3.11.2010, 15:36
PM MAIL   Вверх
Earnest
Дата 4.11.2010, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(KirillV007 @  3.11.2010,  16:35 Найти цитируемый пост)
тоже не работает, может вообще не там копаю)

Может и не там, кто тебя знает.
Заполняешь вроде правильно. Разве что в качестве стиля лучше передавать прямо значение из cs, оно как-то логичнее.
Проверь отладчиком, какие размеры получаются в cs. И какое в результате получается окно (это Спаем посмотреть удобно). Если размеры соответствуют, но окно все равно выглядит не так, как нужно, это одно дело. А если размеры отличаются - совершенно другое.
Кстати, можно еще попробовать использовать AdjustWindowRectEx, она позволяет учесть и расширенный стиль.



--------------------
...
PM   Вверх
KirillV007
Дата 7.11.2010, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Размеры клиенсткой части я перехватил spy++, при изменяемом размере окна, она 220x220 (собственно что мне и надо, только чтобы окно нельзя было растягивать), общий размер окна не меняется 236x278, а вот клиенсткая часть становится 230x230, я пробовал задавать параметры из spy++ в структуру rc, при изменяемых размерах:
Код

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
     if( !CFrameWndEx::PreCreateWindow(cs) )
        return FALSE;
CRect rc; // передача параметров выше в структуру LPRECT
rc.left = 8;  
rc.top = 50;  
rc.right =228;  
rc.bottom = 270;

    cs.style =WS_OVERLAPPED | WS_SYSMENU | WS_BORDER; // задание стилей таким образом, чтобы размеры окна не менялись
    ::AdjustWindowRect(rc, WS_OVERLAPPED | WS_SYSMENU | WS_BORDER, true );
    // TODO: изменить класс Window или стили посредством изменения
    //  CREATESTRUCT cs
    cs.y = 8;
    cs.x = 50;
    //размер по горизонтали
      cs.cx =rc.right - rc.left;
    //размер по вертикали
      cs.cy =rc.bottom - rc.top;
      return CFrameWnd::PreCreateWindow(cs);


    return TRUE;
}
 
но всеравно окно получается с клиенсткой частью 230x230, такое ощущение что любые параметры окна, кроме стиля, из precreatewindow игнорируются)
PM MAIL   Вверх
Earnest
Дата 8.11.2010, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(KirillV007 @  7.11.2010,  15:03 Найти цитируемый пост)
но всеравно окно получается с клиенсткой частью 230x230, такое ощущение что любые параметры окна, кроме стиля, из precreatewindow игнорируются) 

Опять у тебя ощущения...
Если окно имеет неправильный размер, значит этот размер кто-то устанавливает. В чем проблема? Сделай обработчик WM_SIZE И посмотри отладчиком, откуда идет вызов с неправильными размерами. Имей в виду, WM_SIZE при создании приходит несколько раз, поэтому посмотри все и выясни что откуда. 

AdjustWindowRectEx не пробовал?



--------------------
...
PM   Вверх
KirillV007
Дата 8.11.2010, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Earnest @  8.11.2010,  08:58 Найти цитируемый пост)
AdjustWindowRectEx не пробовал?


Да пробовал, все равно также, даже если я убираю из CMainFrame::PreCreateWindow все, кроме задания стиля или вообще все, то размеры поля устанавливаются 230 на 230, может проблема в том, что я задаю не в тех единицах? я читал про logical units начиная с 2008ой версии visual studio, или же окно создается по какомуто шаблону, где вызвать WM_SIZE, честно говоря не понял) я пробовал добавить его в карту сообщений, а где писать его обработчик не пойму, документацию читал)

либо, если ты знаешь - как ограничить размеры окна, если я оставлю его растягиваемым, может просто както можно запретить растягивать больше и меньше размеров, которые я задаю...) функция minmax поможет?
PM MAIL   Вверх
Earnest
Дата 8.11.2010, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Плохо ты читал MSDN.
WM_SIZE - это сообщение, перехватывает его обработчик OnSize, добавлять в карту сообщений - ON_WM_SIZE. 
Где писать обработчик - не принципиально. Там же, где другой код. 
Logical units здесь не при чем, это же не диалог.
Размеры окна ограничить тоже можно - обрабатывать сообщение WM_GETMINMAXINFO, но это тебе не поможет. По-моему, это работает только при растяжении-сжатии, а не при создании.
Не знаю, насколько это влияет, но клиентскую область лучше задавать с нуля, т.е. так:
CRect rc (0, 0, 220, 220); 
Это прямоугольник нужно передать в AdjustWindowRect, причем лучше все-таки использовать Ex, чтобы учесть расширенный стиль - вдруг он тоже влияет на рамку?

AdjustWindowRectEx (rc, cs.style, true, cs.dwExStyle);

Что возвращается в качестве размера окна?
Реальное окно эти размеры имеет? А стиль? А клиентские размеры какие?
Кажется, я это уже писала, но ответов так и нет. Где-то нестыковка, вот ее и надо искать. Систематически, а не методом тыка.




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


 




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


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

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