首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Win32 開發入門(13):對話框基礎與非模態對話框實作

     編輯:關於C++

對話框與視窗的關係

對話框本質上就是一種視窗(控制項也可視為子視窗)。最簡單的對話框莫過於 MessageBox,但若要自訂介面與互動邏輯,就需要建立對話框資源並撰寫對話框程序。

建立對話框資源

  1. 在「方案總管」的「資源檔案」節點右鍵 →「加入」→「新增項目」加入 .rc 檔,或從「檢視」→「資源檢視」→專案右鍵→「加入」→「資源」。
  2. 選擇「對話框」並按「新增」。
  3. 在屬性視窗設定對話框 ID(例如 IDD_MYDLG)。
  4. 使用工具箱拖放控制項(Static Text、Button 等),並為每個控制項設定唯一 ID(如 IDC_DISP、IDC_BTN)。

資源檢視加入對話框

新增對話框資源

設定對話框 ID

對話框設計介面

非模態對話框的建立與顯示

在主視窗的 WM_CREATE 中呼叫 CreateDialog 建立非模態對話框,父視窗為主視窗:

case WM_CREATE:
    hdlg = CreateDialog(hgapp, MAKEINTRESOURCE(IDD_MYDLG), hwnd, (DLGPROC)DlgProc);
    if (hdlg) ShowWindow(hdlg, SW_NORMAL);
    return 0;

注意:對話框程序 DlgProc 必須先宣告(前置宣告),否則編譯器會找不到。回傳型別為 INT_PTR CALLBACK,切勿 在內部呼叫 DefDlgProc,否則會導致無限遞迴。

處理對話框關閉訊息

使用者點擊標題列關閉鈕會觸發 WM_SYSCOMMAND(wParam == SC_CLOSE),此時應呼叫 DestroyWindow 銷毀對話框:

case WM_SYSCOMMAND:
    if (wParam == SC_CLOSE) {
        DestroyWindow(hdlg); // 會觸發 WM_DESTROY
    }
    return 0;

回應按鈕點擊並更新靜態文字

按鈕點擊產生 WM_COMMAND,LOWORD(wParam) 為控制項 ID。取得靜態文字控制項控制代碼需用 GetDlgItem(hdlg, IDC_DISP),然後以 SetWindowText 更新內容:

case WM_COMMAND:
    if (LOWORD(wParam) == IDC_BTN) {
        nCount++;
        HWND hStatic = GetDlgItem(hdlg, IDC_DISP);
        WCHAR str[MAXCHAR];
        int n = wsprintf(str, L"你點擊了%d次按鈕。", nCount);
        str[n] = L'\0';
        SetWindowText(hStatic, str);
    }
    return 0;

對話框初始畫面

按鈕點擊計數效果

完整程式碼清單

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

LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE hgapp;

int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow) {
    LPCWSTR cn = L"My";
    WNDCLASS wc = { sizeof(WNDCLASS) };
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.hInstance = hThisApp;
    wc.lpfnWndProc = WinMainProc;
    wc.lpszClassName = cn;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wc);
    
    HWND hwnd = CreateWindow(cn, L"主視窗", WS_OVERLAPPEDWINDOW,
                             30, 22, 360, 280, NULL, NULL, hThisApp, NULL);
    if (!hwnd) return 0;
    
    hgapp = hThisApp;
    ShowWindow(hwnd, nShow);
    UpdateWindow(hwnd);
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    HWND hdlg;
    switch (msg) {
        case WM_CREATE:
            hdlg = CreateDialog(hgapp, MAKEINTRESOURCE(IDD_MYDLG), hwnd, (DLGPROC)DlgProc);
            if (hdlg) ShowWindow(hdlg, SW_NORMAL);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
    static int nCount = 0;
    switch (msg) {
        case WM_SYSCOMMAND:
            if (wParam == SC_CLOSE) DestroyWindow(hdlg);
            return 0;
        case WM_COMMAND:
            if (LOWORD(wParam) == IDC_BTN) {
                nCount++;
                HWND hStatic = GetDlgItem(hdlg, IDC_DISP);
                WCHAR str[MAXCHAR];
                int n = wsprintf(str, L"你點擊了%d次按鈕。", nCount);
                str[n] = L'\0';
                SetWindowText(hStatic, str);
            }
            return 0;
    }
    return (INT_PTR)FALSE;
}

重點整理

  • 對話框資源建立流程與屬性設定
  • 非模態對話框:CreateDialog + ShowWindow
  • 對話框程序 不可 呼叫 DefDlgProc
  • 關閉處理:WM_SYSCOMMAND / SC_CLOSE → DestroyWindow
  • 控制項存取:GetDlgItem(hDlg, controlID)
  • 文字更新:SetWindowText / WM_SETTEXT / Static_SetText
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved