Owner-draw with CTabCtrl using MFC - c++

Using VS 2015. I have a dialog-based app (NOT a PropertySheet), and have a CTabCtrl-derived object in which I want to disable specific tabs. From what I've googled, owner-draw is the way to go. Fine, can understand that.
What I would like to do is START with an owner-drawn version that acts exactly like the non-owner-drawn version, and then start tweaking it variously to experiment. For example, I'd like to use things like
void CTabControl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CTabCtrl::DrawItem( lpDrawItemStruct ); // do exactly what unmodified does
}
so that I am basically calling everything the unmodified CTabCtrl would do to accomplish the drawing. Even the simplest starting point would be helpful. What routines do I need to override or intercept to do this?
I'm setting TCS_OWNERDRAWFIXED in PreSubclassWindow() and doing what I showed above, and one or two other things, but the result definitely doesn't look the same. For one thing, no text in the tabs.
I'd really love it if I could get some pointers on where to start. BTW, I'm creating the control programatically (no dialog resources) like this (CTabControl inherits from CTabCtrl):
MyDlg::OnInitDialog()
{
...
m_tabctrl = new CTabControl();
m_tabctrl->Create( TCS_TABS | TCS_BOTTOM | TCS_HOTTRACK | TCS_FIXEDWIDTH | WS_CHILD | WS_VISIBLE, dummyRect, this, ID_TABCTRL );
...
}

Related

MFC: How can I initialise CTabbedPane tabs (dialogs) using information from the Document in a SDI?

I'm fairly new to MFC and would like to create an SDI application that has a pane of tabs always embedded on the right of the window with a view left of it. In my app I have a calculation core, with variables that are changed in the tabs with edit boxes. I would like to initialise these variables in the calculation class and then during the initialisation of the dialogs used for tabs set the initial values in the edit boxes to those of the corresponding variable in the calculator.
Currently, I create an instance of the calculator in my document class.
I also create a CTabbedPane in the MainFrame OnCreate Method as follows:
m_TabbedPane.Create(_T(""), this, CRect(0, 0, 290, 200),
TRUE,
(UINT)-1,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | CBRS_RIGHT |
CBRS_FLOAT_MULTI))
m_tab = new CParametersDlg();
m_tab->Create(IDD_TAB, this);
m_TabbedPane.AddTab(m_tab);
I would the like to be able in CParameterDlg's OnInitDialog do something like:
BOOL CParameterDlg::OnInitDialog() {
CDialog::OnInitDialog()
float value = pointerToDocument->GetCalculatorVariable();
And use value to initialise an edit box. However I can't access the document from in the main frames OnCreate as it returns null (using GetActiveDocument, AfxGetApp etc).
How can I initialise the tabs then? I have thought about trying to put the Calculator in the App class instead. Or possibly trying to initialise the dialogs somewhere else which is called later when the document is properly initialised and linked? Or should I be doing things entirely differently?
I think that CMainFrame::OnCreate() is too early in the sequence of events to access the document class, it would not normally be created yet.
It would be better to wait until the docuent is created / initialised, the document class could then call a new method in CMainFrame() passing this as a parameter to create the tabs.

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.

c++: owlnext + vcl: New Window missing its Parent

I have a Application mostly written with the owl-libary.
There I want open new vcl-windows out of the main owl-window.
This works great, though if a dialog-window is opened (even with ShowModal) and I focus another application, then the main-window get's into foreground but is blocked by the window behind it.
I guess the Problem is the missing parent-setting.
However, I can't convert owl's TWindow to vcl's TWinControl.
Is there a trick to set a vcl's parent setting to a owl's TWindow-Object?
Or could this be caused by something entirely different?
EDIT:
I'm using...
void(TWindow* parent){
Form=new TForm((HWND)parent->Handle);
Form->ParentWindow=parent->Handle;
Form->BorderIcons >> biMinimize >> biMaximize << biSystemMenu; //No minimize, no maximize, but close
Form->BorderStyle = bsSingle;
Form->Position = poMainFormCenter;
...
Form->ShowModal();
...now.
However, the new window is locked up and can not be clicked/closed/switched to.
Is there something I missed in using ParentWindow?
EDIT2:
I think it might be a Problem that the parent is a TDecoratedMDIFrame, which is a MDI-Container, so my dialog is treated like a mdi-child instead of a normal dialog...
TWinControl has a ParentWindow property for specifying a non-VCL parent window.
Also, in modern VCL versions, you can specify a ParentWnd when displaying a VCL dialog.

How to show a window before processing in MFC

How can I get a window visible before processing?
I'm trying to do something like this:
void CMyClass::OnButton1Clicked()
{
CString class_str = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL,IDC_ARROW),(HBRUSH)::GetStockObject(WHITE_BRUSH),::LoadIcon(NULL, IDI_APPLICATION));
CWnd* wnd = new CWnd();
wnd->Create(class_str,"Test",WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(0,0,100,100), AfxGetMainWnd(), 1432);
//AfxMessageBox("test"); // <- if this is executed wnd gets visible before sleep()
Sleep(5000); //this would be processing
wnd->DestroyWindow();
delete wnd;
return;
}
The window doesn't show at all. I've tried displaying it in an UI thread but it doesn't show either. If I do a message loop until window is created, it shows up but after a while the main message loop asserts.
I know it shouldn't be made like this but rather processing in worker thread, but with current code I'm working with it would require changes too big.
Disclaimer: I don't know MFC, but I know the windows API, which is what MFC was built on top of.
Perhaps you need to make a call to ShowWindow(). Also, are you handling the WM_CREATE message? If so, perhaps you are returning the wrong value.
If the above doesn't apply or make sense, disregard.

Motif main window w/o system menu, minimize and maximize boxes how? (C++)

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