Low-Level DigitalPaint: Initializing and Freeing a Paint Handle
Take the following steps to create a new paint handle:
Start a new project as follows: |
|
1. |
Run Microsoft Visual Studio 2005, select File à New à Project, and do the following: |
|
Expand Visual C++ tree, if it is not already expanded. |
|
Select Win32 from the sub tree. |
|
Select Win32 Project from the right window. |
|
In the Project name text box, specify Tutorial. |
|
In the Location text box, specify the path of the project. |
|
Click the OK button. |
2. |
In the overview window, click Next. |
3. |
In the Application Type step dialog box, do the following: |
|
Select Windows application. |
|
Be sure to un-check the Empty project checkbox. |
|
Click the Finish button. |
4. |
Add the following Menu to the tutorial.rc: |
|
In File menu: |
|
|
&Open… |
with ID = IDM_FILE_OPEN |
5. |
In Tutorial.cpp replace the WndProc procedure with the following code: |
static LRESULT WINAPI WndProc ( HWND hWnd, L_UINT uMessage, WPARAM wParam, LPARAM lParam )
{
static BITMAPHANDLE hBitmap ;
static RECT rcView ;
static L_INT nVScroll = 0 ;
static L_INT nHScroll = 0 ;
static L_INT nZoomFactor = 100 ;
static pPAINTHANDLE pPaint ;
switch( uMessage )
{
case WM_CREATE:
if ( SUCCESS == L_PntInit ( &pPaint ) )
{
return 0L ;
}
else
{
return -1L ;
}
case WM_DESTROY:
if ( hBitmap.Flags.Allocated )
{
L_FreeBitmap( &hBitmap ) ;
}
if ( SUCCESS == L_PntIsValid ( pPaint ) )
{
L_PntFree ( pPaint ) ;
}
PostQuitMessage ( 0 ) ;
return 0L ;
case WM_SIZE:
OnSize ( hWnd,
&hBitmap,
&rcView,
LOWORD ( lParam ),
HIWORD ( lParam ),
nZoomFactor,
&nHScroll,
&nVScroll ) ;
break ;
case WM_HSCROLL:
OnHScroll ( hWnd,
LOWORD ( wParam ),
nZoomFactor,
&rcView,
&nHScroll,
&nVScroll ) ;
break ;
case WM_VSCROLL:
OnVScroll ( hWnd,
LOWORD ( wParam ),
nZoomFactor,
&rcView,
&nHScroll,
&nVScroll ) ;
break ;
case WM_PAINT:
OnPaint ( hWnd, &hBitmap, &rcView) ;
break ;
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case IDM_FILE_OPEN:
{
BITMAPHANDLE hTempBitmap ;
HDC hDC ;
if ( OnOpen ( hWnd, &hTempBitmap ) )
{
if ( hBitmap.Flags.Allocated )
{
L_FreeBitmap( &hBitmap ) ;
}
L_CopyBitmapHandle( &hBitmap, &hTempBitmap, sizeof(BITMAPHANDLE)) ;
hDC = GetDC ( hWnd ) ;
ReleaseDC ( hWnd, hDC ) ;
{//ADJUST WINDOW SIZE
RECT rcWindow ;
L_INT nWidth, nHeight ;
SystemParametersInfo ( SPI_GETWORKAREA, 0, &rcWindow, 0 ) ;
nWidth = min ( MulDiv ( BITMAPWIDTH ( &hBitmap ), nZoomFactor, 100 ),
( rcWindow.right - rcWindow.left ) ) ;
nHeight = min ( MulDiv ( BITMAPHEIGHT ( &hBitmap ), nZoomFactor, 100 ),
( rcWindow.bottom - rcWindow.top ) ) ;
MoveWindow ( hWnd,
0,
0,
nWidth,
nHeight,
TRUE ) ;
}//ADJUST WINDOW SIZE
InvalidateRect ( hWnd, NULL, TRUE ) ;
}
}
return 0L ;
case IDM_EXIT:
PostMessage ( hWnd, WM_CLOSE, 0, 0 ) ;
return 0L ;
}
break ;
}
return DefWindowProc ( hWnd, uMessage, wParam, lParam ) ;
}
6. |
Add the following code right before WndProc procedure: |
static L_VOID OnSize
(
HWND hWnd,
pBITMAPHANDLE pBitmap,
LPRECT prcView,
L_INT cx,
L_INT cy,
L_INT nZoom,
L_INT *pnHScroll,
L_INT *pnVScroll
)
{
SCROLLINFO si ;
L_INT nXOffset, nYOffset ;
if ( NULL != pBitmap && pBitmap->Flags.Allocated )
{
si.cbSize = sizeof ( SCROLLINFO ) ;
si.fMask = SIF_ALL ;
// vertical scroll.
GetScrollInfo ( hWnd, SB_VERT, &si ) ;
si.nMin = 0 ;
si.nMax = BITMAPHEIGHT ( pBitmap ) ;
si.nPage = MulDiv ( cy, 100, nZoom ) ;
SetScrollInfo ( hWnd, SB_VERT, &si, TRUE ) ;
GetScrollInfo ( hWnd, SB_VERT, &si ) ;
*pnVScroll = si.nPos ;
// horizontal scroll
GetScrollInfo ( hWnd, SB_HORZ, &si ) ;
si.nMin = 0 ;
si.nMax = BITMAPWIDTH ( pBitmap ) ;
si.nPage = MulDiv ( cx, 100, nZoom ) ;
SetScrollInfo ( hWnd, SB_HORZ, &si, TRUE ) ;
GetScrollInfo ( hWnd, SB_HORZ, &si ) ;
*pnHScroll = si.nPos ;
}
else
{
si.cbSize = sizeof ( SCROLLINFO ) ;
si.fMask = SIF_RANGE ;
si.nMin = 0 ;
si.nMax = 0 ;
SetScrollInfo ( hWnd, SB_VERT, &si, TRUE ) ;
SetScrollInfo ( hWnd, SB_HORZ, &si, TRUE ) ;
*pnHScroll = 0 ;
*pnVScroll = 0 ;
}
// set the painting rectangel.
SetRect ( prcView, 0, 0, BITMAPWIDTH ( pBitmap ), BITMAPHEIGHT ( pBitmap ) ) ;
if ( nZoom < 100 )
{
nXOffset = MulDiv ( *pnHScroll, 100, nZoom ) ;
nYOffset = MulDiv ( *pnVScroll, 100, nZoom ) ;
}
else
{
nXOffset = *pnHScroll ;
nYOffset = *pnVScroll ;
}
OffsetRect ( prcView, - nXOffset, - nYOffset ) ;
prcView->left = MulDiv ( prcView->left, nZoom, 100 ) ;
prcView->top = MulDiv ( prcView->top, nZoom, 100 ) ;
prcView->right = MulDiv ( prcView->right, nZoom, 100 ) ;
prcView->bottom = MulDiv ( prcView->bottom, nZoom, 100 ) ;
}
L_VOID OnHScroll
(
HWND hWnd,
L_UINT code,
L_INT nZoom,
LPRECT prcView,
L_INT *pnHScroll,
L_INT *pnVScroll
)
{
SCROLLINFO si ;
si.cbSize = sizeof (SCROLLINFO) ;
si.fMask = SIF_ALL ;
GetScrollInfo (hWnd, SB_HORZ, &si) ;
*pnHScroll = si.nPos ;
switch ( code )
{
case SB_LINELEFT:
si.nPos -= 1 ;
break ;
case SB_LINERIGHT:
si.nPos += 1 ;
break ;
case SB_PAGELEFT:
si.nPos -= si.nPage ;
break ;
case SB_PAGERIGHT:
si.nPos += si.nPage ;
break ;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos ;
break ;
default:
break ;
}
si.fMask = SIF_POS ;
SetScrollInfo (hWnd, SB_HORZ, &si, TRUE) ;
GetScrollInfo (hWnd, SB_HORZ, &si) ;
if ( si.nPos != *pnHScroll )
{
L_INT dxUpdate ;
// update screen.
if ( nZoom >= 100 )
{
dxUpdate = MulDiv ( ( *pnHScroll - si.nPos ), nZoom, 100 ) ;
}
else
{
dxUpdate = *pnHScroll - si.nPos ;
}
// update screen.
OffsetRect ( prcView, dxUpdate, 0 ) ;
ScrollWindow ( hWnd, dxUpdate, 0, NULL, NULL ) ;
*pnHScroll = si.nPos ;
UpdateWindow ( hWnd ) ;
}
}
L_VOID OnVScroll
(
HWND hWnd,
L_UINT code,
L_INT nZoom,
LPRECT prcView,
L_INT *pnHScroll,
L_INT *pnVScroll
)
{
SCROLLINFO si ;
si.cbSize = sizeof ( SCROLLINFO ) ;
si.fMask = SIF_ALL ;
GetScrollInfo (hWnd, SB_VERT, &si) ;
*pnVScroll = si.nPos ;
switch ( code )
{
case SB_LINEUP:
si.nPos -= 1 ;
break ;
case SB_LINEDOWN:
si.nPos += 1 ;
break ;
case SB_PAGEUP:
si.nPos -= si.nPage ;
break ;
case SB_PAGEDOWN:
si.nPos += si.nPage ;
break ;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos ;
break ;
default:
break ;
}
si.fMask = SIF_POS ;
SetScrollInfo ( hWnd, SB_VERT, &si, TRUE ) ;
GetScrollInfo ( hWnd, SB_VERT, &si ) ;
if ( si.nPos != *pnVScroll )
{
L_INT dyUpdate ;
// update screen.
if ( nZoom >= 100 )
{
dyUpdate = MulDiv ( ( *pnVScroll - si.nPos ), nZoom, 100 ) ;
}
else
{
dyUpdate = *pnVScroll - si.nPos ;
}
// update screen.
OffsetRect ( prcView, 0, dyUpdate ) ;
ScrollWindow ( hWnd, 0, dyUpdate, NULL, NULL ) ;
*pnVScroll = si.nPos ;
UpdateWindow ( hWnd ) ;
}
}
L_VOID OnPaint
(
HWND hWnd,
pBITMAPHANDLE pBitmap,
LPRECT prcView
)
{
HDC hDC ;
PAINTSTRUCT ps ;
HPALETTE hOldPal = NULL;
HPALETTE hPalette;
hDC = BeginPaint (hWnd, &ps) ;
if ( pBitmap->Flags.Allocated )
{
hPalette = L_CreatePaintPalette( hDC, pBitmap ) ;
if ( hPalette )
{
hOldPal = SelectPalette ( hDC, hPalette, TRUE ) ;
RealizePalette ( hDC ) ;
}
L_PaintDC( hDC, pBitmap, NULL, NULL, prcView, &ps.rcPaint, SRCCOPY ) ;
if ( NULL != hOldPal )
{
SelectPalette ( hDC, hOldPal, TRUE ) ;
DeleteObject(hPalette);
}
}
EndPaint (hWnd, &ps) ;
}
static L_BOOL OnOpen ( HWND hWnd, pBITMAPHANDLE pBitmap )
{
static L_INT nOpenIndex = 0 ;
OPENFILENAME OpenFileName ;
L_TCHAR szFile [ MAX_PATH ] = TEXT("\0") ;
L_TCHAR szFileTitle [ MAX_PATH ] = TEXT("\0") ;
L_TCHAR szOpenFileFilter [ ] = {TEXT("ALL\0")TEXT("*.*\0")} ;
OPENDLGPARAMS FileOpenParams ;
BITMAPHANDLE hThumb ;
memset ( &FileOpenParams, 0, sizeof ( OPENDLGPARAMS ) ) ;
lstrcpy ( szFile, TEXT("") ) ;
L_InitBitmap( pBitmap, sizeof(BITMAPHANDLE), 0, 0, 0 ) ;
L_InitBitmap( &hThumb, sizeof(BITMAPHANDLE), 0, 0, 0 ) ;
OpenFileName.lStructSize = sizeof(OPENFILENAME);
OpenFileName.hwndOwner = hWnd;
OpenFileName.lpstrFilter = szOpenFileFilter;
OpenFileName.lpstrCustomFilter = NULL;
OpenFileName.nMaxCustFilter = 0;
OpenFileName.nFilterIndex = nOpenIndex;
OpenFileName.nMaxFile = sizeof(szFile);
OpenFileName.lpstrFile = szFile;
OpenFileName.nMaxFileTitle = sizeof(szFileTitle);
OpenFileName.lpstrFileTitle = szFileTitle;
OpenFileName.lpstrInitialDir = NULL;
OpenFileName.lpstrTitle = TEXT("Open a File");
OpenFileName.nFileOffset = 0;
OpenFileName.nFileExtension = 0;
OpenFileName.lpstrDefExt = NULL;
OpenFileName.lpfnHook = NULL;
OpenFileName.Flags = OFN_LONGNAMES;
FileOpenParams.uStructSize = sizeof(OPENDLGPARAMS);
FileOpenParams.uDlgFlags = DLG_OPEN_SHOW_PROGRESSIVE |
DLG_OPEN_SHOW_MULTIPAGE |
DLG_OPEN_SHOW_LOADROTATED |
DLG_OPEN_SHOW_LOADCOMPRESSED |
DLG_OPEN_SHOW_FILEINFO |
DLG_OPEN_SHOW_PREVIEW |
DLG_OPEN_ENABLESIZING |
DLG_OPEN_USEFILESTAMP |
DLG_OPEN_LOADBITMAP;
if (L_DlgOpen( hWnd, &OpenFileName, &FileOpenParams) == SUCCESS_DLG_OK)
{
L_CopyBitmap(pBitmap, FileOpenParams.pFileData[0].pBitmap, sizeof(BITMAPHANDLE));
L_FreeBitmap(FileOpenParams.pFileData[0].pBitmap);
nOpenIndex = OpenFileName.nFilterIndex;
L_FreeBitmap( &hThumb );
L_ChangeBitmapViewPerspective(pBitmap, pBitmap, sizeof(BITMAPHANDLE), TOP_LEFT );
return TRUE ;
}
else
{
return FALSE ;
}
}
7. |
Add the following lines in _tWinMain after HACCEL hAccelTable;
|
UNLOCKSUPPORT ( ) ;
L_DlgInit(DLG_INIT_COLOR);
8. |
In stdafx.h add the following headers: (keep in mind, you may have to change the path to where the header files reside): |
#include <commdlg.h>
#include "..\..\..\..\..\Include\ltpnt.h"
#include "..\..\..\..\..\Include\l_bitmap.h"
#include "..\..\..\..\..\Include\ltdlg.h"
9. |
Add the following code before the function "PostQuitMessage" call in the WM_DESTROY message in the WndProc function: |
if ( SUCCESS == L_PntIsValid ( pPaint ) )
{
L_PntFree ( pPaint ) ;
}
10. |
Create a new file called Imports.cpp in place it beside your project files. |
|
In the Project Workspace, click the Solution Explorer tab. |
|
Double-click the ToolbarTutorial folder to open it. |
|
Right-click the Source files folder and select Add à New item. |
|
Right-click on the Source file |
|
Expand Visual C++ tree, if it is not already expanded. |
|
Select Code from the sub tree. |
|
Select C++ File (.cpp) from the right window. |
|
In the name text box, specify Imports. |
|
Click the OK button. |
|
Double-click the Imports.cpp in the solution Explorer and add the following lines: (keep in mind, you may have to change the path to where the header files reside) |
#include "StdAfx.h"
#if defined(FOR_WIN64)
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\x64\\Ltkrn_x.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\x64\\Ltdis_x.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\x64\\Ltdlgkrn_x.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\x64\\Ltdlgfile_x.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\x64\\Ltpnt_x.lib")
#elif defined(FOR_WIN32)
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\Win32\\Ltkrn_u.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\Win32\\Ltdis_u.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\Win32\\Ltdlgkrn_u.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\Win32\\Ltdlgfile_u.lib")
#pragma comment(lib, "..\\..\\..\\..\\..\\Lib\\API\\Win32\\Ltpnt_u.lib")
#endif // #if defined(FOR_WIN64)
11. |
Compile and run the project by selecting Build->Execute tutorial.exe from the menu. |