How to Scroll CEdit(MFC) smoothly - mfc

I want a multiline CEdit control to scroll itself downside slowly like a rolling subtitle.
So far, I use CEdit::LineScroll() in OnTimer() event. It can do a full line roll with is not as smooth as I expected.
I try to replace LineScroll() by ScrollWindow() so that I can scroll the text by pixels however the ScrollWindow() function don't draw the new text lines which should be scrolled into the control.
Anyone have any idea on how to achieve this?
In case I did not describe the issue clear. I add these gifs:
What LineScroll() do (and I just need it smoother):
And this is what ScrollWindow() do (the following text is cut):
Here is the code of ScrollWindow():
CRect clientRect;
m_editAns.GetClientRect(&clientRect);
m_editAns.ScrollWindow(0, -10, NULL, &clientRect);
m_editAns.UpdateWindow();
ValidateRect(&clientRect);
*PS: The project uses the CEdit control else where so I can't replace it by another control, though inheritance is acceptable.

According to CWnd::ScrollWindow,
To repaint the uncovered area at the same time the scrolling is done,
call the UpdateWindow member function immediately after calling
ScrollWindow.

Related

How can I erase the window background in an owner drawn static control?

I am currently developing a kind of "WinMerge" clone, and currently I am trying to implement a custom scrollbar which should later represent both compared files as a rectangle in the background each.
This is what it looks like at the startup:
However, after scrolling around a little bit, this is what I end up with:
As you can clearly see, only those parts look correct which I explicitely paint over in my paint routine:
void LocationPane::OnPaint(CDCHandle dc)
{
DefWindowProc();
dc = GetDC();
DrawLocationPaneFigures(dc);
}
This is how my control is configured in my .rc file:
CONTROL "",IDC_LOCATIONPANE,"Static",SS_OWNERDRAW | SS_NOTIFY | WS_BORDER | WS_GROUP,7,21,91,541
As you can see, it is an owner drawn control.
How can I erase the background for this control while repainting it?
A static control with SS_OWNERDRAW style receives a WM_DRAWITEM message when it needs to be redrawn.
So first you need to replace your OnPaint() handler by a handler for WM_DRAWITEM. Instead of calling GetDC() use the device context supplied to you in the DRAWITEMSTRUCT.
To erase the background it's generally best to do it as part of the regular painting code to reduce flickering (by calling FillRect() for instance).
I suggest to always draw the whole client area of your control. Then you may handle WM_ERASEBKGND to return TRUE without calling DefWindowProc() to reduce flickering even more.

How To Capture Mouse Movement Over Caption Bar In C++ Win32?

I have my own custom painted caption bar for a window. I have also painted a bitmap on this bar which I want to know when someone hovers over it with the mouse cursor. I have handled the WM_NCMOUSEMOVE message but this seems to only be triggered over the borders and not my caption area itself.
How can I detect when the mouse is over a certain area of the caption bar?
This is with Visual C++ 2010.
Update:
I have worked out the problem to an extent. I (deliberately) do not have the WS_CAPTION style set on the window and instead I handle the WM_NCCALCSIZE and manually adjust the size of the non-client area - shifting it down by 20 pixels in this case. This means that the area that I am "forcing" as a non-client area does not get WM_NCMOUSEMOVE messages but neither does it get WM_MOUSEMOVE messages either. One way round it is to force the WM_CAPTION style, get rid of my custom code on WM_NCCALCSIZE but this isn't ideal. Is there a way round it?
Update2:
It is the same problem with WM_NCHITTEST messages. The area does not get these triggered unless I have WS_CAPTION style set which I don't want. Also it is somehow affecting the client area in that it no longer gets WM_LBUTTONDOWN messages.
I am not quite positive what you mean, but I think you are saying you want to check for a certain section of the caption bar being moused over. if so, then maybe try tracking window size and position, and then check to see if, relative to your window position and size, that section of the bar would be moused over (in pixels). This is the only way I can think of that doesn't use OS specific functions, which I try my best to avoid.

change background colour in parent window

I'm very new to win32api programming. I have 3 questions.
how to change the background colour in the parent window. i did it as folows but it dont work
wClass.hbrBackground=(HBRUSH)(RGB(255,255,255));
second question is, I use to add text in the window as follows. the text is in bold font and with a background colour. I want the text to be in normal and without background colour.
PAINTSTRUCT ps;
HDC hDC;
char szBuffer[]="Hello, World!";
hDC=BeginPaint(hWnd,&ps);
TextOut(hDC,10,10,szBuffer,strlen(szBuffer));
third question is how to add group boxes in the parent window. i searched it in the internet but this was discribed how to add group boxes on dialog boxes using resources.
pls some one help me with these isue...
> wClass.hbrBackground=(HBRUSH)(RGB(255,255,255));
I suppose the class structure requiers the handle of the brush, not the color value itself (but I'm not sure). Something like this:
wClass.hbrBackground=(HBRUSH)(CreateSolidBrush(RGB(255,255,255)));
To make the text background transparent use special WinAPI function, SetBkMode(TRANSPARENT); (Oof, spend some time to remember it's name:) ).
In most tasks it will be much better to make a dialog resource and use it like an ordinary window (drawing smth in it, putting simple windows in which you draw, etc) than take an ordinary window and try to add dialog controls in it. It became a common practice since WinForms and then WPF - every window in them is a "form" in which you can add controls, draw in it and so on.
I'm trying to remember if Microsoft put in code to clear the client area. I know at the minimum, you can get the client rect and then use that to base a drawRect() command to the whole client area. You also may have to trap the command to erase the background

Avoid Flickering on a dialog that moves its controls on resize

I have a popup dialog( CDialog ) that handles WM_CTLCOLOR message to color itself. It is having some controls (like bitmap buttons) that draws themselves using OwnerDraw. It is also having a control that displays an image with size that takes up to 70% of the dialog.
When user re-sizes the dialog, some of the controls in the dialog should be re-positioned (not re-sized). It also involves re-sizing of the image inside the dialog. As the re-sizing of image makes the whole process slow, individual re-positioning of the controls are causing a visual effect of flickering.
I need to get rid of these. One idea is to put the controls as the children of an intermediate dialog that is the child of the original popup dialog. So, when there is a re-size, I can re-position the dialog only instead of moving each controls individually. (Re-position happens only in one direction (x or y), so moving the intermediate dialog should be enough.
As it involves some coding effort, before going this way, I need answers to the following questions:
Will this work?
If yes, whats the complexity involved in this method?
Is there a better way?
Please help!
Simple fixes are:
creating the slow window last so that it doesn't hold up drawing of the simple controls
turning on the WS_EX_COMPOSITED style flag so Windows double-buffers the entire window, including its children. Beware of painting artifacts
turning off the WS_CLIPCHILDREN style flag so the holes are not so noticeable. Making the background white would accomplish the same
keeping the drawing of slow controls simple between WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE
using less controls, burning up an expensive window on a simple string or image is unnecessary
It will probably work, but you should try solutions that don't alter your control hierarchy before, because it has other subtle consequences (focus, tab order, message notifications, etc).
Try one or all of the following:
Use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos functions to move the children.
Set the WS_CLIPCHILDREN style flag in the dialog.
Set the WS_EX_LAYERED extended style flag in the dialog.

How to get CEdit to scroll properly?

I have a CEdit control that's used to display a diagnostics output.
Sometimes the data overflows the screen size, so naturally I set the Vertical Scroll property to true (MFC dialog editor).
But then, when I tried to scroll the text that was in the window before isn't cleared and the new text is written over it.
The result is a big mess of everything I have scrolled past.
I've looked for a draw background property or something similar that will erase everything in the window while scrolling (before redrawing the new data).
Any suggestions?
I think you might want to set Auto VScroll and Multiline to true, and Auto HScroll to false.
We were having a similar problem. We ended up having to invalid the region of the parent window to get it to update when we got WM_VSCROLL. I tried to do as user demorge says here:
SetBkMode(hdc, TRANSPARENT) doesn't work
But our code doesn't use handles, we actually use the class CWnd, so we ended up doing this in the WindowProc instead:
switch(message)
{
...
case WM_VSCROLL:
case WM_HSCROLL:
LRESULT answer;
PAINTSTRUCT ps;
CDC* pdc;
CWnd* MyParentHWnd;
// We want the scroll to work the same way it has always worked for our
// ancestor class. Let them handle the scrolling and save off their
// return.
answer = AncestorClass::WindowProc(message, wParam, lParam);
pdc = BeginPaint(&ps);
// DO NOT change the assignement operator in the conditional below to an
// equality operator. We are actually trying to get the parent window and
// and storing locally, and then verifying that we didn't get back null.
// This is a purposeful design decision.
if (MyParentHWnd = GetParent()){
RECT MyRect;
GetClientRect(&MyRect);
ClientToScreen(&MyRect);
MyParentHWnd->ScreenToClient(&MyRect);
MyParentHWnd->InvalidateRect(&MyRect);
}
EndPaint(&ps);
return answer;
break;
...
}
Of course, I had to genericize it a little bit. I just wanted you to know that yes, there are other people that are seeing your problem, and we found how to fix it.
I tested this with VS2005, which ships with MFC 8.0. I couldn't replicate your problem.
I added one CEdit and one CRichEditCtrl to a dialog based app. Changed properties Multiline, Auto VSCroll and Vertical Scroll to true. Used SetWindowText-method to put loooooong string of text to both of them. I started the app and text scrolled just fine.
What did you do differently?
Just to be sure. You didn't use the SetCaretPos-method, did you? There was some note about that in the MSDN page. Here's the Knowledge Base article.