我有一个表单,我正在尝试打开位于表单顶部而不是屏幕中心的文件夹浏览器对话框。 (Windows 7,Visual Studio Express 2012)
表单名称为“form”
我使用FolderBrowserDialog尝试了以下内容:
browseFolderDialog = gcnew FolderBrowserDialog();
DialogResult result = browseFolderDialog->ShowDialog(form);
我也尝试使用SHBrowseForFolder提供表单句柄为hwnd:
System::String^ BrowseUtility::getFolder(System::Windows::Forms::Form^ form)
{
//HWND hwnd = GetForegroundWindow();
System::Windows::Forms::Control ^ctrl1 = form; // Form derives from Control
System::IntPtr wrappedHandle = form->Handle;
void *windowHandle1 = wrappedHandle.ToPointer();
HWND hwnd = reinterpret_cast<HWND>(windowHandle1);
System::String^ result = L"-1";
TCHAR szFolder[MAX_PATH];
if (GetFolderSelection(hwnd, szFolder, TEXT("Please select a folder.")))
{
result = gcnew System::String(szFolder);
}
return result;
}
BOOL BrowseUtility::GetFolderSelection(HWND hWnd, LPTSTR szBuf, LPCTSTR szTitle)
{
LPITEMIDLIST pidl = NULL;
BROWSEINFO bi = { 0 };
BOOL bResult = FALSE;
bi.hwndOwner = hWnd;
bi.pszDisplayName = szBuf;
bi.pidlRoot = NULL;
bi.lpszTitle = szTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
if ((pidl = SHBrowseForFolder(&bi)) != NULL)
{
bResult = SHGetPathFromIDList(pidl, szBuf);
CoTaskMemFree(pidl);
}
return bResult;
}
注意我甚至试过提供hWnd作为HWND hwnd = GetForegroundWindow();
文件夹浏览器仍显示在屏幕中央。
任何想法都会有所帮助 - 我知道这不会那么难
答案 0 :(得分:0)
感谢您的建议 我需要使用回调来处理setWindowPos
以下是我提出的课程:
CustomFolderBrowser
部首:
#ifndef _CUSTOMFOLDERBROWSER_H_
#define _CUSTOMFOLDERBROWSER_H_
class CustomFolderBrowser
{
public: CustomFolderBrowser(void);
public: System::Windows::Forms::DialogResult showDialog(System::Windows::Forms::Form^ form);
public: System::String^ getSelectedFolder(void);
};
#endif
cpp文件:
#include "CustomFolderBrowser.h"
#include <shlobj.h>
#include <Windows.h>
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "shell32.lib")
int x;
int y;
int w;
int h;
TCHAR result[MAX_PATH];
int CALLBACK Folder_Browse_Callback (HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData);
CustomFolderBrowser::CustomFolderBrowser () {}
System::Windows::Forms::DialogResult CustomFolderBrowser::showDialog(System::Windows::Forms::Form^ form)
{
x = form->Bounds.X;
y = form->Bounds.Y;
w = form->Bounds.Width;
h = form->Bounds.Height;
System::IntPtr wrappedHandle = form->Handle;
void *windowHandle1 = wrappedHandle.ToPointer();
HWND hwnd = reinterpret_cast<HWND>(windowHandle1);
LPITEMIDLIST pidl = NULL;
BROWSEINFO bi = { 0 };
BOOL bResult = FALSE;
bi.hwndOwner = hwnd;
bi.pszDisplayName = result;
bi.pidlRoot = NULL;
bi.lpszTitle = TEXT("Please select a folder.");
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
bi.lpfn = Folder_Browse_Callback;
bi.lParam = (LPARAM)this;
if ((pidl = SHBrowseForFolder(&bi)) != NULL)
{
bResult = SHGetPathFromIDList(pidl, result);
CoTaskMemFree(pidl);
}
if (bResult)
return System::Windows::Forms::DialogResult::OK;
return System::Windows::Forms::DialogResult::Cancel;
}
System::String^ CustomFolderBrowser::getSelectedFolder(void)
{
return gcnew System::String(result);
}
int CALLBACK Folder_Browse_Callback (HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
{
if(uMsg == BFFM_INITIALIZED)
{
RECT desktopRect;
HWND hDesktop=::GetDesktopWindow();
::GetWindowRect(hDesktop, &desktopRect);
RECT dialogRect;
::GetWindowRect(hwnd, &dialogRect);
int wDialog = dialogRect.right - dialogRect.left;
int hDialog = dialogRect.bottom - dialogRect.top;
double xoff = (w - wDialog)/2.0;
double yoff = (h - hDialog)/2.0;
int xDialog = x + (int)xoff;
int yDialog = y + (int)yoff;
if(xDialog < 0)
xDialog = 0;
if(xDialog + wDialog > desktopRect.right)
xDialog = desktopRect.right - wDialog;
if(yDialog + hDialog > desktopRect.bottom)
yDialog = desktopRect.bottom - hDialog;
if(yDialog < 0)
yDialog = 0;
::SetWindowPos(hwnd, NULL, xDialog, yDialog, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
}
return 0;
}
然后我用
显示对话框CustomFolderBrowser* bu = new CustomFolderBrowser();
DialogResult result = bu->showDialog(form);
if(result == DialogResult::OK)
{
label->Text = bu->getSelectedFolder();
}
感谢您的建议
答案 1 :(得分:0)
我查看了Winforms中的C#解决方案,并提出了以下c ++解决方案
Class CenterWinDialog
部首:
#pragma once
ref class CenterWinDialog :
public System::IDisposable
{
public: static int mTries;
public: static System::Windows::Forms::Form^ mOwner;
public:
CenterWinDialog(System::Windows::Forms::Form^ form);
public:
void findDialog(void);
delegate void FindDelegate();
~CenterWinDialog()
{
mTries = -1;
this->!CenterWinDialog();
}
!CenterWinDialog() {}
};
CPP:
#include "CenterWinDialog.h"
#include <Windows.h>
#pragma comment(lib, "User32.lib")
using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::Runtime::InteropServices;
BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam)
{
TCHAR s[260];
GetClassName(hwnd, s, 260);
String^ name = gcnew String(s);
if (name != "#32770") return true;
System::Drawing::Rectangle^ frmRect = gcnew System::Drawing::Rectangle(
CenterWinDialog::mOwner->Location, CenterWinDialog::mOwner->Size);
RECT dlgRect;
GetWindowRect(hwnd, &dlgRect);
RECT dskRect;
HWND hDesktop = GetDesktopWindow();
GetWindowRect(hDesktop, &dskRect);
int wdlg = dlgRect.right - dlgRect.left;
int hdlg = dlgRect.bottom - dlgRect.top;
int xdlg = frmRect->X + (frmRect->Width - wdlg)/2;;
int ydlg = frmRect->Y + (frmRect->Height - hdlg)/2;;
if(xdlg < 0)
xdlg = 0;
if(xdlg + wdlg > dskRect.right)
xdlg = dskRect.right - wdlg;
if(ydlg + hdlg > dskRect.bottom)
ydlg = dskRect.bottom - hdlg;
if(ydlg < 0)
ydlg = 0;
MoveWindow(hwnd, xdlg, ydlg, wdlg, hdlg, true);
return false;
}
CenterWinDialog::CenterWinDialog(Form^ owner)
{
mTries = 0;
mOwner = owner;
FindDelegate^ action = gcnew FindDelegate(this, &CenterWinDialog::findDialog);
owner->BeginInvoke(action);
}
void CenterWinDialog::findDialog()
{
if (CenterWinDialog::mTries < 0) return;
if (EnumThreadWindows(GetCurrentThreadId(), EnumThreadWndProc, NULL))
{
FindDelegate^ action = gcnew FindDelegate(this, &CenterWinDialog::findDialog);
if (++CenterWinDialog::mTries < 10)
CenterWinDialog::mOwner->BeginInvoke(action);
}
}
典型用法:
FolderBrowserDialog^ fbd = gcnew FolderBrowserDialog();
gcnew CenterWinDialog(form);
DialogResult result = fbd->ShowDialog();
if(result == DialogResult::OK)
{
label->Text = fbd->SelectedPath;
}