Reputation: 119
I am currently building a ProgressBar in WinApi I want the caption "Loading" to appear on it.
I managed to create a label that would have a transparent background but I can not make the caption to be higher than the ProgressBar window.
This is my code:
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
static HWND hwndPrgBar;
static HWND lable;
static int i = 1;
HDC hdcStatic = NULL;
INITCOMMONCONTROLSEX InitCtrlEx;
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCtrlEx.dwICC = ICC_PROGRESS_CLASS;
InitCommonControlsEx(&InitCtrlEx);
switch (msg)
{
case WM_CREATE:
CenterWindow(hwnd);
/* creating the progress bar */
hwndPrgBar = CreateWindowEx(0, PROGRESS_CLASS, NULL,
WS_CHILD | WS_VISIBLE | PBS_SMOOTH | PBS_MARQUEE, // pbs_smooth makes no difference when manifest sets new windows styles
0, 0, 350, 25, hwnd, NULL, g_hinst, NULL);
/* sets progress bar looks */
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(hwndPrgBar));
SendMessage(hwndPrgBar, (UINT)PBM_SETBKCOLOR, 0, RGB(224, 224, 224));
SendMessage(hwndPrgBar, (UINT)PBM_SETBARCOLOR, 0, (LPARAM)RGB(131, 203, 123));
SendMessage(hwndPrgBar, (UINT)PBM_SETMARQUEE, (WPARAM)TRUE, (LPARAM)5);
/* create the lable as child of prgress bar */
lable = CreateWindowEx(WS_EX_TRANSPARENT, L"STATIC", L"", WS_CHILD | WS_VISIBLE | SS_LEFT | WS_SYSMENU, 140, 5, 100, 100, hwnd, (HMENU)(100), (HINSTANCE)GetWindowLong(hwndPrgBar, GWL_HINSTANCE), NULL);
/* sets lable text to Loading */
SendMessage(lable, WM_SETTEXT, NULL, (LPARAM)L"Loading");
SetWindowPos(lable, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
/* I have tried this lines -> it didn't worked
SetForegroundWindow(lable);
BringWindowToTop(lable);
SetActiveWindow(lable);
SwitchToThisWindow(lable, TRUE);
SetWindowPos(lable, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
*/
/* set progress bar components */
SendMessage(hwndPrgBar, PBM_SETRANGE, 0, MAKELPARAM(0, 150));
SendMessage(hwndPrgBar, PBM_SETSTEP, 1, 0);
/* start prorgess bar */
i = 1;
SendMessage(hwndPrgBar, PBM_SETPOS, 0, 0);
SetTimer(hwnd, ID_TIMER, 100, NULL);
break;
case WM_TIMER:
SendMessage(hwndPrgBar, PBM_STEPIT, 0, 0);
i++;
if (i == 150)
{
KillTimer(hwnd, ID_TIMER);
exit(0);
}
break;
case WM_COMMAND:
break;
case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);
PostQuitMessage(0);
break;
case WM_CTLCOLORSTATIC:
/* makes the lable transperent*/
hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(0, 0, 0));
SetBkMode(hdcStatic, TRANSPARENT);
return (LRESULT)GetStockObject(NULL_BRUSH);
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
How can I make a label on one side have a transparent background and on the other hand it will be above the progress bar?
Upvotes: 2
Views: 171
Reputation: 31599
Handling WM_CTLCOLORSTATIC
will work, but you have to invalidate label
each time the progress bar changes the background:
case WM_TIMER:
SendMessage(hwndPrgBar, PBM_STEPIT, 0, 0);
InvalidateRect(lable, NULL, FALSE);
...
Or using subclass instead (remove the static control):
LRESULT CALLBACK PrgBarProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
UINT_PTR, DWORD_PTR)
{
switch(msg) {
case WM_PAINT:
{
LRESULT lres = DefSubclassProc(hwnd, msg, wp, lp);
HDC hdc = GetDC(hwnd);
RECT rc;
GetClientRect(hwnd, &rc);
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, L"Text", -1, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
ReleaseDC(hwnd, hdc);
return lres;
}
case WM_NCDESTROY:
RemoveWindowSubclass(hwnd, SubclassProc, 0);
return DefSubclassProc(hwnd, msg, wp, lp);
}
return DefSubclassProc(hwnd, msg, wp, lp);
}
...
SetWindowSubclass(hwndPrgBar, PrgBarProc, 0, 0);
PBS_MARQUEE
forces the bar to go back and forth. You don't want that here. And it won't work unless visual styles are enabled through the manifest file, or the following lines in Visual Studio:
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
Upvotes: 2