mercredi 1 avril 2015

Opening a file selection dialog is taking long using the Win32 C++ API

Essentially, opening a file dialog is going really slow. I press my button and it takes many seconds before the open file dialog pops up. Right now I am using the older Common File Dialog, but I had the same problem using the more recent Common Item Dialog, I tracked it down and in that instance the slowdown was in the Show(hWnd) call. In this case, it is the call to GetOpenFileName that blocks for several seconds.


The dialog is created in WinMain and the message loop is contained there.



int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
HWND hWnd;
MSG Msg;

#ifdef DEBUG
if (fopen_s(&g_fLOG, "log.txt", "w") != 0)
{
MessageBox(NULL, L"Failed to open log file!", L"Error", MB_OK | MB_ICONERROR);
}
#endif

hWnd = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);

while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return Msg.wParam;
}


The DialogProc is something like this:



BOOL CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_SELECTPROFILE:
switch (HIWORD(wParam))
{
case BN_CLICKED:
//CommonFileDialog.BasicFileOpen(hwnd);
DWORD dwOpenThreadID;
HANDLE hOpenThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) OpenFileThread, hwnd, 0, &dwOpenThreadID);
break;
}
break;
}
}
}
break;

case WM_CLOSE:
DestroyWindow(hwnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

}
return FALSE;
}


Finally, the thread that opens the dialog box is like so:



DWORD WINAPI OpenFileThread(HWND hWnd)
{
OPENFILENAME ofn; // common dialog box structure
wchar_t szFile[260]; // buffer for file name
HANDLE hf; // file handle

// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
BOOL res = GetOpenFileName(&ofn);
return 0;
}


I originally had the open function as part of the main DialogProc but I wanted to be able to process messages for the DialogProc window in the background, and thought perhaps that was my problem so moved it into a thread. There is the same result though.


Aucun commentaire:

Enregistrer un commentaire