a.創建個ClipBoard的對話框應用程序,加兩EditBox和兩個Button發送接收。
b.具體代碼:
發送端代碼:
if(OpenClipboard())
{
CString str;
HANDLE hClip;
char *pBuf;
EmptyClipboard();
GetDlgItemText(IDC_EDIT_SEND,str);
hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);
pBuf=(char*)GlobalLock(hClip);將句柄轉換爲指針!
strcpy(pBuf,str);
GlobalUnlock(hClip);
SetClipboardData(CF_TEXT,hClip);
CloseClipboard();
}
接收端代碼:
if(OpenClipboard())
{
if(IsClipboardFormatAvailable(CF_TEXT))
{
HANDLE hClip;
char *pBuf;
hClip=GetClipboardData(CF_TEXT);
pBuf=(char*)GlobalLock(hClip);
GlobalUnlock(hClip);
SetDlgItemText(IDC_EDIT_RECV,pBuf);
CloseClipboard();
}
}
2.匿名管道:只能在父子進程之間進行通信
a.先建一個Parent的單文檔應用程序,增加“創建管道”“讀取數據”“寫入數據”三個菜單
b.增加成員變量HANDLE類型的hRead,hWrite,初始化變量,並在析構函數中釋放句柄
c.響應菜單代碼:
void CParentView::OnPipeCreate() 菜單“創建管道”代碼
{
// TOD Add your command handler code here
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
MessageBox("創建匿名管道失敗!");
return;
}
STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO));將數據清0!
sui.cb=sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES;
sui.hStdInput=hRead;
sui.hStdOutput=hWrite;
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess("../Child/Debug/Child.exe",NULL,NULL,NULL,
TRUE,0,NULL,NULL,&sui,&pi))創建子進程
{
CloseHandle(hRead);
CloseHandle(hWrite);關閉句柄,將內核對象的使用計數減少1,這樣當操作系統發現內核對象的使用計數爲0時,將清除內核對象。
hRead=NULL;
hWrite=NULL;
MessageBox("創建子進程失敗!");
return;
}
else
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
void CParentView::OnPipeRead() 菜單“讀取數據”代碼
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox("讀取數據失敗!");
return;
}
MessageBox(buf);
}
void CParentView::OnPipeWrite() 菜單“寫入數據”代碼
{
// TOD Add your command handler code here
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("寫入數據失敗!");
return;
}
}
d.再建一個Child的單文檔,在View中增加兩個成員hRead和hWrite.在OnInitialUpdate()中得到句柄的值。
void CChildView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TOD Add your specialized code here and/or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE);注意這句代碼!
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
e.加菜單“讀取數據”“寫入數據”其代碼如下:
void CChildView::OnPipeRead()
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
MessageBox("讀取數據失敗!");
return;
}
MessageBox(buf);
}
void CChildView::OnPipeWrite()
{
// TOD Add your command handler code here
char buf[]="匿名管道測試程序";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("寫入數據失敗!");
return;
}
}
3.命名管道:還可以跨網絡通信,服務器只能在win2000和NT下運行!而客戶端可以在95下運行。關鍵函數CreateNamedPipe
a.先建一個NamedPipeSRV單文檔應用程序,加菜單“創建管道”“讀取數據”“寫入數據”
b.在View中增加Handle變量hPipe,注意在析構函數中釋放它!
c.響應菜單,創建命名管道
void CNamedPipeSrvView::OnPipeCreate()
{
// TOD Add your command handler code here
hPipe=CreateNamedPipe("//./pipe/MyPipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
0,1,1024,1024,0,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
MessageBox("創建命名管道失敗!");
hPipe=NULL;
return;
}
HANDLE hEvent;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(!hEvent)
{
MessageBox("創建事件對象失敗!");
CloseHandle(hPipe);
hPipe=NULL;
return;
}
OVERLAPPED ovlap;
ZeroMemory(&ovlap,sizeof(OVERLAPPED));
ovlap.hEvent=hEvent;
if(!ConnectNamedPipe(hPipe,&ovlap))
{
if(ERROR_IO_PENDING!=GetLastError())
{
MessageBox("等待客戶端連接失敗!");
CloseHandle(hPipe);
CloseHandle(hEvent);
hPipe=NULL;
return;
}
}
if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))
{
MessageBox("等待對象失敗!");
CloseHandle(hPipe);
CloseHandle(hEvent);
hPipe=NULL;
return;
}
CloseHandle(hEvent);
}
void CNamedPipeSrvView::OnPipeRead()
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
MessageBox("讀取數據失敗!");
return;
}
MessageBox(buf);
}
void CNamedPipeSrvView::OnPipeWrite()
{
// TOD Add your command handler code here
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("寫入數據失敗!");
return;
}
}
d.再建一個NamedPipeCLT單文檔工程,加菜單“連接管道”“讀取數據”“寫入數據”,當然別忘記成員變量hPipe的定義和初始化
e.響應菜單代碼
void CNamedPipeCltView::OnPipeConnect() 連接管道
{
// TOD Add your command handler code here
if(!WaitNamedPipe("//./pipe/MyPipe",NMPWAIT_WAIT_FOREVER))
{
MessageBox("當前沒有可利用的命名管道實例!");
return;
}
hPipe=CreateFile("//./pipe/MyPipe",GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
MessageBox("打開命名管道失敗!");
hPipe=NULL;
return;
}
}
void CNamedPipeCltView::OnPipeRead() 讀取數據
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
MessageBox("讀取數據失敗!");
return;
}
MessageBox(buf);
}
void CNamedPipeCltView::OnPipeWrite() 寫入數據
{
// TOD Add your command handler code here
char buf[]="命名管道測試程序";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("寫入數據失敗!");
return;
}
}
4.郵槽,使用時應將消息長度限制在424字節以下,關鍵函數CreateMailSlot()
a.先建一個MailSlotSRV工程,加菜單“接收數據”
b.消息響應代碼:
void CMailslotSrvView::OnMailslotRecv() 菜單“接收數據”的代碼
{
// TOD Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateMailslot("//./mailslot/MyMailslot",0,
MAILSLOT_WAIT_FOREVER,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
MessageBox("創建油槽失敗!");
return;
}
char buf[100];
DWORD dwRead;
if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))
{
MessageBox("讀取數據失敗!");
CloseHandle(hMailslot);
return;
}
MessageBox(buf);
CloseHandle(hMailslot);
}
c.加工程MailSlotCLT,加菜單“發送數據”
d.加消息響應,添加代碼,客戶端也比較簡單。
void CMailslotCltView::OnMailslotSend() 菜單“發送數據”的代碼
{
// TOD Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateFile("//./mailslot/MyMailslot",GENERIC_WRITE,
FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
MessageBox("打開油槽失敗!");
return;
}
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
{
MessageBox("寫入數據失敗!");
CloseHandle(hMailslot);
return;
}
CloseHandle(hMailslot);
}
5.以上4種方法各有優缺點:剪貼板比較簡單。郵槽是基於廣播的,可以一對多發送。但只能一個發送,一個接收,要想同時發送接收,須寫兩次代碼。
命名管道和郵槽可以進行網絡通信。