alpha49 2023-03-17 23:06 采纳率: 61.1%
浏览 111
已结题

请问C语言如何实现多个窗口的嵌套?

我在学习C语言win窗口编程的时候,写了如下基础的程序:
#include "windows.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    WNDCLASS wc_1;
    WNDCLASS wc_2;

    static TCHAR* NAME_1 = TEXT("one");
    static TCHAR* NAME_2 = TEXT("two");

    HWND hwnd_1 = NULL;
    HWND hwnd_2 = NULL;

    MSG msg_1;
    MSG mag_2;

    wc_1.style = CS_HREDRAW | CS_VREDRAW; //窗口样式
    wc_1.lpfnWndProc = WndProc; //过程函数
    wc_1.cbClsExtra = 0; //扩展字段
    wc_1.cbWndExtra = 0; //扩展字段
    wc_1.hInstance = hInstance; //当前实例句柄
    wc_1.hIcon = LoadIcon(hInstance, IDI_APPLICATION); //设置程序图标
    wc_1.hCursor = LoadCursor(NULL, IDC_ARROW); //设置鼠标
    wc_1.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wc_1.lpszMenuName = NULL;
    wc_1.lpszClassName = NAME_1;

    RegisterClass(&wc_1);
    RegisterClass(&wc_2);

    hwnd_1 = CreateWindow(NAME_1, //要注册的窗口类名
                        TEXT("The first window"),//窗口标题
                        WS_OVERLAPPEDWINDOW, //窗口样式
                        CW_USEDEFAULT, //窗口距离屏幕左上角都横坐标
                        CW_USEDEFAULT, //窗口距离屏幕左上角都纵坐标
                        400, //窗口宽度
                        300, //窗口高度
                        NULL, //父窗口句柄
                        NULL, //菜单句柄
                        hInstance, //当前实例句柄
                        NULL); //指向一个值的指针,该值传递给窗口 WM_CREATE消息。一般为NULL
                        
    ShowWindow(hwnd_1, iCmdShow);

    UpdateWindow(hwnd_1);

    while (GetMessage(&msg_1, NULL, 0, 0)) {
        TranslateMessage(&msg_1);
        DispatchMessage(&msg_1);
    }

    return msg_1.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

这样只能得到一个黑黢黢的窗口,没有什么用途。为了学习我下载了一款定时打铃的简易软件,用vs的spy++工具发现这个程序可以在一个窗口内嵌套另一些别的窗口:

img

img

img

img

在大窗口内存在很多小窗口,它们有的窗口类是一样的,但句柄都是不一样的,这样有很多窗口就可以让这个程序更加美观,功能更齐全,使用起来更方便。
请问使用C语言如何才可以实现这种窗口的嵌套,并实现多功能美观的应用程序?感谢!
  • 写回答

5条回答 默认 最新

  • 「已注销」 2023-03-17 23:52
    关注

    参考GPT和自己的思路:实现窗口嵌套需要在窗口过程函数中处理WM_CREATE消息,以创建子窗口,并在父窗口的WM_SIZE消息中调整子窗口的大小和位置。以下是一个简单的示例代码,可以创建两个嵌套的窗口。

    #include <windows.h>
    
    LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
        WNDCLASS wc;
        HWND hwndParent, hwndChild;
        MSG msg;
    
        // 注册父窗口类
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = ParentWndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName = NULL;
        wc.lpszClassName = TEXT("ParentWndClass");
        RegisterClass(&wc);
    
        // 注册子窗口类
        wc.lpfnWndProc = ChildWndProc;
        wc.lpszClassName = TEXT("ChildWndClass");
        RegisterClass(&wc);
    
        // 创建父窗口
        hwndParent = CreateWindow(TEXT("ParentWndClass"), TEXT("Parent Window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL);
    
        // 创建子窗口
        hwndChild = CreateWindow(TEXT("ChildWndClass"), TEXT("Child Window"), WS_CHILD | WS_VISIBLE, 50, 50, 200, 150, hwndParent, NULL, hInstance, NULL);
    
        ShowWindow(hwndParent, iCmdShow);
        UpdateWindow(hwndParent);
    
        // 消息循环
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return (int)msg.wParam;
    }
    
    LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        switch (msg) {
            case WM_CREATE:
                // 创建子窗口
                CreateWindow(TEXT("ChildWndClass"), TEXT("Child Window"), WS_CHILD | WS_VISIBLE, 50, 50, 200, 150, hwnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
                break;
    
            case WM_SIZE:
                // 调整子窗口的大小和位置
                MoveWindow(GetDlgItem(hwnd, 1), 50, 50, LOWORD(lParam) - 100, HIWORD(lParam) - 100, TRUE);
                break;
    
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
    
            default:
                return DefWindowProc(hwnd, msg, wParam, lParam);
        }
    
        return 0;
    }
    
    LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        switch (msg) {
            case WM_CREATE:
                break;
    
            case WM_PAINT:
                {
                    PAINTSTRUCT ps;
                    HDC hdc = BeginPaint(hwnd, &ps);
                    TextOut(hdc, 10, 10, TEXT("Hello from child window!"), 25);
    EndPaint(hwnd, &ps);
    }
    break;
    case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    return 0;
    }
    LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static HWND child_hwnd = NULL;
    switch (msg) {
        case WM_CREATE:
            {
                WNDCLASS wc = { 0 };
    
                wc.style = CS_HREDRAW | CS_VREDRAW;
                wc.lpfnWndProc = ChildWndProc;
                wc.hInstance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
                wc.lpszClassName = TEXT("Child");
    
                RegisterClass(&wc);
    
                child_hwnd = CreateWindow(TEXT("Child"), TEXT("Child Window"),
                    WS_CHILD | WS_VISIBLE, 50, 50, 200, 200,
                    hwnd, NULL, wc.hInstance, NULL);
            }
            break;
    
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hwnd, &ps);
                TextOut(hdc, 10, 10, TEXT("Hello from parent window!"), 27);
                EndPaint(hwnd, &ps);
            }
            break;
    
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    return 0;
    }
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    static TCHAR szAppName[] = TEXT("Parent");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = ParentWndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    
    if (!RegisterClass(&wndclass)) {
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
        return 0;
    }
    
    hwnd = CreateWindow(szAppName, TEXT("The Hello Program"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    return msg.wParam;
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 3月26日
  • 已采纳回答 3月18日
  • 创建了问题 3月17日

悬赏问题

  • ¥50 关于#html5#的问题:H5页面用户手机返回的时候跳转到指定页面例如(语言-javascript)
  • ¥15 无法使用此凭据登录,因为你的域不可用,如何解决?(标签-Windows)
  • ¥15 yolov9的训练时间
  • ¥15 二叉树遍历没有报错但无法正常运行
  • ¥15 在linux系统下vscode运行robocup3d上场球员报错
  • ¥15 Python语言实验
  • ¥15 SAP HANA SQL 增加合计行
  • ¥20 用C#语言解决一个英文打字练习器,有偿
  • ¥15 srs-sip外部服务 webrtc支持H265格式
  • ¥15 在使用abaqus软件中,继承到assembly里的surfaces怎么使用python批量调动