1、notebook的使用
Pages属性里添加page
右键点击notebook, next page|Previous page,然后把控件加到页面上
2、设置toolbutton的快捷键
加个Action List
利用它来关联ToolButton
3、自定义组件注册过程
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('MYT', [TMYTHouse]);
end;
4、Delphi鼠标左键点击Button弹出快捷菜单Popupmenu
procedure TForm1.SpeedButton4Click(Sender: TObject);
begin
PopupMenu2.Popup(Mouse.CursorPos.X-30,Mouse.CursorPos.Y+12);
end;
在光标所在位置弹出菜单;
procedure TForm1.Label1Click(Sender: TObject);
var
Point: TPoint;
begin
GetCursorPos(Point);
PopupMenu1.Popup(Point.X,Point.Y);
end;
[说明:两种方式实现的效果一样];
5、popupmenu.OwnerDraw默认为false,如果为true菜单可能会乱掉
6、包安装,包名相同会冲突,造成包安装不上,可能把包改名再安装
7、StringGrid根据条件设置单元格或行的颜色
procedure TfrmQuery.rzstrngrdDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
// 改变行颜色
if (rzstrngrd.Cells[11, ARow] = '异常') then
begin
if rzstrngrd.Canvas.Brush.Color <> clRed then // 设置背景颜色
rzstrngrd.Canvas.Brush.Color := clRed;
if rzstrngrd.Canvas.Font.Color <> clWhite then // 设置字体颜色
rzstrngrd.Canvas.Font.Color := clWhite;
end
else
begin
if rzstrngrd.Canvas.Brush.Color <> clWindow then // 设置背景颜色
rzstrngrd.Canvas.Brush.Color := clWindow;
if rzstrngrd.Canvas.Font.Color <> clBlack then // 设置字体颜色
rzstrngrd.Canvas.Font.Color := clBlack;
end;
rzstrngrd.Canvas.FillRect(Rect); //显示底色
rzstrngrd.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, rzstrngrd.Cells[ACol, ARow]); //显示字
// 改变单元格颜色
//ACol 和 ARow 按需要进行设定!
// if (ACol = 11) and (ARow > 0) then
// begin
// if (rzstrngrd.Cells[11, ARow] = '异常') then
// begin
// if rzstrngrd.Canvas.Brush.Color <> clRed then
// rzstrngrd.Canvas.Brush.Color := clRed;
// end
// else
// begin
// if rzstrngrd.Canvas.Brush.Color <> clMoneyGreen then
// rzstrngrd.Canvas.Brush.Color := clMoneyGreen;
// end;
// rzstrngrd.Canvas.FillRect(Rect); //显示底色
// rzstrngrd.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, rzstrngrd.Cells[ACol, ARow]); //显示字
// end;
end;
8、DataSet定位查找记录
if qryTimePriceEUse.Locate('Weekname;TimeNum',VarArrayOf([1,1]),[]) then
9、Contnrs(Containers):存放容器类单元
10、做定时备份功能,如果时间设置到分钟,那么定时器间隔时间设置1分钟, 如果时间设置到秒钟,那么定时器间隔时间设置1秒钟,如果时间设置到小时,那么定时器间隔时间设置1小时,这样才能定时
10、delphi在线程中建立ado的数据库连接
如题,delphi在线程中建立ado的数据库连接 因为不在线程中使用ado连接不存在的数据库,则窗体会停止响应。比较麻烦,而我对线程方面又不太了解,所以希望有大侠帮我写下代码。谢谢! 能详细点吗,最好给我做个demo 主窗体放三个edit,分别填服务器名称,sql用户名,密码 然后线程里是这样的代码 ConnMain:=TADOConnection.Create(nil); ConnMain.Connected:=False; connMain.ConnectionString:='Provider=SQLOLEDB.1;Password='+sqlpwd+';Persist Security Info=True;User ID='+sqluser+';Initial Catalog=''master'';Data Source='+server+''; ConnMain.Connected:=True;
procedure SendUDPThread.Execute();
var
AdoConn1:TADOConnection;
AdoQuery1:TAdoQuery;
begin
try
Lock.Enter;
AdoConn1:=TADOConnection.Create(nil);//动态创建ADO控件
AdoConn1.ConnectionString:=Form1.ADOConnection1.ConnectionString;
AdoConn1.LoginPrompt:=false;
AdoQuery1:=TAdoQuery.Create(Form1);
AdoQuery1.Connection:=AdoConn1;
with AdoQuery1 do
begin
SQL.Add('select * from Users where id='+inttostr(RecordID)+' order by id desc'); //RecordID是我在线程创建时定义的一个私有变量
open;
While not eof do
begin
Form1.Memo1.Lines.Add(FieldByName('Name').AsString);
next;
end;
end;
Form1.Memo1.Lines.Add('处理成功.');
Lock.Leave;
AdoConn1.Close;
AdoQuery1.Destroy;
AdoConn1.Destroy;//消除
except
Lock.Leave;
AdoConn1.Destroy;
AdoQuery1.Destroy;
Form1.Memo1.Lines.Add('处理失败.');
end;
11、frxReport frxDBSet设置UserName属性让报表设计器访问
frxReport.loadfromfile装载报表模板,showreport显示报表
12、TListview添加子项如果为空要添加空字符串,否则排序会报错
if FADOQuery.fieldbyname('TypeID').AsString = AMMETER_LIUYI then
begin
subitems.Add(AMMETER_LIUYI_NAME);
end
else if FADOQuery.fieldbyname('TypeID').AsString = AMMETER_DELIXI then
begin
subitems.Add(AMMETER_DELIXI_NAME);
end
else
begin
subitems.Add('');
end;
12、多线程的基本规则之一是不得从非GUI线程与GUI进行交互。
13、SuperObject字段区别大小写,字段不存在会报错
14、SuperObejct应用知识
vJson,vItem: ISuperObject;
iMtype: Integer;
ArrJsonValue,
ArrJsonKeyname :TSuperArray;
ObjJsonKey :TSuperTableString;
sRec := {"ac":200,"tag":{"reqid":"J80M7L"},"body":{"devices":[1,2,3,4,5,7,65534],"args":{"f01":1,"f02":2}}}
vJson := nil;
vJson := SO(sRec);
vItem := vJson['body'];
iMtype:= vJson['ac'].AsInteger;
ObjJsonKey :=vJson['body'].AsObject;
ArrJsonKeyName:=ObjJsonKey.GetNames.AsArray; // 同一级对象名
ArrJsonValue :=ObjJsonKey.GetValues.AsArray; // 同一级对象值
iDeviceCount := vItem.A['devices'].Length; // 数组
ObjJsonKey :=vItem['body']['args'].AsObject; // 对象里的对象
// 数组也要判断
hdrItem := vItem['hdr'];
if Assigned(hdrItem) then
begin
WriteOrderKeyname := hdrItem.A['writeOrder'];
if Assigned(WriteOrderKeyname) then
begin
if WriteOrderKeyname.Length > 0 then
NeedOrder := True;
end;
end;
// 增加对象
objectSuperSend.I['data.f01']:=StateToInt(tpDevice);
{”data“:{"f01":1}}
15、Edit高度和字体要协调,要不高度会自动变化
16、TForm.autosize:= True窗口会拉不开
改为TForm.autosize:= False就可以了
17、状态栏显示时间可用RzClockStatus
18、mqtt登录事件触发不了,while循环要注意消息阻塞的问题,可以加上application.processmessage避免
procedure TfrmRemoteSetting.MQTTRecMsg(Sender: TObject; aTopic: UTF8String;
aMessage: String; aQos: TMQTTQOSType; aRetained: Boolean);
var
sRec: string;
iMtype: Integer;
vJson: ISuperObject;
begin
sRec := aMessage;
if Trim(sRec) = '' then Exit;
try
vJson := nil;
vJson := SO(sRec);
if not Assigned(vJson) then Exit;
try
iMtype := vJson['ac'].AsInteger;
except
// self.ShowDebugMsg('Read Error Msg:' + sRec);
Exit;
end;
case iMtype of
113:
begin
FSettingResult := True;
FReceived := True;
end;
end;
except
end;
end;
procedure TfrmRemoteSetting.mqtqOffline(Sender: TObject;
Graceful: Boolean);
begin
Self.FLoginSuccessed := False;
end;
procedure TfrmRemoteSetting.mqtqOnline(Sender: TObject);
var
sLoginState,sTop:string;
begin
Self.FLoginSuccessed := True;
function TfrmRemoteSetting.SetGatewayCode(GatewayCode: string):Integer;
var
RemoteDomainName,RemoteIP,sTempIp,sTop,strSend: string;
RemotePort: Integer;
LogTimeOut, RecTimeOut: Integer; // 等待响应超时时间
mqttClient: TMQTTClient;
sWill: string;
begin
LogTimeOut := 100;
RecTimeOut := 5;
FReceived:=false;
RemoteDomainName := Trim(edtDomain.Text);
if(RemoteDomainName<>'')then
begin
sTempIp :=Trim(RemoteIP);
//解析不到域名,则RemoteIP为主.
if not HostToIP(RemoteDomainName,RemoteIP) then RemoteIP :=sTempIp;
end;
RemoteIP := Trim(RemoteIP);
if not IsLegalIP(RemoteIP) then RemoteIP :='192.168.1.3';
RemotePort := StrToInt(Trim(edtRomatePort.Text));
mqttClient := TMQTTClient.Create(nil);
try
mqttClient.Broker := False;
mqttClient.ClientID := RandomStr(20);
mqttClient.Clean := True;
mqttClient.Host := RemoteIP;
mqttClient.Port := RemotePort;
mqttClient.Username := Trim(edtAccount.Text);
mqttClient.Password := Trim(des.DecryStrHex(edtPWD.Hint, '1reeBlLb'+DECODE_HALF_KEY));
mqttClient.OnMsg := MQTTRecMsg;
mqttClient.OnOnline := mqtqOnline;
mqttClient.OnOffline := mqtqOffline;
// sTop := PUBGETWAY + '/' + edtGatewayCode.hint;
// sWill := '{"ac":100,"body":{"status":0}}';
// mqttClient.SetWill(sTop, sWill, qtAT_LEAST_ONCE);
if not mqttClient.Enabled then
mqttClient.Activate(True);
while LogTimeOut <> 0 do
begin
Application.ProcessMessages;
if FReceived then Break;
if FLoginSuccessed then
begin
//订阅一个用来控制设备的主题
sTop := SUBGETWAY + '/' + edtGatewayCode.hint;
mqttClient.Subscribe(sTop, qtAT_LEAST_ONCE);
Break;
end;
Sleep(1000);
Dec(LogTimeOut);
end;
if not FLoginSuccessed then
begin
Result := 2; // 连接失败
exit;
end;
sTop := PUBGETWAY + '/' + edtGatewayCode.Hint;
strSend := '{"ac":113, "tag":{"reqid":"' + RandomStr(6) + '"},"hdr":{"SourceGWCode":"' + edtGatewayCode.Hint
+'","NewGWCode" :"' + GatewayCode + '"}}';
mqttClient.Publish(sTop, strSend, qtAT_LEAST_ONCE);
while RecTimeOut <> 0 do
begin
if FReceived then Break;
Sleep(1000);
Dec(RecTimeOut);
end;
if FSettingResult then
Result := 0
else Result := 1;
finally
mqttClient.Free;
end;
end;
19、DatasetProvider使用范例
procedure LoadRightTable(pUserName: string);
var qryUserTable, qryUserRight: TADOQuery;
dpUserRight: TDataSetProvider;
begin
//加载用户信息
try
qryUserTable := TADOQuery.Create(nil);
ExecADOQuery(qryUserTable, True, 'select * from UserTable where UserName=''' + pUserName + '''');
if qryUserTable.RecordCount <= 0 then
isAdmin := False
else
case qryUserTable.FieldByName('UserType').AsInteger of
0: isAdmin := false;
1: isAdmin := True;
end;
finally
qryUserTable.Free;
end;
//加载用户权限信息
try
qryUserRight := TADOQuery.Create(nil);
dpUserRight := TDataSetProvider.Create(nil);
ExecADOQuery(qryUserRight, True, 'select * from UserRight where UserName=''' + pUserName + '''');
dpUserRight.DataSet := qryUserRight;
qryUserRight.Open;
if dsRightTable <> nil then
begin
dsRightTable.Free;
dsRightTable := nil;
end;
dsRightTable := TClientDataSet.Create(nil);
dsRightTable.SetProvider(dpUserRight);
dsRightTable.Open;
finally
qryUserRight.Free;
freeandnil(dpUserRight);//1234567890
end;
end;
20、设置系统短日期的格式
// 设置WINDOWS系统的短日期的格式
SetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, 'yyyy-MM-dd');
Application.UpdateFormatSettings := False;
// 设定程序本身所使用的日期时间格式
LongDateFormat := 'yyyy-MM-dd';
ShortDateFormat := 'yyyy-MM-dd';
LongTimeFormat := 'hh:nn:ss';
ShortTimeFormat := 'hh:nn:ss';
DateSeparator := '-';
TimeSeparator := ':';
21、InputQuery输入密码
procedure InputboxPassword(var MSG: TMessage); message InputBoxMessage;
procedure TfrmMain.InputboxPassword(var MSG: TMessage);
var
InputForm,Hedit: THandle;
begin
InputForm:= Screen.Forms[0].Handle;
if InputForm <> 0 then
begin
Hedit:= FindWindowEx(InputForm,0,'Tedit',nil);
SendMessage(Hedit,EM_SETPASSWORDCHAR,Ord('*'),0);
end;
end;
var
strResult: string;
begin
PostMessage(Handle,InputboxMessage,0,0);
if InputQuery('请输入维护密码', '密码:', strResult) then
begin
if strResult='dlxadmin123456' then
UAllocationDetail.showform()
else
ShowMessage('密码错误!');
end;
end;
22、MaskEdit 控件IP地址的Mask设置
(1) 添加 MaskEdit 控件。
(2) 选中TextEdit控件,查看控件属性。
(3) 展开Properties属性项,找到Mask属性项。
(4) 设置Mask属性项的EditMask属性值为:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
(5) 设置Mask属性项的MaskKind属性值为:emkRegExprEx
23、Toolbutton使Caption显示到图片右边
Toolbutton.List := True;
24、delphi 无窗体无界面exe怎么做?
要做一个无窗体的EXE,在Delphi下有两种方法:
console application
Hide all Foms(MainForm,esc.)
1、做一个控制台程序,生成console application工程文件的办法是:File\new\other\Console Application
2、隐藏窗体,跟无窗体差不多了吧,这样做最简单。
procedure TForm1.FormCreate(Sender: TObject);
begin
application.ShowMainForm:=false;
end;
25、combox实现键值对作用可用AddObject(objects[index]),Items.add(items[index])加values.add(values[index])
26、TListView如果caption列宽度为0,那么MultiSelect属性设为false,列表会显示不出来
27、mqtt频繁连接、断开原因
一、业务场景
我们在使用MQTT协议的时候,有些伙伴可能会遇到MQTT客户端频繁掉线、上线问题
二、原因分析及异常处理
原因:使用相同的clientID
方案:全局使用的clientID保证唯一性,可以采用UUID等方式
原因: 当前用户没有Topic权限
方案:如果配置有acl权限,则查询当前登录mqtt用户是否具有订阅对应topic的权限,无权时也会造成一直频繁断线重连
3. 原因:在回调函数内进行业务处理遇到异常并没有捕获
方案:在可能出现异常的语句块,进行try-catch捕获
/**
* subscribe订阅后得到的消息会执行到这里
*/
@Override
public void messageArrived(String topic, MqttMessage message) {
String msg = new String(message.getPayload());
try {
//此处可能因为收到的消息不合法,会造成JSON转化异常,若异常未捕获,会导致MQTT客户端掉线
JSONObject jsonObject = JSON.parseObject(msg);
String gwId = String.valueOf(jsonObject.get("gwId"));
} catch (JSONException e) {
log.error("JSON Format Parsing Exception : {}", msg);
}
}
28、datetimepick要设置下format,否则控件日期格式会受系统日期格式影响
29、fastreport4自动换行后还是出现显示不全的问题
解决办法:字符集改为:DEFAULT_CHARSET
30、DBGrid渲染背景颜色
procedure DBGridRowColor(Sender: TObject; //DBGrid颜色
const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if gdSelected in State then
begin
(Sender as TDBGrid).Canvas.Brush.Color := $000080FF; //当前选中单元格显示红色$00149BF0;//$005591B9;
(Sender as TDBGrid).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end
else
begin
//隔行改变网格背景色:
if (Sender as TDBGrid).DataSource.DataSet.RecNo mod 2 = 0 then
(Sender as TDBGrid).Canvas.Brush.Color := $00EFF1FC //定义背景颜色
else
(Sender as TDBGrid).Canvas.Brush.Color := $00B8E9FB; //$00F3EADE; // 定义背景颜色
(Sender as TDBGrid).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
end;
31、嵌入窗体设置属性
FForm.WindowState :=wsMaximized;
FForm.Align :=alclient;
FForm.BorderStyle :=bsNone;
FForm.TransparentColor :=true;
32、ListBox第一行字体比其他行小
ListBox第一行字体比其他行小,把字体设置成“宋体”就可以了。
33、ClientDataSet概述
Delphi TClientDataSet控件的数据存储文件格式扩展名为Cds。它是一个基于文件数据存储和操作的控件。通过在Delphi中使用TClientDataSet控件,可以将应用程序与数据库驱动程序完全分离,并实现了传统数据集控件简单使用的特点,这为编写“精简”数据库应用程序提供了技术方法和手段。