如鹏网 大学生计算机学习社区

CowNew开源团队

http://www.cownew.com 邮件请联系 about521 at 163.com

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  363 随笔 :: 2 文章 :: 808 评论 :: 0 Trackbacks

#

在与COM对象交互的时候有的时候我们得到一个对象,我们想知道它的类型,可以使用Object.GetType()方法得到的类型却是System.__ComObject,因为System.__ComObject是代表所有COM对象的,但是它对我们来说是没有任何意义的。如果想得到System.__ComObject的真正类型只要使用Microsoft.VisualBasic.Information.TypeName(objWindow.Object)就可以了,如果是非VB.net工程需要引用Microsoft.VisualBasic.dll 才能保证编译通过。
12月6日添加说明:
经过反编译TypeName方法,发现其核心实现为:
    UnsafeNativeMethods.ITypeInfo pTypeInfo = null;
    string pBstrName = null;
    string pBstrDocString = null;
    string pBstrHelpFile = null;
    UnsafeNativeMethods.IDispatch dispatch = VarName as UnsafeNativeMethods.IDispatch;
    if (((dispatch != null) && (dispatch.GetTypeInfo(0, 0x409, out pTypeInfo) >= 0)) && (pTypeInfo.GetDocumentation(-1, out pBstrName, out pBstrDocString, out num, out pBstrHelpFile) >= 0))
    {
        str5 = pBstrName;
    }

和猜想的一致,它确实是通过IDispatch接口来完成的(呵呵,貌似也只有这一种方式)
posted @ 2007-12-05 13:01 CowNew开源团队 阅读(5666) | 评论 (0)编辑 收藏

        刚才客户打电话过来说系统有问题,分析他发过来的日志后发现原来程序中用Integer.parserInt的方法把字符串形式的金额解析为整形,以前金额较小没有发现问题,今天发了一笔大额交易,总金额是2150220201,正好比Integer在32位平台上的最大值2147483647大一点点,所以发生了转换异常。
经验再次提醒我们:
        为了防止精度、大金额溢出等问题,禁止在涉及到金额的地方使用integer、double、float等原始类型,统一使用BigDecimal、BigInteger。在python中也有对应的类型decimal类型用来进行不限精度的。
posted @ 2007-12-04 14:52 CowNew开源团队 阅读(416) | 评论 (0)编辑 收藏

去掉一个字符串中的$符号以及大括号中的字符(包括大括号)。
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main
{
 public static void main(String[] args)
 {
  Pattern p = Pattern.compile("(\\$)|(\\{.+?\\})");
  Matcher m = p.matcher("abc$ggg{12dgd3}");
  System.out.println(m.replaceAll(""));
 }
}

posted @ 2007-11-26 14:46 CowNew开源团队 阅读(2996) | 评论 (1)编辑 收藏

本章翻译人 CowNew开源团队 周晓

记号词表

每一个文法都指定了带有规则(子结构)和词表语言结构。这些符号在运行时被转换成整型的"记号类型"从而可以有效的比较。定义从符号到记号类型的映射的文件对ANTLR和ANTLR生成的分析器来说是基础。 这份文档描述了ANTLR使用和生成的这类文件,还介绍了用于控制词表的选项。

导言

在分析时,一个语法分析器文法通过符号在它的词表里引用记号要符合由词法分析器或其他几号流生成的Token对象。记号类型储存在记号对象中,每种符号的值是唯一的,分析器比较这些整数来判断记号类型。如果分析器期望下一个记号类型是23,但发现第一个超前扫描记号类型,LT(1).getType(),不是23,这时分析器抛出MismatchedTokenException异常。

一个文法可能有一个导入词表,经常也会有一个导出词表,用于被其他文法引用。导入的词表从未被修改,通过它可以知道词表的"初始条件"。不要和导入词汇混淆了。

下面列出了最常见的问题:

ANTLR如何决定哪一个词法符号是什么记号类型?

每个文法有一个记号管理器来管理文法的导出词表。从文法的importVocab选项,记号管理器以 符号/记号类型 的形式被预载。这个选项强制ANTLR寻找有如下映射关系的文件:

PLUS=44

没有importVocab选项,文法的记号管理器是空的(稍后会看见一个警告)。

你的文法中的任意记号没有预设值,它们被按照遇到的顺序赋值。例如,在下面的文法中,记号A和B分别是4和5:

class P extends Parser;
a : A B ;

词法文件以如下形式命名: NameTokenTypes.txt.

为什么记号类型从4开始?

因为ANTLR在分析过程中需要一些特殊的记号类型,用户定义的记号类型必须在3后开始。

ANTLR生成什么样的词表文件?

ANTLR为词表V生成VTokenTypes.txtVTokenTypes.javaV是文法的名字或者是exportVocab选项指定的名字。文本文件有点像一个简化的记号管理器,保存着ANTLR需要的一些信息,供定义在其他文件中的文法查看其词表信息等等。Java文件是是一个包含了记号类型常量定义的接口。ANTLR生成的分析器实现了其中的一个接口,获得所需要的记号类型定义。

ANTLR怎样同步符号类型在相同文件和不同文件间文法的映射?

一个文法的导出词表必须是另一个文法的导入词表或者2个文法必须共享一个公共的导入词表。

设想p.g中有一个语法分析器P:

// yields PTokenTypes.txt
class P extends Parser;
// options {exportVocab=P;} ---> default!
decl : "int" ID ;

l.g中有一个词法分析器L

class L extends Lexer;
options {
importVocab=P; // reads PTokenTypes.txt
}
ID : ('a'..'z')+ ;

即使L主要是P的词表中的值,但ANTLR生成的是LTokenTypes.txt和LTokenTypes。

不同文件中的文法必须共享同样的记号类型空间,使用importVocab选项去预载同样的词表。

如果这些文法在同一个文件中,ANTLR会用同样的方法处理它。然而,你可以通过设置它们的导出词表到同一个文件来使这2个文法共享同一个词表。例如,如果P和L在一个文件中,你可以这样做:

// yields PTokenTypes.txt
class P extends Parser;
// options {exportVocab=P;} ---> default!
decl : "int" ID ;
class L extends Lexer;
options {
exportVocab=P; // shares vocab P
}
ID : ('a'..'z')+ ;

如果你没有为L指定词表,它将会选择共享文件中导出的第一个词表;在这里,它将共享P的词表。

// yields PTokenTypes.txt
class P extends Parser;
decl : "int" ID ;
// shares P's vocab
class L extends Lexer;
ID : ('a'..'z')+ ;

记号类型映射文件像这样:

P    // exported token vocab name
LITERAL_int="int"=4
ID=5

文法继承和词表

文法继承父文法的规则,动作和选项,但是子文法使用什么词表和记号词表呢?ANTLR对子文法的处理就好像你复制粘贴父文法的所有非重载规则到子文法。因此,子文法记号的集合就是父文法和子文法的交集。所有的文法都导出词表所以子文法导出并使用一个和父文法不同的词表文件。除非你使用importVocab选项重载,否则子文法导入父文法的词表。

文法Q继承P,会预先设置好P的词表,就好像Q使用了importVocab=P选项。例如,下面的文法有2个记号符号。

class P extends Parser;
a : A Z ;

子文法Q,最初和父文法有相同的词表,但随后会增加一些符号。

class Q extends P;
f : B ;

在上面的情况,Q定义了几个符号,B使得Q的词表为{A,B,C}.

一个子文法的词表一般是父文法词表的父集。注意重载规则不影响最初的词表。

如果你的子文法需要父文法未使用过的新词法结构,你或许需要子语法分析器使用一个子词法分析器。使用importVocab选项指定子词法分析器的词表来重载它初始的词表。例如,假设语法分析器P使用词法分析器PL。不用importVocab重载,Q的词表将使用P的词表,即PL的词表。如果你想让Q使用另一个词法分析器的记号类型,比如说使用QL,那么做下面的事情:

class Q extends P;
options {
importVocab=QL;
}
f : B ;

Q的词表现在和QL的词表相同或者是QL词表的父集。

识别器生成次序

如果你所有的文法在一个文件中,你就不用担心ANTLR将会最先处理哪一个文法文件,不过你仍要担心ANTLR处理文件中文法的次序。如果你尝试去导入一个会被另一个文法导出的词表,ANTLR将提示它不能读取这个文件。下面的文法文件会造成ANTLR出错:

class P extends Parser;
options {
importVocab=L;
}
a : "int" ID;
class L extends Lexer;
ID : 'a';

ANTLR在文法文件中还没有发现文法L,所以它将提示不能发现LTokenTypes.txt。另一方面,如果LTokenTypes.txt存在(比如说在文法文件中还没有P文法的时候ANTLR运行生成的),ANTLR将为P读取这个文件,然后在处理L文法的时候覆盖掉它。ANTLR不知道它要处理的文法恰好在一个文件中,所以它假设是要读取从另一个文件生成的词表。

一般的,如果你想让文法B使用文法A的记号类型(无论什么文法类型),你必须首先对A运行ANTLR。例如,一个树文法用到了分析器文法的词表,应该在ANTLR生成了分析器之后再去处理树文法。

例如,当你想让一个词法分析器和一个语法分析器共享同一个词表空间的时候,你要做的就是去把它们放到同一个文件中,设置它们的导出词表到同一个空间。如果它们在分开的文件中,把语法分析器的导入词表选项设置为词法分析器的导出词表,除非记号都定义在语法分析器中,这时,换一下导入/导出的关系让词法分析器使用语法分析器的导出词表。

词表的一些使用技巧

如果你的文法在不同的文件中,你仍想让它们共享全部或部分记号空间,该怎么办。有2种解决方案:(1) 让文法导入同样的词表 (2) 让文法继承同一个父文法,该父文法含有记号空间。

第一个方案在下面情况使用,你有2个词法分析器和2个语法分析器,语法分析器必须要处理从根本上就不同的输入部分。ANTLR 2.6.0发行版examples/java/multiLexer中的例子就属于这种情况。javadoc注释和Java代码部分的词法分析和语法分析过程都不一样。javadoc词法分析器有必要识别"*/"中止注释的词法结构,但它一般让Java语法分析器用打开/关闭的记号引用来嵌套运行javadoc语法分析器:

javadoc
: JAVADOC_OPEN
{
DemoJavaDocParser jdocparser =
new DemoJavaDocParser(getInputState());
jdocparser.content();
}
JAVADOC_CLOSE
;

问题在于:javadoc词法分析器定义了JAVADOC_CLOSE,即也定义了它的记号类型。不幸的是Java语法分析器的词表基于Java词法分析器而不是javadoc词法分析器。 要让javadoc词法分析器和java词法分析器都可以看到JAVADOC_CLOSE (并且有同样的记号类型),2个词法分析器都要导入含有这种记号类型定义的词表。这里有DemoJavaLexer和DemoJavaDocLexer的头部:

class DemoJavaLexer extends Lexer;
options {
importVocab = Common;
}
...
class DemoJavaDocLexer extends Lexer;
options {
importVocab = Common;
}
...

CommonTokenTypes.txt有:

Common // name of the vocab
JAVADOC_CLOSE=4

共享词表的第二种方案在下面情况使用,你有1个语法分析器和3个不同的词法分析器(比如说为不同类型的C)。如果你只想语法分析器空间利用率高,语法分析器必须可以访问3个词法分析器的词表,去掉文法不用的结构(大概可以用语义断言)。给出CLexer,GCCLexer和MSCLexer,CLexer作为父文法定义出所有记号的集合。例如,如果MSCLexer需要"_int32",那么在CLexer中定义一个所有词法分析器可见的记号类型:

tokens {
INT32;
}

在MSCLexer中,你可以给它实际意义的字符。

tokens {
INT32="_int32"
}

用这种方法,3个词法分析器共享同一个记号空间,允许你用一个语法分析器识别多种C的输入。

Version: $Id: //depot/code/org.antlr/release/antlr-2.7.6/doc/vocab.html#1 $
posted @ 2007-11-24 17:40 CowNew开源团队 阅读(2181) | 评论 (0)编辑 收藏

原文:http://blog.csdn.net/nileel/archive/2007/04/17/1567656.aspx

Java和C#都提供了对网络的不同抽象层,编程人员可以使用不同的网络接口完成对网络的操作。

Java C#
应答/请求:
java.net.URL和java.net.URLConnection。
System.Net.WebRequest。

协议:
TCP/IP协议使用java.net.Socket和java.net.ServerSocket;
UDP协议使用java.net.DatagramSocket和java.net.MulticastSocket。
CP/IP协议使用System.Net.Sockets.TCPListener和System.Net.Sockets.TCPClient;
UDP协议使用TSystem.Net.Sockets.UDPClient

原始套接字层:
没有。
System.Net.Sockets.Socket


  应答/请求层可以用于HTTP类的请求,其中的一端开始启动一个连接,发送一些字节的数据,然后停止,等待对方作为应答发回的一些字节。对于象流这样更灵活的操作,协议层的用处更大。对于大多数的Java编程人员来说,除非需要完成性能非常高的网络操作,不需要对套接字进行直接控制。如果需要。C#仍然提供了对原始的Berkeley套接字进行控制的能力。


应答/请求层:

  这个层次抽象掉了所有网络层的细节,提供了一个可以双向传输数据的象流那样的接口。Java可以接受HTTP URL,并通过下面的命令完成GET命令:

URL url= new URL( "http://to.post.to.com" );
URLConnection urlConnection url.openConnection();
InputStream input urlConnection.getInputStream();
... read stuff from input ...
input.close();

  C#通过System.Net.WebRequest对象完成同样的功能:

 WebRequest request= WebRequestFactory.Create(
  "http://to.post.to.com" );
 Stream input request.GetResponse().GetResponseStream();
 ... read stuff from input ...
 input.Close();

  二种语言都隐藏了底层的套接字创建HTTP协议要求,而是提供了编程人员可以用来发送和接收数据的流。与C#中的Stream类一样,WebRequest类有可以异步地获得流进行写或从中读数据的流的方法,或者可以从中读取数据的WebResponse对象。

  协议层:

  对于熟悉java.net.Socket的Java编程人员对于System.Net.Sockets.TCPClient应该非常熟悉,因为二者是非常相似的。由于编程人员无须处理套接字的实现,而只须返回一个可供使用的流,因此二者的API和功能都非常相似。

  在Java中可以使用下面的命令实现一个非常简单的telnet客户端:

Socket telnet= new Socket( "telnet.host.com", 23 );
OutputStream output= telnet.getOutputStream();
InputStream input= telnet.getInputStream();

  二个流都可用于与telnet同telnet.host.com的连接中。同样功能的程序可以以相同的风格在C#中用下面的方式实现:

TCPClient telnet= new TCPClient( "telnet.host.com", 23 );
Stream telnetStream= telnet.GetStream();
StreamWriter output =new StreamWriter( telnetStream );
StreamReader input =new StreamReader( telnetStream );


  接收TCP/IP连接在二种语言中几乎是相同的。在Java中,可以用下面的命令建立、并接收TCP/IP连接:

ServerSocket server= new ServerSocket( 23 );
Socket accept =server.accept();


  在C#中的实现方式如下:

TCPListener server= new TCPListener( 23 );
server.Start();
Socket accept= server.Accept();


  在二种语言中,每个接收的套接字都需要单独处理。在Java中,比较好的方法(直到Java 1.4)是为每个接收的套接字产生一个线程。在C#中也可以作同样的处理,Socket类提供了使用带有select方法的事件驱动的接口。(在事件驱动方式下对套接字编程已经超出了本文的范围。)

  原始套接字层:

  这一部分的内容对于大多数Java程序员来说都是陌生的。由于被java.net.Socket和 java.net.DatagramSocket二个类进行了抽象,只使用Java编程语言的编程人员几乎无需了解Berkeley套接字的实现。通过对Berkeley Socket类进行操作,同样可以实现Java中的流功能。
至此,我们已经用C#中的命令实现了大多数在Java中被抽象的功能━━对I/O和网络的操作。
posted @ 2007-11-23 00:02 CowNew开源团队 阅读(599) | 评论 (0)编辑 收藏

一篇介绍写自定义浏览器的很好的文章:
from:http://www.codeproject.com/csharp/ExtendedWebBrowser.asp

Sample Image

Contents

  1. Introduction
  2. The goals, challenges, and solutions
  3. Creating the extended WebBrowser component
  4. Using the component
  5. Conclusion

1: Introduction

.NET 2.0 has a new WebBrowser control in the System.Windows.Forms namespace. This control itself is very useful, but doesn't supply some events that might be needed in certain situations. This article explains how to extend the WebBrowser control and add functionality for things like pop-up blocking, script error handling, and handling new windows in a tabbed browser environment.

For extending the WebBrowser control, some features are not documented in the Help files of the .NET Framework. Not letting us be stopped by the "This method supports the .NET Framework infrastructure and is not intended to be used directly from your code." message, it is possible to create an object that implements IWebBrowser2 and use all the functionality of the underlying browser. Besides this, DWebBrowserEvents2 can be implemented for adding events to the control.

This article assumes that you have already some knowledge of the browser interfaces IWebBrowser2 and DWebBrowserEvents2. Some knowledge about COM Interop and interfaces is also required.

2: The goals, challenges, and solutions

The goals of this component are:

  • Handling script errors in a neat way
  • Blocking unwanted pop-ups
  • Enabling functionality for tabbed browsing or MDI browsing
  • Making sure that a window is closed when it is closed by script

This section explains the problems associated with the goals and their solutions, in a short form. The next section goes more into the coding details.

Handling Script Errors

The WebBrowser control has a ScriptErrorsSuppressed property... Setting this property to true does actually a bit more than it is supposed to. It not only disables the script error dialog, but also the dialog for logging on to a secure website with user certificates... What if we still want that functionality, or we would like to be notified when a script error has taken place, or we would like to know all the details about the script error?

The script error can be caught by the HtmlWindow.Error event. This event fires whenever a script error occurs, with all the details. The challenge is that HtmlWindow is to be accesed with the HtmlDocument object, which is not always available. HtmlDocument comes available as soon as the Navigated event is fired. But what if the user refreshes the browser with F5? Sorry, the Navigated event doesn't fire. After some testing, I found that the only reliable way was to use the DownloadComplete event, which is not part of the default WebBrowser control.

Solution:

  1. Implement DWebBrowserEvents2
  2. Create a DownloadComplete event
  3. When DownloadComplete fires, subscribe to the HtmlWindow.Error event
  4. Use the error event for obtaining the script error information
  5. Set the Handled property to true to suppress the script error

Blocking unwanted pop-ups

Pop-ups are most of the time not very welcome, or could be inappropriate. To block these things, some additional information is needed. NewWindow3 gives this information when the user uses Windows XP SP2, or Windows 2003 SP1 or better. If this event is not fired, NewWindow2 takes its place. When NewWindow3 is fired, you can check:

  • If the user initiated the action that leads to the new window
  • If the user holds the override key (the Ctrl Key)
  • If it is a pop-up displayed because of a window that is closing
  • The URL that is going to be opened
  • And more...

Using NewWindow3 clearly is very interesting for this purpose. To use this event, DWebBrowserEvents2 needs to be implemented.

Solution:

  1. Implement DWebBrowserEvents2
  2. Create a new event and a new event arguments class
  3. Launch this event with the appropriate information
  4. After the event is fired, see if the navigation needs to be canceled

Enabling functionality for tabbed browsing or MDI browsing

Tabbed browsing seems to gain popularity these days. For Internet Explorer 7, this is one of the new features. The challenge in tabbed browsing is that you need to create a window when this is needed by scripts or links. Besides this, window name resolution should work over multiple windows or tabs. (For example: <A href="http://SomeSite" target="SomeWindowName"/>) To achieve this, the automation object (called ppDisp in the NewWindowX event, and Application in the IWebBrowser2 interface) should be passed from the new browser back to the event. To get access to the Application property, it is needed to get a reference to the underlying IWebBrowser2 interface.

Solution:

  1. Override AttachInterfaces and DetachInterfaces
  2. Store a reference to the IWebBrowser2 interface object
  3. Create a property called Application that exposes the Application property of the interface
  4. Implement the DWebBrowserEvents2 interface
  5. Listen for NewWindow2 and/or NewWindow3 events
  6. Whenever an event is raised, create a new instance of the browser control
  7. Assign the event parameter ppDisp to the Application property of the new instance

Making sure that a window is closed when it is closed by script

When you invoke window.close() in JScript, it looks like the WebBrowser control hangs. Somehow, it can't be used for navigation, nor can it be used for anything else. It would be nice if we know when this happens. There are several events that fire when this happens, but none of the events gives us actually the information needed. Overriding WndProc and seeing if the parent is notified that the browser is destroyed, is the only reliable solution. (If someone knows how to get WindowClosing to work, it would be nice here!)

Solution:

  1. Override WndProc
  2. Check for the message WM_PARENTNOTIFY
  3. Check for the parameter WM_DESTROY
  4. If this is the case, fire a new event (this event is called Quit, in the example)

3: Creating the extended WebBrowser component

From the last section, we have seen that all of this basically comes down to two things:

  1. Implement an object of type IWebBrowser2, for obtaining the Application property of the browser
  2. Implement DWebBrowserEvents2 for firing events

Implementing IWebBrowser2

The WebBrowser control has two methods that are undocumented: AttachInterfaces() and DetachInterfaces(). These methods need to be used when you want to obtain a reference to the IWebBrowser2 interface.

Collapse
  /// <summary>
/// An extended version of the <see cref="WebBrowser"/> control.
/// </summary>
public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser
{
private UnsafeNativeMethods.IWebBrowser2 axIWebBrowser2;
/// <summary>
/// This method supports the .NET Framework
/// infrastructure and is not intended
/// to be used directly from your code. 
/// Called by the control when the underlying
/// ActiveX control is created. 
/// </summary>
/// <param name="nativeActiveXObject"></param>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void
AttachInterfaces(object nativeActiveXObject)
{
this.axIWebBrowser2 =
(UnsafeNativeMethods.IWebBrowser2)nativeActiveXObject;
base.AttachInterfaces(nativeActiveXObject);
}
/// <summary>
/// This method supports the .NET Framework infrastructure
/// and is not intended to be used directly from your code. 
/// Called by the control when the underlying
/// ActiveX control is discarded. 
/// </summary>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void DetachInterfaces()
{
this.axIWebBrowser2 = null;
base.DetachInterfaces();
}
...
}

Next, we can add the Application property.

/// <summary>
/// Returns the automation object for the web browser
/// </summary>
public object Application
{
get { return axIWebBrowser2.Application; }
}

This property can be used for creating a new window, and redirecting the browser to this new window, when a new window event is fired.

Implementing DWebBrowserEvents2

The following events are implemented in this sample:

  • NewWindow2 and NewWindow3 (for blocking pop-ups and creating new windows)
  • DownloadBegin and DownloadComplete (for handling script errors)
  • BeforeNavigate2 (if you want to see where you're going before even starting to get there)

To neatly implement DWebBrowserEvents2, it is best to create a privately nested class in the component. This way, all the events that are needed are on one place and easy to find. When we instantiate this class, we provide a reference to the caller, whose methods can be invoked for raising the events we need.

Events are not attached at component construction, but a bit later. There are two methods here that provide this and can be overridden. These are CreateSink() and DetachSink(). When adding this all up, we get something like this (note that some code has been cut for readability):

Collapse
  /// <summary>
/// An extended version of the <see cref="WebBrowser"/> control.
/// </summary>
public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser
{
// ... (More code here)
System.Windows.Forms.AxHost.ConnectionPointCookie cookie;
WebBrowserExtendedEvents events;
/// <summary>
/// This method will be called to give
/// you a chance to create your own event sink
/// </summary>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void CreateSink()
{
// Make sure to call the base class or the normal events won't fire
base.CreateSink();
events = new WebBrowserExtendedEvents(this);
cookie = new AxHost.ConnectionPointCookie(this.ActiveXInstance,
events, typeof(UnsafeNativeMethods.DWebBrowserEvents2));
}
/// <summary>
/// Detaches the event sink
/// </summary>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void DetachSink()
{
if (null != cookie)
{
cookie.Disconnect();
cookie = null;
}
}
/// <summary>
/// Fires when downloading of a document begins
/// </summary>
public event EventHandler Downloading;
/// <summary>
/// Raises the <see cref="Downloading"/> event
/// </summary>
/// <param name="e">Empty <see cref="EventArgs"/></param>
/// <remarks>
/// You could start an animation
/// or a notification that downloading is starting
/// </remarks>
protected void OnDownloading(EventArgs e)
{
if (Downloading != null)
Downloading(this, e);
}
// ... (More code here)
    #region The Implementation of DWebBrowserEvents2 for firing extra events
//This class will capture events from the WebBrowser
class WebBrowserExtendedEvents :
UnsafeNativeMethods.DWebBrowserEvents2
{
public WebBrowserExtendedEvents() { }
ExtendedWebBrowser _Browser;
public WebBrowserExtendedEvents(ExtendedWebBrowser
browser) { _Browser = browser; }
      #region DWebBrowserEvents2 Members
// ... (More code here)
public void DownloadBegin()
{
_Browser.OnDownloading(EventArgs.Empty);
}
public void DownloadComplete()
{
_Browser.OnDownloadComplete(EventArgs.Empty);
}
// ... (More code here)
      #endregion
}
    #endregion
}

4: Using the component

In the last section, we created a new component. Now, it's time to use the new events and get the maximum functionality out of the browser. For each of the goals, the details are explained here.

Handling the script errors

In the sample application, there is a tool window that simply shows a list of errors that occured, with their details. A single-instance class holds the script errors' information and notifies the subscribers when this information has been changed. For handling these script errors, the BrowserControl first attaches to the DownloadComplete event, and next subscribes to the HtmlWindow.Error event. When this event is fired, we register the script error and set the Handled property to true.

Collapse
  public partial class BrowserControl : UserControl
{
public BrowserControl()
{
InitializeComponent();
_browser = new ExtendedWebBrowser();
_browser.Dock = DockStyle.Fill;
// Here's the new DownloadComplete event
_browser.DownloadComplete +=
new EventHandler(_browser_DownloadComplete);
// Some more code here...
this.containerPanel.Controls.Add(_browser);
// Some more code here...
}
void _browser_DownloadComplete(object sender, EventArgs e)
{
// Check wheter the document is available (it should be)
if (this.WebBrowser.Document != null)
// Subscribe to the Error event
this.WebBrowser.Document.Window.Error +=
new HtmlElementErrorEventHandler(Window_Error);
}
void Window_Error(object sender, HtmlElementErrorEventArgs e)
{
// We got a script error, record it
ScriptErrorManager.Instance.RegisterScriptError(e.Url,
e.Description, e.LineNumber);
// Let the browser know we handled this error.
e.Handled = true;
}
// Some more code here
}

Blocking unwanted pop-ups, and enabling functionality for tabbed browsing or MDI browsing

Handling pop-ups should be user configurable. For the purpose of demonstration, I've implemented four levels, ranging from blocking nothing to blocking every new window. This code is part of the BrowserControl, and shows how to do this. After the new window is allowed, the example shows how to let the new browser participate in the window name resolution.

Collapse
void _browser_StartNewWindow(object sender,
BrowserExtendedNavigatingEventArgs e)
{
// Here we do the pop-up blocker work
// Note that in Windows 2000 or lower this event will fire, but the
// event arguments will not contain any useful information
// for blocking pop-ups.
// There are 4 filter levels.
// None: Allow all pop-ups
// Low: Allow pop-ups from secure sites
// Medium: Block most pop-ups
// High: Block all pop-ups (Use Ctrl to override)
// We need the instance of the main form,
// because this holds the instance
// to the WindowManager.
MainForm mf = GetMainFormFromControl(sender as Control);
if (mf == null)
return;
// Allow a popup when there is no information
// available or when the Ctrl key is pressed
bool allowPopup = (e.NavigationContext == UrlContext.None)
|| ((e.NavigationContext &
UrlContext.OverrideKey) == UrlContext.OverrideKey);
if (!allowPopup)
{
// Give None, Low & Medium still a chance.
switch (SettingsHelper.Current.FilterLevel)
{
case PopupBlockerFilterLevel.None:
allowPopup = true;
break;
case PopupBlockerFilterLevel.Low:
// See if this is a secure site
if (this.WebBrowser.EncryptionLevel !=
WebBrowserEncryptionLevel.Insecure)
allowPopup = true;
else
// Not a secure site, handle this like the medium filter
goto case PopupBlockerFilterLevel.Medium;
break;
case PopupBlockerFilterLevel.Medium:
// This is the most dificult one.
// Only when the user first inited
// and the new window is user inited
if ((e.NavigationContext & UrlContext.UserFirstInited)
== UrlContext.UserFirstInited &&
(e.NavigationContext & UrlContext.UserInited)
== UrlContext.UserInited)
allowPopup = true;
break;
}
}
if (allowPopup)
{
// Check wheter it's a HTML dialog box.
// If so, allow the popup but do not open a new tab
if (!((e.NavigationContext &
UrlContext.HtmlDialog) == UrlContext.HtmlDialog))
{
ExtendedWebBrowser ewb = mf.WindowManager.New(false);
// The (in)famous application object
e.AutomationObject = ewb.Application;
}
}
else
// Here you could notify the user that the pop-up was blocked
e.Cancel = true;
}

The reason the event is called StartNewWindow is that the code design guidelines do not allow an event to begin with "Before" or "After". "NewWindowing" doesn't have the same kind of ring to it :)

Using the Quit event

When the Quit event is fired, it's simply a matter of finding the right window or tab to close, and Dispose the instance.

5: Conclusion

The WebBrowser control is a good control for enabling web content in Windows applications. The additions in this article can be used to overcome the obstacles that developers face when they have no control over what web pages or other content the user might visit with their application. Hopefully, the next version of the .NET Framework will give us a little extra.

The sample application and source

The sample application is not a flashy UI, but it does demonstrate everything about this article. The code is commented, and hopefully gives enough information for helping you put your own solution together.

Acknowledgements

I would like to thank the following persons that made part of this article possible:

  • The technique for DWebBrowserEvents2 was in the bug list of Microsoft .NET 2.0. This has been used with modification.
  • The technique for WndProc was told by someone called "JoeBlow" on the MSDN forums, who had it derived from the MSKB article #253219.

This is my first article on The Code Project. Please excuse me for my English. Thanks for reading! If you can add anything or have suggestions or tips, please post a message below.

License

This code is copyrighted by The Wheel Automatisering in The Netherlands. Some rights are reserved.

The code in this license may be used for any purpose, just let your users know where it came from, and share derived code under the same license as this one. Don't blame me if something goes wrong. More information can be found here.

If you wish to use and/or publish this in commercial closed-source applications, you have my consent. You may use this code under your own license when you do so.

History

  • 27th of March 2006: First post of this article.

About Jeroen Landheer


I am
- born in The Netherlands
- living in Chile together with my wife.
- a Microsoft Certified Professional Developer on all 3 areas (Windows, Web and Enterprise)
- an MCITP on Microsoft SQL Server 2005 (Database Administrator)
- an active programmer for about 14 years.
- a business owner, of a Dutch company called "The Wheel Automatisering" (http://www.thewheel.nl)
- a coder in C#, VB.Net and Managed C++.
- someone who likes to share knowledge

For fun I like to go out with my dogs, enjoy the sun or write some articles that I share with the community.

Click here to view Jeroen Landheer's online profile.

posted @ 2007-11-20 13:27 CowNew开源团队 阅读(1743) | 评论 (0)编辑 收藏

from ftplib import FTP
import time,os,sys

print "按回车开始备份"
raw_input()

ftp=FTP()
ftp.set_debuglevel(2)
ftp.connect('服务器IP', '21')
ftp.login("用户名","密码")
ftp.cwd('/wwwroot/bbs/DataBase')
now = time.localtime()
blocksize = 1024
poststr = str(now.tm_year)+"-"+str(now.tm_mon)+"-"+str(now.tm_mday)
filename=r'e:\网站备份\bbs\database\Dbbs7'+poststr+'.asp'
if(os.path.isfile(filename)):
    print "文件已经存在"
    raw_input()
    sys.exit()
file_handler = open(filename,'w').write
ftp.retrbinary("RETR Dbbs7.asp", file_handler, blocksize)
ftp.quit()
print "下载完毕"
raw_input()

 

posted @ 2007-11-20 10:51 CowNew开源团队 阅读(463) | 评论 (0)编辑 收藏

实现了一个简单的请假审批功能,展示了一个常用JBPM API的使用,工程下载地址:

http://www.blogjava.net/Files/huanzhugege/myjbpm002.zip
posted @ 2007-11-19 20:17 CowNew开源团队 阅读(572) | 评论 (0)编辑 收藏

 

已经可以比较好的运行JBPM了,但是如果能以图形化的方式显示工作流,并且把当前节点高亮显示,这样可用性就更好了,用户可以很轻松的看到当前流程到哪个节点了。

       我发现JBPMstarters-kit的例子中就有类似的效果,所以决定分析一下它是怎么实现的。

       打开网页,浏览到有显示当前工作流节点的页面,查看到此页面的地址为task.jsp,发现其中的核心代码如下:

<jbpm:processimage task="${taskBean.taskInstanceId}"/>

       这里使用了JBPM提供的jbpm:processimage标签,此标签定义在jbpm.tld中,这个Tag的类为org.jbpm.webapp.tag.ProcessImageTag。所以只要使用这个标签我们就可以很轻松的在Web页面中显示图形化的工作流了。

       那么如果是在SwingSWT等非Web界面中也想显示这种效果怎么办呢?那么让我们来分析一下ProcessImageTag类。

 private void retrieveByteArrays() {

    try {

      FileDefinition fileDefinition = processDefinition.getFileDefinition();

      gpdBytes = fileDefinition.getBytes("gpd.xml");

      imageBytes = fileDefinition.getBytes("processimage.jpg");

    } catch (Exception e) {

      e.printStackTrace();

    }

 }

       gpd.xml中记录的是节点的位置关系,processimage.jpg是图形化的图片(只是基图,没有高亮显示当前节点),这两个文件是JBPMEclipse插件自动生成的。

       得到流程实例当前节点的方法:

 private void initialize() {

    JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();

    if (this.taskInstanceId > 0) {

           TaskInstance taskInstance = jbpmContext.getTaskMgmtSession().loadTaskInstance(taskInstanceId);

           currentToken = taskInstance.getToken();

    }

    else

    {

           if (this.tokenInstanceId > 0)

                  currentToken = jbpmContext.getGraphSession().loadToken(this.tokenInstanceId);

    }

    processDefinition = currentToken.getProcessInstance().getProcessDefinition();

 }

       currentToken中可以得到当前节点在显示的时候的长度、宽度、横纵坐标等值。得到的方式如下:

 private int[] extractBoxConstraint(Element root) {

    int[] result = new int[4];

    String nodeName = currentToken.getNode().getName();

    XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']");

    Element node = (Element) xPath.selectSingleNode(root);

    result[0] = Integer.valueOf(node.attribute("x").getValue()).intValue();

    result[1] = Integer.valueOf(node.attribute("y").getValue()).intValue();

    result[2] = Integer.valueOf(node.attribute("width").getValue()).intValue();

    result[3] = Integer.valueOf(node.attribute("height").getValue()).intValue();

    return result;

 }

       这样用<div/>标签就可以将当前节点框上一个红色的框框了:

           jspOut.println("<div style='position:relative; background-image:url(" + imageLink + "); width: " + imageDimension[0] + "px; height: " + imageDimension[1] + "px;'>");

       //详细代码参考:writeTable方法

原来高亮显示是在原有的图片上叠加一个高亮的框框实现的。所以如果要显示在SwingSWT中的话也只要参考这个思路,在当前节点位置显示一个高亮的框框就可以了!

posted @ 2007-11-19 17:44 CowNew开源团队 阅读(6038) | 评论 (8)编辑 收藏

本版主要新增特性:
  1、对Show语句的支持

       自从CowNewSQL2.1开始,我们提供了对Show语句的支持,主要用来查看系统中的表定义、字段定义、支持的函数等。由于各个数据库中取得这些元信息的方式各有不同,经常需要关联查询很多系统表才能搬到,为了简化用户的使用,我们创新性的设计了Show系列语句,这样您至少使用非常短的语句就可以实现以前需要编写很复杂的语句才能实现的功能。

       Show语句语法列表:

1show  tables:显示系统中默认Schema下的所有表的表名。

2show  tables Schema名:显示指定Schema下的所有表的表名。例子:show tables DEMO

3show  functions:显示系统支持的函数的列表。

4show  functioncolumns:显示系统支持的函数参数以及返回值的详细说明。

5show  tablecolumns 表名:显示指定表的数据列信息。例子:show  tablecolumns table_1。
2、提供了JDBC驱动的使用方式 

       自从CowNewSQL2.1开始,我们提供了以JDBC驱动方式使用的支持(支持最新的JDBC4.0标准)。通过这种方式用户无需修改系统的任何代码,只要修改原有的JDBC连接字符串就可以轻松的将CowNewSQL融入系统,使用CowNewSQLJDBC驱动后系统中所有的SQL语句在送到数据库系统中执行前都将会自动进行翻译。

       CowNewSQLJDBC驱动类为:com.cownew.cownewsql.imsql.jdbc.DBDriver;连接字符串格式为:jdbc:cownewsql:目标数据库类型:目标数据库JDBC驱动类:JDBC连接字符串。

使用方式举例:

       原有程序连接到Oracle数据库,使用的Oracle驱动类为oracle.jdbc.driver.OracleDriverJDBC连接字符串为:jdbc:oracle:thin:@192.168.88.128:1521:XE

       我们只要将CowNewSQLJar包(包括cownewsql***.jarantlr.jarcommons-lang**.jarretrotranslator-runtime**.jar等)加入程序的ClassPath,然后修改使用的数据库驱动为:com.cownew.cownewsql.imsql.jdbc.DBDriver,然后修改JDBC连接字符串为:jdbc:cownewsql:oracle:oracle.jdbc.driver.OracleDriver:jdbc:oracle:thin:@192.168.88.128:1521:XE

       这样我们无需修改任何代码就将CowNewSQL翻译器轻松的植入了原有系统。
3、增加了对Alter Table语句的支持;修正了Convert函数在各个数据库中取值范围不一致的Bug;改进了方言管理器的实现机制;修复了若干Bug。

下载地址1:http://www.blogjava.net/Files/huanzhugege/cownewsql-2.1.zip
下载地址2:http://www.cownew.com/Soft/UploadSoft/cownewsql-2.1.zip


=======================================================================================
 

       由于种种原因,各个数据库系统的SQL语句语法以及支持的函数都不尽相同,这造成了如下两个问题:(1)系统在多个不同数据库之间移植变得非常困难,特别是需要维护多个数据库版本的时候;(2)开发人员必须对各种数据库的语法差异非常了解,这加大了开发难度。

       虽然Hibernate通过HQL等技术部分的解决了跨数据库移植的问题,但是在对性能要求比较高的场合还是需要直接使用SQL语句访问数据库的,在这种情况下如何编写能被不同数据库支持的SQL语句就成了。目前解决这种差异的最常用的技术就是SQL语句翻译,使用SQL翻译器可以将SQL语句翻译为在不同的数据库中支持的特定平台的SQL语句。CowNewSQL就是这样一款产品。

       CowNewSQL简化了跨数据库产品的开发,比如取当前日期在MSSQL中是“SELECT GETDATE()”,在MYSQL中是“SELECT NOW()”,在Oracle中是“SELECT SYSDATE FROM DUAL”,使用CowNewSQL以后您只要使用“SELECT NOW()”,那么CowNewSQL就会为您自动将其翻译为对应数据库平台支持的SQL语句,而且CowNewSQL的兼容性也非常好,比如“SELECT NOW()”写成“SELECT GETDATE()”同样可以被正确的翻译;取数据库前10条记录,在MSSQL中是“Select top 10 from T_1”、在MYSQL中是“SELECT  LIMIT 0, 10 ”、在Oracle中是“SELECT  FROM DUAL WHERE ROWNUM <= 10”,使用CowNewSQL以后您只要使用“Select top 10 from T_1”,那么CowNewSQL就会为您自动将其翻译为对应数据库平台支持的SQL语句。

       CowNewSQL还通过变通的方式对目标数据库不直接支持的语法进行了支持。比如MYSQL是不支持“select * from t1 where fid in(select fid from t2 limit 0,5)”这样在子查询中的Limit语句的,CowNewSQL通过将子查询进行二次结果集包装的方式巧妙的对其进行了支持,“delete from T_SaleInvoice where FId in(select top 5 FParentId from T_SaleInvoiceDetails)”通过CowNewSQL的翻译以后就成了“DELETE FROM T_SaleInvoice WHERE FId IN (select * from(SELECT FParentId FROM T_SaleInvoiceDetails LIMIT 0, 5 ) t_temp_sub)”这样被MYSQL支持的语法了;MYSQL中没有提供计算两个日期之间月份差异的函数,CowNewSQL通过组合其他日期函数的方式模拟了这个函数,这样使用者只要使用MONTHS_BETWEEN函数即可了,无需关心内部的差异。

       CowNewSQL支持如下几种类型的SQL语句:CreateTable/AlterTable/DropTable/CreateIndex/DropIndex/Select/Insert/Delete/Update/Show;支持子查询、JoinUnion等高级的SQL特性;支持日期(包括取当前日期、从日期中提取任意部分、计算日期差异、日期前后推算等)、数学(包括取绝对值、取PI值、四舍五入、对数计算、随机数等)、字符串(包括取子字符串、取字符串长度、字符串截断、大小写转换等)、基本数据处理(包括数字字符串互转、日期转字符串、非空判断等)等函数。

posted @ 2007-11-17 15:27 CowNew开源团队 阅读(2903) | 评论 (10)编辑 收藏

仅列出标题
共30页: First 上一页 5 6 7 8 9 10 11 12 13 下一页 Last