日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

VC实用小知识总结 (一),转http://blog.csdn.net/myiszjf/article/details/10007431

發布時間:2023/11/27 生活经验 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 VC实用小知识总结 (一),转http://blog.csdn.net/myiszjf/article/details/10007431 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上一篇中,我們以經介紹了程序的流程和框架,在本篇將詳細討論各個功能的實現主要包括


1.獲取磁盤信息
2.獲取目錄信息
3.獲取文件信息
4.運行指定文件
5.刪除指定文件
6.刪除指定目錄
7.創建指定目錄
8.上傳下載文件
9.獲取遠程文件圖標


獲取磁盤信息

磁盤信息可以用API GetDriveType來實現,它以路徑名作為參數(如C:/)返回磁盤類型,其實例代碼如下

DWORD GetDriverProc(COMMAND command,SOCKET client)
{
for(char i='A';i<='Z';i++)
{
char x[20]={i,':'};
UINT Type=GetDriveType(x);
if(Type==DRIVE_FIXED||Type==DRIVE_REMOVABLE||Type==DRIVE_CDROM)
{
/*返回處理結果...*/
}
}
return 0;
}

GetDriveType可能返回的結果如下

#define DRIVE_UNKNOWN ?? 0 // 無效路徑名
#define DRIVE_NO_ROOT_DIR?? 1 // 無效路經,如無法找到的卷標
#define DRIVE_REMOVABLE 2 // 可移動驅動器
#define DRIVE_FIXED ?? ??? 3 // 固定的驅動器
#define DRIVE_REMOTE ?? 4 // 網絡驅動器
#define DRIVE_CDROM ?? ??? 5 // CD-ROM
#define DRIVE_RAMDISK ?? 6 // 隨機存取(RAM)磁盤

在上面的實例代碼中我們只取,硬盤,光驅和移動磁盤




獲取目錄信息




這里只要枚舉用戶指定的目錄就可以了,其實例代碼如下:

DWORD GetDirInfoProc(COMMAND command,SOCKET client)
{
/*command為要枚舉的路徑如(C:/)client為返回結果的SOCKET句柄*/

FILEINFO fi;
memset((char*)&fi,0,sizeof(fi));

strcat((char*)command.lparam,"*.*");//枚舉所有文件

CFileFind file;
BOOL bContinue = file.FindFile((char*)command.lparam);

while(bContinue)
{
memset((char*)&fi,0,sizeof(fi));

bContinue = file.FindNextFile();
if(file.IsDirectory()) //為目錄
{
fi.IsDir=true;
}
strcpy(fi.FileName,file.GetFileName().LockBuffer()); //保存文件名稱

if(send(client,(char*)&fi,sizeof(cmd),0)==SOCKET_ERROR)
{
cout << "Send Dir is Error/n";
}
}
return 0;
}



獲取文件信息


以下實例代碼用來獲取 文件的名稱,路徑,時間,屬性等信息

DWORD FileInfoProc (COMMAND command,SOCKET client)
{
/*command為要查看的文件如(C:/TEST.EXE)client為返回結果的SOCKET句柄*/
FILEINFO fi;
HANDLE hFile;
WIN32_FIND_DATA WFD;
memset((char*)&WFD,0,sizeof(WFD));
if((hFile=FindFirstFile((char*)command.lparam,&WFD))==INVALID_HANDLE_VALUE) //查看文件屬性
{
fi.Error=true;
return 0;
}
//得到文件的相關信息
SHGetFileInfo(WFD.cFileName,?
FILE_ATTRIBUTE_NORMAL,
&shfi, sizeof(shfi),
SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_TYPENAME );
strcpy(fi.FileName,(char*)command.lparam); //文件路徑
FileLen=(WFD.nFileSizeHigh*MAXDWORD+WFD.nFileSizeLow)/1024; //文件長度
fi.FileLen=FileLen;
//轉化格林時間到本地時間
FileTimeToLocalFileTime(&WFD.ftLastWriteTime,&localtime);
FileTimeToSystemTime(&localtime,&systime);
//文件修改時間
sprintf(stime,"%4d-%02d-%02d %02d:%02d:%02d",
systime.wYear,systime.wMonth,systime.wDay,systime.wHour,
systime.wMinute,systime.wSecond);
if(GetFileAttributes((char*)command.lparam)&FILE_ATTRIBUTE_HIDDEN)
{
/*隱藏文件...*/
}else
if(GetFileAttributes((char*)command.lparam)&FILE_ATTRIBUTE_READONLY)
{?
/*只讀文件...*/
}
send(client,(char*)&fi,sizeof(fi),0);
FindClose(hFile);
return 0;
}




運行指定文件

運行文件 有以下幾種方法 1.WinExec 2.ShellExecute 3.CreateProcess

這里使用的是ShellExecute其實例代碼如下

DWORD ExecFileProc (COMMAND command,SOCKET client)
{
/*command為要運行的文件路徑如(C:/TEST.EXE)client為返回結果的SOCKET句柄*/

COMMAND ??? cmd;
memset((char*)&cmd,0,sizeof(cmd));
cmd.ID=ExecFile;

if(ShellExecute(NULL,"open",(char*)command.lparam,NULL,NULL,SW_HIDE)<(HINSTANCE)32)
{
strcpy((char*)cmd.lparam,"文件執行失敗!");
send(client,(char*)&cmd,sizeof(cmd),0);
}
else
{
strcpy((char*)cmd.lparam,"文件執行成功!");
send(client,(char*)&cmd,sizeof(cmd),0);
}

return 0;
}

API函數ShellExecute原形為:?

HINSTANCE ShellExecute( ???
HWND hwnd, ?? ?? ?? ?? //窗口句柄?
LPCTSTR lpOperation, //操作類型?
LPCTSTR lpFile, ?? ?? ?? //文件指針?
LPCTSTR lpParameters, ?? //文件參數?
LPCTSTR lpDirectory, //缺省目錄?
INT nShowCmd ?? ?? ?? //顯示方式?
); ???

這是一個相當有意思的函數,在調用此函數時只須指定要執行的文件名,而不必管用什么程序去打開
或執行文件,WINDOWS會自動根據要打開或執行的文件去判斷該如何執行文件或用什么程序去打開文件,如果
要求不高的話比CreateProcess要好用的多,如果想做出像NCPH和灰鴿子那樣帶參數執行的話,其實也不難
只要指定lpParameters為執行參數就可了


刪除指定文件

DWORD DelFileProc (COMMAND command,SOCKET client)
{
/*command為要刪除的文件路徑如(C:/TEST.EXE)client為返回結果的SOCKET句柄*/
COMMAND ??? cmd;
memset((char*)&cmd,0,sizeof(cmd));
cmd.ID=DelFile;
SetFileAttributes((char*)command.lparam,FILE_ATTRIBUTE_NORMAL); //去掉文件的系統和隱藏屬性
if(DeleteFile((char*)command.lparam)==0)
{
strcpy((char*)cmd.lparam,"文件刪除失敗!");
send(client,(char*)&cmd,sizeof(cmd),0);
}
else
{
strcpy((char*)cmd.lparam,"文件刪除成功!");
send(client,(char*)&cmd,sizeof(cmd),0);
}
return 0;
}

需要注意的是在 DeleteFile前應該去文件的系統和隱藏屬性,否則會刪除失敗


刪除目錄

可以用RemoveDirectory函數刪除目錄,但是RemoveDirectory有個缺點就是只能刪除為空的的目錄,對于不為空
的目錄就無能為力了,想要刪除不無空的目錄可以使用下面的實例代碼

BOOL DeleteDirectory(char *DirName)
{
CFileFind tempFind;
char tempFileFind[200];
sprintf(tempFileFind,"%s*.*",DirName);
BOOL IsFinded=(BOOL)tempFind.FindFile(tempFileFind);
while(IsFinded)
{
?? IsFinded=(BOOL)tempFind.FindNextFile();
?? if(!tempFind.IsDots())
?? {
?? ?? char foundFileName[200];
?? ?? strcpy(foundFileName,tempFind.GetFileName().GetBuffer(200));
?? ?? if(tempFind.IsDirectory())
?? ?? {
?? ?? ?? char tempDir[200];
?? ?? ?? sprintf(tempDir,"%s//%s",DirName,foundFileName);
?? ?? ?? DeleteDirectory(tempDir);
?? ?? }
?? ?? else
?? ?? {
?? ?? ?? char tempFileName[200];
?? ?? ?? sprintf(tempFileName,"%s//%s",DirName,foundFileName);
SetFileAttributes(tempFileName,FILE_ATTRIBUTE_NORMAL); //去掉文件的系統和隱藏屬性
?? ?? ?? DeleteFile(tempFileName);
cout <<"now delete "<<tempFileName<<"/n";
?? ?? }
?? }
}
tempFind.Close();
if(!RemoveDirectory(DirName))
{
?? return FALSE;
}
return TRUE;
}

這個函數的代碼可以參照上面 枚舉目錄的代碼來看,它的原理就是枚舉目錄下的所有文件并刪除,最后刪除
指定目錄,成功返回TRUE失敗則返回FALSE,這段代碼可以直使用,但要小心使用,因為我在傳參數時的失誤
結果把整個D盤差點清空了..........




創建目錄

實例代碼如下:

DWORD CreateDirProc (COMMAND command,SOCKET client)
{
/*command為要創建目錄的路徑如(C:/)client為返回結果的SOCKET句柄*/
COMMAND ??? cmd;
memset((char*)&cmd,0,sizeof(cmd));
cmd.ID=CreateDir;
if(::CreateDirectory((char*)command.lparam,NULL))
{
strcpy((char*)cmd.lparam,"創建目錄成功!");
send(client,(char*)&cmd,sizeof(cmd),0);
}
else
{
strcpy((char*)cmd.lparam,"創建目錄失敗!可能有重名文件或文件夾");
send(client,(char*)&cmd,sizeof(cmd),0);
}
return 0;
}


在創建目錄時應該注意幾點,首先創始目錄的上層目錄必須是存在的,比如想創建C:/DIR1/DIR2目錄,要求
DIR1是必須存在,用CreateDirectory并不能創建多級目錄.再者不可以存在和要創建目錄同名的目錄和文件
因為在磁盤上目錄和文件的存放格式是相同的,惟一不同的是 目錄的屬性與文件屬性不同
(FILE_ATTRIBUTE_DIRECTORY屬性),所在即使有同名文件也會創始失敗.




上傳下載文件

上傳下載是是文件管理的重點所在,在這里按文件的大小,分兩種情況討論文件的傳輸方法

小文件的傳輸相對比較簡單可按以下方法進行

1.首先發送文件長度和名稱
2.跟據文件長度建立緩沖區
3.讀取整個文件到緩沖區
4.發送緩沖區里的內容

其實現代碼如下:

CFile file;
FILEINFO fileinfo;
if(file.Open(path,CFile::modeRead|CFile::typeBinary))
{
fileinfo.FileLen=file.GetLength(); //文件長度
strcpy(fileinfo.FileName,file.GetFileName()); //文件名稱
send(client,(char*)&fileinfo,sizeof(fileinfo),0); //發送長度和名稱

char *date=new char[fileinfo.FileLen]; //分配和文件長度相同的緩沖區
int nLeft=fileinfo.FileLen;
int idx=0;
file.Read(date,fileinfo.FileLen); //讀整個文件到緩沖區
while(nLeft>0)
{
int ret=send(client,&date[idx],nLeft,0); //發送文件
if(ret==SOCKET_ERROR)
{
break;
}
nLeft-=ret;
idx+=ret;
}
file.Close();
delete[] date;
}
跟據上面的實例相信大家可以領悟到文件傳輸的基本原理和方法,雖然很簡單但用它傳輸小文件還是非常實用的


大文件傳輸方法

用上面的方法傳輸小文件還可以,但是大文件呢?比如一個500M的電影.上面的方法就會力不從心了因為
按思路要創建一個跟文件大小相同的緩沖區,顯然這是不太現實的,我們就得采用另種方法了,在這里我們使用
分塊文件傳輸,所謂分塊是指把大文件分成若干小文件,然后傳輸,比如設定每塊大小為64KB其思路如下


1.取得文件長度和名稱
2.跟據長度/64KB計算文件塊數
3.分配64KB緩沖區
4.讀文件到緩沖區
5.發送緩沖的數據
6.重復4,5兩步直到發完所有數據

其實現代碼如下:

#define CHUNK_SIZE (64*1024) //分為64K塊傳輸

DWORD?? GetFileProc (COMMAND command,SOCKET client)
{
/*command為要下載文件的路徑如(C:/TEST.EXE)client為發送文件的SOCKET句柄*/

COMMAND ??? cmd;
FILEINFO fi;
memset((char*)&fi,0,sizeof(fi));
memset((char*)&cmd,0,sizeof(cmd));
cmd.ID=GetFile;

CFile file;
int nChunkCount=0; //文件塊數

if(file.Open((char*)command.lparam,CFile::modeRead|CFile::typeBinary))//打開文件
{
int FileLen=file.GetLength(); //取文件長度
fi.FileLen=file.GetLength();
strcpy((char*)fi.FileName,file.GetFileName()); //取文件名稱
memcpy((char*)&cmd.lparam,(char*)&fi,sizeof(fi));
send(client,(char*)&cmd,sizeof(cmd),0); //發送文件名稱和長度

nChunkCount=FileLen/CHUNK_SIZE; //文件塊數
if(FileLen%nChunkCount!=0)
nChunkCount++;
char *date=new char[CHUNK_SIZE]; //創建數據緩沖區
for(int i=0;i<nChunkCount;i++) //分為nChunkCount塊發送
{
int nLeft;
if(i+1==nChunkCount) //最后一塊
nLeft=FileLen-CHUNK_SIZE*(nChunkCount-1);
else
nLeft=CHUNK_SIZE;
int idx=0;
file.Read(date,CHUNK_SIZE); //讀取文件
while(nLeft>0)
{
int ret=send(client,&date[idx],nLeft,0);//發送文件
if(ret==SOCKET_ERROR)
{
break;
}
nLeft-=ret;
idx+=ret;
}
}
file.Close();
delete[] date;
}
return 0;
}
這樣文件傳輸部分就完成了,止于客戶端的實現于上面代碼其本相同,只是由讀文件變為寫文件,詳細請參考源代碼


獲取遠程ICO文件圖標

我們在文件列表框中需要顯示文件的圖標,但遠程文件的ICO圖標是無法直接得到的
猛若RADMIN 黑洞者也沒有到(對于EXE文件只顯示可執行程序圖示),當然了也不見的決對沒有......

我們可以通過如下變通方法得到:就是跟據文件的擴展名,從本地注冊表中查找對應的程序圖標

不過這也有它的缺點對于EXE文件它只能顯示一個可執行文件的圖示,而且只能顯示注冊過的圖示比如,如果
本機裝有WINRAR那么就可以識別.RAR的文件圖示,否則就無法識別...

實現方法

CImageList m_ImageList;

m_ImageList.Create(32,32,ILC_COLOR32,10,30); //創建圖示
m_list.SetImageList(&m_ImageList,LVSIL_NORMAL); //與列表控件相關連


SHFILEINFO info;
memset((char*)&info,0,sizeof(info));

SHGetFileInfo(fi->FileName,0,&info,sizeof(&info),?? SHGFI_ICON|SHGFI_USEFILEATTRIBUTES);//關鍵所在

int i = m_ImageList.Add(info.hIcon);
m_list.InsertItem(i,fi->FileName,i);

原來我試圖在Server端通過上面的代碼把info.hIcon句柄保存下來,然后放到Client,在單臺電腦上很好使,但
Server在另一臺電腦上時就玩完了,因為info.hIcon里保存的句柄是個索引而每臺機器上的索引是不相同的所以
直接導致的結果就是:什么也顯示不出來.....


到這里程序的主要功能實現就介紹完了,下一篇將詳細介紹斷點續傳和多線程傳輸的實現

轉載于:https://www.cnblogs.com/devc/p/3423222.html

總結

以上是生活随笔為你收集整理的VC实用小知识总结 (一),转http://blog.csdn.net/myiszjf/article/details/10007431的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。