目录
1.事件中的代码在服务器端和客户端,哪一端执行?
2.为什么UniGUI控件在IE中显示的字体会变小、模糊?
3.在浏览器端不能使用ShowMessage()
4.unigui程序只显示loading
5.uniGUI执行程序部署有3种形式
6.在UniGUI里使用ADO的设置
7.MainModule怎样得到js变量的值
8.TUniServerModule和TUniMainModule模块区别
9.MainModule里一般放什么,ServerModule一般放什么?
10.主窗体的标题怎么去掉
11.用ExtEvent打开链接和下载文件
12.WebApplication显示对话框
13.Uni中的UniChart的Series增删
14.怎样给每一个在线用户建立一套变量,在用户断开后立即清除
15.TUniHiddenPanel的作用
16.uniGUI实现Excel的导出
17.Send File()应用
18.UniGUI的Canvas使用
19.动态生成 TUniTabSheet和Frame
20.UniGUI中如果获得Session情况
21.uniGUI 通过SessionList操作另外的登录用户
22.UniGUI如何禁止关闭新窗口
23.UniGUI中Cookies使用中文汉字的方法
24.UniGUI如何实现压缩传输数据?
25.UniGUI TreeView处理
26.UniGUI 设置超时
27.从ASP网站登录到UniGUI中
28 UniGUI数据库初始化要放到MainModule里
30.写js的注意
31.JS,Jquery获取各种屏幕的宽度和高度
32.uniGUI动态建立Form及释放
32.uniGUI经验两则 uniTimer uniHtmlFrame
33.UniGUI的TUniLoginForm窗口自定义背景色
34.UniDBGrid选择字段Boolean处理
35.如何打开URL
36.事件操作时,如果出现等待效果
37.UniImage可以嵌入PNG图片
代码如下:
for i:=0 to 20 do
begin
if Frm[i]<>nil then
if Frm[I].Name=ProCaption then
begin
BaesFrame := Frm[i];
IsOpen := True;
Break;
end;
end;
if IsOpen then exit;
为什么这段代码是在服务器端执行,而不是在客户端执行呢?
解答: UniGUI的运行机制就是除非你在ClientEvents里的东西,其他都是要由UniGUI通过后台程序执行完成后解析成js发回客户端浏览器显示。
字体修改UniSessionModule的CustomCSS的内容:
/* ---------------------------修改 Ext CSS -------------------------- */
/* Ext 2.0 */
.x-window-footer {
position: relative;
top: 0;
right: 0;
}
.x-tab-strip SPAN.x-tab-strip-text {
font-size: 13px;
}
.x-panel-header {
font-size: 13px;
}
.x-tree-node {
font-size: 13px;
}
.x-grid3-hd-row TD {
font-size: 13px;
}
.x-grid3-row TD {
font-size: 13px;
LINE-HEIGHT: 18px;
}
.x-tip .x-tip-bd {
font-size: 13px;
}
.x-tip h3 {
font-size: 13px;
}
.x-tip .x-tip-bd-inner {
font-size: 13px;
}
.x-panel-t1 .x-panel-header {
FONT: normal 13px tahoma,arial,verdana,sans-serif;
}
.x-form-field {
FONT: 13px tahoma,arial,helvetica,sans-serif;
}
.x-small-editor .x-form-field {
FONT: 13px tahoma,arial,helvetica,sans-serif;
}
.x-combo-list-item {
FONT: 13px tahoma,arial,helvetica,sans-serif;
}
.x-btn button,x-toolbar .x-item {
FONT: 13px tahoma,arial,sans-serif;
}
.x-menu-list-item {
FONT: 13px tahoma,arial,sans-serif;
}
.x-window-t1 .x-window-header {
FONT: bold 13px tahoma,arial,verdana,sans-serif;
}
.x-layout-split-west .x-layout-mini {
BACKGROUND-IMAGE: url(../images/mini-left.jpg);
}
.x-form-text {
Margin-top:1px;
}/* the textField missing bottom line */
.x-form-item {
FONT: 13px tahoma,arial,helvetica,sans-serif;
}
.x-grid-group-hd DIV {
FONT: bold 13px tahoma,arial,helvetica,sans-serif;
}
/*按钮字体大小 Add by extjs.org.cn */
.x-btn-text {
Font: 12px tahoma,arial,sans-serif;
}
/* END */
function ShowMsg(AskString: String): Boolean;
begin
if MainForm.WebMode then
//must uses UniGUIApplication
UniSession.AddJS(‘alert(‘’’+AskString+’’’);’)
else
ShowMessage(AskString);
end;
在浏览器执行不可用ShowMessage
uniGUI以后发布要分别带上extjs和uni的两个js文件夹,这两个文件夹的具体位置要在UniServerModule模块中指定以下两个属性:
UniServerModule.UniRoot 代表uni的js及资源文件夹目录,即uni-0.94.0.1024目录中的文件,如果属性值为: [uni]\ ,则程序运行时会到uniGui的安装目录下去寻找
UniServerModule.ExtRoot 代表extjs的js及资源文件夹目录,即ext-4.2.1.883目录中的文件,如果属性值为:[ext]\ ,则程序运行时会到uniGUI的安装目录下去寻找
procedure TUniServerModule.UniGUIServerModuleBeforeInit(Sender: TObject);
begin
Self.ExtRoot := 'ext-7.4.0';
Self.UniRoot := 'uni-1.90.0.1555';
end;
这样,在程序编译调试时,就无需要每个uniGUI工程的exe文件下添加uni_94和ext_42这两个目录文件,程序会到unigui的安装目录中去寻找。而程序布署后,由于布署后主程序目录下有ext_42目录,就可以将uniRoot和ExtRoot两个属性动态设置为我们布署时设置的文件夹名。
1.ISAPI模式
部署在IIS或Apache,程序编译为Dll形式,没有试,准备后续专门测试一下。
2.标准执行文件模式
将软件编译成一个独立的Exe文件,包括了WEB服务和业务内容,是uniGUI部署方式中最简单的一种。该方式最大特点是可以进行代码跟踪,同一般exe程序调试一样,在Debug模式下程序调试非常方便。运行exe后就可以直接打开页面进行测试,通过任务栏上的图标可以打开服务监控页面,监控服务程序的运行情况,如下图:
3.Windows服务模式
将软件编译成Windows下的Service模式,并自动启动。从工程文件上看,与一般的程序工程文件略有差异,这里不详述。另外工程中增加了一个ServiceModule.pas文件和对应的窗体文件,该模块单元定义了Windows Service的一些属性,包括名称、依赖等,我只修改了DisplayName属性,其他属性都采用缺省。
特别需要注意的是:不要尝试修改该文件的文件名和模块类名,否则系统无法识别,编译能通过,但运行时报无法启动,估计是内部代码上写死了。
注册Service的方式同一般的Windows Service程序,通过命令行加 –install参数,注销用 –uninstall参数,如下:
MyServiceApp –install
MyServiceApp -uninstall
启动用命令行,如下:
net start UniServiceModule
UniServiceModule就是模块的类名不要前缀T
最关心的是该服务程序在较多客户终端(300~500个)情况下的性能,按照作者的话说是不取决于程序,而取决于服务器硬件条件。拟在近期用WinRunner做个测试,看看具体效果,主要是ISAPI 和 Windows Service两种模式的性能。
UniServerModule 设置 AutoCoInitialize 为 True
MainForm.UniTrackBar1.SetValue(Sender.Field.GetValue());
TUniServerModule 一个连接创建一个
TUniMainModule 只创建一个作为共用
TUniServerModule 所有客户端公用
TUniMainModule 你的连接使用
可以描述如下:
TUniServerModule,只有一個是公用,若用連接池在此建立,在此定義變量是公用
TUniMainModule,一個user一個,在此放資料庫控件是各user獨立,
TUniMainModule之public定義之變量是user單獨用
如果用到数据库,ADOConnection1、ADOQuery1、DataSource1要放到MainModule
可以在UniServerModule里设置主窗体的显示模式,属性MainFormDisplayMode:
mfPage: 主窗体无边框
mfWindows: 标准窗体,有边框
Application.MessageBox 不可以,要用WebApplication 不要用Application
UniChart似乎不能动态增加Series,没有AddSeries()方法,所以只能提前多建立几个,然后隐藏即可。再或者,考虑再画布上画。这个没试过。
Demo里的Session例子,似乎只讲了TimeOut,其余怎么处理?
另外,类似于隐藏域,用不可见的Label可以吗?
User之私有变量,请定义在MainModule的Public
public
{ Public Declarations }
LocalCacheURL: String;
LocalCachePath: String;
StartPath: String;
ExtFullPath: String;
ServerRoot: String;
ServerIni: String;
StartFlagMainDm: Boolean;
User,Test: String;
Comp: array of TComponent;
CompCount: Integer;
全域变量的意思:User1, User2, User3看到值是一样的。
在Form上放一个TUniHiddenPanel,放上的元件是隐藏的,TUniHiddenPanel的可视化元件是有,但执行时看不到,类似ASP里的隐藏域,HTML的Hidden
多种方法,推荐用TMS FlexCel读写速度块,并且不需要安装Excel就可执行
uses
FlexCel.XlsAdapter,VCL.FlexCel.Core;
//函数:
procedure TfmExport.saveToExcel(xls: TExcelFile);
{导出到EXCEL功能函数}
var
rowCount, colCount, i, j: Integer;
tempFile, destPath, destFile: string;
begin
if not UniMainModule().qry_exprot.Active then
begin
UniSweetAlert1.Title := '请先查询!';
UniSweetAlert1.Show();
exit;
end;
if UniMainModule().qry_exprot.RecordCount < 1 then
begin
UniSweetAlert1.Title := '没有记录,取消导出!!';
UniSweetAlert1.Show();
exit;
end;
xls.NewFile(1); //创建一个excel表格sheet
UniMainModule().qry_exprot.First; //定位到第一条记录
rowCount := UniMainModule().qry_exprot.RecordCount; //获取记录数
colCount := UniMainModule().qry_exprot.FieldCount; //获取字段列数
//写列头
i := 1; //定位到第一行
for j := 1 to colCount do
begin //UniMainModule().qry_exprot.Fields.FieldByNumber(j).FieldName
xls.SetCellValue(i, j, TCellValue.Create(DBData.Columns[j - 1].Title.Caption));
end;
//写数据
i := 2; //第二行开始
while not UniMainModule().qry_exprot.Eof do
begin
for j := 1 to colCount do
begin
xls.SetCellValue(i, j, TCellValue.Create(UniMainModule().qry_exprot.Fields.FieldByNumber(j).AsString));
end;
UniMainModule().qry_exprot.Next;
i := i + 1;
end;
xls.PrintLandscape := true;
tempFile := 'exportdata.xlsx'; //临时文件名
destPath := UniServerModule().FilesFolder + '\excelfile\';
if not DirectoryExists(destPath) then
begin
ForceDirectories(PChar(destPath));
end;
destFile := destPath + '\' + tempFile;
if FileExists(destFile) then
begin
deletefile(destFile);
end;
xls.Save(destFile); //保存表格到服务器端的临时目录
UniSession.SendFile(destFile); //下载表格到本地浏览器默认的目录
end;
//调用
procedure TfmExport.lblExportClick(Sender: TObject);
var
xls: TExcelFile;
begin
xls := TXlsFile.Create;
try
saveToExcel(xls); //调用自定义功能函数
finally
xls.Free;
end;
end;
UniSession.SendFile() 下载至Client端存档,这里面的参数是什么?
//前端下载 Fn是档名 (Server端档案,Client端档名)
UniSession.SendFile(MainSm.LocalCachePath+Fn, Fn)
//或者
LabDownLoad.Caption :=
‘<a href=”’+UniServerModule.TempFolderURL+FName+’”target=new>Click here to download: (‘+FName+’)</a>’;
Procedure TMainForm.UniImage1MouseUp(Sender: TObject;Button:TMouseButton;
Shift:TShiftState;X,Y:Integer);
begin
UniImage1.Picture.Bitmap.Canvas.Pen.Width := 1;
UniImage1.Picture.Bitmap.Transparent := True;
if Button=mbLeft then
begin
if x0=’’ then
begin
x0 := IntToStr(x);
y0 := IntToStr(y);
UniLabel2.Caption := x0+’,’+y0+’,’;
end
else begin
UniImage1.Picture.Bitmap.Canvas.MoveTo(StrToInt(x0), StrToInt(y0));
x0 := IntToStr(x);
y0 := IntToStr(y);
UniLabel2.Caption := UniLabel2.Caption+x0+’,’+y0+’,’;
end;
end;
end;
procedure TMainForm.openPage(pageName: string; pageCaption: string; pageControl: TUniPageControl; newFrame: TUniFrame);
{
参数说明
pageName:页面名称
pageCaption:新建UniTabSheet的Caption
pageControl:UniPageControl的控件名
newFrame:要新建的UniFrame的名字
}
var
newTabSheet: TUniTabSheet;
Err: string;
begin
Err := '';
newTabSheet := nil;
//查找是否已经存在要创建的页面
newTabSheet := TUniTabSheet(pageControl.FindChildControl(pageName));
if not Assigned(newTabSheet) then
begin
newTabSheet := TUniTabSheet.Create(Self); //创建一个sheet新页面
newTabSheet.PageControl := pageControl; //新sheet页面放到pageControl下
newTabSheet.Name := pageName; //设置新页面名字
newTabSheet.Caption := pageCaption; //设置新页面Caption页眉内容
newTabSheet.Closable := true; //设置新页面可一个关闭
newFrame.Parent := newTabSheet; //将新Frame放到新创建的页面上
newFrame.Align := alClient; //新Frame在新页面上居中显示
end;
pageControl.ActivePage := newTabSheet; //激活新页面
end;
在ServerModule单元中有如下属性,可以使用
ServerModule.UniServerModule.ServerStats.ActiveSessions
ServerModule.UniServerModule.ServerStats.MaxSessions 【最大会话】
ServerModule.UniServerModule.ServerStats.BytesSent
ServerModule.UniServerModule.ServerStats.BytesReceived
参照bbs,写了这个方法,检查是否有同名用户已经登录:
procedure TUniMainModule.CheckSameUser(aUserLoginCode: string);
var
ASessionList: TList;
I: Integer;
M: TUniMainModule;
USession: TUniGUISession;
begin
UniServerModule.SessionManager.Sessions.Lock;
try
ASessionList := UniServerModule.SessionManager.Sessions.SessionList;
for I := 0 to ASessionList.Count - 1 do
begin
USession := TUniGUISession(ASessionList[I]);
M := USession.UniMainModule as TUniMainModule;
if M.UserLoginCode = aUserLoginCode then//这里UserLoginCode是在MainModule中定义的一公共变量,用来保存用户登录代码,标示用户身份.
begin
M.ExitFlag:=True; //ExitFlag也是在MainModule中定义的公共变量,表示是否退出.
USession.TerminateAfterSecs(10);
Break;
end;
end;
finally
UniServerModule.SessionManager.Sessions.Unlock;
end;
end;
1.取消新窗口的SystemMenu,目的是去掉窗体的关闭按钮
2. 在窗体加上新按钮,点击事件为 Close;
3. 在窗体的OnClose事件中添加如下代码:
Action := CaNone; //这句一定要放在MessageDlg前面
MessageDlg(xxxxx);
在目前的UniGUI(ver:0.88)中使用UniApplication.Cookies.SetCookie来设置一个中文的Cookies时,然后用UniApplication.Cookies.Values来读取Cookies值时,中文会变成乱码。查询UniGUI论坛,得到如下解决方案:
procedure TMainForm.UniButton1Click(Sender: TObject);
var UserName: String;
begin
//使用EncodeString函数编码
UniApplication.Cookies.SetCookie(‘name’, EncodeString(‘中文汉字’));
//使用DecodeString解码
UserName := DecodeString(UniApplication.Cookies.Values[‘name’]);
end;
TUniServerModule类中有一个属性是控制压缩的,要以设置是否压缩和压缩级别,最小数据尺寸。
一般按以下设置就可以了:
ServerModule.Compression.Enabled := True;
ServerModule.Compression.Level := zcMax;
1)节点处理
procedure TFrameTree.ExpandTree(PNode: TUniTreeNode);
var Str, DirName: String; Qry: TAdoQuery; DirID,Fid: Integer; Node: TUniTreeNode;
begin
//展开父节点
Fid := GetDirID(FNode);
Str := ‘select * from DocDir where Del=0 and fid=’+IntToStr(Fid);
Qry := dm.CreateQuery;
Qry.SQL.Add(Str);
Qry.Open;
while not Qry.Eof do
begin
DirName := Qry.FieldByName(‘Name’).AsString;
DirID := Qry.FieldByName(‘ID’).AsString;
Node := AddNodeById(DirID, DirName, FNode);
//递归
ExpandTree(Node);
Qry.Next;
end;
Qry.Free;
end;
//不要一次全加,点击一个节点,才加载当前的。
2)ReadOnly设置
如果设置了js(显示CheckBox),是否ReadOnly不能设置了。之前有代码设置后,就异常。
AjaxTimeOut,建议60000
SessionTimeOut,建议900000
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312” />
</head>
<form action=”http://网址’ method=”post” id=”id” name=”id”>
<input name=”username” value=”test” type=”hidden” />
<input name=”userpwd” value=”test” type=”hidden” />
<a href=”#” onclick=”id.submit()”>提交</a>
</form>
获取:
UniApplication.Parameters.Values[‘UserName’]
UniApplication.Parameters.Values[‘UserPwd’]
数据库初始化要放到MainModule里,不可以放到ServerModule,否则,不同用户用同一个数据库连接,操作会相互干扰。
UniServerModule的AutoCoInitialize属性设置为True
29.UniGUI组件中的Client JavaScript Delphi组件之间的操作
UniGUI组件中Client、JavaScript、Delphi组件之间的操作:
1)UniLabel组件
function OnClick(Sender,e)
{
MainForm.UniLabel1.setText(‘Click!’);
}
function OnMouseMove(Sender,x,y)
{
MainForm.UniEdit1.setPositon(x,y);
}
2)UniButton组件
function OnMouseOut(Sender,e)
{
Sender.setText(‘Out’);
}
3)UniEdit组件
function form.OnMouseMove(Sender,x,y)
{
MainForm.UniEdit1.setValue(x+’ : ‘+y);
ss=MainForm.UniEdit1.getValue();
}
写js要注意 \ 都是要两个
特殊符号 \n 要改为 \n 才能正常
要显示 \ 原应该为 \ 要改为 \\
网页可见区域宽:document.body.clientWidth
网页可见区域高:document.body.clientHeight
网页可见区域宽:document.body.offsetWidth (包括边线的宽)
网页可见区域高:document.body.offsetHeight (包括边线的宽)
网页正文全文宽:document.body.scrollWidth
网页正文全文高:document.body.scrollHeight
网页被卷去的高:document.body.scrollTop
网页被卷去的左:document.body.scrollLeft
网页正文部分上:window.screenTop
网页正文部分左:window.screenLeft
屏幕分辨率的高:window.screen.height
屏幕分辨率的宽:window.screen.width
屏幕可用工作区高度:window.screen.availHeight
屏幕可用工作区宽度:window.screen.availWidth
HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth
scrollHeight: 获取对象的滚动高度。
scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离
scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离
scrollWidth:获取对象的滚动宽度
offsetHeight:获取对象相对于版面或由父坐标 offsetParent 属性指定的父坐标的高度
offsetLeft:获取对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置
offsetTop:获取对象相对于版面或由 offsetTop 属性指定的父坐标的计算顶端位置
event.clientX 相对文档的水平座标
event.clientY 相对文档的垂直座标
event.offsetX 相对容器的水平坐标
event.offsetY 相对容器的垂直坐标
document.documentElement.scrollTop 垂直方向滚动的值
event.clientX+document.documentElement.scrollTop 相对文档的水平座标+垂直方向滚动的量
用uniGUI开发的项目中,难免要遇到动态建立一个Form,再释放掉,与传统Delphi项目不一样,这是从forum转贴过来的,要这样写:
//建立方法
if Frm = nil then
Frm := TUniForm1.Create(UniApplication);
//调用及释放方法
Frm.ShowModal(
Procedure(Sender: TComponent; AResult:Integer)
begin
//Frm := nil;//作者这样写的
FreeAndNil(Frm);//应这样写.
end );
1.uniTimer的妙用
很多时候,都会遇到在一个uniForm或者uniFrame加载完后,执行一个具体的动用,比如执行一个查询,当这个动作是调用第三方JS显示库时,如调用百度的ECharts,显示一个分析图,在OnCreate、OnShow、OnFramedLoaded事件都不能显示这个动作的结果。这时候,利用uniTimer来执行,是最好的方法。
2.uniHtmlFrame
看名称就知道是显示html内容的Frame,但遇到不显示html内容的时候,百试不得其解,将同样一个HtmlFrame放到不同的uniFrame上,有的显示,有的不显示。
最后发现当不显示的时候,把uniHtmlFrame.StaticHtml=True解决。
uniGUI的TUniLoginForm类创建的登录窗口默认是不带颜色,可以自定义css风格来改变背景颜色。
一般是通过在UniServerModule中,在CustcomSS属性中,修改extjs的css定义来实现,修改登录窗口的背景颜色可以修改 的定义来实现,如:
.x-body{
background-color: rgb(11, 80, 184);
margin: 0;
}
类似的,还可以给UniLoginForm的背景添加上背景图案等个性化的风格。
Columns下某字段设置为CheckBok
属性:CheckBoxField
FieldValues: 存储的值 [1;0]
DisplayValues: 显示的内容 [是;否] 【如何做到只显示勾项,可以在这里设置为: ; 单个字符即可】
BooleanFieldOnly: 如果True,则要求字段为Boolean类型
1)UniSession.BrowserWindow;
UniSession.BrowserWindow(‘http://www.baidu.com’, 800, 600, ‘’, [bwResizable,bwStatus]);
2)使用AddJS方法;
UniSession.AddJS(‘window.open (’+‘’‘’+str+‘’‘’+‘, ‘‘newwindow’’)’);
3)用HtmlFrame窗口,将代码封装进去。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>某单据打印</title>
<meta http-equiv="Content-Type" content="text/html; charset=GBK" />
</head>
<body>
<iframe id="reportFrame" width="900" height="400" src="http://localhost:8075/WebReport/ReportServer?reportlet=djjj%2Fv_RS_CostApply_1.cpt&BillNo=RSCA160315091149450001"></iframe>
</body>
</html>
使用控件UniScreenMask,设置TargetControl父类控件,设置AttachedControl具体控制的控件。
可以在DisplayMessage里设置等待的中文说明字样。
如果使用自带的Image图片导入后效果为底色黑色,就改用URL传入模式。
UniImage1.Url := ‘http://’+g_ServerIP+‘:’+g_ServerPort+‘/pic/flowinit_arrow_right.png’;