无模态对话框


  现在来看看CreateDialog(),它是DialogBox()的姐妹函数.区別在于DialogBox()拥有自己的消息循环并且直到对话框关闭才返回,CreateDialog()则更加像CreateWindowEx()创建的一个窗口,立即返回并向你的消息循环发送消息,就像是你的主窗口发的消息样.这就是所谓的无模态,而DialogBox()创建的是模态对话框.

  创建的资源如下:

IDD_TOOLBAR DIALOGEX 0, 0, 98, 52
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "My Dialog Toolbar"
FONT 8, "MS Sans Serif"
BEGIN
    PUSHBUTTON      "&Press This Button",IDC_PRESS,7,7,84,14
    PUSHBUTTON      "&Or This One",IDC_OTHER,7,31,84,14
END

  你可以看到资源编辑器把DIALOG換成了DIALOGEX表明我们要为我们的对话框设置扩展风格.

  接下来想在程序运行的时候创建对话框,想要对话框可视,所以在WM_CREATE的消息处理中创建它.我们也需要声明一个全局变量来保持从CreateDialog()返回的窗口句柄以便在后面使用它.DialogBox()不向我们返回句柄因为DialogBox()在窗口销毀的时候才返回.

    HWND g_hToolbar = NULL;
    case WM_CREATE:
        g_hToolbar = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_TOOLBAR),
            hwnd, ToolDlgProc);
        if(g_hToolbar != NULL)
        {
            ShowWindow(g_hToolbar, SW_SHOW);
        }
        else
        {
            MessageBox(hwnd, "CreateDialog returned NULL", "Warning!",  
                MB_OK | MB_ICONINFORMATION);
        }
    break;

  要检查返回值,这什么时候总是一个好的习惯,如果是正确的(不为NULL)我们就用ShowWindow()来显示这个窗口,要是用DiaglogBox(),这一步就是不必要的,因为系统为我们调用了ShowWindow().

  现在我需要为工具栏写一个对话过程.

BOOL CALLBACK ToolDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDC_PRESS:
                    MessageBox(hwnd, "Hi!", "This is a message", 
                        MB_OK | MB_ICONEXCLAMATION);
                break;
                case IDC_OTHER:
                    MessageBox(hwnd, "Bye!", "This is also a message", 
                        MB_OK | MB_ICONEXCLAMATION);
                break;
            }
        break;
        default:
            return FALSE;
    }
    return TRUE;
}

  大多数适用于DialogBox()的消息处理规则也适用于CreateDialog(),不调用DefWindowProc(),对不处理的消息返回FALSE,处理的返回TRUE.

  有个攺变就是不为无模态窗口调用EndDialog(),可以像对常规的窗口一样调用DestroyWindow().在主窗口的WndProc()中这样写...

    case WM_DESTROY:
        DestroyWindow(g_hToolbar);
        PostQuitMessage(0);
    break;

  还有一点,希望在任何时候显示或隠藏我们的工具栏,所以我在菜单上加上了两个命令来做这件事情,并这样处理:

    case WM_COMMAND:
        switch(LOWORD(wParam))
        {   
            case ID_DIALOG_SHOW:
                ShowWindow(g_hToolbar, SW_SHOW);
            break;
            case ID_DIALOG_HIDE:
                ShowWindow(g_hToolbar, SW_HIDE);
            break;
            //... other command handlers
        }
    break;

  如果在此时运行你的程序并试图在两个按钮间切換的话,就会注意到不行,按Alt+P和Alt+O来激活按钮都不行.为什么? 因为DialogBox()有自己的消息循环并默认地处理这些事件,CreateDialog()卻沒有.但是可以通过在消息循环中调用可以为做默认处理的IsDialogMessage()来自己处理它们.

    while(GetMessage(&Msg, NULL, 0, 0))
    {
        if(!IsDialogMessage(g_hToolbar, &Msg))
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
    }

  这里我们首先将消息传给IsDialogMessage(),如果消息是为工具栏的(由我们传进的窗口的句柄来指示),系统就作默认的处理并返回TRUE.这种情況下消息已经被处理了所以我们不需要再调用TranslateMessage()或DispatchMessage()了.如果消息是为另外一个窗口就照常处理.

  值得提出来的是IsDialogMessage()也可以用于不是对话框的窗口来给它们一些像对话框的功能.记住,对话框就是一个窗口,并且大多数(如果不是全部的话)对话框的API可以工作于任何窗口.

贴个完整的代码吧 有点长:

资源文件的建立如上。

#include <windows.h>
#define IDD_TOOLBAR                     101
#define IDC_OTHER 9003
#define IDC_PRESS   9004
#define ID_DIALOG_SHOW 9005
#define ID_DIALOG_HIDE 9006

HWND g_hToolbar = NULL;
const char g_szClassName[] = "myWindowClass";

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	switch(Message)
	{
	case WM_INITDIALOG:
		return TRUE;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case IDC_PRESS:
			MessageBox(hwnd,"you press a button!","this is message",MB_OK | MB_ICONINFORMATION);
			break;
		case IDC_OTHER:
			MessageBox(hwnd,"you press a other button!","this is message",MB_OK | MB_ICONINFORMATION);
		case IDOK:
			EndDialog(hwnd, IDOK);
			break;
		case IDCANCEL:
			EndDialog(hwnd, IDCANCEL);
			break;
		}
		break;
	default:
		return FALSE;
	}
	return TRUE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_CREATE:
		{
			HMENU hmenu,hSubMenu;
			hmenu = CreateMenu();
			hSubMenu = CreatePopupMenu();
			AppendMenu(hSubMenu,MF_STRING,ID_DIALOG_SHOW,"&Show");
			AppendMenu(hSubMenu,MF_STRING,ID_DIALOG_HIDE,"&Hide");
			AppendMenu(hmenu,MF_STRING | MF_POPUP,(UINT)hSubMenu,"&Dialog");
			SetMenu(hwnd,hmenu);
			g_hToolbar = CreateDialog(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_TOOLBAR),hwnd,AboutDlgProc);
			if(g_hToolbar != NULL)
				ShowWindow(g_hToolbar,SW_HIDE);
			else
				MessageBox(hwnd,"CreateDialog return NULL","Warning",MB_OK | MB_ICONINFORMATION);
		}
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_DIALOG_SHOW:
			ShowWindow(g_hToolbar, SW_SHOW);
			break;
		case ID_DIALOG_HIDE:
			ShowWindow(g_hToolbar, SW_HIDE);
			break;
		}
		break;
	case WM_LBUTTONDOWN:
		{
			char szFileName[MAX_PATH];
			HINSTANCE hInstance = GetModuleHandle(NULL);
			GetModuleFileName(hInstance, szFileName, MAX_PATH);
			MessageBox(hwnd, szFileName, "This program is:", MB_OK | 
				MB_ICONINFORMATION);
		}
		break;
	case WM_CLOSE:
		DestroyWindow(hwnd);
		break;
	case WM_DESTROY:
		DestroyWindow(g_hToolbar);
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd;
	MSG Msg;
	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = g_szClassName;
	wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Window Registration Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
	hwnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		g_szClassName,
		"The title of my window",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
		NULL, NULL, hInstance, NULL);
	if(hwnd == NULL)
	{
		MessageBox(NULL, "Window Creation Failed!", "Error!",
			MB_ICONEXCLAMATION | MB_OK);
		return 0;
	}
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
		if(!IsDialogMessage(g_hToolbar,&Msg))
		{
			TranslateMessage(&Msg);
			DispatchMessage(&Msg);
		}
	}
	return Msg.wParam;
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iot-genius

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值