C++ 构建器 > 从 TThread 禁用 Form TButton 不起作用

C++ builder > disabling Form TButton from TThread does not work

我的环境:

C++ Builder XE4 on Windows7 Pro (32bit)

我正在尝试从 TThread Enable/Disable Form1 上的 TButton;

在TThread中,我定义了以下并使用它们

void __fastcall TThreadMain::Form1_enableButtons(bool bfOn)
{
    m_setOnOff = bfOn;
    Synchronize(Sync_enableButtons);
}

void __fastcall TThreadMain::Sync_enableButtons(void) {
    Form1->B_button->Enabled = m_setOnOff;
}

但是,这不会 disable/enable Form1 上的按钮。

当我想要disable/enable来自TThread的按钮时,我应该怎么做?


(添加:2015 年 8 月 3 日) 我补充一些信息

我可能需要通过小程序查看这些才能了解问题。


现在,我有4个小文件,我仍然有同样的问题。

Main.h

#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ComCtrls.hpp>
#include "ThreadMain.h"

class TFormMain : public TForm
{
__published:
    TStatusBar *StatusBar1;
    TButton *B_manualPdfMake;
    TButton *B_option;
    void __fastcall B_optionClick(TObject *Sender);
    void __fastcall B_manualPdfMakeClick(TObject *Sender);

private:
    TThreadMain *m_thr_main;
public:
    void __fastcall EnableButtons(bool bfOn);
    __fastcall TFormMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormMain *FormMain;
//---------------------------------------------------------------------------
#endif

Main.cpp

#include <vcl.h>
#pragma hdrstop

#include "Main.h"
#include "option.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMain *FormMain;
//---------------------------------------------------------------------------

__fastcall TFormMain::TFormMain(TComponent* Owner)
    : TForm(Owner)
{
    m_thr_main = new TThreadMain(NULL);
    m_thr_main->Resume();
}
void __fastcall TFormMain::B_optionClick(TObject *Sender)
{
    Options->ShowModal();
}
void __fastcall TFormMain::B_manualPdfMakeClick(TObject *Sender)
{
    m_thr_main->SetManualPdfReq();
}
void __fastcall TFormMain::EnableButtons(bool bfOn)
{
    B_manualPdfMake->Enabled = bfOn;
}

线程Main.h

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

#ifndef ThreadMainH
#define ThreadMainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp> // for TMemo
//---------------------------------------------------------------------------
class TThreadMain : public TThread
{
private:

    void __fastcall FormMain_enableButtons(bool bfOn);
    void __fastcall Sync_enableButtons(void);

    bool m_bfManualPdfReq;
    bool m_setOnOff;  // for Synchronize()

protected:
    void __fastcall Execute();
public:

    void __fastcall SetManualPdfReq(); // start process

    __fastcall TThreadMain(TMemo *pmemo);
};
//---------------------------------------------------------------------------
#endif

线程Main.cpp

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

#include <vcl.h>
#pragma hdrstop

#include "ThreadMain.h"
#include "Main.h"
#include "option.h"

#pragma package(smart_init)

__fastcall TThreadMain::TThreadMain(TMemo *pmemo)
    : TThread(/* CreateSuspended=*/ true)
{

//  Priority = tpHigher; // TODO: consider priority

    m_bfManualPdfReq = false;
    FreeOnTerminate = true;
}

//---------------------------------------------------------------------------
void __fastcall TThreadMain::SetManualPdfReq() { m_bfManualPdfReq = true; }

void __fastcall TThreadMain::Execute()
{
    while(!Terminated) {
        if (m_bfManualPdfReq) {
            m_bfManualPdfReq = false;

            FormMain_enableButtons(false);
            Sleep(3000); // instead of calling some function()
            FormMain_enableButtons(true);
            ShowMessage(L"Fin");
        }

        Sleep(100);
    }
    int nop=1;
}
//---------------------------------------------------------------------------
void __fastcall TThreadMain::FormMain_enableButtons(bool bfOn)
{
    m_setOnOff = bfOn;
    Synchronize(Sync_enableButtons);
}

void __fastcall TThreadMain::Sync_enableButtons(void) {

    Options->Show();
    Options->B_cancel->Enabled = m_setOnOff;  // works

    FormMain->EnableButtons(m_setOnOff); // does not work
}

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


(添加:2015 年 8 月 03 日)

发生了一些奇怪的事情。

当 FormMain 是在应用程序启动期间打开的默认窗体时,无法通过 TThread 的 Synchronize() 禁用 FormMain 的 TButtons。

另一方面,如果在应用程序启动期间将同一个 FormMain 设置为非默认 Form,并且在其他 Form 的 Show() 之后,可以从 TThread 的 Synchronize() 禁用 FormMain 的 TButtons。

我自己解决了

在项目 cpp 文件中,我以某种方式复制了 FormMain 的 CreateForm(),如下所示。

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

#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
USEFORM("Unit2.cpp", Form2);
USEFORM("Main.cpp", FormMain);
//---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    try
    {
        Application->Initialize();
        Application->MainFormOnTaskBar = true;
        Application->CreateForm(__classid(TFormMain), &FormMain);
        Application->CreateForm(__classid(TForm2), &Form2);
        Application->CreateForm(__classid(TFormMain), &FormMain);
        Application->Run();
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}
//---------------------------------------------------------------------------

当我为 FormMain 注释掉其中一个 CreateForm() 时,问题就消失了。

我不确定为什么 .cpp 文件有这个奇怪的设置。