When I add the BS_AUTO3STATE style to a default-styled checkbox on a dialog window like so at runtime;
this->Style |= BS_AUTO3STATE; // wrapper of Get/SetWindowLongPtr, ignore the specifics
.. it turns into a group box rather than a 3-state checkbox. What am I doing wrong?
Have I got the wrong control style?
This problem is caused by the fact that the BS_Xxx values are not actually defined in the headers to work as bit flags. Instead, their values just increase linearly:
#define BS_PUSHBUTTON 0x00000000L
#define BS_DEFPUSHBUTTON 0x00000001L
#define BS_CHECKBOX 0x00000002L
#define BS_AUTOCHECKBOX 0x00000003L
#define BS_RADIOBUTTON 0x00000004L
#define BS_3STATE 0x00000005L
#define BS_AUTO3STATE 0x00000006L
#define BS_GROUPBOX 0x00000007L
#define BS_USERBUTTON 0x00000008L
#define BS_AUTORADIOBUTTON 0x00000009L
// ... and so on
Note that BS_GROUPBOX (which is the style you're getting and don't want) is equal to 0x7. Your control is ending up with that style flag set because you're setting a combination of flags that works out to have a value of 0x7. Unfortunately, you can't just OR the flags together and get the result you desire.
Instead, you'll have to clear out the current button style using the BS_TYPEMASK flag and then set the individual BS_Xxx flag that you desire. For a normal checkbox, that is probably BS_AUTOCHECKBOX; for a 3-state checkbox, that is BS_AUTO3STATE.
Working sample code:
void ToggleCheckboxCtrl(HWND hwndCheckBox)
{
// Retrieve the control's current styles.
LONG_PTR styles = GetWindowLongPtr(hwndCheckBox, GWL_STYLE);
// Remove any button styles that may be set so they don't interfere
// (but maintain any general window styles that are also set).
styles &= ~BS_TYPEMASK;
// Just for example purposes, we're maintain our last state as a static var.
// In the real code, you probably have a better way of determining this!
static bool isRegularCheckBox = true;
if (isRegularCheckBox)
{
// If we're a regular checkbox, toggle us to a 3-state checkbox.
styles |= BS_AUTO3STATE;
}
else
{
// Otherwise, we want to go back to being a regular checkbox.
styles |= BS_AUTOCHECKBOX;
}
isSet = !isSet;
// Update the control's styles.
// (You'll also need to force a repaint to see your changes.)
SetWindowLongPtr(hwndCheckBox, GWL_STYLE, styles);
}
The Spy++ utility (bundled with Visual Studio) is an indispensable little utility for figuring out what is going wrong when toggling window styles. Run your app, and use Spy++ to locate the window and enumerate its current styles. Then change the styles, dump the new styles with Spy++, and see what went wrong.
Related
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)
I wanted to "play around" with new extended styles, especially the ones that manipulate with checkboxes.
The problem is that none of them seem to work.
I can not determine if TVS_EX_DOUBLEBUFFER works or not, because my treeview is small. I haven't tested TVS_EX_RICHTOOLTIP yet. Apart from that, no matter what other style I set, I am unable to see any effect.
Here is the relevant snippet:
HWND hwndTV = CreateWindowEx(...);
// first, add checkboxes
DWORD dwStyle = GetWindowLong(hwndTV, GWL_STYLE);
dwStyle |= TVS_CHECKBOXES;
SetWindowLongPtr(hwndTV, GWL_STYLE, dwStyle);
// now add extended window styles
HRESULT h = TreeView_SetExtendedStyle(hwndTV,
TVS_EX_PARTIALCHECKBOXES, TVS_EX_PARTIALCHECKBOXES);
// insert items...
I have checked the return value of the TreeView_SetExtendedStyle macro and it did not fail, which increases my frustration even more.
QUESTION:
Can you show me how to properly apply extended styles? For example, how to properly set TVS_EX_PARTIALCHECKBOXES or any other?
Thank you.
There's nothing wrong with how you're setting the style - it's when you're setting it that's the problem.
You need to set the TVS_EX_PARTIALCHECKBOXES extended style before you set TVS_CHECKBOXES. This is because setting TVS_CHECKBOXES triggers the creation of a state imagelist for the treeview, and this imagelist only includes the "partial" images if the partial style is set at the time it's created. The imagelist isn't recreated automatically if TVS_EX_PARTIALCHECKBOXES is set later on.
Additionally, you can't specify TVS_CHECKBOXES in the call to CreateWindowEx if you want to use the partial checkboxes style, since there's no way to set TVS_EX_PARTIALCHECKBOXES until the control has been created.
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.
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));
}
How do I create a Motif main window that doesn't have a system menu, minimize and maximize boxes? I just cannot find out how by googling and reading docs and tutorials. I believe that it should be possible with some additional parameters for XtVaCreateManagedWindow, but which?
I have tried several variants of XtVaSetValues (topWid, XmNmwmDecorations, ...) but none worked. Instead I get an error message that I need to use a vendor shell for this. Most widget types aren't derived from vendor shells however, and when I e.g. try to use a dialog shell and put a scrollable text widget inside of it, then then text widget seems to control the dialog.
Apparently it's not (easily) possible to get rid of the window (system) menu, but it seems to be possible to disable window menu items with some code like this:
int i;
XtVaGetValues (widget, XmNmwmFunctions, &i);
i &= ~(MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE);
XtVaSetValues (widget, XmNmwmFunctions, i);
which removes the related window decoration too and apparently even works for non vendor shell widgets.
There should also be the possibility to remove the decorations (i.e. make them invisible). However, please note that these "system menu" decorations belong to the Window Manager, not your Motif program itself. It is up to the Window Manager to handle your requests or disregard them--you might get vendor-specific behavior with any MWM resources.
Anyway, here's the code sample to try out:
int decors; //bit-mask of flags defining the decorations, from Xm/MwmUtil.h
XtVaGetValues(dlg, XmNmwmDecorations, &decors, NULL);
decors &= ~MWM_DECOR_MENU;
decors &= ~MWM_DECOR_MAXIMIZE;
decors &= ~MWM_DECOR_MINIMIZE;
XtVaSetValues(dlg, XmNmwmDecorations, decors, NULL);
If you intend to run your application from Mwm, you can achieve the desired behavior by setting (e.g. via XtVaAppInitialize()) the following X11 resources:
! Title bar buttons
Mwm*YourApplicationClassHere.clientDecoration: -minimize -maximize
! Window menu functions
Mwm*YourApplicationClassHere.clientFunctions: -minimize -maximize
These resources are explained in more detail here and here.
Speaking of window menu, this one depends on a specific window manager in use. Mwm, for instance, allows the client to set the menu name using Mwm*YourApplicationClassHere.windowMenu resource, the menu itself must be defined in either ${HOME}/.mwmrc or global mwmrc, or XmNmwmMenu resource of VendorShell. The resulting custom window menu is exposed as a _MOTIF_WM_MENU atom, which seems to be ignored by modern window managers.
Sample mwmrc menu definitions may look like this
Menu CustomMenu0
{
Restore _R Alt<Key>F5 f.restore
Move _M Alt<Key>F7 f.move
Size _S Alt<Key>F8 f.resize
Minimize _n Alt<Key>F9 f.minimize
Maximize _x Alt<Key>F10 f.maximize
Lower _L Alt<Key>F3 f.lower
no-label f.separator
Pass\ Keys _K f.pass_keys
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
Menu CustomMenu1
{
Your\ Application\ Name\ Here f.title
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
(see the function descriptions). Custom menu items can be added using f.send_msg (examples here and here).
I'm pretty sure all of the above also applies to Dtwm (CDE).