mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 05:24:10 +08:00
2735 lines
80 KiB
C++
2735 lines
80 KiB
C++
#pragma once
|
||
|
||
#include "resource.h"
|
||
#include <atlctl.h>
|
||
#include <registration.h>
|
||
#include <windowsex.h>
|
||
#include <messages.h>
|
||
#include <tracking.h>
|
||
#include "constants.h"
|
||
#include <imagestudioutils.h>
|
||
|
||
[object, uuid("B78D5241-08FB-43ef-A06B-F57D2DBB1F77"), dual, pointer_default(unique)]
|
||
|
||
__interface IImageView3 : public IDispatch
|
||
{
|
||
[id(101)] HRESULT SetAdditionalParam([in] BSTR ParamName, [in] VARIANT ParamValue);
|
||
[id(102)] HRESULT GetAdditionalParam([in] BSTR ParamName, [out, retval] VARIANT* ParamValue);
|
||
|
||
[id(201)] HRESULT SetImage([in, satype("BYTE")] SAFEARRAY** Image);
|
||
[id(202)] HRESULT SetMediaData(IUnknown* pInterface);
|
||
|
||
[id(211)] HRESULT SetMask([in, satype("BYTE")] SAFEARRAY** Image);
|
||
|
||
[id(251)] HRESULT Refresh();
|
||
[id(252)] HRESULT GetScreen([out, satype("BYTE")] SAFEARRAY** Image, [out, retval] VARIANT_BOOL* Success);
|
||
|
||
[id(301), propget] HRESULT AutoRefresh([out, retval] VARIANT_BOOL* Allow);
|
||
[id(301), propput] HRESULT AutoRefresh([in] VARIANT_BOOL Allow);
|
||
|
||
[id(401)] HRESULT ZoomIn();
|
||
[id(402)] HRESULT ZoomOut();
|
||
[id(403)] HRESULT ZoomToFit();
|
||
[id(404)] HRESULT ShrinkToFit();
|
||
|
||
[id(501), propget] HRESULT viewCenterX([out, retval] double* CenterX);
|
||
[id(501), propput] HRESULT viewCenterX([in] double CenterX);
|
||
[id(502), propget] HRESULT viewCenterY([out, retval] double* CenterY);
|
||
[id(502), propput] HRESULT viewCenterY([in] double CenterX);
|
||
[id(503), propget] HRESULT viewZoom([out, retval] double* Zoom);
|
||
[id(503), propput] HRESULT viewZoom([in] double Zoom);
|
||
[id(504), propget] HRESULT viewAspect([out, retval] double* Aspect);
|
||
[id(504), propput] HRESULT viewAspect([in] double Aspect);
|
||
|
||
[id(511), propget] HRESULT formatShowBorder([out, retval] VARIANT_BOOL* Show);
|
||
[id(511), propput] HRESULT formatShowBorder([in] VARIANT_BOOL Show);
|
||
[id(512), propget] HRESULT formatWindowStyle([out, retval] long* Style);
|
||
[id(512), propput] HRESULT formatWindowStyle([in] long Style);
|
||
[id(513), propget] HRESULT formatMousePointer([out, retval] long* Pointer);
|
||
[id(513), propput] HRESULT formatMousePointer([in] long Pointer);
|
||
|
||
[id(521), propget] HRESULT formatMaskStyle([out, retval] long* Style);
|
||
[id(521), propput] HRESULT formatMaskStyle([in] long Style);
|
||
[id(522), propget] HRESULT formatMaskColor([out, retval] OLE_COLOR* Color);
|
||
[id(522), propput] HRESULT formatMaskColor([in] OLE_COLOR Color);
|
||
|
||
[id(531), propget] HRESULT formatBackStyle([out, retval] long* Style);
|
||
[id(531), propput] HRESULT formatBackStyle([in] long Style);
|
||
[id(532), propget] HRESULT formatBackColor1([out, retval] OLE_COLOR* Color);
|
||
[id(532), propput] HRESULT formatBackColor1([in] OLE_COLOR Color);
|
||
[id(533), propget] HRESULT formatBackColor2([out, retval] OLE_COLOR* Color);
|
||
[id(533), propput] HRESULT formatBackColor2([in] OLE_COLOR Color);
|
||
|
||
// tracking
|
||
[id(600), propget] HRESULT trackType([out, retval] long* Type);
|
||
[id(601), propget] HRESULT trackColorScheme([out, retval] long* ColorScheme);
|
||
[id(601), propput] HRESULT trackColorScheme([in] long ColorScheme);
|
||
|
||
[id(701)] HRESULT EndTrack();
|
||
[id(702)] HRESULT BeginTrackPoint([in] double X, [in] double Y);
|
||
[id(703)] HRESULT BeginTrackLine([in] double X1, [in] double Y1, [in] double X2, [in] double Y2);
|
||
[id(704)] HRESULT BeginTrackEllipse([in] double Left, [in] double Top, [in] double Right, [in] double Bottom);
|
||
[id(705)] HRESULT BeginTrackRectangle([in] double Left, [in] double Top, [in] double Right, [in] double Bottom);
|
||
[id(706)] HRESULT BeginTrackRectangleFixedSize([in] double Left, [in] double Top, [in] double Width, [in] double Height);
|
||
[id(707)] HRESULT BeginTrackRectangleFixedAspect([in] double Left, [in] double Top, [in] double Width, [in] double Height);
|
||
[id(708)] HRESULT BeginTrackPolyline([in, satype("double")] SAFEARRAY** Points);
|
||
[id(709)] HRESULT BeginTrackPolygon([in, satype("double")] SAFEARRAY** Points);
|
||
[id(710)] HRESULT BeginTrackPie([in] double Left, [in] double Top, [in] double Right, [in] double Bottom, [in] double StartAngle, [in] double SweepAngle);
|
||
[id(711)] HRESULT BeginTrackSector([in] double Left, [in] double Top, [in] double Right, [in] double Bottom, [in] double StartAngle, [in] double SweepAngle, [in] double Ratio);
|
||
[id(712)] HRESULT BeginTrackSimpleSector([in] double CenterX, [in] double CenterY, [in] double Radius1, [in] double Radius2, [in] double StartAngle, [in] double SweepAngle);
|
||
[id(713)] HRESULT BeginTrackSimplePie([in] double CenterX, [in] double CenterY, [in] double Radius1, [in] double StartAngle, [in] double SweepAngle);
|
||
[id(714)] HRESULT BeginTrackEllipseInRectangle([in] double Left, [in] double Top, [in] double Right, [in] double Bottom);
|
||
[id(715)] HRESULT BeginTrackCircle([in] double CenterX, [in] double CenterY, [in] double Radius);
|
||
[id(716)] HRESULT BeginTrackRectangleRotatable([in] double Left, [in] double Top, [in] double Right, [in] double Bottom, [in] double Angle, [in] double StickAngle);
|
||
[id(717)] HRESULT BeginTrackRectangleRotatableFixedAspect([in] double Left, [in] double Top, [in] double Right, [in] double Bottom, [in] double Angle, [in] double StickAngle);
|
||
[id(718)] HRESULT BeginTrackTextRotatable([in] double Left, [in] double Top, [in] double Right, [in] double Bottom, [in] double Angle, [in] double StickAngle, [in] BSTR inText, [in] BSTR FontName, [in] int FontSize, [in] int FontType, [in] int FontColor);
|
||
[id(719)] HRESULT BeginTrackText([in] double Left, [in] double Top, [in] double Right, [in] double Bottom, [in] BSTR inText, [in] BSTR FontName, [in] int FontSize, [in] int FontType, [in] int FontColor);
|
||
[id(720)] HRESULT BeginTrackTrajectoryPolyline([in, satype("double")] SAFEARRAY** Points);
|
||
|
||
[id(801)] HRESULT MoveTrack([in] double dX, [in] double dY);
|
||
|
||
[id(901)] HRESULT TransformCoordToBitmap(double* X, double* Y);
|
||
[id(902)] HRESULT TransformCoordToControl(double* X, double* Y);
|
||
};
|
||
|
||
[dispinterface, uuid("2CBB019D-2A27-406a-BA1A-ACFD768913F2")]
|
||
__interface _IImageView3Events
|
||
{
|
||
[id(101)] HRESULT MouseDown(long Button, long Shift, double X, double Y);
|
||
[id(102)] HRESULT MouseUp(long Button, long Shift, double X, double Y);
|
||
[id(103)] HRESULT MouseMove(long Button, long Shift, double X, double Y);
|
||
[id(104)] HRESULT MouseDblClick(long Button, long Shift, double X, double Y);
|
||
|
||
[id(201)] HRESULT TrackPoint(long Type, double X, double Y);
|
||
[id(202)] HRESULT TrackLine(long Type, double X1, double Y1, double X2, double Y2);
|
||
[id(203)] HRESULT TrackEllipse(long Type, double Left, double Top, double Right, double Bottom);
|
||
[id(204)] HRESULT TrackRectangle(long Type, double Left, double Top, double Right, double Bottom);
|
||
[id(205)] HRESULT TrackRectangleFixedSize(long Type, double X, double Y);
|
||
[id(206)] HRESULT TrackRectangleFixedAspect(long Type, double Left, double Top, double Right, double Bottom);
|
||
[id(207)] HRESULT TrackPolyline(long Type, BYTE* Points);
|
||
[id(208)] HRESULT TrackPolygon(long Type, BYTE* Points);
|
||
[id(209)] HRESULT TrackPie(long Type, double Left, double Top, double Right, double Bottom, double StartAngle, double SweepAngle);
|
||
[id(210)] HRESULT TrackSector(long Type, double Left, double Top, double Right, double Bottom, double StartAngle, double SweepAngle, double Ratio);
|
||
[id(211)] HRESULT TrackSimpleSector(long Type, double CenterX, double CenterY, double Radius1, double Radius2, double StartAngle, double SweepAngle);
|
||
[id(212)] HRESULT TrackSimplePie(long Type, double CenterX, double CenterY, double Radius1, double StartAngle, double SweepAngle);
|
||
[id(213)] HRESULT TrackEllipseInRectangle(long Type, double Left, double Top, double Right, double Bottom);
|
||
[id(214)] HRESULT TrackCircle(long Type, double CenterX, double CenterY, double Radius);
|
||
[id(215)] HRESULT TrackRectangleRotatable(long Type, double Left, double Top, double Right, double Bottom, double Angle);
|
||
[id(216)] HRESULT TrackTextRotatable(long Type, double Left, double Top, double Right, double Bottom, double Angle, BSTR Text);
|
||
[id(217)] HRESULT TrackText(long Type, double Left, double Top, double Right, double Bottom, BSTR Text);
|
||
[id(218)] HRESULT TrackRectangleRotatableFixedAspect(long Type, double Left, double Top, double Right, double Bottom, double Angle);
|
||
[id(219)] HRESULT TrackTrajectoryPolyline(long Type, BYTE* Points);
|
||
|
||
[id(501)] HRESULT ChangeBackBuffer( INT_PTR hDC );
|
||
};
|
||
|
||
[coclass, uuid("875E3D2E-FAFF-44f6-9FDA-6E01AEA4F8A6"), threading(apartment), vi_progid("AVSImageView.ImageView3"), progid("AVSImageView.ImageView3.2"), version(1.0), event_source(com), support_error_info(IImageView3), registration_script("control.rgs")]
|
||
class ATL_NO_VTABLE ImageView3 :
|
||
public IImageView3,
|
||
public IPersistStreamInitImpl<ImageView3>,
|
||
public IOleControlImpl<ImageView3>,
|
||
public IOleObjectImpl<ImageView3>,
|
||
public IOleInPlaceActiveObjectImpl<ImageView3>,
|
||
public IViewObjectExImpl<ImageView3>,
|
||
public IOleInPlaceObjectWindowlessImpl<ImageView3>,
|
||
public IPersistStorageImpl<ImageView3>,
|
||
public ISpecifyPropertyPagesImpl<ImageView3>,
|
||
public IQuickActivateImpl<ImageView3>,
|
||
public IDataObjectImpl<ImageView3>,
|
||
public CComControl<ImageView3>,
|
||
public Messages::CMessageReceiver
|
||
{
|
||
public:
|
||
|
||
__event __interface _IImageView3Events;
|
||
|
||
DECLARE_VIEW_STATUS(0)
|
||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||
DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE | OLEMISC_CANTLINKINSIDE | OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST)
|
||
|
||
BEGIN_PROP_MAP(ImageView3)
|
||
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
|
||
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
|
||
END_PROP_MAP()
|
||
|
||
BEGIN_MSG_MAP(ImageView3)
|
||
MESSAGE_RANGE_HANDLER(0, 0xFFFFFFFF, OnMessages)
|
||
DEFAULT_REFLECTION_HANDLER()
|
||
END_MSG_MAP()
|
||
|
||
public:
|
||
|
||
// image attributes
|
||
int m_nWidth;
|
||
int m_nHeight;
|
||
BYTE* m_pPixels;
|
||
BYTE* m_pMask;
|
||
|
||
// additional helpers
|
||
BOOL m_bAutoRefresh;
|
||
|
||
// formatting
|
||
BOOL m_bShowBorder;
|
||
int m_nWindowStyle;
|
||
|
||
int m_nMaskStyle;
|
||
int m_nMaskColor;
|
||
|
||
int m_nBackStyle;
|
||
int m_nBackColor1;
|
||
int m_nBackColor2;
|
||
|
||
int m_nPointer;
|
||
|
||
// preview attributes
|
||
double m_dCenterX;
|
||
double m_dCenterY;
|
||
double m_dZoom;
|
||
double m_dAspect;
|
||
int m_nAspectWidth;
|
||
int m_nAspectHeight;
|
||
|
||
// handle to window for timer messages
|
||
//HWND m_hWndTimer;
|
||
|
||
// tracking
|
||
int m_nTrackingColorScheme;
|
||
Tracking::CTrackPainter m_oTrackingPainter;
|
||
Tracking::CTrackObject* m_pTracking;
|
||
|
||
// rendering
|
||
Windows::CDoubleBuffer m_oDoubleBuffer;
|
||
|
||
// gdi+
|
||
CGdiPlusInit m_oGdiPlusInit;
|
||
// MemoryUtils::CMemoryUtils m_oMemoryUtils;
|
||
|
||
TRACKMOUSEEVENT tme;
|
||
|
||
public:
|
||
|
||
LRESULT OnMessages(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
||
{
|
||
// reset handling flag
|
||
bHandled = FALSE;
|
||
|
||
// setup mouse cursor if
|
||
if (uMsg == WM_SETCURSOR)
|
||
bHandled = OnSetCursor();
|
||
|
||
if (uMsg == WM_MOUSEMOVE)
|
||
{
|
||
// initialize track mouse event
|
||
tme.cbSize = sizeof( TRACKMOUSEEVENT );
|
||
tme.dwFlags = TME_LEAVE;
|
||
tme.hwndTrack = m_hWnd;
|
||
|
||
TrackMouseEvent( &tme );
|
||
}
|
||
|
||
// handle mouse events - send necessary event to parent
|
||
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN ||
|
||
uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP ||
|
||
uMsg == WM_LBUTTONDBLCLK || uMsg == WM_RBUTTONDBLCLK || uMsg == WM_MBUTTONDBLCLK ||
|
||
uMsg == WM_MOUSEMOVE)
|
||
OnMouseEvent(uMsg);
|
||
|
||
|
||
if (uMsg == WM_LBUTTONDBLCLK)
|
||
SetFocus();
|
||
|
||
// allow trackers to handle its own events
|
||
if (m_pTracking)
|
||
m_pTracking->OnMessages(uMsg, wParam, lParam);
|
||
|
||
// handle painting messages
|
||
if (uMsg == WM_ERASEBKGND)
|
||
bHandled = TRUE;
|
||
else if (uMsg == WM_PAINT)
|
||
{
|
||
OnPaint(c_SenderDraw);
|
||
bHandled = FALSE; // <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> painting'<27>
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
BOOL OnPaint(int nSender)
|
||
{
|
||
// check for autorefresh flag
|
||
if (!m_bAutoRefresh && nSender != c_SenderRefresh)
|
||
return FALSE;
|
||
|
||
if (!IsWindow())
|
||
return FALSE;
|
||
|
||
// retrieve window rectangle and check for valid size
|
||
RECT rect; GetClientRect(&rect);
|
||
if (rect.right - rect.left < 1 || rect.bottom - rect.top < 1)
|
||
return FALSE;
|
||
|
||
HDC hPreviewDC = GetDC();
|
||
m_oDoubleBuffer.Create(hPreviewDC, rect, TRUE);
|
||
|
||
// extract last frame (skip mouse tracking case)
|
||
BOOL bScreenValid = IsValid();
|
||
if (nSender != c_SenderTrack)
|
||
{
|
||
int nWidth = m_oDoubleBuffer.GetRect().GetWidth();
|
||
int nHeight = m_oDoubleBuffer.GetRect().GetHeight();
|
||
BYTE* pPixels = m_oDoubleBuffer.GetBackBitmapPixels();
|
||
|
||
if( FALSE == IPP_ExtractRect(nWidth, nHeight, 4, pPixels) )
|
||
bScreenValid = ExtractRect(nWidth, nHeight, 4, pPixels);
|
||
else
|
||
bScreenValid = TRUE;
|
||
}
|
||
|
||
// draw the screen
|
||
if (bScreenValid)
|
||
{
|
||
m_oDoubleBuffer.RenderBackBitmapPixels();
|
||
ShowTracking(m_oDoubleBuffer.GetBackDC(), rect);
|
||
}
|
||
else
|
||
Rendering::Gdi::FillRectangle(m_oDoubleBuffer.GetBackDC(), m_nBackColor1, rect);
|
||
|
||
ChangeBackBuffer( (INT_PTR)m_oDoubleBuffer.GetBackDC() );
|
||
|
||
// show window borders
|
||
ShowWindowBorders(m_oDoubleBuffer.GetBackDC(), rect);
|
||
|
||
// flip back buffer to the screen
|
||
m_oDoubleBuffer.Render();
|
||
|
||
ReleaseDC(hPreviewDC);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL OnSetCursor()
|
||
{
|
||
// variables
|
||
POINT point; GetCursorPos(&point); ::ScreenToClient(m_hWnd, &point);
|
||
|
||
// compute cursor style
|
||
int nPointer = m_nPointer;
|
||
|
||
if (m_nPointer == c_MousePointerDefault)
|
||
{
|
||
if (!m_pTracking)
|
||
return FALSE;
|
||
|
||
int nPointStatus = Tracking::c_nTrackPointStatusNone;
|
||
int nTrackChangeStatus = Tracking::c_nTrackChangeStatusNone;
|
||
|
||
m_pTracking->OnSetCursor(point.x, point.y, nPointStatus, nTrackChangeStatus);
|
||
|
||
if (nPointStatus == Tracking::c_nTrackPointStatusPoint) // hand arrow
|
||
nPointer = c_MousePointerHand;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusHorizontal) // - size
|
||
nPointer = c_MousePointerSizeWE;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusVertical) // | size
|
||
nPointer = c_MousePointerSizeNS;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusSize1) // \ size
|
||
nPointer = c_MousePointerSizeNWSE;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusSize2) // / size
|
||
nPointer = c_MousePointerSizeNESW;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusSizeAll) // + size
|
||
nPointer = c_MousePointerSizeAll;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusCanAdd) // pick cross
|
||
nPointer = c_MousePointerCross;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusRotation) // rotation cross
|
||
nPointer = c_MousePointerRotation;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusIBeam) // edit text
|
||
nPointer = c_MousePointerIBeam;
|
||
else if (nPointStatus == Tracking::c_nTrackPointStatusSizeForRotation) // size for rotation
|
||
nPointer = c_MousePointerSizeForRotation;
|
||
else
|
||
return FALSE;
|
||
}
|
||
|
||
// setup mouse pointer
|
||
switch (nPointer)
|
||
{
|
||
case c_MousePointerArrow: return (BOOL)SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||
case c_MousePointerCross: return (BOOL)SetCursor(LoadCursor(NULL, IDC_CROSS));
|
||
case c_MousePointerIBeam: return (BOOL)SetCursor(LoadCursor(NULL, IDC_IBEAM));
|
||
case c_MousePointerIcon: return (BOOL)SetCursor(LoadCursor(NULL, IDC_ICON));
|
||
case c_MousePointerSize: return (BOOL)SetCursor(LoadCursor(NULL, IDC_SIZEALL));
|
||
case c_MousePointerSizeNESW: return (BOOL)SetCursor(LoadCursor(NULL, IDC_SIZENESW));
|
||
case c_MousePointerSizeNS: return (BOOL)SetCursor(LoadCursor(NULL, IDC_SIZENS));
|
||
case c_MousePointerSizeNWSE: return (BOOL)SetCursor(LoadCursor(NULL, IDC_SIZENWSE));
|
||
case c_MousePointerSizeWE: return (BOOL)SetCursor(LoadCursor(NULL, IDC_SIZEWE));
|
||
case c_MousePointerUpArrow: return (BOOL)SetCursor(LoadCursor(NULL, IDC_UPARROW));
|
||
case c_MousePointerHourglass: return (BOOL)SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
case c_MousePointerNoDrop: return (BOOL)SetCursor(LoadCursor(NULL, IDC_NO));
|
||
case c_MousePointerArrowHourglass: return (BOOL)SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
|
||
case c_MousePointerArrowQuestion: return (BOOL)SetCursor(LoadCursor(NULL, IDC_HELP));
|
||
case c_MousePointerSizeAll: return (BOOL)SetCursor(LoadCursor(NULL, IDC_SIZEALL));
|
||
case c_MousePointerHand: return (BOOL)SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(32649)));
|
||
case c_MousePointerRotation: return (BOOL)SetCursor(LoadCursor(_AtlComModule.m_hInstTypeLib, MAKEINTRESOURCE(IDC_CURSOR2)));
|
||
case c_MousePointerSizeForRotation: return (BOOL)SetCursor(LoadCursor(_AtlComModule.m_hInstTypeLib, MAKEINTRESOURCE(IDC_CURSOR1)));
|
||
}
|
||
|
||
// invalid pointer id
|
||
return FALSE;
|
||
}
|
||
BOOL OnMouseEvent(int nMessage)
|
||
{
|
||
// variables
|
||
int nButton, nShift;
|
||
double dX, dY;
|
||
|
||
// retrieve current mouse state
|
||
GetMouseState(nButton, nShift, dX, dY);
|
||
|
||
// fire the event
|
||
if (nMessage == WM_LBUTTONDOWN || nMessage == WM_RBUTTONDOWN || nMessage == WM_MBUTTONDOWN)
|
||
{
|
||
SetCapture();
|
||
MouseDown(nButton, nShift, AspectXAdd(dX), AspectYAdd(dY));
|
||
}
|
||
else if (nMessage == WM_LBUTTONUP || nMessage == WM_RBUTTONUP || nMessage == WM_MBUTTONUP)
|
||
{
|
||
ReleaseCapture();
|
||
MouseUp(nButton, nShift, AspectXAdd(dX), AspectYAdd(dY));
|
||
}
|
||
else if (nMessage == WM_LBUTTONDBLCLK || nMessage == WM_RBUTTONDBLCLK || nMessage == WM_MBUTTONDBLCLK)
|
||
MouseDblClick(nButton, nShift, AspectXAdd(dX), AspectYAdd(dY));
|
||
else if (nMessage == WM_MOUSEMOVE)
|
||
MouseMove(nButton, nShift, AspectXAdd(dX), AspectYAdd(dY));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
virtual void ReceiveMessage(Messages::CMessage* pMessage)
|
||
{
|
||
if (!pMessage)
|
||
return;
|
||
|
||
if (pMessage->GetType() == Tracking::c_nTrackMessageTrackPointBegin)
|
||
FireEvent(0);
|
||
else if (pMessage->GetType() == Tracking::c_nTrackMessageTrackPointProcess)
|
||
FireEvent(1);
|
||
else if (pMessage->GetType() == Tracking::c_nTrackMessageTrackPointProcessAll)
|
||
FireEvent(1);
|
||
else if (pMessage->GetType() == Tracking::c_nTrackMessageTrackPointEnd)
|
||
FireEvent(2);
|
||
else if (pMessage->GetType() == Tracking::c_nTrackMessageTrackTextEnd)
|
||
FireEvent(4);
|
||
else if (pMessage->GetType() == Tracking::c_nTrackMessageTrackTextBegin)
|
||
FireEvent(5);
|
||
else if (pMessage->GetType() == Tracking::c_nTrackMessageTrackTextChange)
|
||
FireEvent(6);
|
||
|
||
OnPaint(c_SenderTrack);
|
||
}
|
||
|
||
public:
|
||
|
||
ImageView3()
|
||
{
|
||
#ifdef _DEBUG
|
||
int flag = _CrtSetDbgFlag ( _CRTDBG_REPORT_FLAG ); // Get current flag
|
||
flag |= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit
|
||
flag |= _CRTDBG_CHECK_ALWAYS_DF; // Turn on CrtCheckMemory
|
||
// flag |= _CRTDBG_DELAY_FREE_MEM_DF;
|
||
//_CrtSetBreakAlloc ( 4775 );
|
||
_CrtSetDbgFlag(flag); // Set flag to the new value
|
||
#endif
|
||
// initialize gdi+
|
||
m_oGdiPlusInit.Init();
|
||
|
||
// setup invalid image parameters
|
||
m_nWidth = 0;
|
||
m_nHeight = 0;
|
||
m_pPixels = 0;
|
||
m_pMask = 0;
|
||
|
||
// setup additional helpers
|
||
m_bAutoRefresh = TRUE;
|
||
|
||
m_bShowBorder = TRUE;
|
||
m_nWindowStyle = c_WindowStyleClient;
|
||
|
||
m_nMaskStyle = c_MaskStyleDotsDense;
|
||
m_nMaskColor = RGB(255, 0, 0);
|
||
|
||
m_nBackStyle = c_BackStyleSolid;
|
||
m_nBackColor1 = ImageStudioUtils::GetColorLight(GetSysColor(COLOR_3DFACE), 16);
|
||
m_nBackColor2 = ImageStudioUtils::GetColorDark(GetSysColor(COLOR_3DFACE), 16);
|
||
|
||
// default preview image offsets and zoomings
|
||
m_dCenterX = 0.0;
|
||
m_dCenterY = 0.0;
|
||
m_dZoom = 1.0;
|
||
m_dAspect = -1.0;
|
||
m_nAspectWidth = 0;
|
||
m_nAspectHeight = 0;
|
||
|
||
// disable mouse capturing flag - mouse unlocked by default
|
||
m_nPointer = c_MousePointerDefault;
|
||
|
||
// setup tracking object
|
||
m_nTrackingColorScheme = c_TrackColorSchemeInverse;
|
||
m_pTracking = 0;
|
||
|
||
// disallow windowless activation
|
||
m_bWindowOnly = TRUE;
|
||
}
|
||
|
||
//HWND CreateControlWindow(HWND hWndParent, RECT& rcPos)
|
||
//{
|
||
// //T* pT = static_cast<T*>(this);
|
||
// //return pT->Create(hWndParent, rcPos);
|
||
// m_hWndTimer = CComControl::CreateControlWindow( hWndParent, rcPos );
|
||
|
||
// ::SetTimer( m_hWndTimer, // handle to main window
|
||
// IDT_TIMER1, // timer identifier
|
||
// 1000, // 1-second interval
|
||
// (TIMERPROC) NULL ); // no timer callback
|
||
|
||
// return hWndParent;
|
||
//}
|
||
|
||
~ImageView3()
|
||
{
|
||
Clear();
|
||
|
||
if (m_pTracking)
|
||
{
|
||
delete m_pTracking;
|
||
m_pTracking = 0;
|
||
}
|
||
}
|
||
|
||
BOOL IsValid()
|
||
{
|
||
if (!m_pPixels || !m_nWidth || !m_nHeight || !IsWindow())
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
void Clear()
|
||
{
|
||
// destroy the image
|
||
if (m_pPixels)
|
||
{
|
||
delete[] m_pPixels;
|
||
m_pPixels = 0;
|
||
}
|
||
if (m_pMask)
|
||
{
|
||
delete[] m_pMask;
|
||
m_pMask = 0;
|
||
}
|
||
/*
|
||
if (m_pTracking)
|
||
{
|
||
delete m_pTracking;
|
||
m_pTracking = 0;
|
||
}
|
||
*/
|
||
m_nWidth = 0;
|
||
m_nHeight = 0;
|
||
}
|
||
|
||
BOOL IPP_ExtractRect( int nWidth, int nHeight, int nChannels, BYTE* pPixels )
|
||
{
|
||
return FALSE;
|
||
|
||
// check for valid preview image
|
||
if (!pPixels || !nWidth || !nHeight || nChannels != 4)
|
||
return FALSE;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
BYTE* pBuffer = NULL;
|
||
BYTE* pImage = m_pPixels;
|
||
DWORD nImageSize = m_nWidth*m_nHeight*4;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
if( m_pMask && m_nMaskStyle != c_MaskStyleHidden )
|
||
{
|
||
pBuffer = new Ipp8u[nImageSize];
|
||
if( pBuffer )
|
||
{
|
||
COLORREF nSelection; OleTranslateColor(m_nMaskColor, NULL, &nSelection);
|
||
COLORREF nBackground1; OleTranslateColor(m_nBackColor1, NULL, &nBackground1);
|
||
COLORREF nBackground2; OleTranslateColor(m_nBackColor2, NULL, &nBackground2);
|
||
|
||
int nSelectionRed = GetRValue(nSelection);
|
||
int nSelectionGreen = GetGValue(nSelection);
|
||
int nSelectionBlue = GetBValue(nSelection);
|
||
|
||
memcpy( pBuffer, m_pPixels, nImageSize );
|
||
|
||
BYTE* pMaskPixel = m_pMask;
|
||
BYTE* pBufferPixel = pBuffer;
|
||
|
||
if( c_MaskStyleSolid == m_nMaskStyle )
|
||
{
|
||
for( int nCountPixels = nWidth*nHeight; nCountPixels > 0; --nCountPixels, pMaskPixel += 1, pBufferPixel += 4 )
|
||
{
|
||
if( *pMaskPixel )
|
||
{
|
||
pBufferPixel[0] = BYTE((pBufferPixel[0] + nSelectionBlue) >> 1);
|
||
pBufferPixel[1] = BYTE((pBufferPixel[1] + nSelectionGreen) >> 1);
|
||
pBufferPixel[2] = BYTE((pBufferPixel[2] + nSelectionRed) >> 1);
|
||
}
|
||
}
|
||
}
|
||
else if( m_nMaskStyle > c_MaskStyleBorder && m_nMaskStyle <= c_MaskStyleThatches )
|
||
{
|
||
const BYTE* pPattern = &c_Patterns[m_nMaskStyle - c_MaskStyleBorder][0][0];
|
||
|
||
for( int nRow = 0; nRow < m_nHeight; ++nRow )
|
||
{
|
||
for( int nPos = 0; nPos < m_nWidth; ++nPos, ++m_pMask )
|
||
{
|
||
if( pPattern[(nRow & 7) << 3 + (nPos & 7)] )
|
||
{
|
||
pBufferPixel[0] = BYTE((pBufferPixel[0] + nSelectionBlue) >> 1);
|
||
pBufferPixel[1] = BYTE((pBufferPixel[1] + nSelectionGreen) >> 1);
|
||
pBufferPixel[2] = BYTE((pBufferPixel[2] + nSelectionRed) >> 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
pImage = pBuffer;
|
||
}
|
||
}
|
||
|
||
int nDstStride = ImageStudioUtils::Align32(nWidth * nChannels);
|
||
|
||
// retrieve selection color components
|
||
COLORREF nBackground1; OleTranslateColor(m_nBackColor1, NULL, &nBackground1);
|
||
|
||
int nBackgroundRed1 = GetRValue(nBackground1);
|
||
int nBackgroundGreen1 = GetGValue(nBackground1);
|
||
int nBackgroundBlue1 = GetBValue(nBackground1);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>
|
||
IppiSize DstSize = {nWidth, nHeight};
|
||
Ipp8u BackColor[4] = {
|
||
GetBValue(nBackground1),
|
||
GetGValue(nBackground1),
|
||
GetRValue(nBackground1),
|
||
255
|
||
};
|
||
|
||
ippiSet_8u_C4R( BackColor, pPixels, nDstStride, DstSize);
|
||
|
||
if( m_nBackStyle > c_BackStyleSolid && m_nBackStyle < c_BackStyleThatches )
|
||
{
|
||
COLORREF nBackground2; OleTranslateColor(m_nBackColor2, NULL, &nBackground2);
|
||
|
||
nBackground2 |= 0xff000000;
|
||
|
||
DWORD* pCurrentPixel = (DWORD*)pPixels;
|
||
const BYTE* pPattern = &c_Patterns[m_nBackStyle - c_BackStyleSolid][0][0];
|
||
|
||
for( int nRow = 0; nRow < nHeight; ++nRow )
|
||
{
|
||
for( int nPos = 0; nPos < nWidth; ++nPos, pCurrentPixel += 1 )
|
||
{
|
||
if( pPattern[(nRow & 7) << 3 + (nPos & 7)] )
|
||
{
|
||
pCurrentPixel[0] = nBackground2;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
IppiSize SrcSize = {m_nWidth, m_nHeight};
|
||
IppiRect SrcRect = {0, 0, m_nWidth, m_nHeight};
|
||
IppiRect OutRect = {0, 0, nWidth, nHeight};
|
||
|
||
double dX = (nWidth - m_nWidth * m_dZoom)*0.5;
|
||
double dY = (nHeight - m_nHeight * m_dZoom)*0.5;
|
||
dX += dX > 0 ? 0.5 : -0.5;
|
||
dY += dY > 0 ? 0.5 : -0.5;
|
||
dX = int(dX);
|
||
dY = int(dY);
|
||
|
||
if( dX > 0 )
|
||
{
|
||
OutRect.x = int(dX);
|
||
OutRect.width -= 2 * OutRect.x;
|
||
}
|
||
if( dY > 0 )
|
||
{
|
||
OutRect.y = int(dY);
|
||
OutRect.height -= 2 * OutRect.y;
|
||
}
|
||
|
||
dX += m_dCenterX * m_dZoom - nWidth * 0.5;
|
||
dY += m_dCenterY * m_dZoom - nHeight * 0.5;
|
||
|
||
int nLeft = OutRect.x - int(dX);
|
||
int nRight = nLeft + OutRect.width;
|
||
int nTop = OutRect.y - int(dY);
|
||
int nBottom = nTop + OutRect.height;
|
||
|
||
OutRect.x -= int(dX);
|
||
OutRect.y += int(dY);
|
||
|
||
if( OutRect.x < 0 )
|
||
{
|
||
pImage -= int(OutRect.x / m_dZoom) * 4;
|
||
SrcSize.width += int(OutRect.x / m_dZoom);
|
||
|
||
OutRect.x = 0;
|
||
}
|
||
else if( OutRect.x > nWidth - OutRect.width )
|
||
{
|
||
OutRect.width = nWidth - OutRect.x;
|
||
}
|
||
|
||
if( OutRect.y < 0 )
|
||
{
|
||
pImage -= int(OutRect.y / m_dZoom) * m_nWidth * 4;
|
||
SrcSize.height += int(OutRect.y / m_dZoom);
|
||
|
||
OutRect.y = 0;
|
||
}
|
||
else if( OutRect.y > nHeight - OutRect.height )
|
||
{
|
||
OutRect.height = nHeight - OutRect.y;
|
||
}
|
||
|
||
BYTE* pDstPixels = pPixels + OutRect.y * nDstStride + OutRect.x * 4;
|
||
DstSize.width = OutRect.width;
|
||
DstSize.height = OutRect.height;
|
||
|
||
ippiResize_8u_C4R( pImage, SrcSize, m_nWidth*4, SrcRect, pDstPixels, nDstStride, DstSize, m_dZoom, m_dZoom, IPPI_INTER_LINEAR );
|
||
|
||
// show border (if present)
|
||
if(m_bShowBorder)
|
||
{
|
||
// show vertical sides
|
||
for( int nY = nTop; nY <= nBottom; ++nY )
|
||
{
|
||
// check for valid y coordinate
|
||
if (nY < 0 || nY >= nHeight)
|
||
continue;
|
||
|
||
if (nLeft >= 0 && nLeft < nWidth)
|
||
{
|
||
int nIndex = nChannels*nLeft + (nHeight - 1 - nY)*nDstStride;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
if (nRight >= 0 && nRight < nWidth)
|
||
{
|
||
int nIndex = nChannels*nRight + (nHeight - 1 - nY)*nDstStride;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
}
|
||
|
||
// show horizontal sides
|
||
for( int nX = nLeft; nX <= nRight; ++nX )
|
||
{
|
||
// check for valid x coordinate
|
||
if (nX < 0 || nX >= nWidth)
|
||
continue;
|
||
|
||
if (nTop >= 0 && nTop < nHeight)
|
||
{
|
||
int nIndex = nChannels*nX + (nHeight - 1 - nTop)*nDstStride;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
if (nBottom >= 0 && nBottom < nHeight)
|
||
{
|
||
int nIndex = nChannels*nX + (nHeight - 1 - nBottom)*nDstStride;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
if( pBuffer )
|
||
delete [] pBuffer;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL ExtractRect(int nWidth, int nHeight, int nChannels, BYTE* pPixels)
|
||
{
|
||
// check for valid preview image
|
||
if (!pPixels || !nWidth || !nHeight)
|
||
return FALSE;
|
||
|
||
// variables
|
||
int nSourceX, nSourceY;
|
||
int nLineSize = ImageStudioUtils::Align32(nWidth * nChannels);
|
||
int nX, nY, nOffset, nIndex, nNewIndex;
|
||
int nPatternX, nPatternY;
|
||
|
||
// retrieve selection color components
|
||
COLORREF nSelection; OleTranslateColor(m_nMaskColor, NULL, &nSelection);
|
||
|
||
int nSelectionRed = GetRValue(nSelection);
|
||
int nSelectionGreen = GetGValue(nSelection);
|
||
int nSelectionBlue = GetBValue(nSelection);
|
||
|
||
// retrieve background color components
|
||
COLORREF nBackground1; OleTranslateColor(m_nBackColor1, NULL, &nBackground1);
|
||
COLORREF nBackground2; OleTranslateColor(m_nBackColor2, NULL, &nBackground2);
|
||
|
||
int nBackgroundRed1 = GetRValue(nBackground1);
|
||
int nBackgroundGreen1 = GetGValue(nBackground1);
|
||
int nBackgroundBlue1 = GetBValue(nBackground1);
|
||
|
||
int nBackgroundRed2 = GetRValue(nBackground2);
|
||
int nBackgroundGreen2 = GetGValue(nBackground2);
|
||
int nBackgroundBlue2 = GetBValue(nBackground2);
|
||
|
||
// check for simpliest case
|
||
if (m_nBackStyle == c_BackStyleNone) ZeroMemory(pPixels, nLineSize*nHeight);
|
||
|
||
// preview rectangle variables
|
||
double dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom;
|
||
|
||
// compute preview rectangle coordinates
|
||
ComputeRectangle(dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom);
|
||
|
||
// compute preview rectangle extensions
|
||
double dPreviewWidth = dPreviewRight - dPreviewLeft;
|
||
double dPreviewHeight = dPreviewBottom - dPreviewTop;
|
||
|
||
// compute preview rectangle steps
|
||
double dSourceX, dSourceY;
|
||
double dStepX = dPreviewWidth/(nWidth - 1);
|
||
double dStepY = dPreviewHeight/(nHeight - 1);
|
||
|
||
// extract sub-image pixels
|
||
for (nY = 0, nIndex = 0, dSourceY = dPreviewBottom; nY < nHeight; ++nY, dSourceY -= dStepY, nIndex += nLineSize)
|
||
{
|
||
// compute integer y coordinate
|
||
nSourceY = m_nHeight - 1 - (int)floor(dSourceY);
|
||
|
||
// compute pettern y coordinate
|
||
nPatternY = nY % 8;
|
||
|
||
// row y coordinate is valid - copy row information
|
||
for (nX = 0, nNewIndex = nIndex, dSourceX = dPreviewLeft; nX < nWidth; ++nX, nNewIndex += nChannels, dSourceX += dStepX)
|
||
{
|
||
// compute integer x coordinate
|
||
nSourceX = (int)floor(dSourceX);
|
||
|
||
// compute pettern x coordinate
|
||
nPatternX = nX % 8;
|
||
|
||
// check for valid pixel coordinate
|
||
if (m_pPixels && nSourceY >= 0 && nSourceY < m_nHeight && nSourceX >= 0 && nSourceX < m_nWidth)
|
||
{
|
||
// compute offset
|
||
nOffset = 4*(nSourceX + nSourceY*m_nWidth);
|
||
|
||
// column x coordinate is valid - copy pixel information
|
||
pPixels[nNewIndex + 0] = m_pPixels[nOffset + 0];
|
||
pPixels[nNewIndex + 1] = m_pPixels[nOffset + 1];
|
||
pPixels[nNewIndex + 2] = m_pPixels[nOffset + 2];
|
||
|
||
// check for pixel mask
|
||
if (m_pMask && m_pMask[nOffset/4] && m_nMaskStyle != c_MaskStyleHidden)
|
||
{
|
||
// check for solid selection style
|
||
if (m_nMaskStyle == c_MaskStyleSolid)
|
||
{
|
||
// update pixel color
|
||
pPixels[nNewIndex + 0] = (BYTE)(0.5*(nSelectionBlue + m_pPixels[nOffset + 0]));
|
||
pPixels[nNewIndex + 1] = (BYTE)(0.5*(nSelectionGreen + m_pPixels[nOffset + 1]));
|
||
pPixels[nNewIndex + 2] = (BYTE)(0.5*(nSelectionRed + m_pPixels[nOffset + 2]));
|
||
}
|
||
else
|
||
{
|
||
// compute nearest pixels coordinates
|
||
int nX1 = (int)( dSourceX - dStepX );
|
||
int nX2 = nSourceX;
|
||
int nX3 = (int)( dSourceX + dStepX );
|
||
int nY1 = m_nHeight - 1 - (int)( dSourceY - dStepY );
|
||
int nY2 = nSourceY;
|
||
int nY3 = m_nHeight - 1 - (int)( dSourceY + dStepY );
|
||
|
||
// correct pixels
|
||
if (nX1 < 0) nX1 = nX2;
|
||
if (nX1 >= m_nWidth) nX1 = nX2;
|
||
if (nX3 < 0) nX3 = nX2;
|
||
if (nX3 >= m_nWidth) nX3 = nX2;
|
||
|
||
if (nY1 < 0) nY1 = nY2;
|
||
if (nY1 >= m_nHeight) nY1 = nY2;
|
||
if (nY3 < 0) nY3 = nY2;
|
||
if (nY3 >= m_nHeight) nY3 = nY2;
|
||
|
||
// check whether pixel is on mask border
|
||
if (!m_pMask[nX1 + nY1*m_nWidth] || !m_pMask[nX2 + nY1*m_nWidth] || !m_pMask[nX3 + nY1*m_nWidth] ||
|
||
!m_pMask[nX1 + nY2*m_nWidth] || !m_pMask[nX2 + nY2*m_nWidth] || !m_pMask[nX3 + nY2*m_nWidth] ||
|
||
!m_pMask[nX1 + nY3*m_nWidth] || !m_pMask[nX2 + nY3*m_nWidth] || !m_pMask[nX3 + nY3*m_nWidth])
|
||
{
|
||
// update pixel color
|
||
pPixels[nNewIndex + 0] = (BYTE)(0.5*(nSelectionBlue + m_pPixels[nOffset + 0]));
|
||
pPixels[nNewIndex + 1] = (BYTE)(0.5*(nSelectionGreen + m_pPixels[nOffset + 1]));
|
||
pPixels[nNewIndex + 2] = (BYTE)(0.5*(nSelectionRed + m_pPixels[nOffset + 2]));
|
||
|
||
// proceed to next pixel
|
||
continue;
|
||
}
|
||
|
||
// apply other pixel masking
|
||
if (m_nMaskStyle > c_MaskStyleBorder && m_nMaskStyle < c_MaskStyleThatches)
|
||
{
|
||
if (c_Patterns[m_nMaskStyle - c_MaskStyleBorder][nPatternY][nPatternX])
|
||
{
|
||
pPixels[nNewIndex + 0] = (BYTE)(0.5*(nSelectionBlue + m_pPixels[nOffset + 0]));
|
||
pPixels[nNewIndex + 1] = (BYTE)(0.5*(nSelectionGreen + m_pPixels[nOffset + 1]));
|
||
pPixels[nNewIndex + 2] = (BYTE)(0.5*(nSelectionRed + m_pPixels[nOffset + 2]));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// proceed to next pixel
|
||
continue;
|
||
}
|
||
|
||
// fill pixel with background color
|
||
if (m_nBackStyle == c_BackStyleSolid)
|
||
{
|
||
pPixels[nNewIndex + 0] = nBackgroundBlue1;
|
||
pPixels[nNewIndex + 1] = nBackgroundGreen1;
|
||
pPixels[nNewIndex + 2] = nBackgroundRed1;
|
||
}
|
||
else if (m_nBackStyle > c_BackStyleSolid && m_nBackStyle < c_BackStyleThatches)
|
||
{
|
||
if (c_Patterns[m_nBackStyle][nPatternY][nPatternX])
|
||
{
|
||
pPixels[nNewIndex + 0] = nBackgroundBlue2;
|
||
pPixels[nNewIndex + 1] = nBackgroundGreen2;
|
||
pPixels[nNewIndex + 2] = nBackgroundRed2;
|
||
}
|
||
else
|
||
{
|
||
pPixels[nNewIndex + 0] = nBackgroundBlue1;
|
||
pPixels[nNewIndex + 1] = nBackgroundGreen1;
|
||
pPixels[nNewIndex + 2] = nBackgroundRed1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// show border (if present)
|
||
if(m_bShowBorder)
|
||
{
|
||
// show vertical line
|
||
int nLeft = (int)floor(nWidth*(0 - dPreviewLeft)/dPreviewWidth);
|
||
int nRight = (int)floor(nWidth*(m_nWidth - dPreviewLeft)/dPreviewWidth);
|
||
int nTop = (int)floor(nHeight*(0 - dPreviewTop)/dPreviewHeight);
|
||
int nBottom = (int)floor(nHeight*(m_nHeight - dPreviewTop)/dPreviewHeight);
|
||
|
||
// show vertical sides
|
||
for (nY = nTop; nY <= nBottom; ++nY)
|
||
{
|
||
// check for valid y coordinate
|
||
if (nY < 0 || nY >= nHeight)
|
||
continue;
|
||
|
||
if (nLeft >= 0 && nLeft < nWidth)
|
||
{
|
||
nIndex = nChannels*nLeft + (nHeight - 1 - nY)*nLineSize;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
if (nRight >= 0 && nRight < nWidth)
|
||
{
|
||
nIndex = nChannels*nRight + (nHeight - 1 - nY)*nLineSize;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
}
|
||
|
||
// show horizontal sides
|
||
for (nX = nLeft; nX <= nRight; ++nX)
|
||
{
|
||
// check for valid x coordinate
|
||
if (nX < 0 || nX >= nWidth)
|
||
continue;
|
||
|
||
if (nTop >= 0 && nTop < nHeight)
|
||
{
|
||
nIndex = nChannels*nX + (nHeight - 1 - nTop)*nLineSize;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
if (nBottom >= 0 && nBottom < nHeight)
|
||
{
|
||
nIndex = nChannels*nX + (nHeight - 1 - nBottom)*nLineSize;
|
||
|
||
pPixels[nIndex + 0] = 0;
|
||
pPixels[nIndex + 1] = 0;
|
||
pPixels[nIndex + 2] = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
// all ok
|
||
return TRUE;
|
||
}
|
||
void ShowWindowBorders(HDC hDC, RECT rect)
|
||
{
|
||
RECT rect1, rect2;
|
||
|
||
rect1.left = rect.left;
|
||
rect1.top = rect.top;
|
||
rect1.right = rect.right;
|
||
rect1.bottom = rect.bottom;
|
||
|
||
rect2.left = rect.left + 1;
|
||
rect2.top = rect.top + 1;
|
||
rect2.right = rect.right - 1;
|
||
rect2.bottom = rect.bottom - 1;
|
||
|
||
// show stylized window borders
|
||
if (m_nWindowStyle == c_WindowStyleClient)
|
||
{
|
||
Rendering::Gdi::DrawRectangle3D(hDC, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DLIGHT), rect1);
|
||
Rendering::Gdi::DrawRectangle3D(hDC, GetSysColor(COLOR_3DDKSHADOW), GetSysColor(COLOR_3DHILIGHT), rect2);
|
||
}
|
||
else if (m_nWindowStyle == c_WindowStyleModal)
|
||
{
|
||
Rendering::Gdi::DrawRectangle3D(hDC, GetSysColor(COLOR_3DLIGHT), GetSysColor(COLOR_3DSHADOW), rect1);
|
||
Rendering::Gdi::DrawRectangle3D(hDC, GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DDKSHADOW), rect2);
|
||
}
|
||
else if (m_nWindowStyle == c_WindowStyleStatic)
|
||
{
|
||
Rendering::Gdi::DrawRectangle3D(hDC, GetSysColor(COLOR_3DLIGHT), GetSysColor(COLOR_3DSHADOW), rect1);
|
||
Rendering::Gdi::DrawRectangle3D(hDC, GetSysColor(COLOR_3DDKSHADOW), GetSysColor(COLOR_3DHILIGHT), rect2);
|
||
}
|
||
}
|
||
void ShowTracking(HDC hDC, RECT rect)
|
||
{
|
||
if (!m_pTracking)
|
||
return;
|
||
|
||
// compute preview rectangle coordinates
|
||
double dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom;
|
||
ComputeRectangle(dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom);
|
||
|
||
Structures::RECTI rectWindow(rect);
|
||
Structures::RECTD rectData(dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom);
|
||
|
||
m_oTrackingPainter.Create(hDC);
|
||
m_pTracking->OnPaint(m_oTrackingPainter, rectWindow, rectData);
|
||
}
|
||
void ComputeRectangle(double& dLeft, double& dTop, double& dRight, double& dBottom)
|
||
{
|
||
// retrieve cursor position and preview window rectanlge
|
||
RECT rect; GetWindowRect(&rect);
|
||
|
||
// compute preview image size
|
||
int nWidth = abs(rect.right - rect.left + 1);
|
||
int nHeight = abs(rect.bottom - rect.top + 1);
|
||
|
||
// check for valid simpliest case when image size is invalid
|
||
if (!nWidth || !nHeight)
|
||
return;
|
||
|
||
// compute preview rectangle coordinates
|
||
dLeft = m_dCenterX - 0.5 * nWidth / m_dZoom;
|
||
dRight = m_dCenterX + 0.5 * nWidth / m_dZoom;
|
||
dTop = m_dCenterY - 0.5 * nHeight / m_dZoom;
|
||
dBottom = m_dCenterY + 0.5 * nHeight / m_dZoom;
|
||
}
|
||
void GetMouseState(int& nButton, int& nShift, double& dX, double& dY)
|
||
{
|
||
// retrieve cursor position and preview window rectanlge
|
||
RECT rect; GetWindowRect(&rect);
|
||
POINT point; GetCursorPos(&point);
|
||
|
||
// correct mouse coordinates
|
||
point.x = min(max(point.x, rect.left), rect.right);
|
||
point.y = min(max(point.y, rect.top), rect.bottom);
|
||
|
||
// compute preview image size
|
||
int nWidth = abs(rect.right - rect.left);
|
||
int nHeight = abs(rect.bottom - rect.top);
|
||
|
||
// check for valid simpliest case when image size is invalid
|
||
if (nWidth < 2) nWidth = 2;
|
||
if (nHeight < 2) nHeight = 2;
|
||
|
||
// compute preview rectangle coordinates
|
||
double dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom;
|
||
ComputeRectangle(dPreviewLeft, dPreviewTop, dPreviewRight, dPreviewBottom);
|
||
|
||
// compute click point
|
||
dX = dPreviewLeft + (dPreviewRight - dPreviewLeft)*(point.x - rect.left)/nWidth;
|
||
dY = dPreviewTop + (dPreviewBottom - dPreviewTop)*(point.y - rect.top)/nHeight;
|
||
|
||
// compute mouse button state
|
||
nButton = GetKeyState(VK_LBUTTON) < 0 ? 1 : GetKeyState(VK_RBUTTON) < 0 ? 2 : GetKeyState(VK_MBUTTON) < 0 ? 4 : 0;
|
||
nShift = (GetKeyState(VK_SHIFT) < 0 ? 1 : 0) + (GetKeyState(VK_CONTROL) < 0 ? 2 : 0) + (GetKeyState(VK_MENU) < 0 ? 4 : 0);
|
||
}
|
||
void GetTrackArray(SAFEARRAY** pArray, BOOL bAspectAdd)
|
||
{
|
||
// check for valid safe array
|
||
if (!pArray || !m_pTracking) return;
|
||
|
||
// compute SAFEARRAY bounds
|
||
SAFEARRAYBOUND rgsaBound[1];
|
||
rgsaBound[0].lLbound = 0;
|
||
rgsaBound[0].cElements = 2*m_pTracking->GetCount();
|
||
|
||
// create array
|
||
*pArray = SafeArrayCreate(VT_R8, 1, rgsaBound);
|
||
|
||
// retrieve data pointer
|
||
double* pData = (double*)((*pArray)->pvData);
|
||
|
||
// fill the array
|
||
for (int nIndex = 0; nIndex < m_pTracking->GetCount(); ++nIndex)
|
||
{
|
||
if (bAspectAdd)
|
||
{
|
||
pData[2*nIndex + 0] = AspectXAdd(m_pTracking->GetAt(nIndex).dX);
|
||
pData[2*nIndex + 1] = AspectYAdd(m_pTracking->GetAt(nIndex).dY);
|
||
}
|
||
else
|
||
{
|
||
pData[2*nIndex + 0] = m_pTracking->GetAt(nIndex).dX;
|
||
pData[2*nIndex + 1] = m_pTracking->GetAt(nIndex).dY;
|
||
}
|
||
}
|
||
}
|
||
BOOL SetTrackArray(SAFEARRAY** pArray, BOOL bAspectRemove)
|
||
{
|
||
// check for valid input parameters
|
||
if (!pArray || !(*pArray))
|
||
return FALSE;
|
||
|
||
// variables
|
||
VARTYPE type;
|
||
long lBound, uBound;
|
||
|
||
// check for valid pixel array size
|
||
if (SafeArrayGetDim(*pArray) != 1)
|
||
return FALSE;
|
||
|
||
// check for valid array element type
|
||
if (FAILED(SafeArrayGetVartype(*pArray, &type)) || type != VT_R8 || SafeArrayGetElemsize(*pArray) != 8)
|
||
return FALSE;
|
||
|
||
// retrieve image attributes
|
||
if (FAILED(SafeArrayGetLBound(*pArray, 1, &lBound)) || FAILED(SafeArrayGetUBound(*pArray, 1, &uBound)))
|
||
return FALSE;
|
||
|
||
// compute image attributes
|
||
int nSize = 1 + uBound - lBound;
|
||
|
||
// check that the array contains 2*n doubles
|
||
if (nSize % 2)
|
||
return FALSE;
|
||
|
||
m_pTracking->SetSize(nSize/2);
|
||
double* pData = (double*)(*pArray)->pvData;
|
||
|
||
// fill the array
|
||
for (int nIndex = 0; nIndex < m_pTracking->GetCount(); ++nIndex)
|
||
{
|
||
if (bAspectRemove)
|
||
{
|
||
m_pTracking->GetAt(nIndex).dX = AspectXRemove(pData[2*nIndex + 0]);
|
||
m_pTracking->GetAt(nIndex).dY = AspectYRemove(pData[2*nIndex + 1]);
|
||
}
|
||
else
|
||
{
|
||
m_pTracking->GetAt(nIndex).dX = pData[2*nIndex + 0];
|
||
m_pTracking->GetAt(nIndex).dY = pData[2*nIndex + 1];
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
BOOL SafeArrayToPoints(SAFEARRAY** pArray, BOOL bAspectRemove, Structures::POINTD*& pPoints, int& nCount)
|
||
{
|
||
// check for valid input parameters
|
||
if (!pArray || !(*pArray))
|
||
return FALSE;
|
||
|
||
// variables
|
||
VARTYPE type;
|
||
long lBound, uBound;
|
||
|
||
// check for valid pixel array size
|
||
if (SafeArrayGetDim(*pArray) != 1)
|
||
return FALSE;
|
||
|
||
// check for valid array element type
|
||
if (FAILED(SafeArrayGetVartype(*pArray, &type)) || type != VT_R8 || SafeArrayGetElemsize(*pArray) != 8)
|
||
return FALSE;
|
||
|
||
// retrieve image attributes
|
||
if (FAILED(SafeArrayGetLBound(*pArray, 1, &lBound)) || FAILED(SafeArrayGetUBound(*pArray, 1, &uBound)))
|
||
return FALSE;
|
||
|
||
// compute image attributes
|
||
int nSize = 1 + uBound - lBound;
|
||
|
||
// check that the array contains 2*n doubles
|
||
if ((nSize % 2) || (nSize/2 >= 127))
|
||
return FALSE;
|
||
|
||
nCount = nSize/2;
|
||
pPoints = new Structures::POINTD[nCount];
|
||
double* pData = (double*)(*pArray)->pvData;
|
||
|
||
// fill the array
|
||
for (int index = 0; index < nCount; ++index)
|
||
{
|
||
if (bAspectRemove)
|
||
{
|
||
pPoints[index].x = AspectXRemove(pData[2*index + 0]);
|
||
pPoints[index].y = AspectYRemove(pData[2*index + 1]);
|
||
}
|
||
else
|
||
{
|
||
pPoints[index].x = pData[2*index + 0];
|
||
pPoints[index].y = pData[2*index + 1];
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
void BeginTrack(Tracking::CTrackObject* pTracking)
|
||
{
|
||
// destroy old tracking object
|
||
if (m_pTracking)
|
||
{
|
||
delete m_pTracking;
|
||
m_pTracking = 0;
|
||
}
|
||
|
||
// check for valid new tracking object
|
||
m_pTracking = pTracking;
|
||
|
||
// setup message receiver for tracking object
|
||
m_pTracking->SetReceiver(this);
|
||
|
||
// update preview
|
||
OnPaint(c_SenderTrack);
|
||
}
|
||
|
||
double AspectXAdd(double x)
|
||
{
|
||
if (m_dAspect < 0.001)
|
||
return x;
|
||
|
||
return m_nAspectWidth*x/m_nWidth;
|
||
}
|
||
double AspectYAdd(double y)
|
||
{
|
||
if (m_dAspect < 0.001)
|
||
return y;
|
||
|
||
return m_nAspectHeight*y/m_nHeight;
|
||
}
|
||
double AspectXRemove(double x)
|
||
{
|
||
if (m_dAspect < 0.001)
|
||
return x;
|
||
|
||
return m_nWidth*x/m_nAspectWidth;
|
||
}
|
||
double AspectYRemove(double y)
|
||
{
|
||
if (m_dAspect < 0.001)
|
||
return y;
|
||
|
||
return m_nHeight*y/m_nAspectHeight;
|
||
}
|
||
|
||
void BGRA_Flip(BYTE* pBGRA, int nWidth, int nHeight)
|
||
{
|
||
/* @desc:
|
||
int BGRA_Flip(BYTE* pBGRA, int nWidth, int nHeight)
|
||
{
|
||
<09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (pBGRA, nWidth, nHeight)
|
||
}
|
||
*/
|
||
|
||
if (NULL == pBGRA)
|
||
return;
|
||
|
||
int nLineSize = 4*nWidth;
|
||
|
||
BYTE* pBGRALineCopy = new BYTE[nLineSize];
|
||
if (NULL == pBGRALineCopy)
|
||
return;
|
||
|
||
BYTE* pBGRALineTop = pBGRA;
|
||
BYTE* pBGRALineBottom = pBGRA + nLineSize*(nHeight - 1);
|
||
|
||
for (int nY = 0; nY < nHeight/2; ++nY)
|
||
{
|
||
memcpy(pBGRALineCopy, pBGRALineTop, nLineSize);
|
||
memcpy(pBGRALineTop, pBGRALineBottom, nLineSize);
|
||
memcpy(pBGRALineBottom, pBGRALineCopy, nLineSize);
|
||
|
||
pBGRALineTop += nLineSize;
|
||
pBGRALineBottom -= nLineSize;
|
||
}
|
||
|
||
delete[] pBGRALineCopy;
|
||
}
|
||
|
||
public:
|
||
|
||
// event wrappers with coordinates corrections
|
||
void FireEvent(int Type)
|
||
{
|
||
if (!m_pTracking || m_pTracking->GetCount() < 1)
|
||
return;
|
||
|
||
// check for event type
|
||
if (m_pTracking->IsTrackPoint())
|
||
{
|
||
TrackPoint(Type, AspectXAdd(m_pTracking->GetAt(0).dX), AspectYAdd(m_pTracking->GetAt(0).dY));
|
||
}
|
||
else if (m_pTracking->IsTrackRectangleFixedSize())
|
||
{
|
||
TrackRectangleFixedSize(Type, AspectXAdd(m_pTracking->GetAt(0).dX), AspectYAdd(m_pTracking->GetAt(0).dY));
|
||
}
|
||
else if (m_pTracking->IsTrackRectangleFixedAspect())
|
||
{
|
||
TrackRectangleFixedAspect(Type, AspectXAdd(m_pTracking->GetAt(0).dX), AspectYAdd(m_pTracking->GetAt(0).dY), AspectXAdd(m_pTracking->GetAt(2).dX), AspectYAdd(m_pTracking->GetAt(2).dY));
|
||
}
|
||
else if (m_pTracking->IsTrackLine())
|
||
{
|
||
TrackLine(Type, AspectXAdd(m_pTracking->GetAt(0).dX), AspectYAdd(m_pTracking->GetAt(0).dY), AspectXAdd(m_pTracking->GetAt(1).dX), AspectYAdd(m_pTracking->GetAt(1).dY));
|
||
}
|
||
else if (m_pTracking->IsTrackEllipse())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
|
||
rectD.Normalize();
|
||
|
||
TrackEllipse(Type, AspectXAdd(rectD.left), AspectYAdd(rectD.top), AspectXAdd(rectD.right), AspectYAdd(rectD.bottom));
|
||
}
|
||
else if (m_pTracking->IsTrackRectangle())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
|
||
rectD.Normalize();
|
||
|
||
TrackRectangle(Type, AspectXAdd(rectD.left), AspectYAdd(rectD.top), AspectXAdd(rectD.right), AspectYAdd(rectD.bottom));
|
||
}
|
||
else if( m_pTracking->IsTrackRectangleRotatable() )
|
||
{
|
||
double dAngle = Geometry::GetAngle( m_pTracking->GetAt(9).dX, m_pTracking->GetAt(9).dY, m_pTracking->GetAt(8).dX, m_pTracking->GetAt(8).dY) + M_PI_2;
|
||
|
||
Structures::RECTD rectD = m_pTracking->GetUnrotatableRect( dAngle );
|
||
|
||
dAngle = grad( ((dAngle <= 0 )? dAngle + 2.0 * M_PI: dAngle));
|
||
|
||
TrackRectangleRotatable( Type, AspectXAdd( rectD.left ), AspectYAdd( rectD.top ), AspectXAdd( rectD.right ), AspectYAdd( rectD.bottom ), dAngle);
|
||
}
|
||
else if( m_pTracking->IsTrackRectangleRotatableFixedAspect() )
|
||
{
|
||
double dAngle = Geometry::GetAngle( m_pTracking->GetAt(5).dX, m_pTracking->GetAt(5).dY, m_pTracking->GetAt(4).dX, m_pTracking->GetAt(4).dY) + M_PI_2;
|
||
|
||
Structures::RECTD rectD = m_pTracking->GetUnrotatableRect( dAngle, 0, 2, 5 );
|
||
|
||
dAngle = grad( ((dAngle <= 0 )? dAngle + 2.0 * M_PI: dAngle));
|
||
|
||
TrackRectangleRotatableFixedAspect( Type, AspectXAdd( rectD.left ), AspectYAdd( rectD.top ), AspectXAdd( rectD.right ), AspectYAdd( rectD.bottom ), dAngle );
|
||
}
|
||
else if (m_pTracking->IsTrackPolyline())
|
||
{
|
||
SAFEARRAY* pArray = 0; GetTrackArray(&pArray, TRUE);
|
||
|
||
TrackPolyline(Type, (BYTE*)pArray);
|
||
|
||
SafeArrayDestroy(pArray);
|
||
}
|
||
else if (m_pTracking->IsTrackPolygon())
|
||
{
|
||
SAFEARRAY* pArray = 0; GetTrackArray(&pArray, TRUE);
|
||
|
||
TrackPolygon(Type, (BYTE*)pArray);
|
||
|
||
SafeArrayDestroy(pArray);
|
||
}
|
||
else if (m_pTracking->IsTrackPie())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
rectD.Normalize();
|
||
|
||
// get center and angles
|
||
double dCenterX = rectD.GetCenter().x;
|
||
double dCenterY = rectD.GetCenter().y;
|
||
|
||
double dAngle1 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(5).dX, m_pTracking->GetAt(5).dY));
|
||
double dAngle2 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(4).dX, m_pTracking->GetAt(4).dY));
|
||
dAngle1 = (dAngle1 >= 0)? dAngle1 : 360 + dAngle1;
|
||
dAngle2 = (dAngle2 >= 0)? dAngle2 : 360 + dAngle2;
|
||
double SweepAngle = dAngle2 - dAngle1;
|
||
SweepAngle = (SweepAngle >= 0)? SweepAngle : 360 + SweepAngle;
|
||
|
||
TrackPie(Type, AspectXAdd(rectD.left), AspectYAdd(rectD.top), AspectXAdd(rectD.right), AspectYAdd(rectD.bottom), dAngle1, SweepAngle);
|
||
}
|
||
else if (m_pTracking->IsTrackPieSimple())
|
||
{
|
||
// get center, radiuses and angles
|
||
double dCenterX = m_pTracking->GetAt(2).dX;
|
||
double dCenterY = m_pTracking->GetAt(2).dY;
|
||
|
||
double dAngle1 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(1).dX, m_pTracking->GetAt(1).dY));
|
||
double dAngle2 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(0).dX, m_pTracking->GetAt(0).dY));
|
||
dAngle1 = (dAngle1 >= 0)? dAngle1 : 360 + dAngle1;
|
||
dAngle2 = (dAngle2 >= 0)? dAngle2 : 360 + dAngle2;
|
||
double SweepAngle = dAngle2 - dAngle1;
|
||
SweepAngle = (SweepAngle >= 0)? SweepAngle : 360 + SweepAngle;
|
||
|
||
// apply aspect correction
|
||
dCenterX = AspectXAdd(dCenterX);
|
||
dCenterY = AspectYAdd(dCenterY);
|
||
|
||
// get radius
|
||
double dRadius = fabs(dCenterX - AspectXAdd(m_pTracking->GetAt(3).dX));
|
||
|
||
// event track simple pie
|
||
TrackSimplePie(Type, dCenterX, dCenterY, dRadius, dAngle1, SweepAngle);
|
||
}
|
||
else if (m_pTracking->IsTrackSector())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
rectD.Normalize();
|
||
|
||
// get center, radiuses and angles
|
||
double dCenterX = rectD.GetCenter().x;
|
||
double dCenterY = rectD.GetCenter().y;
|
||
|
||
double dAngle1 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(7).dX, m_pTracking->GetAt(7).dY));
|
||
double dAngle2 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(6).dX, m_pTracking->GetAt(6).dY));
|
||
dAngle1 = (dAngle1 >= 0)? dAngle1 : 360 + dAngle1;
|
||
dAngle2 = (dAngle2 >= 0)? dAngle2 : 360 + dAngle2;
|
||
double SweepAngle = dAngle2 - dAngle1;
|
||
SweepAngle = (SweepAngle >= 0)? SweepAngle : 360 + SweepAngle;
|
||
|
||
double dRadius1 = Geometry::GetLength(dCenterX, dCenterY, m_pTracking->GetAt(6).dX, m_pTracking->GetAt(6).dY);
|
||
double dRadius2 = Geometry::GetLength(dCenterX, dCenterY, m_pTracking->GetAt(4).dX, m_pTracking->GetAt(4).dY);
|
||
double dRatio = (dRadius1 < 0.001)? 1. : dRadius2/dRadius1;
|
||
|
||
TrackSector(Type, AspectXAdd(rectD.left), AspectYAdd(rectD.top), AspectXAdd(rectD.right), AspectYAdd(rectD.bottom), dAngle1, SweepAngle, dRatio);
|
||
}
|
||
else if (m_pTracking->IsTrackSectorSimple())
|
||
{
|
||
// get center
|
||
double dCenterX = m_pTracking->GetAt(4).dX;
|
||
double dCenterY = m_pTracking->GetAt(4).dY;
|
||
|
||
// get angles
|
||
double dAngle1 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(1).dX, m_pTracking->GetAt(1).dY));
|
||
double dAngle2 = grad(Geometry::GetAngle(dCenterX, dCenterY, m_pTracking->GetAt(0).dX, m_pTracking->GetAt(0).dY));
|
||
dAngle1 = (dAngle1 >= 0)? dAngle1 : 360 + dAngle1;
|
||
dAngle2 = (dAngle2 >= 0)? dAngle2 : 360 + dAngle2;
|
||
double SweepAngle = dAngle2 - dAngle1;
|
||
SweepAngle = (SweepAngle >= 0)? SweepAngle : 360 + SweepAngle;
|
||
|
||
// set aspect for center
|
||
dCenterX = AspectXAdd(dCenterX);
|
||
dCenterY = AspectYAdd(dCenterY);
|
||
|
||
// get radiuses
|
||
double dRadius1 = fabs(dCenterX - AspectXAdd(m_pTracking->GetAt(5).dX));
|
||
double dRadius2 = fabs(dCenterX - AspectXAdd(m_pTracking->GetAt(9).dX));
|
||
|
||
// event track simple sector
|
||
TrackSimpleSector(Type, dCenterX, dCenterY, dRadius1, dRadius2, dAngle1, SweepAngle);
|
||
}
|
||
else if (m_pTracking->IsTrackCircle())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
|
||
rectD.Normalize();
|
||
|
||
// get center and angles
|
||
double dCenterX = rectD.GetCenter().x;
|
||
double dCenterY = rectD.GetCenter().y;
|
||
|
||
// apply aspect correction
|
||
dCenterX = AspectXAdd(dCenterX);
|
||
dCenterY = AspectYAdd(dCenterY);
|
||
|
||
// get radius
|
||
double dRadius = fabs(dCenterX - AspectXAdd(m_pTracking->GetAt(0).dX));
|
||
|
||
TrackCircle(Type, dCenterX, dCenterY, dRadius);
|
||
}
|
||
else if (m_pTracking->IsTrackEllipseInRectangle())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
|
||
rectD.Normalize();
|
||
|
||
TrackEllipseInRectangle(Type, AspectXAdd(rectD.left), AspectYAdd(rectD.top), AspectXAdd(rectD.right), AspectYAdd(rectD.bottom));
|
||
}
|
||
else if (m_pTracking->IsTrackTextRotatable())
|
||
{
|
||
double dAngle = Geometry::GetAngle( m_pTracking->GetAt(9).dX, m_pTracking->GetAt(9).dY, m_pTracking->GetAt(8).dX, m_pTracking->GetAt(8).dY) + M_PI_2;
|
||
|
||
Structures::RECTD rectD = m_pTracking->GetUnrotatableRect( dAngle );
|
||
|
||
dAngle = grad( ((dAngle <= 0 )? dAngle + 2.0 * M_PI: dAngle));
|
||
|
||
Tracking::CTrackObjectTextRotatable *pTrackingTextRotatable = dynamic_cast <Tracking::CTrackObjectTextRotatable*> (m_pTracking);
|
||
CString resString = "";
|
||
if( NULL != pTrackingTextRotatable ) resString = pTrackingTextRotatable->GetString();
|
||
|
||
TrackTextRotatable( Type, AspectXAdd( rectD.left ), AspectYAdd( rectD.top ), AspectXAdd( rectD.right ), AspectYAdd( rectD.bottom ), dAngle, resString.AllocSysString() );
|
||
}
|
||
else if (m_pTracking->IsTrackText())
|
||
{
|
||
Structures::RECTD rectD = m_pTracking->GetDoubleBoundingRect(0, 3);
|
||
|
||
rectD.Normalize();
|
||
|
||
Tracking::CTrackObjectText *pTrackingText = dynamic_cast <Tracking::CTrackObjectText*> (m_pTracking);
|
||
CString resString = "";
|
||
if( NULL != pTrackingText ) resString = pTrackingText->GetString();
|
||
|
||
TrackText(Type, AspectXAdd(rectD.left), AspectYAdd(rectD.top), AspectXAdd(rectD.right), AspectYAdd(rectD.bottom), resString.AllocSysString());
|
||
}
|
||
else if (m_pTracking->IsTrackTrajectoryPolyline())
|
||
{
|
||
SAFEARRAY* pArray = 0; GetTrackArray(&pArray, TRUE);
|
||
|
||
TrackTrajectoryPolyline(Type, (BYTE*)pArray);
|
||
|
||
SafeArrayDestroy(pArray);
|
||
}
|
||
}
|
||
|
||
public:
|
||
|
||
// common
|
||
STDMETHOD(SetImage)(SAFEARRAY** Image)
|
||
{
|
||
|
||
if (!CRegistratorClient::IsRegistered())
|
||
return S_OK;
|
||
|
||
// destroy existing image
|
||
Clear();
|
||
|
||
// variables
|
||
int nWidth = 0;
|
||
int nHeight = 0;
|
||
int nChannels = 0;
|
||
BYTE* pPixels = 0;
|
||
|
||
// extract image from the array
|
||
pPixels = ImageStudioUtils::ExtractImage(Image, nWidth, nHeight, nChannels);
|
||
|
||
// check that the image is valid
|
||
if (!pPixels || nWidth < 2 || nHeight < 2 || nChannels != 4)
|
||
return S_OK;
|
||
|
||
// save image parameters
|
||
m_nWidth = nWidth;
|
||
m_nHeight = nHeight;
|
||
|
||
// save non-aspected image
|
||
m_nAspectWidth = m_nWidth;
|
||
m_nAspectHeight = m_nHeight;
|
||
|
||
// apply aspect correction
|
||
if (m_dAspect >= 0.001)
|
||
{
|
||
// apply aspect correction to the image
|
||
double dAspectZoom = min(m_nWidth/(m_nHeight*m_dAspect), 1.0);
|
||
|
||
// compute aspected image width and height
|
||
int nAspectWidth = (int)(dAspectZoom*m_nHeight*m_dAspect);
|
||
int nAspectHeight = (int)(dAspectZoom*m_nHeight);
|
||
|
||
// allocate memory for new mask
|
||
m_pPixels = new BYTE[4*m_nWidth*m_nHeight];
|
||
|
||
// check for allocated memory
|
||
if (!m_pPixels)
|
||
{
|
||
Clear();
|
||
return S_OK;
|
||
}
|
||
|
||
// variables
|
||
int nSrcX, nSrcY, nSrcIndex = 0;
|
||
int nDstX, nDstY, nDstIndex = 0;
|
||
|
||
// resize image from [m_nWidth,m_nHeight] to [nAspectWidth,nAspectHeight]
|
||
for (nDstY = 0; nDstY < nAspectHeight; ++nDstY)
|
||
{
|
||
nSrcY = (m_nHeight - 1)*nDstY/(nAspectHeight - 1);
|
||
|
||
nSrcIndex = 4*nSrcY*m_nWidth;
|
||
|
||
for (nDstX = 0; nDstX < nAspectWidth; ++nDstX, nDstIndex += 4)
|
||
{
|
||
nSrcX = (m_nWidth - 1)*nDstX/(nAspectWidth - 1);
|
||
nSrcX = nSrcIndex + 4*nSrcX;
|
||
|
||
m_pPixels[nDstIndex + 0] = pPixels[nSrcX + 0];
|
||
m_pPixels[nDstIndex + 1] = pPixels[nSrcX + 1];
|
||
m_pPixels[nDstIndex + 2] = pPixels[nSrcX + 2];
|
||
}
|
||
}
|
||
|
||
// save image size
|
||
m_nWidth = nAspectWidth;
|
||
m_nHeight = nAspectHeight;
|
||
}
|
||
else
|
||
{
|
||
// allocate memory for new mask
|
||
m_pPixels = new BYTE[4*m_nWidth*m_nHeight];
|
||
|
||
// check for allocated memory
|
||
if (!m_pPixels)
|
||
{
|
||
Clear();
|
||
return S_OK;
|
||
}
|
||
|
||
// retrieve data from safe array
|
||
memcpy(m_pPixels, pPixels, 4*m_nWidth*m_nHeight);
|
||
}
|
||
|
||
// remove mask
|
||
if (m_pMask)
|
||
{
|
||
delete[] m_pMask;
|
||
m_pMask = 0;
|
||
}
|
||
|
||
// update window
|
||
return Refresh();
|
||
}
|
||
STDMETHOD(SetMediaData)(IUnknown* pInterface)
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> safearray <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (FALSE)
|
||
{
|
||
SAFEARRAY* pImageArray = NULL;
|
||
if (ImageStudioUtils::MediaDataToSafeArray(&pInterface, pImageArray))
|
||
{
|
||
try
|
||
{
|
||
MediaCore::IAVSUncompressedVideoFrame* pFrame = (MediaCore::IAVSUncompressedVideoFrame*)pInterface;
|
||
if (NULL != pFrame)
|
||
{
|
||
long nAspectX = 0;
|
||
long nAspectY = 0;
|
||
|
||
pFrame->get_AspectRatioX(&nAspectX);
|
||
pFrame->get_AspectRatioY(&nAspectY);
|
||
|
||
if (nAspectX > 0 && nAspectY > 0)
|
||
m_dAspect = nAspectX/(double)nAspectY;
|
||
else
|
||
m_dAspect = -1.0;
|
||
}
|
||
}
|
||
catch (...)
|
||
{
|
||
}
|
||
|
||
SetImage(&pImageArray);
|
||
ImageStudioUtils::DestroySafeArray(&pImageArray);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (NULL == pInterface)
|
||
return S_OK;
|
||
|
||
MediaCore::IAVSUncompressedVideoFrame* pFrame = NULL;
|
||
pInterface->QueryInterface(MediaCore::IID_IAVSUncompressedVideoFrame, (void**)&pFrame);
|
||
|
||
BYTE* pPixels = NULL;
|
||
long nWidth = 0;
|
||
long nHeight = 0;
|
||
BOOL bIsOK = TRUE;
|
||
|
||
BOOL bIsResize = TRUE;
|
||
BOOL bIsFlip = FALSE;
|
||
|
||
BOOL bIsReleaseEndOnly = FALSE;
|
||
|
||
if (NULL != pFrame)
|
||
{
|
||
long lColorspace = pFrame->ColorSpace;
|
||
if (lColorspace != CSP_BGRA && lColorspace != (CSP_BGRA | CSP_VFLIP))
|
||
{
|
||
RELEASEINTERFACE(pFrame);
|
||
if (!ImageStudioUtils::MediaDataToBGRAMediaData(&pInterface, pFrame, FALSE))
|
||
{
|
||
RELEASEINTERFACE(pFrame);
|
||
bIsOK = FALSE;
|
||
return S_FALSE;
|
||
}
|
||
if (NULL != pFrame)
|
||
{
|
||
lColorspace = pFrame->ColorSpace;
|
||
bIsReleaseEndOnly = TRUE;
|
||
}
|
||
}
|
||
|
||
pFrame->get_Buffer(&pPixels);
|
||
|
||
bIsFlip = (lColorspace == CSP_BGRA);
|
||
|
||
long nAspectX = 0;
|
||
long nAspectY = 0;
|
||
|
||
pFrame->get_Width(&nWidth);
|
||
pFrame->get_Height(&nHeight);
|
||
|
||
pFrame->get_AspectRatioX(&nAspectX);
|
||
pFrame->get_AspectRatioY(&nAspectY);
|
||
|
||
if (nAspectX > 0 && nAspectY > 0)
|
||
m_dAspect = (double)nAspectX / nAspectY;
|
||
else
|
||
m_dAspect = -1.0;
|
||
|
||
if (m_dAspect == (((double)nWidth) / nHeight))
|
||
{
|
||
bIsResize = FALSE;
|
||
}
|
||
|
||
if (!bIsReleaseEndOnly)
|
||
{
|
||
RELEASEINTERFACE(pFrame);
|
||
}
|
||
|
||
if ((NULL == pPixels) || (nWidth < 2 || nHeight < 2))
|
||
{
|
||
bIsOK = FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
bIsOK = FALSE;
|
||
}
|
||
|
||
if (!bIsOK)
|
||
{
|
||
RELEASEINTERFACE(pFrame);
|
||
return S_OK;
|
||
}
|
||
|
||
Clear();
|
||
|
||
// save image parameters
|
||
m_nWidth = nWidth;
|
||
m_nHeight = nHeight;
|
||
|
||
// save non-aspected image
|
||
m_nAspectWidth = m_nWidth;
|
||
m_nAspectHeight = m_nHeight;
|
||
|
||
// apply aspect correction
|
||
if (m_dAspect >= 0.001 && bIsResize)
|
||
{
|
||
// apply aspect correction to the image
|
||
double dAspectZoom = min(m_nWidth/(m_nHeight*m_dAspect), 1.0);
|
||
|
||
// compute aspected image width and height
|
||
int nAspectWidth = (int)(dAspectZoom*m_nHeight*m_dAspect);
|
||
int nAspectHeight = (int)(dAspectZoom*m_nHeight);
|
||
|
||
// allocate memory for new mask
|
||
m_pPixels = new BYTE[4*m_nWidth*m_nHeight];
|
||
|
||
// check for allocated memory
|
||
if (!m_pPixels)
|
||
{
|
||
Clear();
|
||
RELEASEINTERFACE(pFrame);
|
||
return S_OK;
|
||
}
|
||
|
||
// variables
|
||
int nSrcX, nSrcY, nSrcIndex = 0;
|
||
int nDstX, nDstY, nDstIndex = 0;
|
||
|
||
// resize image from [m_nWidth,m_nHeight] to [nAspectWidth,nAspectHeight]
|
||
for (nDstY = 0; nDstY < nAspectHeight; ++nDstY)
|
||
{
|
||
nSrcY = (m_nHeight - 1)*nDstY/(nAspectHeight - 1);
|
||
|
||
nSrcIndex = 4*nSrcY*m_nWidth;
|
||
|
||
for (nDstX = 0; nDstX < nAspectWidth; ++nDstX, nDstIndex += 4)
|
||
{
|
||
nSrcX = (m_nWidth - 1)*nDstX/(nAspectWidth - 1);
|
||
nSrcX = nSrcIndex + 4*nSrcX;
|
||
|
||
m_pPixels[nDstIndex + 0] = pPixels[nSrcX + 0];
|
||
m_pPixels[nDstIndex + 1] = pPixels[nSrcX + 1];
|
||
m_pPixels[nDstIndex + 2] = pPixels[nSrcX + 2];
|
||
}
|
||
}
|
||
|
||
// save image size
|
||
m_nWidth = nAspectWidth;
|
||
m_nHeight = nAspectHeight;
|
||
|
||
if (bIsFlip)
|
||
{
|
||
BGRA_Flip(m_pPixels, m_nWidth, m_nHeight);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// allocate memory for new mask
|
||
m_pPixels = new BYTE[4*m_nWidth*m_nHeight];
|
||
|
||
// check for allocated memory
|
||
if (!m_pPixels)
|
||
{
|
||
Clear();
|
||
RELEASEINTERFACE(pFrame);
|
||
return S_OK;
|
||
}
|
||
|
||
if (bIsFlip)
|
||
{
|
||
BYTE* pLineDst = m_pPixels;
|
||
BYTE* pLineSrc = pPixels;
|
||
|
||
int nCountLines = m_nHeight;
|
||
int nSizeLine = 4 * m_nWidth;
|
||
for (int nIndex = 0; nIndex < nCountLines; ++nIndex)
|
||
{
|
||
pLineSrc = pPixels + (nCountLines - nIndex - 1) * nSizeLine;
|
||
memcpy(pLineDst, pLineSrc, nSizeLine);
|
||
pLineDst += nSizeLine;
|
||
}
|
||
}
|
||
|
||
else
|
||
{
|
||
// retrieve data from safe array
|
||
memcpy(m_pPixels, pPixels, 4*m_nWidth*m_nHeight);
|
||
}
|
||
}
|
||
|
||
// remove mask
|
||
if (m_pMask)
|
||
{
|
||
delete[] m_pMask;
|
||
m_pMask = 0;
|
||
}
|
||
|
||
RELEASEINTERFACE(pFrame);
|
||
// update window
|
||
return Refresh();
|
||
}
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(SetMask)(SAFEARRAY** Image)
|
||
{
|
||
// check for valid image
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// destroy previous mask
|
||
if (m_pMask)
|
||
{
|
||
delete[] m_pMask;
|
||
m_pMask = 0;
|
||
}
|
||
|
||
// variables
|
||
int nWidth = 0;
|
||
int nHeight = 0;
|
||
int nChannels = 0;
|
||
BYTE* pPixels = 0;
|
||
|
||
// extract image from the array
|
||
pPixels = ImageStudioUtils::ExtractImage(Image, nWidth, nHeight, nChannels);
|
||
|
||
// check that the image is valid
|
||
if (!pPixels || nWidth != m_nWidth || nHeight != m_nHeight || nChannels != 1)
|
||
return S_OK;
|
||
|
||
// allocate memory for new mask
|
||
m_pMask = new BYTE[m_nWidth*m_nHeight];
|
||
|
||
// check for allocated memory
|
||
if (!m_pMask)
|
||
return S_OK;
|
||
|
||
// copy information about mask
|
||
memcpy(m_pMask, pPixels, m_nWidth*m_nHeight);
|
||
|
||
// update window
|
||
return Refresh();
|
||
}
|
||
STDMETHOD(Refresh)()
|
||
{
|
||
// repaint window
|
||
OnPaint(c_SenderRefresh);
|
||
|
||
// all ok
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(GetScreen)(SAFEARRAY** Image, VARIANT_BOOL* Success)
|
||
{
|
||
*Success = VARIANT_FALSE;
|
||
|
||
if (!Image || !IsWindow())
|
||
return S_OK;
|
||
|
||
// retrieve window rectangle
|
||
RECT rect; GetClientRect(&rect);
|
||
int nWidth = abs(rect.right - rect.left);
|
||
int nHeight = abs(rect.bottom - rect.top);
|
||
|
||
// check whether window is valid
|
||
if (!nWidth && !nHeight)
|
||
return S_OK;
|
||
|
||
// variables
|
||
SAFEARRAYBOUND rgsaBound[3];
|
||
rgsaBound[0].lLbound = 0;
|
||
rgsaBound[0].cElements = 4;
|
||
rgsaBound[1].lLbound = 0;
|
||
rgsaBound[1].cElements = nWidth;
|
||
rgsaBound[2].lLbound = 0;
|
||
rgsaBound[2].cElements = nHeight;
|
||
|
||
*Image = SafeArrayCreate(VT_UI1, 3, rgsaBound);
|
||
|
||
// extract image pixels
|
||
if (!ExtractRect(nWidth, nHeight, 4, (BYTE*)((*Image)->pvData)))
|
||
return S_OK;
|
||
|
||
*Success = VARIANT_TRUE;
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(get_AutoRefresh)(VARIANT_BOOL* Allow)
|
||
{
|
||
*Allow = m_bAutoRefresh ? VARIANT_TRUE : VARIANT_FALSE;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_AutoRefresh)(VARIANT_BOOL Allow)
|
||
{
|
||
m_bAutoRefresh = (Allow == VARIANT_TRUE) ? TRUE : FALSE;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
// zommings
|
||
STDMETHOD(ZoomIn)()
|
||
{
|
||
m_dZoom *= c_dImageFactorZoomIn;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(ZoomOut)()
|
||
{
|
||
m_dZoom *= c_dImageFactorZoomOut;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(ZoomToFit)()
|
||
{
|
||
// check for valid image
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// convert size in inches to size in pixels
|
||
RECT rect; GetClientRect(&rect);
|
||
|
||
// correct zoom factor to shrink image in window
|
||
m_dZoom = min((rect.right - rect.left)/(double)m_nWidth, (rect.bottom - rect.top)/(double)m_nHeight);
|
||
|
||
// reinitialize center values
|
||
m_dCenterX = 0.5*m_nWidth;
|
||
m_dCenterY = 0.5*m_nHeight;
|
||
|
||
// update window
|
||
OnPaint(c_SenderDraw);
|
||
|
||
// all ok
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(ShrinkToFit)()
|
||
{
|
||
// check for valid image
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// convert size in inches to size in pixels
|
||
RECT rect; GetClientRect(&rect);
|
||
|
||
// correct zoom factor to shrink image in window
|
||
m_dZoom = min((rect.right - rect.left)/(double)m_nWidth, (rect.bottom - rect.top)/(double)m_nHeight);
|
||
|
||
// correct zoom factor
|
||
m_dZoom = min(1.0, m_dZoom);
|
||
|
||
// reinitialize center values
|
||
m_dCenterX = 0.5*m_nWidth;
|
||
m_dCenterY = 0.5*m_nHeight;
|
||
|
||
// update window
|
||
OnPaint(c_SenderDraw);
|
||
|
||
// all ok
|
||
return S_OK;
|
||
}
|
||
|
||
// view settings
|
||
STDMETHOD(get_viewCenterX)(double* CenterX)
|
||
{
|
||
*CenterX = m_dCenterX;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_viewCenterX)(double CenterX)
|
||
{
|
||
m_dCenterX = CenterX;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_viewCenterY)(double* CenterY)
|
||
{
|
||
*CenterY = m_dCenterY;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_viewCenterY)(double CenterY)
|
||
{
|
||
m_dCenterY = CenterY;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_viewZoom)(double* Zoom)
|
||
{
|
||
*Zoom = m_dZoom;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_viewZoom)(double Zoom)
|
||
{
|
||
m_dZoom = Zoom;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_viewAspect)(double* Aspect)
|
||
{
|
||
*Aspect = m_dAspect;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_viewAspect)(double Aspect)
|
||
{
|
||
m_dAspect = Aspect;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
// formatting
|
||
STDMETHOD(get_formatShowBorder)(VARIANT_BOOL* Show)
|
||
{
|
||
*Show = m_bShowBorder ? VARIANT_TRUE : VARIANT_FALSE;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatShowBorder)(VARIANT_BOOL Show)
|
||
{
|
||
m_bShowBorder = (Show == VARIANT_TRUE) ? TRUE : FALSE;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_formatWindowStyle)(long* Style)
|
||
{
|
||
*Style = m_nWindowStyle;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatWindowStyle)(long Style)
|
||
{
|
||
m_nWindowStyle = Style;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_formatMousePointer)(long* Pointer)
|
||
{
|
||
*Pointer = m_nPointer;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatMousePointer)(long Pointer)
|
||
{
|
||
m_nPointer = Pointer;
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(get_formatMaskStyle)(long* Style)
|
||
{
|
||
*Style = m_nMaskStyle;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatMaskStyle)(long Style)
|
||
{
|
||
m_nMaskStyle = Style;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_formatMaskColor)(OLE_COLOR* Color)
|
||
{
|
||
*Color = m_nMaskColor;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatMaskColor)(OLE_COLOR Color)
|
||
{
|
||
m_nMaskColor = Color;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(get_formatBackStyle)(long* Style)
|
||
{
|
||
*Style = m_nBackStyle;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatBackStyle)(long Style)
|
||
{
|
||
m_nBackStyle = Style;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_formatBackColor1)(OLE_COLOR* Color)
|
||
{
|
||
*Color = m_nBackColor1;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatBackColor1)(OLE_COLOR Color)
|
||
{
|
||
m_nBackColor1 = Color;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_formatBackColor2)(OLE_COLOR* Color)
|
||
{
|
||
*Color = m_nBackColor2;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_formatBackColor2)(OLE_COLOR Color)
|
||
{
|
||
m_nBackColor2 = Color;
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
// tracking
|
||
STDMETHOD(get_trackType)(long* Type)
|
||
{
|
||
if (m_pTracking)
|
||
*Type = m_pTracking->GetType();
|
||
else
|
||
*Type = Tracking::c_nTrackTypeNone;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(get_trackColorScheme)(long* ColorScheme)
|
||
{
|
||
*ColorScheme = m_nTrackingColorScheme;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(put_trackColorScheme)(long ColorScheme)
|
||
{
|
||
m_nTrackingColorScheme = ColorScheme;
|
||
|
||
if (m_nTrackingColorScheme == c_TrackColorSchemeInverse) m_oTrackingPainter.SetColors(-2, -1, -2, -2);
|
||
else if (m_nTrackingColorScheme == c_TrackColorSchemeBlackWhite) m_oTrackingPainter.SetColors(0, RGB(255, 255, 255), RGB(255, 255, 255), 0);
|
||
else if (m_nTrackingColorScheme == c_TrackColorSchemeWhiteBlack) m_oTrackingPainter.SetColors(0, RGB(255, 255, 255), 0, RGB(255, 255, 255));
|
||
else if (m_nTrackingColorScheme == c_TrackColorSchemeWhiteOrange) m_oTrackingPainter.SetColors(RGB(255, 128, 64), RGB(255, 255, 255), RGB(255, 128, 64), RGB(255, 255, 255));
|
||
else if (m_nTrackingColorScheme == c_TrackColorSchemeBlueYellow) m_oTrackingPainter.SetColors(RGB(255, 255, 128), RGB(0, 0, 128), RGB(255, 255, 128), RGB(0, 0, 128));
|
||
else if (m_nTrackingColorScheme == c_TrackColorSchemeBlackGreen) m_oTrackingPainter.SetColors(RGB(0, 255, 128), 0, RGB(0, 255, 128), 0);
|
||
|
||
OnPaint(c_SenderDraw);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(EndTrack)()
|
||
{
|
||
// check for valid image
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// check for no tracking
|
||
if (!m_pTracking || m_pTracking->IsTrackNone())
|
||
return S_OK;
|
||
|
||
// fire final event
|
||
FireEvent(3);
|
||
|
||
// clear point list
|
||
delete m_pTracking;
|
||
m_pTracking = 0;
|
||
|
||
// update preview
|
||
OnPaint(c_SenderTrack);
|
||
|
||
// all ok
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(BeginTrackPoint)(double X, double Y)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dX = AspectXRemove(X);
|
||
double dY = AspectYRemove(Y);
|
||
|
||
Tracking::CTrackObjectPoints* pTracking = new Tracking::CTrackObjectPoints();
|
||
|
||
pTracking->Create(dX, dY);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackLine)(double X1, double Y1, double X2, double Y2)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dX1 = AspectXRemove(X1);
|
||
double dY1 = AspectYRemove(Y1);
|
||
double dX2 = AspectXRemove(X2);
|
||
double dY2 = AspectYRemove(Y2);
|
||
|
||
Tracking::CTrackObjectLine* pTracking = new Tracking::CTrackObjectLine();
|
||
|
||
pTracking->Create(dX1, dY1, dX2, dY2);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackEllipse)(double Left, double Top, double Right, double Bottom)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectEllipse* pTracking = new Tracking::CTrackObjectEllipse();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackRectangle)(double Left, double Top, double Right, double Bottom)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectRectangle* pTracking = new Tracking::CTrackObjectRectangle();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackRectangleFixedSize)(double Left, double Top, double Width, double Height)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Left + Width);
|
||
double dBottom = AspectYRemove(Top + Height);
|
||
|
||
Tracking::CTrackObjectRectangleFixedSize* pTracking = new Tracking::CTrackObjectRectangleFixedSize();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackRectangleFixedAspect)(double Left, double Top, double Width, double Height)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Left + Width);
|
||
double dBottom = AspectYRemove(Top + Height);
|
||
|
||
Tracking::CTrackObjectRectangleFixedAspect* pTracking = new Tracking::CTrackObjectRectangleFixedAspect();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(BeginTrackPolyline)(SAFEARRAY** Points)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
Structures::POINTD* pPoints = 0;
|
||
int nPointsCount = 0;
|
||
|
||
if (!SafeArrayToPoints(Points, TRUE, pPoints, nPointsCount))
|
||
return S_OK;
|
||
|
||
Tracking::CTrackObjectPolyline* pTracking = new Tracking::CTrackObjectPolyline();
|
||
|
||
pTracking->Create(pPoints, nPointsCount);
|
||
|
||
delete[] pPoints;
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackPolygon)(SAFEARRAY** Points)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
Structures::POINTD* pPoints = 0;
|
||
int nPointsCount = 0;
|
||
|
||
if (!SafeArrayToPoints(Points, TRUE, pPoints, nPointsCount))
|
||
return S_OK;
|
||
|
||
Tracking::CTrackObjectPolygon* pTracking = new Tracking::CTrackObjectPolygon();
|
||
|
||
pTracking->Create(pPoints, nPointsCount);
|
||
|
||
delete[] pPoints;
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackPie)(double Left, double Top, double Right, double Bottom, double StartAngle, double SweepAngle)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectPie* pTracking = new Tracking::CTrackObjectPie();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, StartAngle, SweepAngle);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(BeginTrackSimplePie)(double CenterX, double CenterY, double Radius, double StartAngle, double SweepAngle)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// create rect
|
||
double Left = CenterX - Radius;
|
||
double Right = CenterX + Radius;
|
||
double Top = CenterY - Radius;
|
||
double Bottom = CenterY + Radius;
|
||
|
||
// set aspect
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectPieSimple* pTracking = new Tracking::CTrackObjectPieSimple();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, StartAngle, SweepAngle);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackSector)(double Left, double Top, double Right, double Bottom, double StartAngle, double SweepAngle, double Ratio)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectSector* pTracking = new Tracking::CTrackObjectSector();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, StartAngle, SweepAngle, Ratio);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackSimpleSector)(double CenterX, double CenterY, double Radius1, double Radius2, double StartAngle, double SweepAngle)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// create rect
|
||
double Left = CenterX - Radius1;
|
||
double Right = CenterX + Radius1;
|
||
double Top = CenterY - Radius1;
|
||
double Bottom = CenterY + Radius1;
|
||
|
||
// set aspect
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
double Ratio = Radius2/Radius1;
|
||
|
||
Tracking::CTrackObjectSectorSimple* pTracking = new Tracking::CTrackObjectSectorSimple();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, StartAngle, SweepAngle, Ratio);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackEllipseInRectangle)(double Left, double Top, double Right, double Bottom)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectEllipseInRectangle* pTracking = new Tracking::CTrackObjectEllipseInRectangle();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackCircle)(double CenterX, double CenterY, double Radius)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
// set aspect
|
||
double dLeft = AspectXRemove(CenterX - Radius);
|
||
double dTop = AspectYRemove(CenterY - Radius);
|
||
double dRight = AspectXRemove(CenterX + Radius);
|
||
double dBottom = AspectYRemove(CenterY + Radius);
|
||
|
||
Tracking::CTrackObjectCircle* pTracking = new Tracking::CTrackObjectCircle();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackRectangleRotatable)(double Left, double Top, double Right, double Bottom, double Angle, double StickAngle)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectRectangleRotatable* pTracking = new Tracking::CTrackObjectRectangleRotatable();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, Angle, StickAngle );
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(BeginTrackRectangleRotatableFixedAspect)(double Left, double Top, double Right, double Bottom, double Angle, double StickAngle)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectRectangleRotatableFixedAspect* pTracking = new Tracking::CTrackObjectRectangleRotatableFixedAspect();
|
||
|
||
pTracking->Create( dLeft, dTop, dRight, dBottom, Angle, StickAngle );
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(BeginTrackTextRotatable)(double Left, double Top, double Right, double Bottom, double Angle, double StickAngle, BSTR inText, BSTR FontName, int FontSize, int FontType, int FontColor)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectTextRotatable* pTracking = new Tracking::CTrackObjectTextRotatable();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, Angle, StickAngle, inText, FontName, FontSize, FontType, FontColor);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(BeginTrackText)(double Left, double Top, double Right, double Bottom, BSTR inText, BSTR FontName, int FontSize, int FontType, int FontColor)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
double dLeft = AspectXRemove(Left);
|
||
double dTop = AspectYRemove(Top);
|
||
double dRight = AspectXRemove(Right);
|
||
double dBottom = AspectYRemove(Bottom);
|
||
|
||
Tracking::CTrackObjectText* pTracking = new Tracking::CTrackObjectText();
|
||
|
||
pTracking->Create(dLeft, dTop, dRight, dBottom, inText, FontName, FontSize, FontType, FontColor);
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(MoveTrack)(double dX, double dY)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
if (m_pTracking)
|
||
{
|
||
m_pTracking->MoveTrack(dX, dY);
|
||
OnPaint(c_SenderTrack);
|
||
}
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(TransformCoordToBitmap)(double* X, double* Y)
|
||
{
|
||
// retrieve cursor position and preview window rectanlge
|
||
RECT rect; GetWindowRect(&rect);
|
||
|
||
// compute preview image size
|
||
int nWidth = abs( rect.right - rect.left );
|
||
int nHeight = abs( rect.bottom - rect.top );
|
||
// check for valid simpliest case when image size is invalid
|
||
if (!nWidth || !nHeight)
|
||
return S_FALSE;
|
||
|
||
*X = ( *X - 0.5 * nWidth + m_dCenterX * m_dZoom ) / m_dZoom;
|
||
*Y = ( *Y - 0.5 * nHeight + m_dCenterY * m_dZoom ) / m_dZoom;
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(TransformCoordToControl)(double* X, double* Y)
|
||
{
|
||
// retrieve cursor position and preview window rectanlge
|
||
RECT rect; GetWindowRect(&rect);
|
||
|
||
// compute preview image size
|
||
int nWidth = abs( rect.right - rect.left );
|
||
int nHeight = abs( rect.bottom - rect.top );
|
||
|
||
// check for valid simpliest case when image size is invalid
|
||
if (!nWidth || !nHeight)
|
||
return S_FALSE;
|
||
|
||
*X = *X * m_dZoom + 0.5 * nWidth - m_dCenterX * m_dZoom;
|
||
*Y = *Y * m_dZoom + 0.5 * nHeight - m_dCenterY * m_dZoom;
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
// additional parameters
|
||
STDMETHOD(SetAdditionalParam)(BSTR ParamName, VARIANT ParamValue)
|
||
{
|
||
CComVariant ParamVal = ParamValue;
|
||
CComBSTR ParamStr = ParamName;
|
||
|
||
if (ParamStr == L"TrackingColors")
|
||
{
|
||
ParamVal.ChangeType(VT_I4, NULL);
|
||
|
||
put_trackColorScheme(ParamVal.lVal);
|
||
}
|
||
else if (ParamStr == L"MediaData")
|
||
{
|
||
ParamVal.ChangeType(VT_UNKNOWN, NULL);
|
||
IUnknown* pImage = ParamVal.punkVal;
|
||
|
||
SetMediaData(pImage);
|
||
}
|
||
else if (ParamStr == L"BeginTrackQuadraticBezier" )
|
||
{
|
||
Structures::POINTD* pPoints = 0;
|
||
int nPointsCount = 0;
|
||
|
||
if (!SafeArrayToPoints(&ParamValue.parray, TRUE, pPoints, nPointsCount))
|
||
return S_OK;
|
||
|
||
Tracking::CTrackObjectQuadraticBezier* pTracking = new Tracking::CTrackObjectQuadraticBezier();
|
||
|
||
pTracking->Create(pPoints, nPointsCount);
|
||
|
||
delete[] pPoints;
|
||
|
||
BeginTrack(pTracking);
|
||
}
|
||
|
||
return S_OK;
|
||
}
|
||
STDMETHOD(GetAdditionalParam)(BSTR ParamName, VARIANT* ParamValue)
|
||
{
|
||
CComBSTR ParamStr = ParamName;
|
||
|
||
if (ParamStr == L"TrackingColors")
|
||
(*ParamValue).lVal = (LONG)m_nTrackingColorScheme;
|
||
else if (ParamStr == L"TrackChangeType")
|
||
{
|
||
POINT point; GetCursorPos(&point); ::ScreenToClient(m_hWnd, &point);
|
||
int nPointStatus = Tracking::c_nTrackPointStatusNone;
|
||
int nTrackChangeStatus = Tracking::c_nTrackChangeStatusNone;
|
||
if( m_pTracking )
|
||
m_pTracking->OnSetCursor(point.x, point.y, nPointStatus, nTrackChangeStatus);
|
||
(*ParamValue).lVal = (LONG)nTrackChangeStatus;
|
||
}
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHOD(BeginTrackTrajectoryPolyline)(SAFEARRAY** Points)
|
||
{
|
||
if (!IsValid())
|
||
return S_OK;
|
||
|
||
Structures::POINTD* pPoints = 0;
|
||
int nPointsCount = 0;
|
||
|
||
if (!SafeArrayToPoints(Points, TRUE, pPoints, nPointsCount))
|
||
return S_OK;
|
||
|
||
Tracking::CTrackObjectTrajectoryPolyline* pTracking = new Tracking::CTrackObjectTrajectoryPolyline();
|
||
|
||
pTracking->Create(pPoints, nPointsCount);
|
||
|
||
delete[] pPoints;
|
||
|
||
BeginTrack(pTracking);
|
||
|
||
return S_OK;
|
||
}
|
||
};
|