You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SDI应用创建类似VS安装程序样式的无边框CFrameWnd窗口

如何为SDI应用创建类似VS安装程序样式的无边框CFrameWnd窗口

我现在有一个基于MFC的SDI应用,框架类继承自CFrameWnd,还有对应的视图类。我想把应用窗口改成VS安装程序那种样式:无边框、直角、带窗口阴影,同时保留最小化、关闭这类控制按钮。

之前我找到过一篇针对CDialog派生类实现「带阴影的无边框窗口」的方案,但就是没法把代码适配到自己的SDI框架里。我自己尝试了一些修改,目前的做法是在应用类里初始化Gdiplus:

BOOL Application::InitInstance()
{
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);
    CWinApp::InitInstance();

    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR                    gdipToken = 0;
    Gdiplus::GdiplusStartup(&gdipToken, &gdiplusStartupInput, nullptr);
    // ...

然后是框架类的代码:

MainFrame.h

#pragma once

class MainFrame : public CFrameWnd
{
public:
    BOOL PreCreateWindow(CREATESTRUCT& cs) override
    {
        if (!CFrameWnd::PreCreateWindow(cs))
            return FALSE;

        cs.style     = WS_POPUP | WS_CAPTION | DS_CENTER;
        cs.dwExStyle = 0;

        return TRUE;
    }

    void DoDataExchange(CDataExchange* pDX) override
    {
        CFrameWnd::DoDataExchange(pDX);

        if (!m_initialized) {
            MARGINS m { 0, 0, 0, 1 };
            DwmExtendFrameIntoClientArea(m_hWnd, &m);

            SetWindowPos(
                nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
            SetWindowLong(m_hWnd, DWLP_MSGRESULT, 0);
            m_initialized = true;
        }
    }

protected:
    DECLARE_DYNCREATE(MainFrame)
    DECLARE_MESSAGE_MAP()

    void OnPaint()
    {
        PAINTSTRUCT ps { 0 };
        HDC         hdc = ::BeginPaint(m_hWnd, &ps);
        // 用GDI+绘制,确保alpha通道不透明
        Gdiplus::Graphics   gfx { hdc };
        Gdiplus::SolidBrush brush { Gdiplus::Color { 255, 255, 255 } };
        gfx.FillRectangle(&brush,
                          static_cast<INT>(ps.rcPaint.left),
                          static_cast<INT>(ps.rcPaint.top),
                          static_cast<INT>(ps.rcPaint.right - ps.rcPaint.left),
                          static_cast<INT>(ps.rcPaint.bottom - ps.rcPaint.top));

        ::EndPaint(m_hWnd, &ps);
    }

private:
    bool m_initialized = false;
};

MainFrame.cpp

#include "pch.h"
#include "framework.h"
#include "Application.h"
#include "MainFrame.h"

IMPLEMENT_DYNCREATE(MainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()

我把初始化代码放在DoDataExchange里了,因为暂时没找到更合适的地方。但现在的问题是,应用窗口要么干脆不显示,要么就是普通的默认窗口样式——取决于我有没有在cs.style里加WS_POPUP。

后来我更新了样式,改成cs.style = DS_CENTER;,但窗口样式几乎没变化,还是普通的带边框窗口。另外我还想去掉视图的内边框,但这个打算单独提问。

有没有大佬能告诉我,怎么才能做出VS安装程序那种样式的窗口啊?

备注:内容来源于stack exchange,提问作者qloq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 12:09:49