问题
Here is what I'm talking about:program window
I know, this topic was several times published, but I can't find any good solution.
My problem is
1.: -flickering controls showing time and histogram (static, not double bufferred).
2.: -I can't change background of controls (labels, trackbar buddies, histogram bkgnd) from white to LTGRAY_BRUSH.
And here's some code:
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);
}
Adding this code:
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORDLG:
case WM_CTLCOLORBTN:
return (LRESULT)GetStockObject(LTGRAY_BRUSH);
causes that only trackbars are drawn without a frame. I tried to use timers to invalidate and redraw controls but it doesn't help. Now I have no idea how to fix it. Could someone help me, please?
回答1:
Source code using a static control:
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:
Remove the handler for WM_PAINT and call your PaintProcedure() when the timer fires: sample code
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;
}
回答3:
Oh, I was not using winapi since years, so I could forget how gdi works, but I don't understand how could I not get it, you was talking about: remove WM_PAINT - the whole handler, not only the calls I do from it.
Earlier I solved problem with histogram flickering. It is very fast procedure, all algorithms in camera class I wrote and checked in python, so I was sure it should work. And it works. I had to turn off code optimalization.
Your tip solves timer flickering problem and overall interface efficiency. But there is now not solved white background problem. Should I use subclassing to give my controls the color of my choice? I tried on 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 );
but without an effect.
Here is my interface looks like now: https://www.dropbox.com/s/7123ef7wi1sars8/follower2.png
Thank you. :D
来源:https://stackoverflow.com/questions/22567889/background-color-of-a-control-winapi