C++ Win32 API Controls messages - c++

im starting with Win32 api, im adding a button control to my main window with the flowing code:
HWND boton = CreateWindow(
"BUTTON", //
"Caption", //
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles.
250, // x position.
10, // y position.
100, // Button width.
40, // Button height.
hwnd, // Parent window.
NULL, // No menu.
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
how can i assign it an id, so i can get the message on the loop, in the message loop im trying to catch the message as WM_COMMAND but i don't get any result i've tried with WM_NOTIFY too.

To assign it an ID, you have to use the hMenu parameter. If you have specified that the window will be a child (i.e. with WS_CHILD), the hMenu parameter will be interpreted as an integer ID for the window. Also, provide the BS_NOTIFY style.
HWND boton = CreateWindow (
"BUTTON",
WS_TAPSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | BS_NOTIFY,
250, 10, 100, 40,
hwnd,
(HMENU)101, // This becomes the Control ID
(HINSTNACE)GetWindowLong(hwnd,GWL_HINSTANCE),
NULL);
EDIT: Special shout goes out to Heath Hunnicutt for the info on BS_NOTIFY.

In fact, you do not need to specify an ID for the button. The problem is your code is missing a style bit to CreateWindow().
You must specify the style BS_NOTIFY for the parent window to receive notifications from Button controls.
You will then receive window message WM_COMMAND with (HIWORD(w_param) == BN_CLICKED) every time your button is clicked. See the BN_CLICKED documentation for more.
Using a control ID is unnecessary because the BN_CLICKED message will provide you with the control's window handle. Because you are already required to keep track of the window handle in order to properly call DestroyWindow when you receive WM_DESTROY comparing the button's window handle is just as easy as using a control ID.

To set the window id, pass it in as if it were an HMENU:
(HMENU) nChildID

Related

How to get text from a textbox in the Windows API

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.

WinApi : Add style to combo box

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.

How to group radio box buttons using Win32 API

I am working on a program with grouped check box and get confused on how the messages convey through different handles.
IDE:VC++, Win32 API
First, I have a main window which has a handle, say hWnd.
And in the WndProc function under case WM_CREATE, we create the "group button" and the individual 2 check boxes
Note: the first button uses "BS_GROUPBOX" style, and it was created with the handle hGrpButton while its parent handler is hWnd. The second and third button is "BS_AUTORADIOBUTTON" style and it's parent handle is hGrpButton.
If the 2 buttons are not grouped(so their parent hanlder would be hWnd), it is easy to check the status of them. Just simply go to case WM_COMMAND AND use their ID to check with the IsDlgButtonChecked function. After the two check boxes are grouped (their parent handle are not longer hWnd but hGrpButtons), I don't think the case WM_COMMAND will find their IDs since it is looking for the IDs under hWnd.
In short, after 2 check boxes are grouped, I don't know what is the event to monitor them.
case WM_CREATE:
{
/*Group for Radio button for preview/single or batch operation */
hGrpButtons=CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"Select Process Mode:",
WS_VISIBLE | WS_CHILD|BS_GROUPBOX, // Styles
10,280,
350,100,
hWnd,
NULL,
hInst, NULL);
CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"Batch Process Mode",
WS_VISIBLE | WS_CHILD|BS_AUTORADIOBUTTON, // Styles
10,20,
300,20,
hGrpButtons,
(HMENU)IDC_CHK1,
hInst, NULL);
CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"Single Process Mode (Preview Mode)",
WS_VISIBLE | WS_CHILD|BS_AUTORADIOBUTTON, // Styles
10,45,
300,20,
hGrpButtons,
(HMENU)IDC_CHK2,
hInst, NULL);
After read Coder_Dan's comment and MSDN article "http://msdn.microsoft.com/en-us/library/bb775947(v=vs.85).aspx#related_topics" about the button types, I finally sort it out.
BS_GROUPBOX is just an "eye candy" and it did no contribute to the group of the radio box!! The critical parameter to control the grouping is the "WS_GROUP"
How to group the radio box: Put the WS_GROUP in the first radio button's style. It will group the current radio button until it see the second WS_GROUP as mentioned by Coder_Dan.
Modification on my previous code
a. use hWnd as parent for all 4 radio buttons
b. Put WS_GROUP in the first and third button style so that we group the 1,2 and 3,4 radio buttons
c. Now you can go to the WM_COMMAND, and listen to the messages from the 4 buttons according to their IDs under the main window's handle hWnd
case WM_CREATE:
{
/*Group for Radio button for preview/single or batch operation */
hGrpButtons=CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"Select Process Mode:",
WS_VISIBLE | WS_CHILD|BS_GROUPBOX,// <----BS_GROUPBOX does nothing on the grouping
10,280,
350,100,
hWnd,
(HMENU)IDC_GRPBUTTONS,
hInst, NULL);
CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"first radio button",
WS_VISIBLE | WS_CHILD|BS_AUTORADIOBUTTON|WS_GROUP, // <---- WS_GROUP group the following radio buttons 1st,2nd button
10,520,
300,20,
hWnd, //<----- Use main window handle
(HMENU)IDC_CHK1,
hInst, NULL);
CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"second radio button",
WS_VISIBLE | WS_CHILD|BS_AUTORADIOBUTTON, // Styles
10,545,
300,20,
hWnd,
(HMENU)IDC_CHK2,
hInst, NULL);
CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"third radio button",
WS_VISIBLE | WS_CHILD|BS_AUTOCHECKBOX|WS_GROUP, //<---Start second group for 3rd,4th button
10,570,
300,20,
hWnd,
(HMENU)IDC_CHK3,
hInst, NULL);
CreateWindowEx(WS_EX_WINDOWEDGE,
L"BUTTON",
L"forth radio button",
WS_VISIBLE | WS_CHILD|BS_AUTORADIOBUTTON, // Styles
500,545,
300,20,
hWnd,
(HMENU)IDC_CHK4,
hInst, NULL);

Change button style on the fly in Win32

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);

How to make an icon button in C++

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()