?? dos程序如何讀寫windows剪貼板.txt
字號:
DOS程序如何讀寫Windows剪貼板
李海
本文發(fā)表在98年7月1日《計算機世界》7期
現(xiàn)在再也沒有人會懷疑Windows將取代DOS了,但由于種種原因,特別是在擁有大量正在運行的DOS程序的情況下,軟件開發(fā)還只能逐步從DOS向Windows過渡,如何使DOS程序與Windows程序進行數(shù)據(jù)交換就成了一個重要的問題。在介紹我們的解決方案之前,先簡單回顧一下經(jīng)典的方法[1]。一般是由處于實模式的DOS程序先申請一塊常規(guī)內(nèi)存,然后由Windows程序利用Windows 3.x API中的三個函數(shù):AllocSelector()、SetSelectorBase()和SetSelectorLimit(),在保護模式下讀寫這塊內(nèi)存,從而實現(xiàn)Windows和DOS程序的數(shù)據(jù)交換。這種方法在實時數(shù)據(jù)采集方面有很好的效果,但它也有兩個比較大的缺點:一個是Windows程序設計比較麻煩,特別是初學者容易導致GPF錯誤,而且難于用Visual Basic和FoxPro實現(xiàn);另一個是在Win32 API中取消了這三個函數(shù),使得Windows 95程序不能再采用這一方法。我們的方法是讓DOS程序直接讀寫Windows的剪貼板,這樣可以象其他Windows程序一樣利用剪貼板交換數(shù)據(jù)。這種方法可以在一些經(jīng)典方法不能使用的場合獲得較好的效果。
我們知道,DOS程序調(diào)用系統(tǒng)功能都是通過中斷實現(xiàn),而Windows程序則是通過一組API來實現(xiàn)的,但這并不等于說Windows就不使用中斷了。在Windows中不光是文件操作使用了DOS中斷,它自身特有的許多功能也是通過中斷實現(xiàn),這其中就包括了我們所要用到的剪貼板函數(shù)。不單單是Windows 3.x使用了內(nèi)部中斷,Windows 95也使用了大量的內(nèi)部中斷。Windows的內(nèi)部中斷主要是利用了INT 2FH,所有在Windows下運行的程序(包括MS-DOS應用程序)都可以調(diào)用這些中斷。所以DOS程序可以象Windows程序一樣完全合法地調(diào)用這些Windows功能,只不過這種方法是秘密的,在Windows SDK手冊上沒有介紹。剪貼板函數(shù)使用的都是INT 2FH的17號功能,即AH=17H。比如在Windows程序讀寫剪貼板之前都要調(diào)用OpenClipboard()函數(shù),這個函數(shù)對應著17號功能的1號子功能,可以用下面這段代碼來實現(xiàn):
MOV AX, 1701H
INT 2FH
類似地,我們可以實現(xiàn)Windows API中的EmptyClipboard()、CloseClipboard() 、SetClipboardData()和GetClipboardData()函數(shù)。除此以外,我們還發(fā)現(xiàn)了一個在SDK手冊上沒有的GetClipboardDataSize()函數(shù),這個函數(shù)返回剪貼板的數(shù)據(jù)大小,這個數(shù)值通常是16的整數(shù)倍,它比剪貼板上實際字符串的長度要大,這個函數(shù)對你在讀剪貼板之前進行內(nèi)存分配很有幫助。下面這段示例程序包括了這些函數(shù)的實現(xiàn)。在調(diào)用這些中斷之前先要確保Windows已經(jīng)運行,示例中的IsWindowsRunning()函數(shù)就是完成這一工作的。你甚至可以用老掉牙的編譯系統(tǒng)Turbo C 2.0來運行它。示例程序先在剪貼板上寫入一個字符串,然后從剪貼板讀回這個字符串。你可以發(fā)現(xiàn)整個示例程序的編程同Windows程序的差別是很小的,這是此種方法的一個優(yōu)點:你對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,來檢驗這一結(jié)果。從Windows使用者的角度來看,你甚至感覺不到這個字符串是來自DOS的。如果打開Windows的剪貼板查看程序,你會發(fā)現(xiàn)此時剪貼板上的數(shù)據(jù)格式為“文本”和“OEM文本”兩種。
由于Windows利用剪貼板交換圖形數(shù)據(jù)使用的是位圖句柄,而這不易于DOS應用程序操作,所以利用本方法交換圖形時最好不使用Windows定義的位圖格式。本方法也不是萬能的,它對于時序要求嚴格的或數(shù)據(jù)更新很快的場合不太適用。另外,我們還沒有找到如何截取Windows的DDE消息的辦法,所以目前這種方法不能實現(xiàn)DOS程序和Windows程序間的DDE連接。我們的工作權(quán)且算作拋磚引玉,希望你能找到更好的方法。
參考文獻
[1]紀秀華,一種實現(xiàn)Windows與DOS應用程序間數(shù)據(jù)交換的簡單方法,計算機世界報,1996年4月15日第195版。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -