Low-Level DigitalPaint: Initializing and Freeing a Paint Handle
Take the following steps that will create a new paint handle:
1. |
Start Visual C++, version 4.2. |
|
2. |
Select the File->New menu option, and in the dialog box, select Project Workspace. |
|
3. |
In the New Project Workspace dialog box, enter the location (c:\lead\examples\paint), make sure to select Application (Win32 Application) as the project type. Give the project the name "tutorial" and press Enter. |
|
4. |
Select File->New menu option, and in the dialog box, select Resource Script and press Enter. |
|
5. |
Right click the script you just created and select Insert and then Menu from the dialog box that will appear and click OK. |
|
6. |
Create this Menu structure: |
|
|
IDR_MENU1 |
|
|
&File |
|
|
&Open… |
with ID = IDM_FILE_OPEN |
|
E&xit |
with ID = IDM_FILE_EXIT |
7. |
Select File->Save from the menu, enter Tutorial.rc in the Save As box and click Save. |
|
8. |
Select Insert->Files into Project, browse to the Tutorial.rc file we have just created and click Add. |
|
9. |
Select File->New menu option, and in the dialog box, select Text File and press Enter. |
|
10. |
Copy and paste the following code into the text file you have just created. This code will do the basic job of loading and painting the bitmap: |
#include <windows.h>
#include <windowsx.h>
#include "c:\lead14\include\l_bitmap.h"
#include "resource.h"
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,
HPALETTE hPalette
)
{
HDC hDC ;
PAINTSTRUCT ps ;
HPALETTE hOldPal ;
hDC = BeginPaint (hWnd, &ps) ;
if ( pBitmap->Flags.Allocated )
{
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 ) ;
}
}
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")} ;
FILEOPENPARM FileOpenParams ;
FILEINFO FileInfo ;
L_UINT32 uFlags ;
BITMAPHANDLE hThumb ;
memset ( &FileOpenParams, 0, sizeof ( FILEOPENPARM ) ) ;
lstrcpy ( szFile, TEXT("") ) ;
L_InitBitmap ( pBitmap, 0, 0, 0 ) ;
L_InitBitmap( &hThumb, 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 ;
uFlags = DLG_FO_AUTOPROCESS |
DLG_FO_FILEINFO |
DLG_FO_SHOWPREVIEW |
DLG_FO_95STYLE ;
FileOpenParams.pBitmap = pBitmap ;
FileOpenParams.pThumbnail = &hThumb ;
FileOpenParams.bPreviewEnabled = TRUE ;
FileOpenParams.pFileInfo = &FileInfo ;
if ( L_DlgFileOpen( hWnd, &OpenFileName, &FileOpenParams, uFlags, NULL, NULL ) == SUCCESS )
{
nOpenIndex = OpenFileName.nFilterIndex;
L_FreeBitmap( &hThumb ) ;
L_ChangeBitmapViewPerspective( NULL, pBitmap, TOP_LEFT );
return TRUE ;
}
else
{
return FALSE ;
}
}
static LRESULT WINAPI WndProc ( HWND hWnd, L_UINT uMessage, WPARAM wParam, LPARAM lParam )
{
static BITMAPHANDLE hBitmap ;
static RECT rcView ;
static HPALETTE hPalette = NULL ;
static L_INT nVScroll = 0 ;
static L_INT nHScroll = 0 ;
static L_INT nZoomFactor = 100 ;
switch( uMessage )
{
case WM_CREATE:
return 0L ;
case WM_DESTROY:
if ( hBitmap.Flags.Allocated )
{
L_FreeBitmap( &hBitmap ) ;
}
if ( hPalette )
{
DeletePalette ( hPalette ) ;
}
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, hPalette ) ;
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 ) ;
}
if ( hPalette )
{
DeletePalette ( hPalette ) ;
}
L_CopyBitmapHandle( &hBitmap, &hTempBitmap ) ;
hDC = GetDC ( hWnd ) ;
hPalette = L_CreatePaintPalette( hDC, &hBitmap ) ;
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_FILE_EXIT:
PostMessage ( hWnd, WM_CLOSE, 0, 0 ) ;
return 0L ;
}
break ;
}
return DefWindowProc ( hWnd, uMessage, wParam, lParam ) ;
}
L_INT WINAPI WinMain ( HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR pCmdLine, L_INT nCmdShow )
{
const L_TCHAR szClassName [ ] = TEXT("lead_paint_tutorial") ;
WNDCLASSEX WndClass ;
HWND hWnd ;
MSG Msg ;
UNREFERENCED_PARAMETER ( hInstPrev ) ;
UNREFERENCED_PARAMETER ( pCmdLine ) ;
// unlock lead file formats support
UNLOCKSUPPORT ( ) ;
WndClass.cbSize = sizeof ( WNDCLASSEX ) ;
WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
WndClass.lpfnWndProc = WndProc ;
WndClass.cbClsExtra = 0 ;
WndClass.cbWndExtra = 0 ;
WndClass.hInstance = hInst ;
WndClass.hIcon = LoadIcon ( NULL, IDI_APPLICATION ) ;
WndClass.hCursor = LoadCursor ( NULL, IDC_ARROW ) ;
WndClass.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 ) ;
WndClass.lpszMenuName = MAKEINTRESOURCE ( IDR_MENU1 ) ;
WndClass.lpszClassName = szClassName ;
WndClass.hIconSm = NULL ;
RegisterClassEx ( &WndClass ) ;
hWnd = CreateWindowEx ( 0L,
szClassName,
TEXT("Paint Tutorial"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
CW_USEDEFAULT,
0,
NULL,
NULL,
hInst,
NULL ) ;
ShowWindow ( hWnd, nCmdShow ) ;
UpdateWindow ( hWnd ) ;
while ( GetMessage ( &Msg, NULL, 0, 0 ) != 0 )
{
TranslateMessage ( &Msg ) ;
DispatchMessage ( &Msg ) ;
}
UnregisterClass ( szClassName, hInst ) ;
return Msg.wParam ;
}
11. |
Add the following include statement: |
#include "c:\lead14\include\ltpnt.h"
12. |
Add the following declaration to the WndProc function: |
static pPAINTHANDLE pPaint ;
13. |
Replace the "return 0L ; " in the WM_CREATE message in the WndProc function with following code: |
if ( SUCCESS == L_PntInit ( &pPaint ) )
{
return 0L ;
}
else
{
return -1L ;
}
14. |
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 ) ;
}
15. |
Select File->Save from the menu and give the text file the name "painttut.c" |
16. |
Select Insert->Files into Project from the menu, in the dialog box that will appear, browse to painttut.c you have just created, select it and click Add. |
17. |
Select Insert->Files into Project from the menu, in the dialog box that will appear, browse to c:\lead\lib\ltkrn_n.lib, select it and click Add. |
18. |
Select Insert->Files into Project from the menu, in the dialog box that will appear, browse to c:\lead\lib\ltdis_n.lib, select it and click Add. |
19. |
Select Insert->Files into Project from the menu, in the dialog box that will appear, browse to c:\lead\lib\ltdlg_n.lib, select it and click Add. |
20. |
Select Insert->Files into Project from the menu, in the dialog box that will appear, browse to c:\lead\lib\ltpnt_n.lib, select it and click Add. |
21. |
Compile and run the project by selecting Build->Execute tutorial.exe from the menu. |