程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 無模態對話框

無模態對話框

編輯:C++入門知識

現在來看看CreateDialog(),它是DialogBox()的姐妹函數.區別在於DialogBox()擁有自己的消息循環並且直到對話框關閉才返回,CreateDialog()則更加像CreateWindowEx()創建的一個窗口,立即返回並向你的消息循環發送消息,就像是你的主窗口發的消息樣.這就是所謂的無模態,而DialogBox()創建的是模態對話框.
  創建的資源如下:
[cpp] 
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()在窗口銷毀的時候才返回.
[cpp] view plaincopyprint?
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().
  現在我需要為工具欄寫一個對話過程.
[cpp]
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()中這樣寫...
[cpp]

case WM_DESTROY: 
    DestroyWindow(g_hToolbar); 
    PostQuitMessage(0); 
break; 
  還有一點,希望在任何時候顯示或隠藏我們的工具欄,所以我在菜單上加上了兩個命令來做這件事情,並這樣處理:
[cpp] view plaincopyprint?
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()來自己處理它們.
[cpp]
while(GetMessage(&Msg, NULL, 0, 0)) 

    if(!IsDialogMessage(g_hToolbar, &Msg)) 
    { 
        TranslateMessage(&Msg); 
        DispatchMessage(&Msg); 
    } 

  這裡我們首先將消息傳給IsDialogMessage(),如果消息是為工具欄的(由我們傳進的窗口的句柄來指示),系統就作默認的處理並返回TRUE.這種情況下消息已經被處理了所以我們不需要再調用TranslateMessage()或DispatchMessage()了.如果消息是為另外一個窗口就照常處理.
  值得提出來的是IsDialogMessage()也可以用於不是對話框的窗口來給它們一些像對話框的功能.記住,對話框就是一個窗口,並且大多數(如果不是全部的話)對話框的API可以工作於任何窗口.
貼個完整的代碼吧 有點長:
資源文件的建立如上。
[cpp]
#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; 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved