牛骨文教育服务平台(让学习变的简单)
博文笔记

win32 API实现文件拖拽打开

创建时间:2017-04-15 投稿人: 浏览次数:1172

在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!
"));
	}

	file_size = GetFileSize(hFile,NULL);
	chBuffer = (TCHAR*)malloc(file_size*sizeof(TCHAR) +1);//多分配一字符用于存储""
        ReadFile(hFile,chBuffer,file_size,&dwReadSize,NULL);  

	chBuffer[file_size] = "";
	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] = ""将字符串的最后一个字符设为""结束符。



声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。