 |
|
 |
Please note that CPaintDC should only be used in OnPaint and should not be used in OnSize.
http://msdn.microsoft.com/en-us/library/a48eab8d%28v=vs.80%29.aspx[^]
It can cause a nasty bug where the scroll bars disappear(EndPaint called by CPaintDC causes the client window area to be validated), use CClientDC instead.
Hope this helps future generations...
|
|
|
|
 |
|
 |
Hello,
I have a problem with CZoomView. Let's say in my application I simply draw a rectangle
in the OnDraw function and zoom in on it several times. Afterwards when I click my left mouse button
I want to draw a new rectangle of exactly the same size as the one that is zoomed in, but the problem is
that when I do that the rectangle sizes do not match (the new one is a bit bigger in width and / or height
depending on where it is drawn on the screen than the old one). I use the LPtoDP function, but no luck and the
difference in sizes only gets bigger with every zoom in operation.
Personally, I think that the problem might somehow be connected with the function LPtoDP because the coordinates
of the rectangles don't exactly match, but that is only an assumption and I could be wrong...
Can anyone plaease give me a clue on what might be the problem here and how to fix it?
I'm stuck with this for quite a while now... Big Thanks in advance.
modified on Friday, September 11, 2009 3:35 AM
|
|
|
|
 |
|
 |
Hi Roonglit - firstly thanks for your code and for contributing.
I've been trying to apply this to an existing SDI MFC application I have. I had been using the CMemDC class to do my drawing, but changed that to the CDC* pDC since your CScrollView has bitblt support.
So here is my problem: when I Zoom in or out, all that changes is the scroll bar positions - the drawing stays the same size. I tried just drawing your own rectangles example, but they also stay the same size. Obviously each time the drawing is done in logical units - so I think it's somethiing to do with the mapping modes. However, I don't set any from my own code. The only one thing that is different from my code and the demo is that I have an OnInitialUpdate() function. In this I just did the following:
//CScrollView::OnInitialUpdate();
CZoomView::OnInitialUpdate();
and carried out initing my own stuff.
I'd appreciate any help you have to offer on this strange problem - thanks!
|
|
|
|
 |
|
 |
The code in OnInitialUpdate() is for creating an initial bitmap to solve flicker-free issue. If you remove this line, it would affect the application's WM_SIZE handler function, because I checked whether the bitmap is created or not. One thing that you might need to check is IMPLEMENT_DYNCREATE and BEGIN_MESSAGE_MAP macro. Please make sure that the base class is CZoomView, not CScrollView.
Let me know if this helps.
|
|
|
|
 |
|
 |
Hi Roonglit - thanks for replying. I made a silly error and forgot to change the class names in the macros - as you correctly identified. My aplogies for this silly mistake!
Perhaps you might let me ask another question? Because my application needs the view port origin set at the middle of the client window, I tried implementing my own zoom function. The zoom works, but the scrolling doesn't - when I zoom in the image moves the the left and when I zoom out the image moves to the right. I think it's to do with the coordinate conversions, but as you can see from the code below I have tried to allow for them. Any help you can give is really appreciated
void CTrafficView::OnPrepareDC(CDC *pDC, CPrintInfo *pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC); pDC->SetWindowExt(m_DrawArea);
int xExtent = m_Scale * m_DrawArea.cx;
int yExtent = m_Scale * m_DrawArea.cy;
pDC->SetViewportExt(xExtent, yExtent);
GetClientRect(&m_ClientRect); CPoint viewOrg;
viewOrg.y = m_ClientRect.Height()/2;
viewOrg.x = m_Border_Lhs*m_Scale;
viewOrg -= GetDeviceScrollPosition(); pDC->SetViewportOrg(viewOrg);
}
void CTrafficView::ResetScrollBars()
{
CClientDC aDC(this);
OnPrepareDC(&aDC);
CSize temp = m_DrawArea; aDC.LPtoDP(&temp);
SetScrollSizes(MM_TEXT, temp);
}
void CTrafficView::OnToolsZoomin()
{
CPoint pt;
GetClientRect(&m_ClientRect);
pt.x = (m_ClientRect.Width() / 2);
pt.y = (m_ClientRect.Height() / 2);
CClientDC aDC(this);
OnPrepareDC(&aDC);
CPoint vp = aDC.GetViewportOrg();
pt = pt - vp;
CScrollView::ScrollToPosition(pt);
m_Scale += 0.2; ResetScrollBars();
Invalidate(); }
Maybe if you can't advise on the above code, you could help me adapt your CZoomView so that I can set the viewport origin to my needs?
Thanks for your time.
|
|
|
|
 |
|
 |
I can't see what is the problem from your code. Actually, there are some variable you are using that I don't understand. However, if you want to see how the scroll bar is adjusted, try looking in SetZoomScale function. I think the code has demonstrated on that.
|
|
|
|
 |
|
 |
Hi Roonglit,
I did as you suggested and ripped the relevant parts of your code and it works! Thanks so much for getting back to me, and for your help.
To help others avoid the same problems here is the final code:
void CTrafficView::OnPrepareDC(CDC *pDC, CPrintInfo *pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC); // for scaling
pDC->SetWindowExt(m_DrawArea); // in logical units
int xExtent = m_Scale * m_DrawArea.cx;
int yExtent = m_Scale * m_DrawArea.cy;
pDC->SetViewportExt(xExtent, yExtent);
// keep the road divider in the centre of screen
// by moving the viewport origin
GetClientRect(&m_ClientRect); // the height of the window
CPoint viewOrg;
viewOrg.y = m_ClientRect.Height()/2; // move centre of road to middle of screen
viewOrg.x = m_Border_Lhs*m_Scale; // a left border
viewOrg -= GetDeviceScrollPosition(); // so scrolling accounted for
pDC->SetViewportOrg(viewOrg);
}
// note this function sets the new m_Scale so call it as follows
// SetZoomScale(m_Scale + 0.2) for example
// do not set m_Scale and then call the function!!!
void CTrafficView::SetZoomScale(double newScale)
{
if(newScale > 0.1)
{
double oldZoomFactor = m_Scale;
CPoint centerScrollPosition = GetScrollPosition();
CRect ClientRect(0,0,0,0);
centerScrollPosition.x += m_ClientRect.right/2;
centerScrollPosition.y += m_ClientRect.bottom/2;
m_Scale = newScale;
CSize displaySize;
displaySize.cx = Round(m_DrawArea.cx * m_Scale);
displaySize.cy = Round(m_DrawArea.cy * m_Scale);
SetScrollSizes(MM_TEXT,displaySize);
int newXScrollPosition = Round((centerScrollPosition.x / oldZoomFactor) * m_Scale); // I think this is the magic bit!
int newYScrollPosition = Round((centerScrollPosition.y / oldZoomFactor) * m_Scale);
newXScrollPosition -= m_ClientRect.right/2;
newYScrollPosition -= m_ClientRect.bottom/2;
ScrollToPosition(CPoint(newXScrollPosition,newYScrollPosition));
}
else
MessageBox("You cannot zoom out any further - minimum view scale is 0.1.", "Traffic", MB_OK|MB_ICONWARNING);
Invalidate(FALSE);
}
void CTrafficView::initRoad() // called whenever a "road" parameter changes - updates data behind objects to be drawn
{
// some other initilisation code here
// the new road draw area dimensions
m_DrawArea.cy = m_Border_Top + m_Border_Btm + m_RoadWidth;
m_DrawArea.cx = m_Border_Lhs + m_Border_Rhs + m_RoadLength;
CSize scrolls;
scrolls.cx = m_DrawArea.cx*m_Scale; // when scale is not 1.0 so user can alter road parameters
scrolls.cy = m_DrawArea.cy*m_Scale; // when zoomed in and not see a radical change in scroll bars
CScrollView::SetScrollSizes(MM_TEXT, scrolls);
}
|
|
|
|
 |
|
 |
I find to that How to zoom in and zoom out on another class...( I can't speak English very well)
Your source are useful to my program.
Thank's a lot~!
James
|
|
|
|
 |
|
 |
Hi
is it possible to zoom only in one axis and not in both axis? say if i want to zoom in only x direction, something like streatching the image in the positive x and neative X direction, how can this be done?
any ideas?
Zeus 1981
|
|
|
|
 |
|
 |
The point of the zoom ability is the ratio between Window and ViewPort. You may have to add an additional variable for other direction and modify the code in CZoomView::SetMapMode()
For example:
int CZoomView::SetMapMode(CDC* pDC)
{
...
pDC->SetViewport(FlatToInt(100*m_xZoomFactor), FloatToInt(100*m_yZoomFactor));
...
}
I'm not sure for negative X direction. You may have to flip the image by yourself for that.
|
|
|
|
 |
|
 |
is the following possible?
say i create a button on toolbar (a zoom button) , now when i click it , the bitmap is soomed only in the x direction. something like streaching the bitmap in the x axis only. something like a square is streched to form a rectangle.
any ideas, how this can be done?
Zeus 1981
|
|
|
|
 |
|
 |
It should be. Have you tried my last suggestion? My ZoomView is designed for general use. Therefore, if you want it behave in a specific way, you have to modify it yourself.
|
|
|
|
 |
|
 |
hi
thanks for the suggestion. i have taken your suggestion into consideration and i m working on it. i hope it will work just fine.
thanks.
Zeus 1981
|
|
|
|
 |
|
 |
In the application i am working on we can zoom In and Out up to a great extent.There is also provision to load Iamges, Rectanle which is proportionate to the client rectangles height and the images is caliculated and is in StretchBlt( ) while loading the image.The problem occurs when i zoom in many times(more than 20)and again zoom out,the image disppears!! This i have found to be because we are doing LPToDP on the recatngle object and passing that StretchBlt( ) again to strech it to new(zoomed window size), this Rectangle size is getting disturbed,The top and bottom values are coming up to be same(hence height becomes Zero).The recatngle values that we get while we zoom in dont match with the ones when we do zoom out. This happens only with zoom Out , Zoom In is working fine. Have chekced the zooming factors and all the other probable faults but havent found any. LPtoDP( ) function seems to be the trouble.Help Please!!
|
|
|
|
 |
|
 |
Hi! I've loaded a CImage picture and I've used your class to zoom out. The problems is that the zoomed picture (zoom factor = 50%) looks terrible. It's quite a difference than using StretchBlt. Any ideas on how to fix this problem???Is this the way to zoom images or bitmaps???
|
|
|
|
 |
|
 |
Nice work,but if it works with other map mode will be very useful!
--------------------------------------------------------------------------
For high quality flow/diagram MFC/C++ Visio Like visualization Source Code,download XD++ at:
http://www.ucancode.net
|
|
|
|
 |
|
 |
I loaded one bitmap in a dialog based appln.Now i want to zoom that bitmap using SetViewportExt
|
|
|
|
 |
|
 |
Hi.
I'm building an mfc app, using this class as base for the views, and i'm facing a problem when trying to print a view...
The print preview dialog shows too little, and the printing itself it's too big (OUCH)...what i'm trying to do is to print the view fitting the page...
Any help will be GREAT.
THX!,
Alberto.
|
|
|
|
 |
|
 |
Sorry about printing. I don't have time to look at it now. So, I can't promise about this. But I'll try looking at it to make this project complete.
|
|
|
|
 |
|
 |
Ok...If I can do it, i'll let you know...(I'm half way already)
|
|
|
|
 |
|
 |
I'm fighting with this printing stuff, and i can't seem to get it right...
i've added to the project "view modes" (always scale to fit, normal zoom and so on), and what i'm trying to do now is to print accordingly...but...print and print preview work kind of weird...the size of the paper on wich is printed the image is 6 times bigger than it shows (say, it shows just one page in print preview, and it prints only one, but it's 1/6 of the entire image)...
Has anybody tried to add printing and found this problem????
Any help would be appreciated....
Alberto
|
|
|
|
 |
|
 |
Hi,
I tried your code. It's good, appreciate it. But there is a
bug after certain stage of zooming.
It centers the rubberband area properly when I do once.
From second time onwards, centering is not proper and there is a bug. The rubber band area isn't centered on the client area.
Fixing that bug would make this article more useful.
Thanks
Vipin - MVP
|
|
|
|
 |
|
 |
ok, I figured it due to this function:-
void CZoomView::SetZoomFactor(float fZoomFactor)
{
....
}
It's ok when I make it to
void CZoomView::SetZoomFactor(float fZoomFactor)
{
m_zoomFactor = fZoomFactor;
return;
}
May be you should document this as part of the article somewhere, because the rubber banding is useless after one or two zooms.
Thanks
Vipin - MVP
|
|
|
|
 |
|
 |
This function is a normal accessor function to prevent not setting too low zoom factor or too much zoom factor. I'm not sure what are you talking about centering not perfect. Would you please explain a little bit more?
|
|
|
|
 |
|
 |
I would disagree with you putting a upper threshold on the zoom factor.
Many graphics internsive apps, have the ability to zoom to very higher
orders.
It would make your application much more attractive, if you improve on it.
Vipin - MVP
|
|
|
|
 |