#include "hbclass.ch"
#include "GdiPlus.ch"
#define VK_CONTROL 17
#define VK_SHIFT 16
#define VK_TAB 9
#define CRLF Chr( 9 ) + Chr( 13 )
#xcommand DEFAULT <uVar> := <uVal> => IF <uVar> == NIL; <uVar> := <uVal>; ENDIF
//-----------------------------------------------------------------------------------------------//
INIT PROC C5ImageGdiPlus
RegisterClass()
RETURN
//-----------------------------------------------------------------------------------------------//
CLASS TImageGdiPlus From TControl
DATA oImage
DATA nLeft INIT 010
DATA nTop INIT 010
DATA nWidth INIT 200
DATA nHeight INIT 200
DATA nX INIT 000
DATA nY INIT 000
DATA nZoom INIT 001
DATA nStep INIT 010 // pixeles que se va a mover cada que presionas una tecla de movimiento
DATA nFactSpeed INIT 003 // Factor por el que se va a multiplicar cuando hagas GoXXXX( .T. )
DATA nFactZoom INIT 0.005
DATA nMaxZoom INIT 002
DATA nMinZoom INIT 0.500
DATA nColorRect INIT 0x10FF0000
DATA aColorRect INIT { 0, 0, 0, 0 }
DATA nAjusteX INIT 0
DATA nAjusteY INIT 0
DATA nAngle INIT 0
DATA nFactAngle INIT 0.10
METHOD New()
METHOD SetImage( oImage, lEnd )
Method SetImage2( cImage )
METHOD OnPaint()
METHOD GoLeft()
METHOD GoRight()
METHOD GoUp()
METHOD GoDown()
METHOD ZoomPlus() INLINE ::nZoom += Min( ::nFactZoom, ::nMaxZoom - ::nZoom )
METHOD ZoomMinus() INLINE ::nZoom -= Min( ::nFactZoom, ::nZoom - ::nMinZoom )
METHOD SetPos( nX, nY ) INLINE ::nX := nX, ::nY := nY, ::Refresh()
DATA bKeyDown
METHOD OnKeyDown()
METHOD Redefine()
METHOD Initiate()
METHOD Link()
DATA lMouseMark INIT .F.
DATA aMouseMark INIT { 0, 0, 0, 0 }
DATA nMouseMark INIT 0x40FF0000
DATA lButtonDown INIT .F.
DATA nMouseX INIT 0
DATA nMouseY INIT 0
DATA lDestroy INIT .T.
METHOD OnMouseMove()
METHOD OnLButtonDown()
METHOD OnLButtonUp()
METHOD OnRButtonUp()
METHOD AllPage()
Method OnNCDestroy()
Method SetImage()
ENDCLASS
//-----------------------------------------------------------------------------------------------//
Method OnNCDestroy()
if ::oImage != NIL .AND. ::lDestroy
::oImage:End()
Endif
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD OnLButtonUp()
IF ::lMouseMark
::lButtonDown := .F.
ENDIF
IF GetKeyState( VK_CONTROL )
::nX := ::aMouseMark[01] * -1
::nY := ::aMouseMark[02] * -1
::nZoom := 1
::Refresh()
ENDIF
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD OnRButtonUp()
IF ::lMouseMark
IF ::aMouseMark[03] != 0
::nX := ::aMouseMark[01] * -1
::nY := ::aMouseMark[02] * -1
::nZoom := 1
::nZoom := Min( ::GetCliRect:nWidth() / ::aMouseMark[03],;
::GetCliRect():nHeight() / ::aMouseMark[04] )
::aMouseMark := { 0, 0, 0, 0 }
ENDIF
::Refresh()
ENDIF
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD AllPage()
::nX := 0
::nY := 0
::nZoom := Min( ::GetCliRect():nWidth / ::oImage:GetWidth(),;
::GetCliRect():nHeight / ::oImage:GetHeight )
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD OnLButtonDown()
IF ::lMouseMark
::aMouseMark[01] := ::nMouseX
::aMouseMark[02] := ::nMouseY
::lButtonDown := .T.
ENDIF
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD OnMouseMove( nX, nY )
LOCAL a
IF ::lMouseMark
::nMouseX := ( ::nX * -1 ) + ( nX / ::nZoom )
::nMouseY := ( ::nY * -1 ) + ( nY / ::nZoom )
IF ::lButtonDown
::aMouseMark[03] := ::nMouseX - ::aMouseMark[01]
::aMouseMark[04] := ::nMouseY - ::aMouseMark[02]
::Refresh()
ENDIF
a := ::aMouseMark
ENDIF
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD Redefine( oWnd, nId )
::oWnd := oWnd
::nId := nId
::oWnd:AddControl( SELF )
RETURN SELF
//-----------------------------------------------------------------------------------------------//
METHOD Initiate()
::hWnd := GetDlgItem( ::oWnd:hWnd, ::nId )
::Link( ::hWnd )
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD OnKeyDown( nKey )
LOCAL lSpeed
IF nKey == 119 // VK_F8
::GoLeft( .T. )
::Refresh()
ENDIF
IF nKey == 120 // VK_F9
::GoRight( .T. )
::Refresh()
ENDIF
IF !GetKeyState( VK_CONTROL )
RETURN NIL
ENDIF
IF GetKeyState( VK_CONTROL ) .AND. GetKeyState( 65 )
DO CASE
CASE nKey == 37
::nAjusteX += 05
CASE nKey == 38
::nAjusteY += 05
CASE nKey == 39
::nAjusteX -= 05
CASE nKey == 40
::nAjusteY -= 05
CASE nKey == 107
IF ::nAngle < 45; ::nAngle += ::nFactAngle; ENDIF
CASE nKey == 109
IF ::nAngle > -45; ::nAngle -= ::nFactAngle; ENDIF
ENDCASE
::Refresh()
RETURN NIL
ENDIF
IF GetKeyState( VK_SHIFT )
lSpeed := .T.
ENDIF
DO CASE
CASE nKey == 80
::AllPage()
CASE nKey == 37
::GoLeft ( lSpeed )
CASE nKey == 38
::GoUp ( lSpeed )
CASE nKey == 39
::GoRight( lSpeed )
CASE nKey == 40
::GoDown ( lSpeed )
CASE nKey == 107 // +
::ZoomPlus()
CASE nKey == 109 // -
::ZoomMinus()
ENDCASE
::Refresh()
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD GoLeft( lSpeed )
LOCAL nSt
DEFAULT lSpeed := .F.
nSt := ::nStep * IF( lSpeed, ::nFactSpeed, 1 )
::nX += Min( nSt, Abs( ::nX ) )
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD GoRight( lSpeed )
LOCAL oRC := ::GetCliRect()
LOCAL nSt
DEFAULT lSpeed := .F.
nSt := ::nStep * IF( lSpeed, ::nFactSpeed, 1 )
::nX -= Min( nSt, ::oImage:GetWidth() - Abs( ::nX ) - ( oRC:nWidth / ::nZoom ) )
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD GoUp( lSpeed )
LOCAL nSt
DEFAULT lSpeed := .F.
nSt := ::nStep * IF( lSpeed, ::nFactSpeed, 1 )
::nY += Min( nSt, Abs( ::nY ) )
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD GoDown( lSpeed )
LOCAL oRC := ::GetCliRect()
LOCAL nSt
DEFAULT lSpeed := .F.
nSt := ::nStep * IF( lSpeed, ::nFactSpeed, 1 )
::nY -= Min( nSt, ::oImage:GetHeight() - Abs( ::nY ) - ( oRC:nHeight / ::nZoom ) )
RETURN NIL
//-----------------------------------------------------------------------------------------------//
METHOD SetImage( oImage, lEnd )
LOCAL oImageTmp
DEFAULT lEnd := .T.
IF ::oImage != NIL
oImageTmp := ::oImage
ENDIF
::oImage := oImage
IF lEnd .AND. oImageTmp != NIL
oImageTmp:END()
ENDIF
RETURN SELF
//-----------------------------------------------------------------------------------------------//
METHOD SetImage2( cImage )
Local oImage, oImageTmp
oImage := Image( cImage )
if ::oImage != NIL
oImageTmp := ::oImage
Endif
::oImage := oImage:GetThumbnailImage( oImage:GetWidth(), oImage:GetHeight() )
if oImageTmp != NIL
oImageTmp:End()
Endif
oImage:End()
Return NIL
//-----------------------------------------------------------------------------------------------//
METHOD New( oWnd, nLeft, nTop, nWidth, nHeight )
::oWnd := oWnd
DEFAULT nLeft := ::nLeft
DEFAULT nTop := ::nTop
DEFAULT nWidth := ::nWidth
DEFAULT nHeight := ::nHeight
::nLeft := nLeft
::nTop := nTop
::nWidth := nWidth
::nHeight := nHeight
::hWnd := CreateWindowEx( ::nLeft, ::nTop, ::nWidth, ::nHeight, ::oWnd:hWnd, SELF )
::bKeyDown := { |nKey| ::OnKeyDown( nKey ) }
RETURN SELF
//-----------------------------------------------------------------------------------------------//
METHOD OnPaint( hDC )
LOCAL oG, oRC, oBM, FontFamily, Font, RectF, stringformat, solidbrush, string, aPoints, nAngle
LOCAL nL, nT, nW, nH, nRadA, nRadB, oBitmap, oGraphics
oRC := ::GetCliRect()
// Doble Buffer
oBitmap := BITMAP( oRC:nWidth, oRC:nHeight )
oG := Graphics( oBitmap )
// Eof Doble Buffer
oG:Clear( oG:Color( 255, 230, 230, 230 ) )
IF ::oImage != NIL
IF ::nAngle == 0
oG:DrawImage( ::oImage, ( ::nX + ::nAjusteX ) * ::nZoom, ( ::nY + ::nAjusteY ) * ::nZoom, ::oImage:GetWidth() * ::nZoom,;
::oImage:GetHeight() * ::nZoom )
ELSE
// Rotacion de la imagen -45 a 45 Grados
nAngle := ::nAngle
nL := ( ::nX + ::nAjusteX ) * ::nZoom
nT := ( ::nY + ::nAjusteY ) * ::nZoom
nW := ::oImage:GetWidth() * ::nZoom
nH := ::oImage:GetHeight() * ::nZoom
IF nAngle > 0
nRadB := nAngle * ( 3.14159265 / 180 )
nRadA := ( 180 - nAngle - 90 ) * ( 3.14159265 / 180 )
aPoints := { { nL, nT },;
{ nL + ( nW * sin( nRadA ) ), nT + ( nW * sin( nRadB ) ) },;
{ nL - ( nH * sin( nRadB ) ), nT + ( nH * sin( nRadA ) ) } }
ELSE
nAngle := nAngle * - 1
nRadB := nAngle * ( 3.14159265 / 180 )
nRadA := ( 180 - nAngle - 90 ) * ( 3.14159265 / 180 )
aPoints := { { nL, nT },;
{ nL + ( nW * sin( nRadA ) ), nT - ( nW * sin( nRadB ) ) },;
{ nL + ( nH * sin( nRadB ) ), nT + ( nH * sin( nRadA ) ) } }
ENDIF
oG:DrawImage( ::oImage, aPoints, 3 )
ENDIF
ENDIF
// Cuadro
IF ::aColorRect != NIL
oG:FillRectangle( oG:SolidBrush( oG:Color( ::nColorRect ) ),;
oG:RectF( ( ::aColorRect[1] + ::nX ) * ::nZoom, ( ::aColorRect[2] + ::nY ) * ::nZoom,;
::aColorRect[3] * ::nZoom, ::aColorRect[4] * ::nZoom ) )
ENDIF
// Marca
IF ::lMouseMark
oG:FillRectangle( oG:SolidBrush( oG:Color( ::nMouseMark ) ),;
oG:RectF( ( ::aMouseMark[1] + ::nX ) * ::nZoom, ( ::aMouseMark[2] + ::nY ) * ::nZoom,;
::aMouseMark[3] * ::nZoom, ::aMouseMark[4] * ::nZoom ) )
ENDIF
IF GetKeyState( VK_TAB ) .AND. GetKeyState( VK_CONTROL )
fontFamily := oG:FontFamily( "Arial" )
font := oG:Font( fontFamily, 12, FontStyleBold, UnitPoint )
rectF := oG:RectF( 0, 0, oRC:nWidth, oRC:nHeight )
stringFormat := StringFormat()
solidBrush := SolidBrush( oG:Color( 255, 255, 0, 0 ) )
stringFormat:SetAlignment( StringAlignmentCenter )
stringFormat:SetLineAlignment( StringAlignmentCenter )
string := ;
"Step:" + Str( ::nStep ) + " Factor Speed:" + Str( ::nFactSpeed ) + CRLF +;
"Posicion X:" + Str( ::nX ) + " Posicion Y:" + Str( ::nY ) + CRLF +;
"Zoom: " + Str( ::nZoom ) + " Zoom Minimo: " + Str( ::nMinZoom ) + " Zoom Maximo: " + Str( ::nMaxZoom )
oG:DrawString( string, -1, font, rectF, stringFormat, solidBrush )
ENDIF
oG:END()
// Volcado DobleBuffer
oGraphics := Graphics( hDC )
oGraphics:DrawImage( oBitmap, 0, 0, oRC:nWidth, oRC:nHeight )
oGraphics:END()
oBitmap:END()
// Eof Volcado Doble Buffer
RETURN NIL
//-----------------------------------------------------------------------------------------------//
#pragma BEGINDUMP
#include <hbvm.h>
#include <hbapi.h>
#include <windows.h>
#include <hbapiitm.h>
/*-----------------------------------------------------------------------------------------------*/
LRESULT CALLBACK ImageGdiPlus_WindowProcedure( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
switch( iMsg )
{
case WM_NCCREATE:
{
if ((PHB_ITEM)(((LPCREATESTRUCT)lParam)->lpCreateParams))
{
PHB_ITEM pSelf = hb_itemNew( ( PHB_ITEM ) ( ( ( LPCREATESTRUCT ) lParam ) -> lpCreateParams ) );
SetProp( hWnd, "C5OBJECT", pSelf );
return TRUE;
}
else
return FALSE;
}
case WM_PAINT:
{
PHB_ITEM pSelf;
HDC hdc;
PAINTSTRUCT ps;
pSelf = (PHB_ITEM) GetProp( hWnd, "C5OBJECT" );
hdc = BeginPaint( hWnd, &ps );
if( pSelf )
{
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFind( "ONPAINT" ) ) );
hb_vmPush( pSelf );
hb_vmPushLong( (long) hdc );
hb_vmDo( 1 );
}
EndPaint( hWnd, &ps );
return 1;
}
case WM_ERASEBKGND:
return 1;
case WM_RBUTTONUP:
{
PHB_ITEM pSelf;
pSelf = (PHB_ITEM) GetProp( hWnd, "C5OBJECT" );
if( pSelf )
{
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFind( "ONRBUTTONUP" ) ) );
hb_vmPush( pSelf );
hb_vmDo( 0 );
}
break;
}
case WM_NCDESTROY:
{
PHB_ITEM pSelf;
pSelf = (PHB_ITEM) GetProp( hWnd, "C5OBJECT" );
if( pSelf )
{
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFind( "ONNCDESTROY" ) ) );
hb_vmPush( pSelf );
hb_vmDo( 0 );
}
break;
}
case WM_LBUTTONDOWN:
{
PHB_ITEM pSelf;
pSelf = (PHB_ITEM) GetProp( hWnd, "C5OBJECT" );
if( pSelf )
{
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFind( "ONLBUTTONDOWN" ) ) );
hb_vmPush( pSelf );
hb_vmDo( 0 );
}
break;
}
case WM_LBUTTONUP:
{
PHB_ITEM pSelf;
pSelf = (PHB_ITEM) GetProp( hWnd, "C5OBJECT" );
if( pSelf )
{
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFind( "ONLBUTTONUP" ) ) );
hb_vmPush( pSelf );
hb_vmDo( 0 );
}
break;
}
case WM_MOUSEMOVE:
{
PHB_ITEM pSelf;
pSelf = (PHB_ITEM) GetProp( hWnd, "C5OBJECT" );
if( pSelf )
{
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFind( "ONMOUSEMOVE" ) ) );
hb_vmPush( pSelf );
hb_vmPushInteger( LOWORD( lParam ) );
hb_vmPushInteger( HIWORD( lParam ) );
hb_vmDo( 2 );
}
break;
}
}
if ( GetProp( hWnd, "C5OLDPROC" ) )
CallWindowProc( (WNDPROC) GetProp( hWnd, "C5OLDPROC" ), hWnd, iMsg, wParam, lParam );
return DefWindowProc( hWnd, iMsg, wParam, lParam );
}
/*-----------------------------------------------------------------------------------------------*/
HB_FUNC_STATIC( REGISTERCLASS )
{
WNDCLASS wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASS));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = ImageGdiPlus_WindowProcedure;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hCursor = LoadCursor(0,IDC_ARROW);
wndClass.hbrBackground = NULL;
wndClass.lpszClassName = "C5IMAGEGDIPLUS";
hb_retnl( RegisterClass(&wndClass) );
}
/*-----------------------------------------------------------------------------------------------*/
HB_FUNC_STATIC( TIMAGEGDIPLUS_LINK )
{
SetProp( (HWND)hb_parnl( 1 ), "C5OBJECT", hb_itemNew( hb_param( 0, HB_IT_OBJECT ) ) );
SetProp( (HWND)hb_parnl( 1 ), "C5OLDPROC", (HANDLE)SetWindowLong( (HWND)hb_parnl( 1 ), GWL_WNDPROC,
(long)ImageGdiPlus_WindowProcedure ) );
}
/*-----------------------------------------------------------------------------------------------*/
HB_FUNC_STATIC( CREATEWINDOWEX )
{
hb_retnl( (long) CreateWindowEx( 0, "C5IMAGEGDIPLUS", "", WS_CHILD | WS_VISIBLE | WS_BORDER,
hb_parni( 1 ), hb_parni( 2 ), hb_parni( 3 ), hb_parni( 4 ), (HWND)hb_parnl( 5 ),
(HMENU)-1, GetModuleHandle( 0 ), hb_param( 6, HB_IT_OBJECT ) ) );
}