2008年9月27日星期六

实模式 保护模式和虚拟86模式

首先,80386以及80386以后的CPU都是32位的

纯32位windows是不能进入实模式的,重启以后到载入WINDOWS以前都是实模式,也许你会说windows98不是是可以不用重启机器直接进入到纯DOS(实模式)下么

首先,98是个16位和32混编的系统,所以不稳定,但对游戏支持甚好,而且其内核是建立在16位上的(你要是搞过Win32编程就会有所了解),这样的话进入DOS很方便,或者在DOS下一条win命令就可以进入WINDOWS...

但是从NT开始就不行了,2000/XP都是建立在纯32位(NT开始)内核上的,所以很稳定,但是如果不重新启动到DOS下是不能进行实模式操作的,但是考虑程序的兼容问题,为了让以前的16位程序能在32位下运行,80386就提供了虚拟86模式(这和windows无关,是CPU提供的模式,另外可以告诉你,因为80286没有虚拟86模式,只有实模式和保护模式,当时一些流行的16位程序要使用的话必须重启到DOS下,再进到到保护模式),虚拟86模式实际上就是模拟16位的8086
CPU的实模式,但这和实模式有很大区别,最大的因该算是中断被屏蔽或转为windows的异常处理了,这样你要用诸如:int 13h 命令是行不通的,因为windows是建立在保护模式上的,保护模式下有自己的中断模式,如果你要从windows进入实模式的话只有重新启动再到DOS 下了。

现在几乎不需要进入实模式了,除非你windows中了毒不能进入,到DOS下重装/恢复/备份系统,还有就是一些硬件底层的破解啦,比如破解还原卡之类的。

进入保护模式是每个32位系统必须的,因为这样系统才能才能利用保护模式提供的保护机制管理和维护自己,程序也就稳定了,

虚拟86模式没什么需要不需要,CPU提供这个模式,程序是16位的时候,系统会自动加载到虚拟86模式中运行...

我们在windows下打开的cmd(别忘了98下叫MS-DOS方式,这个模式仍是在16的内核上,而从NT开始的CMD就是纯32位了!!!!)它在系统中的定义是字符模式(非窗口),这样给一些16位的程序提供了运行环境....

2008年9月26日星期五

How to Determine Text File Encoding

With the explosion of international text resources brought by the Internet, the standards for determining file encodings have become more important. This is my attempt at making the text file encoding issues digestible by leaving out some of the unimportant anecdotal stuff. I'm also calling attention to blunders in the MSDN docs.

For Unicode files, the BOM ("Byte Order Mark" also called the signature or preamble) is a set of 2 or so bytes at the beginning used to indicate the type of Unicode encoding. The key to the BOM is that it is generally not included with the content of the file when the file's text is loaded into memory, but it may be used to affect how the file is loaded into memory. Here are the most important BOMs and the encodings they indicate:

  • FF FE UCS-2LE or UTF-16LE
  • FE FF UCS-2BE or UTF-16BE
  • EF BB BF UTF-8

BOM stands for Byte Order Mark which literally is meant to distinguish between little-endian LE and big-endian BE byte order by representing the code point U+FEFF ("zero width no-break space"). Since 0xFFFE (bytes swapped) is not a valid Unicode character, you can be sure of the byte order. Note that the BOM does not distinguish between UCS-2 and UTF-16 (they are the same except that UTF-16 has surrogate pairs to represent more code points). The UTF-8 BOM is not concerned with "byte order," but it is a unique enough sequence (representing the same U+FEFF code point) that would be very unlikely to be found in a non-UTF-8 file, thus distinguishing UTF-8 especially from other "ASCII-based" encodings.

The BOM is not guaranteed to be in every Unicode file. In fact the BOM is not necessary in XML files because the Unicode encoding can be determined from the leading less than sign. If the first byte is an ASCII less than sign 3C followed by a non-zero byte then the file is assumed to be UTF-8 until otherwise specified in the XML Declaration. If the XML file begins with 3C 00 it is UCS-2LE or UTF-16LE (normal for Windows Unicode files). If the XML file begins with 00 3C it is UCS-2BE or UTF-16BE. In summary then:

  • 3C 00 UCS-2LE or UTF-16LE
  • 00 3C UCS-2BE or UTF-16BE
  • 3C XX UTF-8 (where XX is non-zero)

Unlike the BOM, these bytes are part of the text content of the file.

Also, the BOM is not used to determine non-Unicode encodings such as Windows-1250, GB2312, Shift-JIS, or even EBCDIC. Generally you should have some way of knowing the encoding due to the context of your situation. However, markup languages have ways of specifying the encoding in the markup near the top of the file. The following appears inside the area of an HTML page:

charset=utf-8" />

In XML, the XML declaration specifies the encoding.

encoding="iso-8859-1"?>

This works because all of the encodings are compatible enough with ASCII in the lower 128, so the encoding can be specified as an ASCII string. The alternative to ASCII is EBCDIC; if an XML file begins with the EBCDIC less than sign 4C it is treated as EBCDIC and the XML declaration (if present) would be processed in standard EBCDIC to determine the extended EBCDIC variant.

If I hadn't seen fundamental problems in Microsoft documentation before it would be inconceivable to me that in articles about the Unicode BOM, the BOM is shown backwards, but it is true! Both the Byte-order Mark and IsTextUnicode MSDN articles get the UTF-16 BOM bytes backwards. Herfried K. Wagner [MVP] agreed that the documentation is wrong (plain as day but it is still good to be MVP corroborated).

Another thing that irks me is the IsTextUnicode API. This API is so useless it bears mentioning. First of all, it does not deal with UTF-8, so it can only be one part of the way Notepad detects Unicode. Raymond Chen said it is used in Notepad but Notepad actually auto-detects UTF-8 as explained below (his blog, The Old New Thing is one of my three favorites). Secondly, when text is in memory, it should usually not have the BOM with it since it can only be efficient to interrogate the BOM before loading the file. Thirdly, if you cannot guarantee the statistical analysis, you are better off using a simple deterministic mechanism that you can explain to the end user so that they don't experience seemingly erratic behavior.

UTF-8 auto-detection (when there is no UTF-8 BOM) is not widely documented (although it is exhibited by Windows Notepad). UTF-8 multi-byte sequences have a pattern that would be almost impossible to accidentally produce in another encoding. The more non-ASCII characters a UTF-8 file has, the more certain you can be that it is UTF-8, but my impression is that you don't need many.

Without going into the full algorithm, just perform UTF-8 decoding on the file looking for an invalid UTF-8 sequence. The correct UTF-8 sequences look like this:

  • 0xxxxxxx ASCII <>
  • 110xxxxx 10xxxxxx 2-byte >= 0x80
  • 1110xxxx 10xxxxxx 10xxxxxx 3-byte >= 0x400
  • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4-byte >= 0x10000

If the file is all ASCII, you cannot know if it was meant to be UTF-8 or any other character set compatible with ASCII in the lower 128.

Without contextual information, a BOM, or a file type standard with a header like XML and HTML, a file should be assumed to be in the default system locale ANSI code page, governed by the Language for non-Unicode Programs in the Regional Settings on the computer on which it is found.

2008年9月3日星期三

VB为office编写插件

http://www.cnblogs.com/szyicol/archive/2006/10/26/540248.html

通过此演练,可以用 VB 创建 COM 加载项。COM
加载项可以在不给用户增加复杂性的情况下扩展应用程序的功能。究其实质,COM
加载项是一个动态链接库 (DLL),需要进行注册才能供 Microsoft?
Office XP
应用程序加载和使用。虽然可以将加载项编写成可执行文件
(.exe),但 DLL 通常会比.exe 文件提供更好的性能。

  此演练将使用 VB 创建并运行一个自定义工具栏 COM
加载项。本主题中的任务假定您熟悉 Office 应用程序、VB
工程,以及调试和运行代码。

  引言

  创建 COM 加载项时可以使用任何支持 COM 的语言,如 VBA、Visual
Basic 和 Microsoft Visual C 。用 Office Developer
创建的加载项将自动打包成 DLL,并由宿主应用程序注册后进行加载。可以创建一个加载项但能用于多个应用程序中。有关详细信息。请参阅为多个应用程序创建
COM 加载项。

  此演练将完成一系列步骤,从而用 VB 创建一个 COM
加载项。创建 COM 加载项的基本步骤包括:

  1.配置外接程序设计器。

  2.在外接程序设计器中编写代码。

  3.将命令条控件集成到加载项中。

  4.对 COM 加载项进行调试和测试。

  5.为 COM 加载项生成 DLL。

  6.解决 COM 加载项的开发问题。

  配置外接程序设计器

  用外接程序设计器创建的工程为开发加载项提供工作区域。使用外接程序设计器可以创建用于
VBA 或任何 Office 应用程序的 COM
加载项。工程中的每个外接程序设计器都表示一个单独的、只能在一种
Office 应用程序中运行的加载项。创建的 DLL
可包含多个加载项,它们使用相同的窗体、模块和类模块,但面向的却是不同的应用程序。此演练使用
Excel 作为宿主 Office 应用程序。

  如果希望加载项可供多个应用程序使用,就必须为每个宿主应用程序各自添加一个外接程序设计器。可以通过模块共享代码;但在每个工程中,必须引用每个宿主应用程序所特定的对象模型。

  配置外接程序设计器

  1.打开 VB

  2.在“文件”菜单中,选择“新建工程”,然后选择“外接程序”。

  3.把窗体移除,双击设计器中的Connect。

  3.在“外接程序显示名称”文本框中键入名称 Greeting
Toolbar,在“外接程序描述”文本框中键入说明 Toolbar add-in
that launches a Hello World message in Excel。

  4.从“应用程序”列表中选择 Microsoft Excel。

  5.从“应用程序版本”列表中选择 Microsoft Excel 10.0。

  6.从“初始化加载行为”列表中选择 "Startup"。有关各种不同类型初始加载行为的详细信息,请参阅指定加载行为。

  此主题相关图片如下:

  7.在“工程”菜单中,选择“引用”,确保让工程引用下列类型库。(该引用列表是此演练所必需的。对于您的加载项,要确保选择每个可以使用加载项的
Office 应用程序所需的类型库。)

●Visual Basic for Applications

●OLE Automation

●Microsoft Add-in Designer

●Microsoft Office 10.0 Object Library

●Microsoft Excel 10.0 Object Library

  8.在“文件”菜单中选择“保存 Connect”。

  9.在“工程另存为”对话框中,输入名称 Greetings.Dsr,选择要将其保存到的文件夹,然后单击“保存”。


  在外接程序设计器中编写代码

  在创建工程并为外接程序设计器赋值后,可以添加代码将加载项与宿主应用程序连接起来。此演练将向您展示将加载项与宿主应用程序连接起来所需的典型过程和事件。IDTExtensibility2
接口提供连接这二者所需的 COM
对象和事件。然后,加载项可以使用宿主应用程序所展示的对象模型与宿主应用程序接合。可以在对象浏览器中查看特定应用程序的对象模型。

  外接程序设计器中的代码可处理加载项与宿主应用程序的集成。例如,加载或卸载加载项时运行的代码驻留在“外接程序设计器”的模块中。如果加载项中包含窗体,则外接程序设计器还可以包含用于显示窗体的代码。

  声明变量和设置过程存根

  1.在“工程资源管理器”窗口中,选择 Connect,然后打开“视图”菜单,单击“代码”。清除原来有的代码。

  2.在“通用声明”部分,引用可扩展性接口。

Implements IDTExtensibility2

  3.添加用于在加载项和宿主之间提供通讯的模块级变量。只要加载了
COM 加载项,赋值为 As Excel.Application
的变量就一直存在,因此,所有过程都可以确定加载项当前正在哪个应用程序中运行。因为
WithEvents 关键字指派给 cbbButton 变量,所以菜单项的 Click
事件过程将在用户单击新菜单项时触发。


'Global object references

Public appHostApp As Excel.Application

Private WithEvents cbbButton As Office.CommandBarButton


  4.在“代码”窗口中,从“对象”列表中选择
IDTExtensibility2,从“事件”列表中选择 OnConnection。这将创建
OnConnection 事件过程存根。

注意 您必须使由 IDTExtensibility2
界面提供的每个事件中都包括事件过程存根。如果您删除了任何事件过程,工程就无法编译。

  5.为下列每个事件添加事件过程存根:

●OnDisconnection

●OnStartupComplete

●OnBeginShutdown

●OnAddinsUpdate

  现在就可以为您的加载项添加功能了。


  将命令条控件集成到加载项中

  如果您的 COM
加载项有一个用户界面,就可以添加用于显示命令条的代码,以方便用户运行您的加载项。此演练将显示如何在宿主应用程序中包含用于创建新命令条控件(工具栏按钮或菜单项)的代码。加载您的加载项时,会同时加载控件,用户可以通过单击按钮或菜单项打开并使用加载项。

  创建命令条控件

  1.查找 OnConnection 事件过程。在 Private Sub 和 End Sub
行之间,添加代码以创建新的命令条控件并将其指派给支持事件的
CommandBarButton 对象变量。整个过程将显示如下:


Private Sub IDTExtensibility2_OnConnection(ByVal _

Application As Object, ByVal ConnectMode As _

AddInDesignerObjects.ext_ConnectMode, ByVal AddInInst _

As Object, custom() As Variant)

' 存储启动引用

Set appHostApp = Application

' 添加命令条

Set cbbButton = CreateBar()

End Sub


  如果您熟悉使用 Visual Basic
创建加载项,就可能注意到,在 VBA
中创建加载项时,不用设置命令条按钮 OnAction
属性的值。这是因为事件自动为您挂起。

  2.查找 OnDisconnection 事件过程。在 Private Sub 和 End Sub
行之间,添加代码以便在卸载加载项时删除命令条控件。整个过程将显示如下:


Private Sub IDTExtensibility2_OnDisconnection(ByVal _

RemoveMode As AddInDesignerObjects.ext_DisconnectMode, _

custom() As Variant)

RemoveToolbar

' 移除要关闭的引用

Set appHostApp = Nothing

Set cbbButton = Nothing

End Sub


  3.通常,只要在代码中存储函数,就会在 OnConnection
过程中添加您调用的函数对应的代码。该函数将创建命令条,设置命令按钮的属性,并提供错误信息的处理。


Public Function CreateBar() As Office.CommandBarButton

' 指定命令条

Dim cbcMyBar As Office.CommandBar

Dim btnMyButton As Office.CommandBarButton

On Error GoTo CreateBar_Err

Set cbcMyBar = appHostApp.CommandBars.Add(Name:="GreetingBar")

' 指定命令条按钮

Set btnMyButton = cbcMyBar.Controls.Add(Type:=msoControlButton, _

Parameter:="Greetings")

With btnMyButton

.Style = msoButtonCaption

.BeginGroup = True

.Caption = "&Greetings"

.TooltipText = "Display Hello World Message"

.Width = "24"

End With

' 显示并返回命令条

cbcMyBar.Visible = True

Set CreateBar = btnMyButton

Exit Function

CreateBar_Err:

MsgBox Err.Number & vbCrLf & Err.Description

End Function


  4.在 OnDisconnection
过程中添加您调用的函数对应的代码。该函数在加载宏被卸载时会删除命令条。


Private Function RemoveToolbar()

 appHostApp.CommandBars("GreetingBar").Delete

End Function


  5.为 CommandBarButton
对象添加一个单击事件过程。该过程将在单击新的命令条按钮时被调用。下面的代码将显示一条消息以表明单击事件正在进行:


Private Sub cbbButton_Click(ByVal Ctrl As Office.CommandBarButton,
CancelDefault As Boolean)

 MsgBox ("Hello World!")

End Sub


  6.保存您的工程。

  现在,COM
加载项完成。其余的步骤就是调试和测试代码以确保它运行顺利,然后将加载项放入
DLL 文件中,该文件可以在其他装有 Office XP
的计算机上进行分发和使用。


  对加载项进行调试和测试

  当您在 VB 中开发 COM
加载项时,可以通过将工程置于运行模式而调试加载项。如果工程处于运行模式,就可以从
Office 应用程序中加载 COM 加载项并使用它,通过使用任何 VB
调试工具而对它进行测试和调试。

  使用 VB 调试和测试 COM 加载项

  1.将任何所需的断点、Stop 语句或监视放在代码中。(可先不做这步)

  2.在“工程”菜单上,单击“属性”,在“调试”对话框中,选择“等待要创建的部件”,单击“确定”

  3.在“运行”菜单上,单击“全编译执行”。这将对工程进行编译(当出现任何编译错误时将提出警告),然后将工程置于运行模式。

  4.检查“[运行]”是否出现在VB的标题栏中。

  注意 必须发布加载项,宿主应用程序才能使用它。

  4.启动一个新的 Excel
实例。因为将加载项的加载行为设为 "Startup",所以只要启动应用程序,加载项就会加载,OnConnection
事件就会发生,于是出现 Greetings
按钮。现在,您可以使用为调试代码而添加的断点和 Stop
语句了。

  如果单击 Greetings 按钮,则只要在 VB 中运行工程,Hello
World 消息就会出现在编辑器之前(不在 Excel
之前)。在将工程生成为 DLL 文件后,该消息就会出现在 Excel
之前。

  5.当完成调试和测试后,打开“运行”菜单,单击“终止工程”。这会清除临时文件和注册表项,并将工程置于正确的状态以生成
DLL 文件。

  为 COM 加载项生成 DLL

  编写并调试代码后,可以使您的加载项成为一个 DLL
以将其部署到其他装有 Office XP 的计算机上。

  在 VB 中将 COM 加载项打包为 DLL

  1.从“文件”菜单上,选择“生成 myAddin.DLL”。

  2.在“生成工程”对话框中保存文件名 Greetings,并选择要用于保存工程的位置。

  3.单击“确定”。 (此时,加载项可在本机正式使用)

  这一步骤将创建 COM 加载项,添加适当的注册表项,并使COM
加载项可用于 Office 宿主中。创建加载项 DLL 时,VB
使用给外接程序设计器提供的信息,将 DLL 注册为 COM
加载项。VB
向注册表中写入加载项的名称、说明和初始加载行为设置。加载项的宿主应用程序读取这些注册表项并加载相应的加载项。

  常见加载项开发问题疑难解答

  当在开发环境中工作并在应用程序之间进行切换时,可能会遇到某些错误信息或意外行为。下面是一些常见问题及其解决方案。

  出现编译错误或语句结束在编辑器中无效

  要确保为工程引用了适当的对象库。

  运行工程并打开新的宿主应用程序实例时没有任何反应

 

  ●要确保字“已发布的”出现在所运行的加载项的标题栏中。如果不如此,就必须运行工程。

  ●单击每个打开的应用程序窗口。您的对象可能正在运行,但只有在您单击所打开的应用程序的第一个实例时,它才是可见的。

  ●要确保正确地指定并设置模块级变量。

  ●在宿主应用程序中,要确保在“COM 加载项”对话框中选中了您的加载项。可以通过向工具栏中添加
COM 加载项命令而对宿主应用程序进行自定义。此命令将打开“COM
加载项”对话框。

  将 COM 加载项对话框添加到工具栏中

  1.打开EXCEL“工具”菜单,单击“自定义”,选择“命令”选项卡。在“类别”下,选择“工具”。沿“命令”列表向下滚动,以查找“COM
加载项”。将“COM 加载项”拖动到工具栏中,以创建新的按钮,然后关闭“自定义”对话框。

  2.在该工具栏上,单击刚添加的“COM 加载项”按钮。

  3.在“COM 加载项”对话框中,确认选中您的加载项旁边的复选框。若要卸载加载项,请清除该复选框。

  对象出现在宿主应用程序中但没有响应

  可能是有多个对象实例在运行。用于检测和移除已有的具有该名称的代码可能没在运行。检查并调试您的
OnDisconnection 代码。

--------------------------------------------------------.

another:http://www.excelperfect.com/2008/06/08/%E4%BD%BF%E7%94%A8vb6%E7%BC%96%E5%86%99com%E5%8A%A0%E8%BD%BD%E9%A1%B9/

Office Addin 自动化(Automation)基础概念

http://www.winxgui.cn/blog/?p=101

自动化(Automation)基础概念:二次开发接口(API)与插件(Addin)

在前文,我们已经解释了:

而同时,我们经常也可能经常听到以下这些词语:

  • 自动化(Automation,COM Automation)
  • OA(办公自动化,Office Automation)
  • 二次开发接口(应用程序开发接口,Application Programming Interface,API)
  • 插件(Addin,Addon)

等等。本文试图解释这些概念。

自动化(Automation)顾名思义是指“让机器在没有人工干预的情况下自动完成特定的任务”。为了完成这一目标,自动化(Automation)技术的核心想法是,应用程序(Application)需要把自己的核心功能以DOM模型的形式对外提供,使得别人能够通过这个DOM模型来使用该应用程序的功能。这也就是我们通常说的应用程序编程接口:Application Programming Interface,简称API。为了与Windows API这样的编程接口区分开来,我们引入一个专有名词,叫“二次开发接口”。“二次开发”取意于“在现有应用程序基础上进行再开发”。其实如果你愿意把操作系统当作一个更大的应用程序的话,二次开发接口和Windows API并没有什么很大的本质上的差异(尽管我们知道Windows API并不是以COM组件方式提供的)。

理解了自动化(Automation),OA(办公自动化,Office Automation)就比较好解释,无非是应用程序特指办公软件而已。而OA是指办公(包括公文流转)系统的自动化。

在应用程序提供了编程接口(API)的前提下,典型情况下,我们有两种办法来使用这些API。方法一是把应用程序当作一个Server,通过API 对外提供服务。在此情形下,应用程序只是作为一个EXE COM Server的服务程序而已。只要我们理解进程间的LPC或者RPC调用是怎么回事,那么一切就非常Easy。方法二是实现一个应用程序插件 (Addin)。这种方法更有意思一些。首先,这是一种进程内的调用,效率非常好。其次,这是一种双向的通讯,应用程序通过它提供的插件机制感知到插件的 存在,并且将插件加载上来;插件则是在获得活动权后,通过应用程序的API完成特定的功能。最后,也是最重要的,插件与应用程序融为一体,实际上是扩展了 应用程序的能力,使得应用程序变得更为强大。

插件(Addins)的启动过程大体如下:

  1. 应用程序启动。通过注册表(或者存放于其他任何地方)获得插件列表。插件一般以 COM 组件形式提供,故此只要有一个插件的 CLSID 或者 ProgID 的列表就可以了。另外,插件的功能可以千差万别,但是他们需要统一实现一个接口,例如 _IDTExtensibility2 或者类似的东西。这个接口在下面的第二步就用到了。
  2. 遍历插件列表,创建并初始化各插件。关键是初始化。当然应用程序并不知道插件想做什么,它只是取得 _IDTExtensibility2(或者类似接口),调用其中的初始化函数(如 OnConnection)。
  3. 插件获得了初始化机会。注意,在初始化的时候,应用程序把自己的DOM模型的根接口(我们通常称为Application)传入。在 _IDTExtensibility2 中, 根接口被定义为 IDispatch 类型,即 IDispatch* Application。但是实际上可以更通用,如IUnknown* Application。有了这个 Application 指针,插件就可以为所欲为,做它想做的事情,调用它想要调用的任何API。

从插件(Addins)展开来讲,可以讲非常多的内容。然而这不是本文的意图。所以关于这方面的内容,我们只能留待以后有机会继续这个话题。不过我 还是忍不住把话题起个开头:由于插件(Addin)机制使得应用程序结构显得更为灵活,所以,越来越多的软件架构,追求一种超轻量的内核(也就是我们说的 应用程序,之所以称为内核,是因为它是组织一切的核心),并把更多的功能通过插件(Addin)方式提供。超轻量的内核意味着需要解决一个额外的关键点: 就是插件(Addin)不只是扩展应用程序的功能,也同时扩展了应用程序的API,这些API与原有内核的API无缝地结合在一起,从而使得整个系统可以 滚雪球一样越滚越大。