0

无论我如何尝试使用它,我都无法动态创建 aTScrollBox并为其分配OnMouseWheelEvent处理程序。我收到以下编译器错误:

E2034 无法将 'void (_fastcall * (_closure )(TObject *,TShiftState,int,TPoint &,bool &))(TObject *,TShiftState,int,TPoint &,bool &)' 转换为 'TMouseWheelEvent'

我对OnMouseWheelEvent处理程序的声明是正确的(据我所知):

....
TScrollBox *sb = new TScrollBox(funnelCharts);
sb->Top = 5000;
sb->Parent = funnelCharts;
sb->Align = alClient;
sb->Height = funnelCharts->ClientHeight;
sb->OnMouseWheel = scrollEvent;
....

// --------------------------------------------------------------

void __fastcall TForm1::scrollEvent(TObject *Sender, TShiftState Shift, int WheelDelta, TPoint &MousePos, bool &Handled)
{
    TScrollBox *scrollbox = dynamic_cast<TScrollBox*>(Sender);
    if (scrollbox)
    {
        for (int i = 1; i < Mouse->WheelScrollLines; i++)
        {
            if (WheelDelta > 0)
            {
                scrollbox->Perform(WM_VSCROLL, SB_LINEUP, 0);
            }
            else
            {
                scrollbox->Perform(WM_VSCROLL, SB_LINEDOWN, 0);
            }
        }
        scrollbox->Perform(WM_VSCROLL, SB_ENDSCROLL, 0);
        Handled = true;
    }
}
4

1 回答 1

0

这是编译器错误,而不是链接器错误。

查看TMouseWheelEventin的实际声明Controls.hpp。您的scrollEvent()方法与实际声明的不匹配,否则您将不会收到错误消息。

根据您是针对 32 位还是 64 位进行编译,TMouseWheelEvent(特别是其MousePos参数)的声明方式不同:

32 位:

typedef void __fastcall (__closure *TMouseWheelEvent)(System::TObject* Sender, System::Classes::TShiftState Shift, int WheelDelta, const System::Types::TPoint &MousePos, bool &Handled);

64 位:

typedef void __fastcall (__closure *TMouseWheelEvent)(System::TObject* Sender, System::Classes::TShiftState Shift, int WheelDelta, System::Types::TPoint MousePos, bool &Handled);

原因是 BCC32 和 BCC64 传递 8 字节结构类型(如TPoint)的方式不同。这种差异记录在 Embarcadero 的 DocWiki 上:

具有 5-8 字节结构或集合的事件对 BCC64 无效

受此差异影响的其他事件类型包括TGetSiteInfoEventTMouseWheelUpDownEventTContextPopupEvent

要解决此问题,您必须#ifdef按照记录的方式编写代码:

class TForm1 : public TForm
{
    ...
    #ifndef _WIN64
    void __fastcall scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled);
    #else
    void __fastcall scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta, TPoint MousePos, bool &Handled);
    #endif
    ...
};

...

#ifndef _WIN64
void __fastcall TForm1::scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
#else
void __fastcall TForm1::scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta, TPoint MousePos, bool &Handled)
#endif
{
    ...
}

或者,更简洁的方法:

class TForm1 : public TForm
{
    ...
    void __fastcall scrollEvent(
        TObject* Sender, TShiftState Shift, int WheelDelta,
        #ifndef _WIN64
        const TPoint &MousePos,
        #else
        TPoint MousePos,
        #endif
        bool &Handled);
    ...
};

...

void __fastcall TForm1::scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta,
    #ifndef _WIN64
    const TPoint &MousePos,
    #else
    TPoint MousePos,
    #endif
    bool &Handled)
{
    ...
}

或者,更清洁:

#ifndef _WIN64
#define SAFE_5TO8_PARAM(type, name) const type &name
#else
#define SAFE_5TO8_PARAM(type, name) type name
#endif

class TForm1 : public TForm
{
    ...
    void __fastcall scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta, SAFE_5TO8_PARAM(TPoint, MousePos), bool &Handled);
    ...
};

...

void __fastcall TForm1::scrollEvent(TObject* Sender, TShiftState Shift, int WheelDelta, SAFE_5TO8_PARAM(TPoint, MousePos), bool &Handled)
{
    ...
}
于 2017-08-16T02:18:00.107 回答