C++ Checkbox's acting like radio buttons WINAPI ( No MFC ) - c++

I am trying to get 2 checkboxs in my application to act like radio buttons. IE - When one is ticked the other button will untick itself. I dont believe that this can be achieved through the properties menu so I am trying to do it in code.
I dont know much about how to do this at all so I am getting a bit lost. This is what I have so far (which Is not working)
case BN_CLICKED:
if(BN_CLICKED == IDC_CHECK_MW){
SendMessage(GetDlgItem(hDlg,IDC_CHECK_MW), BM_GETCHECK, (WPARAM)0 ,(LPARAM)0) == BST_CHECKED;
}
I may be way oof but any help would be great!

If you have the handles or something handy, just send a BM_SETCHECK:
int checkState = SendMessage (otherHwnd, BM_GETCHECK, 0, 0);
SendMessage (otherHwnd, BM_SETCHECK, checkState == BST_CHECKED ? BST_UNCHECKED : BST_CHECKED, 0);
This of course assumes that it can only be checked or unchecked, not in an intermediate state. I would also really reconsider your thinking, as checkboxes are meant to act as such, and radio buttons are the right tools for this behaviour.
Also, in your message switch, you want this probably:
case WM_COMMAND:
{
if (HIWORD (wParam) == BN_CLICKED)
{
switch (LOWORD (wParam))
{
case IDC_CHECK_MW:
//check this, uncheck that
break;
case IDC_OTHER_CHECK:
//check other, uncheck first
break;
default:
//something went wrong
}
}
}

Related

How to add checkbox beside a text using mfc

I'm learning mfc, activex controls and containers. I'm doing a assignment on containers(Dialog).I have created a dialog, when I do right click, there are system menu items like Minimize, Maximize, Move, Size. All these items appeared by selecting true in dialog properties. I have added another item "Always on top" which will be appear on top. When the user click on Always on top I provided a message box which will say "Do you want enable?" I gave yes or no for that, but I have to avoid this message box and need to add a checkbox beside the Always on top item. So that whenever user wants the dialog to appear on top they can use the checkbox.
I have tried in one possible way by adding a bitmap image of checkmark but somehow it's not working and I have less time. If anyone has any idea how I can add this checkbox please let me know.
This is the code where I have appended the item
BOOL CDiagDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
CMenu * pSystemMenu = GetSystemMenu(FALSE);
pSystemMenu->AppendMenu(MF_ENABLED, IDM_SYSCOMMAND_CUSTOM,_T("Always on top"));
return TRUE; // return TRUE unless you set the focus to a control
}
void CDiagDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if (nID == IDM_SYSCOMMAND_CUSTOM)
{
AfxMessageBox(
_T("Enable Always on top"), MB_YESNO
);
switch (iResponse) {
case IDYES:
SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOSIZE);
break;
case IDNO:
SetWindowPos(&CWnd::wndNoTopMost, 0, 0, 0, 0, SWP_NOSIZE);
break;
}
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

How to add mouse double click to ListBox

To this code: https://www.dreamincode.net/forums/topic/163804-microsoft-working-with-listboxes-part-i/
It is displaying list and looping nicely.
Sadly my guru never finished his code.
So plan would be adding double click detection on a name. How?
case WM_COMMAND:
{
return 0;
}
Something like this? 11 is this child window where names are.
case WM_COMMAND:
{
if (LOWORD(wparam) == 11) {
if ((message) == LBN_DBLCLK) {
cout << "double click" << endl;
}
}
return 0;
}
Doesn't work
First, according to the documentation:
Parameters
wParam
The LOWORD contains the identifier of the list box. The HIWORD specifies the notification code.
lParam
Handle to the list box.
Remarks
This notification code is sent only by a list box that has the LBS_NOTIFY style.
So in the first step you need to add this style and use HIWORD (wParam) to determine whether to double-click the list.
Then if you need to get the elements of the list, you should not send LB_GETCURSEL to window_handle, but should send it to This->listbox_handle, which is the window handle of the listbox. Then you can get it by sending LB_GETTEXT Text content.
Here is the code:
case WM_COMMAND:
{
if (HIWORD(wparam) == LBN_DBLCLK) {
TCHAR temp[100]{};
int index = SendMessageW(This->listbox_handle, LB_GETCURSEL, 0, 0L);
SendMessageW(This->listbox_handle, LB_GETTEXT, index, (LPARAM)temp);
MessageBox(window_handle, temp, L"test", 0);
}
return 0;
}
And it works for me:
Try replacing:
if ((message) == LBN_DBLCLK)
with:
if (HIWORD (wParam) == LBN_DBLCLK)
Documentation here.

win32 C++ Custom Color for Trackbar thumb

I have spent today searching everywhere for a concrete explanation or example of coloring the thumb on a trackbar (slider) in win32 C++. Everything I've found has been partially explained, and in trying every conceivable variation I have come up blank.
The control I have been focused on is defined in my rc file as
CONTROL "",IDC_PLAYSLIDER,"msctls_trackbar32",TBS_NOTICKS | WS_TABSTOP,5,22,187,15
Essentially, my message handling of NM_CUSTOMDRAW comes down to the following. I have no confidence on my color/hdc handling, but the lack of messages is my primary problem.
INT_PTR CALLBACK dialogproc(HWND h, UINT m, WPARAM w, LPARAM l)
{
switch (m) {
case WM_NOTIFY:
{
switch (((LPNMHDR)l)->code) {
case NM_CUSTOMDRAW:
{
LPNMCUSTOMDRAW lpNMCD = (LPNMCUSTOMDRAW)l;
UINT idc = lpNMCD->hdr.idFrom;
switch (lpNMCD->dwDrawStage) {
case CDDS_PREPAINT:
return CDRF_NOTIFYSUBITEMDRAW;
break;
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
{
switch (lpNMCD->dwItemSpec)
{
case TBCD_THUMB:
HGDIOBJ old_pen = SelectObject(lpNMCD->hdc, penSlider);
HGDIOBJ old_brush = SelectObject(lpNMCD->hdc, brushSlider);
return CDRF_NEWFONT;
}
}
break;
}
What I am getting at runtime is a CDDS_PREPAINT on the correct control, but no matter what I have tried, I have had no further CDDS_ drawStage messages.
If anyone has done this on a trackbar (most examples are list controls) and is willing to share their message handler code, or can otherwise shed light on my confusion, that would be greatly appreciated.
From the docs for NM_CUSTOMDRAW:
If this message is handled in a dialog procedure, you must set the
return value as part of the window data before returning TRUE. For
more information, see DialogProc.
The DialogProc docs say:
If the dialog box procedure processes a message that requires a
specific return value, the dialog box procedure should set the desired
return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult)
immediately before returning TRUE
Note that with the advent of 64-bit windows it is better practice to use SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, lResult).

C++ window draggable by its menu bar

So I'm using Visual C++, and I have created a draggable, borderless window. Anyway, there is a toolbar along the top, and i want to be able to drag the window by that toolbar. I still want the toolbar to be functional, but i have no earthly idea how to be able to drag the window by it. This is my current window (see the toolbar on the top):
And this is my current code to make it draggable:
case WM_NCHITTEST: {
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if(hit == HTCLIENT) hit = HTCAPTION;
return hit;
}
break;
You are on the right track with hooking WM_NCHITTEST. Now, you need to make change what constitutes a client hit versus a caption hit. If I understand your code right now, anywhere you click within the client area of the window (everything but the border) will allow you to drag the window elsewhere. This will make interacting with your application very difficult. Instead, you should be returning HTCAPTION only after you have determined that the hit was within the menubar area. Specifically, the area of the menubar that does not hold the File/Edit/Help buttons.
case WM_NCHITTEST: {
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if (hit == HTCLIENT) { // The hit was somewhere in the client area. Don't know where yet.
// Perform your test for whether the hit was in the region you would like to intercept as a move and set hit only when it is.
// You will have to pay particular attention to whether the user is actually clicking on File/Edit/Help and take care not to intercept this case.
// hit = HTCAPTION;
}
return hit;
break;
}
Some things to keep in mind here:
This can be very confusing to a user that wants to minimize, close, or move your application. Menubars do not convey to the user that you can move the window by dragging them.
If you are concerned with vertical pixels you may consider doing what other applications on Windows are starting to do -- moving the menubar functionality to a single button that is drawn in the titlebar. (See recent versions of Firefox/Opera or Windows explorer in Windows 8 for some idea to move things to the titlebar.
In one of my applications I also wanted to make the window what I call "client area draggable". Unfortunately the mentioned solution (replacing HTCLIENT with HTCAPTION)
does have a serious flaws:
Double-clicking in the client area now shows the same behaviour as
double-clicking the caption (i.e. minimizing/maximizing the window)!
To solve this I did the following in my message handler (excerpt):
case WM_MOUSEMOVE:
// Move window if we are dragging it
if (mIsDragging) // variable: bool mIsDragging;
{
POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
mIsDragging = (ClientToScreen(hWnd, &mousePos) &&
SetWindowPos(hWnd,
NULL,
mDragOrigin.left + mousePos.x - mDragPos.x,
mDragOrigin.top + mousePos.y - mDragPos.y,
0,
0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE));
}
break;
case WM_LBUTTONDOWN:
// Check if we are dragging and safe current cursor position in case
if (wParam == MK_LBUTTON)
{
POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
if (ClientToScreen(hWnd, &mousePos) &&
DragDetect(hWnd, mousePos))
{
// Check if the cursor is pointing to your new caption here!!!!
mIsDragging = true;
mDragPos = mousePos;
GetWindowRect(hWnd, &mDragOrigin);
SetCapture(hWnd);
}
}
break;
// Remove this case when ESC key handling not necessary
case WM_KEYDOWN:
// Restore original window position if ESC is pressed and dragging active
if (!mIsDragging || wParam != VK_ESCAPE)
{
break;
}
// ESC key AND dragging... we restore original position of window
// and fall through to WM_LBUTTONUP as if mouse button was released
// (i.o.w. NO break;)
SetWindowPos(hWnd, NULL, mDragOrigin.left, mDragOrigin.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
case WM_LBUTTONUP:
ReleaseCapture();
break;
case WM_CAPTURECHANGED:
mIsDragging = false;
break;
The (pseudo) code omits the return values (default: 0) and variable definitions but
should make the procedure clear anyway!? (If not drop me a line and I'll add more
or all code).
ps: I just found another comprehensive description which also explains the differences
of these two solutions: http://tinyurl.com/bqtyt3q

dialog box controls - detect changes

I want to detect when any control on a dialog box is changed by user action. For example, when data is entered in a text box, a date is entered in a date-time picker, a check box is checked or unchecked, etc. Up to now I have ignored such notifications and simply retrieved the state of the controls when the user pushes some button but now I want to know a change has taken place (I want to enable the Apply button on a property sheet). I don't really care what change has taken place, all I want to know is that something has changed. By change I do NOT mean a change in focus but some actual action by the user to change a control.
I use plain old c++, no MFC or anything fancy.
How do I go about this?
You can test whether a checkbox has been checked with the BN_CLICKED notification code which you'd get through WM_COMMAND.
switch( uMsg ) {
...
case WM_COMMAND: {
switch( HIWORD( wParam ) ) {
case BN_CLICKED: {
if( Button_GetCheck( lParam ) == BST_CHECKED ) {
...
}
break;
}
default:
return false;
}
break;
}
default:
return false;
}
return true;
That is an example of how your DialogProc might be set up. You can switch on lParam or LOWORD( wParam ) to identify which button.