昨天遇到的问题是打开文件选择框后选择文件后程序会直接关闭,这样就无法进行下一步操作,或是取消选择后程序卡死。
经过一段时间的思索,选择文件关闭后程序退出是因为
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case 1:
OpenDlg(hwnd);
return DefWindowProc(hwnd, message, wParam, lParam);
}
在处理鼠标点击事件时,最下面的return语句应该放到switch外,否则控制权就交还不到windows手里,相当于接收不到下一条消息,程序直接退出。
而取消选择程序卡死是因为没有处理Show函数的返回值
hr = pfd->Show(NULL); //展示对话框
if (!hr)
{
MessageBox(hwnd, L"hr", TEXT("warn"), MB_OK);
IShellItem *pSelItem;
hr = pfd->GetResult(&pSelItem); //获取选择的项目
LPWSTR pszFilePath = NULL;
//获取文件完整路径
hr = pSelItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pszFilePath);
CoTaskMemFree(pszFilePath); //释放指针
pfd->Release();
}
在官方文档查出Show成功运行的返回值是S_OK,就是0,所以判断一下即可,否则后面指针释放异常,按理来说每一步hr都应该判断一下,这里偷个小懒(错误的)。
接下来就是文件内容处理,这里只考虑txt文件。打算再创建一个子窗口,在子窗口里创建一个文本框控件,在里面显示文件内容,然后修改之后再写入文件,在结果在第一个地方就出了问题,关于如何创建子窗口,找了好久才找到,叫模态窗口,原教程作者的写法中有一个地方涉及到long long转换到long,结果在自己编译器上不让转换,去搜了下涉及到的函数,发现不用类型转换,于是换了一种写法,新窗口诞生了,还是一样效率堪忧,面向搜索引擎编程,悲惨的一天。
codeblocks没法调试win32程序。。太蛋疼了,迫不得已转用vs,结果跑不通,原来是long long 转换到 long的那个地方,原作者是对的,我的锅。不该质疑大佬的写法。
以上说的是创建子窗口,原理也好理解,首先停止在当前窗口的操作,就是打开新窗口后无法对旧窗口操作,然后创建新的,最后调用自己写的消息处理函数。
if (pszFilePath != NULL)//如果文件路径不为空
{
EnableWindow(hwnd, FALSE);//停止在当前窗口的操作
//创建新窗口
HWND hwnd1 = CreateWindowEx(NULL, szAppName1, TEXT("文本内容"),
WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME,
150, 150, 550, 700,
hwnd, NULL,
hInst,
0
);
if (hwnd1 == NULL)
{
MessageBox(NULL, TEXT("创建窗口失败!"), TEXT("错误"), MB_ICONERROR);
return 0;
}
SetWindowLong(hwnd1, GWLP_WNDPROC, (LONG)&WndProc2);
ShowWindow(hwnd1, 5);
UpdateWindow(hwnd1);
//调用自己写的消息处理函数
ModelWindow(hwnd);
}
下面是用来处理新窗口的消息处理函数,在关闭新窗口后,通过最后两个函数把控制权交还给主窗口。
void ModelWindow(HWND last) {
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
EnableWindow(last, TRUE);
SetForegroundWindow(last);
}
void WriteTxtFile(HWND TxtContent)
{
HANDLE pfile;
//获取要写入文件的内容大小
int Editsize = GetWindowTextLength(TxtContent) * 2;
TCHAR *Data = new TCHAR[Editsize];
//获取要写入内容
GetWindowText(TxtContent, Data, Editsize);
//打开文件
pfile = CreateFile(pszFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (pfile == INVALID_HANDLE_VALUE)
{
CloseHandle(pfile);
return;
}
DWORD size;
//写入
if (WriteFile(pfile, Data, Editsize, &size, NULL) == 0) {
CloseHandle(pfile);
return;
}
CloseHandle(pfile);
return;
}
写是能写,但是通过WriteFile写入文件或者ReadFile读取后会把文件指针放到文件开头,就是打开txt文件后光标总是在第一位,导致下一次读取时只能读入第一个字符,可能是打开文件模式的问题,但CreateFile的打开模式要么是直接重写,要么是从开头添加新内容,试遍了所有模式光标始终都在第一位,也尝试过用SetFilePointer重设指针位置,但导致了更多的bug,直接放弃了,在读入文件时还会读进来一些奇奇怪怪的东西,明明文件大小没问题,折腾了好几天了,直接弃了,不如进入下一步。
还有个问题就是用char类型读进来,直接显示会乱码,需要转成宽字符BYTE类型,但用BYTE也没法显示中文,直接乱码,不想折腾了,卡在这太久了,直接下一步吧。
按理来说应该都是直接调用api来实现对应功能,速度应该很快,但实际上会遇到很多问题,问题一改就是半天,导致效率过低,一个bug改一天唉。
2022年7月30日