Win32 Button keeps the blue border on focus lost

NorthernSun 101 Reputation points
2024-04-13T02:32:01.41+00:00

In a non-dialog window, is it a known bug or normal behavior that a push button keeps the blue focus border after a control in another window gets focused? I checked to see if the button receives the WM_KILLFOCUS message and yes it does. I noticed that in this situation the button keeps the style BS_DEFPUSHBUTTON.

GIF example:

ezgif-3-541aa06182

So far I saw behavior on the following systems: Windows Vista SP2, Windows 7, Windows 10.

I am also kind of curious about why push buttons get the BS_DEFPUSHBUTTON at all when they get the focus by a click for example.

edit: My aim is to have a simple child window that does not have a default button. I dont want the system to automatically make my button the default one when clicked because this is not a dialog window. If it unmakes it the default button on focus lost its fine I guess, but it does not do so in this situation. This button will be used to reset the values of other controls within the same window to their default values.

edit: sample code

#pragma comment(lib,"comctl32.lib")

#pragma comment(linker,"\"/manifestdependency:type='win32' \ name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#include <windows.h>
#include <CommCtrl.h>

::LRESULT CALLBACK WindowProc(::HWND hWnd, ::UINT msg, ::WPARAM wParam, ::LPARAM lParam);

// function fwd decls.
::HWND createWindow();
::HWND createChildWindow(::HWND hParent);
::HWND createStatic(::HWND hParent, ::TCHAR* text);
::HWND createButton(::HWND hParent);
::HWND createTextbox(::HWND hParent);

::HWND g_hMainWindow;
::HWND g_hChildWindow1;
::HWND g_hChildWindow2;
::HWND g_hStatic1;
::HWND g_hStatic2;
::HWND g_hButton;
::HWND g_hTextbox;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* szCmdLine, int iCmdShow) {

	::INITCOMMONCONTROLSEX iccex;
	iccex.dwSize = sizeof(iccex);
	iccex.dwICC = ICC_STANDARD_CLASSES;
	::InitCommonControlsEx(&iccex);

	// create main window
	g_hMainWindow = createWindow();
	
	// create child windows
	g_hChildWindow1 = createChildWindow(g_hMainWindow);
	g_hChildWindow2 = createChildWindow(g_hMainWindow);

	// calc main window new position
	int screenResolutionX = ::GetSystemMetrics(SM_CXSCREEN);
	int screenResolutionY = ::GetSystemMetrics(SM_CYSCREEN);

	::RECT rcMainWindow;
	::GetWindowRect(g_hMainWindow, &rcMainWindow);

	int iMainWindowWidth = rcMainWindow.right - rcMainWindow.left;
	int iMainWindowHeight = rcMainWindow.bottom - rcMainWindow.top;

	// position main window
	::SetWindowPos(g_hMainWindow, 0, screenResolutionX / 2 - iMainWindowWidth / 2, screenResolutionY / 2 - iMainWindowHeight / 2, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

	// position child window 2
	::SetWindowPos(g_hChildWindow2, 0, 250, 20, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);

	// create child window controls
	g_hStatic1 = createStatic(g_hChildWindow1, (::TCHAR*)TEXT("Child Window 1"));
	g_hStatic2 = createStatic(g_hChildWindow2, (::TCHAR*)TEXT("Child Window 2"));
	g_hTextbox = createTextbox(g_hChildWindow1);
	g_hButton = createButton(g_hChildWindow2);

	::MSG msg = { 0 };

	while ((::GetMessage(&msg, NULL, 0, 0))) {

		if (!::IsDialogMessage(::GetParent(msg.hwnd), &msg)) {

			::TranslateMessage(&msg);
			::DispatchMessage(&msg);

		}

	}

	return msg.wParam;
}


::LRESULT CALLBACK WindowProc(::HWND hWnd, ::UINT msg, ::WPARAM wParam, ::LPARAM lParam) {

	switch (msg) {

		case WM_CLOSE:
		{
			
			::PostQuitMessage(0);

			break;

		}

		case WM_CTLCOLORSTATIC:
		{
			
			::HDC hDC = ::GetDC(hWnd);
			
			::HBRUSH hBrush = (::HBRUSH)::GetStockObject(WHITE_BRUSH);
			::LOGBRUSH lb = { 0 };

			::GetObject(hBrush, sizeof(lb), &lb);

			::SetBkMode(hDC, OPAQUE);
			::SetBkColor(hDC, lb.lbColor);

			return (::LRESULT)hBrush;

			break;

		}

	}

	return DefWindowProc(hWnd, msg, wParam, lParam);

}

::HWND createWindow() {

	::WNDCLASS wndClass = { 0 };

	wndClass.hbrBackground = (::HBRUSH)::GetStockObject(GRAY_BRUSH);
	wndClass.hCursor       = ::LoadCursor(NULL, IDC_ARROW);
	wndClass.hIcon         = ::LoadIcon(NULL, IDC_ICON);
	wndClass.hInstance     = ::GetModuleHandle(0);
	wndClass.lpfnWndProc   = WindowProc;
	wndClass.lpszClassName = TEXT("MainWindow");

	if (!::RegisterClass(&wndClass))
		return 0;

	::HWND hWnd = ::CreateWindowEx(0,
	                               TEXT("MainWindow"),
	                               TEXT("MainWindow"),
	                               WS_OVERLAPPEDWINDOW,
	                               20, 20, 485, 400,
	                               NULL,
	                               (::HMENU)NULL,
	                               ::GetModuleHandle(0),
	                               0);

	::ShowWindow(hWnd, SW_SHOW);
	::UpdateWindow(hWnd);

	return hWnd;

}

::HWND createChildWindow(::HWND hParent) {

	::WNDCLASS wndClass = { 0 };

	wndClass.hbrBackground = (::HBRUSH)::GetStockObject(WHITE_BRUSH);
	wndClass.hCursor       = ::LoadCursor(NULL, IDC_ARROW);
	wndClass.hIcon         = ::LoadIcon(NULL, IDC_ICON);
	wndClass.hInstance     = ::GetModuleHandle(0);
	wndClass.lpfnWndProc   = WindowProc;
	wndClass.lpszClassName = TEXT("ChildWindow");
	wndClass.lpszMenuName  = NULL;

	RegisterClass(&wndClass);

	static int iUniqueIDGen = 1000;

	::HWND hWnd = ::CreateWindowEx(0,
	                               TEXT("ChildWindow"),
	                               TEXT("ChildWindow"),
	                               WS_CHILDWINDOW | WS_BORDER | WS_CLIPSIBLINGS,
	                               20, 20, 200, 200,
	                               hParent,
	                               (::HMENU)iUniqueIDGen++,
	                               ::GetModuleHandle(0),
	                               0);

	::ShowWindow(hWnd, SW_SHOW);
	::UpdateWindow(hWnd);

	return hWnd;

}

::HWND createTextbox(::HWND hParent) {

	::HWND hWnd = ::CreateWindowEx(0,
	                               WC_EDIT,
	                               WC_EDIT,
	                               WS_CHILD | WS_BORDER,
	                               50, 50, 100, 20,
	                               hParent,
	                               0,
	                               ::GetModuleHandle(0),
	                               0);
	
	::ShowWindow(hWnd, SW_SHOW);
	::UpdateWindow(hWnd);

	return hWnd;

}

::HWND createStatic(::HWND hParent, ::TCHAR* text) {

	::HWND hWnd = ::CreateWindowEx(0,
	                               WC_STATIC,
	                               text,
	                               WS_CHILD,
	                               50, 20, 200, 20,
	                               hParent,
	                               0,
	                               ::GetModuleHandle(0),
	                               0);

	::ShowWindow(hWnd, SW_SHOW);
	::UpdateWindow(hWnd);

	return hWnd;

}

::HWND createButton(::HWND hParent) {

	::HWND hWnd = ::CreateWindowEx(0,
	                               WC_BUTTON,
	                               WC_BUTTON,
	                               WS_CHILD | BS_PUSHBUTTON | BS_NOTIFY,
	                               50, 50, 100, 20,
	                               hParent,
	                               0,
	                               ::GetModuleHandle(0),
	                               0);

	::ShowWindow(hWnd, SW_SHOW);
	::UpdateWindow(hWnd);

	return hWnd;

}
Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,423 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,531 questions
{count} votes

Accepted answer
  1. RLWA32 40,471 Reputation points
    2024-04-16T08:04:23.35+00:00

    BlueButton

    I've made a couple of changes to the posted code. Give it a try -

    #pragma comment(lib,"comctl32.lib")
    
    #pragma comment(linker,"\"/manifestdependency:type='win32' \
     name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
     processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    
    #include <windows.h>
    #include <CommCtrl.h>
    
    ::LRESULT CALLBACK WindowProc(::HWND hWnd, ::UINT msg, ::WPARAM wParam, ::LPARAM lParam);
    
    // function fwd decls.
    ::HWND createWindow();
    ::HWND createChildWindow(::HWND hParent);
    ::HWND createStatic(::HWND hParent, ::TCHAR* text);
    ::HWND createButton(::HWND hParent);
    ::HWND createTextbox(::HWND hParent);
    
    ::HWND g_hMainWindow;
    ::HWND g_hChildWindow1;
    ::HWND g_hChildWindow2;
    ::HWND g_hStatic1;
    ::HWND g_hStatic2;
    ::HWND g_hButton;
    ::HWND g_hTextbox;
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* szCmdLine, int iCmdShow) {
    
        ::INITCOMMONCONTROLSEX iccex;
        iccex.dwSize = sizeof(iccex);
        iccex.dwICC = ICC_STANDARD_CLASSES;
        ::InitCommonControlsEx(&iccex);
    
        // create main window
        g_hMainWindow = createWindow();
    
        // create child windows
        g_hChildWindow1 = createChildWindow(g_hMainWindow);
        g_hChildWindow2 = createChildWindow(g_hMainWindow);
    
        // calc main window new position
        int screenResolutionX = ::GetSystemMetrics(SM_CXSCREEN);
        int screenResolutionY = ::GetSystemMetrics(SM_CYSCREEN);
    
        ::RECT rcMainWindow;
        ::GetWindowRect(g_hMainWindow, &rcMainWindow);
    
        int iMainWindowWidth = rcMainWindow.right - rcMainWindow.left;
        int iMainWindowHeight = rcMainWindow.bottom - rcMainWindow.top;
    
        // position main window
        ::SetWindowPos(g_hMainWindow, 0, screenResolutionX / 2 - iMainWindowWidth / 2, screenResolutionY / 2 - iMainWindowHeight / 2, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
    
        // position child window 2
        ::SetWindowPos(g_hChildWindow2, 0, 250, 20, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
    
        // create child window controls
        g_hStatic1 = createStatic(g_hChildWindow1, (::TCHAR*)TEXT("Child Window 1"));
        g_hStatic2 = createStatic(g_hChildWindow2, (::TCHAR*)TEXT("Child Window 2"));
        g_hTextbox = createTextbox(g_hChildWindow1);
        g_hButton = createButton(g_hChildWindow2);
    
        ::MSG msg = { 0 };
    
        while ((::GetMessage(&msg, NULL, 0, 0))) {
    
            if (!::IsDialogMessage(/*::GetParent(msg.hwnd)*/g_hMainWindow, &msg)) {
    
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
    
            }
    
        }
    
        return msg.wParam;
    }
    
    
    ::LRESULT CALLBACK WindowProc(::HWND hWnd, ::UINT msg, ::WPARAM wParam, ::LPARAM lParam) {
    
        switch (msg) {
    
        case WM_CLOSE:
        {
    
            ::PostQuitMessage(0);
    
            break;
    
        }
    
        case WM_CTLCOLORSTATIC:
        {
    
            ::HDC hDC = ::GetDC(hWnd);
    
            ::HBRUSH hBrush = (::HBRUSH)::GetStockObject(WHITE_BRUSH);
            ::LOGBRUSH lb = { 0 };
    
            ::GetObject(hBrush, sizeof(lb), &lb);
    
            ::SetBkMode(hDC, OPAQUE);
            ::SetBkColor(hDC, lb.lbColor);
    
            return (::LRESULT)hBrush;
    
            break;
    
        }
    
        }
    
        return DefWindowProc(hWnd, msg, wParam, lParam);
    
    }
    
    ::HWND createWindow() {
    
        ::WNDCLASS wndClass = { 0 };
    
        wndClass.hbrBackground = (::HBRUSH)::GetStockObject(GRAY_BRUSH);
        wndClass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
        wndClass.hIcon = ::LoadIcon(NULL, IDC_ICON);
        wndClass.hInstance = ::GetModuleHandle(0);
        wndClass.lpfnWndProc = WindowProc;
        wndClass.lpszClassName = TEXT("MainWindow");
    
        if (!::RegisterClass(&wndClass))
            return 0;
    
        ::HWND hWnd = ::CreateWindowEx(0,
            TEXT("MainWindow"),
            TEXT("MainWindow"),
            WS_OVERLAPPEDWINDOW,
            20, 20, 485, 400,
            NULL,
            (::HMENU)NULL,
            ::GetModuleHandle(0),
            0);
    
        ::ShowWindow(hWnd, SW_SHOW);
        ::UpdateWindow(hWnd);
    
        return hWnd;
    
    }
    
    ::HWND createChildWindow(::HWND hParent) {
    
        ::WNDCLASS wndClass = { 0 };
    
        wndClass.hbrBackground = (::HBRUSH)::GetStockObject(WHITE_BRUSH);
        wndClass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
        wndClass.hIcon = ::LoadIcon(NULL, IDC_ICON);
        wndClass.hInstance = ::GetModuleHandle(0);
        wndClass.lpfnWndProc = WindowProc;
        wndClass.lpszClassName = TEXT("ChildWindow");
        wndClass.lpszMenuName = NULL;
    
        RegisterClass(&wndClass);
    
        static int iUniqueIDGen = 1000;
    
        ::HWND hWnd = ::CreateWindowEx(WS_EX_CONTROLPARENT,
            TEXT("ChildWindow"),
            TEXT("ChildWindow"),
            WS_CHILDWINDOW | WS_BORDER | WS_CLIPSIBLINGS,
            20, 20, 200, 200,
            hParent,
            (::HMENU)iUniqueIDGen++,
            ::GetModuleHandle(0),
            0);
    
        ::ShowWindow(hWnd, SW_SHOW);
        ::UpdateWindow(hWnd);
    
        return hWnd;
    
    }
    
    ::HWND createTextbox(::HWND hParent) {
    
        ::HWND hWnd = ::CreateWindowEx(0,
            WC_EDIT,
            WC_EDIT,
            WS_CHILD | WS_BORDER | WS_TABSTOP,
            50, 50, 100, 20,
            hParent,
            0,
            ::GetModuleHandle(0),
            0);
    
        ::ShowWindow(hWnd, SW_SHOW);
        ::UpdateWindow(hWnd);
    
        return hWnd;
    
    }
    
    ::HWND createStatic(::HWND hParent, ::TCHAR* text) {
    
        ::HWND hWnd = ::CreateWindowEx(0,
            WC_STATIC,
            text,
            WS_CHILD,
            50, 20, 200, 20,
            hParent,
            0,
            ::GetModuleHandle(0),
            0);
    
        ::ShowWindow(hWnd, SW_SHOW);
        ::UpdateWindow(hWnd);
    
        return hWnd;
    
    }
    
    ::HWND createButton(::HWND hParent) {
    
        ::HWND hWnd = ::CreateWindowEx(0,
            WC_BUTTON,
            WC_BUTTON,
            WS_CHILD | BS_PUSHBUTTON | BS_NOTIFY | WS_TABSTOP,
            50, 50, 100, 20,
            hParent,
            0,
            ::GetModuleHandle(0),
            0);
    
        ::ShowWindow(hWnd, SW_SHOW);
        ::UpdateWindow(hWnd);
    
        return hWnd;
    
    }
    
    2 people found this answer helpful.

0 additional answers

Sort by: Most helpful