Borland Builder 2007 Дочерние элементы управления VCL и метод WindowProc

Мне удалось переопределить функцию управления 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;
}
//---------------------------------------------------------------------------

Компонент Wnd Proc Method (появляется здесь дважды для панели и один раз для кнопки)

//---------------------------------------------------------------------------
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 ответ

Решение

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

Другие вопросы по тегам