C# : avoids display flickering - drawing

I'm working on a C# project in which I draw on a tabPage of a tabControl several geometric form to display a music score (see picture). I update regularly the drawing. I had a flicker in the display.
To correct this, I added this function and It works :
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
But if the user has redimentioned the form, the flickering comes back. What can I do to correct this.
Thanks in advance.
[drawing][1]
[1]: https://i.stack.imgur.com/ilyMv.png

Finally, I've fix my own problem with theses lines :
tabPageLearn.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(tabPageLearn, new object[]
{
System.Windows.Forms.ControlStyles.UserPaint |
System.Windows.Forms.ControlStyles.AllPaintingInWmPaint |
ystem.Windows.Forms.ControlStyles.DoubleBuffer, true
});
With "tabPageLearn", the name of the tabPage

Related

MFC MDI CtabView hidden / remove navigation controls that are not used

I have 4 buttons that have no direct application to my program. I would like to hide or remove them. I've searched to find out what they are called...they look like navigation, left/right arrows, next/previous. I can't seem to find what they are called. I have looked on the Microsoft site and looking at the CTabView members doesn't seem to jump out and say "hey, these are what you're looking for"....
I'm hoping it is a relatively easy task. Anyone know how to just "turn them off"?
Thanks.
UPDATE:
I was able to resolve the C4430 mentioned by moving the new function before the existing in OutputWnd.h and that solved the issue in the output pane area where the arrows are now gone. What I forgot to mention is that I have another mechanism AddView that is creating 2 runtime classes and putting those into a tabbed document view. This time, I've been using GetTabControl() to make it pretty, but this also suffers from the same issue, the scroll arrows are now present.
This is what the code looks like that creates the 2 new tabs:
Above this code is the constructor/destructor/headers, nothing else.
IMPLEMENT_DYNCREATE(CTrackView, CTabView)
void CTrackView::OnInitialUpdate()
{
// add document views
AddView(RUNTIME_CLASS(CTrainView), AfxStringID(IDS_TRAIN));
AddView(RUNTIME_CLASS(CStationView), AfxStringID(IDS_STATION));
GetTabControl().EnableTabSwap(TRUE);
GetTabControl().SetLocation(CMFCBaseTabCtrl::Location::LOCATION_BOTTOM);
GetTabControl().ModifyTabStyle(CMFCTabCtrl::STYLE_3D);
GetTabControl().SetActiveTabBoldFont(TRUE);
CTabView::OnInitialUpdate();
}
I have tried to comment out CTabView::OnInitialUpdate(); but I know it won't and didn't affect the arrows. I done some searching on the control and I don't see any examples to remove the arrows, I assume another override is in order. I will follow the method shown in the other example, I am looking to see if it can be fixed similar to what has been shown.
Do these share the same CMFCTabCtrl mechanism or is this something different?
Update 2:
The OutputWnd.cpp that the MFC wizard creates has the same issue now that I've modified the tab control, I can't find the right pointer to fix the issue where &tabCtrl()is an unknown identifier. EDIT: This was the issue, I found the fix, see update 3 to see the resolution.
int COutputWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rectDummy;
rectDummy.SetRectEmpty();
// Create User Define tab style:
int UserTabStyle = AfxGetApp()->GetProfileInt(_T("Settings"), _T("UserTabStyle"), 0); //Get value from registry
// If the key doesn't exist, UserTableStyle will be 0 or FALSE;
if (UserTabStyle != FALSE && UserTabStyle <= 8) { // User selected tab style type
int EnumUserTabStyle = UserTabStyle - 1; // Fix enum if key doesn't exist.
if (!m_wndTabs.Create(static_cast<CMFCTabCtrl::Style>(EnumUserTabStyle), rectDummy, this, 1))
{
TRACE0("Failed to create output tab window\n");
return -1; // fail to create
}
}
else { // Default tabs style if Reg key does not exist i.e. new install/program reset
if (!m_wndTabs.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, 1))
{
TRACE0("Failed to create output tab window\n");
return -1; // fail to create
}
}
// Nicely hack to access protected member
class CMFCTabCtrlEx : public CMFCTabCtrl
{
public:
void SetDisableScroll() { m_bScroll = FALSE; }
};
// One-Liner to Disable navigation control
((CMFCTabCtrlEx*)&tabCtrl())->SetDisableScroll();
// Create output panes:
const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER;
if (!m_wndOutputBuild.Create(dwStyle, rectDummy, &m_wndTabs, 2) ||
!m_wndOutputDebug.Create(dwStyle, rectDummy, &m_wndTabs, 3))
{
TRACE0("Failed to create output windows\n");
return -1; // fail to create
}
UpdateFonts();
CString strTabName;
BOOL bNameValid;
//Attach list windows to tab:
bNameValid = strTabName.LoadString(IDS_STATUS_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputBuild, strTabName, (UINT)0);
bNameValid = strTabName.LoadString(IDS_DEBUG_TAB);
ASSERT(bNameValid);
m_wndTabs.AddTab(&m_wndOutputDebug, strTabName, (UINT)1);
int EnableDebugTab = AfxGetApp()->GetProfileInt(_T("Settings"), _T("EnableDebugTab"), 0); //Get value from registry
if (EnableDebugTab == FALSE)
{
OnOutputtabsDebug(); //Check to see if it should be enabled
}
return 0;
}
Update 3:
I found the answer to my unknown identifier, I was trying to call a function that didn't exist. Reformed as such and it works as expected:
// Nicely hack to access protected member
class CMFCTabCtrlEx : public CMFCTabCtrl
{
public:
void SetDisableScroll() { m_bScroll = FALSE; }
};
// One-Liner to Disable navigation control
((CMFCTabCtrlEx*)&m_wndTabs)->SetDisableScroll();
There is no public, documented API to hide those navigation buttons. However, digging into the MFC sources finds that:
the arrows are CMFCTabButton m_btnScrollLeft, m_btnScrollRight, m_btnScrollFirst, m_btnScrollLast; in CMFCTabCtrl;
they are created in CMFCTabCtrl::OnCreate whenever CMFCTabCtrl::m_bScroll is TRUE;
CMFCTabCtrl::m_bScroll is set to TRUE in CMFCTabCtrl::Create if any of the styles STYLE_FLAT, STYLE_FLAT_SHARED_HORZ_SCROLL, STYLE_3D_SCROLLED, STYLE_3D_ONENOTE, STYLE_3D_VS2005, or STYLE_3D_ROUNDED_SCROLL is used.
With that insight, the navigation buttons can be turned off in a couple of ways.
By the book: create the CMFCTabCtrl without any of the styles that enable those buttons, which leaves only STYLE_3D available. That loses the navigation buttons, indeed, but the styling of the tab control also becomes different, and the tabs themselves display as small rectangles rather than trapezoids.
Undocumented: override the CMFCTabCtrl::m_bScroll and set it to FALSE before the tab window gets created. For example, derive a class CMyTabCtrl to clear m_bScroll.
class CMyTabCtrl : public CMFCTabCtrl
{
protected:
BOOL PreCreateWindow(CREATESTRUCT &cs) override
{
m_bScroll = FALSE;
return CMFCTabCtrl::PreCreateWindow(cs);
}
};
Then instantiate the control as CMyTabCtrl m_wndTabs; instead of CMFCTabCtrl m_wndTabs;.
I remembered I solved this in the past with an One-liner.
Here a solution (hack) to direct access the m_bScroll Variable in your CTrackView::::OnCreate() function. OnInitialUpdate() comes too late as dxiv explained.
int void CTrackView::::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTabView::OnCreate(lpCreateStruct) == -1)
return -1;
// add document views
AddView(RUNTIME_CLASS(CTrainView), AfxStringID(IDS_TRAIN));
AddView(RUNTIME_CLASS(CStationView), AfxStringID(IDS_STATION));
:
:
// Nicely hack to access protected member
class CMFCTabCtrlEx : public CMFCTabCtrl
{
public:
void SetDisableScroll() { m_bScroll = FALSE; }
};
// One-Liner to Disable navigation control
((CMFCTabCtrlEx*)&GetTabControl())->SetDisableScroll();
}

How to stop CDialog(mfc) from flickering on Invalidate when updating a RichEdit20A

I have a timer that I display to the user in a RichEdit20A that is inside a CDialog.
The problem is every time I update the RichEdit20A, the screen flickers.
Since I have several RichEdit20A in my Dialog, I have a method below that I use to update them. I have tried ModifyStyle(0, WS_CLIPCHILDREN, 0);
OnInitDialog but it erases all my RichEdit20A texts. I also tried RedrawWindow(Null,Null, RDW_Erase)--Dialog still flickers and RedrawWindow(Null,Null, RDW_Invalidate)--All the text gets written on top of the old one making it unreadable.
//UpdateData(TRUE);
if(!pRECtrl)
return;
CHARFORMAT cf = {0};
cf.cbSize = sizeof(cf);
cf.dwMask = (bold ? CFM_BOLD : 0) | (italic ? CFM_ITALIC : 0) | CFM_COLOR;
cf.dwEffects = (bold ? CFE_BOLD : 0) | (italic ? CFE_ITALIC : 0) |~CFE_AUTOCOLOR;
cf.crTextColor = color;
pRECtrl->SetSel(0, -1); // Set the cursor to the end of the text area and deselect everything.
pRECtrl->Clear();
pRECtrl->ReplaceSel(text);
// Apply formating to the just inserted text.
pRECtrl->SetSel(0, pRECtrl->GetTextLength());
pRECtrl->SetSelectionCharFormat(cf);
//UpdateData(FALSE);
Invalidate();
I know that Invalidate is what is causing the flickering and that double buffering(I've never done it before) is what is used to fix this kind of issue for CViews...and I don't know what to do to stop the flickering for a CDialog, which is the window I am using for my program. Any help would be appreciated. Thank you!

QDockWidget::restoreGeometry not working correctly when QMainWindow is maximized

I have a number of QDockWidgets, all docked in a single QMainWindow.
I have overridden the showEvent, and after passing the event on to the base class I am restoring the dock widget's geometry
void DockWidget::showEvent(QShowEvent* ev)
{
QDockWidget::showEvent(ev);
QByteArray byte_array = settings_.value(id + ".geometry").toByteArray();
LOG("rest: %s", QString(byte_array.toHex()));
QDockWidget::restoreGeometry(byte_array);
}
In my QMainWindow::closeEvent I am calling saveSettings for each of my dock widgets
void MainWindow::closeEvent(QCloseEvent* ev)
{
QList<DockWidget*> dock_widgets = findChildren<DockWidget*>();
for (DockWidget* dock_widget : dock_widgets)
dock_widget->saveSettings();
QMainWindow::closeEvent(ev);
}
In my dock widget's saveSettings function I write the result of saveGeometry to disk:
void DockWidget::saveSettings()
{
QByteArray byte_array = QDockWidget::saveGeometry();
LOG("save: %s", QString(byte_array.toHex()));
settings_.setValue(id + ".geometry", byte_array);
settings_.sync();
}
Whilst this does work when my QMainWindow is not maximized, when it is maximized the widgets aren't restored correctly.
In this image I have arranged my widgets just prior to closing. (linked because inline the image will be too large)
In this image I reload my app and the widgets' geometry is incorrectly loaded.
You can see in my functions above I log the geometry string being saved and loaded.
I have proven to myself that the settings are correctly saved and restored again, but somehow it's not working correctly
close the app; save the state:
save: 01d9d0cb000200000000053f000000640000077f000001a00000053f000000640000077f000001a000000000000000000780
open the app; restore the state: (the hex data here matches the saved one exactly)
rest: 01d9d0cb000200000000053f000000640000077f000001a00000053f000000640000077f000001a000000000000000000780
close the app again, having touched nothing: (the hex data is different now, as the geometry is different, see marks below)
save: 01d9d0cb000200000000053f000000640000077f0000014e0000053f000000640000077f0000014e00000000000000000780
^ ^
This doesn't happen when the window is not maximized.
Is this a bug in Qt, or am I not using the functionality correctly?
I am using Qt 5.5 on Ubuntu 16.04.
This is a bug in Qt. Specifically, QTBUG-46620 and possibly also QTBUG-16252.
The bug report for QTBUG-46620 details a work-around, which you should try. To begin with, ensure that the main window geometry and main window state are saved when you close the application (note that you should not have to save the geometry of each dock window separately):
void MainWindow::closeEvent(QCloseEvent* ev)
{
settings_.setValue("geometry", saveGeometry());
settings_.setValue("state", saveState());
}
Then, restore the geometry as follows:
restoreGeometry(settings.value("geometry").toByteArray());
if (isMaximized())
{
setGeometry( QApplication::desktop()->availableGeometry(this) );
}
restoreState(settings.value("windowState").toByteArray());
If the you have trouble with the above work-around, you may also have to save the maximized state of the window:
void MainWindow::closeEvent(QCloseEvent* ev)
{
settings_.setValue("geometry", saveGeometry());
settings_.setValue("state", saveState());
settings_.setValue("maximized", isMaximized());
}
Then restore as follows:
restoreGeometry(settings.value("geometry").toByteArray());
if (settings.value("maximized").toBool())
{
showMaximized();
setGeometry( QApplication::desktop()->availableGeometry(this) );
}
restoreState(settings.value("windowState").toByteArray());
Note that these work-arounds may cause some warning messages to be generated on some platforms.

How to remove current Class that is running

Good day! I don't know if my title is right. please change if not :D
Anyway, I do have 3 Rectangles added to List<Rectangle> and load it up
given them a class that has event [ Paint / MouseDown / MouseUp / Mousemove ] each of them.
Now, the 3 Rectangle that has class are now currently running.
Now, when I removed 1 Rectangle in List<Rectangle>
and load it up again, the removed Rectangle still running.
How can I dispose class or classes that are currently running?
thank you!
found a solution.
public EventHandlerList DetachEvents(Component obj)
{
object objNew = obj.GetType().GetConstructor(new Type[] { }).Invoke(new object[] { });
PropertyInfo propEvents = obj.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList eventHandlerList_obj = (EventHandlerList)propEvents.GetValue(obj, null);
EventHandlerList eventHandlerList_objNew = (EventHandlerList)propEvents.GetValue(objNew, null);
eventHandlerList_objNew.AddHandlers(eventHandlerList_obj);
eventHandlerList_obj.Dispose();
return eventHandlerList_objNew;
}

MFC - Printing - Changing page orientation from a custom pagesetup dialog

I am developing a custom print dialog and page setup using MFC and VS2008 for my Win32 program. Since the code is legacy, I can't take much advantage from MFC view/doc architecture. As a result, I wrote a printing code completely from scratch.
I setup CPrintInfo, instantiate my custom print dialog box and hook this dialog box to the CPrintInfo I just created. When my custom print dialog is up, I have a radio button to let a user toggles the page orientation. For some reasons, I couldn't modify the current DEVMODE at the run-time. As a result, every page I print will end up as a portrait.
Even if I manually set pDevMode->dmOrientation to DMORIENT_LANDSCAPE from the event handler of the custom print dialog, the printing result is still ended up as portrait. I am really not sure why this is happening and how to modify the DevMode after the print dialog is up.
Thank you in advance for any help.
Here is the code I have:
void PrintSomething(CWnd* currentWnd) {
// Create CPrintInfo
CPrintInfo* pPrintInfo = new CPrintInfo;
SetupPrintInfo(pPrintInfo); // simply setup some member variables of CPrintInfo
// Create a custom print dialog
CustomPrintDlg* pCustomPrtDlg = new CustomPrintDlg(FALSE, PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS
| PD_HIDEPRINTTOFILE | PD_NOSELECTION, pPrintInfo, currentWnd);
SetupPrintDialog(pPrintInfo,pCustomPrtDlg);
if ( AfxGetApp()->DoPrintDialog(pCustomPrtDlg) == IDOK ) {
... // proceed a print loop
}
}
Code for setting up the custom print dialog:
void SetupPrintDialog(CPrintInfo* pPrintInfo,CustomPrintDlg* pCustomPrtDlg) {
delete pInfo->m_pPD;
pInfo->m_pPD = pCustomPrtDlg;
pInfo->m_pPD->m_pd.hInstance = AfxGetInstanceHandle();
pInfo->m_pPD->m_pd.lpPrintTemplateName = MAKEINTRESOURCE(IDD_CUSTOM_PRTDLG);
// Set the Flags of the PRINTDLG structure as shown, else the
// changes will have no effect.
pInfo>m_pPD->m_pd.Flags |= PD_ENABLEPRINTTEMPLATE;
// Set the page range.
pInfo>m_pPD->m_pd.nMinPage = 1; // one based page numbers.
pInfo>m_pPD->m_pd.nMaxPage = 0xffff; // how many pages is unknown.
}
When a user toggles the radio button to Landscape, this function will be invoked:
void CustomPrintDlg::OnLandscapeChecked() {
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalUnlock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
}
A pseucode for the custom print dialog class:
class CustomPrintDlg: public CPrintDialog {
... // just override some methods from CPrintDialog
};
Thanks again,
Unagi
I figured out the solution:
All I need is to call GlobalLock to obtain a pointer to the Devmode before changing the current DevMode.
void CustomPrintDlg::OnLandscapeChecked()
{
// set the current Devmode to landscape
LPDEVMODE pDevMode = GetDevMode();
GlobalLock(pDevMode);
pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
GlobalUnlock(pDevMode)
}
Thanks again for helping me.
Nowhere in your example code do you show how you're creating the DC for printing. When you call CreateDC, you must pass a pointer to a DEVMODE structure; this defines whether the printing will be portrait or landscape.