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);
}