关于一个抽奖程序在循环滚动中按下回车键或者按下停止按钮让循环停止的实现

七岁小鬼 2008-10-10 03:33:56
单位要小弟我做一个简单的抽奖程序。
实现基本也很简单,一个按钮开始抽奖,另一个按钮按下后就抽出一个号码。
但是小弟在实现过程中发现按下开始按钮后(本来是BUTTON1),停止按钮却怎么也按不了了(停止按钮本来是BUTTON2)。
于是上网搜罗了一下,想换为键盘钩子HOOK来实现预期目的;结果换为键盘钩子后发现问题依旧!!!
在抽奖的过程中按下回车键,只能实现在整个for循环完毕后sign的值才会改变。。。
完蛋了。。。无语了。。。希望那位大侠可以拉兄弟一把啊。。。感谢感谢!!!


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

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#pragma link "Excel_2K_SRVR"
//---------------------------------------------------------------------------
static HINSTANCE hDLL; // DLL句柄
typedef void __stdcall (*DLLFUN)(HWND,bool);
DLLFUN DLLSetHook;
static const myMessage=2000;
static const SecondPar=1;
//---------------------------------------------------------------------------
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::FormCreate(TObject *Sender)
{
AnsiString ExcelFileName = GetCurrentDir()+"\\source_file\\test.xls";
if(!FileExists(ExcelFileName))
{
Application->MessageBox("报表模板文件不存在,无法打开!","错误",MB_ICONSTOP|MB_OK);
return;
}

try
{
Ex = Variant::CreateObject("Excel.Application");
}
catch(...)
{
Application->MessageBox("无法启动Excel","错误",MB_ICONSTOP|MB_OK);
return;
}

Ex.OlePropertySet("Visible",false);
Ex.OlePropertyGet("WorkBooks").OleProcedure("Open",ExcelFileName.c_str());
Wb = Ex.OlePropertyGet("ActiveWorkBook");
Sheet = Wb.OlePropertyGet("ActiveSheet");

hDLL=LoadLibrary((LPCTSTR)"Project2.dll"); // DLL文件名:Project2.dll
if(hDLL==NULL)
{
ShowMessage("DLL: 不能加载!程序退出。");
exit(1);
}

DLLSetHook = (DLLFUN)GetProcAddress(hDLL,"SetHook");
if(DLLSetHook==NULL)
{
ShowMessage("DLL: 函数没找到!程序退出。");
FreeLibrary(hDLL);
exit(1);
}
DLLSetHook(this->Handle,true);

sign = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
for(int i=1;i<=100;i++)
{
for(int j=1;j<=10;j++)
ST1->Caption = Sheet.OlePropertyGet("Cells",i,1).OlePropertyGet("Value");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
Wb.OleProcedure("Close");
Ex.OleFunction("Quit");

DLLSetHook(NULL,false); // 卸下HOOK
FreeLibrary(hDLL); // 卸下DLL
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
for(int i=1;i<=100;i++)
{
if (sign == 0)
for(int j=1;j<=10;j++)
ST1->Caption = Sheet.OlePropertyGet("Cells",i,1).OlePropertyGet("Value");
}
}
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg,
bool &Handled)
{
if((Msg.message==WM_KEYDOWN)&&(Msg.wParam==13))
sign = 1;
//ShowMessage(" 收到HOOK按键消息!\n\n 【键虚拟码】:"+IntToStr(Msg.wParam));

}
//---------------------------------------------------------------------------
...全文
505 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
七岁小鬼 2008-10-28
  • 打赏
  • 举报
回复
感谢感谢!!!解决了!!!谢谢大家啊!!!
nbzip 2008-10-21
  • 打赏
  • 举报
回复
只是针对他的问题回答.(在做随机取值时,如果用这些,会改变一些结果(当然在这里也没多大的事,只要最后得到值就行.)
但在其它某种地方,就不行.)
======================
楼上说的非常好,以前做停顿处理的时候,也是用这二个的.
:>
=====================
yuanreid 2008-10-20
  • 打赏
  • 举报
回复
Application->ProcessMessages();
本身如果用好了,能简化很多工作(某种情况下是的,并非绝对)。

比如界面上运行了一个大循环操作,你想在中间中断执行它,就可以用Application->ProcessMessages();
在循环中Application->ProcessMessages();,并在每次操作前判断一个标志。如果使用按键中断,可以在按键点击事件中修改这个标志即可。

否则,你就要放到一个线程中做大循环,中断时发送消息或修改线程变量标志。
nbzip 2008-10-20
  • 打赏
  • 举报
回复
只需要线程.
如果你在循环中,你用SLEEP(1000)或Application->ProcessMessages();都不是太好,会影响随机抽奖的.

=====================
还有一种方法,就是你一个循环得到一个值或多个值.就是不中断的方法,只有整个循环完成.
中途也不用考虑中断.(必竟参加抽奖的人不应该是很多的).


如,你在另一张表中写上....1000得到一值,10000得到一值...99833得到一个值.(三一边的屏幕中,得到一值就显示一值)
在你把所有人员都循环一边后,跳出循环.得到这三个值,也算是抽奖完成.

yuanreid 2008-10-20
  • 打赏
  • 举报
回复
不需要多线程的解决办法就是定时触发消息队列,处理窗口消息,这样你的按键点击就有反应了。
在循环中添加Application->ProcessMessages();


void __fastcall TForm1::Button1Click(TObject *Sender)
{
for(int i=1;i <=100;i++)
{
for(int j=1;j <=10;j++)
{
Application->ProcessMessages();
ST1->Caption = Sheet.OlePropertyGet("Cells",i,1).OlePropertyGet("Value");
}
}
}

Jim@luckeeinc.com 2008-10-20
  • 打赏
  • 举报
回复
在循环的时候 要做别的事情要用多线程的
//----------.h文件--------------------------------
class TMyThread:public TThread
{
public:
__fastcall TMyThread(bool CreateSuspended, TFeis01 *f);
private:
void __fastcall Execute(void);
void __fastcall MyWork();
TFeis01 *eis01;
};
//-----------.cpp文件---------------------
//------------------------------------------------------------------------------
_fastcall TMyThread::TMyThread(bool CreateSuspended, TFeis01 *f):TThread(true)
{
FreeOnTerminate=true;
Resume();
this->eis01 = f;
}

void __fastcall TMyThread::MyWork()
{
//这里写你的循环
}

void __fastcall TMyThread::Execute()
{
//Synchronize(MyWork);
CoInitialize(NULL);
MyWork();
}


////////TFeis01是我程序里的一个form你自己改一下
laowang2 2008-10-11
  • 打赏
  • 举报
回复
抽奖程序是多线程的,你可以看看vc实效百例,有一个。
yumikoo 2008-10-10
  • 打赏
  • 举报
回复
在你的循环里加个Application->ProcessMessages()
七岁小鬼 2008-10-10
  • 打赏
  • 举报
回复
楼上的我也用过了,不过就是在循环的时候停止按钮按不下去啊。
yumikoo 2008-10-10
  • 打赏
  • 举报
回复
在for循环里加个布尔判断,
bool flag = true;
for(int i=1; (i<=100)&&flag;i++)
在停止按钮里对flag进行修改,flag = true;
其实这样的程序个人觉得用线程去抽奖比较好。

604

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder VCL组件使用和开发
社区管理员
  • VCL组件使用和开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧