Designing an application that requires graph manipulation, frequently requires to see the graph displayed in its smallest forms: to observe how the pixels interact with each other, how close they are, how the software is dealing with them. Most of the time, by direct naked eye observation, you get the information needed, except in those individual cases when it is necessary to get a slightly closer look.
Introduction
Writing graphics processing software has occupied a substantial part of my engineering work. I find it to be enjoyable work. Frequently, I need to amplify pixels painted on the screen. There are magnifiers available, and I have used some with satisfying results. But I wanted a small enough object that I could re-use on my other applications, one over which I would have a bit more control.
The second reason for my desire to write this code is trying to use CMemdDC
, by Keith Rule, in a dialog. I have previously used CMemDC
on a CScrollView::OnDraw()
with great results. Using it on a dialog presented a bit of a problem, one that I could not solve at the time, and had left this work for another day.
The third reason is that I wanted to use a modeless dialog from within a View
environment. Since I had not used this mechanism before, this seemed a good place to investigate.
Most importantly, I thought this would be a fun project to undertake.
CMagnifierDlg
The operation of the magnifier resides on a modeless dialog, a class I have named CMagnifierDlg
.
CMagnifierDlg
magnifies a portion of the graph by drawing the representation of one pixel into a rectangle, a "cell." The larger the cell, the higher the magnification. A combination of a group of cells is placed in a control within the dialog. The dialog allows to zoom in by simply displaying larger cells for each pixel.
Since this process will reside on a modeless dialog, I modified the dialog in two ways:
- Eliminating the "OK" and "Cancel" buttons on the dialog.
- On the "
OnCancel
" function, I placed a call to ShowWindow(SW_HIDE);
to put it out of the way yet ready to be recalled again.
When the user needs to re-activate the magnifier, CScrollView
calls m_MagnifierDlg.ShowWindow(SW_SHOW);
When the user clicks on the observed window surface, CMagnifierAppView
places a call to the dialog, m_MagnifierDlg.vSetMagnificationPoint();
indicating the new location to enlarge.
Using the Code
In the CSrollView
class, I instantiated a CMagnifierDlg
object. The dialog will not be operational until you "create" it. When the user clicks on the magnifier button, the code "creates" the dialog, makes a call to the dialog to Create();
, and now the dialog comes to life. From then on, the CScrollView
will need to communicate the magnifier the location the user has clicked, for a new magnification display.
class CMagnifierAppView : public CScrollView
{
…
CMagnifierDlg m_MagnifierDlg;
…
};
void CMagnifierAppView::OnButtonEmbeddedDialog()
{
if (!m_MagnifierDlg.bDialogWasCreated())
{
m_MagnifierDlg.Create(this);
}
else
{
m_MagnifierDlg.ShowWindow(SW_SHOW);
}
}
void CMagnifierAppView::OnInitialUpdate()
{
CMagnifierAppDoc* pDoc = GetDocument();
CScrollView::OnInitialUpdate();
CString csFilePath = pDoc->GetPathName();
if (!csFilePath.IsEmpty())
{
if (bReadBMPFile(csFilePath))
SetScrollSizes( MM_TEXT, CSize(m_bih.biWidth, m_bih.biHeight));
}
else
{
SetScrollSizes( MM_TEXT, CSize( 1, 1 ) );
}
InvalidateRect(NULL);
}
void CMagnifierAppView::OnLButtonDown(UINT nFlags, CPoint point)
{
CPoint ptUserClicked = point;
ptUserClicked.x += GetScrollPos(SB_HORZ);
ptUserClicked.y += GetScrollPos(SB_VERT);
m_MagnifierDlg.vSetMagnificationPoint(ptUserClicked);
CScrollView::OnLButtonDown(nFlags, point);
}
The function bool CMagnifierAppView::bReadBMPFile(…)
loads the data into a memory buffer from where to paint the graph.
Conclusion and Points of Interest
In this sample, we have shown a simple way to create a magnification of a graph. We have used CMemDC
on a dialog, a modeless dialog and we have instantiated the modeless dialog on a CScrollView
.
History
- 8th June, 2020: Initial version