What's wrong with this CreateWindowEx function? - c++

Okay, so first a little overview of what I am tryna do..
I am trying to create 3 child window in a main parent window, and use EnumChildWindow and EnumChildProc to enumerate them, I want to create 3 child windows of same height as of parent but 1/3rd width, and align them one after the other..
So, I captured the WM_CREATE msg to create those child window, and WM_SIZE to move and align them using MoveWindow, everything is fine except for the fact that no child window is created. When I debugged it, I found that (in the Autos Window in Visual Studio 2008, while debugging) my CreateWindowEx statement is not getting executed (the autos window said "Expression cannot be evaluated."
Here's the statement:
CreateWindowEx(0, (LPCWSTR)("childClass"), (LPCWSTR)NULL, WS_CHILD | WS_BORDER, 0, 0, 0, 0, hWnd, (HMENU) (int) (ID_FIRSTCHILD + 1), hInst, NULL);
of course I was using it in a for loop to create 3 windows, but that's the other thing...
So, can anyone please help/guide/advice me what is going on in here? Or what am I doing wrong?
ps: I am reading this ebook from where I got this code and all, so please don't ask me to adopt another approach or something, say put the Child creation code somewhere else or so... because I am not making any program, but just following a book's example... :)

My psychic powers suggest you need to pass in the WS_VISIBLE style to the CreateWindow call above for your child windows - so you can seem them. :)
My development experience suggests the following:
What is the return value of CreateWindowEx? Did you assign the return value to a variable. And if so, did you set a breakpoint on that line in the debugger? And if the return value from CreateWindow is NULL, then what is GetLastError (which you can evaluate in the debugger as "#err").
After your main window pops up (with the children invisible), did you run Spy++ to see if the child windows exist? What is their state?
Otherwise, did you validate that the WM_CREATE callback of the WndProc of your child window class is getting called?

Related

Hiding the new Windows Terminal

I used to hide my background app's console window until I needed it with
ShowWindow(console_hwnd,SW_HIDE);
My Windows got an update and switched to "Windows Terminal" as the default console app.
That line of code doesn't work anymore it just minimizes the console to taskbar. What is the proper way to fully hide Windows Terminal?
EDIT:
Please read the question carefully. It says HIDE the console window. NOT remove the console completely. I need to be able to show it again later. Thats the purpose of SW_HIDE and SW_SHOW that are no longer working with the new Windows Terminal.
If you want to show the console at any time, you could hide and show the console by changing the coordinates of the console.
int main() {
HWND consoleWindow = GetConsoleWindow();
SetWindowPos(consoleWindow, 0, -600, -600, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
return 0;
}
EDIT:
According to this document, the second parameter to ShowWindow() might get ignored the first time it is called. Try calling it twice.
ShowWindow(hWnd, SW_HIDE);
ShowWindow(hWnd, SW_HIDE);
In addition, did you run this program as administrator? If so, I suggest you cancel it, since the window is in a higher privileged process, so your call will be ignored.
Hope it helps.

How to remove TOPMOST attribute from a window

I have a Windows C++ app that creates two separate windows
I need to be able to make one window topmost temporarily, and then later remove that attribute so that other windows can then overlay it.
I've tried this code:
void setWindowAlwaysOnTop(const std::string& windowTitle, bool onTop) {
HWND hwnd = FindWindowA(NULL, windowTitle.c_str());
HWND insertAfter;
if (onTop) insertAfter = HWND_TOPMOST; //set the window always-on-top
else insertAfter = HWND_BOTTOM;
SetWindowPos(hwnd, insertAfter, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
}
But if I have previously called this code with onTop true it doesn't re-allow other windows to overlay the target window after I call it with onTop false.
I've also tried calling the function from the target window itself rather that from a separate window but it still doesn't work.
As far as I can see at https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setwindowpos it should work?
Is that correct, or is there another way of achieving this?
The documentation link that you provide in the question indicates that you should pass HWND_NOTOPMOST to hWndInsertAfter. Of this flag it says:
Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.
Use SetWindowLongPtr.
This function will discard your window styles, but u can restore them, like the example
below:
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); //Discard WS_EX_TOPMOST
IMPORTANT NOTE:
To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetWindowLongPtr. When compiling for 32-bit Windows, SetWindowLongPtr is defined as a call to the SetWindowLong function.
Hope this works.

Flags Windows 7 window always on top INCLUDING the Win7 taskbar (Custom error)

I know a few flags that make the window always on top (eg Qt :: ToolTip, Qt :: WindowStaysOnTopHint, Qt :: Popup), but each time the method is the same problem.
By clicking on the start menu, the area tray, empty field between programs and tray - window and so is hiding.
Everything is fine when I switch between different applications and I click anywhere except the above-mentioned places.
Just run other applications that I used to use, so it might be a function of the uninvited Windows.
Code does not make sense given, because at the same time where do dumb mistake, and indeed act as a flag to be apart of this "small" problem.
These things work:
HWND hWnd = reinterpret_cast(this->winId());
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
But it turns out that exactly the same as the flag of the subject. : (
Explanation of what exactly is the problem:
http://youtu.be/k5TCtr1hPKY
The solution is, regular exercise such thing:
if(this->isActiveWindow() == false} {
this->raise();
}
Only the minimized window does not always work, but to me it is unnecessary.

Parent-Less Button

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").

How do I get a handle to the Start button in Windows 7?

I use:
Hwnd hStart = ::FindWindow ("Shell_TrayWnd",NULL); // get HWND of taskbar first
hStart = ::FindWindowEx (hStart, NULL,"BUTTON", NULL); // get HWND of start button
to get start button's handle. It's running properly on Windows XP,
but in Windows 7, ::FindWindowEx (hStart, NULL,"BUTTON", NULL) always returns 0, and GetLastError() returns 0, too.
Why is that?
In Windows 7 the start button, which has class name "Button", is a child of the desktop window. Your code assumes that the start button is a child of the window named "Shell_TrayWnd" which does indeed appear to be the way the taskbar and start menu were implemented on XP.
For Windows 7 you want to use something like this:
hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", NULL);
Although I think it would be better search for it by name to be sure that you get the right button.
hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", "Start");
I'm not sure how Vista implements its taskbar and start menu, but you can use Spy++ to find out.
Having said all of this, it would be much better if you can find a way to achieve your goals without poking around in such implementation specific details.
::FindWindow (L"Shell_TrayWnd",NULL);
this code is for complete taskbar