程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言基本語法詳解之文件夾變形

C語言基本語法詳解之文件夾變形

編輯:關於C語言

首先,我們看看這兩個圖,如圖1所示。

一秒前:

一秒後:

怎麼樣?文件夾變成回收站了!不信?雙擊進入試試,裡面真的是回收站哦。神奇吧!看過本文,你不但能變文件夾為回收站,還可以將它變成各種稀奇古怪的東東!

首先要說明一下原理:在Windows資源管理器中,Desktop.ini和Folder.htt中定義了文件夾的屬性,在Windows 9X下,我們可以在文件夾中建一個Desktop.ini,並在其中輸入如下代碼:

[.ShellClassInfo]

Clisd={645FF040-5081-101B-9F08-00AA002F954E}

這樣文件夾就變成了回收站,但是在Windows XP/2003中就失效了。沒關系,另有辦法:我們對著文件夾按下F2,改成“×××.{645FF040-5081-101B-9F08-00AA002F954E}”(不要引號),也變形了吧?!這其實也改變了文件夾的屬性,效果是一樣的。通過資料知道,這其實是運用了微軟的Active Desktop技術。下面我們看看如何利用編程實現它。

系統環境:Windows Server 2003 Enterprice Eidtion

開發工具:VC++ 6.0

本程序是用SDK寫的,這篇文章也是給像我這樣的菜菜看的,現在很多學編程的菜菜們都愛用VB之類的RAD工具或是一頭鑽進MFC,以至於編了N年還不知道什麼是Windows消息循環,把十分平常的API函數調用(如SendMessage,FindWindows之類)奉之為“技巧”。我沒有鄙視的意思,也不是說號召大家以後都這樣編程,畢竟用SDK開發太慢了,我只是覺得要想在Windows編程得到較大進步,學習Win32下的SDK編程是不應該省略的,若只會Click處理事件,而不知道其中IDE到底干了什麼,那就會阻礙你的進步了!

下面簡略說明一下程序流程:

WinMain函數,程序的入口:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE ,hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
if (-1 == DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, Main_Proc))
{
MessageBox(NULL, "加載對話框出錯!" , "", MB_OK);
// MessageBox函數,彈出一個預定義消息框,第一個參數是窗體句柄,第2個參數是消息正文,第三個參數是標題,最後是消息框類型,這裡是指有一個確定按鈕的消息框.
}
return 0;
}

這裡使用了DialogBox,調用一個模式對話框,作為與用戶的交互窗口.為什麼要這樣呢?畢竟在資源文件裡做界面比較方便啊,如圖2所示。

圖2

那麼來看看Main_Proc吧,它是對話框的消息處理函數:

BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//BEGIN MESSAGE CRACK
HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); //初始化的消息
HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); //發給控件們的消息
HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose); //關閉對話框的消息
//END MESSAGE CRACK
}
return FALSE;
}

這裡要重點介紹HANDLE_MSG宏,它可以簡化你的程序,它在 中。說明如下:

#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd),
(wParam), (lParam), (fn))

這個宏的作用是雙重的:首先它消除了冗長的Case 語句,這種 Case 語句在標准的WndProc中實在令人煩惱,再者它使你擺脫必須傳送消息處理函數返回值的責任。所以,這裡Main_OnInitDialog是WM_INITDIALOG對應的消息處理函數,Main_OnCommand和Main_OnClose也是如此。Main_OnClose很簡單,就是EndDialog。Main_OnInitDialog代碼如下:

BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
HWND hCombo=GetDlgItem(hwnd,IDC_TYPE) ;//IDC_TYPE是一個ComboBox的ID,這個函數可以取得特定ID的控件的句柄
SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)"回收站");//第一項
SendMessage(hCombo,CB_ADDSTRING,1,(LPARAM)"控制面板");//第二項
SendMessage(hCombo,CB_ADDSTRING,2,(LPARAM)"計劃任務");//第三項
SendMessage(hCombo,CB_SETCURSEL,0,0);//把第一項 回收站 作為默認項放進Combobox的文本框.
return TRUE;
}

初始化的作用是為下拉列表框加入列表項,我這裡加了5項,指可以偽裝成5種不同的外形。這三種外形的代碼我放到一個全局數組中:

char DefaultType[5][125]={
"{645FF040-5081-101B-9F08-00AA002F954E}",//回收站
"{00000306-0000-0000-C000-000000000046}",//密閉文件夾
"{00020906-0000-0000-C000-000000000046}",//Word文檔
"{D6277990-4C6A-11CF-8D87-00AA0060F5BF}",//計劃任務
"{21EC2020-3AEA-1069-A2DD-08002B30309D}" //控制面板
};

那麼我從哪裡找到這些代碼呢?這些東東都在注冊表的HKEY_CLASSES_ROOT\CLSID\CLSID下,你可以自己去找找已經在系統中注冊的組件ID加到代碼裡,為了方便大家,我這裡用到了幾個比較通用的。
Main_OnCommand函數是處理對話框控件消息的函數,代碼如下:

void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
HWND hCombo,hEidt;
char path[1024]={0},temppath[MAX_PATH]={0},type[125];
int nIndex=0;
LPITEMIDLIST pId; //ITEMIDLIST的指針,以後要用
BROWSEINFO binfo={0};//開啟浏覽框用得結構體,初始化為0
switch(id)
{
case IDC_HIDE: //如果是"偽裝"按鈕的消息,即按下"偽裝" 按鈕
hEidt=GetDlgItem(hwnd,IDC_PATH) ; //得到編輯框的句柄
hCombo=GetDlgItem(hwnd,IDC_TYPE) ; //得到組合框的句柄
GetWindowText(hEidt,path,GetWindowTextLength(hEidt)+1); //得到編輯框中的路徑
nIndex =SendMessage(hCombo,CB_GETCURSEL,0,0L); //得到組合框中被選項序號
strcpy(type,DefaultType[nIndex]); //就使用這一項對應的代碼

if (GetWindowTextLength(hEidt)!=0) //如果路徑不為空
{
Hide(hwnd,path,type); //就偽裝它
}
else
{
MessageBox(hwnd,"路徑不能為空","",MB_OK);
}
//用來偽裝的函數,把參數傳遞進去
SetWindowText(GetDlgItem(hwnd,IDC_PATH),NULL); //清空編輯框
break;
case IDC_BROW: //點擊"浏覽"按鈕
binfo.lpszTitle= "請選擇文件夾路徑"; //文件夾選取框的標題
pId = SHBrowseForFolder(&binfo); //開啟文件夾選取框
if (pId!=0)
{
SHGetPathFromIDList(pId,temppath); //得到選取的路徑
SetWindowText(GetDlgItem(hwnd,IDC_PATH),temppath); //把這個路徑放到編輯框了
}
break;
case IDC_REC: //來自”還原”按鈕的消息,點擊了"還原"按鈕
hEidt=GetDlgItem(hwnd,IDC_PATH) ;
hCombo=GetDlgItem(hwnd,IDC_TYPE) ;
GetWindowText(hEidt,path,GetWindowTextLength(hEidt)+1);
if (GetWindowTextLength(hEidt)!=0) //如果路徑不為空
{
Recover(hwnd,path); //就回復它
}
else
{
MessageBox(hwnd,"路徑不能為空","",MB_OK);
}
SetWindowText(GetDlgItem(hwnd,IDC_PATH),NULL); //清空編輯框
break;
case IDC_EXIT: //點擊"離開按鈕"
EndDialog(hwnd, id); //關掉模態對話框
break;
default:
break;
}
}

能看懂吧?Hide和Recover分別是偽裝和復原的函數:

bool Hide(HWND hwndMain,char *path,char *type)
{
char output[MAX_PATH+1];
sprintf(output,"%s.%s",path,type);//把路徑和偽裝代碼按照原理篇中提到的格式放到output中.
if (output==NULL) //如果為空則退出
{
MessageBox(hwndMain,"路徑意外地為空","錯了",MB_OK);
return false;
}
MoveFile(path,output);//用MoveFile函數改名
MessageBox(hwndMain,"偽裝成功!","OK",MB_OK);
return true;
}
bool Recover(HWND hwndMain,char *path)
{
int i=0;
int pathlen=strlen(path),typelen=strlen(DefaultType[1])+1; //之所以+1是因為還有一個句號
char output[MAX_PATH+1] ;
while (i<=pathlen-typelen) //這裡是為了去掉後面的偽裝代碼.得到原文件名
{
output[i]=path[i];
i++;
}
if (output==NULL) //如果為空則退出
{
MessageBox(hwndMain,"路徑意外地為空","錯了",MB_OK);
return false;
}
output[i]='\0'; //加個結束符
MoveFile(path,output);//用MoveFile函數改回原名
MessageBox(hwndMain,"還原成功!","",MB_OK);
return true;
}

好了,程序做好了,騙騙普通菜鳥還是很好的,我們自己怎麼識別這樣的程序?其實只要用命令行就可以進入回收站了,如圖3所示。之下藏東西方便了!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved