【问题标题】:How to make a window open in a cascade position (using MFC)如何在级联位置打开窗口(使用 MFC)
【发布时间】:2015-10-15 10:07:48
【问题描述】:

我正在使用 Windows MFC 创建一个小程序。 我想让程序的多个实例出现在级联位置。

目前程序总是居中显示,即不可能在多个窗口中看到它。

有没有一种自动的方式让窗口在级联位置创建多个实例?

为了测试,我使用了一个包含多行的批处理脚本:

 "start MyProgram.exe"
 "start MyProgram.exe"
 "start MyProgram.exe"

我使用的对话框是从 CDialogEx 派生的(但我使用 CDialog 有相同的)

我希望这是对话框的标志/属性。

在更改 .rc 文件之前有这样的属性

IDD_MAIN_DLG DIALOGEX 0, 0, 260, 185 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION 

我知道 CascadeWindows() 函数,但据我所知,它需要更多地了解哪些实例已经运行

【问题讨论】:

  • 不,没有,您必须通过MoveWindowOnInitDialog 方法中的对话框自行完成。
  • IMO 应删除 c++ 和 MFC 标签,因为您希望“windows”在不修改程序的情况下完成这项工作
  • 我不同意罗布森的观点。我想配置我的 MFC 代码,以便 windows 可以处理它的位置......虽然解决方案可能超出了 MFC 的范围。如果其他人(像我一样)搜索 MFC 解决方案,他们会发现他们需要使用原始 WinApi。

标签: c++ windows mfc


【解决方案1】:

下面的代码作为起点怎么样?

#include <Psapi.h>
namespace {
    size_t nWnds = 0;
    HWND hWnds[10];

    BOOL CALLBACK enumerate(HWND hWnd, LPARAM This)
    {
        HWND hWndThis = reinterpret_cast<HWND>(This);

        TCHAR nameThis[MAX_PATH], nameOther[MAX_PATH];
        VERIFY(GetWindowModuleFileName(hWndThis, nameThis, _countof(nameThis)));

        TCHAR wndclass[32];
        VERIFY(RealGetWindowClass(hWnd, wndclass, _countof(wndclass)));

        if (_tcscmp(wndclass, _T("#32770")) == 0) {
            DWORD pid;
            GetWindowThreadProcessId(hWnd, &pid);
            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
            if (hProcess != NULL) {
                if (GetModuleFileNameEx(hProcess, NULL, nameOther, _countof(nameOther))) {
                    if (_tcscmp(nameThis, nameOther) == 0) {
                        hWnds[nWnds++] = hWnd;
                    }
                }
                VERIFY(CloseHandle(hProcess));
                hProcess = NULL;
            }
        }

        return TRUE;
    }
}

BOOL CMFCApplication1Dlg::OnInitDialog()
{
    // ...

    VERIFY(EnumWindows(enumerate, reinterpret_cast<LPARAM>(m_hWnd)));
    if (nWnds > 1) {
        VERIFY(CascadeWindows(NULL, MDITILE_ZORDER, NULL, nWnds, hWnds));
    }

    return TRUE;
}

它包括对OnInitDialog 的更改,以扫描由您的可执行文件创建的所有顶级对话框,然后调用CascadeWindows。当然,在 enumerate 中,您还可以将找到的每个窗口移动到从 CPoint(x, y) 开始的点,并随每个找到的窗口更改 CSize(xoffset, yoffset)

注意事项:

  1. CascadeWindows 看起来不是正确的解决方案,它会恢复所有最大化的窗口,并且不仅会触摸由您的进程创建的窗口(我更愿意这样做)。
  2. 如果您的流程创建了多个顶级对话框,那么您可能需要检测要移动哪些对话框。
  3. 如果用户复制您的程序文件,则模块文件名将不同。
  4. 只是概念验证代码,您需要添加错误检查和边界检查。

【讨论】:

  • 这可能是一个解决方案。似乎安排得很好(在 initDialog 中只有一个函数调用)。然而,我的目标是 MS 提供开箱即用的解决方案。我目前没有使用我的 Windows 工具。这个周末我去试试。
猜你喜欢
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 2013-09-04
  • 2019-02-18
相关资源
最近更新 更多