跨进程创建非WS_CHILD的子窗口,Z轴错乱,子窗口被父窗口盖住

radiancez 2013-09-03 01:39:50
现在有2个进程,进程1和进程2。
进程1创建一个父窗口"进程1-父窗口",再创建3个子窗口"进程1-子窗口1"、"进程1-子窗口2"、"进程1-子窗口3",3个子窗口的owner都是"进程1-父窗口"。再创建TopMost的1个孙子窗口"进程1-TopMost孙子窗口1-1",owner是"进程1-子窗口1"。
进程2通过FindWindow找到进程1的"进程1-父窗口",创建3个子窗口"进程2-子窗口1"、"进程2-子窗口2"、"进程2-子窗口3",3个子窗口的owner也都是"进程1-父窗口"。

此时,在各个窗口间点来点去,Z轴就错乱了,子窗口被父窗口盖住。
如何能让它们的Z轴正常,请大侠帮忙!在线等。。。。。。。。。。。。。。

测试发现,如果把进程2的3个子窗口关闭,问题消失,Z轴正常;或者把进程1的TopMost孙子窗口关闭,Z轴也正常。

进程1代码:

#include "stdafx.h"
#include "Test1.h"

#define TEST_WND_CLASS_NAME _T("TestWindow")

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wndCls;
wndCls.style = CS_HREDRAW | CS_VREDRAW;
wndCls.lpfnWndProc = DefWindowProc;
wndCls.cbClsExtra = 0;
wndCls.cbWndExtra = 0;
wndCls.hInstance = hInstance;
wndCls.hIcon = NULL;
wndCls.hCursor = ::LoadCursor (NULL, IDC_CROSS);
wndCls.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndCls.lpszMenuName = NULL;
wndCls.lpszClassName = TEST_WND_CLASS_NAME;
::RegisterClass (&wndCls);

HWND hParent = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-父窗口"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
150, 100, 1000, 400, NULL, NULL, hInstance, NULL);

HWND hWnd1 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-子窗口1"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
300, 50, 250, 150, hParent, NULL, hInstance, NULL);

HWND hWnd2 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-子窗口2"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
550, 50, 250, 150, hParent, NULL, hInstance, NULL);

HWND hWnd3 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-子窗口3"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
800, 50, 250, 150, hParent, NULL, hInstance, NULL);

HWND hWnd1_1 = ::CreateWindowEx(WS_EX_TOPMOST, TEST_WND_CLASS_NAME, _T("进程1-TopMost孙子窗口1-1"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
200, 200, 350, 150, hWnd1, NULL, hInstance, NULL);

MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

return 0;
}


进程2代码:

#include "stdafx.h"
#include "Test2.h"

#define TEST_WND_CLASS_NAME _T("TestWindow")

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wndCls;
wndCls.style = CS_HREDRAW | CS_VREDRAW;
wndCls.lpfnWndProc = DefWindowProc;
wndCls.cbClsExtra = 0;
wndCls.cbWndExtra = 0;
wndCls.hInstance = hInstance;
wndCls.hIcon = NULL;
wndCls.hCursor = ::LoadCursor (NULL, IDC_CROSS);
wndCls.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndCls.lpszMenuName = NULL;
wndCls.lpszClassName = TEST_WND_CLASS_NAME;
::RegisterClass (&wndCls);

// 找到进程1的父窗口
HWND hParent = ::FindWindow(TEST_WND_CLASS_NAME, _T("进程1-父窗口"));

HWND hWnd1 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程2-子窗口1"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
300, 400, 250, 150, hParent, NULL, hInstance, NULL);

HWND hWnd2 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程2-子窗口2"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
550, 400, 250, 150, hParent, NULL, hInstance, NULL);

HWND hWnd3 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程2-子窗口3"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
800, 400, 250, 150, hParent, NULL, hInstance, NULL);

MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

return 0;
}
...全文
250 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2013-10-08
  • 打赏
  • 举报
回复
您好 我是本版版主 此帖已多日无人关注 请您及时结帖 如您认为问题没有解决可按无满意结帖处理 另外本版设置了疑难问题汇总帖 并已在版面置顶 相关规定其帖子中有说明 您可以根据规定提交您帖子的链接 如您目前不想结帖只需回帖说明 我们会删除此结帖通知 见此回复三日内无回应 我们将强制结帖 相关规定详见界面界面版关于版主结帖工作的具体办法
cjfdqchwhj 2013-09-06
  • 打赏
  • 举报
回复
占个沙发看看
Eleven 2013-09-04
  • 打赏
  • 举报
回复
引用 3 楼 RadianceZ 的回复:
如图:
进程一中,父窗口应该始终在后面的吧。


#include "stdafx.h"

#define TEST_WND_CLASS_NAME  _T("TestWindow")

int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
	WNDCLASS wndCls;
	wndCls.style = CS_HREDRAW | CS_VREDRAW;
	wndCls.lpfnWndProc = DefWindowProc;
	wndCls.cbClsExtra = 0;
	wndCls.cbWndExtra = 0;
	wndCls.hInstance = hInstance;
	wndCls.hIcon = NULL;
	wndCls.hCursor = ::LoadCursor (NULL, IDC_CROSS);
	wndCls.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wndCls.lpszMenuName = NULL;
	wndCls.lpszClassName = TEST_WND_CLASS_NAME;
	::RegisterClass (&wndCls);

	HWND hParent = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-父窗口"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		150, 100, 1000, 400, NULL, NULL, hInstance, NULL);

	HWND hWnd1 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-子窗口1"), WS_POPUPWINDOW | WS_CAPTION| WS_VISIBLE, 
		300, 50, 250, 150, hParent, NULL, hInstance, NULL);
	if(NULL == GetParent(hWnd1))
	{
		MessageBox(NULL, _T("AAA"), NULL, 0);
	}

	HWND hWnd2 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-子窗口2"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		550, 50, 250, 150, hParent, NULL, hInstance, NULL);

	HWND hWnd3 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程1-子窗口3"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		800, 50, 250, 150, hParent, NULL, hInstance, NULL);

	HWND hWnd1_1 = ::CreateWindowEx(WS_EX_TOPMOST, TEST_WND_CLASS_NAME, _T("进程1-TopMost孙子窗口1-1"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		200, 200, 350, 150, hWnd1, NULL, hInstance, NULL);

	MSG msg;
	while (::GetMessage(&msg, NULL, 0, 0))
	{
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}

	return 0;
}


#include "stdafx.h"


#define TEST_WND_CLASS_NAME  _T("TestWindow")

int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
	WNDCLASS wndCls;
	wndCls.style = CS_HREDRAW | CS_VREDRAW;
	wndCls.lpfnWndProc = DefWindowProc;
	wndCls.cbClsExtra = 0;
	wndCls.cbWndExtra = 0;
	wndCls.hInstance = hInstance;
	wndCls.hIcon = NULL;
	wndCls.hCursor = ::LoadCursor (NULL, IDC_CROSS);
	wndCls.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wndCls.lpszMenuName = NULL;
	wndCls.lpszClassName = TEST_WND_CLASS_NAME;
	::RegisterClass (&wndCls);

	// 找到进程1的父窗口
	HWND hParent = ::FindWindow(TEST_WND_CLASS_NAME, _T("进程1-父窗口"));

	HWND hWnd1 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程2-子窗口1"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		300, 400, 250, 150, hParent, NULL, hInstance, NULL);

	HWND hWnd2 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程2-子窗口2"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		550, 400, 250, 150, hParent, NULL, hInstance, NULL);

	HWND hWnd3 = ::CreateWindowEx(NULL, TEST_WND_CLASS_NAME, _T("进程2-子窗口3"), WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, 
		800, 400, 250, 150, hParent, NULL, hInstance, NULL);

	MSG msg;
	while (::GetMessage(&msg, NULL, 0, 0))
	{
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}

	return 0;
}
Eleven 2013-09-04
  • 打赏
  • 举报
回复
msdn里面说明了父子窗口必须是同一个进程的。但是由于窗口句柄是系统全局唯一的,不属于同一个进程的情况下,也可以成功调用,可能行为未定义。
radiancez 2013-09-03
  • 打赏
  • 举报
回复
如图:
radiancez 2013-09-03
  • 打赏
  • 举报
回复
引用 1 楼 VisualEleven 的回复:
WS_OVERLAPPEDWINDOW风格的窗口没有父窗口,如果调用GetParent()操作将会返回NULL。 如果你换成WS_POPUP风格的话,应该不会有这个问题的。
我把WS_OVERLAPPEDWINDOW换成WS_POPUPWINDOW,用Spy++看了下,有Parent了,还是没有解决我的问题,Z order还是会乱掉。
Eleven 2013-09-03
  • 打赏
  • 举报
回复
WS_OVERLAPPEDWINDOW风格的窗口没有父窗口,如果调用GetParent()操作将会返回NULL。 如果你换成WS_POPUP风格的话,应该不会有这个问题的。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧