IFileDialog
не дает возможности управлять расположением диалогового окна, но это может быть достигнуто путем подкласса диалогового окна.
Сообщение WM_WINDOWPOSCHANGING
:
Отправляется в окно, размер, положение или положение которого в Z-порядке должны измениться в результате вызова функции SetWindowPos или другой функции управления окнами.
Окно получает это сообщение через свою функцию WindowProc.
Поэтому, если мы перехватим это сообщение, мы можем изменить его параметры, чтобы они указывали на нужное нам место, прежде чем окно будет перемещено туда. Мы можем сделать это путем подкласса диалога, который заменяет оконную процедуру диалога нашей собственной оконной процедурой. Наша пользовательская оконная процедура может выглядеть так:
LRESULT MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_WINDOWPOSCHANGING)
{
WINDOWPOS* wp = (WINDOWPOS*)lParam;
wp->x = 100;
wp->y = 100;
}
return CallWindowProc(owp, hwnd, msg, wParam, lParam);
}
Диалог имеет подкласс SetWindowLong
функция. Однако, чтобы использовать эту функцию, нам нужно знать HWND
диалогового окна. В свою очередь, мы можем получить дескриптор диалогового окна, настроив временный хук с SetWindowsHookEx
, который будет соответствовать, например, заголовку диалогового окна и удалить себя при создании подкласса окна, соответствующего заданному заголовку:
LRESULT CALLBACK GetMsgProc(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (code == HC_ACTION)
{
MSG* msg = (MSG*)lParam;
WCHAR title[120];
GetWindowText(msg->hwnd, title, sizeof(title));
if (lstrcmpW(title, L"MyTest01") == 0)
{
if (sizeof(long long) == 8)
owp = (WNDPROC)SetWindowLongPtr(msg->hwnd, GWLP_WNDPROC, (LONG_PTR)MyWndProc);
else
owp = (WNDPROC)SetWindowLong(msg->hwnd, GWLP_WNDPROC, (LONG_PTR)MyWndProc);
LRESULT r = CallNextHookEx(hhk, code, wParam, lParam);
UnhookWindowsHookEx(hhk);
return r;
}
}
return CallNextHookEx(hhk, code, wParam, lParam);
}
Весь пример:
#include <windows.h>
#include <shobjidl.h>
HHOOK hhk = NULL;
WNDPROC owp = NULL;
LRESULT MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_WINDOWPOSCHANGING)
{
WINDOWPOS* wp = (WINDOWPOS*)lParam;
wp->x = 100;
wp->y = 100;
(WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)owp);
}
return CallWindowProc(owp, hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK GetMsgProc(
_In_ int code,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
if (code == HC_ACTION)
{
MSG* msg = (MSG*)lParam;
WCHAR title[120];
GetWindowText(msg->hwnd, title, sizeof(title));
if (lstrcmpW(title, L"MyTestIFileOpenDialog01") == 0)
{
if (sizeof(long long) == 8)
owp = (WNDPROC)SetWindowLongPtr(msg->hwnd, GWLP_WNDPROC, (LONG_PTR)MyWndProc);
else
owp = (WNDPROC)SetWindowLong(msg->hwnd, GWLP_WNDPROC, (LONG_PTR)MyWndProc);
LRESULT r = CallNextHookEx(hhk, code, wParam, lParam);
UnhookWindowsHookEx(hhk);
return r;
}
}
return CallNextHookEx(hhk, code, wParam, lParam);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOpenDialog *pFileOpen;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (SUCCEEDED(hr))
{
hhk = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, GetCurrentThreadId());
pFileOpen->SetTitle(L"MyTestIFileOpenDialog01");
// Show the Open dialog box.
hr = pFileOpen->Show(NULL);
// Get the file name from the dialog box.
if (SUCCEEDED(hr))
{
IShellItem *pItem;
hr = pFileOpen->GetResult(&pItem);
if (SUCCEEDED(hr))
{
PWSTR pszFilePath;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
// Display the file name to the user.
if (SUCCEEDED(hr))
{
MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
CoUninitialize();
}
return 0;
}
person
mnistic
schedule
28.09.2018
IFileDialog
или вам нужно что-то вродеOpenFileDialog
илиGetOpenFileName
- person ST3   schedule 09.03.2014IFileOpenDialog
является предпочтительным решением для Vista и более поздних версий. Он заменяетGetOpenFileName()
. ОднакоGetOpenFileName()
поддерживает перехват, который позволяет получить доступ к HWND диалога и, таким образом, может быть позиционирован вручную.IFileOpenDialog
не предоставляет ту же функциональность. - person Remy Lebeau   schedule 21.01.2015