Winapi 每10毫秒更改标签颜色的优化方法

Winapi 每10毫秒更改标签颜色的优化方法,winapi,visual-c++,Winapi,Visual C++,我想在每10毫秒触发一次事件时更改一组标签(8 X 8)的背景色,我正在使用一个线程CreateThread(NULL,0,colorLabel,NULL,0,0)每10毫秒调用一次 DWORD WINAPI colorLabel(LPVOID lpParameter) { for (int i = 0; i < 8; i++){ for (int j = 0; j < 8; j++){ if (hBrushLabel) {

我想在每10毫秒触发一次事件时更改一组标签(8 X 8)的背景色,我正在使用一个线程
CreateThread(NULL,0,colorLabel,NULL,0,0)每10毫秒调用一次

DWORD WINAPI colorLabel(LPVOID lpParameter) {
    for (int i = 0; i < 8; i++){
        for (int j = 0; j < 8; j++){
            if (hBrushLabel) {
                DeleteObject(hBrushLabel);
                hBrushLabel = NULL;
            }
            clrLabelBkGnd = RGB((i * 4) % 255, (j * 4) % 255, 0x00);
            InvalidateRect(hWndLabel[i][j], NULL, TRUE);
        }
    }
    colored = 1;
    return 0;
}
DWORD WINAPI彩色标签(LPVOID lpParameter){
对于(int i=0;i<8;i++){
对于(int j=0;j<8;j++){
如果(hBrushLabel){
DeleteObject(hBrushLabel);
hBrushLabel=NULL;
}
clrLabelBkGnd=RGB((i*4)%255,(j*4)%255,0x00);
无效(hwdlabel[i][j],NULL,TRUE);
}
}
有色=1;
返回0;
}
回调程序:

case WM_CTLCOLORSTATIC:
         hdc = reinterpret_cast<HDC>(wParam);
        SetTextColor(hdc, clrLabelText);
        SetBkColor(hdc, clrLabelBkGnd);
        if (!hBrushLabel) hBrushLabel = CreateSolidBrush(clrLabelBkGnd);
        return reinterpret_cast<LRESULT>(hBrushLabel);
case WM\u CTLCOLORSTATIC:
hdc=重新解释铸件(wParam);
SetTextColor(hdc、clrLabelText);
SetBkColor(hdc、clrLabelBkGnd);
如果(!hBrushLabel)hBrushLabel=CreateSolidBrush(clrLabelBkGnd);
返回重新解释(hBrushLabel);
但是这种方法太重,显示器被破坏了

是否有任何优化方法可以每10毫秒更改标签颜色显示编辑:许多旧计算机可能无法使用此方法处理10毫秒的延迟。最小30毫秒延迟更好,或者更高一点。此外,这不是游戏,而是非游戏程序中的轻量级动画

编辑2:更改了调用
GetDC
的方式

另一个选项是绘制一个矩形和文本,然后
睡眠
10毫秒。实际绘制可能需要几毫秒,在这种情况下,使用
QueryPerformanceCounter
睡眠时间少于10毫秒。请注意,除非在
WM_PAINT
中也执行了某些操作,否则不会保存这些更改

DWORD WINAPI foo(LPVOID p)
{
    HWND hwnd = (HWND)p;
    LARGE_INTEGER frequency, clock1, clock2;
    QueryPerformanceFrequency(&frequency);
    wchar_t buf[100];
    for (int i = 0; i < 100; i++)
    {
        QueryPerformanceCounter(&clock1);
        HDC hdc = GetDC(hwnd);//release hdc as soon as possible
        wsprintf(buf, L"%i\n", i);
        RECT rc = {0,0,50,20};
        COLORREF bkcolor = RGB(128, 255, 255);
        HBRUSH brush = CreateSolidBrush(bkcolor);
        SetBkColor(hdc, bkcolor);
        FillRect(hdc, &rc, brush);
        DeleteObject(brush); 
        TextOut(hdc, rc.left, rc.top, buf, lstrlen(buf));
        ReleaseDC(hwnd, hdc);

        QueryPerformanceCounter(&clock2);
        int delay = int(((clock2.QuadPart - clock1.QuadPart) * 1000) / frequency.QuadPart);
        if (delay < 10)
            Sleep(10 - delay); //10 millisecond delay
    }
    return 123;
}    
...
CreateThread(NULL, 0, foo, hwnd, 0, NULL);
DWORD-WINAPI-foo(lpp)
{
HWND HWND=(HWND)p;
大整数频率,时钟1,时钟2;
QueryPerformanceFrequency(&frequency);
wchar_t buf[100];
对于(int i=0;i<100;i++)
{
QueryPerformanceCounter(&clock1);
HDC HDC=GetDC(hwnd);//尽快释放HDC
wsprintf(buf,L“%i\n”,i);
RECT rc={0,0,50,20};
COLORREF bkcolor=RGB(128、255、255);
HBRUSH笔刷=CreateSolidBrush(bkcolor);
SetBkColor(hdc,bkcolor);
FillRect(hdc和rc、笔刷);
删除对象(画笔);
TextOut(hdc、rc.left、rc.top、buf、lstrlen(buf));
释放DC(hwnd、hdc);
QueryPerformanceCounter(&clock2);
整数延迟=整数((时钟2.QuadPart-时钟1.QuadPart)*1000)/频率.QuadPart);
如果(延迟<10)
睡眠(10-延迟);//10毫秒延迟
}
返回123;
}    
...
CreateThread(NULL,0,foo,hwnd,0,NULL);

提前创建笔刷(在
WM\u Create
中,甚至在
main()
中)。使用
WM\u TIMER
切换从
WM\u CTLCOLORSTATIC
返回的画笔。这没有什么意义。也许你想用
WM_-paint
绘制矩形和文本;我不确定这些标签将用于什么目的,所以我想建议,如果我最初说的没有帮助,线程肯定不会有帮助,特别是考虑到OP中的代码,这是错误的(它违反了windows的线程关联规则)。窗口子系统没有优化为每秒渲染100帧。您可能需要研究一种更直接的操作屏幕内容的方法,例如,或。您可以声明一个大的HBRUSH对象数组,每次创建笔刷时,将其句柄指定给数组中的下一个位置。保留一个创建的笔刷数量计数器,当它达到一定数量时,立即删除阵列中的所有笔刷。这样,您就不必每次在循环中调用
DeleteObject()
。如果画笔的数量不是太多,则可以在程序结束时删除画笔。当从线程(而不是所属线程)更新窗口的内容时,结果是未定义的。不要那样做。您对
睡眠
的假设也不成立:您建议
睡眠
将在指定的数量之后正好过期。事实并非如此。线程可以安排在以后运行(明显)。或更早,如果参数小于系统时钟分辨率。10毫秒可能已经低于支持的最小值。@IInspectable第一点很明显,我已经提到,
WM_PAINT
将自行处理,还有其他问题可以解决。我不明白你说的“不要这样做”。我编辑了答案,试图解决您提出的第二点。您正在从一个线程调用
GetDC
,该线程不是窗口的所有者,然后对其进行渲染。这超出了规范:您只能从创建窗口的线程修改窗口(及其拥有的资源)。不管怎样,
基于睡眠的动画通常是急促和令人不快的。常见的解决方案是尽可能快地渲染,并基于当前时间戳渲染内容。我也不明白你的编辑是如何处理我提到的第二点的。该线程仍处于不可预知的休眠状态。@IInspectable非消息线程可以使用
GetDC
,只要它没有被其他线程使用<代码>睡眠
并非完全不可预测。我在15年前的单核笔记本电脑上测试了上述代码,它运行良好。当流氓线程在使用设备上下文时,您建议如何防止拥有线程使用设备上下文?您的代码当然没有实现任何类型的协调,而且由于您可能正在处理标准控件,因此您不能进入并更改它,以实现任何类型的编排。至于使用旧的单核机器进行烟雾测试:这些机器通常比当前的多核设备表现出更多的可预测性。