学习Windows excel转json工具实现主要使用的 Windows 窗口API
一些用到的窗口:
//创建一个按钮
g_bHwnd = CreateWindow(_TEXT("button"), _TEXT("Read Excel"),
WS_CHILDWINDOW,//类型 这个时表示子窗口
100, 40, 100, 50//x,y,宽,高
, g_hWnd//父窗口的句柄
, (HMENU)IDB_READEXCEL//回调的id
, hInstance, NULL);//hInstance 通常为入口函数给的hInstance
//创建一个编辑框
g_tSelPathHwnd = CreateWindowW(WC_EDITW, L"请选择目录:",
WS_CHILD| ES_AUTOHSCROLL | ES_MULTILINE,//风格 子窗口 水平滑动 多行
320, 40, 200, 40
, g_hWnd, NULL, hInstance, NULL);
//选择列表
g_lFileList = CreateWindow(WC_LISTBOX, _T(""),
WS_CHILD | WS_HSCROLL | WS_VSCROLL | LBS_NOTIFY, //风格 子窗口 水平和垂直华东 通知(再选择列表里的选项时有消息通知)
420, 80, 200, 300,
g_hWnd, (HMENU)IDL_FILELIST, hInstance, NULL);//IDL_FILELIST 通知时的id
目前就用到这三个种类型的窗口 这些窗口的回调处理再这个函数
message 是最外层的信号id 如果是WM_COMMAND表示 窗口中的信息回调
但具体那个窗口和该窗口的那个事件 记录再了 wParam的 低两位和高两位
比如
低两位是IDL_FILELIST(自己定义的) 表示是选择列表g_lFileList的信息
高两位是 LBN_SELCHANGE(官方定义的)表示选择改变了的信息
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
}
WndProc函数是通过下面这个函数注册的(我通过vs 创建的windows工程 会自动生成该代码)
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_READEXCEL));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_READEXCEL);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
窗口回调的具体逻辑:
选择路径按钮的点击事件:
其中组要是 SHBrowseForFolder 这个函数它会打开一个路径选择框来选择文件夹
返回一个 itemidlist 理解为一个目录的选择标识
通过SHGetPathFromIDList 转换成字符串形式的文件夹路径
之后查询文件夹下的文件名 加载到list控件下
//函数 WndProc...
case IDB_SELECTPATH:
{
//选择文件夹路径
TCHAR buff[1024] = { 0 };
BROWSEINFO bi;
bi.hwndOwner = NULL;
bi.iImage = 0;
bi.lParam = NULL;
bi.pidlRoot = NULL;
bi.lpfn = BrowseCallbackProc;//选择框的回调处理函数
bi.lpszTitle = _T("select path:");//选择框的title
bi.pszDisplayName = buff;
bi.ulFlags = BIF_USENEWUI | BIF_BROWSEINCLUDEFILES | BIF_BROWSEINCLUDEURLS | BIF_NEWDIALOGSTYLE;
LPITEMIDLIST pil = SHBrowseForFolder(&bi);//打开路径选择框 选择路径
if (pil)
{
::SendMessage(g_lFileList, LB_RESETCONTENT, 0, 0) ;
SHGetPathFromIDList(pil, buff);
COUT << L"select:" << buff<< std::endl;
g_pExcelPath->SetSelectFolderPath(buff);//设置选择的路径
SetWindowTextW(g_tSelPathHwnd, (LPWSTR)g_pExcelPath->GetSelectFolderPath().c_str());//显示选择路径
if (g_pExcelPath->LoadFileName())//加载路径下的json文件名
{
//将加载的json文件名 加入到list列表里
const std::vector<TSTR>& filesName = g_pExcelPath->GetReadFileName();
for (int i = 0; i < filesName.size(); ++i)
{
int pos = ::SendMessage(g_lFileList,LB_ADDSTRING,NULL, (LPARAM)filesName[i].c_str());//文件名 加入到list控件里 返回加入的下标
::SendMessage(g_lFileList, LB_SETITEMDATA, pos, i);//设置下标对于的id 再选择该下标的对象时返回的id
}
}
}
break;
}
再制作玩文件夹选择功能后 我希望再初次打开时能直接打开 配置文件里的默认目录于是有了下面的代码:
BrowseCallbackProc 就是上面目录选择窗口需要的参数中的一个
//目录选择窗口的回调
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT sMsg, LPARAM lParam, LPARAM lpData)
{
//std::cout << __FUNCTION__ << " cmd:" << sMsg << " pParam:" << lParam << std::endl;
switch (sMsg)
{
case BFFM_INITIALIZED:
{
//Getidlist
//设置打开上次选择的目录
::SendMessage(hwnd, BFFM_SETSELECTION, TRUE,(LPARAM)g_pExcelPath->GetSelectFolderPath().c_str());
break;
}
}
return 0;
}
list控件回调:
当点击其中之一项后 进行excel转json的逻辑 然后显示到 用于展示的编辑控件g_tViewTextHwnd中
//函数 WndProc...
case IDL_FILELIST://文件列表
{
int dmId = HIWORD(wParam);
switch (dmId)
{
case LBN_SELCHANGE://选择改变
{
int index = ::SendMessage(g_lFileList, LB_GETCURSEL, 0, 0);//列表选择的id
COUT << _T("select index:") << index << std::endl;
const std::vector<TSTR>& filesName = g_pExcelPath->GetReadFileName();
if (index < filesName.size() )
{
//设置选择的文件路径
TSTR readFilePath = g_pExcelPath->GetSelectFolderPath() + _T("\\") + filesName[index];
g_pExcelPath->SetSelFilePath(readFilePath);
if (readFilePath.length() <= 0)
{
COUT << _T("select file path 0") << std::endl;
return 0;
}
g_pExcelOperator->ReadExcel(readFilePath);
g_pExcelOperator->CreateConfig();
SetWindowTextW(g_tViewTextHwnd,(LPWSTR)g_pExcelOperator->GetOutData().c_str());//显示选择路径
}
break;
}
default:
break;
}
break;
}
剩下一个输出json的按钮比较简单
//函数 WndProc...
case IDB_READEXCEL://按钮 进行excel的读取和转json
{
TSTR readFilePath = g_pExcelPath->GetSelFilePath();
if (readFilePath.length() <= 0)
{
COUT << _T("select file path 0") << std::endl;
return 0;
}
g_pExcelOperator->ReadExcel(readFilePath);
g_pExcelOperator->OutFile();
break;
}
case I
实现这个工具是因为再制作个人游戏项目时 没有发现好用的转换工具比较苦恼 就自己学习做了一个 还能更具自身需求进行更改。
这三篇介绍了制作这个工具时相对困难和耽误时间的东西 ,
以此记录和提供给和我一样喜欢游戏制作并走再路上的小伙伴一点参考。