Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Синхронизация размеров окон (www.firststeps.ru)

3.6K
08 июля 2003 года
void_123
11 / / 30.06.2003
Два вопроса. Подскажите, плз.

Задача:
Есть приложение документ-вид (CTestDoc-CTestView).
Приложение аналогичное тому, что описано на странице
http://www.firststeps.ru/mfc/steps/r.php?320.
Т.е.
- в левой части главной рамки окна приложения СLeftView: public CView
- затем правее сплиттер
- затем в правой части окна CTestView: public CDialView

CDialView умеет рисовать диалоговые панели (панель),
контролы которой имеют "anchors", т.е. меняют
размеры и положение при изменении диалогов,
занимающтх клиентскую часть CTestView.


***Вопрос 1. Как ограничить изменение главного окна
по максимально и минимально допустимым (константы)
размерам диалоговой панели?
Желательно, чтобы при этом, например, изменялся размер CLeftView,
если размер диалога достиг предельного размера, а мы всё
тащим и тащим ЛЕВУЮ границу окна приложения, изменяя его
ШИРИНУ. Другими словами, необходимо сделать так, чтобы
диалоговая панель не "ломалась" окончательно, сохраняя
хоть сколь нибудь приличный вид.

Наверное, можно обработать WM_GETMINMAXINFO главной
рамки приложения (CMainFrame). Замечу, что для данного примера
WM_GETMINMAXINFO всех child Wnd (СLeftView, CTestView и т.д)
не перехватывается. Так что альтернативы
перехвата WM_GETMINMAXINFO кроме как у CMainFrame - нет,
IMHO.
Тогда возникает вопрос, у меня, как у начинающего MFC-киста:
как получить из функции обработки WM_GETMINMAXINFO CMainFrame
указатель или хэндл конкретного "клиентского" объекта,
например, окна СLeftView, или CTestView.
Эсли есть другие идеи в части синхронизации размеров
окон - подскажите,плз.

*** Вопрос 2. При перерисовке диалоговой панели
(при изменении размеров главного окна приложения) возникают
очень неприятные эффекты. Перерисовка происходит "полосками".
Видно, как чередуются белые и серые части окон при перерисовке.
Как "моргание" и рябь такая, что ли.
Надеюсь Вы поняли. Такое ощущение, что перерисовывается главное
окно приложения и все дочерние окна. Как этого избежать?
Надо сказать, что если приложение dialog based,
то таких эффектов нет. Всё перерисовывается красиво и незаметно
при изменении размеров диалога.
3.6K
11 июля 2003 года
void_123
11 / / 30.06.2003
Отвечаю сам себе и тем, кто мучается с аналогичной проблемой. Благодарности тем, кто подсказал, как и что делать.

***Вопрос 1. Как ограничить изменение главного окна
по максимально и минимально допустимым (константы)
размерам диалоговой панели? .....

В класс главной рамки добавляем:

class CMainFrame : public CFrameWnd
{

protected:
CPoint MinLeftSize; // минимальный размер левой панели
CPoint MinRightSize; // минимальный размер правой панели
public:
CMinSplitterWnd m_wndSplitter; // Что это, см. далее
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
afx_msg void OnSize(UINT nType, int cx, int cy);
};

И делаем соответствующие определения для методов CMainFrame:

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

ON_WM_GETMINMAXINFO()
ON_WM_SIZE()
END_MESSAGE_MAP()
//-----------------------------------------------
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
{
MinLeftSize.SetPoint(10,0);
MinRightSize.SetPoint(200,500);

m_wndSplitter.CreateStatic(this,1,2); // 1 ряд из 2 колонок
m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CLeftView), CSize(150,0),pContext);
m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CGkmView), CSize(400,0),pContext);

m_wndSplitter.SetColumnInfo(0,150 , MinLeftSize.x);
m_wndSplitter.SetColumnInfo(1,400 , MinRightSize.x);

m_wndSplitter.Created = true;

return TRUE;
}
//-----------------------------------------------
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// Для того, чтобы не ломать диалог в правом вью (не вью!!!).
lpMMI->ptMinTrackSize = CPoint(MinLeftSize.x + MinRightSize.x + m_wndSplitter.GetX(), MinRightSize.y);
CFrameWnd::OnGetMinMaxInfo(lpMMI);
}
//-----------------------------------------------
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
// Для того, динамически уменьшать левый вью, когда размеры диалога станут предельными (т.е. MinRightSize.x)
CFrameWnd::OnSize(nType, cx, cy);

if (!m_wndSplitter.Created) return;

CRect RightRect;
((CWnd*) m_wndSplitter.GetPane(0, 1))->GetClientRect( RightRect );

if (RightRect.Width() <= MinRightSize.x)
{
// здесь m_wndSplitter.GetX(), см. далее определение сплиттера
int LeftWidth = cx - MinRightSize.x - m_wndSplitter.GetX();
// здесь с LeftWidht возможно умнее. Кто напишет – ну и хорошо. А работает и так.
if (LeftWidth < 0) LeftWidth = 0;

m_wndSplitter.SetColumnInfo(0,LeftWidth, MinLeftSize.x);
m_wndSplitter.SetColumnInfo(1, MinRightSize.x + 1, MinRightSize.x);
m_wndSplitter.RecalcLayout();
}
}

Далее определим сплиттер:

class CMinSplitterWnd : public CSplitterWnd
{
public:

bool Created;
int GetX(void) { return (m_cxSplitter + m_cxBorder*2); }

};
И всё… Арбайтен. Здесь надо добавить, что сплиттер можно существенно улучшить (и без лишних наворотов), как, например, “Minimum size splitter” на странице http://www.ishodnikov.net/visualc/splitter.php.
Что я наглым образом и сделал, в дополнение к тому, что нарисовал выше.

**************************
*** Вопрос 2. При перерисовке диалоговой панели
(при изменении размеров главного окна приложения) возникают
очень неприятные эффекты
Как мне правильно подсказали, вылечилось за счёт обработки WM_ERASEBKGND для правого вию CTestView удивительно легко!!!:

BEGIN_MESSAGE_MAP(CTestView, CDialView)

ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
//-----------------------------------------
BOOL CTestView::OnEraseBkgnd(CDC* pDC)
{
return 0;
}

Если есть более простые идеи, писните, плз.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог