使用win32实现在窗体内拖拽txt文本的消息响应与读取。兼容Unicode于多字节字符集下,对TXT格式中UTF-8、ANSI与UNICODE编码的转换。文本格式的判断使用正则实现。
完整示例代码(VS2015):http://pan.baidu.com/s/1qYp4r2s
// Win32_1.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "DragTxt.h"
#include "GB2312UTF8.h"
#include
#include
#include
using namespace std;
#define MAX_FILE_PATH 256
// 全局变量:
HINSTANCE hInst; // 当前实例
HWND g_hMainWnd;
INT_PTR CALLBACK DialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
std::string WideChar2MultiByte(std::wstring src);
std::wstring MultiByte2WideChar(std::string src);
void OnDropFiles(TCHAR* szFilePath);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
hInst = hInstance;
HWND hWnd = ::CreateDialog(hInstance, (LPCTSTR)IDD_DIALOG_MAIN, NULL, DialogProc);
if (hWnd == INVALID_HANDLE_VALUE)
return 0;
g_hMainWnd = hWnd;
ShowWindow(hWnd, SW_SHOW);
MSG msg;
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
INT_PTR CALLBACK DialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_INITDIALOG:
SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON)));
break;
case WM_DROPFILES:
{
HDROP hDrop = (HDROP)wParam;
TCHAR szFilePath[MAX_FILE_PATH + 1];
WORD n = ::DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
for (WORD i = 0; i < n; i++)
{
::DragQueryFile(hDrop, i, szFilePath, sizeof(szFilePath));
OnDropFiles(szFilePath);
}
DragFinish(hDrop);
}
break;
case WM_DESTROY:
DestroyWindow(hwndDlg);
break;
default:
return (INT_PTR)FALSE;
}
return (INT_PTR)FALSE;
}
std::string WideChar2MultiByte(std::wstring src)
{
int nLen = WideCharToMultiByte(CP_ACP, 0, src.c_str(), -1, NULL, 0, NULL, NULL);
char * szString = new char[nLen];//malloc and
int nReturnLen = WideCharToMultiByte(CP_ACP, 0, src.c_str(), -1, szString, nLen, NULL, NULL);
std::string ret = szString;
delete[] szString;
return ret;
}
std::wstring MultiByte2WideChar(std::string src)
{
std::wstring result = L"";
WCHAR * wszString;
int i = MultiByteToWideChar(936, 0, src.c_str(), -1, NULL, 0);
if (i)
{
wszString = new WCHAR[i * 2];
RtlZeroMemory(wszString, i * sizeof(WCHAR) * 2);
MultiByteToWideChar(936, 0, src.c_str(), -1, wszString, i);
result = wszString;
delete[] wszString;
}
return result;
}
void OnDropFiles(TCHAR* szFilePath)
{
int cnt = 0;
unsigned short head;
string path;
regex_constants::syntax_option_type f1 = regex_constants::icase;
#ifdef UNICODE
path = WideChar2MultiByte(szFilePath);
#else
path = szFilePath;
#endif
regex pattern("\\.txt", f1);
if (!regex_search(path, pattern))
{
::MessageBox(g_hMainWnd, _T("不是一个txt文件"), _T("提示"), MB_OK | MB_ICONHAND);
return;
}
HWND hWnd = GetDlgItem(g_hMainWnd, IDC_TEXT);
#ifdef UNICODE
#define TFOPEN _wfopen
#else
#define TFOPEN fopen
#endif // UNICODE
FILE *pFile = TFOPEN(szFilePath, _T("rb"));
#ifdef UNICODE// Unicode
char szTxt[2048] = { 0 };
char* pUtf8;
while ((cnt = fread(szTxt, sizeof(char), sizeof(szTxt) - 1, pFile)) > 0)
{
memcpy(&head, szTxt, sizeof(unsigned short));
switch (head)
{
case 0xFEFF://Unicode
::SetDlgItemText(g_hMainWnd, IDC_TEXT, (LPCWSTR)szTxt);
break;
case 0xBBEF://UTF-8
pUtf8 = szTxt;
pUtf8 += 3;
::SetDlgItemTextA(g_hMainWnd, IDC_TEXT, _G(pUtf8));
break;
default://ANSI
::SetDlgItemTextA(g_hMainWnd, IDC_TEXT, szTxt);
break;
}
}
#else// 多字节
wchar_t szTxt[2048] = { 0 };
wchar_t* pUnicode;
while ((cnt = fread(szTxt, sizeof(wchar_t), sizeof(szTxt) - 1, pFile)) > 0)
{
memcpy(&head, szTxt, sizeof(unsigned short));
std::string src;
char * p;
switch (head)
{
case 0xFEFF://Unicode
pUnicode = szTxt;
pUnicode += 1; // 去掉文件头
::SetDlgItemTextW(g_hMainWnd, IDC_TEXT, (LPCWSTR)pUnicode);
break;
case 0xBBEF://UTF-8
p = (char*)szTxt;
p = p + 3;// 去除文件头
::SetDlgItemText(g_hMainWnd, IDC_TEXT, (LPCSTR)_G(p));
break;
default:
::SetDlgItemText(g_hMainWnd, IDC_TEXT, (LPCTSTR)szTxt);
break;
}
}
#endif // UNICODE
fclose(pFile);
}