Hide "Close Window" option from taskbar - c++

I want to make a window that has an icon on the taskbar, but does not have the option to be closed from there. I could simply intercept WM_CLOSE, but then a non-functional option still remains on the window's taskbar menu. There are other questions on stackoverflow pertaining to that method, but none that describe how to hide the option itself. How can I accomplish this?

The Taskbar button uses the same menu that is assigned to the window itself. There is no way to differentiate whether the menu is being invoked by clicking on the Taskbar versus clicking on the window (or even if it is being invoked by mouse or keyboard, for that matter). If you disable the "Close" item, the user would not be able to close the window at all. So just don't do it.

Related

Win32: Combobox loses focus when clicking its child window

I have a c++ Win32 application with a node-based GUI where I create a dynamic combobox with CreateWindowEx when the user presses a certain key within the GUI. I want the user to be able to click outside of the combobox Rect in order to make the combobox disappear.
To do this, I'm currently destroying the combobox inside a WM_KILLFOCUS notification of its DlgProc (so any click outside of it destroys it). However, it seems that the WM_KILLFOCUS notification is sent anytime one of its child windows gains focus. For example, if I click in the combobox's edit text region, the combobox itself loses focus since that child gains focus. Given my setup, this causes the combobox to be removed when clicking within it's Rect.
How can I prevent this behavior? Basically I want to be able to detect when anything other than the combobox or its child windows gains focus, rather than simply detecting if the combobox itself loses focus.
You can determine, whether focus moves to a different control from inside the WM_KILLFOCUS handler. This message receives
[a] handle to the window that receives the keyboard focus.
through its wParam argument.
Use the CB_GETCOMBOBOXINFO message to retrieve a COMBOBOXINFO structure, that contains window handles to all contributing windows (hwndCombo, hwndItem, and hwndList). Comparing the wParam value to all of those window handles allows you to determine, whether focus moves inside the combo box or outside.
While this answers the question that was asked, the real solution would be to handle the CBN_KILLFOCUS notification instead. It is sent to the control parent when the combo box loses keyboard focus, ignoring focus change events internal to the combo box control.

How to create multiple Dialogues?

In a Project I am using multiple dialogues so in that my requirement is while I am initiating dialog if it is modal then it should come top else it should be behind the parent window...so suggest me how to do it???
Modal dialog always come to the top of the parent window. But what is the else case? You have a non-Modal dialog that should stay behind the Parent window? This doesn't make sense to me.
But if you want to have a non-modal dialog behind the parent window (or any other window) you need to define NULL for the dialog as a parent (owner window). Than you can change the Z-order of the top level window to be behind/after the parent window (use SetWindowPos for this).
Please note that the user can always change the Z-Order of top-level windows when he clicks on it.
Remember: If the window is owned by a parent it is always on top of the owned window.

Capture mouse clicks on text boxes in a Win32 game

Using C++, I am making a Tic-Tac-Toe game using the Win32 API. To mark a square (X or O) I want the player to click the square which then changes to an X or O.
What I am doing right now is having a button click event which turns a static text box to X or O. However, when I place the button on top of the text box and make it not visible, I can't click it.
What I really need is an invisible button that still functions. So it's not set WS_VISIBLE, but you can still click it.
Is this possible or is there another way around this problem?
I can see a couple of reasonable possibilities here.
The first and most obvious would be to skip using a button at all, and just have the underlying window process the WM_LBUTTONDOWN message, and set the "X" or "O" in the correct location. For this, you don't even need static controls -- you can just detect the mouse clicks directly on the parent window, and draw your "X" or "O" in the corresponding square.
Another possibility would be a button that's marked as "visible", but happens to be transparent. IMO, this is a fairly poor choice though. To do it, you'd need to either create a transparent button control on your own, or subclass a button control to disable its drawing.
At least IMO, the obvious route would be to skip using the static control at all. Instead, just use the buttons directly -- a button normally has a caption. Start with that caption as an empty string. When the button is clicked, change its caption to "X" or "O" as appropriate. It should probably also disable itself in response to the button click, so clicking it again won't have any further effect.
There's no way to make an invisible button that still functions. Imagine all of the ways that could be abused if it were possible! Not to mention how confusing to have invisible, yet functional, UI.
What Mark Ransom posted is exactly right: you need to get your existing control to respond to mouse click events, just like a button does. Then you can do whatever you want in response to clicks. You don't need a button just to be clickable.
You say that you have a "static text box", but I'm not really sure what that is. There are text boxes (which are not static), and then there are static controls (which can display text). I'm going to assume that you have the latter.
In that case, you don't need to handle the WM_LBUTTONDOWN and WM_LBUTTONUP messages directly, which would require that you subclass the control. Although that's probably the best approach design-wise (separation of responsibilities and all that), it's also a lot more trouble.
Instead, you can handle the click events from the parent's window procedure by setting the SS_NOTIFY style for your static control (you can do this either in the Dialog Editor or in your call to CreateWindow, depending on how you create the control). This causes the control to notify its parent in four cases: when it is clicked (STN_CLICKED), when it is double-clicked (STN_DBLCLK), when it is enabled (STN_ENABLE), and when it is disabled (STN_DISABLE).
So at the parent, you need to process WM_COMMAND messages. The message you're looking for will have a HIWORD(wParam) of STN_CLICKED (indicating that a static control with the SS_NOTIFY style has been clicked), a LOWORD(wParam) corresponding to your static control's ID (set either in the Dialog Editor or specified as the hMenu parameter in your call to CreateWindow), and an lParam containing a handle to your static control.
If you use SW_HIDE, it doesn't just make the window invisible but makes it behave like that too. What you really wanted is probably just make the button transparent. I never did that, you may find this or this helpful.
You may just scrap the textbox just use the button, i mean a button-looking checkbox with ownerdraw or bitmaps. Or scrapping the button and handle the mouse events Like Mark suggests.

Use dialog controls without stealing focus

I have a modeless CDialog that contains controls, some CButtons and a CScrollbar. The CDialog is parented off of an edit box that I want to keep focus at all times. The problem is that whenever the user uses the controls, clicking a button or on the scrollbar, the control steals focus from the edit box, causing both the parent window to draw without focus (grayed-out header bar), and causing the control to take all the keyboard input. Is there a way for the controls to respond to mouse actions but not steal focus?
The controls and the dialog are all created with WS_CHILD. The controls are parented off the dialog, and the dialog is parented off of the edit box.
I've tried setting focus back after the controls are used, but that causes the parent window to flicker as it loses and then regains focus. Basically I want something that works like a combo box, where the scroll bar can be clicked or dragged around, but keyboard input still goes to the dialog itself, not just the scroll bar, and the whole thing never loses focus.
I haven't done anything like this for a long time, so I'm sure there are a million little details, but I think the starting point is to override the handling of WM_MOUSEACTIVATE.
I am a little confused about child-parent relationship you described.
Can you explain what do you mean by:
The CDialog is parented off of an edit box that I want to keep focus at all times
Any window hosting other windows inside of the client area is a parent of those windows. It is impossible to create window without WS_CHILD that is contained by other window.
Therefore all dialog’s controls are children of this dialog. It is also possible that child window hosts another child window.
CDialog is just an MFC representation of a dialog window; the same applies to other controls. For example CButton is an MFC class that wraps handle of the window’s window that is predefined as window button control.
Dialog never has focus unless is empty (does not have any controls). If dialog contains even one control, this control always has focus.
What focus means is that any given window receives mouse and keyboard messages. Only one control can have focus at any given time. In order for scroll bar to process mouse click or keyboard to move slider, scroll bar must have focus; therefore some other control must give it up.
Combo box drop box (I think this is what you are referring to) is not a child of the dialog. It is a popup window that for the duration has keyboard focus and captures mouse. When it drops down, dialog is deactivated and once dropdown hides, dialog state is changed back to active hence focus never changes, it returns to the control that had focus when dialog was deactivated.
What you are trying to do is probably possible but it would require a lot of coding. Probably hooking messages would do the job but I think it would be going against the stream.

Hide main MFC window while modal dialog is active?

I have a native C++ MFC app. It has a main window based on CWnd, and user action can create a modal dialog. While the dialog is active, I want the main window to disappear, the dialog to be visible, and the main window's icon to remain in the task bar.
How can I accomplish this?
If I hide the main window (ShowWindow(SW_HIDE)), the task bar icon disappears. If I minimize the main window (SW_MINIMIZE), the icon remains. However, since the dialog is owned by the main window, this also hides the dialog.
After the dialog is created, clicking on the task bar icon makes the dialog visible. Naturally, I do not want to require the user to do this.
Even if I insert ShowWindow(SW_SHOW) in the dialog's OnInit handler, the dialog remains not visible. Spy++ shows that its visible bit is set, though. Same is true if I add SetWindowActive to OnInit.
I am not interested in changing the UI design. While the dialog is active, the user interacts only with it, and is not interested in anything in the main window. Therefore, the main window should disappear.
Using Windows VS2005 under WinXP32.
Well, in the block of code where you create the dialog and show it modal, you can do whatever you want to the main window of your app (show/hide) as long as you make the desktop window the parent of your dialog. Usually, the constructor for CDialog and derivatives takes a default argument of NULL for the parent window in which the framework ends up substituting AfxGetMainWnd(). Instead pass CWnd::GetDesktopWindow() as the parent of your dialog and then you should probably be able to hide your main window. However, you still might have a problem with the taskbar--but I'll let someone else give hints since I know nothing offhand about it.
In OnInitDialog, add following codes
//Set windows size zero, the windows disappear.
MoveWindow(0,0,0,0);
//If you want it invisible on taskbar. add following codes.
DWORD dwStyle = GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
dwStyle &=~WS_EX_APPWINDOW;
dwStyle |= WS_EX_TOOLWINDOW;
SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, dwStyle);
You're fighting the OS. A modal dialog, by definition, disables but does not hide the "main" (parent) window. If you wanted another window, make a second one, but don't tell the OS to treat it as a modal dialog over the first window.
Perhaps you can resize the main window to a really small size and always keep it behind the modal dialog.