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 日)
我补充一些信息
- 从 Form1 调用 TThread (TMainThread)
- 通过 TThread 启用 Form1->B_button 的更改无效
- 通过 TThread 启用 Form2->B_close 的更改有效
我可能需要通过小程序查看这些才能了解问题。
现在,我有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 文件有这个奇怪的设置。
我的环境:
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 日) 我补充一些信息
- 从 Form1 调用 TThread (TMainThread)
- 通过 TThread 启用 Form1->B_button 的更改无效
- 通过 TThread 启用 Form2->B_close 的更改有效
我可能需要通过小程序查看这些才能了解问题。
现在,我有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 文件有这个奇怪的设置。