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_DLGMODALFRAME
Extended Window Style,并将WS_CLIPCHILDREN
Window 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 中的父子窗口问题的主要内容,如果未能解决你的问题,请参考以下文章