Класс CSkinBaseDialog
От: 2Los  
Дата: 28.02.02 22:25
Оценка: 160 (7)
Статья:
Класс CSkinBaseDialog
Автор(ы): 2Los
Дата: 01.03.2002


Авторы:
2Los

Аннотация:
Как известно, окна в Windows квадратные. И в принципе этого достаточно для большинства приложений. Если это, например, файл-менеджер, то очень даже неплохо, что он квадратный. Однако иногда хочется, чтобы программа выглядела не как все. Классическим примером могут служить WinAmp или Window Media Player, а также многие autoran'ы для CD дисков. Отличительной особенностью этих программ является то, что все они обладают окнами произвольной формы, с опять же произвольным фоновым изображением, а плэйеры к тому же могут менять свой внешний вид.

У разработчика подобного окна выбор средств не богатый: это функция SetWindowRgn() — устанавливающая регион, занимаемый окном и обработчик события WM_ERASEBKGND, в котором следует поместить код, выводящий фоновую картинку в окно. И если окно не меняет свой размер, этого достаточно, иначе придется потрудиться, чтобы корректно отображать фон и пересчитывать регион окна. Если вам это занятие не по душе, то предлагаю воспользоваться моим новым MFC-классом диалога CSkinBaseDialog, который возьмет всю эту работу на себя.
Баг обнаружен.
От: Saruman Россия none
Дата: 25.03.03 12:12
Оценка:
Обнаружен баг в функции
POSITION CSkinBaseDialog::FindMoveInfo(int nIDEvent)
Выражается он в том что если запускаешь движение части диалога, то все запущенные таймеры диалога затыкаются. Предлагаю другой вариант тела функции:
POSITION CSkinBaseDialog::FindMoveInfo(int nIDEvent)
{
POSITION result=NULL, pos=m_lstActiveMoves.GetHeadPosition();
CMoveInfo* pMI;
while(pos != NULL)
{
result=pos;
pMI=m_lstActiveMoves.GetNext(pos);
if(pMI->m_nIDEvent==nIDEvent) return result;
}
return NULL;
}
Типа того что как бы...
Контролы на движушихся частях диалога
От: Saruman Россия none
Дата: 25.03.03 04:23
Оценка:
2Los, а не могли бы вы описать каким образом добавлять контролы на выдвигающуюся часть диалога? Что-то я совсем сообразить не могу как это сделать.
Типа того что как бы...
Важное дополнение!
От: Saruman Россия none
Дата: 20.03.03 11:38
Оценка:
Для того чтобы контролы правильно отрисовывались на бакграунде диалога, необходимо при инициализации сначала делать все вызовы AddSkinDIB, а уже потом вызавать AddOwnerDrawControl для каждого контрола. Если же вызвать AddOwnerDrawControl ДО AddSkinDIB может произойти ситуация при которой уже отрисованый контрол перекроется изображением фона.
P.S. Целый день мучался, пока понял в чем дело :(
Типа того что как бы...
OwnerDraw Controls
От: Saruman Россия none
Дата: 19.03.03 09:02
Оценка:
В статье сказано, что для синхронной отрисовки контролов нужно использовать функцию AddOwnerDrawControl. Так же в классе контрола должна быть реализована функция SkinDraw.
Я сделал свой цветной CStatic, но почему-то при отрисовке диалога текст в статике сначала удаляется. Не пойму в чем дело? Вроде и функция SkinDraw вызывается вовремя, но после OnEraseBkgnd для диалога изображения контрола на бакграунде нет. Оно появляется уже после OnPaint'а для контрола. Может кто подскажет почему так происходит?
Типа того что как бы...
Skins
От: Hobos  
Дата: 08.10.02 07:58
Оценка:
Господа, если у кого есть какие-нибудь скины в таком формате и вам не жалко ими поделиться ( для некоммерческого, разумеется, использования), не могли бы ими, собственно, поделиться? Из меня художник, как выяснилось, никакой, и дцатая подряд попытка изобразить что-нибудь пристойное не увенчалась успехом. Заранее спасибо!!
Небольшой - не баг, а просто недочёт!
От: Gambler  
Дата: 06.04.02 02:08
Оценка:
Что бы кнопки произвольной формы рисовались правильно добавте в
CSkinBaseButton.h

в метод void DrawButton(CDC* pDC, CRect rc, int iButton)

в самом конце вот такой код.

Удачи всем.


//.......................................
HRGN hrgn = CreateRectRgn(0,0,0,0);
GetWindowRgn(hrgn);
CRgn *pRgn = CRgn::FromHandle(hrgn);
pDC->SelectClipRgn(pRgn);
//.......................................

m_dibButtonStates.Draw(pDC, rc.TopLeft(), rc.Size(), CPoint(m_szButton.cx*iButton, 0), CSize(m_szButton.cx, m_szButton.cy));
-------------------------------------------------------------------

Вызывает презедент к себе коров и говорит:
— Ну, что будем сдавать, молоко или мясо?
(с) Г. Явлинский TV6 — Герой дня (18.04.2002)
Возможная проблема!
От: RadSal  
Дата: 24.03.02 19:21
Оценка:
Почему, когда делаешь toggle-button, ее положение фиксируется при нажатии на кнопку мыши, а вот метод, связанный с этой кнопкой выполняется только при отпускании. Поэтому, если нажать на такую кнопку и не отпуская кнопки мыши вынести курсор за ее пределы, и только там отпустить, то получим нажатую кнопу, а вот метод, с ней связанный не выполнится.
А вообще, огромное спасибо за этот класс. Очень помог!
Eto zdorovo! Tolko v kakih Windah eto zarabotaet?
От: Michel http://www.tatianafineart.com
Дата: 14.03.02 05:49
Оценка:
Ideya prosto zamechatel'naya. Pravda pervaya zhe popytka zapustit' demostracionnoe prilozhenie v Win95 zakonchilos' neudachej :(( Est' li u kogo idei na etu temu???
P.S. Izveni za latinskij shrift, no ya ne doma a na rabote vybora netu:(
Вопрос по теме!
От: RadSal  
Дата: 06.03.02 19:22
Оценка:
Где конкретно можно найти остальные элементы управления, которые хорошо бы смотрелись с этими окнами?
Прикольно :) , но Обидно
От: OlegO Россия http://www.mediachase.ru
Дата: 01.03.02 22:25
Оценка:
Что убирается контекстное меню и иконка в Taskbare. Из-за этого окно
начинает вести себя, если говорить чесно ненормально.
Хотя прекрасно понимаю все проблемы, с которыми придется столкнуться
в противном случае.
С уважением, OlegO.
Re: Баг обнаружен.
От: 2Los  
Дата: 25.03.03 22:44
Оценка:
Теперь твоя очередь объяснять, в чем тут дело. А то я никак не могу уловить разницу с текущим вариантом тела функции FindMoveInfo :)
Re: Контролы на движушихся частях диалога
От: 2Los  
Дата: 25.03.03 22:42
Оценка:
Все дело в том, что контролы не добавляются на выдвигающуюся часть. Они добавляются в диалог, как и другие контролы, а потом просто выдвигаются вместе с выдвигающейся (небольшая тавтология) частью.

В демо-проекте, выдвижение инициируется нажатием кнопки, обработчик которой выглядит
следующим образом.

void CSkinDialogDlg::OnButton()
{
BOOL s_bMoveOut=m_button.GetCheck();

ARR_BK_PARTS ar; //массив
ar.Add(GetAt(10)); //выдвигающая часть диалога
ar.Add(GetAt(11)); //кнопка

//Выдвигаем все, что есть в массиве ar. В том числе кнопки и картинки.
StartMoveBkParts(ar, CSize(0, s_bMoveOut ? 90 : -90), 5, 101);
}

Но это был простой пример, когда выдвигающаяся кнопка всегда видна на экране. Допустим необходимо, чтобы контрол первоначально был скрыт и потом плавно "выезжал". Сделать это будет посложней и в текущей версии CSkinBaseDialog очень заморочено, но тем не менее возможны два варианта:

Вариант 1. Контрол не поддерживает функцию SkinDraw (см. статью выше). Тогда о плавном выдвижении можно забыть. В этом случае, контрол сначала скрыт, а после того, как выдвигающаяся часть "вылезет" наружу, его нужно вручную показать вызовом ShowWindow(SW_SHOW) в переопределенной функции OnEndMoveBkParts. В обратном случае, когда выдвигающаяся часть начинает "заползать" обратно, этот контрол нужно скрыть вызовом ShowWindow(SW_HIDE) в переопределенной функции OnBeginMoveBkParts.

Вариант 2. Контрол поддерживает функцию SkinDraw. В этом случае можно организовать его плавное выдвижение. Для этого нужно при добавлении контрола указать перекрывающие его картинки.

//добавляем кнопку
AddOwnerDrawControl(&m_button, sbdLeft, sbdBottom);

//задаем картинки, которые перекрывают контрол
GetAt(11)->m_aOverBkParts.Add(GetAt(4));
GetAt(11)->m_aOverBkParts.Add(GetAt(7));

Во-вторых, Контрол должен отрисовываться только в функции SkinDraw и никак иначе (OnPaint, OnEraseBkgnd). В-третьих, в текущей версии есть баг, поэтому чтобы контрол действительно перекрывался, нужно исправить функцию CSkinOwnerDrawControl::Draw

virtual void Draw(CDC *pDC=NULL)
{
if(m_nType!=sbdOwnerDrawControl || pDC==NULL)
{
CRgn rgn;
GetDestRgn(&rgn, TRUE);
pDC->SelectClipRgn(&rgn);
rgn.DeleteObject();
CSkinBkPart::Draw(pDC);
}
else if(IsVisible())
m_pOwnerDrawControl->SkinDraw(pDC);
}

И последнее, вариант номер два я не проверял, поэтому если он заработает, то я сильно удивлюсь:)
Re: OwnerDraw Controls
От: 2Los  
Дата: 19.03.03 22:08
Оценка:
Проверь, не забыл ли ты в функции SkinDraw преобразовать
координаты перед отрисовкой, примерно так:

CRect client;
GetWindowRect(client);
GetParent()->ScreenToClient(client);

//client — клиентский прямоугольник, в котором и следует рисовать
Re: Возможная проблема!
От: 2Los  
Дата: 30.03.02 16:50
Оценка:
А можешь пример кода с кнопкой привести, а то у меня вроде все нормально?
Re: Вопрос по теме!
От: 2Los  
Дата: 23.03.02 15:12
Оценка:
Загляни на www.codeguru.com или www.codeproject.com, там много всяких контролов.
Re: Прикольно :) , но Обидно
От: 2Los  
Дата: 23.03.02 15:12
Оценка:
Ну на самом деле иконка в Taskbare никуда не пропала, тока меню.
Re: Eto zdorovo! Tolko v kakih Windah eto zarabota
От: 2Los  
Дата: 23.03.02 15:11
Оценка:
В win95 это работать не будет, точнее работать будет только диалог CSkinBaseDialog, а расположенные на нем кнопки CSkinBaseButton — нет (из-за функции TrackMouseEvent), так что нужно сменить кнопку, либо винды. Если решишь сменить винды, то вот версии в которых я проверял демо приложение: XP/98/ME, теоретически должно работать и в NT4.0/2000
Re: Баг обнаружен.
От: Saruman Россия none
Дата: 26.03.03 08:08
Оценка:
Я тебе письмо с объяснением отправил.
Типа того что как бы...
Re: Баг обнаружен.
От: 2Los  
Дата: 26.03.03 20:38
Оценка:
Да, ты прав, в функции FindMoveInfo действительно баг.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.