[Win32SDK基本] 模态窗口 和 多窗口

原创 2015年07月08日 13:52:57
本文由CSDN用户zuishikonghuan所作,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/46802537

什么是模态窗口呢,想必大家都知道模态对话框和非模态对话框吧,模态窗口和模态对话框类似。假设我们需要在按钮单击时创建一个新窗口,如果只是在按钮单击消息里CreateWindow(Ex)一个新窗口,那么这个窗口和之前的窗口是独立的,他们同时接受用户的响应。那么我们想在新窗口完成它的使命之前让之前的窗口拒绝接收响应,就要创建一个“模态窗口”

如何创建模态窗口呢,其实模态窗口和真正的窗口一样,只是创建之前将之前的窗口禁用掉,关闭之后恢复先前的窗口而已。

如果创建的第二个窗口还是使用原来的窗口类,他和之前的窗口就会公用同一个窗口回调函数,我们可以根据回调函数发回的窗口句柄判断是那一个窗口,当然,如果我们愿意,我们可以使用SetWindowLong(Ptr)修改窗口回调函数或者干脆重新注册一个窗口类。我喜欢再注册一个窗口类,因为这么做最简单,程序最美观,不至于一个回调函数特别不清晰。

那么我们就可以通过收到第二个窗口的WM_DESTROY消息时恢复第一个窗口,不过那样会使代码显得有点乱,因此,我们先写一个函数:

void Modal(HWND last){
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	EnableWindow(last, TRUE);
	SetForegroundWindow(last);
}

这个函数是做什么的呢,很简单,他重新写了一个消息循环(可以把这个消息循环称为模态循环),函数调用之后,线程的消息都转移到这个消息循环里了,当收到WM_QUIT消息时只退出这个消息循环,还有一个WinMain上的消息循环顶着,退出后再恢复之前的窗口,这样,我们只需要创建完窗口调用一下这个函数就OK了。

还是以我的博客“[Win32SDK基本] 窗口详解(超详细)”(地址:http://blog.csdn.net/zuishikonghuan/article/details/46378475)为模板,进一步编写。

首先,重新写一个我们的回调函数:

LRESULT CALLBACK WndProc2(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg){
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
		return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

这是第二个窗口的“回调函数”

再在注册窗口类下面再注册一个窗口类

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	
	//InitCommonControls();

	//这里是在构建窗口类结构
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;//窗口回调函数指针
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;//实例句柄
	wc.hIcon = LoadIcon(hInstance, TEXT("ICON_1"));
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);//默认指针
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);//默认背景颜色
	wc.lpszMenuName = NULL;
	wc.lpszClassName = AppName;//窗口类名

	//注册窗口类
	if (!RegisterClass(&wc))
	{
		MessageBox(NULL, TEXT("注册窗口类失败!"), TEXT("错误"), MB_ICONERROR);
		return 0;
	}

	//注册第二个窗口的窗口类
	wc.lpfnWndProc = WndProc2;
	wc.lpszClassName = AppName2;

	if (!RegisterClass(&wc))
	{
		MessageBox(NULL, TEXT("注册窗口类失败!"), TEXT("错误"), MB_ICONERROR);
		return 0;
	}//。。。。。。

创建模态窗口,在之前创建的又有文字又有图片的按钮的单击消息里创建:

	case WM_COMMAND:
		int id;
		int ent;
		ent = HIWORD(wParam);//通知吗
		id = LOWORD(wParam);//子窗口ID
。。。
		//判断按钮的单机事件
		if (ent == BN_CLICKED){
			switch (id)
			{
			case 4://按钮的子窗口ID
。。。

			case 7:
				EnableWindow(hwnd, FALSE);
				hwnd2 = CreateWindowEx(NULL, AppName2, TEXT("窗口标题"), WS_OVERLAPPEDWINDOW, 150, 150, 500, 500, hwnd,NULL, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), 0);
				if (hwnd2 == NULL)
				{
					MessageBox(NULL, TEXT("创建窗口失败!"), TEXT("错误"), MB_ICONERROR);
					return 0;
				}
				SetWindowLong(hwnd2, GWL_WNDPROC, (LONG)&WndProc2);
				ShowWindow(hwnd2, 5);
				UpdateWindow(hwnd2);

				Modal(hwnd);
			case 8://Check Boxes被单机
。。。。
			}
		}
		break;
注意CreateWindowEx的倒数第四个参数用之前的窗口的句柄。(父窗口,单和原来的窗口是两个窗口,如果这里不用hwnd,结果也能实现类似效果,但是单机之前的窗口时新窗口就不闪动了)

效果图:

(在第二个窗口关闭之前,第一个不能与用户交互)

多窗口:

创建一个新窗口与原来的窗口相互独立:

基本上一样,需要改两点:

1.去掉 EnableWindow(hwnd, FALSE); 和 Modal(hwnd);

2.将 CreateWindowEx  倒数第四个参数(父窗口)改为NULL


版权声明:本文为博主原创文章,本文作者授权在知识共享"署名-非商业性使用-相同方式共享" 4.0 (CC BY-NC-SA 4.0) 许可证下发布,您可以自由地在任何媒介以任何形式复制、发行本作品、修改、转换或以本作品为基础进行创作;您将必须同样提供原作者信息以及协议声明,您不得将本作品用于商业目的,并且您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。

[Win32SDK基本] Combo Box

老规矩,先上MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/bb775792(v=vs.85).aspx 其实还是子窗口,s...
  • zuishikonghuan
  • zuishikonghuan
  • 2015年07月14日 09:15
  • 2024

[Win32SDK基本]GetWindowRect/GetClientRect

GetWindowRect/GetClientRect 获取窗口矩形/获取窗口客户区矩形 函数原型为:BOOL WINAPI GetWindowRect( _In_ HWND hWnd, ...
  • zuishikonghuan
  • zuishikonghuan
  • 2015年06月18日 13:48
  • 1946

模态窗口和非模态窗口

对话框一般分为两种类型:模态类型(modal)与非模态类型(modeless)。所谓模态对话框,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。非模态对话框则不会强制...
  • wds1224
  • wds1224
  • 2007年07月25日 19:11
  • 1854

[Win32SDK基本]WM_MOUSELEAVE消息和TrackMouseEvent

WM_MOUSELEAVE这个消息很有意思,它是鼠标指针离开窗口时发送的,但是它每一次发送都必须用TrackMouseEvent注册一次。 如果想自绘制窗口控件(比如按钮),使用WM_MOUSELEA...
  • zuishikonghuan
  • zuishikonghuan
  • 2015年06月17日 13:45
  • 2074

模态窗口和非模态窗口

   对话框一般分为两种类型:模态类型(modal)与非模态类型(modeless)。所谓模态对话框,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。非模态对话框则不...
  • yangli1103
  • yangli1103
  • 2006年08月17日 09:46
  • 588

[Win32SDK基本]Edit Control详解

对于Win32窗口控件也说了不少了,今天来说说编辑框 Edit Control控件。 MSDN:https://msdn.microsoft.com/en-us/library/windows/des...
  • zuishikonghuan
  • zuishikonghuan
  • 2015年07月06日 13:44
  • 2224

C#模态窗口和非模态窗口

C#窗口对话框一般分为两种类型:模态类型(modal)与非模态类型(modeless)。 所谓模态对话框,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。非模态对话...
  • liyanchen78
  • liyanchen78
  • 2013年08月20日 10:30
  • 11370

MFC模态窗口和非模态窗口

模态窗口:程序运行的过程中,若出现了模态对话框,那么主窗口将无法发送消息,直到模态对话框退出才可以发送。即只能操作弹出窗口,不能操作主窗口,只有当模态窗口退出后才能操作主窗口。 创建并显示一个模态...
  • u010275850
  • u010275850
  • 2018年01月12日 22:26
  • 16

我为什么选择Win32SDK以及Win32SDK的特点

玩Win32SDK已有一段时间内,从初中的时候就开始了,虽然时间紧,就假期里或插空背着父母玩会,但是两三年下来,收获也是不浅。所以就想着把我学的东西都整理下来,算是纪念吧,如果还能帮助一下别人,也是我...
  • zuishikonghuan
  • zuishikonghuan
  • 2015年06月02日 13:43
  • 2708

模态窗口详解及各浏览器适配经验分享

模态窗口详解及各浏览器适配经验分享
  • gunri_tianjin
  • gunri_tianjin
  • 2017年08月28日 11:10
  • 368
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[Win32SDK基本] 模态窗口 和 多窗口
举报原因:
原因补充:

(最多只允许输入30个字)