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

Win32 開發入門(14):以對話框作為主視窗

     編輯:關於C++

前言

在前幾篇文章中,我們建立 Win32 應用程式的標準流程是:設計視窗類別、註冊視窗類別、建立視窗。然而,當開始使用控制項時,會發現直接在視窗上排版控制項相當麻煩。相反地,資源編輯器中的對話框提供了圖形化設計介面,配置控制項輕鬆許多。因此,許多開發者萌生了一個想法:能不能直接把對話框當作主視窗使用?

這個概念在網路上已有高手實作(甚至有用 Win32 組合語言完成的),改寫成 C++ 更是輕而易舉。本文將介紹兩種主要做法。

方法一:以桌面視窗為父視窗直接建立對話框

這是最直接的方式,步驟如下:

  1. 建立對話框資源:在資源編輯器中設計介面,盡情發揮排版創意。
  2. 建立圖示資源:該圖示同時作為應用程式圖示(VS 編譯時會自動採用資源中第一個圖示)與對話框標題列圖示。
  3. 程式碼中建立並顯示對話框:使用 CreateDialog,父視窗指定為 GetDesktopWindow()。

完整程式碼範例

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

// 啟用視覺樣式 (Common Controls 6.0)
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE hgInst;

int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow) {
    hgInst = hThisApp;
    
    // 建立對話框,父視窗為桌面視窗
    HWND hdlg = CreateDialog(hThisApp, MAKEINTRESOURCE(IDD_MY), 
                             GetDesktopWindow(), (DLGPROC)DlgProc);
    if (!hdlg) return 0;
    
    ShowWindow(hdlg, SW_SHOW);
    
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

INT_PTR CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_INITDIALOG:
            // 設定對話框圖示
            SendMessage(hDlg, WM_SETICON, ICON_SMALL, 
                        (LPARAM)LoadIcon(hgInst, MAKEINTRESOURCE(IDI_APP)));
            return 0;
            
        case WM_SYSCOMMAND:
            if (wParam == SC_CLOSE) {
                PostQuitMessage(0); // 退出訊息迴圈
            }
            return 0;
    }
    return (INT_PTR)FALSE;
}

對話框主視窗執行畫面

方法二:建立一般視窗,再將 Form View 對話框作為子視窗嵌入

此法保留傳統「設計視窗類別→註冊→建立視窗」流程,差別在於 WM_CREATE 時建立一個 Form View 風格的對話框並將其貼在主視窗上。

步驟說明

  1. 在資源編輯器中新增對話框時,選擇 IDD_FORMVIEW 範本,產生的對話框無標題列、無邊框,適合當作子視窗嵌入。
  2. 在該對話框上自由配置控制項。
  3. 在主視窗的 WM_CREATE 處理函式中,呼叫 CreateDialog 建立對話框,父視窗傳入主視窗 hwnd,並以 SW_SHOWNA 顯示(不啟動視窗)。

關鍵程式碼片段

case WM_CREATE: {
    // 建立 Form View 對話框,父視窗為 hwnd
    HWND hdlg = CreateDialog(hgAppInst, MAKEINTRESOURCE(IDD_MYFORM), 
                             hwnd, (DLGPROC)DlgProc);
    // 顯示但不啟動
    ShowWindow(hdlg, SW_SHOWNA);
} return 0;

選擇 IDD_FORMVIEW 範本

無標題列、無邊框的 Form View 對話框

在 Form View 上配置控制項

嵌入 Form View 後的執行結果

完整程式碼清單(方法二)

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

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

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

int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow) {
    // 設計視窗類別
    WNDCLASS wc = { };
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpfnWndProc = (WNDPROC)WindowProc;
    wc.lpszClassName = L"supper_man";
    wc.hInstance = hThisApp;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wc);
    
    hgAppInst = hThisApp;
    
    // 建立主視窗
    HWND hwnd = CreateWindow(L"supper_man", L"超級應用", 
                             WS_OVERLAPPEDWINDOW, 40, 25, 380, 300, 
                             NULL, NULL, hThisApp, NULL);
    if (!hwnd) return 0;
    
    ShowWindow(hwnd, nShow);
    UpdateWindow(hwnd);
    
    // 訊息迴圈
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            HWND hdlg = CreateDialog(hgAppInst, MAKEINTRESOURCE(IDD_MYFORM), 
                                     hwnd, (DLGPROC)DlgProc);
            ShowWindow(hdlg, SW_SHOWNA);
        } 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) {
    /* 處理對話框內控制項的訊息 */
    return (INT_PTR)FALSE;
}

小結

  • 方法一 適合簡單工具型程式,程式碼極精簡,對話框本身就是最上層視窗。
  • 方法二 適合需要保留標準視窗框架(標題列、選單、最小化/最大化按鈕)且想善用資源編輯器排版控制項的情境。
  • 兩種做法都需啟用 Common Controls 6.0 以獲得現代視覺風格。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved