создание cbutton'а вручную
От: pan One  
Дата: 19.02.03 22:36
Оценка:
имеется окошко (наследник cwnd) в котором отрисовываются несколько кнопок. само окошко лежит на диалоге в виде custom control'а.
вопрос номер раз: как правильно создавать кнопки? в текущем варианте они создаются примерно таким кодом:
class CОкошко : public CWnd
{
protected:
    void  PreSubclassWindow( void ); 

    CButton  prevButton;
    CButton  nextButton;
    ...
}
void CОкошко::PreSubclassWindow() 
{
    CWnd::PreSubclassWindow();

    GetClientRect( &clientRect );
    CRect bRect = clientRect;
    DWORD style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;

    bRect.right = bRect.left + prevWidth;
    prevButton.Create( _T( "Prev" ), style, bRect, this, IDC_PREV );
    bRect.left  = bRect.right;
    bRect.right = bRect.left + nextWidth;
    nextButton.Create( _T( "Next" ), style, bRect, this, IDC_NEXT );
    ...
}
это работает но не совсем здорово. при попытке создать второй экземпляр окошка мы весело рушимся при попытке зарегистрировать контрол с номером IDC_PREV во второй раз. допустим, номера можно сгенерировать в ран-тайм, но как тогда быть с MESSAGE_MAP?

вопрос номер два: в том единственном экземпляре, который удается создать, кнопки выглядят совершенно невменяемым образом: шрифт надписи на пару пунктов крупнее того, что на диалоге (там стандартный системный) и почему-то болд. мало того при нажатии на кнопку вокруг нее появляется рамка активной кнопки (черненькая такая) и больше не исчезает. тобиш раз прокликал по всем кнопкам и они все выглядят активными. где грабли?
Re: создание cbutton'а вручную
От: SchweinDeBurg Россия https://zarezky.spb.ru/
Дата: 20.02.03 05:22
Оценка:
Здравствуйте, pan One, Вы писали:

PO>имеется окошко (наследник cwnd) в котором отрисовываются несколько кнопок. само окошко лежит на диалоге в виде custom control'а.

PO>вопрос номер раз: как правильно создавать кнопки? в текущем варианте они создаются примерно таким кодом:
PO>
class CОкошко : public CWnd
PO>{
PO>protected:
PO>    void  PreSubclassWindow( void ); 

PO>    CButton  prevButton;
PO>    CButton  nextButton;
PO>    ...
PO>}
void CОкошко::PreSubclassWindow() 
PO>{
PO>    CWnd::PreSubclassWindow();

PO>    GetClientRect( &clientRect );
PO>    CRect bRect = clientRect;
PO>    DWORD style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;

PO>    bRect.right = bRect.left + prevWidth;
PO>    prevButton.Create( _T( "Prev" ), style, bRect, this, IDC_PREV );
PO>    bRect.left  = bRect.right;
PO>    bRect.right = bRect.left + nextWidth;
PO>    nextButton.Create( _T( "Next" ), style, bRect, this, IDC_NEXT );
PO>    ...
PO>}
это работает но не совсем здорово. при попытке создать второй экземпляр окошка мы весело рушимся при попытке зарегистрировать контрол с номером IDC_PREV во второй раз. допустим, номера можно сгенерировать в ран-тайм, но как тогда быть с MESSAGE_MAP?


PO>вопрос номер два: в том единственном экземпляре, который удается создать, кнопки выглядят совершенно невменяемым образом: шрифт надписи на пару пунктов крупнее того, что на диалоге (там стандартный системный) и почему-то болд. мало того при нажатии на кнопку вокруг нее появляется рамка активной кнопки (черненькая такая) и больше не исчезает. тобиш раз прокликал по всем кнопкам и они все выглядят активными. где грабли?


А почему бы не создавать кнопки в OnCreate()? Или это уже опробовано и не работает?
- Искренне ваш, Поросенок Пафнутий
Re: создание cbutton'а вручную
От: Аноним  
Дата: 20.02.03 05:53
Оценка:
Здравствуйте, pan One, Вы писали:

PO>имеется окошко (наследник cwnd) в котором отрисовываются несколько кнопок. само окошко лежит на диалоге в виде custom control'а.

PO>вопрос номер раз: как правильно создавать кнопки? в текущем варианте они создаются примерно таким кодом:
PO>
class CОкошко : public CWnd
PO>{
PO>protected:
PO>    void  PreSubclassWindow( void ); 

PO>    CButton  prevButton;
PO>    CButton  nextButton;
PO>    ...
PO>}
void CОкошко::PreSubclassWindow() 
PO>{
PO>    CWnd::PreSubclassWindow();

PO>    GetClientRect( &clientRect );
PO>    CRect bRect = clientRect;
PO>    DWORD style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;

PO>    bRect.right = bRect.left + prevWidth;
PO>    prevButton.Create( _T( "Prev" ), style, bRect, this, IDC_PREV );
PO>    bRect.left  = bRect.right;
PO>    bRect.right = bRect.left + nextWidth;
PO>    nextButton.Create( _T( "Next" ), style, bRect, this, IDC_NEXT );
PO>    ...
PO>}


>это работает но не совсем здорово. при попытке создать второй экземпляр окошка мы весело рушимся при попытке

зарегистрировать контрол с номером IDC_PREV во второй раз.
Это не совсем понятно. У второго экзепляра будут свои собственные копии IDC_NEXT и IDC_PREV. Видимо, вы "рушитесь" по другой причинр. Кстати, что такое "рушитесь"? Если crash, то значит, проблема где-то в другом месте. Создание кнопок с повторяюшимися ID не должно крэшать программу.

>допустим, номера можно сгенерировать в ран-тайм, но как тогда быть с MESSAGE_MAP?

Теоретически, MESSAGE_MAP тоже можно сгенерировать в ран-тайм но я этого никогда не делал


>вопрос номер два: в том единственном экземпляре, который удается создать, кнопки выглядят совершенно невменяемым образом: шрифт надписи на пару пунктов крупнее того, что на диалоге (там стандартный системный) и почему-то болд.

Это легко исправить. Нужно кнопкам поставить тот же щрифт, что и в диалоге:

nextButton.Create( _T( "Next" ), style, bRect, this, IDC_NEXT );
nextButton.SetFont(GetFont()); //будет OK при условии, что CОкошко точно также имеет фонт из диалога-владельца

>мало того при нажатии на кнопку вокруг нее появляется рамка активной кнопки (черненькая такая) и больше не исчезает. тобиш раз прокликал по всем кнопкам и они все выглядят активными. где грабли?

Тут трудно сказать заочно. Я бы на вашем месте запустил Шпиона и посмотрел на стили кнопочек после создания
Re[2]: создание cbutton'а вручную
От: pan One  
Дата: 20.02.03 07:39
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:
SDB>А почему бы не создавать кнопки в OnCreate()? Или это уже опробовано и не работает?
PO>само окошко лежит на диалоге в виде custom control'а.
окошко создается самой mfc'ей и умные люди говорят, что в таком случае этот экземпляр не получает wm_create.

2 all: кстати, насколько я себе представляю, существуют по меньшей мере три метода ложения (кладения) своих контролов на окно:
а. положить кастом контрол, прописать ему свежезарегистрированный оконный класс и организовать ddx этому контролу (первый экземпляр окошка);
бэ. положить какой-нибудь cstatic и попытатся его субклассировать;
цэ. вручную вызвать create (второй экземпляр).
вопросы: какой из методов наиболее цивилизованный? можно ли их мешать?

Здравствуйте, Аноним, Вы писали:
А>Это не совсем понятно. У второго экзепляра будут свои собственные копии IDC_NEXT и IDC_PREV.
ну, я как-бы тоже на это надеялся...
А>Видимо, вы "рушитесь" по другой причинр. Кстати, что такое "рушитесь"? Если crash, то значит, проблема где-то в другом месте. Создание кнопок с повторяюшимися ID не должно крэшать программу
"рушимся" означает "падаем" срабатывает ассерт внутрях mfc. кусочек стека вызовов:
[code]AfxAssertFailedLine()
CWnd::Attach() <- тут мы ловим сам ассерт
_AfxCbtFilterHook()[code]кусочек кода:
BOOL CWnd::Attach(HWND hWndNew)
{
    ASSERT(m_hWnd == NULL);     // only attach once, detach on destroy
    ASSERT(FromHandlePermanent(hWndNew) == NULL);
        // must not already be in permanent map

падаем на первом ассерте. указатели я еще не смотрел (думал, может люди что скажут), так что что к чему аттачится — толи кнопка к окошку, толи окошко к диалогу — покрыто мраком.

А>Теоретически, MESSAGE_MAP тоже можно сгенерировать в ран-тайм но я этого никогда не делал

ну вот спасибочки! тогда я уж лучше wm_command с bn_clicked'ом ловить буду

А>Это легко исправить. Нужно кнопкам поставить тот же щрифт, что и в диалоге:

а вот за это пасиб. я пару лет назад в делфи упражнялся, так там это было стандартным поведением. вручную шрифт надо было устанавливать если хотелось чтоб он отличался от родительского. а тут такое...

А>Тут трудно сказать заочно. Я бы на вашем месте запустил Шпиона и посмотрел на стили кнопочек после создания

стиль 0x50010000. точно такой-же как у кнопок созданных в дизайнере форм. но те ведут себя прилично.
Re[3]: создание cbutton'а вручную
От: pan One  
Дата: 20.02.03 07:57
Оценка:
зы. забыл, если закомментировать создание кнопок, то оба окошка успешно создаются. хотя, "успешным" это назвать тяжело, так как на них нет кнопок

зыы. а что, свои уже отправленные сообщения здесь редактировать нельзя?
Re: создание cbutton'а вручную
От: disop Украина  
Дата: 20.02.03 14:23
Оценка:
Здравствуйте, pan One, Вы писали:

PO>имеется окошко (наследник cwnd) в котором отрисовываются несколько кнопок. само окошко лежит на диалоге в виде custom control'а.

PO>вопрос номер раз: как правильно создавать кнопки? в текущем варианте они создаются примерно таким кодом:
PO>
class CОкошко : public CWnd
PO>{
PO>protected:
PO>    void  PreSubclassWindow( void ); 

PO>    CButton  prevButton;
PO>    CButton  nextButton;
PO>    ...
PO>}
void CОкошко::PreSubclassWindow() 
PO>{
PO>    CWnd::PreSubclassWindow();

PO>    GetClientRect( &clientRect );
PO>    CRect bRect = clientRect;
PO>    DWORD style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;

PO>    bRect.right = bRect.left + prevWidth;
PO>    prevButton.Create( _T( "Prev" ), style, bRect, this, IDC_PREV );
PO>    bRect.left  = bRect.right;
PO>    bRect.right = bRect.left + nextWidth;
PO>    nextButton.Create( _T( "Next" ), style, bRect, this, IDC_NEXT );
PO>    ...
PO>}
это работает но не совсем здорово. при попытке создать второй экземпляр окошка мы весело рушимся при PO>попытке зарегистрировать контрол с номером IDC_PREV во второй раз. допустим, номера можно сгенерировать в PO>ран-тайм, но как тогда быть с MESSAGE_MAP?


Есть в MFC такой чудесный макрос ON_COMMAND_RANGE. Делаешь например так:

// в начале Окошко.h

#define MYBUTTON_FIRSTID                    2408;
#define MYBUTTON_COUNT                      16;


// в Окошко.h, перед DECLARE_MESSAGE_MAP()
afx_msg void OnMyButtonClicked( WPARAM wParam, LPARAM lParam );
[/сcode]


// в Окошко.cpp, перед END_MESSAGE_MAP

[ccode]
ON_COMMAND_RANGE( MYBUTTON_FIRSTID, MYBUTTON_FIRSTID + MYBUTTON_COUNT,OnMyButtonClicked )


При создании кнопок задаешь им ID соответственно MYBUTTON_FIRSTID, MYBUTTON_FIRSTID +1... до MYBUTTON_FIRSTID + MYBUTTON_COUNT.

И наконец, функция-обработчик щелчка мыши на кнопке:

void CОкошко::OnMyButtonClicked( WPARAM wParam, LPARAM lParam )
{
    DWORD dwButtonID = (DWORD)wParam - MYBUTTON_FIRSTID;
    ASSERT( dwButtonID >= 0 );
    // делаешь то, что нужно...
}


WBR, DisoP.
Re[2]: создание cbutton'а вручную
От: pan One  
Дата: 20.02.03 15:03
Оценка:
Здравствуйте, disop, Вы писали:

D>Есть в MFC такой чудесный макрос ON_COMMAND_RANGE. Делаешь например так:

это, конечно, тоже вариант, но проблема не столько в обработке нескольких кнопок, солько в создании кнопок с одинаковым id в разных окнах.

D>При создании кнопок задаешь им ID соответственно MYBUTTON_FIRSTID, MYBUTTON_FIRSTID +1... до MYBUTTON_FIRSTID + MYBUTTON_COUNT.

тобиш предлагается в классе хранить статик, который будет инкрементироваться всеми экземплярами по очереди? а что тогда будет в случае (количество_экземпляров * количество_кнопок) > MYBUTTON_COUNT?
Re[4]: [moderator] создание cbutton'а вручную
От: Хитрик Денис Россия RSDN
Дата: 20.02.03 16:37
Оценка:
Здравствуйте, pan One, Вы писали:

PO>зыы. а что, свои уже отправленные сообщения здесь редактировать нельзя?


К сожалению, нет.
Правила нашего с вами форума.
Как правильно задавать вопросы. © 2001 by Eric S. Raymond; перевод: © 2002 Валерий Кравчук.
Re[3]: создание cbutton'а вручную
От: pan One  
Дата: 21.02.03 06:53
Оценка:
вопрос про вторую копию кнопок снимается. используя create своего класса не могу создать даже первый его экземпляр. а через субклассирование все работает как часы
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.