I want to have both an image icon and text on the same button, like here in Word for example.
I set an icon on a button, but the text disappears.
HANDLE hBmp = (HBITMAP)LoadImage(g_hDllInstance,
MAKEINTRESOURCE(IDB_BITMAP4),
IMAGE_BITMAP,
NULL,
NULL,
LR_DEFAULTCOLOR);
HWND hwndButton = CreateWindowEx(
NULL,
_T("BUTTON"),
_T("SOME TEXT"),
BS_BITMAP | WS_VISIBLE | WS_CHILD,
point.x - 47,
point.y - 3,
36,
40,
hWnd,
(HMENU)200,
NULL,
NULL);
SendMessage(
(HWND)hwndButton,
(UINT)BM_SETIMAGE,
(WPARAM)IMAGE_BITMAP,
(LPARAM)hBmp);
I have also tried to set the icon on a smaller subwindow on my button, but for some reason my subwindow is not visible.
Instructions on how to get a button to display both an image and text are outlined in the Button Styles reference1:
The appearance of text or an icon or both on a button control depends on the BS_ICON and BS_BITMAP styles, and whether the BM_SETIMAGE message is sent. The possible results are as follows.
BS_ICON or BS_BITMAP set? | BM_SETIMAGE called? | Result
--------------------------+---------------------+--------------------
Yes | Yes | Show icon only.
No | Yes | Show icon and text.
Yes | No | Show text only.
No | No | Show text only
In other words: Don't set the BS_ICON or BS_BITMAP style (but do set the BS_TEXT style), and send a BM_SETIMAGE message once the button has been created.
To see this in action, create a standard Windows Desktop application in Visual Studio, and apply the following changes:
Enable visual styles. This is easiest done by placing a #pragma linker directive into the only compilation unit:
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
Create the button in the main window's WM_CREATE handler:
case WM_CREATE:
{
HWND btn{ ::CreateWindowExW(0x0, L"BUTTON", L"Button text",
WS_VISIBLE | WS_CHILD | BS_TEXT,
10, 10, 200, 50, hWnd, (HMENU)110,
nullptr, nullptr) };
HICON icon{ (HICON)::LoadImageW(::GetModuleHandle(nullptr),
MAKEINTRESOURCEW(107),
IMAGE_ICON, 32, 32, 0x0) };
::SendMessageW(btn, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
}
break;
Make sure to adjust the numeric constants as needed. 110 is the button's control identifier, 107 is the resource ID of the wizard-generated application icon resource, and 32 are the width and height of the requested icon.
This code produces the following output:
1 Note, that you have to enable visual styles for this to work.
Related
I have two buttons. Each button is highlighted instead of just the first one. How do I make the first button to be only the one highlighted?
BTW This is the code for the two buttons:
openFileButton = CreateWindowA("button", "Open File and start hashing", WS_VISIBLE | WS_CHILD | SS_CENTER, 220, 210, 200, 50, hWnd,
(HMENU)BUTTON_OPEN_FILE, NULL, NULL);
SendMessage(openFileButton, WM_SETFONT, my_font, true);
hashFileButton = CreateWindowA("button", "Get the File hash", WS_VISIBLE | WS_CHILD | SS_CENTER, 220, 270, 200, 50, hWnd,
(HMENU)BUTTON_HASH_FILE, NULL, NULL);
SendMessage(hashFileButton, WM_SETFONT, my_font, true);
Tried using SetFocus but got no luck.
First, stop calling the A versions of WinAPI functions. Those went obsolete back in the '90s. Use the W versions instead, with L prefixes on your string literals and wchar_t as your character type.
Second, you are passing the wrong style flags for buttons. Specifically, you are passing SS_CENTER. This is a style for static controls (hence the SS_ prefix), not for buttons. SS_CENTER is #defined in the Windows header files as the value 0x1, which is equivalent to the button style, BS_DEFPUSHBUTTON. (Note that #define macros are not type-safe, so the compiler doesn't know and can't warn you that you're specifying a static-control style when creating a button control.)
The presence of this erroneous BS_DEFPUSHBUTTON style is why your buttons are both appearing highlighted, as if they are the default button in a dialog box. For standard buttons, you want BS_PUSHBUTTON, which is #defined as the value 0x0, and thus equivalent to not passing any style flags to your CreateWindow function. But for readability and self-documenting code, I would strongly recommend explicitly passing BS_PUSHBUTTON.
So, your corrected code becomes:
openFileButton = CreateWindowW(L"button",
L"Open File and Start Hashing",
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
220, 210, 200, 50,
hWnd,
(HMENU)BUTTON_OPEN_FILE,
NULL,
NULL);
SendMessage(openFileButton, WM_SETFONT, my_font, true);
hashFileButton = CreateWindowW(L"button",
L"Get the File Hash",
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
220, 270, 200, 50,
hWnd,
(HMENU)BUTTON_HASH_FILE,
NULL,
NULL);
SendMessage(hashFileButton, WM_SETFONT, my_font, true);
You might actually want to make one (and only one) of your buttons into the "default" button using the BS_DEFPUSHBUTTON style. The behavior is easily implemented by calling the IsDialogMessage function within your main message loop (behavior which you would get for "free" by creating a dialog box, with the added boon of the Resource Editor to lay out the controls and set styles).
I've been scratching my head over this for a week now. I'm using the Windows API and I made a textbox with
editBox = CreateWindowEx(WS_EX_PALETTEWINDOW, TEXT("Edit"), NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | ES_MULTILINE | ES_LEFT | ES_AUTOVSCROLL, 175, 110, 140, 150, hwnd, (HMENU) ID_TEXT, NULL, NULL);
and a button
button = CreateWindowEx(WS_EX_PALETTEWINDOW, "BUTTON", "Ok", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 175, 260, 140, 20, hwnd, (HMENU) ID_BUTTON, NULL, NULL);
and I want to be able to click the button and it store what was typed into editBox in a primitive string. Examples are preffered but links and documentation are also very much appreciated! :)
You can use the GetWindowText API function to get the text of an edit control.
For a window with title this function retrieves the title. For an edit control it retrieves the edit control's text. Just ignore any documentation saying that you're limited to 64K or so, if you encounter it (it was once that way).
To detect the button click, process the WM_COMMAND window message in your window procedure; it's sent to the parent window of the button. There is a more sophisticated approach based on reflecting the message back to button, which can then process it itself, and that approach is used in most higher level frameworks. But at the API level, just check WM_COMMAND in the parent window's window procedure.
I'm trying to add CBS_OWNERDRAWFIXED style to an existing combobox , my code doesn't work and I have no idea why .
I suspect maybe the expression oldStyle | addedStyle is not valid , but I can't figure out why.
HWND hwnd = CreateWindow(
L"ComboBox",
L"",
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST ,
200,
200,
200,
200,
parentHandle,
(HMENU)1,
GetModuleHandle(NULL),
NULL);
auto comboBoxStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
comboBoxStyle = comboBoxStyle | CBS_OWNERDRAWFIXED;
SetWindowLongPtr(hwnd, GWL_STYLE, comboBoxStyle);
the output is just regular combobox , without any change.
This particular style can only be specified at creation time. The documentation alludes to this when it says:
CBS_OWNERDRAWFIXED
Specifies that the owner of the list box is responsible for drawing its contents and that the items in the list box are all the same height. The owner window receives a WM_MEASUREITEM message when the combo box is created and a WM_DRAWITEM message when a visual aspect of the combo box has changed.
Below is part of a working normal win32 application created from scratch, not dialog based. it will show the text on the buttom, not top:
hButtonApply = CreateWindow(
"BUTTON",
"Reset",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_BOTTOM,
95, 130, 120, 40,
hWnd, (HMENU)IDC_BUTTON_RESET, hInstance, NULL);
SendMessage(hButtonApply, BM_SETSTYLE, BS_TOP, TRUE);
this however makes it a radio button:
SendMessage(hButtonApply, BM_SETSTYLE, BS_RADIOBUTTON, TRUE);
same for a resource-defined dialog button control.
Subclassing is acceptable. Owner-Drawn Buttons are not acceptable. Thanks, Haotian Yang
Some window styles can only be set during CreateWindow, I guess this might be one of them.
Did you try SetWindowLong ?
Edit:
This seems to work:
LONG style = GetWindowLong(hBtn,GWL_STYLE);
style = (style & ~BS_BOTTOM) | BS_TOP;
SetWindowLong(hBtn,GWL_STYLE,style);
I know how to draw a button in C++ but how would i make an icon on it can someone post source or give reference please? by SendMessage() or if not that way just please paste
Please need easier anwsers without so many files im new a bit
Since you're new, you may also wish to consult the MSDN Library. You can find information on Button Styles (see, specifically, the BS ICON and BS BITMAP styles) and the BM_SETIMAGE message .
If you use MFC then I would recommend you to use the following CButton method SetIcon:
CButton myButton;
// Create an icon button.
myButton.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_ICON,
CRect(10,10,60,50), pParentWnd, 1);
// Set the icon of the button to be the system question mark icon.
myButton.SetIcon( ::LoadIcon(NULL, IDI_QUESTION) );
This works very well.
send BM_SETIMAGE message, and pass loaded image handle to lParam.
button1 = CreateWindowW(L"BUTTON", L"&Button", WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_BITMAP, 20, 50, 80, 25, hwnd, (HMENU) 600, NULL, NULL);
hImg = LoadImageW(NULL, L"test123.bmp", IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_LOADFROMFILE);
SendMessageW(button1, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImg);
P.S: you need to use BS_BITMAP flag when CreateWindow()