オーバレイはベクタデータやラスタデータを画像データ等に重畳して表示する為の透明のレイヤーです。 1枚のレイヤーに複数のベクタ・ラスタデータを図形オブジェクトとして管理します。 図形オブジェクトは、それぞれ自身の描画位置を保有し、描画機能を実装しています。
オーバレイ処理は、下記の2通りの方法があります。
- オーバレイのインスタンスをユーザ側で管理する方法
- オーバレイのインスタンスを FVCL::GDI::CFvDisplay の内部で管理する方法
方法 (1):
ユーザ側で宣言したオーバレイを、このクラスの Overlays 配列に追加する方法です。 オーバレイのインスタンスはユーザ側で保持しておく必要があります。
方法 (2):
このクラスの CreateOverlay メソッドでオーバレイを生成する方法です。 オーバレイのインスタンスは、このクラスの m_Overlays に保持されており、 オーバレイに対して操作するには、 GetOverlay メソッドでオーバレイのインスタンスを取得する必要があります。
図形描画処理
画像にベクタデータやラスタデータを重畳して表示するには、オーバレイのインスタンスに対して 図形オブジェクト を追加する必要があります。
図形の描画処理は、下記の2通りの方法があります。
- 図形オブジェクトのインスタンスをユーザ側で管理する方法
- 図形オブジェクトのインスタンスを FVCL::GDI::CFvOverlay の内部で管理する方法
方法 (1):
図形オブジェクトのインスタンスをユーザ側で宣言して、オーバレイに配置する方法です。 図形オブジェクトのインスタンスをユーザ側で管理する必要はありますが、 ユーザが図形オブジェクトをマウスで操作するような動的なオーバレイを作成する場合は、この方法が適しています。
方法 (2):
図形オブジェクトのインスタンスを FVCL::GDI::CFvOverlay の内部で管理する方法です。 図形を配置するには、 DrawFigure メソッドを使用します。 この時、メソッドに指定したインスタンスのコピーが m_Figures に保管されます。 図形オブジェクトを操作するには、前述の DrawFigure の戻り値を保持しておくか、 GetFigure で取得したインスタンスを介して行う必要があります。
サンプルコード
下記は、ダイアログ上の任意の位置に画像とオーバレイ(文字列、線分)を描画する例です。
文字列はスケーリングせず表示領域の左上に描画しています。
線分はスケーリングして現在のコントロールポイントを中心に描画しています。
スクリーンショット:
ヘッダー:
#pragma once
#include "afxwin.h"
class CSampleCodeDlg : public CDialogEx
{
public:
CSampleCodeDlg(CWnd* pParent = NULL);
enum { IDD = IDD_SAMPLECODE_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
protected:
HICON m_hIcon;
virtual BOOL OnInitDialog();
afx_msg
void OnSysCommand(
UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
protected:
FVCL::Data::CFvImage m_Image;
FVCL::GDI::CFvDisplay m_Display;
FVCL::GDI::CFvOverlay m_Overlay1;
FVCL::GDI::CFvOverlay m_Overlay2;
FVCL::GDI::CFvGdiLineSegment m_FigureLS1;
FVCL::GDI::CFvGdiLineSegment m_FigureLS2;
public:
CStatic m_View;
afx_msg void OnBnClickedButtonActual();
afx_msg void OnBnClickedButtonReduce();
afx_msg void OnBnClickedButtonExpand();
afx_msg
void OnLButtonDown(
UINT nFlags, CPoint point);
};
実装: (初期化処理)
BOOL CSampleCodeDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
m_Image.Load(_T("TestFiles/floppy_RGB.jpg"));
m_Display.Create();
{
m_Overlay1.SetScaling(false);
m_Display.Overlays.push_back( &m_Overlay1 );
m_Overlay2.SetScaling(true);
m_Display.Overlays.push_back( &m_Overlay2 );
}
{
center.
x = m_Image.GetHorzSize() / 2;
center.
y = m_Image.GetVertSize() / 2;
m_Display.SetControlPoint(center);
}
return TRUE;
}
関連:
実装: (描画処理)
void CSampleCodeDlg::OnPaint()
{
if (IsIconic())
{
}
else
{
CPaintDC dcPaint(this);
{
CPaintDC dc(&m_View);
CRect client;
m_View.GetClientRect( &client );
m_Display.SetDisplayRect(
RECT(client) );
m_Display.SetImage(&m_Image);
{
text.
Format(_T(
"Magnification: %6.2f"), m_Display.GetMagnification());
m_FigureText.SetText(text);
m_FigureText.SetColor(
RGB(0xFF, 0x00, 0x00) );
m_Overlay1.Figures.clear();
m_Overlay1.Figures.push_back( &m_FigureText );
}
{
m_FigureLS1.GetPen().SetColor(
RGB(0xFF, 0xFF, 0x00) );
m_FigureLS2.GetPen().SetColor(
RGB(0xFF, 0xFF, 0x00) );
m_Overlay2.Figures.clear();
m_Overlay2.Figures.push_back( &m_FigureLS1 );
m_Overlay2.Figures.push_back( &m_FigureLS2 );
}
m_Display.Draw(dc.GetSafeHdc());
}
CDialogEx::OnPaint();
}
}
関連:
実装: (その他、MFC ダイアログの初期化部分)
#include "SampleCode.h"
#include "SampleCodeDlg.h"
#include "CAboutDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CSampleCodeDlg::CSampleCodeDlg(CWnd* pParent)
: CDialogEx(CSampleCodeDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CSampleCodeDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_VIEW, m_View);
}
BEGIN_MESSAGE_MAP(CSampleCodeDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_ACTUAL, &CSampleCodeDlg::OnBnClickedButtonActual)
ON_BN_CLICKED(IDC_BUTTON_REDUCE, &CSampleCodeDlg::OnBnClickedButtonReduce)
ON_BN_CLICKED(IDC_BUTTON_EXPAND, &CSampleCodeDlg::OnBnClickedButtonExpand)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void CSampleCodeDlg::OnSysCommand(
UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
HCURSOR CSampleCodeDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
実装: (コントロールポイントの変更)
下記は、ダイアログ上をクリックされると画像座標に変換してコントロールポイントを設定する例です。
void CSampleCodeDlg::OnLButtonDown(
UINT nFlags, CPoint point)
{
CRect rect;
m_View.GetWindowRect( &rect );
CWnd::ScreenToClient(&rect);
CPoint dp;
dp.x = point.x - rect.left;
dp.y = point.y - rect.top;
m_Display.SetControlPoint( ip );
CWnd::SetRedraw( TRUE );
CWnd::Invalidate( TRUE );
CWnd::UpdateWindow();
CDialogEx::OnLButtonDown(nFlags, point);
}
関連:
- FVCL::GDI::CFvDisplay::SetControlPoint
- FVCL::GDI::CFvDisplay::GetControlPoint
- FVCL::GDI::CFvDisplay::DPtoIP( LONG dsp_x, LONG dsp_y, INT mode ) const
- FVCL::GDI::CFvDisplay::DPtoIP( LONG dsp_x, LONG dsp_y, DOUBLE* img_x, DOUBLE* img_y, INT mode ) const
- FVCL::GDI::CFvDisplay::IPtoDP( DOUBLE img_x, DOUBLE img_y, INT mode ) const
- FVCL::GDI::CFvDisplay::IPtoDP( DOUBLE img_x, DOUBLE img_y, LONG* dsp_x, LONG* dsp_y, INT mode ) const
実装: (表示倍率変更)
下記は、表示倍率を設定する例です。
void CSampleCodeDlg::OnBnClickedButtonActual()
{
m_Display.SetMagnification(1.0);
CWnd::SetRedraw( TRUE );
CWnd::Invalidate( TRUE );
CWnd::UpdateWindow();
}
void CSampleCodeDlg::OnBnClickedButtonReduce()
{
double mag = m_Display.GetMagnification() / 2;
if (mag < 0.1)
mag = 0.1;
m_Display.SetMagnification(mag);
CWnd::SetRedraw( TRUE );
CWnd::Invalidate( TRUE );
CWnd::UpdateWindow();
}
void CSampleCodeDlg::OnBnClickedButtonExpand()
{
double mag = m_Display.GetMagnification() * 2;
if (mag > 50.0)
mag = 50.0;
m_Display.SetMagnification(mag);
CWnd::SetRedraw( TRUE );
CWnd::Invalidate( TRUE );
CWnd::UpdateWindow();
}
関連: