1. 程式人生 > >win32 API實現檔案拖拽開啟

win32 API實現檔案拖拽開啟

在windows中,我們開啟一個文字檔案後,可以將另一個文字檔案拖拽進來,從而實現開啟此檔案。那麼這個功能是怎麼實現的呢?

經過一下午的實踐,現將具體程式碼分享如下:

#include <windows.h>
 
#define ID_EDIT     1

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

TCHAR szAppName[] = TEXT ("記事本") ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     HWND     hwnd ;
     MSG      msg ;
     WNDCLASS wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, szAppName, szAppName,
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          700, 500,//設定寬和高
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ; 
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

VOID read_file(HWND hwnd,TCHAR* szFileName){
    TCHAR* chBuffer; //緩衝區
    int file_size; 
    long dwReadSize = 0; //實際讀取字元數
    HWND hEdit = GetDlgItem(hwnd,ID_EDIT);
    HANDLE hFile = CreateFile(szFileName,     //建立檔案的名稱。
    GENERIC_READ,          // 讀檔案。
    0,                      // 不共享讀寫。
    NULL,                   // 預設安全屬性。
    OPEN_EXISTING,          // 如果檔案存在。
    FILE_ATTRIBUTE_NORMAL, // 一般的檔案。       
    NULL);                 // 模板檔案為空。
	if (hFile == INVALID_HANDLE_VALUE) { 
		OutputDebugString(TEXT("CreateFile fail!\r\n"));
	}

	file_size = GetFileSize(hFile,NULL);
	chBuffer = (TCHAR*)malloc(file_size*sizeof(TCHAR) +1);//多分配一字元用於儲存'\0'
        ReadFile(hFile,chBuffer,file_size,&dwReadSize,NULL);  

	chBuffer[file_size] = '\0';
	SetWindowText(hEdit,chBuffer);
	CloseHandle(hFile);
	free(chBuffer);
}

VOID OnDropFiles(HWND hwnd, HDROP hDropInfo)  
{  
  //  UINT  nFileCount = DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);  //查詢一共拖拽了幾個檔案
    TCHAR szFileName[MAX_PATH] = TEXT("");  
    DragQueryFile(hDropInfo, 0, szFileName, sizeof(szFileName));  //開啟拖拽的第一個(下標為0)檔案
	
    read_file(hwnd,szFileName);
    //完成拖入檔案操作,系統釋放緩衝區 
    DragFinish(hDropInfo);  
} 

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static HWND hwndEdit ;

     switch (message)
     {
     case WM_CREATE :
          hwndEdit = CreateWindow (TEXT ("edit"), NULL,
                         WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
                                   WS_BORDER | ES_LEFT | ES_MULTILINE |
                                   ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                         0, 0, 0, 0, hwnd, (HMENU) ID_EDIT,
                         ((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
          return 0 ;
          
     case WM_SETFOCUS :
          SetFocus (hwndEdit) ;
          return 0 ;
          
     case WM_SIZE : 
          //設定子視窗的大小與父視窗相同
          MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ;
          return 0 ;
          
     case WM_COMMAND :
          if (LOWORD (wParam) == ID_EDIT)
               if (HIWORD (wParam) == EN_ERRSPACE || HIWORD (wParam) == EN_MAXTEXT)
                    MessageBox (hwnd, TEXT ("Edit control out of space."), szAppName, MB_OK | MB_ICONSTOP) ;
          return 0 ;
     case WM_DROPFILES:
          OnDropFiles(hwnd, (HDROP)wParam);
	  return 0;
     case WM_DESTROY :
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

此程式手動實現了一個簡單的記事本功能,最重要的是實現了拖拽開啟文字檔案的功能。該程式比起普通的win32程式來說,有幾點不同。

1,採用CreateWindowEx(傳統的CreateWindow缺少一個style的引數),並指定WS_EX_ACCEPTFILES風格。

2,通過DragQueryFiles取得拖拽檔案的檔名,CreateFile、GetFileSize、ReadFile實現讀取檔案內容,並存儲在一個動態的字串指標中。DragQueryFiles的引數形式如下:

UINT DragQueryFile(HDROP hDrop, UINT iFile, LPTSTR lpszFile, UINT cch);
此函式用來獲取拖放的檔名。

(1)hDrop是WM_DROPFILES訊息的wParam引數;

(2)設定iFile=0xFFFFFFFF的話,此函式返回拖放的檔案總數,記為count。設定iFile為區間[0, count)之間的任一整數就可以在lpszFile中得到序號為iFile的檔名,這個序號和使用者在shell中點選檔案圖示的順序有關;

(3)cch是該緩衝區的大小;

(4)lpszFile是用於容納檔名的緩衝區,此檔名包含檔案路徑。

3,SetWindowText設定文字內容時,要通過chBuffer[file_size] = '\0'將字串的最後一個字元設為'\0'結束符。