C++Builder 程序员博客
5 Aug
各位老大,下面的代码生成一个Panel控件到窗体上,但颜色始终是窗体的颜色,不能自行设置,什么原因?怎么修正?
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TPanel *pb = new TPanel(Form1->Handle) ;
pb->Parent = Form1;
pb->Visible = true;
pb->ParentColor=false;
pb->Color=clNavy;
pb->Top=0;
pb->Left=0;
pb->Height = 90;
pb->Width = 90;
}
30 Mar
void __fastcall TForm1::FormClick(TObject *Sender)
{
TButton *L[10][10];
for(int i=0,j=20;i<10;i++)
{
for(int k=20,a=10;a<10;a++)
{
L[i][a]=new TButton(Form1);
L[i][a]->Parent=this;
L[i][a]->Caption=;
L[i][a]->Left=j;
L[i][a]->Top=k;
L[i][a]->Height=8;
L[i][a]->Width=8;
L[i][a]->Show();
k+=8;
}
j+=8;
}
}
为什么单击之后没有反应呢
写在Form的OnCreate事件要好一些。你是说单击Form没有反应还是生成的按钮没有反应呢?
单击form没反应啊 form还是空白的
show()不是应该显示按钮吗?。。
哪里呢。。
啊。。呵呵 不好意思 写错了 应该是a=0.。。呵呵
啊 嘿嘿 太粗心了 嘿嘿 谢谢啦。。。
你生气的按钮好小啊
8 Jan
如题,我想用鼠标拖动时出现一个矩形虚线框(就像在Windows的桌面上拖动鼠标一样),松开鼠标后虚线框范围内生成一个新窗口
我邮箱是yanziyi290@163.com
qq 592392340
希望各位高手指点一下,感激不尽!
hehe
有个性
参观
//—————————————————————————
int x0,y0,y1,x1;
int flag=0;
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
x0=X;
y0=Y;
flag=1;
}
//—————————————————————————
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
x1=X;
y1=Y;
if(flag)
{
Form1->Canvas->LineTo(x0,y0);
Form1->Canvas->LineTo(x0,y1);
Form1->Canvas->LineTo(x1,y1);
Form1->Canvas->LineTo(x1,y0);
Form1->Canvas->LineTo(x0,y0);
//下边把原来的划线去掉
}
}
//—————————————————————————
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
flag=0;
}
//—————————————————————————
7 Jan
先声明本人刚接触c++builder
系统上位机和下位机之间通过千兆网连接,上位机发送测试命令,下位机进行各项测试并将测试结果返回上位机,在上位机主令台画面上把测试流程图实时显示。
大致就是这样,老板这么说,但是我一点头绪都没有,盼高手指教~~~~~~~~~~小女子感激不尽
就是一個C/S 結構的服務端和客戶端的問題
服務端和客戶端進行相應的業務處理、通過TCP傳輸數據
嗯,是这意思,但是大侠好像没看我问的问题,呵呵
这个可以定义个协议来实现
比如下位机运行到第一步,发个1过来,
你上位机收到后将关于1的内容显示出来。
当然还有网络编程的东西,
你下位机与上位机通信可以使用SOCKET编程实现
测试流程图实时显示。
先画好流程图,然后下位机测试到某一部告诉上位机如“测试启动状态”,然后上位机把这一步图标高亮即可。图标可以用TImage制作加载,也可以用TSpeedButton,如果用TBitButton可以通过设置其Enable为true或false来变色,上下位机器可以用rs232,gprs,can等方式通信。
23 Dec
是这样的,比如我把form2设为available了,然后在form1上按button1的时候动态创建了form2了,再按一下又动态创建了form2,这个时候我把第一个动态创建的form2关掉了,但是不释放内存,我现在要再调用那个form应该怎么办啊,如果Form->show()的话出现的应该是第二个创建的form啊
你new出两个窗口出来,要保存它们的指针,通过指针就可以访问了。也是通过这个指针来释放。
如果你自己不保存动态创建对象的指针,我也想不出来有什么办法可以访问对象
用数组吧
form2设为available了,你把form2想象成一个资源,你new了一个form2出来,当你继续点击button时,先做个判断,如果form2已经new给一个指针了,就不要new新的了。
15 Dec
BCB 动态创建ODBC数据源,创建后连接
想连接DBF数据库
谢谢!
动态创建数据源,是什么意思,是否就是手工设置Connection?这个网上很多,不同的数据库,有不同的写法
动补动态没有什么区别啊,就是那些东西,那些控件,只是在程序里面放控件,设属性而已!!
简单一点吧,试一下动态生成Button!!然后动态生成这个就容易了!!
用户需将.DBF文件数据导入SQL SERVER,但源数据的位置和名称不定,又不能随时手工设置ODBC,我想将数据导入写到程序中,让用户选择路径和文件名即可导入。这样,就需要设置ODBC,然后用ADOCoonection连接。请高手指教。多谢。
本人已解决,谢谢各位。
9 Jul
我用c++ builder 连接远程的ms sql server数据库,用代码往数据库中插入数据,为什么老报错呢?
错误提示:无法将null值插入列‘WO’,表'SFIS.USER_sfis.SF_WO_Rang';该列不允许空值,insert失败,
也就是说我用PCBASaveForm->ADOQuery1->FieldByName("WO")->Value 赋值根本没有执行,我想问问这是什么原因造成的?
String wo = PCBASaveForm->woEdit->Text.c_str() ;
String PCBACode = PCBASaveForm->PCBACodeEdit->Text.c_str() ;
String BOSACode =PCBASaveForm->bosaCodeEdit->Text.c_str() ;
String CIGSnFirst =PCBASaveForm->CIGSNFromEdit->Text.c_str() ;
String CIGSnLast = PCBASaveForm->CIGSNToEdit->Text.c_str() ;
String bootVer = PCBASaveForm->bootVerEdit->Text.c_str() ;
String loadVer = PCBASaveForm->loadVerEdit->Text.c_str() ;
String seeprom = PCBASaveForm->seepromEdit->Text.c_str() ;
String mcu = PCBASaveForm->mcuEdit->Text.c_str() ;
String major = PCBASaveForm->majorEdit->Text.c_str() ;
String minor = PCBASaveForm->minorEdit->Text.c_str() ;
String hwver = PCBASaveForm->hwverEdit->Text.c_str() ;
int qty ;
try
{
qty = PCBASaveForm->qtyEdit->Text.ToInt() ;
}
catch (Exception &excpt)
{
MessageBox (PCBASaveForm->PCBADBNavigator->Handle,strcat ("Number expected
",excpt.Message.c_str()),"Error",0) ;
return ;
}
String insertSql ;
insertSql += "insert into SF_WO_Rang (WO, PCBA_Code, BOSA_Code, CIG_Sn_First, CIG_Sn_Last" ;
insertSql += ",BootVer,LoadVer, Seeprom, MCU, Major, Minor, Hwver ) " ;
insertSql += " values( :wo ,:PCBACode,:BOSACode,:CIGSnFirst " ;
insertSql += ",:CIGSnLast,:bootVer,:loadVer,:seeprom,:mcu " ;
insertSql += ",:major,:minor,:hwver) " ;
PCBASaveForm->ADOQuery1->Close() ;
PCBASaveForm->ADOQuery1->SQL->Clear() ;
//PCBASaveForm->ADOQuery1->SQL->Text = insertSql ;
PCBASaveForm->ADOQuery1->SQL->Add(insertSql) ;
PCBASaveForm->ADOQuery1->Active = true ;
PCBASaveForm->ADOQuery1->FieldByName("WO")->Value = wo ;
PCBASaveForm->ADOQuery1->FieldByName("PCBA_Code")->Value = PCBACode ;
PCBASaveForm->ADOQuery1->FieldByName("BOSA_Code")->Value = BOSACode ;
PCBASaveForm->ADOQuery1->FieldByName("CIG_Sn_First")->Value = CIGSnFirst ;
PCBASaveForm->ADOQuery1->FieldByName("CIG_Sn_Last")->Value = CIGSnLast ;
PCBASaveForm->ADOQuery1->FieldByName("BootVer")->Value = bootVer ;
PCBASaveForm->ADOQuery1->FieldByName("LoadVer")->Value = loadVer ;
PCBASaveForm->ADOQuery1->FieldByName("Seeprom")->Value = seeprom ;
PCBASaveForm->ADOQuery1->FieldByName("MCU")->Value = mcu ;
PCBASaveForm->ADOQuery1->FieldByName("Major")->Value = major ;
PCBASaveForm->ADOQuery1->FieldByName("Minor")->Value = minor ;
PCBASaveForm->ADOQuery1->FieldByName("Hwver")->Value = Hwver ;
PCBASaveForm->ADOQuery1->FieldByName("Qty")->Value = qty ;
//PCBASaveForm->ADOQuery1->Parameters->ParamValues["WO"] = wo ;
PCBASaveForm->ADOQuery1->ParamCheck = false ;
PCBASaveForm->ADOQuery1->ExecSQL() ;
感觉比较乱,执行到那句报的错
有字段不允许为空而又没有设置默认值,有三种方法解决这一问题:
1、插入一个值
2、修改数据库表中的字段定义,允许为空选项打勾
3、保持不允许插入空值,但设置一个默认值
wo很可能是空的
在最前面加上类似:
if(PCBASaveForm->woEdit->Text.c_str()=="")return;
的语句
就是 表'SFIS.USER_sfis.SF_WO_Rang'有约束不能为空,
WO插入个默认值就可以了.
关注!~
很久没有来了,谢谢大家的关注。我现在没有用这个方法连了,所以近来的都有分。谢谢!
9 Jul
我现在写一个体育比赛广播员程序,要求程序中利用panel把界面分成一个个格,格内(即panel)上放置数个Label,分别显示运动员的信息(包括姓名、得分等信息),我现在想把panel及在其上面的Label做成一个控件,方便程序能简单的动态生成多个这样的控件(以运动员数目创建),该怎么写呢?我发现网上也有panel上有控件而做成控件数组的,但panel里面的控件也需要动态创建,我希望创建这样的一个控件,动态创建时就像创建Button一样简单,一旦动态创建就能有上面的label,而且label作为控件的属性,能直接赋值,会不会比较难呢?各位,帮忙啊!!
将Panel和其内部的BUTTON、LABEL的创建、销毁封装到一个类中,创建控件的代码可以参考下面
TPanel* p = new TPanel(this);
p->Parent = this;
p->Align = alBottom;
TLabel* pLabel = new TLabel(this);
pLabel->Parent = p;
pLabel->Caption = "asdf";
如果考虑到效率问题,需要动态增减的话,你可以声明一个由 TLabel 构成的 Vector,应该很简单的哇。。。
感谢,问题已经解决,谢谢
13 Apr
HINSTANCE PcommDLL = NULL;
bool LoadPcommDll()
{
try
{
PcommDLL=LoadLibrary("Pcomm.dll");
if(PcommDLL)
{
//LED_Open =(long(WINAPI *)(TDeviceParam*,long,long,long))GetProcAddress(LEDDLL,"LED_Open");
sio_ioctl=(int (WINAPI *)(int port, int baud, int mode))GetProcAddress(PcommDLL,"sio_ioctl");
sio_getch=(int (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_getch");
sio_read=(int (WINAPI *)(int port, char *buf, int len))GetProcAddress(PcommDLL,"sio_read");
sio_putch=(int (WINAPI *)(int port, int term))GetProcAddress(PcommDLL,"sio_putch");
sio_write=(int (WINAPI *)(int port, char *buf, int len))GetProcAddress(PcommDLL,"sio_write");
sio_flush=(int (WINAPI *)(int port, int func))GetProcAddress(PcommDLL,"sio_flush");
sio_iqueue=(long (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_iqueue");
sio_oqueue=(long (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_oqueue");
sio_lstatus=(int (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_lstatus");
sio_lctrl=(int (WINAPI *)(int port, int mode))GetProcAddress(PcommDLL,"sio_lctrl");
sio_cnt_irq=(int (WINAPI *)(int port, VOID (CALLBACK *func)(int port), int count))GetProcAddress(PcommDLL,"sio_cnt_irq");
sio_modem_irq=(int (WINAPI *)(int port, VOID (CALLBACK *func)(int port)))GetProcAddress(PcommDLL,"sio_modem_irq");
sio_break_irq=(int (WINAPI *)(int port, VOID (CALLBACK *func)(int port)))GetProcAddress(PcommDLL,"sio_break_irq");
sio_Tx_empty_irq=(int (WINAPI *)(int port, VOID (CALLBACK *func)(int port)))GetProcAddress(PcommDLL,"sio_Tx_empty_irq");
sio_break=(int (WINAPI *)(int port, int time))GetProcAddress(PcommDLL,"sio_break");
sio_break_ex=(int (WINAPI *)(int port, int time))GetProcAddress(PcommDLL,"sio_break_ex");
sio_flowctrl=(int (WINAPI *)(int port, int mode))GetProcAddress(PcommDLL,"sio_flowctrl");
sio_Tx_hold=(int (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_Tx_hold");
sio_close=(int (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_close");
sio_open=(int (WINAPI *)(int port))GetProcAddress(PcommDLL,"sio_open");
return true;
}
else
return false;
}
catch(…)
{
//
}
}
上面的函数无论是不是成功加载PCOMM.DLL,函数都返回true
就是把PCOMM文件删除了,还是返回TRUE?
为什么这样啊?
Pcomm.dll文件有可能在其它的系统文件夹里,虽然你在当前目录中删除了,但程序在其它地方找到了该文件也说不好啊.因为加载动态库的机制是在当前路径下找,找不到再到各个系统文件夹里去找.你试试将文件名换一个不存在的文件试试,如果返回false就证明我的猜想,否则那就是其它问题了.
PcommDLL=LoadLibrary("Pcomm.dll");
if(PcommDLL!=NULL)
{
…
}else
{
//失败
}
以上方法,我一一测试一下,
然后结贴,谢谢大家帮忙
4 Apr
ADOQuery空间是用new 动态创建的,想动态添加个计算的字段,网上找来的代码好像不行,也不知是自己不懂得如何弄
TADOQuery *adoquery=new TADOQuery(NULL); adoquery->Connection=ADOConnection; adoquery->SQL->Text="select * from aaa"; adoquery->Open();
主要想添加个用来表示记录序号的字段,我的想法是专门写个函数OnCalc(),然后adoquery->OnCalcFields=onCalc;但是不知道该如何添加这个动态计算的字段,希望搞过这个的高手指点迷津,在此谢过啦
ADOQuery1->Close();
ADOQuery1->SQL->Text = "select . ";
TStringField *F = new TStringField(this);
F->FieldName = "Order";
F->DataSet = ADOQuery1;
F->FieldKind = fkCalculated;
ADOQuery1->Open;
你好啊,这方法我刚试过,我把SQL改为select * from aaa,然后用你的这个方面,那么查出来的结果集中在表格里面只显示了这个Order的字段,其他我表中的子都都没有显示出来,不知道怎么回事
DataSet一旦Open , 是不允許修改字段列表的。
要自定義字段列表,是有些無奈。
1、通過另一個DataSet 用 select top 0 * from table 取得字段列表。
TADOQuery *tmpds=new TADOQuery(NULL);
tmpds->Connection=ADOConnection;
tmpds->SQL->Text="select top 0 * from aaa";
tmpds->Open();
2、為目的DataSet構造需要的字段。
TADOQuery *adoquery=new TADOQuery(NULL);
adoquery->Connection=ADOConnection;
//生成應有的字段
TFieldDefs *pDefs = adoquery->FieldDefs;
pDefs->BeginUpdate();
for(int i = 0 ; i < tmpds->FieldCount ; ++i)
{
TField *f = tmpds->Fields->Fields[i];
TFieldDef *pDef = pDefs->AddFieldDef();
pDef->Name = f->FieldName;
pDef->DataType = f->DataType;
pDef->Size = f->Size;
f = pDef->CreateField(adoquery);
…這裡可以設定字段f的各種屬性
}
delete tmpds ;
pDefs->EndUpdate();
//然後加入自己額外的字段(計算字段或Lookup字段),需要的話可以設定各個字段的屬性。
….
//最後設定SQL並打開數據庫
adoquery->SQL->Text="select * from aaa";
adoquery->Open();
大概過程就是這樣。具體代碼請自行調試。這樣建立的字段列表,並不會隨著 DataSet->Close() 而被清空。
這過程代碼比較多,不知道是否有更簡潔的方式來達到同樣的目的。
我在网上找了端代码,但是不知道该如何去调用,测试了好几次都出现异常,代码如下:
[code=C/C++]
void __fastcall TForm1::AddCalcField(String FdName, TADOQuery *DSName, TStringField *dt)
{
static count = 0;
if( DSName-> FindField(FdName)!= NULL)
return;
DSName-> Close();
try
{
dt = new TStringField(DSName);
{
dt-> FieldName = FdName;
dt-> DisplayLabel = FdName;
dt-> FieldKind = fkCalculated;
dt-> Name = "Field " + String(count++);
dt-> Index = DSName-> FieldCount;
dt-> DataSet = DSName;
DSName-> FieldDefs-> Update();
}
}
catch(Exception &e)
{
ShowMessage(e.Message);
}
}
[/code]
我是这样调用的:
[code=C/C++]
adoquery=new TADOQuery(NULL);
adoquery-> Connection=ADOConnection;
adoquery-> Close();
adoquery-> SQL-> Text= "select * from aaa ";
TStringField *dt;
AddCalcField( "Order ",adoquery,dt);
adoquery-> OnCalcFields=onCalc;
adoquery-> Open();
[/code]
但是不行,并且在关系程序时出现异常,郁闷……
void __fastcall OnCalc() { adoquery->FieldByName("Order")->AsString=IntToStr(adoquery->RecNo); }
这个解释的详细,我来学习了
在设计时上双击ADOQuery1, 你先手工加上你需要的字段.(省点事. 要不然你还要写代码一个字段一个字段的加.)
然后再程序中加入我的代码. 就OK了.
ADOQuery1->Close();
ADOQuery1->SQL->Text = "select . ";
//另外先判断一下
TField *F = ADOQuery1->FindField("Order");
if F=NULL then
{
TStringField *F = new TStringField(this);
F->FieldName = "Order";
F->DataSet = ADOQuery1;
F->FieldKind = fkCalculated;
}
ADOQuery1->Open;
晕.写DELPHI代码习惯了.
ADOQuery1->Close();
ADOQuery1->SQL->Text = "select . ";
//另外先判断一下
TField *F = ADOQuery1->FindField("Order");
if (F=NULL) {
TStringField *F = new TStringField(this);
F->FieldName = "Order";
F->DataSet = ADOQuery1;
F->FieldKind = fkCalculated;
}
ADOQuery1->Open;
TO: w88529593
你在5楼的代碼,應該是設計期已經固化了字段列表,然後在這個基礎上再加上一個計算字段,但你的情況是:SQL是後期再加上的,字段列表是空的,設計期沒有辦法固死字段列表。
注意一下代碼需要的應用環境就行了。編程不能只會COPY代碼的。
我說的與 jjwwang 說的意思基本一致。
或许目前除了构造两个TADOQuery对象,然后将一个adoquery->Open后,遍历其字段列表添加到另一个adoquery里面,然后再把动态计算的字段也添加进去,暂时没其他更好的方法了,那就这样了