【问题标题】:background color of a control (winapi)控件的背景颜色(winapi)
【发布时间】:2014-04-29 08:37:22
【问题描述】:

这就是我要说的:program window

我知道,这个话题已经发布了好几次了,但是我找不到任何好的解决方案。 我的问题是
1.: - 显示时间和直方图的闪烁控件(静态,非双缓冲)。
2.:-我无法将控件的背景(标签、轨迹栏伙伴、直方图 bkgnd)从白色更改为 LTGRAY_BRUSH。
下面是一些代码:

case WM_PAINT:
    PaintProcedure( hdcClock );
    SetBkColor(hdcWindow, RGB(255,220,180));
    TextOut(hdcWindow,260,10,TEXT(" -- CAMERA WINDOW -- "),21); 
    break;

... ...

void PaintProcedure( HDC hdc )
{
    img = cam->getFrame();
    cam->ShowImage(img, hdcCam, 1, 1, img->width, img->height, 0, 0);

    InvalidateRect( hClock, &rClock, 1 );               
    RedrawWindow(hClock,&rClock,0,RDW_UPDATENOW);

    char sTime[256];
    SYSTEMTIME time;
    HFONT hFont;
    SIZE size;
    ...
        ...
    BeginPath (hdc) ;
    SetBkMode( hdc, TRANSPARENT/*OPAQUE*/ );
    TextOut( hdc,1,1,sTime, strlen( sTime ) );
    EndPath (hdc) ;

    SelectObject (hdc, CreateHatchBrush (HS_DIAGCROSS, RGB (0, 0, 255))) ;
    SetBkColor (hdc, RGB (255, 0, 0)) ;
    SetBkMode (hdc, OPAQUE) ;

    StrokeAndFillPath (hdc) ;
    DeleteObject (SelectObject (hdc, GetStockObject (LTGRAY_BRUSH)));
    SelectObject (hdc, GetStockObject (SYSTEM_FONT)) ;
    DeleteObject (hFont) ;

    cam->ShowImage(cam->drawIntensityHistogram(),hdcHistogram,1,1,
        rHistogram.right-rHistogram.left,rHistogram.bottom-rHistogram.top,0,0);


    InvalidateRect( hwnd, &r, 1 );
    RedrawWindow(hwnd,&r,0,RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW);
}

添加此代码:

case WM_CTLCOLORSTATIC:
case WM_CTLCOLORDLG:
case WM_CTLCOLORBTN:
    return (LRESULT)GetStockObject(LTGRAY_BRUSH);

导致仅绘制没有框架的轨迹栏。 我尝试使用计时器来使控件无效并重绘控件,但它没有帮助。 现在我不知道如何解决它。有人可以帮帮我吗?

【问题讨论】:

  • 您的主窗口是对话框,还是您自己创建窗口及其控件? [如果是对话框,大概可以在定时器触发时处理绘图,无需处理WM_PAINT]
  • 窗口和所有控件都是“自制”的。我在 WM_CREATE 消息上创建控件。并且主窗口设置了 CS_OWNDC 标志。案例 WM_CREATE: hdcWindow = GetDC (hwnd) ; hClock = CreateWindowEx(0, "STATIC", NULL, WS_CHILD |WS_BORDER |WS_VISIBLE, 10, 4, 100, 25, hwnd, NULL, hInst, NULL);
  • 我建议删除WM_PAINT 的处理程序并在计时器触发时调用您的PaintProcedure(),从您的PaintProcedure() 中删除对InvalidateRect()RedrawWindow() 的所有调用,并使用您不同的@ 987654332@s 绘制到您的控件
  • 这样它什么都不画:dropbox.com/s/t0thgwhzws0einv/follower1.png

标签: winapi controls background-color flicker


【解决方案1】:

使用静态控件的源代码:

LONG WINAPI WndProc(HWND, UINT, WPARAM,LPARAM);

HWND hWndStatic;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{   HWND hwnd;
    MSG msg;
    WNDCLASS w;

    memset(&w,0,sizeof(WNDCLASS));
    w.style = CS_HREDRAW | CS_VREDRAW;
    w.lpfnWndProc = WndProc;
    w.hInstance = hInstance;
    w.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
    w.lpszClassName = L"My Class";
    w.hCursor = LoadCursor(NULL, IDC_ARROW); 
    RegisterClass(&w);

    hwnd = CreateWindow(L"My Class", L"My title", WS_OVERLAPPEDWINDOW, 300, 200, 800, 600, NULL, NULL, hInstance, NULL);
    hWndStatic = CreateWindowEx(0, L"Static", NULL, WS_CHILD| WS_VISIBLE |SS_LEFT, 10, 130, 200, 20, hwnd, NULL, hInstance, NULL);

    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&msg,NULL,0,0))
    {   TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

UINT_PTR uTimerId;
LOGBRUSH lbrBk;

LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
    switch (Message)
    {   case WM_CREATE:
        {   LRESULT lRes = DefWindowProc(hwnd, Message, wparam, lparam);
            HBRUSH hbr = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
            GetObject(hbr, sizeof(lbrBk), &lbrBk);
            uTimerId = SetTimer(hwnd, 123, 1000, NULL);
            return lRes;
        }

        case WM_CTLCOLORSTATIC:
            if ((HWND)lparam == hWndStatic)
            {   SetBkColor((HDC)wparam, lbrBk.lbColor);
                return (BOOL) GetStockObject(LTGRAY_BRUSH);
            }
            return FALSE;

        case WM_TIMER:
        {   TCHAR szTime[128];
            HDC hdc = GetDC(hwnd);
            _tstrtime_s(szTime, _countof(szTime));
            SetWindowText(hWndStatic, szTime);
            ReleaseDC(hwnd, hdc);
            break;
        }

        case WM_DESTROY: 
            KillTimer(hwnd, uTimerId);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, Message, wparam, lparam);
    }
    return 0;
}

【讨论】:

    【解决方案2】:

    哦,多年来我没有使用 winapi,所以我可能会忘记 gdi 是如何工作的,但我不明白我怎么能不明白,你在说:删除 WM_PAINT - 整个处理程序,而不仅仅是调用我从它做。
    早些时候我解决了直方图闪烁的问题。这是一个非常快速的过程,我在 python 中编写并检查了相机类中的所有算法,所以我确信它应该可以工作。它有效。我不得不关闭代码优化。
    您的提示解决了计时器闪烁问题和整体界面效率。但是现在还没有解决白色背景的问题。我应该使用子类化来为我的控件提供我选择的颜色吗?我试过 WM_CREATE

    hStatic = CreateWindowEx( 0, "STATIC", NULL, WS_CHILD| WS_VISIBLE |SS_LEFT, 10, 130, 200, 20, hwnd, NULL, hInst, NULL );
            SetBkColor(GetDC(hStatic), lbrBk.lbColor);
            SetWindowText( hStatic, buf );
    

    但没有效果。
    这是我现在的界面:https://www.dropbox.com/s/7123ef7wi1sars8/follower2.png
    谢谢。 :D

    【讨论】:

    • 您需要在每个 TextOut() 之前调用 SetBkColor() [不确定是否使用全局 HDC 变量并调用 SetBkColor() om WM_CREATE 也可以]
    • 如你所见 on_create 它不起作用,我会在晚上尝试使用它。
    • 在将 WM_CTLCOLORSTATIC 返回值更改为 (LRESULT)CreateSolidBrush(RGB(0,0,255)) 后,我看到控制背景已正确更改为 LTGRAY(现在为蓝色)。控件上文本的白色背景只是字体背景!
    • 我明白了,没有办法使用系统程序更改文本背景。当 SetWindowText() 发生时,系统使用预定义的颜色简单地进行各种布尔操作。我必须使用控件的子类来获得我想要的。在我准备好之前,我不会将主题设置为已解决。再次感谢您的帮助。任何进一步的评论都很好看:D
    • 我不太确定我是否理解您的要求,但在您的 WM_CTLCOLORSTATIC 处理程序中,您可以根据控件返回画笔,例如:if ((HWND)lParam == hWndClock)
    【解决方案3】:

    删除 WM_PAINT 的处理程序并在计时器触发时调用您的 PaintProcedure():示例代码

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {   HWND hwnd;
        MSG msg;
        WNDCLASS w;
    
        memset(&w,0,sizeof(WNDCLASS));
        w.style = CS_HREDRAW | CS_VREDRAW;
        w.lpfnWndProc = WndProc;
        w.hInstance = hInstance;
        w.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); // WHITE_BRUSH
        w.lpszClassName = L"My Class";
        w.hCursor = LoadCursor(NULL, IDC_ARROW);
        RegisterClass(&w);
        hwnd = CreateWindow(L"My Class", L"My title", WS_OVERLAPPEDWINDOW, 300, 200, 800, 600, NULL, NULL, hInstance, NULL);
        ShowWindow(hwnd,nCmdShow);
        UpdateWindow(hwnd);
    
        while(GetMessage(&msg,NULL,0,0))
        {   TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
    UINT_PTR uTimerId;
    LOGBRUSH lbrBk;
    LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
    {   switch (Message)
        {   case WM_CREATE:
            {   LRESULT lRes = DefWindowProc(hwnd, Message, wparam, lparam); // I don't have any controls in the main window
                HBRUSH hbr = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
                GetObject(hbr, sizeof(lbrBk), &lbrBk); // for use in timer logic
                uTimerId = SetTimer(hwnd, 123, 1000, NULL);
                return lRes;
            }
    
            case WM_TIMER:
            {   TCHAR szTime[128];
                HDC hdc = GetDC(hwnd);
                _tstrtime_s(szTime, _countof(szTime));
                SetBkColor(hdc, lbrBk.lbColor);
                TextOut(hdc, 200, 200, szTime, _tcslen(szTime));
                ReleaseDC(hwnd, hdc);
                break;
            }
    
            case WM_DESTROY: 
                KillTimer(hwnd, uTimerId);
                PostQuitMessage(0);
                break;
    
            default:
                return DefWindowProc(hwnd, Message, wparam, lparam);
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-05-08
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      • 2011-11-22
      • 2013-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多