Qt: QMainWindow with a close, minimize and help button - c++

If I have a class which inherits QMainWindow, and I want it to only have the buttons; close, minimize and help in the window bar, how should I proceed?
If I use this code for the window flags:
setWindowFlags(Qt::Window | Qt::WindowContextHelpButtonHint | Qt::WindowMinimizeButtonHint);
It results in a window with maximize, minimize and close button.
If I exclude "WindowMinimizeButtonHint", there is only a help and close button.
How can I, if possible, make so there is a close, help AND minimize button ONLY?

According to Microsoft's documentation..
WS_EX_CONTEXTHELP cannot be used with the WS_MAXIMIZEBOX or
WS_MINIMIZEBOX styles.
which are the underlying windows system flags for Qt::WindowContextHelpButtonHint, Qt::WindowMinimizeButtonHint and Qt::WindowMaximizeButtonHint.

I don't think you can do this directly in Qt. I played around with the "Window Flags" example that ships with Qt and cannot get any combination that works.
If you really need this, you will probably have to use the Windows API directly. Here is a function I have used to enable/disable the close button in a Window. You could probably adapt it for your purposes. (Or, keep it simple and just add an extra "help" button somewhere on your form! :-))
#include "Windows.h"
#include "WinUser.h"
typedef HMENU (WINAPI*pGetSystemMenu)(HWND, BOOL);
typedef BOOL (WINAPI*pEnableMenuItem)(HMENU, UINT, UINT);
void myapp::SetCloseButtonEnabled(QWidget *target, bool enabled) {
// See msdn.microsoft.com/en-us/library/windows/desktop/ms647636(v=vs.85).aspx
QLibrary user32(QLatin1String("user32"));
pGetSystemMenu GetSystemMenu =
(pGetSystemMenu)user32.resolve("GetSystemMenu");
pEnableMenuItem EnableMenuItem =
(pEnableMenuItem)user32.resolve("EnableMenuItem");
HMENU menu = GetSystemMenu(target->winId(), false);
EnableMenuItem(menu,
SC_CLOSE,
MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
}

Related

WS_EX_TOOLWINDOW tool windows doesn't work as expected

In our legacy code Windows extended style WS_EX_TOOLWINDOW is being used.This is basically for showing the title bar narrow.But recently in the later winodws versions the title bar is not drawn as narrow.That is WS_EX_TOOLWINDOW doesnt give a narrow title bar in the newer windows versions.Making the title bar narrow is done on a click event.Let me know if there is another way of achieving this?
I have read that we need to handle WM_NCCALCSIZE.But is there any other way of doing it?.Or if this is the only way,how can I handle it in a button click?
Code Snippet:
HWND hwnd = m_hWnd;
......
DWORD dwStylesEx = ::GetWindowLong( hwnd, GWL_EXSTYLE );
if ( bNarrowTitle == true)
{
dwStylesEx |= WS_EX_TOOLWINDOW;
}
else
{
dwStylesEx &= ~WS_EX_TOOLWINDOW;
}
...
::SetWindowLong( hwnd, GWL_EXSTYLE, dwStylesEx );
MSDN says:
Certain window data is cached, so changes you make using SetWindowLong will not take effect until you call the SetWindowPos function. Specifically, if you change any of the frame styles, you must call SetWindowPos with the SWP_FRAMECHANGED flag for the cache to be updated properly.
The default look just doesn't distinguish it in any way. Which suggests that you will just have to live with it.
It's probably been changed due to not being finger friendly if smaller!
Refer : WS_EX_TOOLWINDOW doesn't give look I want
As you said, handle WM_NCCALCSIZE may be the only way to handle the size of non-client areas.
Refer: How to set the size of the Non-client area of a Win32 window (native)

How to set control focus inside an MFC custom control

Experts!
I am using a class that inherits CWnd to make the content visible using a horizontal scroll bar
The control I want to create looks like this:
However, I have some problems and leave a question
When the button receives focus, it changes to blue. If another button is pressed, the button that received the existing focus should be unfocused.
The button does not release focus as shown in the second picture.
However, the above problem occurs when implemented in Dialog, not in SDI.
I need help solving this problem.
Custom Control Create Code;
m_ScrollWnd.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, 1234);
BOOL CScrollWnd::Create(DWORD dwStyle, CRect &rect, CWnd *pParent, UINT nID)
{
dwStyle |= ((WS_HSCROLL) );
return CWnd::Create(CScrollWnd::IID, nullptr, dwStyle, rect, pParent, nID);
}
m_Button3.Create(_T("Hello3"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(0, 0, 0, 0), this, 1238);
The so called "default button handling" is done by a function named IsDialogMessage.
The easiest way to control this is to make your parent control a window derived from CDialog, or if it's a view derive from CFormView. The MFC will handle all this for you in the appropriate PreTranslateMessage handler.
If you want to do this by your own you might insert your own PreTranslateMessage handler and use IsDialogMessage. The CWnd class also has a predefined implementation named CWnd::PreTranslateInput.
So this might be sufficient:
BOOL CYourParentClass::PreTranslateMessage(MSG* pMsg)
{
// allow standard processing
if (__super::PreTranslateMessage(pMsg))
return TRUE;
return PreTranslateInput(pMsg);
}
Using CFormView / CDialog is the better way from my point of view, because also other "problematic things about dialogs" are solved in it. Including loosing and getting focus and activation...
Official document from MSDN: Dialog Box Keyboard Interface
BTW, xMRi explains it very well.

Enable maximize button in QWizard

I have a Windows application that is built on QWizard (which inherits from QDialog). It must have a working maximization button.
By default maximization button is not even visible. i have set it to show, using:
auto flags = windowFlags();
flags ^= Qt::WindowContextHelpButtonHint;
flags |= Qt::WindowMinMaxButtonsHint;
setWindowFlags(flags);
However, it shows up disabled (grayed out, non-responding).
How can i enable it?
This works for me:
setWindowFlags(windowFlags() | Qt::CustomizeWindowHint |
Qt::WindowMinimizeButtonHint |
Qt::WindowMaximizeButtonHint |
Qt::WindowCloseButtonHint);
According to the documentation, you have to use the Qt::CustomizeWindowHint to be able to change the individual hints on the min/max buttons.
Someone here says this solved his problem:
setWindowFlags(Qt::Window);
I believe that you'll get better results creating your own dialog, but if you really wanna do it, one way is use window styles (Windows only, not cross-plataform).
Wizard class example:
class wizard : public QWizard
{
public:
wizard() {}
~wizard() {}
protected:
bool event(QEvent *event)
{
#ifdef Q_OS_WIN /*Make this code Windows OS only*/
if (event->type() == QEvent::WinIdChange)
{
HWND hwnd = (HWND)winId();
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
lStyle |= (WS_MINIMIZEBOX | WS_MAXIMIZEBOX); /*Enable minimize and maximize*/
SetWindowLong(hwnd, GWL_STYLE, lStyle);
}
#endif
return QWizard::event(event);
}
};
I have this:
QWizard *wizard = new QWizard(this, Qt::CustomizeWindowHint | Qt::WindowMaximizeButtonHint | Qt::Window);
wizard->setSizeGripEnabled(true);
Running Windows 10 on my dev-box, Qt 5.5.1, working for me.
One of my pages is a big QTableWidget that ends up being like an Excel sheet of some sorts (a big page to verify and edit-in-place a lot of data). Making the window resizable and let the user maximize it if they want makes it much easier to work with, instead of having to constantly scroll in a small dialog.
Normally you would say: If you need such a big window, it probably shouldn't be in a QWizard. But in this case it's really the middle of a workflow thing. A big 'verify, edit-if-needed and continue' page so it would be weird to stop the QWizard before and then having to start another one after or something.

Setting Windows Flag on a QDialog hides the form

I currently have a form that inherits from QDialog.
Now in order to hide the ? icon on the form I am doing something like this in the constructor.
foo::foo(QWidget *parent): QDialog(parent)
{
.....
this->setWindowFlags(Qt::WindowTitleHint);
}
The problem with this is that the Dialog does not show up. If I ommit the flags line it shows up. I am using QT 5.1.1
To answer the question, here the solution:
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
If you want the minimize and maximize options, do the following:
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint) | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint);
Eventually you want to call
this->setWindowFlags(this->windowFlags() | Qt::WindowTitleHint);
To get this to work on linux I had to use both options described above:
setFixedSize(width(), height());
setWindowFlags(Qt::Drawer);
The result is a dialog with only a close button.

Notification window in Mac. With or without Qt

Qt project on Mac OS X. I need to show notification window on top without stealing a focus from any active application.
Here the widget constructor part:
setWindowFlags(
Qt::FramelessWindowHint |
Qt::WindowSystemMenuHint |
Qt::Tool |
Qt::WindowStaysOnTopHint
);
setAttribute(Qt::WA_TranslucentBackground);
Qt::WA_ShowWithoutActivating doesn't affect anything.
Is there a way to do that? I'm ready to implement the native Carbon/Cocoa solution there, but Qt is preferred.
Or maybe I'm wrong in Mac philosophy and I should notify user in a kind another manner?
Update Growl doesn't support editor line in its notifications, does it?
I did it!
#ifdef Q_OS_MAC
#include <Carbon/Carbon.h>
#endif
NotifyWindow::NotifyWindow() : QWidget(0 /* This zero is the first point */) {
setWindowFlags(
#ifdef Q_OS_MAC
Qt::SubWindow | // This type flag is the second point
#else
Qt::Tool |
#endif
Qt::FramelessWindowHint |
Qt::WindowSystemMenuHint |
Qt::WindowStaysOnTopHint
);
setAttribute(Qt::WA_TranslucentBackground);
// And this conditional block is the third point
#ifdef Q_OS_MAC
winId(); // This call creates the OS window ID itself.
// qt_mac_window_for() doesn't
int setAttr[] = {
kHIWindowBitDoesNotHide, // Shows window even when app is hidden
kHIWindowBitDoesNotCycle, // Not sure if required, but not bad
kHIWindowBitNoShadow, // Keep this if you have your own design
// with cross-platform drawn shadows
0 };
int clearAttr[] = { 0 };
HIWindowChangeAttributes(qt_mac_window_for(this), setAttr, clearAttr);
#endif
}
We get almost the same nice behavior as in Windows:
It does not stole focus on show. (Two weeks of searching over the Internet)
The controls there handle the first user click, while other windows need an extra click to activate.
When the window is being activated, the other windows of the same application, do not bubble up to the front.
And a small problem remains, but at least it has a simple workaround. Or even could be left.
Pavel,
Have you heard of Growl? Growl is a VERY impressive notification app that you can bundle and use with your application. Adium - a popular instant messaging app for OS X - uses it for all notifications.
http://growl.info/
You could implement Growl. http://growl.info/documentation/developer/
try this on mac:
setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_AlwaysStackOnTop);
Ive just tested these flags
Qt::FramelessWindowHint |Qt::WindowSystemMenuHint |Qt::WindowStaysOnTopHint
And
setFocusPolicy(Qt::NoFocus);
setAttribute(Qt::WA_ShowWithoutActivating,true);
Without Cocoa or Carbon code for window flags/masks.
And notifyWindow works like on Windows or Linux.