HWND ЛЕВОЕилиВЕРХНЕЕокно
HWND ПРАВОЕилиНИЖНЕЕокно
BYTE Выравнивание
Как разделить окно на 2 части (Explorer Style)
Пытаюсь найти метод, которым можно создать окно, состоящее из двух панелей, подобно тому, как это сделано в Проводнике. То есть, чтобы окно состояло из двух контролов (Tree и List, например), разделенных полосой, которую пользователь может таскать мышью.
Буду благодарен за объяснение или ссылку.
P.S. Использование готового шаблона MFC мне не подходит, хочу сделать или только с помощью Win32 API или с лишь минимальным привлечением дополнительных библиотек.
А на чем пишешь? Я для себя писал небольшой класс на эту тему (годится для только вертикального разделения), если на паскале - могу юнит дать если на си или еще чем то длл соберу, а сообщений там немного так что и сам заголовки напишешь.
Я в C++.
Вообще меня интересует сам принцип, порядок действий - что нужно для этого, какие функции API и в каком порядке вызываются, какие структуры и как задействуются.
Готовые же классы есть и в Visual C++ MFC, но для понимания происходящего нужно перелопатить огромный объем исходного кода, пытаясь выделить в нем только необходимое.
По той же причине не подходит и собранный dll - меня интересует теория, принцип, чтобы делать такие вещи самостоятельно.
Вообщем, если не трудно, расскажи, плиз, или отошли к ресурсу который это описывает. Или покажи этот код на паскале - думаю, в обращениях к api я разберусь.
Создается дополнительное окно - граница, при перетаскивании которго одно из окон увеличивается, а другое соответственно уменьшается.
Код:
Из процедур использую
SetWindowPos, GetWindowRect, GetClientRect, OffsetRect, GetCursorPos, ScreenToClient, SetCapture, ReleaseCapture + рисование + события миши.
При изменении размера родитель посылает этому окну сообщение WM_USER, после чего происходит (пере)позиционирование для "ЛЕВОЕилиВЕРХНЕЕокно" и "ПРАВОЕилиНИЖНЕЕокно".
те мой метод может разделить окно только на две части, каждую их которых можно разделить еще на две...
Конечно, в Дельфи и в Билдере есть целый менеджер для этих целей, которому можно только позавидовать.
Код дам чуть-чуть позже, решил доделать таки до конца.
Код:
// сбрасываем признак захвата мыши
Capture = FALSE;
// устанавливаем положение границы областей поумолчанию
BoundPosition = 256;
//*************************************************************
//**
//** Обработчик изменения размеров окна
//**
//*************************************************************
void TFrame::Size(int width, int height)
{
// контролируем границу областей
if( BoundPosition > (width-(width/5)) ) BoundPosition = width - (width / 5);
if( BoundPosition < (width/5) ) BoundPosition = width / 5;
// устанавливаем новые размеры
if( pTreeWindow ) pTreeWindow->SetPosition(0,96,BoundPosition,height-32);
if( pInfoWindow ) pInfoWindow->SetPosition(BoundPosition+2,96,width,height-32);
}
//*************************************************************
//**
//** Перемещение мыши
//**
//*************************************************************
void TFrame::MouseMove(short x, short y)
{
//****
RECT client;
// если мышь незахвачена
if( !Capture )
{
// устанавливаем вид курсора в зависимости от положения в окне
if( y <= 96 ) SetCursor(hArrowCursor);
else SetCursor(hSizeCursor);
}
// мышь захвачена
else
{
// устанавливаем курсор изменения размеров
SetCursor(hSizeCursor);
// определяем размеры окна
GetClientRect(hWindow,&client);
// контролируем границы областей
if( x < ((client.right-client.left)/5) ) x = (client.right-client.left)/5;
if( x > ((client.right-client.left)-((client.right-client.left)/5)) ) x = (client.right-client.left)-((client.right-client.left)/5);
// сохраняем новое положение границы
BoundPosition = x;
// изменяем положение областей
Size(client.right-client.left,client.bottom-client.top);
}
}
//*************************************************************
//**
//** Нажата кнопка мыши
//**
//*************************************************************
void TFrame::MouseDown(short x, short y)
{
// если мышь находится на границе
if( y > 64 )
{
// и мышь до этого небыла захвачена
if( !Capture )
{
// захватываем мышь
SetCapture(hWindow);
// выставляем признак захвата
Capture = TRUE;
}
}
}
//*************************************************************
//**
//** Отпущена кнопка мыши
//**
//*************************************************************
void TFrame::MouseUp(short x, short y)
{
// освобождаем мышь
ReleaseCapture();
// сбрасываем признак захвата
Capture = FALSE;
}
Capture = FALSE;
// устанавливаем положение границы областей поумолчанию
BoundPosition = 256;
//*************************************************************
//**
//** Обработчик изменения размеров окна
//**
//*************************************************************
void TFrame::Size(int width, int height)
{
// контролируем границу областей
if( BoundPosition > (width-(width/5)) ) BoundPosition = width - (width / 5);
if( BoundPosition < (width/5) ) BoundPosition = width / 5;
// устанавливаем новые размеры
if( pTreeWindow ) pTreeWindow->SetPosition(0,96,BoundPosition,height-32);
if( pInfoWindow ) pInfoWindow->SetPosition(BoundPosition+2,96,width,height-32);
}
//*************************************************************
//**
//** Перемещение мыши
//**
//*************************************************************
void TFrame::MouseMove(short x, short y)
{
//****
RECT client;
// если мышь незахвачена
if( !Capture )
{
// устанавливаем вид курсора в зависимости от положения в окне
if( y <= 96 ) SetCursor(hArrowCursor);
else SetCursor(hSizeCursor);
}
// мышь захвачена
else
{
// устанавливаем курсор изменения размеров
SetCursor(hSizeCursor);
// определяем размеры окна
GetClientRect(hWindow,&client);
// контролируем границы областей
if( x < ((client.right-client.left)/5) ) x = (client.right-client.left)/5;
if( x > ((client.right-client.left)-((client.right-client.left)/5)) ) x = (client.right-client.left)-((client.right-client.left)/5);
// сохраняем новое положение границы
BoundPosition = x;
// изменяем положение областей
Size(client.right-client.left,client.bottom-client.top);
}
}
//*************************************************************
//**
//** Нажата кнопка мыши
//**
//*************************************************************
void TFrame::MouseDown(short x, short y)
{
// если мышь находится на границе
if( y > 64 )
{
// и мышь до этого небыла захвачена
if( !Capture )
{
// захватываем мышь
SetCapture(hWindow);
// выставляем признак захвата
Capture = TRUE;
}
}
}
//*************************************************************
//**
//** Отпущена кнопка мыши
//**
//*************************************************************
void TFrame::MouseUp(short x, short y)
{
// освобождаем мышь
ReleaseCapture();
// сбрасываем признак захвата
Capture = FALSE;
}
Как это работает:
1. в основном окне создается два окна - левое и правое - так чтобы между ними было расстояние несколько точек (в данном случае 2).
2. BoundPosition - это положение границы между ними. нужна для того чтобы контролировать выход за границы основного окна.
3. контролируется нажатие мыши в основном окне, если это граница областей - захватываем мышь если она не захвачена.
4. контролируется отпускание мыши - освобождаем мышь.
5. контролируется перемещение мыши - если мышь захвачена менется положение окон, в противном случае - ничего, разве что курсор меняется если это граница областей...
P.S. Я в начале считал что есть некие специальные средства для этой цели. Все оказалось много проще после ваших объяснений.