Detecting when a CControlBar's docking state has changed - winapi

I'm using a CControlBar-derived class and I would like to detect when the docking state of the CControlBar has changed (i.e., docking from vertical to horizontal or when it goes into floating mode).
Of course, I could handle WM_SIZE but it seems to be a waste of ressources doing the task every time a WM_SIZE message is fired instead of only when the docking state has changed.
Can anyone please point me in the right direction?

You can override the CControlBar::OnBarStyleChange virtual function to detect changes in the control bar style (CBRS_XXX values - look in the <afxres.h> header file for details).
To determine whether the control bar is floating/docked, check the CBRS_FLOATING style. To check for horizontal/vertical orientation, use the CBRS_ORIENT_HORZ and CBRS_ORIENT_VERT styles.
So, using CToolBar (which is derived from CControlBar) as an example:
class CMyToolBar : public CToolBar {
public:
virtual void OnBarStyleChange(DWORD dwOldStyle, DWORD dwNewStyle);
};
void CMyToolBar::OnBarStyleChange(DWORD dwOldStyle, DWORD dwNewStyle)
{
// Call base class implementation.
CToolBar::OnBarStyleChange(dwOldStyle, dwNewStyle);
// Use exclusive-or to detect changes in style bits.
DWORD changed = dwOldStyle ^ dwNewStyle;
if (changed & CBRS_FLOATING) {
if (dwNewStyle & CBRS_FLOATING) {
// ToolBar now floating
}
else {
// ToolBar now docked
}
}
if (changed & CBRS_ORIENT_ANY) {
if (dwNewStyle & CBRS_ORIENT_HORZ) {
// ToolBar now horizontal
}
else if (dwNewStyle & CBRS_ORIENT_VERT) {
// ToolBar now vertical
}
}
}
I hope this helps!

Related

How to reset marquee progress bar

I am running the sample code from msdn.
// Turn the marquee animation on or off.
void CCProgressCtrl_s1Dlg::OnSetmarqueeOn()
{
m_progressCtrl.SetMarquee(TRUE, nMarqueeInterval);
}
void CCProgressCtrl_s1Dlg::OnSetmarqueeOff()
{
m_progressCtrl.SetMarquee(FALSE, nMarqueeInterval);
}
This works but the problem is when marquee is off, the progress bar stays frozen at the instance. So if the moving light was in the middle at the time it will just freeze in that position. I want to reset the marquee when I turn it off but couldn't find any function for that. I tried SetPos(0) but that doesn't help either. Is there a way to reset the marquee progress bar once it has been sprang into action?
You have to remove the ProgressBar's PBS_MARQUEE window style, such as with CWnd::ModifyStyle(), before you can then change the position to whatever value you want. Enable the PBS_MARQUEE style only when you are in marque mode, and disable it when not.
void CCProgressCtrl_s1Dlg::OnSetmarqueeOn()
{
m_progressCtrl.ModifyStyle(0, PBS_MARQUEE);
m_progressCtrl.SetMarquee(TRUE, nMarqueeInterval);
}
void CCProgressCtrl_s1Dlg::OnSetmarqueeOff()
{
m_progressCtrl.SetMarquee(FALSE, nMarqueeInterval);
m_progressCtrl.ModifyStyle(PBS_MARQUEE, 0);
m_progressCtrl.SetPos(0);
}

How to override default behavior of the Zoom button in Qt?

I have an application written using Qt5 in Python (PyQt5).
I want to override default behavior of the zoom (green "+" at top left) so it will set appropriate size of the window rather than maximize it to cover all available space.
I tried to override showMaximize, but that method was never called. My window is a subclass of QWidget without any additional window flags set (i.e. defaults are used).
How can I override the event or how can I tell the layout system size I want to be set once user clicks that button?
You cannot override showMaximized because it is not virtual. There is no way to override this action. But you can override changeEvent. It will be called when user maximizes the window. You can reset normal window's position and adjust its size.
void MyWidget::changeEvent(QEvent *e) {
QWidget::changeEvent(e);
if (e->type() == QEvent::WindowStateChange) {
if (isMaximized()) {
showNormal();
resize(200, 200);
move(100, 100);
}
}
}

Click lost on focusing form

Question:
Is there a way to always let a click, that brings a form in to focus, through an have effect on the form?
Background:
With my (C# win form) application out of focus I can hover the form and get shades and borders indicating where my mouse is.
Clicking for example a menu entry (File) the form gets focus but the file menu does not get click. This takes an additional click.
For an ordinary button on the form only one click is required.
This can be fixed by setting focus before the click occurs. Se code:
class ToolStripEx : System.Windows.Forms.ToolStrip
{
protected override void WndProc(ref Message m)
{
// WM_MOUSEACTIVATE = 0x21
if (m.Msg == 0x21 && this.CanFocus && !this.Focused)
{
this.Focus();
}
base.WndProc(ref m);
}
}
This approach also works on MenuStrip
I found a few helpful articles – especially this one by Rick Brewster. The solution lies in overriding the WndProc method for the ToolStrip (or MenuStrip):
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (this.clickThrough &&
m.Msg == NativeConstants.WM_MOUSEACTIVATE &&
m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT)
{
m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
}
}

Let my MFC dialog receive keystroke events before its controls (MFC/Win32 equivalent of WinForms "KeyPreview")

I have an MFC dialog containing a dozen or so buttons, radio buttons and readonly edit controls.
I'd like to know when the user hits Ctrl+V in that dialog, regardless of which control has the focus.
If this were C#, I could set the KeyPreview proprety and my form would receive all the keystrokes before the individual controls - but how do I do that in my MFC dialog?
JTeagle is right. You should override PreTranslateMessage().
// Example
BOOL CDlgFoo::PreTranslateMessage( MSG* pMsg )
{
// Add your specialized code here and/or call the base class
if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN )
{
int idCtrl= this->GetFocus()->GetDlgCtrlID();
if ( idCtrl == IDC_MY_EDIT ) {
// do something <--------------------
return TRUE; // eat the message
}
}
return CDialog::PreTranslateMessage( pMsg );
}
Add a handler to override PreTranslateMessage() in the dialog class, and check the details of the MSG struct received there. Be sure to call the base class to get the right return value, unless you want to eat the keystroke to prevent it going further.

VisualStudio: How to add the dotted border to a UserControl at design time?

i have a user control that descends from UserControl.
When dropped onto the form the user control is invisible, because it doesn't have any kind of border to show itself.
The PictureBox and Panel controls, at design time, draws a dashed 1px border to make it visible.
What is the proper way to do that? Is there an attribute you can use to make VS add that?
There is no property that will do this automatically. However you can archive this by overriding the OnPaint in your control and manually drawing the rectangle.
Inside the overridden event you can call base.OnPaint(e) to draw the controls content and then add use the graphics object to paint the dotted line around the edge.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (this.DesignMode)
ControlPaint.DrawBorder( e.Graphics,this.ClientRectangle,Color.Gray,ButtonBorderStyle.Dashed);
}
As you can see you will need to wrap this extra code in an if statement that queries the controls DesignMode property so it only draws in your IDE.
The way that Panel does this (which suggests that this is the actual proper way of doing this) is with the DesignerAttribute. This attribute can be used for design time additions to Control-components as well as non-control components (like Timer).
When using the DesignerAttribute you need to specify a class derived from IDesigner. For a Control designer specifically, you should derive from ControlDesigner.
In your particular implementation of ControlDesigner you want to override the OnPaintAdornment. The purpose of this method is specifically drawing designer hints on top of the control, like a border for example.
Below is the implementation that Panel uses. You could copy that and use it for your control, but you obviously need to adjust the parts that specifically refer to the Panel class.
internal class PanelDesigner : ScrollableControlDesigner
{
protected Pen BorderPen
{
get
{
Color color = ((double)this.Control.BackColor.GetBrightness() < 0.5) ? ControlPaint.Light(this.Control.BackColor) : ControlPaint.Dark(this.Control.BackColor);
return new Pen(color)
{
DashStyle = DashStyle.Dash
};
}
}
public PanelDesigner()
{
base.AutoResizeHandles = true;
}
protected virtual void DrawBorder(Graphics graphics)
{
Panel panel = (Panel)base.Component;
if (panel == null || !panel.Visible)
{
return;
}
Pen borderPen = this.BorderPen;
Rectangle clientRectangle = this.Control.ClientRectangle;
int num = clientRectangle.Width;
clientRectangle.Width = num - 1;
num = clientRectangle.Height;
clientRectangle.Height = num - 1;
graphics.DrawRectangle(borderPen, clientRectangle);
borderPen.Dispose();
}
protected override void OnPaintAdornments(PaintEventArgs pe)
{
Panel panel = (Panel)base.Component;
if (panel.BorderStyle == BorderStyle.None)
{
this.DrawBorder(pe.Graphics);
}
base.OnPaintAdornments(pe);
}
}
ScrollableControlDesigner is a public class that you may or may not want to use as a base for your particular designer implementation.

Resources