Borland Builder 2007 Дочерние элементы управления VCL и метод WindowProc - PullRequest
0 голосов
/ 12 января 2012

Мне удалось переопределить функцию WindowProc элементов управления, чтобы определить больше событий, чем поддерживается Builder (т.е. двойные средние щелчки мыши и т. Д.)

Проблема в том, что когда я переопределяю, скажем, дочерние компоненты WindowProc, родитель все еще получает событие.

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

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

Проблема, с которой я столкнусь, заключается в том, что, если пользователь нажимает кнопку, событие панели и событие кнопки запускаются.

Пожалуйста, любые советы будут с благодарностью приняты.

Джо

Пример кода: Обратите внимание, что Panel и Button являются производными от класса ConfigComponent, в котором живут методы m_kOldComponentWndMethod и ComponentWndProc.

Перекрытие панели

//---------------------------------------------------------------------------
CConfigComponentPanel::CConfigComponentPanel( TObject* pkParent,
                                              const CConfigComponentDimensions& rkConfigComponentDimensions,
                                              const CConfigComponentPos& rkConfigComponentPos,
                                              const CConfigSelect::SelectCollection& rkSelectCollection,
                                              TColor kBackgroundColour,
                                              TColor kForegroundColour,
                                              const std::string& rstrDisplayText,
                                              const CConfigFontRef& rkConfigFontRef,
                                              const CConfigComponent::ConfigComponentCollection& rkConfigComponentCollection )
:   CConfigComponent( rkConfigComponentDimensions, rkConfigComponentPos, kBackgroundColour, kForegroundColour ),
    m_pkPanel( new TPanel( ( TComponent* )NULL ) ),
    m_kConfigComponentCollection(),
    m_kSelectCollection(),
    m_kConfigFontRef( rkConfigFontRef ),
    m_strDisplayText( rstrDisplayText )
{
    // Set the parent.
    m_pkPanel->Parent = dynamic_cast<TWinControl*>( pkParent );

    if ( rkSelectCollection.size() > 0 )
    {
        // Store the old window proc method before overriding.
        m_kOldComponentWndMethod = m_pkPanel->WindowProc;
        m_pkPanel->WindowProc = ComponentWndProc;
    }

    // Add selects to collection
    AddSelectsToCollection( rkSelectCollection );
    // Add components to collection
    AddConfigComponentsToCollection( rkConfigComponentCollection );
}
//---------------------------------------------------------------------------

Переопределение кнопки

//---------------------------------------------------------------------------
CConfigComponentButton::CConfigComponentButton( TObject* pkParent,
                                                const CConfigSelect::SelectCollection& rkSelectCollection,
                                                const CConfigComponentDimensions& rkConfigComponentDimensions,
                                                const CConfigComponentPos& rkConfigComponentPos,
                                                TColor kBackgroundColour,
                                                TColor kForegroundColour,
                                                const CConfigButtonBGProperties& rkConfigButtonBGProperties ):
    CConfigComponent( rkConfigComponentDimensions, rkConfigComponentPos, kBackgroundColour, kForegroundColour ),
    m_kConfigButtonBGProperties( rkConfigButtonBGProperties ),
    m_pkButton( new TAdvToolButton( NULL ) ),
    m_kSelectCollection( rkSelectCollection )
{
    m_pkButton->Parent = dynamic_cast<TWinControl*>( pkParent );

    // Store the old window proc method before overriding.
    m_kOldComponentWndMethod = m_pkButton->WindowProc;
    m_pkButton->WindowProc = ComponentWndProc;
}
//---------------------------------------------------------------------------

Метод Component Wnd Proc (здесь используется дважды, один раз для панели и один раз для кнопки)

//---------------------------------------------------------------------------
void __fastcall CConfigComponent::ComponentWndProc( TMessage& rkMessage )const
{
    if ( rkMessage.Msg == WM_MBUTTONDBLCLK )
    {
        (void)Application->MessageBox( "CConfigComponent::ComponentWndProc", "" );
    }
    if ( rkMessage.Msg == WM_LBUTTONDBLCLK )
    {
        (void)Application->MessageBox( "ComponentWndProc::Left Button", "" );
    }

    if ( m_kOldComponentWndMethod )
    {
        m_kOldComponentWndMethod( rkMessage );
    }
}
//---------------------------------------------------------------------------

Спасибо, Джо

1 Ответ

2 голосов
/ 13 января 2012

TAdvToolButton является потомком TGraphicControl. TGraphicalControl не имеет собственного окна и, следовательно, не может напрямую получать пользовательский ввод. Пользовательский ввод направляется в окно Parent, поэтому WindowProc из Parent сначала видит сообщения. Если ввод произошел в клиентской области дочернего элемента TGraphicControl, Parent затем перенаправит ввод этому дочернему элементу. Вот почему вы видите, что сообщения ввода пользователя появляются в обоих компонентах. Если вы измените свой класс CConfigComponentButton на использование оконной кнопки, например TButton или TBitBtn, вы больше не увидите повторяющиеся сообщения, поскольку пользовательский ввод будет направлен непосредственно на кнопку, а не на родительский TPanel.

...