1. 程式人生 > >WIN32學習——對話方塊

WIN32學習——對話方塊

  • 一、對話方塊的分類:

1)模式對話方塊 - 當對話方塊顯示時,會禁止其他視窗的輸入等使用者互動操作。

2)非模式對話方塊 - 在對話方塊顯示後,其他視窗同樣可以接收輸入等使用者互動操作。

  • 二、對話方塊的使用過程:

1)對話方塊視窗處理函式(參照MSDN - DialogProc)

2)新增視窗資源

3)建立對話方塊(模式對話方塊和非模式對話的建立不一樣)

4)關閉對話方塊(模式對話方塊和非模式對話的刪除也不一樣)

  • 三、對話方塊視窗處理函式(參照MSDN),模式對話方塊和非模式對話方塊,對話方塊視窗處理函式一樣

1)BOOL CALLBACK DialogProc(

HWND hwndDlg, //視窗控制代碼

UINT uMsg, //訊息ID

WPARAM wParam, //訊息引數

LPARAM lParam //訊息引數

);

返回TRUE - 表示 DialogProc 函式中處理了這個訊息,預設處理函式不需要處理。

返回FALSE - 表示 DialogProc 函式未處理這個訊息,交給預設處理函式處理。

  • 四、模式對話方塊的建立和關閉

1)建立:

int DialogBox( 

HINSTANCE hInstance, //應用程式例項控制代碼

LPCTSTR lpTemplate, //對話方塊模板資源ID

HWND hWndParent, //對話方塊父視窗

DLGPROC lpDialogFunc //對話方塊視窗處理函式

); 

DialogBox 是一個阻塞函式,只有當對話方塊關閉後,才會返回,繼續執行後續程式碼。返回值是通過 EndDialog 設定。

2)關閉:

BOOL EndDialog( 

HWND hDlg, //關閉的對話方塊視窗控制代碼

int nResult //關閉的返回值

);

關閉模式對話方塊,只能使用 EndDialog ,不能使用 DestroyWindow 等函式。

nResult 是 DialogBox 函式退出時的返回值。在對話方塊退出的時候, nResult 作為返回值被 DialogBox 函式接收,可以用來判斷點選了對話方塊中的哪個按鈕。

注意: EndDialog 函式可以解除 DialogBox 的阻塞。

  • 五、非模式對話方塊的建立和關閉:

1)建立:

HWND CreateDialog( 

HINSTANCE hInstance, //應用程式例項控制代碼

LPCTSTR lpTemplate, //模板資源ID

HWND hWndParent, //父視窗控制代碼

DLGPROC lpDialogFunc //視窗處理函式

);

非阻塞函式,建立成功返回視窗控制代碼,需要使用 ShowWindow 函式顯示對話方塊。

2)關閉:

關閉時使用 DestroyWindow 銷燬視窗,不能使用 EndDialog 關閉對話方塊。

  • 六、對話方塊和視窗的對比:

1.建立

模式對話方塊 - DialogBox 函式,是一個阻塞函式

非模式對話方塊 - CreateDialog 

普通視窗 - CreateWindow/CreateWindowEx

2.視窗處理函式

對話方塊 - DialogProc ,被預設的對話方塊視窗處理函式呼叫

普通視窗 - WindowProc ,需要呼叫預設的視窗處理函式(DefWindowProc)

3.視窗訊息

對話方塊 - WM_INITDIALOG

普通視窗 - WM_CREATE

4.視窗關閉

模式對話方塊 - EndDialog

                        非模式對話方塊 - DestroyWindow

        七、例項程式碼

/*
	說明:實現的功能:1、視窗的基本建立2、手動建立方式取代資源方式新增選單3、模式對話方塊和非模式對話的建立和實現(對話方塊需要新增資源IDD_DLG)
	4、為節省程式碼,模式對話方塊和非模式對話方塊共用一個對話方塊處理函式,因為處理方式不同,已經將模式對話方塊的選單功能遮蔽掉
*/

#include <Windows.h>
#include <tchar.h>
#include "resource.h"

#define ID_DIALOG 1000			//非模式對話方塊
#define ID_MODELDLG 1001		//模式對話方塊
#define ID_QUIT 1002			//退出

HINSTANCE g_hInstance;

//視窗處理函式
LRESULT CALLBACK WndPro(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
//註冊視窗類類名
TCHAR szClassName[] = _T("Main");
//視窗名稱
TCHAR szWindowName[] = _T("視窗名稱");
//對話方塊處理函式
BOOL CALLBACK MyDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
	g_hInstance = hInstance;
	//設計視窗類
	WNDCLASSEX wndCls = {0};
	wndCls.cbClsExtra = 0;
	wndCls.cbSize = sizeof(WNDCLASSEX);
	wndCls.cbWndExtra = 0;
	wndCls.hbrBackground = (HBRUSH)COLOR_WINDOW;
	wndCls.hCursor = NULL;
	wndCls.hIcon = NULL;
	wndCls.hIconSm = NULL;
	wndCls.hInstance = hInstance;
	wndCls.lpfnWndProc = WndPro;
	wndCls.lpszClassName = szClassName;
	wndCls.lpszMenuName = NULL;
	wndCls.style = CS_VREDRAW | CS_HREDRAW;
	//註冊視窗類
	if (!RegisterClassEx(&wndCls))
	{
		MessageBox(NULL,_T("註冊視窗類失敗!"),_T("提示"),MB_OK);
		return 1;
	}
	//建立視窗
	HWND hWnd = CreateWindowEx(0,szClassName,szWindowName,WS_OVERLAPPEDWINDOW,10,10,800,600,NULL,NULL,hInstance,NULL);
	if (NULL == hWnd)
	{
		MessageBox(NULL,_T("建立視窗失敗!"),_T("提示"),MB_OK);
		return 1;
	}
	//顯示和更新視窗
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//訊息迴圈
	MSG msg;
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

void OnCreate(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
	//建立選單
	HMENU hMain = CreateMenu();
	HMENU hDialog = CreatePopupMenu();
	AppendMenu(hDialog,MF_STRING,ID_MODELDLG,_T("模式對話方塊"));
	AppendMenu(hDialog,MF_STRING,ID_DIALOG,_T("非模式對話方塊"));
	AppendMenu(hDialog,MF_SEPARATOR,0,NULL);
	AppendMenu(hDialog,MF_STRING,ID_QUIT,_T("退出"));
	AppendMenu(hMain,MF_POPUP,(UINT)hDialog,_T("對話方塊"));

	SetMenu(hWnd,hMain);
}

void OnBtnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
	switch(LOWORD(wParam))
	{
	case IDOK:
		/*
		//關閉模式對話方塊
		if(!EndDialog(hWnd,2))
		{
			MessageBox(NULL,_T("關閉對話方塊失敗!"),_T("提示"),MB_OK);
			return;
		}*/		
		if(!DestroyWindow(hWnd))	//關閉非模式對話方塊
		{
			MessageBox(NULL,_T("關閉非模式對話方塊失敗!"),_T("提示"),MB_OK);
			return;
		}
		break;
	case IDCANCEL:
		/*
		//關閉模式對話方塊
		if(!EndDialog(hWnd,3))
		{
			MessageBox(NULL,_T("關閉對話方塊失敗!"),_T("提示"),MB_OK);
			return;
		}*/
		if(!DestroyWindow(hWnd))	//關閉非模式對話方塊
		{
			MessageBox(NULL,_T("關閉非模式對話方塊失敗!"),_T("提示"),MB_OK);
			return;
		}
		break;
	}
}

BOOL CALLBACK MyDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_SYSCOMMAND:
		if (SC_CLOSE == wParam)
		{
			/*
			//關閉對話方塊,模式對話方塊用EndDialog函式
			if(!EndDialog(hwndDlg,1))
			{
				MessageBox(NULL,_T("關閉對話方塊失敗!"),_T("提示"),MB_OK);
				return 1;
			}*/
			if(!DestroyWindow(hwndDlg))//非模式對話方塊關閉,呼叫DestroyWindow函式
			{
				MessageBox(NULL,_T("關閉非模式對話方塊失敗!"),_T("提示"),MB_OK);
				return 1;
			}
		}
		break;
	case WM_INITDIALOG:
		MessageBox(NULL,_T("對話方塊建立完成,顯示之前呼叫"),_T("提示"),MB_OK);
		break;
	case WM_COMMAND:		//按鈕傳送的是WM_COMMAND訊息
		OnBtnCommand(hwndDlg,wParam,lParam);
	}
	return FALSE;
}

void OnModelDlg(HWND hWnd)
{
	//建立對話方塊,通過EndDialog的第二個引數作為返回值,判斷點選了對話方塊中的控制元件
	int ret = DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DLG),hWnd,MyDialogProc);
	if (1 == ret)
	{
		MessageBox(NULL,_T("您點選了關閉對話方塊"),_T("提示"),MB_OK);
	}
	if (2 == ret)
	{
		MessageBox(NULL,_T("您點選了確定按鈕關閉"),_T("提示"),MB_OK);
	}
	if (3 == ret)
	{
		MessageBox(NULL,_T("您點選了取消按鈕關閉"),_T("提示"),MB_OK);
	}
}

void OnDlg(HWND hWnd)
{
	HWND hDialog = CreateDialog(g_hInstance,MAKEINTRESOURCE(IDD_DLG),hWnd,MyDialogProc);
	if (NULL == hDialog)
	{
		MessageBox(NULL,_T("建立非模式對話方塊失敗!"),_T("提示"),MB_OK);
		return;
	}
	ShowWindow(hDialog,SW_SHOW);
}

void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
	DWORD id = LOWORD(wParam); //WM_COMMAND訊息附加項wParam的低位元組表示選單項的ID,高位元組HIWORD為0
	switch (id)
	{
	case ID_MODELDLG:
//		OnModelDlg(hWnd);	//模式對話方塊
		break;
	case ID_DIALOG:
		OnDlg(hWnd);		//非模式對話方塊
		break;
	case ID_QUIT:
		if (IDYES == MessageBox(NULL,_T("確定要退出?"),_T("提示"),MB_YESNO))
		{
			PostQuitMessage(0);
		}
		break;
	}
}

LRESULT CALLBACK WndPro(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_COMMAND:
		OnCommand(hWnd,wParam,lParam);
		break;
	case WM_CREATE:
		OnCreate(hWnd,wParam,lParam);
		break;
	case WM_SYSCOMMAND:
		if (SC_CLOSE == wParam)
		{
			if (IDYES == MessageBox(NULL,_T("確定要退出?"),_T("提示"),MB_YESNO))
			{
				PostQuitMessage(0);
			}
			else
				return 1;
		}
		break;
	}
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}