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.