精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>电脑技术>>○ DOS>>实用资料>>DOS程序如何读写Windows剪贴板

主题:DOS程序如何读写Windows剪贴板
发信人: 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]

[关闭][返回]