【问题标题】:Change the color of the title bar (caption) of a win32 application更改 win32 应用程序标题栏(标题)的颜色
【发布时间】:2016-09-01 02:31:59
【问题描述】:

我想更改应用程序中标题栏的颜色,就像我在 Skype Preview 等程序中看到的那样。我发现互联网上只提供了一个解决方案(WM_NCPAINT),这似乎需要我绘制一个完全自定义的标题栏,当我只想更改背景颜色时,这当然不理想。有人知道更好的解决方案吗?有人建议挂钩 GetSysColor,但从未使用索引 2 (COLOR_ACTIVECAPTION) 调用它,因此颜色是从其他地方检索的。

当前标题栏:


(来源:pbrd.co

最终目标:

【问题讨论】:

  • @KenWhite:回答一下
  • 查找 Windows 桌面管理器 API。文档有一些自定义绘制标题栏的示例。
  • 很有可能,Skype 确实渲染了整个非客户区。如果您仔细观察,右上角的按钮间距与您的标准应用程序略有不同(Minimize 按钮向左移动了一个像素)。
  • Skype Preview 不是 UWP 应用吗? UWP 不绘制自己的标题栏吗?如果 UWP 允许您使用深色主题,那么我可以假设它也会绘制深色标题栏...
  • @Cheersandhth.-Alf 这些 API 是否已针对 Windows 10 标题栏进行了更新? Windows 7 不允许你有一个“黑暗”的标题栏,因为这个概念没有意义,而且我认为 Windows 8 的情况也没有改变......(我不明白为什么 Windows API 设计者似乎试图阻止为较新版本的 Windows 自定义绘制标题栏...)

标签: c++ winapi


【解决方案1】:

我要说的第一件事是:你被警告了! 这是一项非常费力的任务。阅读 Wine 源代码(本机 win32 功能的 linux 实现)花了很多时间来轻松阅读。

看到这个问题让我想起了我为达到相同结果所做的努力的“喜欢”(读作:令人恼火!)。这个过程有点复杂,并且比简单地绘制标题栏给你带来了更多的责任。 (我已经包含了大约 500 行代码)

除其他外,您还需要处理窗口激活/停用、大小调整、NC 区域按钮、应用程序图标和标题文本。

使用我未包含的其他文件中的一些(绘图)实用程序功能,实现了以下目标:

这两个都是对这个对话框的修改:

借助这些(颜色键控)图像: 和一些拉伸/绘图(图像分为 9 块)

我在重新查看此代码时注意到,客户区过度绘制了边框。我想,因为我没有正确调整它以响应 WM_NCCALCSIZE 消息。我还使用了另一个确实有 8 像素宽边框的图像,而不是这两个显示的 14 像素。 (您可以看到响应我提到的消息的注释掉的代码)

首先,我们将标准对话框的 WindowProc 子类化。在这个子类处理程序中,我们告诉桌面窗口管理器禁用窗口的合成,我们设置一个分层窗口(这就是黑色的半透明窗口),最后,我们自己进行非客户端绘图以响应WM_NCPAINT 消息。

我还要指出,由于我早已忘记的原因,我对代码的功能并不是特别满意。

话虽如此,这里有一些代码可以让你深入了解:

#define _WIN32_WINNT 0x0501
#define UNICODE 1
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
#include "../graphics/graphics.h"
#include <dwmapi.h>
using namespace Gdiplus;

HINSTANCE hInst;
LRESULT CALLBACK DlgSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
LRESULT onNcPaint(HWND hwnd, WPARAM wParam, LPARAM lParam);

HBITMAP frameImg, frameRedImg, frameOrigImg;
int frameIndex = 0;


//HRESULT DwmEnableComposition(UINT uCompositionAction);

typedef HRESULT (WINAPI *pFnDwmEnableComposition)(UINT uCompAction);
typedef HRESULT (WINAPI *pFnDwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);

#define WM_DMWNCRENDERINGCHANGED 0x31F
// wParam = 1 (fRenderingEnabled = true)
// wParam = 0 (fRenderingEnabled = false)


HRESULT EnableNcDwm(HWND hwnd, bool enable)
{
    HMODULE dwmMod = LoadLibrary(L"dwmapi.dll");
    if (dwmMod)
    {
        pFnDwmSetWindowAttribute DwmSetWindowAttribute;
        DwmSetWindowAttribute = (pFnDwmSetWindowAttribute)GetProcAddress(dwmMod, "DwmSetWindowAttribute");

       HRESULT hr = S_OK;
       DWMNCRENDERINGPOLICY ncrp;
       if (enable)
            ncrp = DWMNCRP_ENABLED;
       else
            ncrp = DWMNCRP_DISABLED;

       // Disable non-client area rendering on the window.
       hr = DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp));
       FreeLibrary(dwmMod);
       if (SUCCEEDED(hr))
       {
          return hr;
       }
   }
   return S_FALSE;
}

/*
#define DWM_EC_DISABLECOMPOSITION 0
#define DWM_EC_ENABLECOMPOSITION 1
HRESULT EnableDWM(HWND hwnd, bool enable)
{
    HMODULE dwmMod = LoadLibrary(L"dwmapi.dll");
    pFnDwmEnableComposition DwmEnableComposition;
    DwmEnableComposition = (pFnDwmEnableComposition)GetProcAddress(dwmMod, "DwmEnableComposition");
    HRESULT hr = S_OK;
    // Disable DWM Composition
    if (enable)
        hr = DwmEnableComposition(DWM_EC_ENABLECOMPOSITION);
    else
        hr = DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);
    FreeLibrary(dwmMod);
   return hr;
}
*/

BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static bool isSubclassed = false;
    switch(uMsg)
    {
        case WM_DMWNCRENDERINGCHANGED:
        {
            long dwEx = GetWindowLong(hwndDlg, GWL_EXSTYLE);
            dwEx &= ~(WS_EX_LAYERED);
            SetWindowLong(hwndDlg, GWL_EXSTYLE, dwEx);
            InvalidateRect(hwndDlg, NULL, true);
            UpdateWindow(hwndDlg);
            MoveAnchorsImmediatelly(hwndDlg);
        }
        return 0;

   //     case WM_ERASEBKGND:
   //         {
   //             RECT rc;
   //             GetClientRect(hwndDlg, &rc);
   //             FillRect((HDC)wParam, &rc, (HBRUSH) COLOR_BACKGROUND);
   //             return 1;
   //         }

        case WM_INITDIALOG:
        {
            mSetAnchorMode(GetDlgItem(hwndDlg, IDC_BUTTON1), ANCHOR_CENTER);
        }
        return TRUE;

        case WM_SIZE:
        {
            //MoveAnchorsImmediatelly(hwndDlg);
            DeferAnchorsMove(hwndDlg);
        }
        return TRUE;

        case WM_CLOSE:
        {
            EndDialog(hwndDlg, 0);
        }
        return TRUE;

        case WM_COMMAND:
        {
            switch(LOWORD(wParam))
            {
            case IDC_BUTTON1:
                if (isSubclassed == false)
                {
                    SetWindowSubclass( hwndDlg, DlgSubclassProc, 1, NULL);
                    EnableNcDwm(hwndDlg, false);
                    frameIndex++;
                    frameIndex &= 1;        // make sure it can only be in range [0..1]
                }
                else
                {
                    RemoveWindowSubclass( hwndDlg, DlgSubclassProc, 1);
                    EnableNcDwm(hwndDlg, true);
                }
                isSubclassed = !isSubclassed;


             //   InvalidateRect(hwndDlg, NULL, true);
             //   UpdateWindow(hwndDlg);
             //   MoveAnchorsImmediatelly(hwndDlg);
                break;
            }
        }
        return TRUE;
    }

    return FALSE;
}

LRESULT CALLBACK DlgSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    static byte alpha = 255;
    switch (uMsg)
    {
        case WM_ENTERSIZEMOVE:
            printf("WM_ENTERSIZEMOVE\n");
            return 0;
            break;
        case WM_EXITSIZEMOVE:
            printf("WM_EXITSIZEMOVE\n");
            return 0;
            break;

        case WM_MOUSEWHEEL:
            if (((SHORT)(HIWORD(wParam))) > 0)
            {
                if (alpha > 30)
                    alpha -= 5;
            }
            else if (alpha < 255)
                alpha += 5;
            SetLayeredWindowAttributes(hwnd, RGB(255,0,255), alpha, LWA_COLORKEY|LWA_ALPHA);
            UpdateWindow(hwnd);
            return 0;

        case WM_DMWNCRENDERINGCHANGED:
            {
               // printf("WM_DMWNCRENDERINGCHANGED\n");
                long dwEx = GetWindowLong(hwnd, GWL_EXSTYLE);
                dwEx |= WS_EX_LAYERED;
                SetWindowLong(hwnd, GWL_EXSTYLE, dwEx);
                SetLayeredWindowAttributes(hwnd, RGB(255,0,255), alpha, LWA_COLORKEY|LWA_ALPHA);
                //MoveAnchorsImmediatelly(hwnd);
                DeferAnchorsMove(hwnd);
                InvalidateRect(hwnd, NULL, true);
                UpdateWindow(hwnd);
//                showWndRect(hwnd);
                return 0;
            }
            break;

        case WM_NCACTIVATE:
        case WM_NCPAINT:
          //  printf("WM_NCPAINT -");
          //  printf("wParam: 0x%08d lParam 0x%08x\n", wParam, lParam);
            onNcPaint(hwnd, wParam, lParam);
            return 0;

        case WM_NCCALCSIZE:
            {
                RECT *rc = (RECT*)lParam;
                rc->left += 8;             // frame image margin widths
                rc->top += 30;
                rc->right -= 8;
                rc->bottom -= 8;

//                rc->left += 14;             // frame image margin widths
//               rc->top += 39;
//                rc->right -= 14;
//                rc->bottom -= 14;
            }
            return (WVR_HREDRAW | WVR_VREDRAW);

        case WM_NCHITTEST:
            {
                POINT mousePos, rawMousePos;
                RECT clientRect, windowRect;

                mousePos.x = LOWORD(lParam);
                mousePos.y = HIWORD(lParam);
                rawMousePos = mousePos;

                GetClientRect(hwnd, &clientRect);
                GetWindowRect(hwnd, &windowRect);
                ScreenToClient(hwnd, &mousePos);

                if ((mousePos.x < clientRect.left) && (rawMousePos.y < windowRect.top+8))
                    return HTTOPLEFT;

                if ((mousePos.x > clientRect.right) && (rawMousePos.y < windowRect.top+8))
                    return HTTOPRIGHT;

                if ( (mousePos.x < clientRect.left) && (mousePos.y > clientRect.bottom))
                    return HTBOTTOMLEFT;

                if ( (mousePos.x > clientRect.right) && (mousePos.y > clientRect.bottom))
                    return HTBOTTOMRIGHT;

                if (rawMousePos.x < windowRect.left+11)
                    return HTLEFT;

                if (rawMousePos.x > windowRect.right-11)
                    return HTRIGHT;

                if (mousePos.y  > clientRect.bottom)
                    return HTBOTTOM;

                RECT closeRect;
                SetRect(&closeRect, windowRect.left + 15, windowRect.top+7, windowRect.left+15+16, windowRect.top+25);
                if (PtInRect(&closeRect, rawMousePos))
                {
//                    printf("over sys menu (appIcon) - %d,%d\n", mousePos.x, mousePos.y);
                    return HTSYSMENU;
                }

                if (rawMousePos.y < windowRect.top+8)
                    return HTTOP;

                if (mousePos.y < 0)
                    return HTCAPTION;
                else
                    return HTCLIENT;
            }

    }
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
//    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

LRESULT onNcPaint(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    // draw Frame
//     HBRUSH mBrush = CreateSolidBrush( RGB(0,113,201) );
    HDC hdc = GetWindowDC(hwnd);
//     HDC hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW);//|DCX_INTERSECTRGN);

    RECT mRect, wndRect;
    GetWindowRect(hwnd, &mRect);
    wndRect = mRect;
    mRect.right -= mRect.left;
    mRect.bottom -= mRect.top;
    mRect.left = 0;
    mRect.top = 0;

    HDC memDC = CreateCompatibleDC(hdc);
    HBITMAP old, memBmp;
    old = (HBITMAP)GetCurrentObject(memDC, OBJ_BITMAP);

    memBmp = CreateCompatibleBitmap(hdc, mRect.right, mRect.bottom);
    //memBmp = zCreateDibSection(hdc, mRect.right, mRect.bottom, 24);

    SelectObject(memDC, memBmp);


    //StretchNineDraw(HDC destDC, RECT destRect, HBITMAP srcImage, RECT srcRect,
    //    int marginLeft, int marginTop, int marginRight, int marginBottom, int alpha);

    if (frameIndex == 0)
//        StretchNineDraw(memDC, mRect, frameImg, (RECT){0,0,33,58}, 16,41,16,16, 255);
        StretchNineDrawNoAlpha(memDC, mRect, frameImg, (RECT){0,0,33,58}, 16,41,16,16);
    else
        StretchNineDraw(memDC, mRect, frameRedImg, (RECT){0,0,33,58}, 16,41,16,16, 255);
//        StretchNineDrawNoAlpha(memDC, mRect, frameRedImg, (RECT){0,0,33,58}, 16,41,16,16);
    //    StretchNineDrawNoAlpha(memDC, mRect, frameOrigImg, (RECT){0,0,17,39}, 8,30,8,8);
    //1111drawImgNineSquareStretching(memDC, mRect, frameImg, (RECT){0,0,33,58}, 16,41,16,16);

//void StretchNineDrawNoAlpha(HDC destDC, RECT destRect, HBITMAP srcImage, RECT srcRect,
//                   int marginLeft, int marginTop, int marginRight, int marginBottom)



    // draw icon
    HICON smallIcon = LoadIcon (NULL, IDI_APPLICATION);
    DrawIconEx(memDC, 15, 9, smallIcon, 16, 16, 0,0, DI_NORMAL  );

    // draw window text
    wchar_t wndText[100];
    RECT textRect;
    textRect.left = 9 + 16 + 9;
    textRect.top = 0;
    textRect.right = 1000;
    textRect.bottom = 32;
    GetWindowText(hwnd, wndText, 99);
    //int oldMode = SetBkMode(hdc, TRANSPARENT);
    //int oldMode = SetBkMode(memDC, TRANSPARENT);
    SetBkMode(memDC, TRANSPARENT);

    HFONT oldFont, hfont0 = CreateFont(-13, 0, 0, 0, 0, FALSE, FALSE, FALSE, 1, 0, 0, 0, 0, (L"Ms Shell Dlg"));
    oldFont = (HFONT)SelectObject(memDC, hfont0);
    DrawText(memDC, wndText, -1, &textRect, DT_VCENTER|DT_SINGLELINE|DT_LEFT);
    SelectObject(memDC, oldFont);
    DeleteObject(hfont0);


    // top slice
    BitBlt(hdc, 0,0, mRect.right,41, memDC, 0,0, SRCCOPY);

    // left edge
    BitBlt(hdc, 0, mRect.top + 41, 16, mRect.bottom - (41+16),
           memDC, 0, mRect.top + 41, SRCCOPY);

    // right edge
    BitBlt(hdc, mRect.right-16, mRect.top + 41, 16, mRect.bottom - (41+16),
           memDC, mRect.right-16, mRect.top + 41, SRCCOPY);

    // bottom slice
    BitBlt(hdc, 0,mRect.bottom-16, mRect.right,16, memDC, 0,mRect.bottom-16, SRCCOPY);


 //   BitBlt(hdc, 0,0, mRect.right,mRect.bottom, memDC, 0,0, SRCCOPY);

    ReleaseDC(hwnd, hdc);
    SelectObject(memDC, old);
    DeleteDC(memDC);
    DeleteObject(memBmp);
 //   ValidateRgn(hwnd, (HRGN)wParam);
    return 0;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR           gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    frameImg = mLoadImageFile(L"frame.png");
    frameRedImg = mLoadImageFile(L"frameRed.png");
    frameOrigImg = mLoadImageFile(L"frameOrig.png");

    hInst=hInstance;
    InitCommonControls();
    int result = DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);

    GdiplusShutdown(gdiplusToken);
    return result;
}

在下面找到以下功能: - 加载 png 文件(使用 GDI+) - 将此图像拉伸到边框上

/* BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF */
HBITMAP mLoadImageFile(wchar_t *filename)
{
    HBITMAP result = NULL;
    Bitmap bitmap(filename, false);
    bitmap.GetHBITMAP(0, &result);
    return result;
}


void GetRectSize(LPRECT tgt, int *width, int *height)
{
    *width = (tgt->right - tgt->left) + 1;
    *height = (tgt->bottom - tgt->top) + 1;
}

BOOL SetRectSizePos(LPRECT tgt, int xPos, int yPos, int width, int height)
{
    return SetRect(tgt, xPos, yPos, xPos+(width-1), yPos+(height-1));
}

BOOL MoveRect(LPRECT tgt, int newX, int newY)
{
    int width, height;
    GetRectSize(tgt, &width, &height);
    return SetRectSizePos(tgt, newX,newY, width,height);
}

//  ****** marginLeft = 6
//   ....|....|....  *
//  ..tL.|.tM.|.tR.. *
//  ---------------- * marginTop = 3
//  ..mL.|.mM.|.mR..
//  ---------------- * marginBottom = 3
//  ..bL.|.bM.|.bR.. *
//   ....|....|....  *
//            ****** marginRight = 6
void CalcNineRects(LPRECT srcRect, RECT *dest, int marginLeft, int marginTop, int marginRight, int marginBottom)
{
    int srcWidth, srcHeight;
    int leftWidth, midWidth, rightWidth;
    int topHeight, midHeight, botHeight;
    int xOrig, yOrig;

    GetRectSize(srcRect, &srcWidth, &srcHeight);
    xOrig = srcRect->left;
    yOrig = srcRect->top;

    leftWidth = marginLeft;
    midWidth = srcWidth - (marginLeft + marginRight) - 1;
    rightWidth = marginRight;

    topHeight = marginTop;
    midHeight = srcHeight - (marginTop + marginBottom) - 1;
    botHeight = marginBottom;

    SetRectSizePos(&dest[0], xOrig, yOrig, leftWidth, topHeight);
    SetRectSizePos(&dest[1], xOrig+(leftWidth), yOrig, midWidth, topHeight);
    SetRectSizePos(&dest[2], xOrig+(leftWidth+midWidth), yOrig, rightWidth, topHeight);

    SetRectSizePos(&dest[3], xOrig, yOrig+(topHeight), leftWidth, midHeight);
    SetRectSizePos(&dest[4], xOrig+(leftWidth), yOrig+(topHeight), midWidth, midHeight);
    SetRectSizePos(&dest[5], xOrig+(leftWidth+midWidth), yOrig+(topHeight), rightWidth, midHeight);

    SetRectSizePos(&dest[6], xOrig,yOrig+(topHeight+midHeight), leftWidth, botHeight);
    SetRectSizePos(&dest[7], xOrig+(leftWidth), yOrig+(topHeight+midHeight), midWidth, botHeight);
    SetRectSizePos(&dest[8], xOrig+(leftWidth+midWidth), yOrig+(topHeight+midHeight), rightWidth, botHeight);
}

void StretchNineDraw(HDC destDC, RECT destRect, HBITMAP srcImage, RECT srcRect,
                    int marginLeft, int marginTop, int marginRight, int marginBottom,int alpha)
{
    RECT destRectList[9], srcRectList[9];
    int i;
    int curSrcWidth, curSrcHeight, curDestWidth, curDestHeight;
    HDC srcDC;
    HBITMAP oldSrcBmp;

    srcDC = CreateCompatibleDC(destDC);
//    GetCurrentObject(srcDC, OBJ_BITMAP);
    oldSrcBmp = (HBITMAP) SelectObject(srcDC, srcImage);

    BLENDFUNCTION bf = {AC_SRC_OVER,0,alpha,AC_SRC_ALPHA};

    int destHeight, destWidth;
    GetRectSize(&destRect, &destWidth, &destHeight);

    CalcNineRects(&srcRect, srcRectList, marginLeft, marginTop, marginRight, marginBottom);
    CalcNineRects(&destRect, destRectList, marginLeft, marginTop, marginRight, marginBottom);
    // printf("dst rect: %d,%d - %d,%d -- \n", destRect.left, destRect.top, destRect.right,destRect.bottom);
    for (i=0; i<9; i++)
    {
        GetRectSize(&srcRectList[i], &curSrcWidth, &curSrcHeight);
        GetRectSize(&destRectList[i], &curDestWidth, &curDestHeight);

        AlphaBlend( destDC,
                    destRectList[i].left, destRectList[i].top,
                    curDestWidth, curDestHeight,

                    srcDC,
                    srcRectList[i].left, srcRectList[i].top,
                    curSrcWidth, curSrcHeight,

                    bf
                   );
    }
    SelectObject(srcDC, oldSrcBmp);
    DeleteDC(srcDC);
}

最后,将控件锚定到窗口的代码(窗口调整大小时自动重新计算它们的位置)

typedef struct ANCHORPROPERTY
{
    long anchorType;
    RECT rc;
} *pANCHORPROPERTY;

#define ANCHOR_NONE                  0
#define ANCHOR_WIDTH                 1
#define ANCHOR_RIGHT                 2
#define ANCHOR_CENTER_HORZ           3
#define ANCHOR_HEIGHT                4
#define ANCHOR_HEIGHT_WIDTH          5
#define ANCHOR_HEIGHT_RIGHT          6
#define ANCHOR_BOTTOM                7
#define ANCHOR_BOTTOM_WIDTH          8
#define ANCHOR_BOTTOM_RIGHT          9
#define ANCHOR_CENTER_HORZ_BOTTOM    10
#define ANCHOR_CENTER_VERT           11
#define ANCHOR_CENTER_VERT_RIGHT     12
#define ANCHOR_CENTER                13

pANCHORPROPERTY getWndAnchor(HWND hwnd);
bool removeAnchor(HWND hwnd);
bool mSetAnchorMode(HWND hwnd, long anchorMode);
BOOL CALLBACK AnchorEnum(HWND hwnd, LPARAM lParam);
void MoveAnchorsImmediatelly(HWND controlParent);
void DeferAnchorsMove(HWND controlParent);
long getChildCount(HWND controlParent);

pANCHORPROPERTY getWndAnchor(HWND hwnd)
{
    return (pANCHORPROPERTY)GetProp(hwnd, L"anchor");
}

bool removeAnchor(HWND hwnd)
{
    pANCHORPROPERTY pAnchor;
    if (GetProp(hwnd, L"anchor") != NULL)
    {
        pAnchor = (pANCHORPROPERTY)RemoveProp(hwnd, L"anchor");
        delete pAnchor;
    }
    return false;
}

bool mSetAnchorMode(HWND hwnd, long anchorMode)
{
    bool result = false;
    RECT rc, pr;
    POINT p;
    if (IsWindow(hwnd))
    {
        pANCHORPROPERTY pAnchor;
        pAnchor = getWndAnchor(hwnd);
        if (pAnchor == NULL)
        {
            pAnchor = new ANCHORPROPERTY;
            SetProp(hwnd, L"anchor", pAnchor);
        }
        GetWindowRect(hwnd, &rc);
        p.x = rc.left;
        p.y = rc.top;
        ScreenToClient( GetParent(hwnd), &p);
        GetClientRect( GetParent(hwnd), &pr);
    //    printf("pos: %d,%d\n", p.x, p.y);
        pAnchor->anchorType = mmin( mmax(anchorMode, ANCHOR_NONE), ANCHOR_CENTER);
        pAnchor->rc.left = p.x;
        pAnchor->rc.top = p.y;
        pAnchor->rc.right = pr.right - (rc.right-rc.left + p.x);
        pAnchor->rc.bottom = pr.bottom - (rc.bottom - rc.top + p.y);
        result = true;
    }
    return result;
}

BOOL CALLBACK AnchorEnum(HWND hwnd, LPARAM lParam)
{
    RECT pr, rc;
    long x,y,xW,yH;
    pANCHORPROPERTY pAnchor;
    pAnchor = (pANCHORPROPERTY)GetProp(hwnd, L"anchor");
    if (pAnchor != NULL)
    {
        if (pAnchor->anchorType != ANCHOR_NONE)
        {
       //     printf("child enumerated - %d\n", pAnchor->anchorType);
            RECT client, wnd;
            GetClientRect(hwnd, &client);
            GetWindowRect(hwnd, &wnd);
       //     printf("WndRect: %d x %d", (wnd.right-wnd.left) + 1, (wnd.bottom-wnd.top)+1);
       //     printf("client: %d x %d", client.right-client.left+1, client.bottom-client.top+1 );

            int wW, wH, cW,cH;
            wW = (wnd.right-wnd.left) + 1;
            wH = (wnd.bottom-wnd.top) + 1;
            cW = (client.right-client.left) + 1;
            cH = (client.bottom-client.top) + 1;

            GetClientRect(hwnd, &rc);
            GetClientRect(GetParent(hwnd), &pr);
            switch (pAnchor->anchorType)
            {
            case ANCHOR_WIDTH:
                 x = pAnchor->rc.left;
                 y = pAnchor->rc.top;
                 xW = mmax(pr.right - pAnchor->rc.left - pAnchor->rc.right, 0);
                 yH = rc.bottom;
                 break;

             case ANCHOR_RIGHT:               // = 2
                  x  = (pr.right - rc.right - pAnchor->rc.right) - (wW-cW);
                  y  = pAnchor->rc.top;
                  xW = rc.right +  (wW-cW);
                  yH = rc.bottom + (wH-cH);
               //   printf("xPos, yPos: %d, %d - Size: %d x %d\n", x,y,xW,yH);
                  break;

             case ANCHOR_CENTER_HORZ:         // = 3
                  x  = (pr.right - rc.right) / 2;
                  y  = pAnchor->rc.top;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;

             case ANCHOR_HEIGHT:              // = 4
                  x  = pAnchor->rc.left;
                  y  = pAnchor->rc.top;
                  xW = rc.right;
                  yH = mmax(pr.bottom - pAnchor->rc.top - pAnchor->rc.bottom, 0);
                  break;

             case ANCHOR_HEIGHT_WIDTH:        // = 5
                  x = pAnchor->rc.left;
                  y = pAnchor->rc.top;
                  xW = mmax(pr.right - pAnchor->rc.left - pAnchor->rc.right, 0);
                  yH = mmax(pr.bottom - pAnchor->rc.top - pAnchor->rc.bottom, 0);
                  break;

             case ANCHOR_HEIGHT_RIGHT:        // = 6
                  x  = pr.right - rc.right - pAnchor->rc.right;
                  y  = pAnchor->rc.top;
                  xW = rc.right;
                  yH = mmax(pr.bottom - pAnchor->rc.top - pAnchor->rc.bottom, 0);
                  break;

             case ANCHOR_BOTTOM:              // = 7
                  x  = pAnchor->rc.left;
                  y  = pr.bottom - pAnchor->rc.bottom - rc.bottom;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;

             case ANCHOR_BOTTOM_WIDTH:        // = 8
                  x  = pAnchor->rc.left;
                  y  = pr.bottom - pAnchor->rc.bottom - rc.bottom;
                  xW = mmax(pr.right - pAnchor->rc.left - pAnchor->rc.right, 0);
                  yH = rc.bottom;
                  break;

             case ANCHOR_BOTTOM_RIGHT:        // = 9
                  x  = pr.right - rc.right - pAnchor->rc.right;
                  y  = pr.bottom - pAnchor->rc.bottom - rc.bottom;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;

             case ANCHOR_CENTER_HORZ_BOTTOM:  // = 10
                  x  = (pr.right - rc.right) / 2;
                  y  = pr.bottom - pAnchor->rc.bottom - rc.bottom;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;

             case ANCHOR_CENTER_VERT:         // = 11
                  x  = pAnchor->rc.left;
                  y  = (pr.bottom - rc.bottom) / 2;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;

             case ANCHOR_CENTER_VERT_RIGHT:   // = 12
                  x  = pr.right - rc.right - pAnchor->rc.right;
                  y  = (pr.bottom - rc.bottom) / 2;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;

             case ANCHOR_CENTER:              // = 13
                  x  = (pr.right - rc.right) / 2;
                  y  = (pr.bottom - rc.bottom) / 2;
                  xW = rc.right;
                  yH = rc.bottom;
                  break;
            }
            if (lParam == 0)
                SetWindowPos(hwnd,0, x,y, xW,yH, SWP_NOZORDER|SWP_NOCOPYBITS);
            else
                DeferWindowPos((HDWP)lParam, hwnd, 0, x,y, xW,yH, SWP_NOZORDER|SWP_NOCOPYBITS);
        }
    }
    return true;
}

void MoveAnchorsImmediatelly(HWND controlParent)
{
    EnumChildWindows(controlParent, AnchorEnum, 0);
}

BOOL CALLBACK CountEnum(HWND hwnd, LPARAM lParam)
{
    long *pCount = (long*)lParam;
    ++(*pCount);
    return true;
}

long getChildCount(HWND controlParent)
{
    long curCount = 0;
    EnumChildWindows(controlParent, CountEnum, (LPARAM)&curCount);
  //  printf("Child count: %d\n", curCount);
    return curCount;
}

void DeferAnchorsMove(HWND controlParent)
{
    HDWP deferMoveHandle;
    int childCount = getChildCount(controlParent);
    deferMoveHandle = BeginDeferWindowPos(childCount);
    EnumChildWindows(controlParent, AnchorEnum, (LPARAM)deferMoveHandle);
    EndDeferWindowPos(deferMoveHandle);
}

【讨论】:

  • @MoragHughson - 差不多。我不得不通过将窗口拖出屏幕来触发初始重新绘制,无法循环更改外观以及其他一些缺陷。不幸的是,我目前没有时间重新访问。
【解决方案2】:

您可以尝试创建一个没有框架的窗口;我在这里找到了参考: opening a window that has no title bar with win32

然后在您的应用程序中制作您自己的标题栏,使用您喜欢的颜色(位于窗口顶部,从可见部分开始)。

【讨论】:

    【解决方案3】:

    您可以在 Win32 中使用 DWMAPI 的 DwmSetWindowAttribute 函数更改窗口标题栏颜色/行为。

    注意:可能需要 Windows SDK 10.0.22000.0(又名第一个 Windows 11 SDK),因为 DWMWA_USE_IMMERSIVE_DARK_MODE|DWMWA_BORDER_COLOR|DWMWA_CAPTION_COLOR 未在 Windows SDK 中记录 10.0.19041.0(最新的 Windows 10 SDK)。人们只需将dwAttribute 用作20(如果Windows 早于Windows 10 20H1,则使用19),就可以在变量的公共文档之前使DWMWA_USE_IMMERSIVE_DARK_MODE 工作。 Here is an example of Qt using it in their Windows platform integration by allowing application to use it by passing -platform windows:darkmode=1 flag when launching the application.

    启用沉浸式黑暗模式(在 Windows 10 / 11 中可用,但在 Windows 10 SDK 中未记录(可通过将值设置为 dwAttribute 为 20 来使用),值在 Windows 10 20H1 更新之前为 19)

    #include <dwmapi.h>
    
    BOOL USE_DARK_MODE = true;
    BOOL SET_IMMERSIVE_DARK_MODE_SUCCESS = SUCCEEDED(DwmSetWindowAttribute(
        WINhWnd, DWMWINDOWATTRIBUTE::DWMWA_USE_IMMERSIVE_DARK_MODE,
        &USE_DARK_MODE, sizeof(USE_DARK_MODE)));
    

    更改边框颜色(仅在 Windows 11 SDK 中)

    #include <dwmapi.h>
    
    COLORREF DARK_COLOR = 0x00505050;
    BOOL SET_CAPTION_COLOR = SUCCEEDED(DwmSetWindowAttribute(
        WINhWnd, DWMWINDOWATTRIBUTE::DWMWA_BORDER_COLOR,
        &DARK_COLOR, sizeof(DARK_COLOR)));
    

    更改标题颜色(仅在 Windows 11 SDK 中)

    #include <dwmapi.h>
    
    COLORREF DARK_COLOR = 0x00505050;
    BOOL SET_CAPTION_COLOR = SUCCEEDED(DwmSetWindowAttribute(
        WINhWnd, DWMWINDOWATTRIBUTE::DWMWA_CAPTION_COLOR,
        &DARK_COLOR, sizeof(DARK_COLOR)));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      相关资源
      最近更新 更多