當前位置:網站首頁>關於創建模態窗口和非模態窗口的研究

關於創建模態窗口和非模態窗口的研究

2022-05-14 16:53:17clever101

作者:朱金燦
來源:clever101的專欄

模態窗口和非模態窗口的區別

  模態窗口和非模態窗口的主要區別在於是獨占的活動窗口。模態窗口是獨占的活動窗口,非模態窗口不是獨占的活動窗口,是可以和其它窗口進行切換的。注意這裏說的模態窗口和非模態窗口並不限於模態對話框和非模態對話框。

創建模態窗口和非模態窗口的做法

  模態窗口分為兩種,一種是模態對話框,使用DialogBox函數來彈出,這個網上資料很多,這裏就不介紹了;這裏要重點介紹的是創建不是對話框界面形式的模態窗口,具體做法是需要在CreateWindow後將它的父窗口設置為不可用,使用EnableWindow函數,在關閉模態窗口之前調用EnableWindow函數將父窗口設置為可用。有兩個創建模態窗口的函數:CreateChildWindow和DisplayModalWindow。建議使用DisplayModalWindow,因為使用DisplayModalWindow更為簡潔。創建非模態窗口則直接調用創建窗口函數即可。

//子窗口的消息響應函數
LRESULT CALLBACK WndProc1(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
    
	switch (wMsg)
	{
    
	case WM_DESTROY:
	{
    
		PostQuitMessage(0);
	}
		break;
	case WM_CLOSE:
	{
    
		//啟用主窗口
		if(NULL!= g_hWnd)
		  EnableWindow(g_hWnd, TRUE);

		return DefWindowProc(hWnd, wMsg, wParam, lParam);
	}
	default:
		return DefWindowProc(hWnd, wMsg, wParam, lParam);
	}
}

/* 目的:創建模態或非模態子窗口 pszWinTitle —— 窗口標題 pszClassName —— 窗口類名(這個可以自己指定一個常量字符串) bModal —— 是否為模態窗口,true為模態,false為非模態 */
void CreateChildWindow(LPCTSTR pszWinTitle,TCHAR* pszClassName,bool bModal)
{
    
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc1;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = GetModuleHandle(nullptr);
	wcex.hIcon = 0;
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszMenuName = NULL;

	wcex.lpszClassName = (LPCWSTR)pszClassName;
	wcex.hIconSm = 0;
	RegisterClassEx(&wcex);

	HWND hChildWnd = CreateWindow(pszClassName, pszWinTitle,WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
		0, CW_USEDEFAULT, 0, NULL, NULL, wcex.hInstance, 0);

	//禁用主窗口
	if(bModal)
	   EnableWindow(g_hWnd,FALSE);
	
	ShowWindow(hChildWnd, SW_SHOW);
	UpdateWindow(hChildWnd);

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

LRESULT CALLBACK ChildWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
 switch (message) 
 {
    
   case WM_DESTROY:
       PostQuitMessage(0);
         return 0;
	}
    return DefWindowProc(hwnd, message, wParam, lParam);
}
//創建模態窗口的第二種做法
void DisplayModalWindow(HWND hParent)
{
    
	// 注册窗口類
	WNDCLASS wndclass;
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInst;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpfnWndProc = ChildWinProc;
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = TEXT("ModalWindow2");
    RegisterClass(&wndclass);

	EnableWindow(hParent, FALSE);
	HWND hChildWin = CreateWindow(TEXT("ModalWindow2"),TEXT("模態窗口2"),WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		hParent,
		NULL,
		(HINSTANCE)GetWindowLong(hParent, GWLP_HINSTANCE),
		NULL);
	ShowWindow(hChildWin, SW_SHOW);
	UpdateWindow(hChildWin);

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

	EnableWindow(hParent, TRUE);
// SetForegroundWindow(hParent);
	SetActiveWindow(hParent);
}

//CreateChildWindow函數的調用處
void OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify)
{
    
	switch (id)
	{
    
	case IDM_ABOUT:
		DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
		break;
	case IDM_EXIT:
		DestroyWindow(hWnd);
		break;
	case ID_CREATE_MODAL:
	{
    
		//創建模態窗口的第一種做法
		CreateChildWindow(_T("模態窗口"),_T("ModalChildWin"),true);
		break;
	}
	case ID_CREATE_MODELESS:
	{
    
		//創建非模態窗口
		CreateChildWindow(_T("非模態窗口"), _T("ModelessChildWin"),false);
		break;
	}
    case ID_DISPLAY_MODAL:
	{
    
		DisplayModalWindow(hWnd);
		break;
	}
	default:
		return;
	}
}

版權聲明
本文為[clever101]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/134/202205141633252273.html

隨機推薦