0

我设法覆盖了一个控件 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 );
    }
}
//---------------------------------------------------------------------------

谢谢,乔

4

1 回答 1

2

TAdvToolButtonTGraphicControl后代。 TGraphicalControl没有自己的窗口,因此无法直接接收用户输入。用户输入被定向到Parent窗口,因此首先WindowProc看到Parent消息。如果输入发生在 child 的客户区域内TGraphicControlParent则将输入转发给该 child。这就是为什么您会在两个组件中看到用户输入消息。如果您将CConfigComponentButton类更改为使用窗口按钮,例如TButtonor TBitBtn,您将不会再看到重复的消息,因为用户输入将直接定向到按钮而不是 parent TPanel

于 2012-01-13T19:04:05.770 回答