Label detection mouse click c++ - c++

I'm trying to build a simple API in c++. It detects which button of my mouse I click on my window and it shows a MessageBox saying which button was clicked. I also managed to show in a messageBox when I release the button of my mouse. But I can't use both at the same time.
It is possible, instead using messageBox, inserting text of which button was clicked in a label, and change it depending of which button was pressed/released?
I use a switch with differents cases for each button pressed/released. Tell me if you have something for me, would be appreciated. Can show my code if you want !

I managed to find a solution.
First declareda label.
#define ID_LABEL 1
static HWND myLabel;
Then created it.
case WM_CREATE:
myLabel = CreateWindow(TEXT("BUTTON"),TEXT("hello"),
WS_VISIBLE|WS_CHILD,50,50,150,25,
hwnd,(HMENU) ID_LABEL,NULL,NULL);
break;
And then for each button pressed/released, I edit the text. Example for when i press the left button of my mouse.
case WM_LBUTTONDOWN:
myLabel = CreateWindow(TEXT("BUTTON"),TEXT("left button pressed"),
WS_VISIBLE|WS_CHILD,50,50,150,25,
hwnd,(HMENU) ID_LABEL,NULL,NULL);
break;
And it's working. Is anyway a better way to do it ?

Related

C++ how to display text in child window at real time

This application creates a child window (which is the white box) when I right click anywhere, and destroys the child window after another right click. I have implemented the mechanics to expand and shrink the red rectangle through Direct 2D. I would like the child window to display the width and height of the rectangle at real time, as I make changes to it. I do not interact with the child window at all: it doesn't need an "x" button for closing and stuff; it just prints out a couple lines of data.
Here is what I have in my main window procedure:
case WM_RBUTTONUP:
{
DemoApp *pDemoApp = reinterpret_cast<DemoApp *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
pDemoApp->showTextBox = !pDemoApp->showTextBox; //showTextBox is a boolean
if (pDemoApp->showTextBox) {
POINTS cursor = MAKEPOINTS(lParam);
pDemoApp->child_hwnd = CreateWindowEx(
WS_EX_TOPMOST,
"LISTBOX",
"I dont need a title here",
WS_CHILDWINDOW,
cursor.x,
cursor.y,
100,
200,
pDemoApp->main_hwnd,
NULL,
HINST_THISCOMPONENT,
pDemoApp
);
ShowWindow(pDemoApp->child_hwnd, SW_SHOWNORMAL);
UpdateWindow(pDemoApp->child_hwnd);
}
else {
DestroyWindow(pDemoApp->child_hwnd);
}
}
break;
How may I go from here? I would like to know:
Is using Direct Write to draw text in the child window my only option? I see the dashed lines in the white box so I assume there must be a way to display plain text.
I used LISTBOX here, which is a predefined windows class name. How do I set a procedure for it? What else predefined class name can better suit my need? Or do I have to register a custom one;
I would like to drag the child window around, how can I set it up so that the system handles dragging for me.
Would popping a dialog box to display text be better than popping a child window?
Thanks.
Since you are using a Win32 LISTBOX control as the child window, then you have a couple of options for displaying the rectangle's dimensions in it:
give the ListBox the LBS_HASSTRINGS style, and add 1-2 items to it. Then, any time you change the rectangle, send LB_DELETESTRING and LB_ADDSTRING messages to the ListBox's HWND to display the updated dimensions as needed. A ListBox does not have a way to update an existing item, so to change an existing item's text, you have to remove the item and then re-add it with the new text.
give the ListBox an LBS_OWNERDRAW... style, and add 1-2 blank item(s) in it. Then have the ListBox's parent window handle WM_MEASUREITEM and WM_DRAWITEM notifications from the ListBox to display the rectangle's current dimensions in the item(s) as needed. Whenever the rectangle is changed, call InvalidateRect() on the ListBox's HWND to trigger a redraw.

A message box that never loses focus

A message box created with
MessageBox (NULL, "Text", "Title", MB_ICONINFORMATION | MB_SYSTEMMODAL);
stays on top of other windows, but it loses keyboard focus when the user clicks another window.
How could I create a message box (or an Edit box or a dialog box) that never loses keyboard focus, so if I try to switch to another window using [ALT-TAB] or mouse or any other method, or if another application running in a background opens its own Edit box, the keyboard focus would jump back to my message / Edit box?
The standard MessageBox function doesn't have such an option, so I tried a custom Edit box. I experimented with WM_SETFOCUS, WM_KILLFOCUS, WM_NCACTIVATE, SetForegroundWindow, SetFocus, but had no luck so far. When I open another window, the keyboard focus stubbornly goes to that window.
RegisterHotKey(0,1,MOD_ALT,VK_TAB); //disables alt+tab until message box returns
SetTimer(hwnd,1,100,0); //0.1 sec is enough for message box window creation
MessageBox(0,"Text","Title",MB_ICONINFORMATION|MB_SYSTEMMODAL); //since it's system modal, main message loop will wait for it to return
ClipCursor(0); //frees cursor
UnregisterHotKey(0,1); //enables alt+tab again
Here we use a timer to clip cursor so that user won't be able to click outside of the message box. I left title part of the messagebox outside of the clip area because clicking there negates cursor clipping.
case WM_TIMER:
{
KillTimer(hwnd,1);
RECT rc;
GetWindowRect(FindWindow(0,"Title"),&rc);
rc.top+=22; //title area left out of clip area
ClipCursor(&rc); //user cannot move their mouse outside of the message box
break;
}
This however can't block Ctrl + Alt + Del but does what you ask.

Toggle button in MFC

How to make a toggle button in MFC dialog,?
Like the one you usually used in switching on the wifi in smart phone, push like switch button and radion buttons are not my needs,
Uptil now i reached to changing the switch button to push like effect but i need the real toggle button effect as describe about those in smartphones.
Remember that it supports dragging to on from off and vice versa.... :(
You can keep 2 images that are visible when button is pressed and one when button is not pressed. Now you can use CBitmapButton::LoadBitmaps or CButton::SetBitmap to change the image everytime the button is clicked. Make sure to invalidate the button so that new image can take effect.
//load your bitmaps (in constructor if dialog)
m_wifionBitmap.LoadBitmap(IDB_WIFION);
m_wifioffBitmap.LoadBitmap(IDB_WIFIOFF);
// In turn_on_wifi()
CButton* pButton = (CButton*)GetDlgItem(IDC_WIFI_TOGGLE_BUTTON);
pButton->SetBitmap(HBITMAP)m_wifionBitmap);
// In turn_off_wifi()
CButton* pButton = (CButton*)GetDlgItem(IDC_WIFI_TOGGLE_BUTTON);
pButton->SetBitmap(HBITMAP)m_wifioffBitmap);

Scrollbar moves back after WM_VSCROLL

I have a window with its own H and V scrolling. I'm handling the event like this:
case WM_VSCROLL:
SetScrollPos(hWnd, SB_VERT, (int)HIWORD(wParam), TRUE);
break;
all I want is for the position of the scroll bar to stay once I release my mouse but what it's doing is just going back to the top after. What am I doing wrong?
Thanks
The wParam parameter of the WM_VSCROLL message is either SB_TOP, SB_BOTTOM, SB_PAGEUP, SB_PAGEDOWN, SB_LINEUP, SB_LINEDOWN, SB_THUMBPOSITION, or SB_THUMBTRACK, where the names ought to explain themselves.
SB_TOP and SB_BOTTOM means that the scrolling window is to go to the top or bottom, respectively. These messages can be sent by right-clicking a vertical scroll bar and selecting "Top" and "Bottom". (Look in Windows Notepad, Win XP+, for instance.)
SB_PAGEUP and SB_PAGEDOWN means a page (screen) up or down. These are sent if you click somwhere on the scrollbar beside on the thumb or the up or down arrows, or if you use the scrollbar's right-click menu.
SB_LINEUP and SB_LINEDOWN are sent when the user clicks the up and down buttons on the scrollbar, or selects the appropriate right-click menu commands.
SB_THUMBTRACK is sent continuously when the user scrolls by dragging the thumb of the scrollbar.
SB_THUMBPOSITION is sent when the user has released the thumb.
See the MSDN article WM_VSCROLL for more information.
So, when you receive a WM_VSCROLL message, you first need to do the scrolling itself. If, for instance, you are writing a text editor, then you need to redraw the text, but with a different row at the top of the window. Then you need to update the scrollbar to its new position, preferably by means of SetScrollInfo, but you can also use the old SetScrollPos function.
In the case section, the system is processing a WM_VSCROLL message. It will run the default window procedure after your SetScrollPos. In the default window procedure, the system itself will set the scroll bar's thumb position. So, although SetScrollPos takes effects, the system change the thumb position after that anyway. I think you should do your SetScrollPos after calling the default window procedure, i.e., maybe after returning this funciton, and then you can SetScrollPos.

How to SetFocus to a CButton so that the border and focus dotted line are visible?

I created a simple dialog-based application, and in the default CDialog added three buttons (by drag-and-dropping them) using the Visual Studio editor.
The default OK and Cancel buttons are there too.
I want to set the focus to button 1 when I click button 3.
I set the property Flat to true in the properties for muy buttons.
I coded this:
void CbuttonfocusDlg::OnBnClickedButton3()
{
// TODO: Add your control notification handler code here
GetDlgItem(IDC_BUTTON1)->SetFocus();
Invalidate();
}
But the boder in button1 is never drawn. The caret (the dotted line indicating focus) is only drawn if I pressed TAB any time before clicking button 3.
I want the button to look exactly as it looks after I click it. Showing the dotted line inside the button programatically, would be a plus.
What I want:
What I get:
Use WM_NEXTDLGCTL.
See Reymond Chen's "How to set focus in a dialog box":
void SetDialogFocus(HWND hdlg, HWND hwndControl)
{
SendMessage(hdlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, TRUE);
}
By calling UpdateWindow, the button is being redrawn before the focus change can take effect. The Invalidate should be sufficient by itself, the window will get repainted when everything settles down.
This draws the thick border around the button:
static_cast<CButton*>(GetDlgItem(IDC_BUTTON1))->SetButtonStyle(BS_DEFPUSHBUTTON);
A more elegant way to do this would be to define a CButton member variable in CbuttonfocusDlg and associate it to the IDC_BUTTON1 control, and then calling
this->m_myButton.SetButtonStyle(BS_DEFPUSHBUTTON);
This makes the button to which I'm setting the focus the default button, but note that when the focus goes to a control (inside the dialog) that is not a button, the default button is once more the original default button set in the dialog resource, in this case the "Ok" button.
I am following Joel's suggestion. But slightly different with the API used in that link, my one is :
PostMessage(WM_NEXTDLGCTL, (WPARAM)(pwnd->GetSafeHwnd()), TRUE);