发信人: chenjr() 
整理人: smallhors(1999-07-22 22:57:43), 站内信件
 | 
 
 
 
  
 
     现在再也没有人会怀疑Windows将取代DOS了,但由于种种原因,特别是在拥 有大量正在运行的DOS程序的情况下,软件开发还只能逐步从DOS向Windows过渡, 如何使DOS程序与Windows程序进行数据交换就成了一个重要的问题。在介绍我们 的解决方案之前,先简单回顾一下经典的方法[1]。一般是由处于实模式的DOS程 序先申请一块常规内存,然后由Windows程序利用Windows 3.x API中的三个函数 :AllocSelector()、SetSelectorBase()和SetSelectorLimit(),在保护模式下 读写这块内存,从而实现Windows和DOS程序的数据交换。这种方法在实时数据采 集方面有很好的效果,但它也有两个比较大的缺点:一个是Windows程序设计比较 麻烦,特别是初学者容易导致GPF错误,而且难于用Visual Basic和FoxPro实现; 另一个是在Win32 API中取消了这三个函数,使得Windows 95程序不能再采用这一 方法。我们的方法是让DOS程序直接读写Windows的剪贴板,这样可以象其他Wind ows程序一样利用剪贴板交换数据。这种方法可以在一些经典方法不能使用的场合 获得较好的效果。
 
     我们知道,DOS程序调用系统功能都是通过中断实现,而Windows程序则是通 过一组API来实现的,但这并不等于说Windows就不使用中断了。在Windows中不光 是文件操作使用了DOS中断,它自身特有的许多功能也是通过中断实现,这其中就 包括了我们所要用到的剪贴板函数。不单单是Windows 3.x使用了内部中断,Win dows 95也使用了大量的内部中断。Windows的内部中断主要是利用了INT 2FH,所 有在Windows下运行的程序(包括MS-DOS应用程序)都可以调用这些中断。所以D OS程序可以象Windows程序一样完全合法地调用这些Windows功能,只不过这种方 法是秘密的,在Windows SDK手册上没有介绍。剪贴板函数使用的都是INT 2FH的 17号功能,即AH=17H。比如在Windows程序读写剪贴板之前都要调用OpenClipboa rd()函数,这个函数对应着17号功能的1号子功能,可以用下面这段代码来实现: 
 
 MOV AX, 1701H
 INT 2FH
 
     类似地,我们可以实现Windows API中的EmptyClipboard()、CloseClipboar d() 、SetClipboardData()和GetClipboardData()函数。除此以外,我们还发现 了一个在SDK手册上没有的GetClipboardDataSize()函数,这个函数返回剪贴板的 数据大小,这个数值通常是16的整数倍,它比剪贴板上实际字符串的长度要大, 这个函数对你在读剪贴板之前进行内存分配很有帮助。下面这段示例程序包括了 这些函数的实现。在调用这些中断之前先要确保Windows已经运行,示例中的IsW indowsRunning()函数就是完成这一工作的。你甚至可以用老掉牙的编译系统Tur bo C 2.0来运行它。示例程序先在剪贴板上写入一个字符串,然后从剪贴板读回 这个字符串。你可以发现整个示例程序的编程同Windows程序的差别是很小的,这 是此种方法的一个优点:你对DOS程序的修改可以减少到最少,而Windows程序则 不需要任何修改。可以预见,如果你把DOS部分移植到Windows上来,此处所需的 改动也是很少的。
 
 #include <stdlib.h>
 #include <dos.h>
 #include <string.h>
 
 union REGS r;
 struct SREGS sr;
 
 /*
 The OpenClipboard function opens the clipboard. Other applications
 will not be able to modify the clipboard until the CloseClipboard
 function is called.
 */
 void OpenClipboard()
 {
 r.x.ax = 0x1701;
 int86(0x2f, &r, &r);
 }
 
 /*
 The EmptyClipboard function empties the clipboard and frees handles
 to data in the clipboard.
 */
 void EmptyClipboard()
 {
 r.x.ax = 0x1702;
 int86(0x2f, &r, &r);
 }
 
 /*
 The CloseClipboard function closes the clipboard.
 */
 void CloseClipboard()
 {
 r.x.ax = 0x1708;
 int86(0x2f, &r, &r);
 }
 
 /*
 The SetClipboardData function sets the data in the clipboard. The
 application must have called the OpenClipboard function before
 calling the SetClipboardData function.
 */
 int SetClipboardData(char* s)
 {
 int Len;
 
 Len = strlen(s) + 1;
 r.x.ax = 0x1703;
 r.x.dx = 1;
 r.x.si = 0;
 r.x.cx = Len;
 r.x.bx = FP_OFF(s);
 sr.es = FP_SEG(s);
 int86x(0x2f, &r, &r, &sr);
 return r.x.ax;
 }
 
 /*
 The GetClipboardDataSize function retrieves the size of the current
 clipboard data. This function is undocumented in Windows SDK.
 */
 int GetClipboardDataSize()
 {
 r.x.ax = 0x1704;
 r.x.dx = 1;
 int86(0x2f, &r, &r);
 return r.x.ax;
 }
 
 /*
 The GetClipboardData function retrieves a handle of the current
 clipboard data having string format. The clipboard must have been
 opened previously.
 */
 int GetClipboardData(char* s)
 {
 
 r.x.ax = 0x1705;
 r.x.dx = 1;
 r.x.bx = FP_OFF(s);
 sr.es = FP_SEG(s);
 int86x(0x2f, &r, &r, &sr);
 return r.x.ax;
 }
 
 /*
 The IsWindowsRunning function detects whether Windows is running.
 The application must have called this function before calling all
 Clipboard functions.
 */
 int IsWindowsRunning()
 {
 r.x.ax = 0x1700;
 int86(0x2f, &r, &r);
 return r.x.ax != 0x1700;
 }
 
 void main()
 {
 char s[256],s2[]="This string is passed by an MS-DOS application.";
 
 if (!IsWindowsRunning()) {
 printf("Windows is NOT running!\n");
 exit(- 1);
 }
 
 OpenClipboard();
 SetClipboardData(s2);
 printf("Data size=%d, string length=%d\n", GetClipboardDataSize(s2),
         strlen(s2));
 GetClipboardData(s);
 printf("%s\n", s);
 CloseClipboard();
 getch();
 }
     我们不需要再编写一个Windows的示例程序,因为你可以在任何一个能够进行 文本粘贴的Windows 3.x或Windows 95的程序中,比如NotePad,来检验这一结果 。从Windows使用者的角度来看,你甚至感觉不到这个字符串是来自DOS的。如果 打开Windows的剪贴板查看程序,你会发现此时剪贴板上的数据格式为“文本”和 “OEM文本”两种。
 
     由于Windows利用剪贴板交换图形数据使用的是位图句柄,而这不易于DOS应 用程序操作,所以利用本方法交换图形时最好不使用Windows定义的位图格式。本 方法也不是万能的,它对于时序要求严格的或数据更新很快的场合不太适用。另 外,我们还没有找到如何截取Windows的DDE消息的办法,所以目前这种方法不能 实现DOS程序和Windows程序间的DDE连接。
 
 
  
 
  -- 小白小白。一洗就白
 表白表白。一清二白。。。。。。。。。
                  你忠实的朋友!!!!!
  ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.34.196]
  | 
 
 
 |