How can I make hover on a static window? - c++

Currently only WM_MOUSEMOVE works. The image changes, but WM_MOUSELEAVE doesn't work anymore.
I want to make a hover effect on the button. What am I doing wrong?
[...]
hWndButton= CreateWindowW(L"Static", NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP |
SS_NOTIFY, 10, 25, 109, 30, hwnd, (HMENU)4, NULL, NULL);
[...]
bool TheButtonToggle = false;
[...]
case WM_MOUSEMOVE:
if (TheButtonToggle == false) {
TRACKMOUSEEVENT tm_Event;
tm_Event.cbSize = sizeof(TRACKMOUSEEVENT);
tm_Event.dwFlags = TME_LEAVE;
tm_Event.hwndTrack = GetDlgItem((HWND)dwRefData, IDB_BUTTON);
TrackMouseEvent(&tm_Event);
TheButtonToggle = true;
HBITMAP hbmpButtonHover = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_HOVER_BUTTON));
SendMessage(hWndButton, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmpButtonHover);
}
break;
case WM_MOUSELEAVE:
{
HBITMAP hbmpButton = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_BUTTON));
SendMessage(hWndButton, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmpButton);
TheButtonToggle = false;
break;
}

A workaround:
You can subclass a button to monitor mouse move, if mouse move on the button, WM_MOUSEMOVE message in the subclass callback function will be triggered.
hWndButton = CreateWindowW(L"Static", NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP |
SS_NOTIFY, 10, 25, 109, 30, hWnd, (HMENU)IDC_BUTTON, NULL, NULL);
SetWindowSubclass(hWndButton, &OwnerDrawButtonProc, IDC_BUTTON, 0);
[...]
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
{
HBITMAP hbmpButton = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
SendMessage(hWndButton, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmpButton);
}
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &OwnerDrawButtonProc, 1);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Debug:

Related

How to create a button when another button is pressed and hide the other one

(Questions are at the bottom)
I am trying to write a program, which has one button. If this button is pressed, it should create a new button, and delete the other one, you will see here:
constexpr unsigned int button1=111;
constexpr unsigned int button2=112;
bool buttonIsPressed = false;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static RECT rect;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
{
GetClientRect(hWnd, &rect);
CreateWindowEx(NULL,
L"BUTTON",
L"create new button",
WS_TABSTOP | WS_VISIBLE |
WS_CHILD | BS_DEFPUSHBUTTON,
/*windowWidth-15,*/
400,
rect.bottom - 40,
100,
28,
hWnd,
(HMENU)button1,
GetModuleHandle(NULL),
NULL);
if (buttonIsPressed == true)
{
CreateWindowEx(NULL,
L"BUTTON",
L"Text of the button",
WS_TABSTOP | WS_VISIBLE |
WS_CHILD | BS_DEFPUSHBUTTON,
/*windowWidth-15,*/
400,
rect.bottom - 40,
100,
28,
hWnd,
(HMENU)button2,
GetModuleHandle(NULL),
NULL);
}
}
case WM_PAINT:
{
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case button1:
{
buttonIsPressed = true;
break;
}
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
I also tried to use UpdateWindow and InvalidateRect.
Question 1: How can i create a new button when the other button is pressed?
Question 2: How can i stop drawing the other button. If I use InvalidateRect, the button becomes invisible, but as soon as i press on the window, it is visible again.
THANK YOU for your attention and your time.
You are close. You already know to create individual buttons (CreateWindowEx()). In the code you have shown, you just need to move the 2nd CreateWindowEx() from the WM_CREATE handler into the WM_COMMAND handler, being sure to check the reported ID/HWND to make sure it is the 1st button you are interested in, and then you can ShowWindow()/DestroyWindow() that button as needed and create the new button, eg:
constexpr unsigned int button1=111;
constexpr unsigned int button2=112;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static RECT rect;
//...
switch (message)
{
case WM_CREATE:
{
GetClientRect(hWnd, &rect);
CreateWindowEx(NULL,
L"BUTTON",
L"create new button",
WS_TABSTOP | WS_VISIBLE |
WS_CHILD | BS_DEFPUSHBUTTON,
/*windowWidth-15,*/
400,
rect.bottom - 40,
100,
28,
hWnd,
(HMENU)button1,
GetModuleHandle(NULL),
NULL);
break;
}
//...
case WM_COMMAND:
{
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case button1:
{
HWND hwndBtn = (HWND)lParam;
// use ShowWindow(hwndBtn, SW_HIDE) or DestroyWindow(hwndBtn) as needed...
GetClientRect(hWnd, &rect);
CreateWindowEx(NULL,
L"BUTTON",
L"Text of the button",
WS_TABSTOP | WS_VISIBLE |
WS_CHILD | BS_DEFPUSHBUTTON,
/*windowWidth-15,*/
400,
rect.bottom - 40,
100,
28,
hWnd,
(HMENU)button2,
GetModuleHandle(NULL),
NULL);
break;
}
case button2:
{
//...
break;
}
}
return 0;
}
break;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}

text menu as created window behaviour of highlighting

I have created a Windows application. The elements that I create are using subclassing as I wanted to handle mouse hover events.
DWORD dwStyleOfIcons = SS_BITMAP | SS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER;
img1 = CreateWindow(L"STATIC", NULL, dwStyleOfIcons,
posX, posY, imgWt, imgHt,
hWnd, (HMENU)ICON1_CLICKED, hInst, NULL);
SetWindowSubclass(img1, StaticSubClassWndProc, ICON1_CLICKED, 0);
In my StaticSubClassWndProc(), I handle WM_MOUSEMOVE, WM_MOUSELEAVE, and WM_MOUSEHOVER:
LRESULT CALLBACK StaticSubClassWndProc (HWND hwndsubclass, UINT msg, WPARAM wp, LPARAM lp, UINT_PTR uidsubclass , DWORD_PTR dwrefdata)
{
...
switch(Msg)
{
case WM_MOUSEHOVER: {
if(uidsubclass == ICON1_CLICKED){
texture = "texture2.bmp";
modifyImage(texture);
}
break;
}
case WM_MOUSELEAVE: {
if(uidsubclass == ICON1_CLICKED){
texture = "texture.bmp";
modifyImage(texture);
}
break;
}
There are many STATIC items in my application, which all I wanted the behavior of a pop up context menu, like when I hover over the image it changes to a selected image, and when the cursor is out of view the image changes back to normal. I was able to do that.
I was able to do this for images which act as icons, but how do I do it for static text controls? Essentially, in a pop up menu, the selected text is all highlighted:
Is there no simpler way to make my elements in this window behave like a pop up menu? All I want is this custom structure of pop up menu behavior.
I think you did not handle the TrackMouseEvent function correctly, which caused your child window to be unable to process the WM_MOUSEHOVER and WM_MOUSELEAVE messages.
I tested the following code and it worked for me:
HBITMAP hBmp1 = (HBITMAP)LoadImage(NULL, L"test1.bmp", IMAGE_BITMAP, 200, 300, LR_LOADFROMFILE);
HBITMAP hBmp2 = (HBITMAP)LoadImage(NULL, L"test2.bmp", IMAGE_BITMAP, 200, 300, LR_LOADFROMFILE);
HWND img1;
LRESULT CALLBACK StaticSubClassWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uidsubclass, DWORD_PTR dwrefdata)
{
switch (msg)
{
case WM_MOUSEMOVE:
{
TRACKMOUSEEVENT lpEventTrack;
lpEventTrack.cbSize = sizeof(TRACKMOUSEEVENT);
lpEventTrack.dwFlags = TME_HOVER | TME_LEAVE;
lpEventTrack.hwndTrack = img1;
lpEventTrack.dwHoverTime = 100;
TrackMouseEvent(&lpEventTrack);
break;
}
case WM_MOUSEHOVER:
{
if (uidsubclass == ICON1_CLICKED) {
SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp1);
}
break;
}
case WM_MOUSELEAVE:
{
if (uidsubclass == ICON1_CLICKED) {
SendMessage(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp2);
}
break;
}
default:
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
}
But you need to be aware that WM_MOUSEHOVER and WM_MOUSELEAVE will trigger frequently, so I don't think you should use this method to load pictures when the mouse is hovered or left, which will frequently trigger the loading of pictures.

Is there a way I can hide a button when checkbox is unchecked?

I working to make a program that the user must agree to continue with the program.
The user must check the checkbox to continue, if the user check the checkbox, the "RUN" button displayed, and if he unchecked the checkbox, the button is hidden.
I have two problems with my program, when the user unchecked the checkbox, the "RUN" button does not disappeared, and the second problem is that when the user click on the "RUN" button, my program thinks that the user clicked on the checkbox and check or unchecked the checkbox.
This is my whole program, I would be very happy if you helped me.
If you want you can debug this program and see my problems.
#include <windows.h>
#include <iostream>
#include "resource.h"
using namespace std;
LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM param, LPARAM lparam);
const char *title = "Check Box";
HWND agree, button;
int WINAPI WinMain(HINSTANCE currentInstance, HINSTANCE previousInstance, PSTR cmdLine, INT cmdCount)
{
// Register the window class
const char* CLASS_NAME = "myWin32WindowClass";
WNDCLASS wc{};
wc.hInstance = currentInstance;
wc.lpszClassName = CLASS_NAME;
wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(20, 20, 20));
wc.lpfnWndProc = WindowProcessMessages;
RegisterClass(&wc);
HWND main = CreateWindow(CLASS_NAME, "WastedBit 1.6.2",
WS_OVERLAPPED | WS_VISIBLE | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU, // Window style
CW_USEDEFAULT, CW_USEDEFAULT, // Window initial position
950, 750, // Window size
nullptr, nullptr, nullptr, nullptr);
// TopMost
SetWindowPos(main, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
// Window loop
MSG msg{};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CREATE: {
button = CreateWindow("button", 0,
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
20, 490, 15, 15,
hwnd, (HMENU)1, ((LPCREATESTRUCT)lparam)->hInstance, NULL);
CheckDlgButton(hwnd, 1, BST_UNCHECKED);
}
break;
case WM_COMMAND: {
BOOL checked = IsDlgButtonChecked(hwnd, 1);
if (checked) {
CheckDlgButton(hwnd, 1, BST_UNCHECKED);
}
else if (CheckDlgButton(hwnd, 1, BST_CHECKED) == TRUE) {
CheckDlgButton(hwnd, 1, BST_CHECKED);
agree = CreateWindow("button", "RUN", WS_VISIBLE | WS_CHILD, 750, 525, 150, 150, hwnd, (HMENU)button, 0, 0);
}
else if (CheckDlgButton(hwnd, 1, BST_UNCHECKED) == TRUE) {
ShowWindow(agree, SW_HIDE);
}
}
break;
case WM_DESTROY: {
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
My program works great with #duDE's help.
I put the button and the checkbox in WM_CREATE, I make the button to be invisible when created, but when the user check the checkbox, the button is created.
I wouldn't consider it a problem, but once the "RUN" button is pressed, the button disappears and the checkbox return to be unchecked.
LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CREATE: {
button = CreateWindow("button", 0,
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
20, 490, 15, 15,
hwnd, (HMENU)1, ((LPCREATESTRUCT)lparam)->hInstance, NULL);
agree = CreateWindow("button", "RUN", WS_CHILD, 750, 525, 150, 150, hwnd, 0, 0, 0);
}
break;
case WM_COMMAND: {
BOOL checked = IsDlgButtonChecked(hwnd, 1);
if (checked) {
CheckDlgButton(hwnd, 1, BST_UNCHECKED);
ShowWindow(agree, SW_HIDE);
}
else {
CheckDlgButton(hwnd, 1, BST_CHECKED);
ShowWindow(agree, SW_SHOW);
}
}
break;
case WM_DESTROY: {
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
}
I would create both objects (the check box AND the button) in WM_CREATE, you will get the handleButton back.
And the hiding should happens in WM_COMMAND then like this:
BOOL checked = IsDlgButtonChecked(hwnd, 1);
if (checked)
ShowWindow(handleButton, SW_HIDE);
else
ShowWindow(handleButton, SW_SHOW);

Enable Close Button for Dialog c++ winapi

Having simple window, button which opens dialog. But I want to add close button to it.
I have tried to add close button with adding WM_SYSMENU, with adding EnableMenuItem, but it didn't work:
Minimal code is:
resource.rc:
IDD_FORMVIEW DIALOGEX 0, 0, 178, 86
STYLE DS_SETFONT | DS_CONTROL | WS_VISIBLE | WS_SYSMENU
EXSTYLE WS_EX_OVERLAPPEDWINDOW
CAPTION "TEST"
FONT 12, "Microsoft Sans Serif", 400, 0, 0xCC
BEGIN
CTEXT "Test",IDC_STATIC,46,4,74,8,0,WS_EX_CLIENTEDGE
END
resource.h:
#define IDD_FORMVIEW 101
Test.cpp:
hwndButton = CreateWindowW(L"BUTTON",
L"ENTER",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
605, 510, 255, 45,
hWnd, (HMENU)1, NULL, NULL);
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case 2: {
if (hwndHTDW == NULL) {
hwndHTDW = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, DialogProc);
ShowWindow(hwndHTDW, SW_SHOW);
UpdateWindow(hwndHTDW);
}
}
break;
}
}
{
switch (msg) {
case WM_INITDIALOG: {
EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
MF_BYCOMMAND | MF_ENABLED);
return TRUE;
}
break;
default:
return FALSE;
}
return TRUE;
Modify your code a little bit.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
hwndButton = CreateWindowW(L"BUTTON",
L"ENTER",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
605, 510, 255, 45,
hWnd, (HMENU)1, NULL, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case 1:
{
if (hwndHTDW == NULL)
{
hwndHTDW = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, DialogProc);
Button_Close = CreateWindowW(L"BUTTON",
L"CLOSE",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
130, 100, 80, 30,
hwndHTDW, (HMENU)2, NULL, NULL);
ShowWindow(hwndHTDW, SW_SHOW);
UpdateWindow(hwndHTDW);
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL fError;
switch (message)
{
case WM_INITDIALOG:
{
EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
MF_BYCOMMAND | MF_ENABLED);
return TRUE;
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 2:
{
EndDialog(hwnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
default:
break;
}
}
default:
return FALSE;
}
return TRUE;
}
Updated:
Create an extra button through CreateWindow and pass the handle of the dialog box to the button as a parameter.
HWND Button_Close = CreateWindowW(L"BUTTON",
L"CLOSE",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
130, 100, 80, 30,
hwndHTDW, (HMENU)2, NULL, NULL);
In the callback function of the dialog box, add the WM_COMMAND event and add the following code.
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 2:
{
EndDialog(hwnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
}

A label whose background is transparent on the one hand and the upper window on the other

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?
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='*'\"")