VC++ 非 mfc 中的父子窗口问题

Posted

技术标签:

【中文标题】VC++ 非 mfc 中的父子窗口问题【英文标题】:Parent child window issue in VC++ non mfc 【发布时间】:2014-11-10 11:58:30 【问题描述】:

下面的代码可以正常工作,但是当我将鼠标放在父窗口上并拖动它时,子窗口和父窗口会分开。但是当我放置鼠标并移动它时,我希望子窗口和父窗口一起移动而不是分开。我为子窗口尝试了一些类似 WS_DISABLED 的东西,但没有奏效。请让我知道需要进行哪些修改。我的应用程序不是 MFC。下面是我的代码:

void displayProgressBar()

HINSTANCE g_hinst;
if( (g_hinst = GetModuleHandle( L"LoadFunc.dll" )) == NULL )

    g_hinst = GetModuleHandle( 0 );

RECT screenSize;

InitCommonControls();
BOOL rc = SystemParametersInfo( SPI_GETWORKAREA, 0, &screenSize, 0 );
int height = screenSize.bottom / 15;
int width = screenSize.right / 3;
int x = (screenSize.bottom / 2) - (height / 2);
int y = (screenSize.right / 2) - (width / 2);

//  create a static window, display a graphic and attach a progress bar to it.
wchar_t currentDir[MAX_PATH];
_wgetcwd( currentDir, _MAX_PATH );
HANDLE img = LoadImage(g_hinst, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0,  LR_DEFAULTCOLOR );
//MessageBox(0,L"in",L"out",MB_OK);
hwndParent = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE,
                          WC_STATIC,
                          L"install in progress",
                          WS_POPUP | WS_VISIBLE | WS_CAPTION | SS_BITMAP,
                          x,
                          y,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          hwndParent,
                          NULL,
                          g_hinst,
                          NULL) ;
                          EnableWindow(hwndPB,FALSE);
SendMessage(hwndParent, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)img);
RECT RectControl;
::GetWindowRect( hwndParent, &RectControl );

//MessageBox(0,L"1",L"1",MB_OK);
hwndPB = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE,
    PROGRESS_CLASS,
    NULL,
    WS_POPUP | WS_VISIBLE,
    x + 10, // x
    RectControl.bottom - 25, // y
    RectControl.right - RectControl.left - 20, // width
    20, // height
    hwndParent,
    (HMENU) 0,
    g_hinst,
    NULL);
    EnableWindow(hwndPB,FALSE);

SendMessage(hwndPB, PBM_SETRANGE, 0,
            MAKELPARAM(0, 25));
SendMessage(hwndPB, PBM_SETSTEP, (WPARAM) 2, 0);

提前感谢您提供帮助。

【问题讨论】:

考虑重命名您的问题:“如何锁定子窗口与其父窗口的相对位置?” 如果最后一个问题是您要问的,那么可以在这里找到答案:How to bind child windows to parent window in relative positions? @HuguesFontenelle 感谢您的回复。我们可以根据我的要求对我发布的代码进行任何修改吗? if( (g_hinst = GetModuleHandle( L"LoadFunc.dll" )) == NULL ) - 你为什么选择不处理错误?如果未加载所需的模块,则终止应用程序。不要害怕抛出未捕获的异常——它极大地帮助及早发现错误,而不是掩盖它们。 @Hugues:这个问题是关于 Windows API 的。在问题域的上下文中,声称 “父母独立于孩子移动” 是错误的。要么提供事实(文档),要么移除 cmets(强烈推荐后者)。 @IInspectable 我认为这是大多数 gui 中的默认设置,但我并不精通 windows API,所以我删除了评论。 【参考方案1】:

CreateWindowEx 的hMenu 参数被重载,根据dwStyle 参数有两种不同的含义。以下是文档中的重要信息:

对于重叠或弹出窗口,hMenu 标识要与窗口一起使用的菜单。

对于子窗口,hMenu 指定子窗口标识符。

如果要使用类菜单,则允许为重叠或弹出窗口传递NULL。另一方面,不允许为子窗口传递0:0 不是有效的控件标识符。 (这没有明确说明,但可以很容易地从GetDlgCtrlID 和GetWindowLongPtr [GWLP_ID] 返回 0 表示错误这一事实推断出来。)

要解决您的问题,您必须应用两个更改:指定 WS_CHILD 窗口样式,并分配一个有效的子窗口 ID:

hwndPB = CreateWindowEx(WS_EX_STATICEDGE,
    PROGRESS_CLASS,
    NULL,
    WS_CHILD | WS_VISIBLE,
    x + 10, // x
    RectControl.bottom - 25, // y
    RectControl.right - RectControl.left - 20, // width
    20, // height
    hwndParent,
    (HMENU) 1,    // child-window identifier; this is usually defined as a named
                  // constant in Resource.h
    g_hinst,
    NULL);

【讨论】:

感谢您的回复 我尝试了您分享的方法。但是在使用 WS_CHILD 时进度条不显示。 @helper:删除WS_EX_DLGMODALFRAMEExtended Window Style,并将WS_CLIPCHILDRENWindow Style添加到控件。添加错误处理也没有什么坏处。请查阅相应的 API 文档以了解如何报告错误。 我尝试了建议的更改,但进度条仍然不可见。 @helper:确保在创建子窗口时使用客户端坐标(详见Window Coordinate Systems)。如前所述,请检查错误,如 API documentation 中所述。【参考方案2】:

也许你需要 WS_CHILD 样式的 hwndPB... WS_POPUP 意味着“子”窗口只是禁用父窗口,它们不会一起移动。

顺便说一句,“非 MFC”也称为 Win32 应用程序。

【讨论】:

我为 hwndPB 和 WS_DISABLED 尝试了 WS_CHILD 样式。但是当我这样做时,这个进度条是不可见的。它仅在我使用 WS_POPUP 时可见。 WS_DISABLED 不是必需的。只有 WS_CHILD | WS_VISIBLE(没有 WS_POPUP)。如果窗口未显示,如果 hwndPB 不为空,请尝试使用 ShowWindow。您的 WS_EX_ 标志与 WS_CHILD 窗口不兼容 - 您可以使用经典的 CreateWindow() API。如果返回值为 NULL,则使用 GetLastError() 获取有关错误的更多信息。另外,HMENU 参数的值 0(它是子窗口的 ID)。请注意,子窗口的坐标是相对于其父窗口的,例如0,0 是左上角,无论父位置如何。 我已经尝试过使用 WS_CHILD,在这种情况下进度条不可见。我将尝试使用经典的 CraeteWindow()。 使用 GetClientRect() 代替 GetWindowRect(),然后对于 X、Y、CX、CY - 使用 0、0、RectControl.right、RectControl.bottom。此外,您必须在每个 WM_SIZE 消息上为父窗口调整子控件的大小(如果父窗口很大)。 是的,这有帮助。谢谢你。但我的窗口没有任何按钮或关闭、最小化或最大化选项。现在我需要在特定超时后强制关闭此窗口并释放所有句柄。我无法做到这一点。结果窗口连续显示。

以上是关于VC++ 非 mfc 中的父子窗口问题的主要内容,如果未能解决你的问题,请参考以下文章

WM_MOUSEWHEELWM_LBUTTONDOWN等父子窗口消息传递陷阱

c# mdi父子窗口,传值问题

小弟问个MFC问题

VC MFC中如何制作无边框窗口

vc6.0 mfc窗口问题

jquery iframe父子框架中的元素访问方法