How to dock CPaneDialog to MainFrm and..? - user-interface

I have problem with CPaneDialog.
I tested with SetPaneSize MFC feature pack sample projects. What is weird is that CPaneDialog can't be docked to MainFrm while CDockablePane can be. The CPaneDialog is also a child class of the CDockablePane, but it can't be.
Only DockToWindow( &other_CPaneDialog_instance... ) is possible.
If I call DockToPane(), the content of the CPaneDialog is not drawn or refreshed correctly.
How can a CPaneDialog be docked to MainFrm window?
Another problem is about drawing. If remove codes for tree control in the SetPaneSize sample, the content of the view1 ( an instance of CDockablePane) is not redrawn properly.
After doing some experiment, I decided that something should be done in its OnSize and OnPaint method. (OnSize is more critical. ) Is this expected behaviour?

While converting an older MFC-application I ran into similar problems with the feature pack. I didn't have the time to solve it correctly, but I used following workaround:
take your dialog resource and put it in a CDialogBar class.
now derive a class from CDockablePane
in the OnCreate-method of the pane, create your dialogbar.
2 more things:
void CInputPane::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
m_pInputBar->SetWindowPos(NULL,0,0,cx,cy,SWP_NOACTIVATE | SWP_NOZORDER);
}
BOOL CInputPane::OnBeforeFloat(CRect& /*rectFloat*/,AFX_DOCK_METHOD /*dockMethod*/)
{
return FALSE;
}
This assures proper sizing of the dialog and preventing the user from dragging the bar around.
HTH, it worked for me.

Converting HexEdit to MFC9 (see http://www.hexedit.com) I ran into this problem. I tested in VS2010 (MFC10) and this bug appears to have been fixed.
Also note that this problem is not a major thing as you can just use DockToWindow in CMainFrame::OnCreate to dock to a CDockablePane (if you have one). The user can float the window or dock it elsewhere and the position will be remembered and restored when the program is re-opened.
I am pretty sure someone new about this bug in MFC9 - hence the obvious workaround in the SetPaneSize demo (calling CDockablePane::DockToWindow rather than DockPane as was used for all the other dockable windows). But at least it is fixed in MFC10.
Another bug I found is that if a CPaneDialog is floating when closed (hidden), then when you restart the application the pane is reopened, rather than being restored in the correct (hidden) state. This does not occur if the pane is docked when closed. This has also been fixed in MFC10.

Related

vb6 MDI app - when mdi form maximized it goes underneath the status bottom bar issue

I am working on an old visual basic 6 app, which has just developed an issue, It never used to have.
It is an MDI form application, which has 1 main window which has a menu at the top and status bar at the bottom, along with 2 other status like bars. It also has around 50 Child windows to go within this master frame.
When the user maximizes any child window it seems the window maximizes but does not notice the toolbars at the bottom and it maximizes below them (out of view), so the bottom of the child window does not meet up with the top of the toolbars.
I have done 4 pictures which show it is design time, runtime normal and then maximized, as you can see it hides the buttons.
I have never seen this before
I have tried to code some resizing logic to counteract this in the child Private Sub Form_Resize() event, however, it has no effect at all.
Which leaves me to believe the window resizing when maximizing is dealt with via the windows system itself, or buried deep in vb, where I can not change it.
None of the controls have changed added/deleted on the forms, and I haven't changed any form/control values as far as I remember.
I have also tried bringing the controls to the front, then back etc, no impact
I have tried changing the zindex around in all ways, no impact
Has everyone ever seen this before or have any ideas
Thank You for reading, any help would be greatly appreciated
Thanks
normal working not maxed
maxxed screen showing issue
maxxed even with top menu closed
design time vb6
A pure VB6 solution for the child form:
Private Sub Form_Resize()
If WindowState <> vbMinimized then
Begin
If WindowState = vbMaximized then
WindowState = vbNormal
Top = Me.Parent.Top + Me.Parent.TopToolbar.Height
Height = Me.Parent.Height - Me.Parent.TopToolbar.Height - Me.Parent.BottomToolbar.Height
End
The trick is not to allow maximized mode, and resize the window to fit the remaining space.
The title bar is still at the top of the MDI window, unlike the default maximize behavior.
It has been well over 10 years since I used VB6, please excuse any code imperfections.
I don't have a solution (yet), but I've been facing the same problem with an app of mine. I believe that the issue is caused by the Win-7/Win-10 virtual desktop; the VB6 app thinks it's using the whole screen, but the task bar is on a separate virtual screen, which is on top. I'll post in this thread if I get it solved...

CPropertySheet app lauched with CreateProcess steals focus [duplicate]

I was investigating an issue related to losing focus and changing activation of windows. What I found was that if I create an invisible property sheet, the active/foreground window changes and so does the focus window. Here is some sample MFC code:
// ignore CAutoDeleter, just a template that calls "delete this " in PostNcDestroy()
CPropertySheet* pSheet = new CAutoDeleter<CPropertySheet>(_T("Test Sheet"));
CTestPage* pPage = new CAutoDeleter<CTestPage>();
pSheet->AddPage(pPage);
DWORD style = WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | DS_CONTEXTHELP;
// style |= WS_DISABLED; //does nothing to help
DWORD exStyle = 0;
//exStyle = WS_EX_NOPARENTNOTIFY|WS_EX_NOACTIVATE; // does nothing to help
pSheet->Create(AfxGetMainWnd(), style, exStyle); // adding
After the call to pSheet->Create(), the active/foreground/focus window has changed and the application window is on top. If I use Spy++ and look at the window that is created, it turns out that a property sheet is a DIALOG window class. I am assuming it has a different WNDPROC, of course. What is interesting, is if I create an invisible modeless dialog using, it does not exhibit the problem. If I create the invisible modeless dialog, the active/foreground/focus window remains the same.
I tried setting various flags as in the code snippet, but alas they did not have any discernible effect--I still had the flashing and activation non-sense.
I could get some improvement by setting and clearing a hook (WH_CBT) before and after pSheet->Create()--and then eating the activation messages. When I do that, I don't have the horrible flashing and my application window does not come to the top. However, the focus (and caret for windows that have carets) does go away from whichever window had it before the Create().
Does anyone know a way to keep the focus and activation unchanged when creating an invisible property sheet? (At some point, the property sheet may or may not be set visible. And, if the property sheet is invisible when being destroyed, it also causes the blinking and activation changes.)
I tried using the values returned in GetUIThreadInfo() to try and restore things after the call to Create(), but it causes some flashing as well.
I just want to know how to create an invisible Property Sheet which won't cause the active, foreground, and focus window to change.
Unfortunately the underlying API function PropertySheet calls SetForegroundWindow on the main property sheet dialog after creation. There's no easy way around this - your kludge with the WH_CBT hook is probably your best option.
Edit: As suggested by #stephen in the comments on this duplicate question, you may be able to prevent the activation/focus change using LockSetForegroundWindow.
I have been struggling with this same issue for weeks, with a similar project, where my main application launches a secondary EXE process to act as a server in an audio application (which needs to be a separate process to shield the application from plugin faults, and so it can be high priority for real-time audio processing).
My secondary EXE is a modeless CPropertySheet, for status and diagnostic display, but is intended to be launched hidden and in the background. However it was always stealing the activation from the main application on launch, regardless of what workarounds I tried (such as overriding OnWindowPosChanging).
I thought I was going to go mad, so I was very happy to find this question. The WH_CBT trick is useful, but I found while it prevented activation of the secondary EXE, it did not prevent deactivation of the main application.
But then I discovered an excellent solution, in the LockSetForegroundWindow API (available since Win2K) which I had never heard of before. Looks like it is intended for exactly this purpose, to disable the change of foreground activation and prevent peer processes from stealing it.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
It works very well to nullify the internal call to SetForegroundWindow that happens deep within the property sheet common control, and works equally well whether used in the main application before CreateProcess or in the secondary EXE. I chose the latter case, to wrap the property sheet creation:
LockSetForegroundWindow(LSFW_LOCK);
pSheet->Create(NULL, dwStyle, dwExStyle);
LockSetForegroundWindow(LSFW_UNLOCK);
This minimises the scope of the intervention and keeps the fix localised to the process that is the source of the problem. I hope this will save others from wasting as much time on this tedious issue as I did.

Window in cascade not raised to top when selected

I have an app which creates a series of modeless dialog windows which are shown in a 'cascade. The user is supposed to be able to click on any window to bring it to the top and interact with it.
Here's a screenshot, showing this working as intended. The user has clicked on the window 3rd from the bottom, successfully bringing it to the top.
A user reports that when he runs this, and clicks on one of the obscured window then the window does not rise to the top.
Here is a video showing the problem occurring. It shows a normal cascade of notebook windows, behaving as expected. Then a cascade of my application windows appears, but the user cannot bring any selected window to the top. The selected window changes appearance, indicating that it has been selected, but it remains obscured. ( The video concludes by demonstrating a related problem, which we can probably ignore for now )
The user reports that this problem occurs on other PCs he has tried. I cannot reproduce the problem.
I am completely stumped and cannot even guess what might be causing this.
( One theory I had was that the app had frozen and was no longer responding to paint messages. However, the video shows the user dragging the obscured window out of the cascade, and then the window is painted just fine. It seems clear that the app does not get a paint message, or ignores it, when the window is selected )
The app is written using C++ and wxWidgets 2.9.4 and runs under windows 7
This appears to be a wxWidgets 2.9 issue. When built with v2.8.12 libraries, the user reports that it works fine.
Here is the code to create the windows. Note that the parent is NULL. ( This allows the main application window to be minimized without minimizing the cascade windows - a required feature. )
cNewDataPopup::cNewDataPopup( cPatDataset& data )
: wxDialog(NULL,-1,L"New data",wxPoint(200,200),wxSize(570,242),
wxDEFAULT_DIALOG_STYLE|wxSTAY_ON_TOP )
, myData( data )
{
After some experimentation, I found that adding wxDIALOG_NO_PARENT to the wxSTAY_ON_TOP 'fixes' the problem.
( The following explanation is due to VZ. )
Apparently, specifying the window's parent as NULL is not sufficient to convince wxWidgets that you want no parent. It goes ahead and assigns a parent anyway, more or less at random. This is why odd, unexpected and unreproducible behaviour is observed. The algorithm for assigning a parent was changed in v2.9.x, which is why the odd and unexpected behaviour changes when I upgraded wxWidgets. In order to convince wxWidgets that, yes, really, I do not want a parent for a window, I have to specify BOTH a NULL parent and the wxDIALOG_NO_PARENT style.
The use of wxSTAY_ON_TOP is almost certainly the culprit. If you just need the windows to stay on top of the parent window, don't use this style, either use wxFRAME_TOOL_WINDOW or override WM_SIZE handling by overriding MSWWindowProc() in your parent frame.

Big problems with MFC/WinAPI

I need to create a SDI form with a formview that has two tabs, which encapsulate multiple dialogs as the tab content. But the form has to have a colored background.
And things like these makes me hate programming.
First, I tried CTabControl, via resource editor, tried different things, but the undocumented behavior and the quirks with no answers led me into a roadblock.
After many hours of searching, I found that there is a control called property sheet, which is actually what I need.
Some more searching later, I found that property sheet can even be actually embedded onto CFormView like so: http://www.codeguru.com/Cpp/controls/propertysheet/article.php/c591
And that the dialog classes derived from CPropertyPage can be directly added as pages via AddPage method of CPropertySheet.
Great! Not quite so... Some of the controls didn't worked, and were not created, ran into weird asserts. Turns out the DS_CONTROL style was missing from the dialogs. Found it completely accidentaly on Link, no word about that on MSDN!!!! Property page must have: DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_TABSTOP, and can have: DS_SHELLFONT | DS_LOCALEDIT | WS_CLIPCHILDREN styles! Not any other, which are created by default with resource editor. Sweet, super hidden information for software developers!
The quote in comments on that page: "OMG. That's where that behavior came from...
It turns out that the PlaySound API relied on that behavior when playing sounds on 64bit machines." by Larry Osterman, who as I understand works for Microsoft for 20 years, got me laughing out loud.
Anyway, fixed that, the dialog-controls(CPropertyPages) are created as expected now, and that part looks something remotely promising, but the next part with color is dead end again!
Normally you override WM_CTLCOLOR, check for control ID or hwnd and supply the necessary brush to set the color you need. Not quite so with CPropertySheet, the whole top row stays gray! For CTabCtrl it somehow works, for CPropertySheet it doesn't.
Why? Seems that the CPropertySheet is kinda embedded inside CTabControl or something, because if I override WM_ERASEBKGND, only the internal part changes the color.
Now it seems that there is a GetTabControl() method in the CPropertySheet, that returns the actual CTabCtrl* of the CPropertySheet. But since it's constructed internally, I can't find how to override it's WM_CTLCOLOR message processing.
There seems to be a way to subclass the windowproc, but after multiple tries I can't find any good source on how to do it. SubclassWindow doc on MSDN says: "The window must not already be attached to an MFC object when this function is called."?! What's that?
I tried creating a custom CCustomTabCtrl class based on CTabCtrl via MFC wizard, created an instance of it, called SubclassWindow from one of the CCustomPropertySheet handlers to override the internal CTabCtrl, but nothing works, mystical crashes deep inside MFC.
Tried setting WindowLong with GCL_HBRBACKGROUND for the internal CTabCtrl, nothing changed.
And worst of all, I can't find any sort of useful documentation or tutorials on the topic.
Most I can find is how to ownerdraw the tab control, but this is seriously wrong on so many ways, I want a standard control behavior minus background color, I don't want to support different color schemes, windows versions, IAccesible interfaces and all this stuff, and none of the ownerdraw samples I've seen can get even 10% of all the standard control behavior right. I have no illusion that I will create something better, I wont with the resources at hand.
I stumbled upon this thread, and I can't agree with the author more: http://arstechnica.com/civis/viewtopic.php?f=20&t=169886&sid=aad002424e80121e514548d428cf09c6 owner draw controls are undocumented PITA, that are impossible to do right, and there is NULL information on MSDN to help.
So is there anything I have missed or haven't tried yet? How to change the top strip background color of the CPropertySheet? Anyone?
Your only option is to ownerdraw the tab control. It's not that hard. Well, it is frustrating because MFC doesn't tell you how to make the necessary Win32 calls.
In your CPropertySheet-derived class, overwrite OnInitDialog() and add:
GetTabControl()->ModifyStyle(0,TCS_OWNERDRAWFIXED);
This puts your CPropertySheet-derived class in charge of drawing the tab control. Add a handler for WM_DRAWITEM (OnDrawItem) and change backgroundColor and textColor to match whatever colors you wanted. Code for OnDrawItem follows:
void CPropSht::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (ODT_TAB != lpDrawItemStruct->CtlType)
{
CPropertySheet::OnDrawItem(nIDCtl, lpDrawItemStruct);
return;
}
// prepare to draw the tab control
COLORREF backgroundColor = RGB(0,255,0);
COLORREF textColor = RGB(0,0,255);
CTabCtrl *c_Tab = GetTabControl();
// Get the current tab item text.
TCHAR buffer[256] = {0};
TC_ITEM tcItem;
tcItem.pszText = buffer;
tcItem.cchTextMax = 256;
tcItem.mask = TCIF_TEXT;
if (!c_Tab->GetItem(c_Tab->GetCurSel(), &tcItem )) return;
// draw it
CDC aDC;
aDC.Attach(lpDrawItemStruct->hDC);
int nSavedDC = aDC.SaveDC();
CBrush newBrush;
newBrush.CreateSolidBrush(backgroundColor);
aDC.SelectObject(&newBrush);
aDC.FillRect(&lpDrawItemStruct->rcItem, &newBrush);
aDC.SetBkMode(TRANSPARENT);
aDC.SetTextColor(textColor);
aDC.DrawText(tcItem.pszText, &lpDrawItemStruct->rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
aDC.RestoreDC(nSavedDC);
aDC.Detach();
}
Thank you for this solution but...
The above solution works well with one tab, but when you have multiple tabs it seems rename the wrong tabs. I needed to change the if statement for GetItem to:
if (!c_Tab->GetItem(lpDrawItemStruct->itemID, &tcItem )) return;
Needed lpDrawItemStruct->itemID to get the tabs named correctly

Windows CWnd::OnLButtonDown not called as expected on double click

I'm developing an interactive MFC application which displays a 3D object using my own algorithm, essentially using MFC as a framework, but using lots of pDC->Polygon(), pDC->Rectangle(), pDC->DrawText(), etc. calls.
The UI has numerous clickable areas which all work well. However, the onscreen controls for rotating, spinning, etc. the 3D image motivate users to double click, triple click, and beyond.
I'm 99% positive that CWnd::OnLButtonDown() is not called until Windows (or whatever) has decided the operation is not a double click, or when double clicked, but only once. That is a series of clicks results in a notification every second click. The user experience is stuttered rotation. The temporary workaround is to have users move the mouse slightly between clicks—It solves the problem, but is rather unfriendly.
The application does no double click event hooking. Maybe there's a way to go further to disable potential double click processing? Or maybe there is a lower-level way to capture the mouse button down?
I think you have it backwards - the first click gets through as a WM_LBUTTONDOWN, the second one gets turned into a double-click.
To prevent a window from generating WM_LBUTTONDBLCLK messages, remove the CS_DBLCLKS style from the window.
This is all explained in the WM_LBUTTONDBLCLK documentation.
Edit: I misspoke, CS_DBLCLKS is a class style, not a window style. I don't think you can remove it, you have to create a new window class that doesn't include it. It's provided by MFC - see this page http://msdn.microsoft.com/en-us/library/a77269ff(VS.80).aspx.
Just to add an answer, this method worked for me:
WORD dwStyle = GetClassLongPtr(handle, GCL_STYLE);
dwStyle &= ~CS_DBLCLKS;
SetClassLongPtr(handle, GCL_STYLE, dwStyle);
You can use these functions to edit a WNDCLASSEX style structure for an specific window removing the double click event and correcting the single click behavior.
GetClassLongPtr
SetClassLongPtr

Resources