jjzjj

c++ - 更改 win32 应用程序标题栏(标题)的颜色

coder 2023-06-02 原文

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

当前标题栏:


(来源:pbrd.co)

最终目标:

最佳答案

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

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

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

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

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

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

我在重新查看此代码时注意到,客户区过度绘制了边框。我想,因为我没有正确调整它以响应 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+) - 将此图像拉伸(stretch)到边框上

/* 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);
}

关于c++ - 更改 win32 应用程序标题栏(标题)的颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39261826/

有关c++ - 更改 win32 应用程序标题栏(标题)的颜色的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  3. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  4. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  5. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  6. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  7. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  8. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  9. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  10. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

随机推荐