posts - 13,  comments - 8,  trackbacks - 0
摘要: 熟悉么?反正我是烦透了!不管他是个什么玩意,暂且把它叫做度娘的防御机制。它很烦?跳过它!怎么跳?看代码:procedure DeleteIECache(httpStr: string); // 清理IE缓存,IE.cookiesvar lpEntryInfo: PInternetCacheEntryInfo; hCacheDir: LongWord; dwEntrySize: LongWord; cachefile: string; begin dwEntrySize := 0; FindFirstUrlCacheEntry(nil, TInterne...阅读全文
posted @ 2011-09-20 16:44 Bach 阅读(289) 评论(1) 编辑
摘要: 看了动车的报道,从来没有这样强烈的想法:好想有鬼神,好想有仙侠,好想穿越!好想有青天,好想有大侠,好想仗剑江湖! 是GJ这台机器的程序BUG?是那些肥肠满脑的蛀虫在DDOS?是怎么了?怎么感觉就和我这种程序菜鸟一样,没有做大型程序的经验,就蛮干,虽然有一个系统的样子了,但是漏洞频出? 不废话,直接上代码: var Obj:对象; Action:动作; LawIsEnabled:Boolean; begin if Obj=农民 then begin LawIsEnabled:=True; if Action=劳动 then begin Showmessage('劳动最光荣,你很光荣!&#阅读全文
posted @ 2011-07-27 09:46 Bach 阅读(168) 评论(2) 编辑
摘要: 最近用到access数据库做小软件,无奈是access对数据的批量操作没有mysql方便,曾一度傻傻地用TClientDataSet把服务器返回的xml用LoadFromStream加载进来,再For循环insert到表中,这个笨办法在数据量小的时候可以,毕竟TClientDataSet比xmlDocument用起来方便,但是数据量大,超过1000就有点不堪重负了。 首先,TClientDataSet.LoadFromStream在数据量大的时候CPU占用量大,且会造成程序无影响(本想在LoadFromStream中加入sleep()和application.ProgressMessage,.阅读全文
posted @ 2011-07-08 10:30 Bach 阅读(916) 评论(0) 编辑

  用惯了EmbeddedWB,不想换,但是IE内核一直存在内存泄漏问题,没办法,只有寻找替代品了。

  要把用习惯的EmbeddedWB换成完全不一样的TChromium,有点挑战,特别是在资料不多,英语没过三级的情况下。未来趋势是这样,只有慢慢啃了。

  首先,想到的是跨域,如果不能跨域,就没办法替代手上的成品。TChromium的跨域比想像中的简单,直接通过chrm.Browser.GetFrameNames(list);//list:tstringList;取得各个IFrame/Frame的名称(所谓名称不是指name属性,只是一个标识,在有name时,返回name,没有name时,ID 也行,都没有时,自动生成一个唯一名称),如:

  ff                                                                       //这个是一个框架的ID

  <!--framePath //ff/<!--frame0-->--> 

  <!--framePath //ff/<!--frame1-->-->

  <!--framePath //ff/<!--frame2-->-->                   //后面三个是自动生成的唯一名称

获取指定Frame时,通过chrm1.Browser.Frame['frame 的名称'],取得ICefFrame接口,后面的操作请随意。

  其次是填表,用过google浏览器的都知道,其填表功能实在强大,在webbrowser时代,一般都是获取表单元素的各种接口,然后设置其value、checked等属性,而在TChromium中,一切皆js,把想做的事都让js去执行吧,所以,用TChromium,js功力深厚的会轻松很多了。比如:

strTemp := 'document.forms[0].inmembername.value="User_Name";'; 
  JavaExec(strTemp); 
  strTemp := 'document.forms[0].inpassword.value="Password";'; 
  JavaExec(strTemp); 
  strTemp := 'document.forms[0].submit.click();'; 
  chrm.browser.Frame['ff'].ExecuteJavaScript(str,'about:blank',0);; //想在哪一层frame执行,就调用哪一层

更神奇的是,还可以通过以下方法加载属于自己的jquery到浏览器中:

procedure TForm3.chrm1LoadEnd(Sender: TCustomChromium;
  const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer;
  out Result: TCefRetval);
var
  str:string;
begin
   str:='var oHead = document.getElementsByTagName(''HEAD'').item(0);'#13#10+
      'var oScript = document.createElement( "script" );'#13#10+
      'oScript.language = "javascript";'#13#10+
      'oScript.type = "text/javascript";'#13#10+
      'oScript.id = "sid";'#13#10+
      'oScript.defer = true;'#13#10+
      'oScript.src = "jquery.js";'#13#10+
      'oHead.appendChild( oScript );'#13#10+
      'alert("8")' ;
   Frame.ExecuteJavaScript(str,'about:blank',0);
end;

直接连接本地的js!!!这段代码最后写在LoadEnd中,每加载完成一个frame,就让这个frame加载自己的jquery,如果在需要使用的时候再去加载jquery,jquery加载是需要时间的,可能会导致紧接着的js代码不能生效。

  最后,最后先到这里,下一次再说关于弹出窗口、右键菜单、摸拟鼠标点击等内容。

附:google论坛,delphi TChromium的问题讨论群组:http://groups.google.com/group/delphichromiumembedded

posted @ 2012-04-20 17:53 Bach 阅读(833) 评论(1) 编辑
摘要: webbrowser 跨域阅读全文
posted @ 2012-03-22 11:53 Bach 阅读(1251) 评论(0) 编辑

  问题来源如下:有一个EXE和两个DLL,用到同一个公共单元:

unit UnitBpl;

interface
uses Classes;
type
TBaseClass= class of TBase;

TBase=class(TPersistent)
public
procedure show;virtual;
end;

implementation

{ TBase }

procedure TBase.show;
begin

end;

end.

在DLL_1中:

Type

TMy1=class(TBase)
public
procedure Show;override;
end;

implementation


procedure TMy1.Show;
begin
inherited;
ShowMessage('我是TMy1');
end;

initialization
RegisterClass(TMy1);
finalization
UnregisterClass(TMy1);

DLL_2中:

Type

TMy2=class(TBase)
public
procedure Show;override;
end;

implementation


procedure TMy2.Show;
begin
inherited;
ShowMessage('我是TMy2222');
end;

initialization
RegisterClass(TMy2);
finalization
UnregisterClass(TMy2);

EXE中:

procedure TFrmMain.btn1Click(Sender: TObject);
var
myObj:TBase;
BaseClass:TBaseClass;
begin
BaseClass:=TBaseClass(FindClass('TMy2'));//TBaseClass(FindClass('TMy1'));
myObj:=BaseClass.Create;
myObj.show;

end;

  目的很明显了,就是想从dll_1和dll_2 中导出相同父类的不同子类,但是在loadLibary的时候,会提示如下图:

提示名为TBase的类已经存在!!!为什么呢?  

RegisterClass(TMy2);
RegisterClass(TMy1); 
  没有注册TBase类啊?

如果注释掉其中一句RegisterClass,则哥运行,当然,

BaseClass:=TBaseClass(FindClass('TMy2'))
这一句就会出错了

因为其中有一个类未注册

 

期待高手为人解惑。。



posted @ 2012-02-25 19:05 Bach 阅读(98) 评论(0) 编辑

  关于idhttp取网页源码编码问题,在这里记录最后一次的解决方法,不想再纠结下去,再也伤不起了。(本文内容均在d2010,indy10.55的环境下产生及结束)。

  网上只要搜索关于idhttp取网页乱码,idyttp编码问题的文章有一大堆,试了无数,都不满意,最后再这里记录一下个人解决方法。

  在IDE中写如下代码,str:=http.get(xxxxx);然后Ctrl跟踪get,会在源码中得到如下一行,也是最关键的一行:

Result := ReadStringAsCharset(LResponse, Response.CharSet);

很明显,idhttp想给我们做点好事,直接返回解码后(能正常阅读、没有乱码)的内容,问题来了,当Response.CharSet有值时,返回的内容是完全正确的,当Response.CharSet没有值时,返回的结果值得商榷了。所以就有了网上常有人问的“为什么在UTF-8的情况下,返回内容是正常的,但是GBK的就不行了?”,经我测试,当网页是UTF-8时,Response.CharSet='utf-8',当网页是GBK时,Response.CharSet就不一定是GBK,很多时候都是空的,这时候,在使用上面的函数时,CharSet默认为西欧(可能吧)编码,得到的内容比UTF-8编码后的结果更难看懂。所以,我们要做的,就是给CharSet一个可用的、正确的值。

  如果得到一个可用的、正确的CharSet值呢?首先,idhttp.Response.CharSet这个是首选的,如果这个值为空呢,就需要在返回的HTML中找了,如:

<html> 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>执行 Application.Terminate 后, OnDestroy 中的代码还会执行 - 万一 - 博客园</title>
<link type="text/css" rel="stylesheet" href="http://www.cnblogs.com/css/common.css"/>

在上面代码中醒目的部分,charset=utf-8,我们要的就是这个,这部分是英文,所以不管什么编码,都能正常得到这部分内容,需要做的就是用正则把charset=后面的内容取出,再判断具体的编码,一般只需要考虑两种情况:utf-8和gbk,实现代码如下:

function Txxxxxx.getMethod(AURL: string): string;
var
LResponse: TMemoryStream;
LEncoding:TIdTextEncoding;
per:TPerlRegEx;
begin
LResponse := TMemoryStream.Create;
try
try
http.Get(AURL, LResponse);
finally
http.Disconnect;
end;
LResponse.Position := 0;
if http.Response.CharSet<>'' then
begin
LEncoding := CharsetToEncoding(http.Response.CharSet);
if AnsiSameText(http.Response.CharSet,'utf-8') then
isutf8:=true
else isutf8:=False;
end
else
begin
LEncoding := TEncoding.Default;
Result := ReadStringFromStream(LResponse, -1, LEncoding);

per:=TPerlRegEx.Create(nil);
per.Options:=[preCaseLess];
per.Subject:=Result;
per.RegEx:='<meta[\S\s]*?charset=(.*)>';
if per.Match then
begin
if AnsiContainsText(per.MatchedExpression,'utf-8') then
begin
isutf8:=true;
LEncoding := CharsetToEncoding('utf-8');
end
else
begin
isutf8:=False;
LEncoding := CharsetToEncoding('gbk');
end;
end;
FreeAndNil(per);
end;
LResponse.Position := 0;
Result := ReadStringFromStream(LResponse, -1, LEncoding);
finally
FreeAndNil(LResponse);
end;
end;

我承认,我欺骗了你,因为在上面的代码中,我没有给CharSet找一个正确的值,而是用到了IdGlobal, IdGlobalProtocols中的两个函数,直接返回一个理想的内容,就像你看到的,首先,需要一个http:IDHTTP和isutf8:boolean,然后直接调用 str:=GetMethod(xxxxxx)就可以得到内容了。

  通过如上方法,能解决80%的网页编码问题,为什么不是100%呢,因为还有一部分的网页,通过idhttp.get,你会发现Response.CharSet='',并且在HTML中没有设置编码的meta标签,如果这种情况,请不要纠结,略过它吧。。。。

  注明:本文只适合菜鸟阅读,也欢迎高手拍砖。



posted @ 2012-02-20 16:58 Bach 阅读(2306) 评论(2) 编辑

  最近做一个软件,用webbrowser做软件界面,通过js的window.external调用delphi的函数实现数据库操作等功能,在需要返回值的时候,遇到问题了,来源如下图:

在接口中加入一方法,传入参数为BSTR(wideString)类型,希望返回VARIANT(OLEVariant),自动生成的函数结构如下:

  在***_TLB.pas中:

 

Itest = interface(IDispatch)
['{D9941302-C827-4517-ADA0-003D176E9E9A}']
function Method1(const a: WideString): OleVariant; stdcall;
end;

 

 在接口实现单元中:

 

type
Ttest = class(TAutoObject, Itest)
protected
function Method1(const fd: WideString): OleVariant; stdcall;

end;

implementation

uses ComServ;

function Ttest.Method1(const fd: WideString): OleVariant;
begin

end;

 

运行后,在网页中调用:

  

var a=window.external.Method1('fdsa');
alert(a);

执行时,报错;
纠结很久,对函数重新申明如下图:

 

在***_TLB.pas中:

Itest = interface(IDispatch)
['{D9941302-C827-4517-ADA0-003D176E9E9A}']
function Method1(const a: WideString): OleVariant; safecall;
end;

在接口实现单元中:

  Ttest = class(TAutoObject, Itest)
protected
function Method1(const a: WideString): OleVariant; safecall;

end;

implementation

uses ComServ;

function Ttest.Method1(const a: WideString): OleVariant;
begin

end;


运行后可正常显示返回内容,对于我这种菜鸟来说,唯一的区别就是safecallstdcall, 由于没有程序基础,用delphi全靠自学,不太明白这两个东西的区别,暂时不管他,只要程序能工作就行,在这里做个记录,以免再犯错。



			
posted @ 2012-02-11 18:53 Bach 阅读(168) 评论(0) 编辑
摘要: 刚从D7转过来有点不习惯,到发贴时都没搞懂string,ansistring,widestring的区别与具体使用环境。 这里主要记录一些在D2010中使用自带INDY10.5.5 post网站的一些问题(主要用于发贴)。 首先,与大家一样,遇到的是使用TIdMultiPartFormDataStream,post中文变乱码(这个乱码不是UTF8那种乱码,是一串“口”),网上说把IdMultipartFormData.pas中的IdRead函数修改,如下:function TIdMultiPartFormDataStream.IdRead(var VBuffer: TIdBytes; ...阅读全文
posted @ 2011-11-30 13:00 Bach 阅读(817) 评论(2) 编辑
摘要: RT。idhttp的httpOption,默认为[hoForceEncodeParams],即自动编码参数,但是idhttp自动编码有点小问题,如果参数中有" (空格)",会转成“+”,有加号会转成“ (空格)”,问题来了,如果我想提交一个参数,值为一个MD5值(MD5中很可能有“+”),在自动编码过程中,加号被编码成空格,最终导致参数错误。所以,post参数最好还是自己用函数编码,这样比较放心,附上urlEncode函数:function EncodeURL(const InputStr: string): string;var Idx: Integer;begin Re阅读全文
posted @ 2011-10-13 13:30 Bach 阅读(544) 评论(0) 编辑
摘要: 用关键词“idhttp cookie”在各大搜索引擎得到的结果,大多千篇一律,如果你搜索到这一篇,恭喜你,你有福了。 以下内容测试环境:delphi2007, winxp sp3, indy10。 一、idhttp的自动维护cookie功能。 idhttp的AllowCookies属性默认是true,意思是自动维护cookie,所以,打算用idhttp登陆网站、发贴等操作,只需要设置此属性为true就行了。 二、提交自定义cookie。 如其它帖子所说,设置idhttp的cookie有多种说法,经我测试,以下两条有用: 1:http1.Request.CustomHeaders...阅读全文
posted @ 2011-10-10 16:22 Bach 阅读(1172) 评论(0) 编辑
摘要: (******************************************************)(* **工作室 *)(* HTML解析单元库 *)(* *)(* DxHtmlParser Unit *)(* ...阅读全文
posted @ 2011-09-21 16:38 Bach 阅读(188) 评论(0) 编辑
摘要: 熟悉么?反正我是烦透了!不管他是个什么玩意,暂且把它叫做度娘的防御机制。它很烦?跳过它!怎么跳?看代码:procedure DeleteIECache(httpStr: string); // 清理IE缓存,IE.cookiesvar lpEntryInfo: PInternetCacheEntryInfo; hCacheDir: LongWord; dwEntrySize: LongWord; cachefile: string; begin dwEntrySize := 0; FindFirstUrlCacheEntry(nil, TInterne...阅读全文
posted @ 2011-09-20 16:44 Bach 阅读(289) 评论(1) 编辑
仅列出标题  下一页