如何发光最小。最大和关闭按钮?

2024-04-13

我按照以下指南使用 DWM API 创建自定义 Aero 框架。

My work:

void CMainFrame::OnActivate(UINT nState,CWnd* pWndOther,BOOL bMinimized )
{
    CFrameWnd::OnActivate(nState,pWndOther,bMinimized);
    BOOL fDwmEnabled = FALSE;
    if (SUCCEEDED(DwmIsCompositionEnabled(&fDwmEnabled)))
    {
        if(nState == WA_ACTIVE )
        {
            MARGINS margins ={-1};
            HRESULT hr = DwmExtendFrameIntoClientArea(m_hWnd, &margins);
            if (!SUCCEEDED(hr));
        }
    }
}

void CMainFrame::OnNcPaint(){
    RECT rcClient;
    GetWindowRect(&rcClient);
    // Inform the application of the frame change.
    SetWindowPos( 
             NULL, 
             rcClient.left, rcClient.top,
             RECTWIDTH(rcClient), RECTHEIGHT(rcClient),
             SWP_FRAMECHANGED);
    CFrameWnd::OnNcPaint();
    CDC* dc = GetWindowDC();
    dc->FillSolidRect(0,0,RECTWIDTH(rcClient),RECTHEIGHT(rcClient),RGB(0,0,0));
}

 LRESULT CMainFrame::OnNcHitTest(CPoint p)
 {
    LRESULT r ;
    r = CFrameWnd::OnNcHitTest( p);      
    if(r == HTMINBUTTON || r == HTMAXBUTTON || r == HTCLOSE)
        return r;
    else
        r = HitTestNCA(m_hWnd,p); // this function is direct copied from above link.
     return r;
 }

Result:

我发现当我将鼠标移动到这些按钮上时,最小、最大和关闭按钮不会发光。

一般情况:

如何解决这个问题?

此致,


DwmDefWindowProc需要处理标题按钮。从

对于标题按钮点击测试,DWM 提供了DwmDefWindowProc功能。正确点击测试自定义框架中的标题按钮 场景中,消息首先应该传递到DwmDefWindowProc为了 处理。DwmDefWindowProc回报TRUE如果消息被处理并且FALSE如果不是。如果该消息未被处理DwmDefWindowProc, 您的应用程序应该自行处理消息或传递消息 到DefWindowProc.

在MFC中可以这样计算:

LRESULT cframeWnd::OnNcHitTest(CPoint p)
{
    BOOL dwm_enabled = FALSE;
    if (SUCCEEDED(DwmIsCompositionEnabled(&dwm_enabled)))
    {
        LRESULT result = 0;
        if (!DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(p.x, p.y), &result))
            result = HitTestNCA(m_hWnd, p);

        if (result == HTNOWHERE && GetForegroundWindow() != this)
        {
            return HTCAPTION;
        }

        return result;
    }

    return CWnd::OnNcHitTest(p);
}

我添加了一个修复GetForegroundWindow(),因为HitTestNCAMSDN 示例中的函数是错误的,它不返回HTCLIENT当它应该的时候。因此,当另一个窗口获得焦点时,在客户区单击鼠标时,它不会切换窗口。

另外,还有漏水现象OnNcPaint:

CDC* dc = GetWindowDC();

每当GetWindowDC()被称为它应该跟随ReleaseDC。或者只是使用CWindowDC它具有自动清理功能。你实际上不需要覆盖OnNcPaint因为框架已经扩展到“客户区”。

这是一个完整的示例:

class cglassWnd : public CWnd
{
    void    OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS FAR*);
    LRESULT OnNcHitTest(CPoint p);
    void    OnNcMouseLeave();
    int     OnCreate(LPCREATESTRUCT lpCreateStruct);
    void    OnActivate(UINT state, CWnd* otherWnd, BOOL minimized);
    void    OnPaint();
    CRect   borders;
    int     titlebar_height;
    DECLARE_MESSAGE_MAP()
public:
    cglassWnd();
};

BEGIN_MESSAGE_MAP(cglassWnd, CWnd)
    ON_WM_NCHITTEST()
    ON_WM_NCCALCSIZE()
    ON_WM_NCMOUSELEAVE()
    ON_WM_ACTIVATE()
    ON_WM_CREATE()
    ON_WM_PAINT()
END_MESSAGE_MAP()

cglassWnd::cglassWnd()
{
    BOOL dwm_enabled = FALSE;
    DwmIsCompositionEnabled(&dwm_enabled);
    if (!dwm_enabled)
        TRACE("Error: don't use this class, add error handling...");

    //modified height for the new title bar
    titlebar_height = 60;
}

int cglassWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    int res = CWnd::OnCreate(lpCreateStruct);

    //find border thickness
    borders = { 0,0,0,0 };
    if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_THICKFRAME)
    {
        AdjustWindowRectEx(&borders,
            GetWindowLongPtr(m_hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
        borders.left = abs(borders.left);
        borders.top = abs(borders.top);
    }
    else if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & WS_BORDER)
    {
        borders = { 1,1,1,1 };
    }

    //Extend caption in to client area
    MARGINS margins = { 0 };
    margins.cyTopHeight = titlebar_height;
    DwmExtendFrameIntoClientArea(m_hWnd, &margins);

    SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

    return res;
}

void cglassWnd::OnPaint()
{
    CPaintDC dc(this);

    //paint titlebar area (this used to be the non-client area)
    CRect rc;
    GetClientRect(&rc);
    rc.bottom = titlebar_height;

    //see MSDN reference for explanation of this code
    //upside-down bitmap is for the sake of DrawThemeTextEx
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    BITMAPINFOHEADER infhdr = { sizeof(infhdr), rc.right, -rc.bottom, 1, 32 };
    HBITMAP hbitmap = CreateDIBSection(dc,(BITMAPINFO*)(&infhdr),DIB_RGB_COLORS,0,0,0);
    auto oldbitmap = memdc.SelectObject(hbitmap);

    //do extra titlebar painting here
    //for example put DrawThemeTextEx for window's name

    dc.BitBlt(0, 0, rc.Width(), rc.Height(), &memdc, 0, 0, SRCCOPY);
    memdc.SelectObject(oldbitmap);
    DeleteObject(hbitmap);

    //begin normal paint
    //The new client area begins below titlebar_height which we define earlier
    GetClientRect(&rc);
    rc.top = titlebar_height;
    dc.FillSolidRect(&rc, RGB(128, 128, 255));
}

void cglassWnd::OnNcCalcSize(BOOL validate, NCCALCSIZE_PARAMS FAR* sz)
{
    if (validate)
    {
        sz->rgrc[0].left += borders.left;
        sz->rgrc[0].right -= borders.right;
        sz->rgrc[0].bottom -= borders.bottom;
    }
    else
    {
        CWnd::OnNcCalcSize(validate, sz);
    }
}

LRESULT cglassWnd::OnNcHitTest(CPoint pt)
{
    LRESULT result = 0;
    //handle close/minimize/maximize button
    if (DwmDefWindowProc(m_hWnd, WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y), &result))
        return result;

    //cursor is over the frame or client area:
    result = CWnd::OnNcHitTest(pt);
    if (result == HTCLIENT)
    {
        ScreenToClient(&pt);
        if (pt.y < borders.top) return HTTOP;
        if (pt.y < titlebar_height) return HTCAPTION;
    }
    return result;
}

void cglassWnd::OnNcMouseLeave()
{
    //This is for close/minimize/maximize/help buttons
    LRESULT result;
    DwmDefWindowProc(m_hWnd, WM_NCMOUSELEAVE, 0, 0, &result);
    CWnd::OnNcMouseLeave();
}

void cglassWnd::OnActivate(UINT state, CWnd* otherWnd, BOOL minimized)
{
    CWnd::OnActivate(state, otherWnd, minimized);
    Invalidate(FALSE);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何发光最小。最大和关闭按钮? 的相关文章

随机推荐

  • 在 Swift 中从字符串中提取浮点数

    我可以使用下面的代码提取数字 let weightt x components separatedBy CharacterSet decimalDigits inverted joined separator 例如 我从字符串 0 1kg
  • Eclipse JPA 项目更改事件处理程序(等待)

    每当我尝试构建项目时 为什么会收到 JPA 项目更改事件处理程序 正在等待 我的工作区中有一些 JPA 项目 需要花费很多时间来构建我的项目 它还会导致 GC 超出限制 分配给 eclipse 的堆空间为 6GB 我目前正在使用开普勒 He
  • Jenkins 管道在条件内验证特定格式的文件是否存在

    我需要验证特定目录中是否存在 doc 格式的文件 根据该条件何时执行 即 当在具有 doc 扩展名的目录中找到文件时 它应该继续执行步骤 下面的代码无法找到 doc格式的文件 when expression return fileExist
  • 复选框列表

    我有两个域类 class Contract String number static hasMany statements Statement class Statement String code static hasMany contr
  • qgraph可以在实际边缘之外渲染边缘标签吗?

    为了便于阅读 我正在尝试在 qgraph 中的实际边缘之外插入边缘标签 我特别不喜欢在标签下方添加白色背景的选项 它会弄乱边缘 根据手册 只能沿线调整边缘标签位置 而不能在侧面调整 以前有人为此苦苦挣扎吗 是否可以规避这个问题 干杯 似乎没
  • 更改 GKE 上的 kubernetes 主环境变量

    我想在 GKE 上使用我的 Kubernetes 集群启用 Stackdriver 日志记录 这里有说明 https kubernetes io docs user guide logging stackdriver https kuber
  • PLS-00394: fetch 语句的 INTO 列表中的值数量错误

    这是我在存储过程中创建游标的尝试 Second Stored Procedure CREATE OR REPLACE PROCEDURE sp GetDiscountedRate DiscountCode IN VARCHAR2 Perce
  • 如何在Vue.js中添加一堆全局过滤器?

    我想在 Vue js 应用程序中使用一些全局过滤器 我知道我需要在主 Vue 实例之前定义它们 但从代码组织的角度来看 将它们全部放在 main js 文件中对我来说似乎并不正确 我怎样才能将定义放在一个单独的文件中 导入到 main js
  • GitHub API v3:确定用户是否是组织的所有者

    很容易确定用户是否是团队成员如果你知道id http developer github com v3 orgs teams get team member GET teams id members user 但如何才能轻松确定每个组织都拥有
  • Perl 字符串是不可变的吗?

    当我对字符串进行串联时 幕后发生了什么 my short short short cake Perl 是否有效地创建一个新字符串 然后为其分配正确的变量引用 或者 Perl 字符串本质上总是可变的 这个问题的动机来自我与一位同事的讨论 他说
  • 模板构造函数优先于普通复制和移动构造函数?

    以下程序的输出 include
  • 如何检查 VBA DAO 记录集中是否为空?

    我在数据库中有一个可选字段 我正在使用 DAO 记录集提取该字段 在将字段与其他字段连接之前 我需要检查该字段是否已设置 到目前为止 我已经尝试过以下代码片段Is and 这是明显错误的语法 Is 无济于事 看来如果我使用 它不会正确地与N
  • 添加资源文件到VC6 dll

    我有许多 VC 6 0 项目 DSP 它们构建到没有资源文件的 dll 中 知道如何将资源添加到现有项目中吗 该项目很快就会发布一个主要版本 我想为那些目前缺少的 dll 添加一个文件版本 dll 将在发布之前重新编译 因此我只是尝试使这些
  • Active Directory 是否支持事务?

    简单的问题 但我在任何地方都找不到答案 Active Directory 是否支持事务 换句话说 以下更改是否会回滚 因为我没有调用scope Complete using var scope new TransactionScope Di
  • 是否可以定义一个符合协议的Class类型的属性?

    例如 我有MyFancyData协议 如何指定 MyFancyDataClass 属性仅接受符合此协议的类 interface MyObject NSObject property Class MyFancyDataClass proper
  • 头文件中的内存分配

    我工作的公司有针对嵌入式目标的 C 开发的开发规则 一是 建议不要在头文件中分配任何存储空间 我不确定这意味着什么 写它的人不在身边 其他开发人员也不在乎 所以我在这里问 我的理解是 我不应该在头文件中声明变量 因此在 h 中不鼓励类似的操
  • 使用 caseInSensitive 在 Firebase 中保存和/或查询用户显示名称?

    我正在将我的项目从 Swift 转移到 Firebase Firebase 用户没有用户名 但我允许他们保存显示名称 该名称更像是属性而不是实际对象 如何让用户在敏感文本中使用大小写来查询其他用户 朋友 您可以轻松完成此任务 我们不知道您当
  • 如何缓存 sbt TaskKey 的结果?

    我有一项昂贵的任务需要在测试中参考 lazy val exampleSources TaskKey Seq File exampleSources for use in tests exampleSources updateClassifi
  • 空指针与悬挂指针

    空指针和悬空指针之间有有意义的区别吗 看起来这两个术语都用于表示不指向任何内容的指针 是一个悬空指针的想法used引用某些东西 但现在没有 其中空指针只是一个不引用任何东西的指针 无论它过去指向什么 指针术语 悬空 或野 指针 指向某处的指
  • 如何发光最小。最大和关闭按钮?

    我按照以下指南使用 DWM API 创建自定义 Aero 框架 My work void CMainFrame OnActivate UINT nState CWnd pWndOther BOOL bMinimized CFrameWnd