Creating a ruler bar in MFC - c++

What's the best way to go about creating a vertical and horizontal ruler bars in an SDI app? Would you make it part of the frame or the view? Derive it from CControlBar, or is there a better method?
The vertical ruler must also be docked to a pane and not the frame.
To make it a little clearer as to what I'm after, imagine the vertical ruler in the Dialog Editor in Visual Studio (MFC only). It gets repositioned whenever the tree view is resized.

I would not use control bars. I have no good reason other then (IMOHO) are difficult to get to do what you want - if what you want if something other than a docking toolbar.
I would just draw them directly on the View window using GDI calls.
I guess I might think about making each ruler its own window, and draw the rulers on their own window. I would then create these two CWnd derived classes in the view and position as child windows. This is good if you want to interact with the mouse on these rulers (easier to sort out what messages are for the rulers).

I ended up deriving the ruler from CWnd as you suggested and skipping the control bar route. This code works in either case:
m_wndSplitter.CreateStatic(this, 1, 3);
m_wndLeftPane.Create(&m_wndSplitter,WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(0, 0));
m_ruler.Create(&m_wndSplitter,WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(0, 1));
m_wndSplitter.CreateView(0, 2, pContext->m_pNewViewClass, CSize(300, 0), pContext);
SetActiveView((CScrollView*)m_wndSplitter.GetDlgItem(m_wndSplitter.IdFromRowCol(0, 2)));

Related

What is the best way to create custom menu with WinAPI

Since there is no way to deep customizing (a gradient background for example) win32 controls (such as buttons, menu items e.t.c) many people advise to create an own custom control.
And if I need a custom button I will use WM_MOUSEMOVE, WM_LBUTTONDOWN and a shadow buffer. I will draw all controls on the shadow buffer and then use BitBlt(hDC, ...) for my window.
But if I want to create a custom menu I must to foresee that menu can be drawn outside of the client area.
At first I need to mouse tracking outside of the client area. SetCapture(hWnd) seems to be a bad solution as it blocks mouse tracking for windows below.
Then I need to draw/erase items outside of my window. Erasing with InvalidateRect(NULL, NULL, TRUE/FALSE) seems to be a bad solution too as it cause of blinking.
What is the best approach to create custom menu with WinAPI?
Runtime menus that can appear anywhere on the screen can be shown with TrackPopupMenu() function. Create the menu with CreateMenu(), AppendMenu() etc, then show it with TrackPopupMenu().

Suggestion wanted for MFC custom scrollbars

I want to make my own scrollbars for a custom drawn plot, like this image, what would be the best way to go?
Scrollbars should:
Only be visible when mouse hover over it (with fade in/out)
Be a part of the x/y axis of the plot, like in the picture
Not have any arrow buttons, just the thumb Thinner than the normal scrollbars
Would you suggest to:
Create everything from scratch, handling paging, scrollwheel etc.
Try to inherit CScrollBar and do my own drawing?
From what I've read, it's not very easy to customize scrollbars in MFC, for example here)
First off, these have to be scrollbar (or other) controls, not window scrollbars (used for scrolling a window).
Second, the statement "it's not very easy to customize scrollbars in MFC", is only partially true. MFC is a "thin wrapper" of Windows API, so you should better refer to the documentation of the Windows scrollbar control.
Then there is the CScrollBar class, but took a short look, and indeed, it does not really offer anything more than the Windows scrollbar does. As for the sample in the link you posted is a new (custom) control (painting everything on its own), i.e. literally "from scratch", not inheriting anything from CScrollBar.
So, you have to look into the Windows scrollbar control, and what it offers. Did take a look, and saw few things. Unfortunately there seems to be no owner-draw functionality. You can process the WM_CTLCOLORSCROLLBAR message, but this only allows you to change colors.
And according to the documentation the background color only. This appears to be the only possible customization, apart from the SBM_ENABLE_ARROWS message, which can hide the arrows. And no fading effect. If these are enough to you, you could try the Windows/MFC scrollbar, otherwise try writing your own.

Black highlight bar with GDI

I got some nice splitter code for my GUI but I can't get the pen/brush/whatever it is I need to do proper highlighting. You know how in visual studio 10, the splitter bars can be dragged and there's a beautiful black transparent bar letting you know where the split will happen when you lift up your mouse button. Here's a picture: http://www.freeimgshost.com/fullsize/efmcxyyu1wbyb1r7mz0.png
How can I achieve that black highlight bar using solely GDI and c++?
The Visual Studio UI is implemented in WPF, so I'd guess that the splitter bar is just a semi-transparent filled rectangle.
However, GDI has fairly poor support for transparency.
You could get the same effect using a semi-transparent, always-on-top, layered window. This is a simple solution because you don't have to worry about repainting anything. You just move the window about.
This answer to another question has some code that creates such a window (for a different purpose).
This is probably one of the correct uses for LockWindowUpdate().
On Mousedown, lock the window, and start drawing the drag bar directly. As the mouse is still captured, the drag bar will still receive mouse notification. On mouseup, unlock the window, resize and let the drawing carry on as normal.

Displaying a popup widget in QT over application border

Let's say that I have an application frame, and I want to show a popup QCalendarWidget over on the right side of the frame. Normally, QT will clip the edges of the QCalendarWidget, cutting it in half and not displaying the rest, as it would be over the right side border.
Is there a way to work around this limitation without resorting to implementing a QDialog?
I want the widget to be visible outside the bounds of it's container.
If you'd show your Calendar, let's say, after a button click, as QDateTimeEditor does, it's contents will not be clipped, cause it do not belong to frame. It will be just a widget, that shows in a dialog manner. And maybe you should even place it in QDialog, that is modal and provides some convenience methods, rather then simple QWidget.
Btw, why don't you want to use QDatetimeEditor?

Docking a CControlBar derived window

How can I dock a CControlBar derived window to the middle of a splitter window (CSplitterWnd)? I would like the bar to be repositioned whenever the splitter is moved.
To make it a little clearer as to what I'm after, imagine the vertical ruler in the Dialog Editor in Visual Studio (MFC only). It gets repositioned whenever the tree view is resized.
Alf,
In case of VS, there's no splitter used:
The resource view is a resizable ControlBar (It looks and feels like a splitter but it isn't a CSplitterWnd).
The rest is a child frame (either tabbed or MDI. Go to Tools/Options/Environment/General and choose Multiple Documents to convince yourself). The ruler is part (controlbar?) of the child frame.
In your case, I think you don't want a 3 panes splitter. You need a 2 pane splitter and the control bar should be part of your view (it wouldn't be a CControlBar per se). Unless you use MDI in which case you can make it a true ControlBar in your child frame.
HTH
Serge,
I apologize, I wasn't very clear. The splitter would be between the resource view and the ruler bar. It would looke like this:
Resource View | Vertical ruler | View
In any case, I found the (now obvious) answer: split the main frame into three windows:
m_wndSplitter.CreateStatic(this, 1, 3);
m_wndLeftPane.Create(&m_wndSplitter,WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(0, 0));
m_ruler.Create(&m_wndSplitter,WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(0, 1));
m_wndSplitter.CreateView(0, 2, pContext->m_pNewViewClass, CSize(300, 0), pContext);
SetActiveView((CScrollView*)m_wndSplitter.GetDlgItem(m_wndSplitter.IdFromRowCol(0, 2)));