0

フォームがあり、画面の中央ではなく、フォームの上に配置されているフォルダー ブラウザー ダイアログを開こうとしています。(Windows 7、Visual Studio Express 2012)

フォーム名は「フォーム」

FolderBrowserDialog で次のことを試しました。

browseFolderDialog = gcnew FolderBrowserDialog();
DialogResult result = browseFolderDialog->ShowDialog(form);

また、フォームのハンドルを hwnd として提供する SHBrowseForFolder を使用してみました。

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(); として提供しようとしたことにも注意してください。

フォルダ ブラウザは引き続き画面の中央に表示されます。

どんなアイデアでも役に立ちます-これはそれほど難しいことではありません

4

2 に答える 2

0

Winforms の C# ソリューションを調べて、次の C++ ソリューションを思いつきました。

クラス 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;
}
于 2012-12-13T06:46:36.553 に答える
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();
}

提案をありがとう

于 2012-12-12T09:58:37.170 に答える