I have combo box created with style CBS_DROPDOWN | CBS_HASSTRINGS | WS_VISIBLE | WS_CHILD.i want to perform some action on command cbn_closeup.But my control is not getting this event.Even in spy++ there is no cbn_closeup sent to combo box.Please somebody help me.
Not your Control gets the WM_COMMAND notification. The parent gets it. So you Need an ON_CBN_CLOSEUP in the parent window code.
If you want that your window gets the notification you Need an ON_CONTROL_REFLECT handler. But this only works if the parent window is created by the MFC too, or at least subclassed.
Related
I'm making a program to check whether the window is shown or not. I found that if I set WS_MINIMIZEBOX to the MainDlg, I can easily use IsIconic function to get the window state when I click Win+D. But if I delete WS_MINIMIZEBOX, the IsIconic and IsWindowVisible function faild. I have also tried GetWindowInfo and GetWindowPlacement, but also useless.
Is it possible to hook Win+D event? Or is there any WinAPI to get the window state.
Can I create a button without a parent in WINAPI?
I tried doing:
CreateWindowEx(0, "Button", "BTN", WS_POPUP | BS_PUSHBUTTON, 0, 0, 15, 15, nullptr, nullptr, nullptr, nullptr);
then setting the parent to a specified window later on and also showing the button using ShowWindow. This indeed created a fine looking button.
However, the button has no ID and cannot be Identified in WM_COMMAND because the ID is 0.. If two buttons were parentless, there'd be no way to tell them apart. Now if I give it an ID through the HMENU parameter:
CreateWindowEx(0, "Button", "BTN", WS_POPUP | BS_PUSHBUTTON, 0, 0, 15, 15, nullptr, 15, nullptr, nullptr);
GetLastError() prints "Invalid Menu Handle" and the button will not be created.
If I give it no parent and WS_CHILD, it will say cannot create a top level child window which is understandable.
So what I did was I set the Parent to GetDesktopWindow() and give the button an ID. That works but the button isn't parentless..
So is there a way to give a button an ID (So as to identify it in WM_COMMAND) and at the same time, have its parent NULL so that I can set the parent later? How does Windows Forms do it? The buttons can be parentless until you do Form.add(ButtonName);
Can the same effect be achieved in WINAPI?
This is appears on its face to be a very silly sort of question.
Button controls are by definition child controls, so the call to the CreateWindowEx function you use to create the button should also be specifying the WS_CHILD style.
Of course, as you mention, you cannot create a child control with no parent; you'll get an error. There is no such thing as a top-level child window.
So then, the answer to the initial question
Can I create a button without a parent in WINAPI?
is clearly no. Buttons are child controls, and all child controls must have a parent.
Just because Windows let you get away with specifying the WS_POPUP flag when you create a button control doesn't mean that it's a valid combination.
I strongly recommend re-reading the documentation for the CreateWindowEx function. In particular, note that the hMenu parameter is overloaded with respect to its meaning. If you are creating an overlapped or pop-up window (WS_OVERLAPPED or WS_POPUP), it specifies a handle to a menu. If you're creating a child window (WS_CHILD), it specifies the identifier of the child window. The fact that the same parameter is used for both things, depending on the style of the window, should tell you something.
How does Windows Forms do it? The buttons can be parentless until you do Form.add(ButtonName);
They most certainly cannot. The button controls are not created until you add them to a form or other parent control. The System.Windows.Forms.Button class constructor does not create a Win32 window. It just holds a collection of necessary styles used to create the underlying Win32 window when appropriate.
You could, of course, do the same thing by writing a C++ Button class. A simple implementation would just have member variables corresponding to the parameters of CreateWindowEx and a Create member function that would actually call CreateWindowEx to create the Win32 window once all of the members had been set. The Create method could throw an exception if one of the necessary members had not yet been set to a valid value.
I solved it. I had to pass HWND_MESSAGE as the Parent Parameter. When you call SetParent, that parameter gets changed to the Parent's handle and all is well.
No, this really is not a "solution" to the problem. As kero points out, you've simply set the button control's parent to the message-only window. Again, this might appear to work, but it's a rather strange thing to do and I hardly recommend it as a solution.
If you really want to hack it, I recommend creating your own hidden top-level window to use as a parent for your "unparented" child controls. Then you could use the same trick of calling SetParent to reparent them.
I solved it. I had to pass HWND_MESSAGE as the Parent Parameter. When
you call SetParent, that parameter gets changed to the Parent's handle
and all is well.
No, you didn't get "Parent-Less Button": the parent window of your message-only button is the "main" message-only window (class "Message").
I have a custom CWnd-derived MFC control, which works like this:
the control has its own OnPaint, and a black background
clicking anywhere on the control causes an edit control to appear at that location, borderless and with black-background, so it blends in
the user types in this box and hits enter, the box disappears and the control's custom paint functionality renders the same text in the same position on the background.
So our control owns a CCustomEdit, when you click on the background the control is either created or moved, and made visible:
CCustomEdit::Show(Rect &rc,CCustomControl *pParent)
{
if ( !::IsWindow( m_hWnd ) )
{
Create( ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | ES_NOHIDESEL | ES_CENTER | ES_UPPERCASE, rc, pParent, 999 );
}
else
MoveWindow( &rc );
}
The main parts actually work OK (and we're stuck with the approach). But one thing that's not working is that CCustomEdit self-registers for EN_CHANGE events and so on. When CCustomEdit is created as a normal dialog control (CEdit on the dialog template, DDX-bound to a CCustomEdit variable) these work, but within CCustomControl they are not.
CCustomEdit::PreSubclassWindow() calls SetEventmask() and is being called. And CCustomEdit's ON_CHAR handler is also being called for key-presses in the edit box, however the handlers for edit-box messages like EN_CHANGE are not.
Are there any obvious things like changing the style flags? Otherwise, why is my custom control stopping these events reaching the contained edit control?
I'm not sure I understand the situation, but I have a number of control that work roughly in the same way as what I think is happening and they all work, it is possible.
EN_CHANGE for the edit control is send to your CWnd-derived control. Are you reflecting the messages? Have you tried if EN_CHANGE gets to the custom control? From what you are describing, you are expecting EN_CHANGE to end up in CCustomEdit's message dispatcher macro chain automatically, but it doesn't; you need the help of the containing window. Now MFC does most of that for you in a CDialog, but if you roll your own you need to do it manually, or use the message reflection macro's.
I found it... somehow, my SetEventMask() was being overriden. I don't know how or where but when I added an extra call later on to test, most event handlers started getting called.
I can only assume some part of the init code in MFC is responsible.
I'm currently experiencing a very strange problem with a CComboBox used within a CFormView.
After adding strings to the combobox (created with WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWN | CBS_SORT | CBS_AUTOHSCROLL), I'm selecting an entry via CComboBox::SetCurSel and resize the combobox via MoveWindow in the OnSize() handler of the CFormView derived class.
As soon as I include the call to MoveWindow, the whole text in the edit part of the combobox gets selected. If I remove the call to MoveWindow, the text doesn't get selected. This happens not only for one, but for all comboboxes used.
I'm somehow lost at this point. Any hint is much appreciated!
Selecting all the text is standard Windows behavior when a combo box gets focus. I guess the MoveWindow is resetting the focus on the control.
Try using CComboBox::SetEditSel to remove the selection after MoveWindow.
I want to create custom tooltips where I can put any kind of controls. I have derived from CDialog and used the WS_POPUP | WS_BORDER styles. I also add the CS_DROPSHADOW style in the OnInitDialog to get the tooltip shadow.
Then I manage myself the WM_MOUSEHOVER and WM_MOUSELEAVE events to show/hide the tooltips.
I display the tooltip using SetWindowPos and SWP_NOACTIVATE to prevent the parent from becoming inactive and the new dialog from becoming active. But anyway, when I create the dialog using CDialog::Create method...the main window becomes inactive...what makes a very bad effect.
So my custion is how can I create a CDialog with the WS_POPUP style without my main window (or the parent window of the dialog) becomening inactive when the new dialog shows up???
Thanks for helping!
Edited: I do not use the WS_VISIBLE style to create the dialog...this this the resource:
IDD_LABEL_TOOLTIP_DLG DIALOGEX 0, 0, 100, 9
STYLE DS_SETFONT | WS_POPUP | WS_BORDER
FONT 8, "Tahoma", 0, 0, 0x0
BEGIN
LTEXT "##################",IDC_TOOLTIP_LBL_TEXT,0,0,99,9
END
The code that display the tooltip is something like that:
if(!pTooltipDlg)
{
pTooltipDlg = new MyCustomTooltipDlg();
pTooltipDlg->Create( MyCustomTooltipDlg::IDD, this);
}
pTooltipDlg->ShowWindow(SW_SHOWNOACTIVATE);
The first time (ie when the create is being call) the main windows lose the focus...the rest of them this ugly effect is not happening...so I am sure is because of the Create.
When you create your window, don't set the WS_VISIBLE flag on it. Then you can use ShowWindow with SW_SHOWNA or SW_SHOWNOACTIVATE to make the dialog visible.
Are you calling CDialog::Create() with WS_VISIBLE set? It might be that even just calling Create() is enough to take focus from the parent. It might also be worth overriding WM_SETFOCUS on your tooltip class and not calling the base class to make it impossible for the focus to change windows.
First off, consider using a CWnd rather than a CDialog. This gives you much finer control. And you are not really using any features of the CDialog anyway other than the dialog template; it is not too difficult to dynamically create your controls.
You may also want to consider, in the message handlers, handling OnShowWindow and ensure any show commands are changed to SW_SHOWNA as in Mark Ransom's comment.
Additionally, as a tooltip, it should probably have a NULL parent window.
Ok. I finally got it! I just had to return FALSE in the OnInitDialog method to avoid the dialog from being activated.
Thanks to all of you!