Prevent screen flickering for CScrollView and CToolBar - mfc

I have a toolbar being displayed on the top of scroll view. When I call invalidate on scroll view, I realize both toolbar and scroll view are having screen flickering problem.
I try to have a workaround, by overriding their erase background event handler.
This method works for scroll view, but not the toolbar.
Here is my code snippet.
void MyCScrollView::OnInitialUpdate() {
CScrollView::OnInitialUpdate();
// ToolBar is NonFlickeringCToolBar, inherited from CToolBar
ToolBar.Create(this);
ToolBar.LoadToolBar(IDR_TOOLBAR);
ToolBar.ShowWindow(SW_SHOW);
ToolBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_SIZE_FIXED);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
}
BOOL MyCScrollView::OnEraseBkgnd(CDC* pDC)
{
// Override to prevent screen flickering. Works!
return TRUE;
}
BOOL NonFlickeringCToolBar::OnEraseBkgnd(CDC* pDC) {
// Override to prevent screen flickering. Doesn't work!
return TRUE;
}
Here is the screen shoot before I override the erase background event handler.
Here is the screen shoot after I override the erase background event handler. Not that, toolbar still keep flickering, with additional problem : its solid background gone till I swing my mouse cursor over its body.
I wish
Make scroll view and toolbar both non-flickering
Solid background for toolbar still there
Anything I had missed out?

Prevent area occupied by toolbar being redrawn.
BOOL MyCScrollView::PreCreateWindow(CREATESTRUCT& cs)
{
// Add the WS_CLIPCHILDREN style to avoid repaint problems.
// Without this, our toolbar will keep flickering.
cs.style |= WS_CLIPCHILDREN;
return CView::PreCreateWindow(cs);
}

Related

QT: shaded window effect (lights out)

I'm opening a modal window from my main window and my interest is to make the background dark so the top window is perfectly visible but the main one looks dark like in the "shade".
You can show some half-transparent widget over the mainwindow and it will create shadow effect.
For example, such widget.
class Overlay : public QWidget
{
public:
Overlay(QWidget *parent) {
setPalette(Qt::transparent);
setAttribute(Qt::WA_TransparentForMouseEvents);
}
protected:
void paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(QBrush(QColor(0,0,0, 150)));
painter.setPen(Qt::NoPen);
painter.drawRect(rect());
}
};
Then create this widget, resize and show:
overlay_.reset(new Overlay(this));
overlay_->resize(size());
overlay_->setVisible(true);
You can play with the shadow color and transperancy by changing brush in paintEvent.
Hope this is the effect you wished.
This is up to the window manager to add such effect.
For example, KWin and Mutter both have their way to handle dialogs. KWin does shade the main window, and I think Mutter does it too with some additional effect.
In Mac OS, modal window are already have special properties to put it in focus on relation of it's patent window.
The way windows handle this is by forcing the focus on the modal I think. But it really is the window manager's job, and up to the user's preference to choose what effect should be active.

CPaintDC(this) in CStatic derived class paints outside of control

As the title says.
Even with CPaintDC in the derived class the GDI drawing is not cut off.
Thanks in advance.
void CGraph::OnPaint ()
{
CPaintDC dc(this);
dc.SetViewportOrg (0, 400);
dc.SetMapMode(MM_ISOTROPIC);
dc.SetWindowExt(1000, 800);
dc.SetViewportExt(1000, -800);
// MessageBox(L"OnPaint");
ProcessData ();
DrawCoordinateSystem (&dc);
DrawGrid (&dc);
DrawGraph (&dc);
}
So, your CGraph is derived from CStatic, and the drawing code you show draws outside of the CStatic control, onto the dialog it is on? That's impossible, a control can only draw on itself. Are you sure the control isn't bigger than you think it is, and what you think is off-control actually isn't? Use spy++ to select your cstatic, it'll show you the border of the window.
Maybe what you are seeing is improper invalidation. Try dragging another window over your control, see what that does.
Otherwise, the methods to restrict the drawing area are
You manually track where to draw. Tedious.
Use SetClipRgn() to set the area to which to restrict drawing.
Not quite the same, but symptoms sometimes look similar: check the WS_CLIPSIBLINGS and WS_CLIPCHILDREN flags of your control and the dialog it's on.
Here is the way I solved the problem
CDC* pDC = GetDC();
CRect rClient(0,0,1000,800);
//GetClientRect(rClient);
CRgn ClipRgn;
if (ClipRgn.CreateRectRgnIndirect(&rClient))
{
pDC->SelectClipRgn(&ClipRgn);
}
pDC->SelectObject (PenBlack);
pDC->MoveTo (-leftMargin*zoomWidth, setPointsCorrected);
pDC->LineTo (1000*zoomWidth, setPointsCorrected);
pDC->SelectClipRgn(NULL);
ReleaseDC(pDC);

Hiding an MFC dialog box

Ok so I am using this code to hide the taskbar icon of a dialog based MFC application(VC++). The taskbar icon and the dialog box hide whenever I click on the cross or the close buttons. But I can’t get this one thing right. Whenever I hit the close or the cross button from title bar, the dialog box first flickers and shows a sort of intermediate dialog box and then hides. This is very annoying. I am posting my code here after two days of vain effort. So guys please help me. Thanks in advance.
void CMyAppDlg::OnBnClickedCancel()
{
// TODO: Add your control notification handler code here
CWnd* pWnd;
pWnd = AfxGetMainWnd();
RemoveTaskbarIcon(pWnd);
pWnd->ModifyStyle(WS_VISIBLE, 0);
mVisible = FALSE;
}
BOOL CMyAppDlg::RemoveTaskbarIcon(CWnd* pWnd)
{
LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
// Create static invisible window
if (!::IsWindow(mWndInvisible.m_hWnd))
{
if (!mWndInvisible.CreateEx(0, pstrOwnerClass, _T(""),
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, 0))
return FALSE;
}
pWnd->SetParent(&mWndInvisible);
return TRUE;
}
Here are the screen shots of dialog box. When I press the close or cross button, the dialog box which looks like this in the first place turns into this for like less than half a second and then disappears (hides).
If you show your dialog using CDialog::DoModal() the framework will make sure your dialog is shown. There is only one way to prevent a modal dialog from being shown:
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()
BOOL CHiddenDialog::OnInitDialog()
{
CDialog::OnInitDialog();
m_visible = FALSE;
return TRUE;
}
void CHiddenDialog::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
if (!m_visible)
lpwndpos->flags &= ~SWP_SHOWWINDOW;
CDialog::OnWindowPosChanging(lpwndpos);
}
I think Paul DiLascia recommended the following. This is for modal dialogs only.
The following code can be put in OnInitDialog to move the dialog off-screen. You will need to implement a method for moving it back on-screen when appropriate.
CRect DialogRect;
GetWindowRect(&DialogRect);
int DialogWidth = DialogRect.Width();
int DialogHeight = DialogRect.Height();
MoveWindow(0-DialogWidth, 0-DialogHeight, DialogWidth, DialogHeight);
The answer from l33t looks good and is probably better but this is an alternative.
Maybe an obvious thing, but what happens when you do the hide before you reparent the dialog? Also what if you don't directly modify the window style but use ShowWindow(SW_HIDE)?
Finally, have you tried switching the dialog's window style to WS_CHILD before calling SetParent() and/or maybe moving it out of the client area so that the window isn't shown any more (MoveWindow(-1000, -1000) or something like that).

Static control with WS_EX_TRANSPARENT style not repainted

I am trying to create a control that implements the per-pixel alpha blend while painting a 32-bit bitmap.
I extended a CWnd and use static control in the resource editor. I managed to paint the alpha channel correctly but still the static control keep painting the gray background.
I overwrote the OnEraseBkgnd to prevent the control from painting the background but it didn't worked. I finally managed to do it by using WS_EX_TRANSPARENT.
My problem now is that my control is placed over other control. The first time the dialog is painted all works fine...but if I click over the "parent" control (ie the one beneath my control) my control doesn't received the WM_PAINT message. So it is not painted anymore.
If I minimize the aplication and maximized it again the controls are painted again.
Please, can anybody give a hint? I am getting crazy with this control!!!
Thanks.
I would have though that if you are processing both the WM_ERASEBKGND and the WM_PAINT messages then you should have cover all the painting options, without having to resort to using the WS_EX_TRANSPARENT style.
Are you sure your code is not passing these messages on to the default processing?
One other option might be to subclass the static control, just to make sure your code is the only one handling these two messages.
BEGIN_MESSAGE_MAP(CTransparentStatic, CStatic)
ON_WM_ERASEBKGND()
ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()
BOOL CTransparentStatic::OnEraseBkgnd(CDC* /*pDC*/)
{
// Prevent from default background erasing.
return FALSE;
}
BOOL CTransparentStatic::PreCreateWindow(CREATESTRUCT& cs)
{
cs.dwExStyle |= WS_EX_TRANSPARENT;
return CStatic::PreCreateWindow(cs);
}
HBRUSH CTransparentStatic::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
{
pDC->SetBkMode(TRANSPARENT);
return reinterpret_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
}
void CTransparentStatic::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
const LONG_PTR exStyle = GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, exStyle | WS_EX_TRANSPARENT);
}

How to SetFocus to a CButton so that the border and focus dotted line are visible?

I created a simple dialog-based application, and in the default CDialog added three buttons (by drag-and-dropping them) using the Visual Studio editor.
The default OK and Cancel buttons are there too.
I want to set the focus to button 1 when I click button 3.
I set the property Flat to true in the properties for muy buttons.
I coded this:
void CbuttonfocusDlg::OnBnClickedButton3()
{
// TODO: Add your control notification handler code here
GetDlgItem(IDC_BUTTON1)->SetFocus();
Invalidate();
}
But the boder in button1 is never drawn. The caret (the dotted line indicating focus) is only drawn if I pressed TAB any time before clicking button 3.
I want the button to look exactly as it looks after I click it. Showing the dotted line inside the button programatically, would be a plus.
What I want:
What I get:
Use WM_NEXTDLGCTL.
See Reymond Chen's "How to set focus in a dialog box":
void SetDialogFocus(HWND hdlg, HWND hwndControl)
{
SendMessage(hdlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, TRUE);
}
By calling UpdateWindow, the button is being redrawn before the focus change can take effect. The Invalidate should be sufficient by itself, the window will get repainted when everything settles down.
This draws the thick border around the button:
static_cast<CButton*>(GetDlgItem(IDC_BUTTON1))->SetButtonStyle(BS_DEFPUSHBUTTON);
A more elegant way to do this would be to define a CButton member variable in CbuttonfocusDlg and associate it to the IDC_BUTTON1 control, and then calling
this->m_myButton.SetButtonStyle(BS_DEFPUSHBUTTON);
This makes the button to which I'm setting the focus the default button, but note that when the focus goes to a control (inside the dialog) that is not a button, the default button is once more the original default button set in the dialog resource, in this case the "Ok" button.
I am following Joel's suggestion. But slightly different with the API used in that link, my one is :
PostMessage(WM_NEXTDLGCTL, (WPARAM)(pwnd->GetSafeHwnd()), TRUE);